Skip to content
This repository was archived by the owner on Apr 26, 2024. It is now read-only.
Merged
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
## 1.0.5
- Fixed `getBalance`: `RoundViewModel.get()` returns null on `index`=0, thus NPE was thrown when `references` were not passed and the first round hadn't been completed. In our implementation the snapshot is already constructed based on relative confirmations, thus it suffices for `getBalances` to respond with balance according to `latestSnapshot`.
- Updated `previousEpochsSpentAddresses` resource files

## 1.0.4
- Fixed several zmq publish statements in which an incorrect format was specified.
Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@

Pendulum is a quorum based [Tangle](https://github.com/iotaledger/iri/) implementation designed towards reliable timekeeping and high-throughput messaging.

- **Latest release:** 1.0.4 pre-release
- **Latest release:** 1.0.5 pre-release
- **License:** GPLv3

Special thanks to all of the [IOTA Contributors](https://github.com/iotaledger/iri/graphs/contributors)!
Expand Down
4 changes: 0 additions & 4 deletions src/main/java/net/helix/pendulum/Pendulum.java
Original file line number Diff line number Diff line change
Expand Up @@ -138,14 +138,12 @@ public Pendulum(PendulumConfig configuration) throws TransactionPruningException
? new LocalSnapshotManagerImpl()
: null;
milestoneService = new MilestoneServiceImpl();
//validatorService = new ValidatorServiceImpl();
validatorManagerService = new ValidatorManagerServiceImpl();
latestMilestoneTracker = new MilestoneTrackerImpl();
candidateTracker = new CandidateTrackerImpl();
latestSolidMilestoneTracker = new LatestSolidMilestoneTrackerImpl();
seenMilestonesRetriever = new SeenMilestonesRetrieverImpl();
milestoneSolidifier = new MilestoneSolidifierImpl();
//validatorSolidifier = new ValidatorSolidifierImpl();
candidateSolidifier = new CandidateSolidifierImpl();
transactionPruner = configuration.getLocalSnapshotsEnabled() && configuration.getLocalSnapshotsPruningEnabled()
? new AsyncTransactionPruner()
Expand Down Expand Up @@ -219,7 +217,6 @@ public void init() throws Exception {
}
}

//TODO: bundleValidator should be passed to: milestoneService, spentAddressService and ledgerService.
private void injectDependencies() throws SnapshotException, TransactionPruningException, SpentAddressesException {
//snapshot provider must be initialized first
//because we check whether spent addresses data exists
Expand All @@ -238,7 +235,6 @@ private void injectDependencies() throws SnapshotException, TransactionPruningEx
latestMilestoneTracker);
seenMilestonesRetriever.init(tangle, snapshotProvider, transactionRequester);
milestoneSolidifier.init(snapshotProvider, transactionValidator);
//validatorSolidifier.init(snapshotProvider, transactionValidator);
candidateSolidifier.init(snapshotProvider, transactionValidator);
ledgerService.init(tangle, snapshotProvider, snapshotService, milestoneService, configuration);
if (transactionPruner != null) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1040,7 +1040,7 @@ public interface Defaults {

//Snapshot
boolean LOCAL_SNAPSHOTS_ENABLED = true;
boolean LOCAL_SNAPSHOTS_PRUNING_ENABLED = true;
boolean LOCAL_SNAPSHOTS_PRUNING_ENABLED = false;
int LOCAL_SNAPSHOTS_PRUNING_DELAY = 50000;
int LOCAL_SNAPSHOTS_INTERVAL_SYNCED = 10;
int LOCAL_SNAPSHOTS_INTERVAL_UNSYNCED = 1000;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -269,9 +269,6 @@ public static Set<Hash> getMilestoneTrunk(Tangle tangle, TransactionViewModel tr
// idx = 0 - (n-1): merkle root in branch, trunk is normal tx hash
trunk.add(transaction.getTrunkTransactionHash());
}
if (log.isTraceEnabled()) {
log.trace("trunk: {}", PendulumUtils.logHashList(trunk, 8));
}
return trunk;
}

Expand Down Expand Up @@ -310,9 +307,6 @@ public static Set<Hash> getMilestoneBranch(Tangle tangle, TransactionViewModel t
}
}
}
if (log.isTraceEnabled()) {
log.trace("Milestone branch: {}", PendulumUtils.logHashList(branch, 8));
}
return branch;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -145,6 +145,9 @@ public void trackLatestSolidMilestones() throws MilestoneException {
try {
int currentSolidRoundIndex = snapshotProvider.getLatestSnapshot().getIndex();
RoundViewModel nextRound;
if (currentSolidRoundIndex < milestoneTracker.getCurrentRoundIndex()) {
log.delegate().trace("Current Solid Round = " + currentSolidRoundIndex + ", Current Round = " + milestoneTracker.getCurrentRoundIndex() + ", Still in Round = " + (currentSolidRoundIndex == milestoneTracker.getCurrentRoundIndex() - 1) + ", Round active = " + milestoneTracker.isRoundActive(RoundIndexUtil.getCurrentTime()));
}
while (!Thread.currentThread().isInterrupted() && (currentSolidRoundIndex < milestoneTracker.getCurrentRoundIndex())
&& (currentSolidRoundIndex != milestoneTracker.getCurrentRoundIndex() - 1 || !milestoneTracker.isRoundActive(RoundIndexUtil.getCurrentTime()))) {

Expand All @@ -154,6 +157,7 @@ public void trackLatestSolidMilestones() throws MilestoneException {
// round has finished without milestones
RoundViewModel latest = RoundViewModel.latest(tangle);
if (latest != null && latest.index() > currentSolidRoundIndex + 1 && isRoundSolid(latest)) {
log.delegate().trace("Round #" + (currentSolidRoundIndex + 1) + " has finished without milestones");
nextRound = new RoundViewModel(currentSolidRoundIndex + 1, new HashSet<>());
nextRound.store(tangle);
tracer.trace("created and stored empty round: {}", nextRound.index());
Expand All @@ -164,6 +168,7 @@ public void trackLatestSolidMilestones() throws MilestoneException {
break;
}
}
log.delegate().trace("Round = " + nextRound.index() + ", solid = " + isRoundSolid(nextRound));
if (isRoundSolid(nextRound)) {
tracer.trace("solid round: {}", nextRound.toString());
// TODO: Ask Oliver about these classes?
Expand All @@ -173,6 +178,7 @@ public void trackLatestSolidMilestones() throws MilestoneException {
logChange(currentSolidRoundIndex);
currentSolidRoundIndex = snapshotProvider.getLatestSnapshot().getIndex();
tangle.publish("ctx %s %d", nextRound.getReferencedTransactions(tangle, nextRound.getConfirmedTips(tangle, BasePendulumConfig.Defaults.VALIDATOR_SECURITY)), nextRound.index());
log.delegate().trace("ctx= " + nextRound.getReferencedTransactions(tangle, nextRound.getConfirmedTips(tangle, BasePendulumConfig.Defaults.VALIDATOR_SECURITY)) + ", round=" + nextRound.index());
}
}
} catch (Exception e) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,6 @@
import net.helix.pendulum.model.Hash;
import net.helix.pendulum.model.HashFactory;
import net.helix.pendulum.service.snapshot.*;
import net.helix.pendulum.service.spentaddresses.SpentAddressesException;
import net.helix.pendulum.service.spentaddresses.SpentAddressesProvider;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

Expand Down Expand Up @@ -101,7 +99,7 @@ public class SnapshotProviderImpl implements SnapshotProvider {
* @return the initialized instance itself to allow chaining
*
*/
public SnapshotProviderImpl init(SnapshotConfig config) throws SnapshotException, SpentAddressesException {
public SnapshotProviderImpl init(SnapshotConfig config) throws SnapshotException {
this.config = config;
File pathToLocalSnapshotDir = Paths.get(this.config.getLocalSnapshotsBasePath()).toFile();
if (!pathToLocalSnapshotDir.exists() || !pathToLocalSnapshotDir.isDirectory()) {
Expand Down Expand Up @@ -201,7 +199,7 @@ public void shutdown() {
*
* @throws SnapshotException if anything goes wrong while loading the snapshots
*/
private void loadSnapshots() throws SnapshotException, SpentAddressesException {
private void loadSnapshots() throws SnapshotException {
initialSnapshot = loadLocalSnapshot();
if (initialSnapshot == null) {
initialSnapshot = loadBuiltInSnapshot();
Expand All @@ -220,7 +218,7 @@ private void loadSnapshots() throws SnapshotException, SpentAddressesException {
* @return local snapshot of the node
* @throws SnapshotException if local snapshot files exist but are malformed
*/
private Snapshot loadLocalSnapshot() throws SnapshotException, SpentAddressesException {
private Snapshot loadLocalSnapshot() throws SnapshotException {
if (config.getLocalSnapshotsEnabled()) {
String fileSeperator = System.getProperty("file.separator");
File localSnapshotFile = new File(
Expand All @@ -231,8 +229,6 @@ private Snapshot loadLocalSnapshot() throws SnapshotException, SpentAddressesExc
);
if (localSnapshotFile.exists() && localSnapshotFile.isFile() && localSnapshotMetaDataFile.exists() &&
localSnapshotMetaDataFile.isFile()) {
//TODO: enable this for mainnet-1.0. This will cause issues on a testnet where value transfers might not be guaranteed during a local snapshot und thus would always be thrown.
//assertSpentAddressesDbExist();
SnapshotState snapshotState = readSnapshotStatefromFile(localSnapshotFile.getAbsolutePath());
if (!snapshotState.hasCorrectSupply()) {
throw new SnapshotException("the snapshot state file has an invalid supply");
Expand All @@ -245,25 +241,9 @@ private Snapshot loadLocalSnapshot() throws SnapshotException, SpentAddressesExc
return new SnapshotImpl(snapshotState, snapshotMetaData);
}
}

return null;
}

private void assertSpentAddressesDbExist() throws SpentAddressesException {
try {
File spentAddressFolder = new File(SpentAddressesProvider.SPENT_ADDRESSES_DB);
//If there is at least one file in the db the check should pass
if (Files.newDirectoryStream(spentAddressFolder.toPath(), "*.sst").iterator().hasNext()) {
return;
}
}
catch (IOException e){
throw new SpentAddressesException("Can't load " + SpentAddressesProvider.SPENT_ADDRESSES_DB + " folder", e);
}

throw new SpentAddressesException(SpentAddressesProvider.SPENT_ADDRESSES_DB + " folder has no sst files");
}

/**
* Loads the builtin snapshot (last global snapshot) that is embedded in the jar (if a different path is provided it
* can also load from the disk).
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -517,15 +517,6 @@ private void cleanupOldData(PendulumConfig config, TransactionPruner transaction
private void persistLocalSnapshot(SnapshotProvider snapshotProvider, Snapshot newSnapshot, PendulumConfig config)
throws SnapshotException {

try {
spentAddressesService.persistSpentAddresses(snapshotProvider.getInitialSnapshot().getIndex(),
newSnapshot.getIndex());

} catch (Exception e) {
throw new SnapshotException(e);
}

// TODO: Add timestamp and hash to this snapshot so it can be saved into hashdir/timestamp-filename
snapshotProvider.writeSnapshotToDisk(newSnapshot, config.getLocalSnapshotsBasePath() );

snapshotProvider.getLatestSnapshot().lockWrite();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,15 +20,6 @@ public interface SpentAddressesService {
*/
boolean wasAddressSpentFrom(Hash addressHash) throws SpentAddressesException;

/**
* Calculates and persists all spent addresses in between a range that were validly signed
*
* @param fromMilestoneIndex the lower bound milestone index (inclusive)
* @param toMilestoneIndex the upper bound milestone index (exclusive)
* @throws Exception when anything went wrong whilst calculating.
*/
void persistSpentAddresses(int fromMilestoneIndex, int toMilestoneIndex) throws Exception;

/**
* Persist all the verifiable spent from a given list of transactions
* @param transactions transactions to obtain spends from
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,18 +2,15 @@

import net.helix.pendulum.BundleValidator;
import net.helix.pendulum.controllers.AddressViewModel;
import net.helix.pendulum.controllers.RoundViewModel;
import net.helix.pendulum.controllers.TransactionViewModel;
import net.helix.pendulum.model.Hash;
import net.helix.pendulum.service.snapshot.SnapshotProvider;
import net.helix.pendulum.service.snapshot.impl.SnapshotServiceImpl;
import net.helix.pendulum.service.spentaddresses.SpentAddressesException;
import net.helix.pendulum.service.spentaddresses.SpentAddressesProvider;
import net.helix.pendulum.service.spentaddresses.SpentAddressesService;
import net.helix.pendulum.service.tipselection.TailFinder;
import net.helix.pendulum.service.tipselection.impl.TailFinderImpl;
import net.helix.pendulum.storage.Tangle;
import net.helix.pendulum.utils.dag.DAGHelper;
import org.apache.commons.collections4.CollectionUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
Expand Down Expand Up @@ -80,42 +77,6 @@ public boolean wasAddressSpentFrom(Hash addressHash) throws SpentAddressesExcept
return false;
}

@Override
public void persistSpentAddresses(int fromMilestoneIndex, int toMilestoneIndex) throws SpentAddressesException {
Set<Hash> addressesToCheck = new HashSet<>();
try {
for (int i = fromMilestoneIndex; i < toMilestoneIndex; i++) {
RoundViewModel currentMilestone = RoundViewModel.get(tangle, i);
if (currentMilestone != null) {
for (Hash confirmedTip : currentMilestone.getConfirmedTips(tangle, 1)) {
DAGHelper.get(tangle).traverseApprovees(
confirmedTip,
transactionViewModel -> transactionViewModel.snapshotIndex() >= currentMilestone.index(),
transactionViewModel -> addressesToCheck.add(transactionViewModel.getAddressHash())
);
}
}
}
} catch (Exception e) {
throw new SpentAddressesException(e);
}

//Can only throw runtime exceptions in streams
try {
spentAddressesProvider.saveAddressesBatch(addressesToCheck.stream()
.filter(ThrowingPredicate.unchecked(this::wasAddressSpentFrom))
.collect(Collectors.toList()));
log.trace("spentAddressesService.persistSpentAddresses += 1");
} catch (RuntimeException e) {
if (e.getCause() instanceof SpentAddressesException) {
throw (SpentAddressesException) e.getCause();
} else {
throw e;
}
}

}

@Override
public void persistSpentAddresses(Collection<TransactionViewModel> transactions) throws SpentAddressesException {
try {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -312,7 +312,7 @@ public boolean processCandidate(TransactionViewModel transaction) throws Validat
* message processor so external receivers get informed about this change.
* </p>
*
* @param candidateAddress
* @param validatorAddress
*
*/

Expand Down
4 changes: 2 additions & 2 deletions src/main/resources/previousEpochsSpentAddresses.sig
100755 → 100644
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
b59766f0f98a37e854abc145ce29dee6d3425687e705276598ee1e5cc978b9aeeed25edac17336d67540375c58aa9a461764e4977d3736353219dcdb4449914deaacc6eaa1ff82326814690ecb3b02f3e5ba1d72535e1726339bc80a54d7ae0f909db021f095e81d1a33220018c84165cc7838c6d938816e59653f3a1860ae44e9ddd1257c84fc1798fcceef2ea3c55e527bf27a66d1d36eaf1d738ea7fd8ad664c21bb62408ac43b2897519af3c76017b991f7f1c8c0b624ff3753d533ce20de94ef08f3a4fd6f6cbdd88e24dc689ecb7c537b8d315a73b0573712cfc71cf92891316868f69b545c9ac4f384f9a1f9af9a84f990c54d482792c5eaf952df82a19483dd598934f75fb0dc7e4727c8c8cdbb122f1e8843266665fa7601b6cea8af3dcde8b291e0271284f1927960e65a9c4df45a0dafef7104756eb17dff29560ec25d8b00c13ed93bc40dd636936454aa71e34adb822adf6ba04296b76902b44d7a784d6f103d347119c2d53a81961d04b793ab95cfd576021026ff63ee2559e19812364047cb86d5b7254cb17bc2d8bdb9a92ec6f0c1e2ff4ef8bba1ebe5638a5c03c725f3e140511a32d93b432c99b7edab2d8c3625106d9850c7fe1fdeb7d31e5422474e31cb3f7bf556fa463e4a8708b9108f9b09946d8c3e3b2e44f8d426942ec03861841fc50e9ae2859e2afdea1d15f650e2bb31c3632e86f6eb81ffe
5d6bbee80c74e0853ffb44016e68b6bf33092c090753315c8237147326f414fab3edc04b3f462750c8b135eb24335b8523f186b48b228340ff8b35e62f8fbb5209cf9b45356741eaac4e23e82bace68a3c9fb4f9af895fc917caaee08111b4fa551cd242dd80545d10d4560f1a784253ce129dfa04d5457d42657ddb4aaebea49cb1c37dd6cf08136328a6d74f4c20469a2ed00368f9db2c49544ec2e8d52d64cb56954f68d9cb29475840ab5d2a585f5e3e2305201f547d1a104d6a4742fc6e8baa014b56a25ab5ff635263d414478c31f6d53857d7770d9d073e17936eb41cb4f6e6f82c29a6f6f5f438e1953666e238591ad064455db0cf9fb6f1098d3896130b03fff84d3dafcf373e56bce1413a396734d9984b0e9633539f7fa7d64983afd8c37b8d2de9efa0f09a87096ad7f34f09f73a534f951abf95504a73c848a2bf7a6d249e29e19407d25f7dae13bc14c4b77ca6c2c501a7afa7783cfdeca4aa5b8d563a2d390186f75d228172857fcaa80c458708e964151296dd6d9a4b6b705d759d555379042246b2b5f4d2ec18f0720d6241498f954f102fe6572b177cb710e56296eaf88d87ae69623c45d4f295575c547459dba97d85316ce534f695a1c14d747351bbacd0a401e6b2a3176d50ce09ca23439dcca5836668111ffd6102e4c23468fc42011e9b2b8cb6d9f1edcdcb589d88350ad79c3dea1f016ce5441d
d54189b20f649dd4f2139b22c61afb6412352660a935ee1713549c3c2614e080cc62333e4f9d5c24c84f507959dd7dce2851d66649125b61c0d84864147c9cacdfe58482527a0e06a5060a3e34998b7e91da5ba5bcb7f31c52d25ddb785a1ad02ef315df3eb125fc3871dde8f47c2f42de12ea26ea092ca8f3a2d53d60680c0ab59766f0f98a37e854abc145ce29dee6d3425687e705276598ee1e5cc978b9aecd97773c2137e43117e1419e990381c5d3fd1f35c5c48273cc4a20cd9487a8fbcc62333e4f9d5c24c84f507959dd7dce2851d66649125b61c0d84864147c9cacbb28fa2f114ac520e726db6ca0008cbe29a347059d2c7c280d7698998bdae972f0c9b65c73b05cafde461aee930ebbcd39ebb09c467b1d907988656e8f0c058ff0c9b65c73b05cafde461aee930ebbcd39ebb09c467b1d907988656e8f0c058fbb28fa2f114ac520e726db6ca0008cbe29a347059d2c7c280d7698998bdae972ec25d8b00c13ed93bc40dd636936454aa71e34adb822adf6ba04296b76902b44cf3bfc91633463acc5b08b15756adb29eb6477c94e98b12d8def8012e4fe1e0419812364047cb86d5b7254cb17bc2d8bdb9a92ec6f0c1e2ff4ef8bba1ebe563864c21bb62408ac43b2897519af3c76017b991f7f1c8c0b624ff3753d533ce20d19812364047cb86d5b7254cb17bc2d8bdb9a92ec6f0c1e2ff4ef8bba1ebe5638
f3dcde8b291e0271284f1927960e65a9c4df45a0dafef7104756eb17dff29560ec25d8b00c13ed93bc40dd636936454aa71e34adb822adf6ba04296b76902b4419812364047cb86d5b7254cb17bc2d8bdb9a92ec6f0c1e2ff4ef8bba1ebe5638891316868f69b545c9ac4f384f9a1f9af9a84f990c54d482792c5eaf952df82ab3edc04b3f462750c8b135eb24335b8523f186b48b228340ff8b35e62f8fbb52b3edc04b3f462750c8b135eb24335b8523f186b48b228340ff8b35e62f8fbb5231e5422474e31cb3f7bf556fa463e4a8708b9108f9b09946d8c3e3b2e44f8d429cb1c37dd6cf08136328a6d74f4c20469a2ed00368f9db2c49544ec2e8d52d64f3dcde8b291e0271284f1927960e65a9c4df45a0dafef7104756eb17dff29560b3edc04b3f462750c8b135eb24335b8523f186b48b228340ff8b35e62f8fbb52b3edc04b3f462750c8b135eb24335b8523f186b48b228340ff8b35e62f8fbb52a5c03c725f3e140511a32d93b432c99b7edab2d8c3625106d9850c7fe1fdeb7d6942ec03861841fc50e9ae2859e2afdea1d15f650e2bb31c3632e86f6eb81ffebf7a6d249e29e19407d25f7dae13bc14c4b77ca6c2c501a7afa7783cfdeca4aac14d747351bbacd0a401e6b2a3176d50ce09ca23439dcca5836668111ffd6102e4c23468fc42011e9b2b8cb6d9f1edcdcb589d88350ad79c3dea1f016ce5441d
53dbf3faa1b7484ede3e498b7b3a52a0ff5ec1397035af7e91d9efa2be3be92bfe176801e7932129583a3b77ec5fb774f58d7b08517d228f80299bdc144eb4df33525ab036bd026748c7792ea433e3cd100c9e89e5a58acdd17bc1d35655ff4107564fa6420478464bcf3dc76976a8bd69fae53ba539ed96ec699d0f8c4e29e68783b7ca67423e70e96d725ab7878faeb63101af872118b3167d267828f525a4232c2e0fcb6dccac4fbb0b06694b83f192b81cf69b9ccb29dd9f1f1b58c3587f67696ca6750cc4d109bcb889fdbe0eb6fd950bbb3bc3b6907624827089164f0f517b4d0d75be8a7497f61861e730e4a768da4bfee4c623094aab12673a070f131b73c1b05108e51c8faa435d7473b79c6ac9081b091912df0a0eec07bd1faf0d8b8650707566ab1b6e0d2919d2b7b59a1a7757d1b4ddfa4cccba0dfaef8d472a
Loading