Skip to content
This repository has been archived by the owner on Aug 23, 2020. It is now read-only.

Commit

Permalink
Added bundle validity rules (#1786)
Browse files Browse the repository at this point in the history
* added bundle validity rules

* commented on test and added invalid bundle tests

* Fix: lower error severity for faulty neighbor to warning (#1710)

Co-authored-by: Dyrell Chapman <dyrell.chapman@iota.org>
  • Loading branch information
acha-bill and DyrellC authored Mar 16, 2020
1 parent b79cdcf commit 450b728
Show file tree
Hide file tree
Showing 3 changed files with 111 additions and 4 deletions.
61 changes: 58 additions & 3 deletions src/main/java/com/iota/iri/BundleValidator.java
Original file line number Diff line number Diff line change
Expand Up @@ -55,22 +55,33 @@ public enum Validity {
*/
public static final int MODE_VALIDATE_SEMANTICS = 1 << 2;

/**
* Instructs the validation code to validate all transactions within the bundle approve via their branch the trunk
* transaction of the head transaction
*/
public static final int MODE_VALIDATE_BUNDLE_TX_APPROVAL = 1 << 3;

/**
* Instructs the validation code to validate that the bundle only approves tail txs.
*/
public static final int MODE_VALIDATE_TAIL_APPROVAL = 1 << 4;

/**
* Instructs the validation code to fully validate the semantics, bundle hash and signatures of the given bundle.
*/
public static final int MODE_VALIDATE_ALL = MODE_VALIDATE_SIGNATURES | MODE_VALIDATE_BUNDLE_HASH | MODE_VALIDATE_SEMANTICS;
public static final int MODE_VALIDATE_ALL = MODE_VALIDATE_SIGNATURES | MODE_VALIDATE_BUNDLE_HASH | MODE_VALIDATE_SEMANTICS | MODE_VALIDATE_TAIL_APPROVAL | MODE_VALIDATE_BUNDLE_TX_APPROVAL;

/**
* Instructs the validation code to skip checking the bundle's already computed validity and instead to proceed to
* validate the bundle further.
*/
public static final int MODE_SKIP_CACHED_VALIDITY = 1 << 3;
public static final int MODE_SKIP_CACHED_VALIDITY = 1 << 5;

/**
* Instructs the validation code to skip checking whether the tail transaction is present or a tail transaction was
* given as the start transaction.
*/
public static final int MODE_SKIP_TAIL_TX_EXISTENCE = 1 << 4;
public static final int MODE_SKIP_TAIL_TX_EXISTENCE = 1 << 6;

/**
* Fetches a bundle of transactions identified by the {@code tailHash} and validates the transactions. Bundle is a
Expand All @@ -85,6 +96,8 @@ public enum Validity {
* <li>Total bundle value is 0 (inputs and outputs are balanced)</li>
* <li>Recalculate the bundle hash by absorbing and squeezing the transactions' essence</li>
* <li>Validate the signature on input transactions</li>
* <li>The bundle must only approve tail transactions</li>
* <li>All transactions within the bundle approve via their branch the trunk transaction of the head transaction.</li>
* </ol>
* <p>
* As well as the following syntactic checks:
Expand Down Expand Up @@ -177,6 +190,17 @@ public static Validity validate(Tangle tangle, Hash startTxHash, int validationM
return bundleHashValidity;
}

//verify that the bundle only approves tail txs
Validity bundleTailApprovalValidity = validateBundleTailApproval(tangle, bundleTxs);
if(hasMode(validationMode, MODE_VALIDATE_TAIL_APPROVAL) && bundleTailApprovalValidity != Validity.VALID){
return bundleTailApprovalValidity;
}

//verify all transactions within the bundle approve via their branch the trunk transaction of the head transaction
Validity bundleTransactionsApprovalValidity = validateBundleTransactionsApproval(bundleTxs);
if(hasMode(validationMode, MODE_VALIDATE_BUNDLE_TX_APPROVAL) && bundleTransactionsApprovalValidity != Validity.VALID){
return bundleTransactionsApprovalValidity;
}

// verify the signatures of input transactions
if (hasMode(validationMode, MODE_VALIDATE_SIGNATURES)) {
Expand Down Expand Up @@ -379,6 +403,37 @@ public static boolean isInconsistent(Collection<TransactionViewModel> transactio
return (sum != 0 || transactionViewModels.isEmpty());
}

/**
* A bundle is invalid if The branch transaction hash of the non head transactions within a bundle, is not the same
* as the trunk transaction hash of the head transaction.
*
* @param bundleTxs list of transactions that are in a bundle.
* @return Whether the bundle tx chain is valid.
*/
public static Validity validateBundleTransactionsApproval(List<TransactionViewModel> bundleTxs){
Hash headTrunkTransactionHash = bundleTxs.get(bundleTxs.size() - 1).getTrunkTransactionHash();
for(int i = 0; i < bundleTxs.size() - 1; i++){
if(!bundleTxs.get(i).getBranchTransactionHash().equals(headTrunkTransactionHash)){
return Validity.INVALID;
}
}
return Validity.VALID;
}

/**
* A bundle is invalid if the trunk and branch transactions approved by the bundle are non tails.
*
* @param bundleTxs The txs in the bundle.
* @return Whether the bundle approves only tails.
*/
public static Validity validateBundleTailApproval(Tangle tangle, List<TransactionViewModel> bundleTxs) throws Exception {
TransactionViewModel headTx = bundleTxs.get(bundleTxs.size() - 1);
TransactionViewModel bundleTrunkTvm = headTx.getTrunkTransaction(tangle);
TransactionViewModel bundleBranchTvm = headTx.getBranchTransaction(tangle);
return bundleTrunkTvm != null && bundleBranchTvm != null && bundleBranchTvm.getCurrentIndex() == 0
&& bundleTrunkTvm.getCurrentIndex() == 0 ? Validity.VALID : Validity.INVALID;
}

/**
* Traverses down the given {@code tail} trunk until all transactions that belong to the same bundle (identified by
* the bundle hash) are found and loaded.
Expand Down
2 changes: 1 addition & 1 deletion src/main/java/com/iota/iri/network/NeighborRouterImpl.java
Original file line number Diff line number Diff line change
Expand Up @@ -508,7 +508,7 @@ private boolean finalizeHandshake(String identity, Neighbor neighbor, SocketChan
return false;
case FAILED:
// faulty handshaking
log.error("dropping connection to neighbor {} as handshaking was faulty", identity);
log.warn("dropping connection to neighbor {} as handshaking was faulty", identity);
closeNeighborConnection(channel, identity, selector);
return false;
default:
Expand Down
Loading

0 comments on commit 450b728

Please sign in to comment.