diff --git a/Dockerfile b/Dockerfile index 66de2df0..210cc4a7 100644 --- a/Dockerfile +++ b/Dockerfile @@ -14,4 +14,4 @@ EXPOSE 14700/udp EXPOSE 14700 EXPOSE 14600/udp -CMD ["/usr/bin/java", "-XX:+DisableAttachMechanism", "-Xmx8g", "-Xms256m", "-Dlogback.configurationFile=/testnet-1.0/conf/logback.xml", "-Djava.net.preferIPv4Stack=true", "-jar", "helix*.jar", "-p", "14700", "-u", "14600", "--remote", "$@"] +ENTRYPOINT ["/usr/bin/java", "-XX:+DisableAttachMechanism", "-Xmx8g", "-Xms256m", "-Dlogback.configurationFile=/testnet-1.0/conf/logback.xml", "-Djava.net.preferIPv4Stack=true", "-jar", "helix*.jar", "-p", "14700", "-u", "14600", "--remote", "$@"] diff --git a/README.md b/README.md index 45bbc8b6..a4d7d4a6 100644 --- a/README.md +++ b/README.md @@ -4,7 +4,7 @@ # Helix Protocol This is the 1.0 implementation of the Helix Protocol based on [**IRI**](https://github.com/iotaledger/iri/). -* **Latest release:** 0.5.3 pre-release +* **Latest release:** 0.5.4 pre-release * **License:** GPLv3 ## Developers @@ -12,20 +12,8 @@ This is the 1.0 implementation of the Helix Protocol based on [**IRI**](https:// - Please see the [CONTRIBUTING.md](https://github.com/HelixNetwork/testnet-1.0/blob/dev/CONTRIBUTING.md) and [STYLEGUIDE.md](https://github.com/HelixNetwork/testnet-1.0/blob/dev/STYLEGUIDE.md) if you wish to contribute to this repository! - Please read and update the [testnet-1.0-specifications](https://github.com/HelixNetwork/helix-specs/blob/master/specs/testnet-1.0.md). - You may enable auto-submission of milestones by passing the `-m`-flag and an integer for the delay. -- Test-Balance: -``` -Seed#0: df36d3a5c687106be8c8880ce06117a302bd09fe88355cd4102b901ad9f76ec2 -Addr#0: 556a2431d03e57e92b7d4d4d37f98332fce5427d8167e16c0a5cfbe20899d261 - -Seed#1: 7b6cc72ce82f3e1369b3e62bfc9607853ae607d352de4110a93645d575898bc6 -Addr#1: 196a2095205189ad2aa77c1125fc9e5d9c4888fb307a4a16caca6f6d311036e7 +- You may enable auto-submission of spam by passing: `--spam ` and `--pow-disabled` -Seed#2: 462813e2e99aeb25e94fba849af07bf8927e3a81911c16359f87a6cef1a960c2 -Addr#2: 9ac84e8c4df3e51e78f088b2f51408c97333ad982313101cac14ccb03f137e1f - -Seed#3: e2ccb4dbaffc70b02f0d1c14bc1214cc2833d157ddcddb8179014bd593861aa1 -Addr#3: b662e011dae0a5a554281efc7d858894d797fe92b292c5a29c8d3b2ce648aae0 -``` These addresses hold value, you may use the corresponding seeds to issue value-transfers. ## Installing @@ -33,7 +21,7 @@ Make sure you have [**Maven**](https://maven.apache.org/) and [**Java 8**](https ### Download ``` -$ git clone https://github.com/HelixNetwork/sbx.git +$ git clone https://github.com/HelixNetwork/testnet-1.0.git ``` ### Compile ``` @@ -47,15 +35,13 @@ This will create a `target` directory in which you will find the executable jar ### Launch ``` -java -jar target/testnet-.jar -p 14700 +java -jar target/helix-.jar -p 14700 ``` With auto-milestone submission: ``` -java -jar target/testnet-.jar -p 14700 -m 30 +java -jar target/helix-.jar -p 14700 -m 30 ``` -**NOTICE**: The `-m` flag is only temporary and will be removed in future updates. Its current purpose is to ease the process of submitting milestones as a developer. spment purposes -If you are running a node with the milestone flag, you should consider limiting the api. ## CLI diff --git a/changelog.md b/changelog.md index 29b15787..a08b8154 100644 --- a/changelog.md +++ b/changelog.md @@ -3,6 +3,19 @@ - API constructor only needs specific objects from helix instance - Separate http server from api backend to improve readability, maintainability and enable multiple impl. - Resteasy undertow integration + - Fixed subseed() in Winternitz class + - Added Unit Tests: + - RocksDB + - Tangle + - Winternitz + - Fixed: Timestamp conversion in API deviates from Node + - Stats Publisher: + - MIN_TRANSACTION_AGE_THRESHOLD set to 5 seconds + - MAX_TRANSACTION_AGE_THRESHOLD set to 2 minutes + - Fix: Timestamp conversion in Node / API + - Fix SignedFiles: line seperator should not be part of digest + - New Resource files + - Added configurable spammer for testing/experiments # 0.5.3 - PoW Integration (Replace divepearler with GreedyMiner) diff --git a/pom.xml b/pom.xml index 00376c83..741311bd 100644 --- a/pom.xml +++ b/pom.xml @@ -5,7 +5,7 @@ net.helix helix - 0.5.3 + 0.5.4 Helix Helix-1.0 diff --git a/src/main/java/net/helix/hlx/HLX.java b/src/main/java/net/helix/hlx/HLX.java index e1ca2694..ea832f63 100644 --- a/src/main/java/net/helix/hlx/HLX.java +++ b/src/main/java/net/helix/hlx/HLX.java @@ -6,6 +6,7 @@ import net.helix.hlx.conf.HelixConfig; import net.helix.hlx.service.API; import net.helix.hlx.service.milestone.MSS; +import net.helix.hlx.service.Spammer; import com.beust.jcommander.JCommander; import com.beust.jcommander.ParameterException; @@ -45,7 +46,7 @@ public class HLX { public static final String MAINNET_NAME = "HLX"; public static final String TESTNET_NAME = "HLX Testnet"; - public static final String VERSION = "0.5.3"; + public static final String VERSION = "0.5.4"; /** * The entry point of the helix sandbox. @@ -67,7 +68,7 @@ public static void main(String[] args) throws Exception { private static void configureLogging() { HelixIOUtils.saveLogs(); // TODO: Find a solution, that allows to save the logs under the condition of `config.isSaveLogEnabled()`. String config = System.getProperty("logback.configurationFile"); - String level = System.getProperty("logging-level", "debug").toUpperCase(); + String level = System.getProperty("logging-level", "info").toUpperCase(); switch (level) { case "OFF": case "ERROR": @@ -96,6 +97,7 @@ private static class HLXLauncher { public static API api; public static HXI hxi; public static MSS mss; + public static Spammer spammer; /** * Starts hlx. Setup is as follows: @@ -123,6 +125,7 @@ public static void main(String [] args) throws Exception { helix.tipsViewModel, helix.transactionValidator, helix.latestMilestoneTracker, helix.graph); mss = new MSS(config, api); + spammer = new Spammer(config, api); shutdownHook(); try { @@ -138,6 +141,9 @@ public static void main(String [] args) throws Exception { if(config.getMsDelay() > 0) { mss.startScheduledExecutorService(); } + if(config.getSpamDelay() > 0) { + spammer.startScheduledExecutorService(); + } } /** diff --git a/src/main/java/net/helix/hlx/SignedFiles.java b/src/main/java/net/helix/hlx/SignedFiles.java index faad0273..bb42b09d 100644 --- a/src/main/java/net/helix/hlx/SignedFiles.java +++ b/src/main/java/net/helix/hlx/SignedFiles.java @@ -60,7 +60,7 @@ private static byte[] digestFile(String filename, Sponge sha3) throws IOExceptio // building snapshot message StringBuilder sb = new StringBuilder(); reader.lines().forEach(line -> { - String hex = line + System.lineSeparator(); // can return a null + String hex = line; // can return a null if (hex == null) { throw new IllegalArgumentException("BYTES ARE NULL. INPUT= '" + line + "'"); } diff --git a/src/main/java/net/helix/hlx/conf/BaseHelixConfig.java b/src/main/java/net/helix/hlx/conf/BaseHelixConfig.java index 0e553db3..66f1fc4e 100644 --- a/src/main/java/net/helix/hlx/conf/BaseHelixConfig.java +++ b/src/main/java/net/helix/hlx/conf/BaseHelixConfig.java @@ -112,6 +112,9 @@ public abstract class BaseHelixConfig implements HelixConfig { protected int minDelay = Defaults.MS_MIN_DELAY; protected String cooAddress = Defaults.COORDINATOR_ADDRESS; + //Spammer + protected int spamDelay = Defaults.SPAM_DELAY; + public BaseHelixConfig() { //empty constructor } @@ -804,6 +807,14 @@ public String getSaveLogXMLFile() { @Parameter(names = {"--savelog-xml"}, description = LoggingConfig.Descriptions.SAVELOG_XML_FILE) protected void setSaveLogXMLFile(String saveLogXMLFile) { this.saveLogXMLFile = saveLogXMLFile; } + @Override + public int getSpamDelay() { + return spamDelay; + } + @JsonProperty + @Parameter(names = {"--spam"}, description = LoggingConfig.Descriptions.SAVELOG_XML_FILE) + protected void setSpamDelay(int spamDelay) { this.spamDelay = spamDelay; } + public interface Defaults { //API int API_PORT = 14700; @@ -896,5 +907,8 @@ public interface Defaults { boolean SAVELOG_ENABLED = false; String SAVELOG_BASE_PATH = "logs/"; String SAVELOG_XML_FILE = "/logback-save.xml"; + + //Spammer + int SPAM_DELAY = 0; } } diff --git a/src/main/java/net/helix/hlx/conf/HelixConfig.java b/src/main/java/net/helix/hlx/conf/HelixConfig.java index 883df99c..6de1e1e9 100644 --- a/src/main/java/net/helix/hlx/conf/HelixConfig.java +++ b/src/main/java/net/helix/hlx/conf/HelixConfig.java @@ -8,7 +8,7 @@ * A container for all possible configuration parameters of SBX. * In charge of how we parse the configuration from given inputs. */ -public interface HelixConfig extends APIConfig, NodeConfig, HXIConfig, DbConfig, ConsensusConfig, ZMQConfig, TipSelConfig, PoWConfig, SolidificationConfig, GraphConfig, LoggingConfig { +public interface HelixConfig extends APIConfig, NodeConfig, HXIConfig, DbConfig, ConsensusConfig, ZMQConfig, TipSelConfig, PoWConfig, SolidificationConfig, GraphConfig, LoggingConfig, SpamConfig { File CONFIG_FILE = new File("hlx.ini"); /** * Parses the args to populate the configuration object diff --git a/src/main/java/net/helix/hlx/conf/SpamConfig.java b/src/main/java/net/helix/hlx/conf/SpamConfig.java new file mode 100644 index 00000000..cd599fb9 --- /dev/null +++ b/src/main/java/net/helix/hlx/conf/SpamConfig.java @@ -0,0 +1,12 @@ +package net.helix.hlx.conf; + +public interface SpamConfig { + /** + * @return {@value Descriptions#GET_SPAM_DELAY} + */ + int getSpamDelay(); + + interface Descriptions { + String GET_SPAM_DELAY = "Delay of spam."; + } +} diff --git a/src/main/java/net/helix/hlx/crypto/Winternitz.java b/src/main/java/net/helix/hlx/crypto/Winternitz.java index a65c13bf..cd943a8d 100644 --- a/src/main/java/net/helix/hlx/crypto/Winternitz.java +++ b/src/main/java/net/helix/hlx/crypto/Winternitz.java @@ -1,10 +1,7 @@ package net.helix.hlx.crypto; -import net.helix.hlx.utils.Serializer; -import org.bouncycastle.util.encoders.Hex; - -import java.math.BigInteger; import java.util.Arrays; +import org.bouncycastle.util.encoders.Hex; public class Winternitz { @@ -21,15 +18,25 @@ public class Winternitz { * Generate subseed by adding seed and index. * @param mode hashing mode * @param seed privately generated random - * @param index subseed index + * @param index subseed index has to be in [1..(Integer.MAX_VALUE-255)] * @return byte[] subseed */ public static byte[] subseed(SpongeFactory.Mode mode, final byte[] seed, int index) { - if (index < 0) { + if (index < 0 || index > Integer.MAX_VALUE - 255) { throw new RuntimeException("Invalid subseed index: " + index); } - byte[] indexInBytes = Serializer.serialize(index); - final byte[] subseedPreimage = new BigInteger(seed).add(new BigInteger(indexInBytes)).toByteArray(); + if (seed.length % Sha3.HASH_LENGTH != 0){ + throw new RuntimeException("Invalid seed length: " + seed.length); + } + final byte[] subseedPreimage = seed.clone(); + for (int i = subseedPreimage.length - 1; i >= 0; i--) { + index += (subseedPreimage[i] & 0xFF); + subseedPreimage[i] = (byte)index; + index >>= 8; + if (index == 0) { + break; + } + } final byte[] subseed = new byte[Sha3.HASH_LENGTH]; final Sponge hash = SpongeFactory.create(mode); hash.absorb(subseedPreimage, 0, subseedPreimage.length); diff --git a/src/main/java/net/helix/hlx/network/Node.java b/src/main/java/net/helix/hlx/network/Node.java index df73bb9f..783b2b0b 100644 --- a/src/main/java/net/helix/hlx/network/Node.java +++ b/src/main/java/net/helix/hlx/network/Node.java @@ -472,7 +472,7 @@ public void processReceivedData(TransactionViewModel receivedTransactionViewMode //if new, then broadcast to all neighbors if (stored) { - receivedTransactionViewModel.setArrivalTime(System.currentTimeMillis()); + receivedTransactionViewModel.setArrivalTime(System.currentTimeMillis()/1000L); try { transactionValidator.updateStatus(receivedTransactionViewModel); receivedTransactionViewModel.updateSender(neighbor.getAddress().toString()); diff --git a/src/main/java/net/helix/hlx/service/API.java b/src/main/java/net/helix/hlx/service/API.java index 04b35bbf..a6e804ab 100644 --- a/src/main/java/net/helix/hlx/service/API.java +++ b/src/main/java/net/helix/hlx/service/API.java @@ -7,9 +7,12 @@ import net.helix.hlx.conf.HelixConfig; import net.helix.hlx.controllers.*; import net.helix.hlx.crypto.*; +import net.helix.hlx.model.BundleHash; import net.helix.hlx.model.Hash; import net.helix.hlx.model.HashFactory; +import net.helix.hlx.model.TransactionHash; import net.helix.hlx.model.persistables.Transaction; +import net.helix.hlx.model.persistables.Bundle; import net.helix.hlx.network.Neighbor; import net.helix.hlx.network.Node; import net.helix.hlx.network.TransactionRequester; @@ -1419,12 +1422,12 @@ public void shutDown() { * @param message The message to store **/ private synchronized AbstractResponse storeMessageStatement(final String address, final String message) throws Exception { - final List txToApprove = getTransactionToApproveTips(3, Optional.empty()); - attachStoreAndBroadcast(address, message, txToApprove); + attachStoreAndBroadcast(address, message); return AbstractResponse.createEmptyResponse(); } - private void attachStoreAndBroadcast(final String address, final String message, final List txToApprove) throws Exception { + public void attachStoreAndBroadcast(final String address, final String message) throws Exception { + final List txToApprove = getTransactionToApproveTips(3, Optional.empty()); attachStoreAndBroadcast(address, message, txToApprove, 0, 1, false); } @@ -1439,7 +1442,7 @@ private void attachStoreAndBroadcast(final String address, final String message, byte[] currentIndexBytes = new byte[TransactionViewModel.CURRENT_INDEX_SIZE]; final byte[] lastIndexBytes = new byte[TransactionViewModel.LAST_INDEX_SIZE]; - final String lastIndexHex = isMilestone ? Hex.toHexString(lastIndexBytes) : Integer.toHexString(txCount); // TODO: lastIndex has to be 0 for milestones and based on txCount for other tx. + final String lastIndexHex = isMilestone ? Hex.toHexString(lastIndexBytes) : Integer.toHexString(txCount-1); // TODO: lastIndex has to be 0 for milestones and based on txCount for other tx. final byte[] newMilestoneIndex = Serializer.serialize(index); final String tagHex = Hex.toHexString(newMilestoneIndex); // milestoneTracker index is parsed from tag @@ -1479,6 +1482,7 @@ private void attachStoreAndBroadcast(final String address, final String message, sponge.squeeze(essenceHash, 0, essenceHash.length); final String bundleHash = Hex.toHexString(essenceHash); transactions = transactions.stream().map(tx -> StringUtils.rightPad(tx + bundleHash + StringUtils.repeat('0', 128) + tagHex, BYTES_SIZE, '0')).collect(Collectors.toList()); + Collections.reverse(transactions); List powResult = attachToTangleStatement(txToApprove.get(0), txToApprove.get(1), minWeightMagnitude, transactions); storeTransactionsStatement(powResult); broadcastTransactionsStatement(powResult); diff --git a/src/main/java/net/helix/hlx/service/Spammer.java b/src/main/java/net/helix/hlx/service/Spammer.java new file mode 100644 index 00000000..5128082f --- /dev/null +++ b/src/main/java/net/helix/hlx/service/Spammer.java @@ -0,0 +1,55 @@ +package net.helix.hlx.service; + +import net.helix.hlx.conf.SpamConfig; +import net.helix.hlx.model.Hash; +import org.apache.commons.lang3.StringUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.util.concurrent.Executors; +import java.util.concurrent.ScheduledExecutorService; +import java.util.concurrent.TimeUnit; + +public class Spammer { + private static final Logger log = LoggerFactory.getLogger(Spammer.class); + private final ScheduledExecutorService scheduledExecutorService = Executors.newSingleThreadScheduledExecutor(); + private API api; + private SpamConfig config; + + private String address; + private String message; + private int delay; + + public Spammer(SpamConfig config, API api) { + this.api = api; + this.config = config; + this.message = StringUtils.repeat('0', 1024*2); + this.address = Hash.NULL_HASH.hexString(); + this.delay = config.getSpamDelay(); + } + + public void startScheduledExecutorService() { + log.info("Spammer scheduledExecutorService started."); + log.info("Submitting Tx every: " + this.delay + "ms."); + this.scheduledExecutorService.scheduleWithFixedDelay(this.getRunnableSendTx(), 10000, this.delay, TimeUnit.MILLISECONDS); + } + + private void sendTx() throws Exception { + this.api.attachStoreAndBroadcast(this.address, this.message); + } + + private Runnable getRunnableSendTx() { + return () -> { + try { + sendTx(); + } catch (Exception e) { + e.printStackTrace(); + } + }; + } + + public void shutdown() { + log.info("Shutting down Spammer Thread"); + scheduledExecutorService.shutdown(); + } +} diff --git a/src/main/java/net/helix/hlx/service/restserver/resteasy/RestEasy.java b/src/main/java/net/helix/hlx/service/restserver/resteasy/RestEasy.java index 22bb3a72..2a718f8e 100644 --- a/src/main/java/net/helix/hlx/service/restserver/resteasy/RestEasy.java +++ b/src/main/java/net/helix/hlx/service/restserver/resteasy/RestEasy.java @@ -139,28 +139,28 @@ public void init(ApiProcessor processFunction) { info.setDeploymentName("Helix Realm"); info.setContextPath("/"); /** TODO: check credentials here instead of in process request - info.addSecurityWrapper(new HandlerWrapper() { - @Override - public HttpHandler wrap(HttpHandler toWrap) { - String credentials = remoteAuth; - if (credentials == null || credentials.isEmpty()) { - return toWrap; - } + info.addSecurityWrapper(new HandlerWrapper() { + @Override + public HttpHandler wrap(HttpHandler toWrap) { + String credentials = remoteAuth; + if (credentials == null || credentials.isEmpty()) { + return toWrap; + } - final Map users = new HashMap<>(2); - users.put(credentials.split(":")[0], credentials.split(":")[1].toCharArray()); + final Map users = new HashMap<>(2); + users.put(credentials.split(":")[0], credentials.split(":")[1].toCharArray()); - IdentityManager identityManager = new MapIdentityManager(users); - HttpHandler handler = toWrap; - handler = new AuthenticationCallHandler(handler); - handler = new AuthenticationConstraintHandler(handler); - final List mechanisms = - Collections.singletonList(new BasicAuthenticationMechanism("Helix Realm")); + IdentityManager identityManager = new MapIdentityManager(users); + HttpHandler handler = toWrap; + handler = new AuthenticationCallHandler(handler); + handler = new AuthenticationConstraintHandler(handler); + final List mechanisms = + Collections.singletonList(new BasicAuthenticationMechanism("Helix Realm")); - handler = new AuthenticationMechanismsHandler(handler, mechanisms); - handler = new SecurityInitialHandler(AuthenticationMode.PRO_ACTIVE, identityManager, handler); - return handler; - } + handler = new AuthenticationMechanismsHandler(handler, mechanisms); + handler = new SecurityInitialHandler(AuthenticationMode.PRO_ACTIVE, identityManager, handler); + return handler; + } });*/ info.addInnerHandlerChainWrapper(handler -> { @@ -318,4 +318,4 @@ private static void setupResponseHeaders(HttpServerExchange exchange) { headerMap.add(new HttpString("Access-Control-Allow-Origin"),"*"); headerMap.add(new HttpString("Keep-Alive"), "timeout=500, max=100"); } -} +} \ No newline at end of file diff --git a/src/main/java/net/helix/hlx/service/snapshot/impl/SnapshotProviderImpl.java b/src/main/java/net/helix/hlx/service/snapshot/impl/SnapshotProviderImpl.java index 91db65b5..45d9a774 100644 --- a/src/main/java/net/helix/hlx/service/snapshot/impl/SnapshotProviderImpl.java +++ b/src/main/java/net/helix/hlx/service/snapshot/impl/SnapshotProviderImpl.java @@ -38,7 +38,7 @@ public class SnapshotProviderImpl implements SnapshotProvider { * Public key that is used to verify the builtin snapshot signature. */ private static final String SNAPSHOT_PUBKEY = - "6a8413edc634e948e3446806afde11b17e0e188faf80a59a8b1147a0600cc5db"; + "a7b6760925b6bb5294d54d9de3f0c0a13b3f78ab21aa4e0ccfa35c4f8b02328c"; /** * Public key depth that is used to verify the builtin snapshot signature. diff --git a/src/main/java/net/helix/hlx/service/stats/TimeWindowedApproveeCounter.java b/src/main/java/net/helix/hlx/service/stats/TimeWindowedApproveeCounter.java index efec0a0b..d46c6658 100644 --- a/src/main/java/net/helix/hlx/service/stats/TimeWindowedApproveeCounter.java +++ b/src/main/java/net/helix/hlx/service/stats/TimeWindowedApproveeCounter.java @@ -31,6 +31,10 @@ private boolean isOlderThanMaxAge(Instant now, TransactionViewModel transaction) return age <= maxTransactionAgeSeconds; } + private boolean isConfirmed(Instant now, TransactionViewModel transaction) { + return transaction.snapshotIndex() > 0; + } + /** * Checks whether the transaction is in the validity time window. * @@ -56,14 +60,14 @@ boolean isInTimeWindow(Instant now, TransactionViewModel transaction) { * processed hashes. * @throws TraversalException if anything goes wrong while traversing the graph and processing the transactions */ - long getCount(Instant now, Hash startingTransactionHash, HashSet processedTransactions) + long getCount(Instant now, Hash startingTransactionHash, HashSet processedTransactions, boolean onlyConfirmed) throws TraversalException { DAGHelper helper = DAGHelper.get(tangle); - ValidTransactionCounter transactionCounter = new ValidTransactionCounter(now); + ValidTransactionCounter transactionCounter = new ValidTransactionCounter(now, onlyConfirmed); helper.traverseApprovees(startingTransactionHash, t -> isOlderThanMaxAge(now, t), transactionCounter::count, - processedTransactions); + processedTransactions); return transactionCounter.getCount(); } @@ -76,16 +80,24 @@ long getCount(Instant now, Hash startingTransactionHash, HashSet processed private final class ValidTransactionCounter { final Instant now; + boolean confirmed; long count = 0; - private ValidTransactionCounter(Instant now) { + private ValidTransactionCounter(Instant now, boolean onlyConfirmed) { this.now = now; + this.confirmed = onlyConfirmed; } private void count(TransactionViewModel transactionViewModel) { if (isInTimeWindow(now, transactionViewModel)) { - count++; + if (confirmed) { + if (isConfirmed(now, transactionViewModel)){ + count++; + } + } else { + count++; + } } } diff --git a/src/main/java/net/helix/hlx/service/stats/TransactionStatsPublisher.java b/src/main/java/net/helix/hlx/service/stats/TransactionStatsPublisher.java index c56b7299..415c1256 100644 --- a/src/main/java/net/helix/hlx/service/stats/TransactionStatsPublisher.java +++ b/src/main/java/net/helix/hlx/service/stats/TransactionStatsPublisher.java @@ -26,13 +26,13 @@ */ public class TransactionStatsPublisher { - private static final long PUBLISH_INTERVAL = Duration.ofMinutes(1).toMillis(); + private static final long PUBLISH_INTERVAL = Duration.ofSeconds(10).toMillis(); - private static final String CONFIRMED_TRANSACTIONS_TOPIC = "ct5m2h"; - private static final String TOTAL_TRANSACTIONS_TOPIC = "t5m2h"; + private static final String CONFIRMED_TRANSACTIONS_TOPIC = "ct5s2m"; + private static final String TOTAL_TRANSACTIONS_TOPIC = "t5s2m"; - private static final Duration MIN_TRANSACTION_AGE_THRESHOLD = Duration.ofMinutes(5); - private static final Duration MAX_TRANSACTION_AGE_THRESHOLD = Duration.ofHours(2); + private static final Duration MIN_TRANSACTION_AGE_THRESHOLD = Duration.ofSeconds(5); + private static final Duration MAX_TRANSACTION_AGE_THRESHOLD = Duration.ofMinutes(2); private final Logger log = LoggerFactory.getLogger(TransactionStatsPublisher.class); @@ -94,7 +94,7 @@ private Hash getSuperTip() throws Exception { private long getConfirmedTransactionsCount(Instant now) throws Exception { - return approveeCounter.getCount(now, getSuperTip(), new HashSet<>()); + return approveeCounter.getCount(now, getSuperTip(), new HashSet<>(), true); } private long getAllTransactionsCount(Instant now) throws Exception { @@ -104,11 +104,12 @@ private long getAllTransactionsCount(Instant now) throws Exception { long count = 0; for (Hash tip : tipsViewModel.getTips()) { // count the tip, if it is the valid time window + log.debug("DZMQ: {}", tip.hexString()); if (approveeCounter.isInTimeWindow(now, TransactionViewModel.fromHash(tangle, tip))) { - count += 1 + approveeCounter.getCount(now, tip, processedTransactions); + count += 1 + approveeCounter.getCount(now, tip, processedTransactions, false); } else { // even if the tip is not in the time window, count approvees that might be older - count += approveeCounter.getCount(now, tip, processedTransactions); + count += approveeCounter.getCount(now, tip, processedTransactions, false); } } diff --git a/src/main/resources/previousEpochsSpentAddresses.sig b/src/main/resources/previousEpochsSpentAddresses.sig index bbe121bd..f4e76061 100644 --- a/src/main/resources/previousEpochsSpentAddresses.sig +++ b/src/main/resources/previousEpochsSpentAddresses.sig @@ -1,2 +1,2 @@ -919c0ea9812b6e99e80d7c0df37d7f8dd3aa1ab072e31e8669782929947af49cd952b2c60c3360a85e27465cd55b61eced4fbd126f1e09fc5f049ebd1d09b5b0a1901a8f060196f97471ea6e5638ec11a5ccdc719436241648524ee47113177c75bc44ea549748390d06efa2c8174fef5d7285b58d3a6070fde07a7d58a1b0711fdf991a588c5a702abbfb3b89b1bbbac044e310345b749632d0d6e18ef7057564699e7044b40aa93ad01c878d80dda5a0cea6479d3ee23ef96c03969fb80a4e287dfa585c01460a2ee4bb664b88250feca23de7a1c95a35c9f12ebed10bdad721492b9fdd65a2270058e15d1a49387960b0b415e42a84b80b0bef67e85a1a68ab7c5b2f569396835cb217670565cc343e2007f00dd7510f311ceebbdc6aead0ba723e4729c1d211c5ac420a0fe0826f84fca1ed5777bf7385cc22fd3584a401f02edef02c9b71594a931b71d15ba560d86bfb28ebc6194b13042cd27983912ec48c1cdd0271dc46c02f65bad11b32b8684e3721ec9d50bcdab3cbaba91aa7b0d196e8ee3021ff214b017d142df28bd28012b1567cdad827a26e7d3188ac959464fac5a6f6c1b69221f3d700d229e4333e825d768ea10afdf7e37966184a5057941a125505095369bbdf62124a831e35cca580385409fbe479cdfb693eedded0dbd7c6efba2075ad1fffcb21c10c7b750b653dec43d6c4caf8df26d8980eef24 -4a54ee5648fb4525485c5547416773ae52cd03795074dba222deddb925c417d27ad8a49bf2826f12b7ec600eebfe7645f623fa5cfa8ef30f3bb5cfbfade55d9a4c69b781f2c970bb7f6989225faa3057735eff620a63a6fd9f43f5025194ec710a83082d019331dac04f92028ff2e5a244c7017551b63ae032f7efe2662a79f8edd4b606101a37a5b12092920ebf9226f470daf979a9cd132b28f9642feca07467956566e602f9eb82f03c9148dc3f7470d63fab81c214a0a8277cb20b6f2ef5d8988d0508031d7fc07ad0ea5ff266feb112ce01d30bf86ab9f9f1223eea4ef8cbbf75ccae8151ea762c3044c4938c782c8da5c7be16b4fe889741f05280e5de6d3dcca3862b37d7d9646d1d62da6ef8c2e6b7067c2e77f22b98242df26aafe12d381bb7c4c14aabf403dfba0c2c973ae44c9832acbd62b4933b263eee6ebd00 \ No newline at end of file +a07da0afb142dbf1e86c61b647846f53288ad21dfabd2640a7b06c35e38b6cdcc7934fb0e54955a78531a132ee80c2a74957a8cbb7415e69bc2173c69c6caa197ca33e56b39f07a0d51a3112dd6d678f9ad54875ddecb478a07cb1bd6919ee99c8d55e5a71fd32dda9f74badef2519850dad60bba6026b4307a5d7a808595caa89223ac53f9133e873411f370e7c6a463fb29fb89493931364d2571672aaa114d996ee938ebd550bd49aa45a12146d9d69c805122b4858b88a7f916025ab5e1c01c74df50ea4ff26428f3475addbc713d2e9ba4fcb041754fcb3fc9a2b70d05c09ab76c413795e89310bd6ebc2579fd8eef43e1229853a4c8683675973fbdc98f071e8ba7581031830aed3510fc51213c1b27d56fdef14b56cf6e32adc3025387fc11f9266b676387d53475dd8f3b335a7e4961b552f9fc9c33ebd9ec9cb27e71b706a67d81277f73e6c27be5988e3cfbef5bfeb33dcf0bd843e468dc47bf878459bdc0b143cf638d456d3c03e84b0cacb29037fed21b69f80860ddaa3c85e96e1540b6b10dd7b7ccef6cabdc278180d6710ac7e7687ff8fd01a6397d5048546887d45e68cbb5b2b21f7265d33a8a9806d1eef5cb75b76e92e4965a0d05ad103e6234dfb37163433343dcfe11a485c49d119f96f5bec65f1e5d188c33f8a17fe730486c3b46233c3bacafcaba046c69d7383cf5932a0ab6cfbc0f1ed961e509d +a841f169683a0d2d768d4582ded75cf5c722658caeb871185638e9b66c789d4300a3630253e2293cba563ca6ed4e16d00d2347f6ac68842a56d8dd477a6248b7364573a694a5241c68065aa5e45b258470e6d33d400723618c7b1ebc2c5e7c55def9706dcaa37edf0bf7a948df51cad8db481516598db7015a9a516fa1b81093ebec65e1fe17504ead9fd533d475669403d8ea69483e72713025fa8ec1a250c7d24f7b9a9bb52a0aa8973368edffab0557fc47d4be9a8447f91a739ef711d88ffcaf39eea552604efefd36b539ef4a37064a3c8acd72a9cf17ef8313428e1aa20ada9e74265de0c685e16f6fd94eb30fb79761157640527979435d345a9f1f819a57de830d70d801329fdaba9221c7238c7bf54f6c07b22c0abfdfd71727d17c516c3ebdc43e85cbaa6b9aa9e3faf5320d7b9af7206e0c3e540c7b1709790438 \ No newline at end of file diff --git a/src/main/resources/snapshotMainnet.sig b/src/main/resources/snapshotMainnet.sig index 44e72591..e950e6d9 100644 --- a/src/main/resources/snapshotMainnet.sig +++ b/src/main/resources/snapshotMainnet.sig @@ -1,2 +1,2 @@ -9e3d8a5ae9b73ed599363915d691214da7522852ddfb45127040feb53dffd7a5825d805d51afae084e5602dc8aa03e8594e089ed4e4b46dfdabdc31da2073c87717b0c8d5e2637878bcfd62f4f3960c4c09314477afea943fa6227d6d62f0344717b0c8d5e2637878bcfd62f4f3960c4c09314477afea943fa6227d6d62f03446809bb10b73ef44cd9517e9c74f33aed0ecfe0814ee009623a34727eac7434d97ae344a00a1dbe0485e1124af89d0d9a4cf90c3274bc51c10a5cd1e40efd0e2933fd2cd99fd4c4468d92a20949f6449e8b13af37a44a5212e642e8b9cfb19fd3b147125a0217b576ebbf9212dd9a1ad0fda4876f34abac48a080371e1b0c59a5890a6da2d22e54cbf118d08e90068c79579c3b15ef64c5b5880d0b65464856b7a91c6899aa281e64c33131d84c98be9c7fca9ebb1dae3a3c94c31c212c37348b107f9e13b36e38deeadaef27e7108f37a3dd7952a1254da6ec16b37ba24c7c3b001e33b78cfff87157596e3e231f1b7683b91d9b596b9d79ede46812d20f23bb64fac5a6f6c1b69221f3d700d229e4333e825d768ea10afdf7e37966184a5057001e33b78cfff87157596e3e231f1b7683b91d9b596b9d79ede46812d20f23bb484fc2de197f28a0ab530adda5816abef912c3b762f17223558bd46b4d59b6d102cb0e9a554a2660c44fa42ff2c477722638c2500c0de5c388dd35dc17143560 -4a54ee5648fb4525485c5547416773ae52cd03795074dba222deddb925c417d27ad8a49bf2826f12b7ec600eebfe7645f623fa5cfa8ef30f3bb5cfbfade55d9a4c69b781f2c970bb7f6989225faa3057735eff620a63a6fd9f43f5025194ec710a83082d019331dac04f92028ff2e5a244c7017551b63ae032f7efe2662a79f8edd4b606101a37a5b12092920ebf9226f470daf979a9cd132b28f9642feca07467956566e602f9eb82f03c9148dc3f7470d63fab81c214a0a8277cb20b6f2ef5d8988d0508031d7fc07ad0ea5ff266feb112ce01d30bf86ab9f9f1223eea4ef8cbbf75ccae8151ea762c3044c4938c782c8da5c7be16b4fe889741f05280e5de6d3dcca3862b37d7d9646d1d62da6ef8c2e6b7067c2e77f22b98242df26aafe12d381bb7c4c14aabf403dfba0c2c973ae44c9832acbd62b4933b263eee6ebd00 \ No newline at end of file +6d933ce349ac1b16f04bfc685ef6ad60db15f99ba6c17ade0d9821c97efba02aa07da0afb142dbf1e86c61b647846f53288ad21dfabd2640a7b06c35e38b6cdc187dbd86f57e4f9770df7f20c97e66c146241628071d6c8f96448a1b137aeff67e908fd2795f05b40e79f789fc290c42c58f3c6590b64b9ec1addf8e7466d13c77b730a011ecaf72e5248802f5a9bf371af559858527cc9a62a6a9218773f7308700225cf36cd22c2e5a5549219e45786bf5976ab1b30db49601f413c9169996eed62d4774b3b724487982919bc9758df03bff9e72dd2069565d3c14501d7884345d113f7348549751a4511553be1d33a5ef5b9e0663e5a9affffecea7bd22d438cd7ebd2ae18b574496f76662416bc5a4e54d2b034cb356e200058d8634cf3bd714fc7c1db2b8be8c840590a6104af9a6e11288980003daca8a3cd069b5190aeec76899a98a89f039b4c791307b0ad3a91a7a904037b8bc3a5d6139f5bcf373438b8ff642083bcbda06f36b6b810abf40a21b512afdc5652cdf88546beb5ce24d16d10220119898a68392d4dd8ed7807a1b914c349318b6d431e0cb79430929d6320984855c3e9521ee1302622a5df20bbd3abed6cc8a3590bfd65f87efafe7af05715407499c58c8990ac9e68fc6012e1b531d4e688d56af93a212a00e0e9d037190a857bf11e8dd3349ab4794c0e497600d5884e8d1abbc67488986e19eba +a841f169683a0d2d768d4582ded75cf5c722658caeb871185638e9b66c789d4300a3630253e2293cba563ca6ed4e16d00d2347f6ac68842a56d8dd477a6248b7364573a694a5241c68065aa5e45b258470e6d33d400723618c7b1ebc2c5e7c55def9706dcaa37edf0bf7a948df51cad8db481516598db7015a9a516fa1b81093ebec65e1fe17504ead9fd533d475669403d8ea69483e72713025fa8ec1a250c7d24f7b9a9bb52a0aa8973368edffab0557fc47d4be9a8447f91a739ef711d88ffcaf39eea552604efefd36b539ef4a37064a3c8acd72a9cf17ef8313428e1aa20ada9e74265de0c685e16f6fd94eb30fb79761157640527979435d345a9f1f819a57de830d70d801329fdaba9221c7238c7bf54f6c07b22c0abfdfd71727d17c516c3ebdc43e85cbaa6b9aa9e3faf5320d7b9af7206e0c3e540c7b1709790438 \ No newline at end of file diff --git a/src/main/resources/snapshotMainnet.txt b/src/main/resources/snapshotMainnet.txt index 43d84af7..f81b185d 100644 --- a/src/main/resources/snapshotMainnet.txt +++ b/src/main/resources/snapshotMainnet.txt @@ -1,8 +1,8 @@ -556a2431d03e57e92b7d4d4d37f98332fce5427d8167e16c0a5cfbe20899d261;536561674354688 -196a2095205189ad2aa77c1125fc9e5d9c4888fb307a4a16caca6f6d311036e7;536561674354688 -9ac84e8c4df3e51e78f088b2f51408c97333ad982313101cac14ccb03f137e1f;536561674354688 -b662e011dae0a5a554281efc7d858894d797fe92b292c5a29c8d3b2ce648aae0;536561674354688 -6341291c330f3efd052cbaa30169072ecf6b6a05832727a5e620572c2fddc1f4;536561674354688 -09b5c36fec0898d3b5194a183aa3cac34cc270ab7b4f4a4a0bbb37d3cbac8d33;536561674354688 -0b6e5b0c7deb070ccfeea2952c61be8cf4746381d368849bed7c95cadca97f55;536561674354688 -78c71217ab4978912c90768da30de3246bbc985c41c76fdb4dc15ecb835086b7;536561674354688 +c212548bd3c4b596bf24b16c36aaa69a5ecaf5a8240232380b0a26539b6b8619;536561674354688 +ee1c15a76b2b1ce72acd7e559afafb7418ffac15246d7c2c9d1bfe0ea4b6a924;536561674354688 +164838c044a83bbe80ce4bd24547442ae6d496caa5496c4746ae71470c13b4ed;536561674354688 +fbbaa16ddca9bb3b77df5c0da972ba28e0bf5f560f58cfac91cf33ff840d874e;536561674354688 +034981b284960406429ce9004213114033095478e37e31944d4a67c32369754a;536561674354688 +0956e0cd8f5a5e3d364b57beb94bd34c73929820d26fba8d47c9b214cb60f3bc;536561674354688 +8434c99110df30e4c3529b78927daa07903e3c90d6d04e857cacb125a64a4723;536561674354688 +b5c0d3905117deabcce27666ca7d61399045d8a72a19b2a962ad4312a1fd9d60;536561674354688 diff --git a/src/main/resources/snapshotTestnet.sig b/src/main/resources/snapshotTestnet.sig index 44e72591..e950e6d9 100644 --- a/src/main/resources/snapshotTestnet.sig +++ b/src/main/resources/snapshotTestnet.sig @@ -1,2 +1,2 @@ -9e3d8a5ae9b73ed599363915d691214da7522852ddfb45127040feb53dffd7a5825d805d51afae084e5602dc8aa03e8594e089ed4e4b46dfdabdc31da2073c87717b0c8d5e2637878bcfd62f4f3960c4c09314477afea943fa6227d6d62f0344717b0c8d5e2637878bcfd62f4f3960c4c09314477afea943fa6227d6d62f03446809bb10b73ef44cd9517e9c74f33aed0ecfe0814ee009623a34727eac7434d97ae344a00a1dbe0485e1124af89d0d9a4cf90c3274bc51c10a5cd1e40efd0e2933fd2cd99fd4c4468d92a20949f6449e8b13af37a44a5212e642e8b9cfb19fd3b147125a0217b576ebbf9212dd9a1ad0fda4876f34abac48a080371e1b0c59a5890a6da2d22e54cbf118d08e90068c79579c3b15ef64c5b5880d0b65464856b7a91c6899aa281e64c33131d84c98be9c7fca9ebb1dae3a3c94c31c212c37348b107f9e13b36e38deeadaef27e7108f37a3dd7952a1254da6ec16b37ba24c7c3b001e33b78cfff87157596e3e231f1b7683b91d9b596b9d79ede46812d20f23bb64fac5a6f6c1b69221f3d700d229e4333e825d768ea10afdf7e37966184a5057001e33b78cfff87157596e3e231f1b7683b91d9b596b9d79ede46812d20f23bb484fc2de197f28a0ab530adda5816abef912c3b762f17223558bd46b4d59b6d102cb0e9a554a2660c44fa42ff2c477722638c2500c0de5c388dd35dc17143560 -4a54ee5648fb4525485c5547416773ae52cd03795074dba222deddb925c417d27ad8a49bf2826f12b7ec600eebfe7645f623fa5cfa8ef30f3bb5cfbfade55d9a4c69b781f2c970bb7f6989225faa3057735eff620a63a6fd9f43f5025194ec710a83082d019331dac04f92028ff2e5a244c7017551b63ae032f7efe2662a79f8edd4b606101a37a5b12092920ebf9226f470daf979a9cd132b28f9642feca07467956566e602f9eb82f03c9148dc3f7470d63fab81c214a0a8277cb20b6f2ef5d8988d0508031d7fc07ad0ea5ff266feb112ce01d30bf86ab9f9f1223eea4ef8cbbf75ccae8151ea762c3044c4938c782c8da5c7be16b4fe889741f05280e5de6d3dcca3862b37d7d9646d1d62da6ef8c2e6b7067c2e77f22b98242df26aafe12d381bb7c4c14aabf403dfba0c2c973ae44c9832acbd62b4933b263eee6ebd00 \ No newline at end of file +6d933ce349ac1b16f04bfc685ef6ad60db15f99ba6c17ade0d9821c97efba02aa07da0afb142dbf1e86c61b647846f53288ad21dfabd2640a7b06c35e38b6cdc187dbd86f57e4f9770df7f20c97e66c146241628071d6c8f96448a1b137aeff67e908fd2795f05b40e79f789fc290c42c58f3c6590b64b9ec1addf8e7466d13c77b730a011ecaf72e5248802f5a9bf371af559858527cc9a62a6a9218773f7308700225cf36cd22c2e5a5549219e45786bf5976ab1b30db49601f413c9169996eed62d4774b3b724487982919bc9758df03bff9e72dd2069565d3c14501d7884345d113f7348549751a4511553be1d33a5ef5b9e0663e5a9affffecea7bd22d438cd7ebd2ae18b574496f76662416bc5a4e54d2b034cb356e200058d8634cf3bd714fc7c1db2b8be8c840590a6104af9a6e11288980003daca8a3cd069b5190aeec76899a98a89f039b4c791307b0ad3a91a7a904037b8bc3a5d6139f5bcf373438b8ff642083bcbda06f36b6b810abf40a21b512afdc5652cdf88546beb5ce24d16d10220119898a68392d4dd8ed7807a1b914c349318b6d431e0cb79430929d6320984855c3e9521ee1302622a5df20bbd3abed6cc8a3590bfd65f87efafe7af05715407499c58c8990ac9e68fc6012e1b531d4e688d56af93a212a00e0e9d037190a857bf11e8dd3349ab4794c0e497600d5884e8d1abbc67488986e19eba +a841f169683a0d2d768d4582ded75cf5c722658caeb871185638e9b66c789d4300a3630253e2293cba563ca6ed4e16d00d2347f6ac68842a56d8dd477a6248b7364573a694a5241c68065aa5e45b258470e6d33d400723618c7b1ebc2c5e7c55def9706dcaa37edf0bf7a948df51cad8db481516598db7015a9a516fa1b81093ebec65e1fe17504ead9fd533d475669403d8ea69483e72713025fa8ec1a250c7d24f7b9a9bb52a0aa8973368edffab0557fc47d4be9a8447f91a739ef711d88ffcaf39eea552604efefd36b539ef4a37064a3c8acd72a9cf17ef8313428e1aa20ada9e74265de0c685e16f6fd94eb30fb79761157640527979435d345a9f1f819a57de830d70d801329fdaba9221c7238c7bf54f6c07b22c0abfdfd71727d17c516c3ebdc43e85cbaa6b9aa9e3faf5320d7b9af7206e0c3e540c7b1709790438 \ No newline at end of file diff --git a/src/main/resources/snapshotTestnet.txt b/src/main/resources/snapshotTestnet.txt index 43d84af7..f81b185d 100644 --- a/src/main/resources/snapshotTestnet.txt +++ b/src/main/resources/snapshotTestnet.txt @@ -1,8 +1,8 @@ -556a2431d03e57e92b7d4d4d37f98332fce5427d8167e16c0a5cfbe20899d261;536561674354688 -196a2095205189ad2aa77c1125fc9e5d9c4888fb307a4a16caca6f6d311036e7;536561674354688 -9ac84e8c4df3e51e78f088b2f51408c97333ad982313101cac14ccb03f137e1f;536561674354688 -b662e011dae0a5a554281efc7d858894d797fe92b292c5a29c8d3b2ce648aae0;536561674354688 -6341291c330f3efd052cbaa30169072ecf6b6a05832727a5e620572c2fddc1f4;536561674354688 -09b5c36fec0898d3b5194a183aa3cac34cc270ab7b4f4a4a0bbb37d3cbac8d33;536561674354688 -0b6e5b0c7deb070ccfeea2952c61be8cf4746381d368849bed7c95cadca97f55;536561674354688 -78c71217ab4978912c90768da30de3246bbc985c41c76fdb4dc15ecb835086b7;536561674354688 +c212548bd3c4b596bf24b16c36aaa69a5ecaf5a8240232380b0a26539b6b8619;536561674354688 +ee1c15a76b2b1ce72acd7e559afafb7418ffac15246d7c2c9d1bfe0ea4b6a924;536561674354688 +164838c044a83bbe80ce4bd24547442ae6d496caa5496c4746ae71470c13b4ed;536561674354688 +fbbaa16ddca9bb3b77df5c0da972ba28e0bf5f560f58cfac91cf33ff840d874e;536561674354688 +034981b284960406429ce9004213114033095478e37e31944d4a67c32369754a;536561674354688 +0956e0cd8f5a5e3d364b57beb94bd34c73929820d26fba8d47c9b214cb60f3bc;536561674354688 +8434c99110df30e4c3529b78927daa07903e3c90d6d04e857cacb125a64a4723;536561674354688 +b5c0d3905117deabcce27666ca7d61399045d8a72a19b2a962ad4312a1fd9d60;536561674354688 diff --git a/src/test/java/net/helix/hlx/crypto/GreedyMinerTest.java b/src/test/java/net/helix/hlx/crypto/GreedyMinerTest.java index 269e0a9f..a225b612 100644 --- a/src/test/java/net/helix/hlx/crypto/GreedyMinerTest.java +++ b/src/test/java/net/helix/hlx/crypto/GreedyMinerTest.java @@ -92,7 +92,6 @@ public void noRandomFailTest() { minerThread.join(1000); } catch (InterruptedException ex) { } - System.out.println("result="+result[0]); Assert.assertFalse(result[0]); } diff --git a/src/test/java/net/helix/hlx/crypto/Sha3Test.java b/src/test/java/net/helix/hlx/crypto/Sha3Test.java index 9207e686..55832ea0 100644 --- a/src/test/java/net/helix/hlx/crypto/Sha3Test.java +++ b/src/test/java/net/helix/hlx/crypto/Sha3Test.java @@ -41,8 +41,8 @@ public void sha3SpongeTest() { s3.absorb(testBytes2, 0, txHex.length()); s3.squeeze(testBytes2Out, 0, Sha3.HASH_LENGTH); - log.info("Expected-Hash-Str: " + Hex.toHexString(testBytesOut)); - log.info("S256-Hash-Str : " + Hex.toHexString(testBytes2Out)); + log.debug("Expected-Hash-Str: " + Hex.toHexString(testBytesOut)); + log.debug("S256-Hash-Str : " + Hex.toHexString(testBytes2Out)); Assert.assertArrayEquals(testBytesOut, testBytes2Out); // Test Hex.decode() @@ -59,8 +59,8 @@ public void sha3SpongeTest() { _s3.absorb(encodedBytes2, 0, encodedBytes2.length); _s3.squeeze(encodedBytes2Out, 0, Sha3.HASH_LENGTH); - log.info("Expected-Hash-Hex: " + Hex.toHexString(encodedBytesOut)); - log.info("S256-Hash-Hex : " + Hex.toHexString(encodedBytes2Out)); + log.debug("Expected-Hash-Hex: " + Hex.toHexString(encodedBytesOut)); + log.debug("S256-Hash-Hex : " + Hex.toHexString(encodedBytes2Out)); Assert.assertArrayEquals(encodedBytesOut, encodedBytes2Out); } diff --git a/src/test/java/net/helix/hlx/crypto/Sha3_512Test.java b/src/test/java/net/helix/hlx/crypto/Sha3_512Test.java index e05c88e8..069e51b9 100644 --- a/src/test/java/net/helix/hlx/crypto/Sha3_512Test.java +++ b/src/test/java/net/helix/hlx/crypto/Sha3_512Test.java @@ -41,8 +41,8 @@ public void sha3_512SpongeTest() { s3.absorb(testBytes2, 0, txHex512.length()); s3.squeeze(testBytes2Out, 0, Sha3_512.HASH_LENGTH); - log.info("Expected-Hash-Str: " + Hex.toHexString(testBytesOut)); - log.info("S512-Hash-Str : " + Hex.toHexString(testBytes2Out)); + log.debug("Expected-Hash-Str: " + Hex.toHexString(testBytesOut)); + log.debug("S512-Hash-Str : " + Hex.toHexString(testBytes2Out)); Assert.assertArrayEquals(testBytesOut, testBytes2Out); // Test Hex.decode() @@ -59,8 +59,8 @@ public void sha3_512SpongeTest() { _s3.absorb(encodedBytes2, 0, encodedBytes2.length); _s3.squeeze(encodedBytes2Out, 0, Sha3_512.HASH_LENGTH); - log.info("Expected-Hash-Hex: " + Hex.toHexString(encodedBytesOut)); - log.info("S512-Hash-Hex : " + Hex.toHexString(encodedBytes2Out)); + log.debug("Expected-Hash-Hex: " + Hex.toHexString(encodedBytesOut)); + log.debug("S512-Hash-Hex : " + Hex.toHexString(encodedBytes2Out)); Assert.assertArrayEquals(encodedBytesOut, encodedBytes2Out); } diff --git a/src/test/java/net/helix/hlx/crypto/WinternitzTest.java b/src/test/java/net/helix/hlx/crypto/WinternitzTest.java new file mode 100644 index 00000000..39ead5dd --- /dev/null +++ b/src/test/java/net/helix/hlx/crypto/WinternitzTest.java @@ -0,0 +1,90 @@ +package net.helix.hlx.crypto; + +import java.util.Arrays; +import java.util.Random; +import org.junit.Assert; +import org.junit.Test; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import net.helix.hlx.model.Hash; +import net.helix.hlx.model.HashFactory; +import net.helix.hlx.controllers.TransactionViewModel; + + +public class WinternitzTest { + + private static final Logger log = LoggerFactory.getLogger(WinternitzTest.class); + private static final Random RND = new Random(); + + + @Test(expected=RuntimeException.class) + public void subseedIndexRangeTest() { + byte[] seed = new byte[Sha3.HASH_LENGTH * 2]; + int index = Integer.MAX_VALUE-254; + Winternitz.subseed(SpongeFactory.Mode.S256, seed, index); + } + + @Test + public void generateWinternitzAddressTest() { + byte[] seed = new byte[Sha3.HASH_LENGTH]; + int index; + for (int security = 1; security <= 3; security++) { + RND.nextBytes(seed); + index = RND.nextInt(256); + byte[] address = Winternitz.generateAddress(seed, index, security); + Assert.assertNotNull(address); + Assert.assertFalse(Arrays.equals(new byte[address.length], address)); + } + } + + @Test + public void signaturesResolveToAddressTest() throws Exception { + int index = 10; + int nof = 1; + SpongeFactory.Mode[] modes = {SpongeFactory.Mode.S256, SpongeFactory.Mode.K256}; + byte[] seed = new byte[64]; + RND.nextBytes(seed); + byte[] messageBytes = new byte[TransactionViewModel.SIZE]; + RND.nextBytes(messageBytes); + + for (SpongeFactory.Mode mode: modes) { + byte[] subseed = Winternitz.subseed(mode, seed, index); + byte[] key = Winternitz.key(mode, subseed, nof); + Sha3 sha3 = new Sha3(); + sha3.absorb(messageBytes, 0, messageBytes.length); + byte[] messageHash = new byte[Sha3.HASH_LENGTH]; + sha3.squeeze(messageHash, 0, Sha3.HASH_LENGTH); + byte[] normalizedFragment = Arrays.copyOf(Winternitz.normalizedBundle(messageHash), + Winternitz.NUMBER_OF_FRAGMENT_CHUNKS); + byte[] signature = Winternitz.signatureFragment(mode, normalizedFragment, key); + byte[] sigDigest = Winternitz.digest(mode, normalizedFragment, signature); + byte[] signedAddress = Winternitz.address(mode, sigDigest); + byte[] digest = Winternitz.digests(mode, key); + byte[] address = Winternitz.address(mode, digest); + Assert.assertTrue(Arrays.equals(address, signedAddress)); + } + } + + @Test + public void generateNAddressesForSeedTest() throws Exception { + int nof = 2; + //log.debug("seed,address_0,address_1,address_2,address_3"); + for (int i = 0; i < 50; i++) { + byte[] b = new byte[Hash.SIZE_IN_BYTES]; + RND.nextBytes(b); + Hash seed = HashFactory.TRANSACTION.create(b); + SpongeFactory.Mode mode = SpongeFactory.Mode.S256; + Hash[] addresses = new Hash[4]; + for (int j = 0; j < 4; j++) { + byte[] subseed = Winternitz.subseed(mode, seed.bytes(), j); + byte[] key = Winternitz.key(mode, subseed, nof); + byte[] digest = Winternitz.digests(mode, key); + byte[] address = Winternitz.address(mode, digest); + addresses[j] = HashFactory.ADDRESS.create(address); + } + //log.debug(String.format("%s,%s,%s,%s,%s", seed, addresses[0],addresses[1],addresses[2],addresses[3])); + } + } + +} diff --git a/src/test/java/net/helix/hlx/storage/TangleTest.java b/src/test/java/net/helix/hlx/storage/TangleTest.java new file mode 100644 index 00000000..323a2220 --- /dev/null +++ b/src/test/java/net/helix/hlx/storage/TangleTest.java @@ -0,0 +1,72 @@ +package net.helix.hlx.storage; + +import java.util.Arrays; +import java.util.Random; +import java.util.Set; + +import org.junit.After; +import org.junit.Before; +import org.junit.Test; +import org.junit.Assert; +import org.junit.rules.TemporaryFolder; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import net.helix.hlx.conf.*; +import net.helix.hlx.crypto.SpongeFactory; +import net.helix.hlx.model.TransactionHash; +import net.helix.hlx.model.persistables.Tag; +import net.helix.hlx.controllers.TransactionViewModel; +import net.helix.hlx.storage.rocksDB.RocksDBPersistenceProvider; +import net.helix.hlx.service.snapshot.SnapshotProvider; +import net.helix.hlx.service.snapshot.impl.SnapshotProviderImpl; + + +public class TangleTest { + + private static final Logger log = LoggerFactory.getLogger(TangleTest.class); + private static final Random RND = new Random(); + + private static final TemporaryFolder dbFolder = new TemporaryFolder(); + private static final TemporaryFolder logFolder = new TemporaryFolder(); + private static SnapshotProvider snapshotProvider; + private final Tangle tangle = new Tangle(); + + + @Before + public void setup() throws Exception { + dbFolder.create(); + logFolder.create(); + RocksDBPersistenceProvider rocksDBPersistenceProvider = new RocksDBPersistenceProvider( + dbFolder.getRoot().getAbsolutePath(), logFolder.getRoot().getAbsolutePath(), + 1000, Tangle.COLUMN_FAMILIES, Tangle.METADATA_COLUMN_FAMILY); + tangle.addPersistenceProvider(rocksDBPersistenceProvider); + tangle.init(); + + //snapshotProvider = new SnapshotProviderImpl().init(new MainnetConfig()); + snapshotProvider = new SnapshotProviderImpl().init(ConfigFactory.createHelixConfig(true)); + } + + @After + public void shutdown() throws Exception { + tangle.shutdown(); + snapshotProvider.shutdown(); + } + + @Test + public void saveTest() throws Exception { + } + + @Test + public void getKeysStartingWithValueTest() throws Exception { + byte[] bytes = new byte[TransactionViewModel.SIZE]; + RND.nextBytes(bytes); + TransactionViewModel transactionViewModel = new TransactionViewModel(bytes, + TransactionHash.calculate(SpongeFactory.Mode.S256, bytes)); + transactionViewModel.store(tangle, snapshotProvider.getInitialSnapshot()); + Set tag = tangle.keysStartingWith(Tag.class, + Arrays.copyOf(transactionViewModel.getTagValue().bytes(), 15)); + Assert.assertNotEquals(tag.size(), 0); + } + +} diff --git a/src/test/java/net/helix/hlx/storage/rocksDB/RocksDBPersistenceProviderTest.java b/src/test/java/net/helix/hlx/storage/rocksDB/RocksDBPersistenceProviderTest.java new file mode 100644 index 00000000..602a6095 --- /dev/null +++ b/src/test/java/net/helix/hlx/storage/rocksDB/RocksDBPersistenceProviderTest.java @@ -0,0 +1,89 @@ +package net.helix.hlx.storage.rocksDB; + +import java.util.Arrays; +import java.util.List; +import java.util.stream.Collectors; +import java.util.stream.IntStream; + +import org.junit.AfterClass; +import org.junit.BeforeClass; +import org.junit.Before; +import org.junit.Test; +import org.junit.Assert; +import org.junit.rules.TemporaryFolder; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import net.helix.hlx.storage.Tangle; +import net.helix.hlx.storage.Indexable; +import net.helix.hlx.storage.Persistable; +import net.helix.hlx.model.IntegerIndex; +import net.helix.hlx.model.persistables.Transaction; +import net.helix.hlx.utils.Pair; + + +public class RocksDBPersistenceProviderTest { + + private static final Logger log = LoggerFactory.getLogger(RocksDBPersistenceProviderTest.class); + + private static RocksDBPersistenceProvider rocksDBPersistenceProvider; + private static final TemporaryFolder dbFolder = new TemporaryFolder(); + private static final TemporaryFolder logFolder = new TemporaryFolder(); + + + @BeforeClass + public static void setupDB() throws Exception { + dbFolder.create(); + logFolder.create(); + rocksDBPersistenceProvider = new RocksDBPersistenceProvider( + dbFolder.getRoot().getAbsolutePath(), logFolder.getRoot().getAbsolutePath(), + 1000, Tangle.COLUMN_FAMILIES, Tangle.METADATA_COLUMN_FAMILY); + rocksDBPersistenceProvider.init(); + } + + @AfterClass + public static void shutdownDB() throws Exception { + rocksDBPersistenceProvider.shutdown(); + dbFolder.delete(); + logFolder.delete(); + rocksDBPersistenceProvider = null; + } + + @Before + public void setUp() throws Exception { + rocksDBPersistenceProvider.clear(Transaction.class); + } + + @Test + public void doSaveAndDeleteBatchTest() throws Exception { + Persistable tx = new Transaction(); + byte[] bytes = new byte[Transaction.SIZE]; + Arrays.fill(bytes, (byte) 1); + tx.read(bytes); + tx.readMetadata(bytes); + List> models = IntStream.range(1, 1000) + .mapToObj(i -> new Pair<>((Indexable) new IntegerIndex(i), tx)) + .collect(Collectors.toList()); + rocksDBPersistenceProvider.saveBatch(models); + + List>> modelsToDelete = models.stream() + .filter(entry -> ((IntegerIndex) entry.low).getValue() < 900) + .map(entry -> new Pair<>(entry.low, entry.hi.getClass())) + .collect(Collectors.toList()); + rocksDBPersistenceProvider.deleteBatch(modelsToDelete); + + for (Pair> model : modelsToDelete) { + Assert.assertNull("value at index " + ((IntegerIndex) model.low).getValue() + " should be deleted", + rocksDBPersistenceProvider.get(model.hi, model.low).bytes()); + } + + List indexes = IntStream.range(900, 1000) + .mapToObj(i -> new IntegerIndex(i)) + .collect(Collectors.toList()); + for (IntegerIndex index : indexes) { + Assert.assertArrayEquals("saved bytes are not as expected in index " + index.getValue(), tx.bytes(), + rocksDBPersistenceProvider.get(Transaction.class, index).bytes()); + } + } + +}