From 450b728155b415a62e206d29371b93497e38d70c Mon Sep 17 00:00:00 2001 From: Acha Bill <57879913+acha-bill@users.noreply.github.com> Date: Mon, 16 Mar 2020 13:06:45 +0100 Subject: [PATCH] Added bundle validity rules (#1786) * 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 --- .../java/com/iota/iri/BundleValidator.java | 61 ++++++++++++++++++- .../iota/iri/network/NeighborRouterImpl.java | 2 +- .../com/iota/iri/BundleValidatorTest.java | 52 ++++++++++++++++ 3 files changed, 111 insertions(+), 4 deletions(-) diff --git a/src/main/java/com/iota/iri/BundleValidator.java b/src/main/java/com/iota/iri/BundleValidator.java index 4242ada537..6158049f13 100644 --- a/src/main/java/com/iota/iri/BundleValidator.java +++ b/src/main/java/com/iota/iri/BundleValidator.java @@ -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 @@ -85,6 +96,8 @@ public enum Validity { *
  • Total bundle value is 0 (inputs and outputs are balanced)
  • *
  • Recalculate the bundle hash by absorbing and squeezing the transactions' essence
  • *
  • Validate the signature on input transactions
  • + *
  • The bundle must only approve tail transactions
  • + *
  • All transactions within the bundle approve via their branch the trunk transaction of the head transaction.
  • * *

    * As well as the following syntactic checks: @@ -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)) { @@ -379,6 +403,37 @@ public static boolean isInconsistent(Collection 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 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 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. diff --git a/src/main/java/com/iota/iri/network/NeighborRouterImpl.java b/src/main/java/com/iota/iri/network/NeighborRouterImpl.java index 2019516e29..c724c1640f 100644 --- a/src/main/java/com/iota/iri/network/NeighborRouterImpl.java +++ b/src/main/java/com/iota/iri/network/NeighborRouterImpl.java @@ -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: diff --git a/src/test/java/com/iota/iri/BundleValidatorTest.java b/src/test/java/com/iota/iri/BundleValidatorTest.java index a9cd40622c..f890d9b253 100644 --- a/src/test/java/com/iota/iri/BundleValidatorTest.java +++ b/src/test/java/com/iota/iri/BundleValidatorTest.java @@ -79,6 +79,58 @@ public void checkInconsistencyOfConsistentBundle() { assertFalse("should be false because bundle is consistent", BundleValidator.isInconsistent(transactions)); } + @Test + public void checkBundleTransactionsApproval() { + //tx0 and tx1 both approve via branch, the trunk of tx2 + String[] trytes = { + "999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999GNXKWQPHMFCEZZCKUCCD9PROQVPCTBVVAPHCLVOPYYQLQRMPGTQXBVZLKGGT9NXHUAASFIAVEOZTBSM9DA99999999999999999999999999RENGLE9BEAT9999999999999999FDKW9AD99999999999B99999999RJPQGE9AXNBBLPQ9IFJXFJTXJAIGDDXAWXGAVU9PJQNYFADJDIDBTJKSAEBBX9NWJGZVAVXYWXPCEFFH9DKZYSMJAQRLXZHCNPTJPJLOONNDZHGNTBIINGYKZQAAWF9LWQTHUQSAXMLQN9DKCQWHIJXNGLGQVA9999XIFVJWCABR9XQKOWCXJAZDZWMWWBVHROBOPISAWDIJTSFPVAUZNJUMNUCOFIBIAAVIOWDTCNIPRVA9999TANGLE9BEAT9999999999999999SVIDBWNOF999999999K99999999POWSRVIO9VMIJ99UGNETMNPNNNE", + "YU9WINMHSBIJ9HRBKDEHZYOCDGOZ9HZSSVXAYYOD9AMAFBCROMLSFDFIAQKEXAVFDLJYVABRSONSTTXLCQJTSDRFDEXZIORLRSQDZQODNCHAAFUPGBCEVYNRSJQGUZRAQIIEZPFQGWPQIBMDVNZGQAKCU9VLHGYSNDPHCMOCTRYQOYHFPRQSGHSDEF9MSHGXYGUTHSBSF9SOSJQFOZXMQGCUXAYWLBJHXOHTOM9ITZPISEXLAYAZBHTZDDCOIHKDBL9AAXZEDFHDYCPXLDGR9JTVXDXBC9DRDVREEEVGVPWVEZHJBYQYTGDEWQHVEDTAVLWW9WBXOIGDGUAAAVKFMPVKSYBVOIWPYGCMACEAAHGUIQVFLFMSCPKTYQWJDGMDNLMDIUUYI9SZOFQPLKKACESSWIXPFYZWDHETYUGEVASPHBGQPJPWVESSUUEVUYDYNQUQURSMCEPKIHYXNFHZSHIIDTMEZQ9IPSHTBDK9UHRSIIEJRILBCMVUMGAGBMHKEMUUKQDCYAVIAN9MBWJCAUSSJRSAUEUBGEFFCFSOBVGLXBAIDOH9NXWQUSIFUINEVZUWELLVIOSSQRVHMTDBCATBWFSDJJDLURAUKEQEIRICSCXAOJNPWHQKYVTRLCRKHLFHHHPYSMUEAPMQPMPS9CHCIYXEYRNIOOGRWKVHUGIWJZIGPWGZGBGYTVC9UVEJ9JBIYMDHYXLWIDXHZVFCCPLYXDPQPJGMKNZMMONGNXSNNPCGEGRJTMCPTJONGPAEDMSHMGAPGBDWVCSCTJAECSHTEGBMVCDZMQYZ9IHERWGCKAIMFOJRAEDRDSWJASV9XYS9CTOEETPQHRKJZ9FPWTVCGLEJQJXVVDTYZ9DNSHQAINKROQQIPTFGTABEELYPBQHGNNB9NCL9BVTG9MH99BPIRNNGC9MQQRH9YUDYSUJIDSZKCIGEKFSJ9PXUYKVPUZYFIREUAMUZE9EIMJK9YGAZXZBPRXIRDCEVDHWOCFIJTVRCRZRRJGFLILKVNMJAX9MUMTXCWTUTP9NXBZUMAYYY9DNVZTCROBCMMHVKSQRXMGROCMMCDENWQWBV9LEIJONWTQXOUQZOTGEJHJELYZOPICLDWPHVCMBFSYHPIJYZQDEGYITVPYNQMXPRTPKADLUKW9AEMSMGIWCUMOQMUDN9HZGYKTNVVNLOQAFVETEDJMJVKYCE9RE9AJP9RMYFKGDEC9GIGAFXEXIYXPFBOMRPULVJMYTQEPDMMIABDHJGRNNCKADZAUFV9WCWFYFHXLCED9E9SKKYHVKDTGNCHEKFJL9YJHTSRUVKEPHPCQSFNBXKOJNGBSEOZLVVGNUQTRACVGEKDSORUHVSDSQNUZASWXRADGAUDYDPODDEDNDDT9OAEARSBLPVSYAOEYYZJIZIZDENQOKMXATCTD9NEFVQWNCET9N9IXWCCWHYUBDTDJUZFXWMATRYSGJUQAFKAPIQIIXVFFEFNLGDPAIGKONUWLUTQTKZJYDEGPASTOMM9QTGOMYHFUKMNEVWPCMTLPDSOEEWDBRHZPZJIFMBUTY9QPRLPSVURIRMCWLH9YIZBOTJQMMF9ZP9VCCEGWVKSSQNANP9ZXVCAFGAVBXDJHUMKTKUBZRNKUGJTVUPDZMUK9KZI9EKY9DQDUNA9ZVPCROKYYPISSTDOJZJXMXZWSGZBEPKAUYPBPUTDVQKUYXWYTZXLYTCLLKLJUUJGFFCMZFKDTJET9KEDRMWZSAEFCSXLMRHRLG9EKLRZJ9NZQEONGFQSKSQMWRZXWVEGHCF9ZKGQITDLGFTZLCQMXVGVYIPKSUPPAOIKVWARJHAEJUZOOJFCFJTGQZWROSCEQSITQWZTQDFKECATBWSIRDFVWH9TXXUVEBRRKOTFSGBMGCMZDK9BJRVEUYOVNSLZNNSTWOB9CFNDJHJENDWSTIMMSWD9HSA9LDGTJDJFRGQCWOHYJNMFFLLDMVQEMCMNVQWMOGCEZUTK9MPULTDMKTIVFNVWXDNTRHNREHEDWIZCCRFVM9TXCTLBLYEKTRVVWHKZDOSYOBNLEKPNXMDZGLSVBBNBJIBZYBXZCENKVIXMNGUJUYFGFYFBKELSBZROQWKMESZTWDEEUCSXOWFSNJUGGJANMJFCBJV9GMDDJCAJHWKYQFJLFWZESTSIRBZQWYHGQDFUUWF9F9HXSBZRKBDLRWXSMKW99KPWJOQYPMHB9KWALSVLFNANYSMNWSJLUOCBKAWAJHNWMLPLXHVEPTKBPWLWHMDZ99999999999999999999999999999999999999999999999999999FDKW9AD99A99999999B99999999RJPQGE9AXNBBLPQ9IFJXFJTXJAIGDDXAWXGAVU9PJQNYFADJDIDBTJKSAEBBX9NWJGZVAVXYWXPCEFFH99XJLIVAZYJGPKEHANESX9DORLEIOIFL9WVQBBNUDRZDGJMVSRTSFKOJPIMEXPBCPGKUUEKRGAXOB99999XIFVJWCABR9XQKOWCXJAZDZWMWWBVHROBOPISAWDIJTSFPVAUZNJUMNUCOFIBIAAVIOWDTCNIPRVA9999999999999999999999999999999RSIDBWNOF999999999K99999999POWSRVIO9VMIJ99FKKNKGPNNNNP", + "COSNPEACSPESTKTUS9CSMOCWVUBLERQJQGLLA9AYRRXMOVOBULQZZZJPLNELEX9EVZDAFOHBB9FBAYOTDB9YGJAVTDWNPJVVGEPFJ9QBYLXAYZEETY9GMYQRIRAIPWMJUFMFRSQRCEIOWISMBJKGCIGIIYNMXAYLXZIBNKANT9DSQXPBUPWGUJTOMD9JKSNFZJJFBZYBWRWQIZFOZXQWNJTRZTUPHVEGTAOLMBEPXOB9TCEBNIWXQUHNQJZHAOWGVOOOTSCTEUEMXJUODZP9CDLCMEXAW9YJGVNREENETEYXOAKZVRJVUSCRUSRCNZUGUOLCNHQITWYPJVJGPVULASTONDZRDVCNGJSN9DMMUORCOIBTITSPBXSAVTOHSAXHMGH99APRTQIVCEI9NWYKDOZCCWBNZGGCUCISSMGJHJ9OVSFBZVFMBODKRKSLIDESGFDQITCYFARWYTLFKSPLNVQ9LTYFODCHBAJKCWVZNBLOJH9ABFGDFOXHDNHZILINMYMVZYWTFJJOLADPTZRPJEMGPFQNYTFDGOKMDTDSKPTHIDWLMRSSACZMTHUCWVZHCYSPJRATABZ9JHWEBGTTQORGFOYDWUIYFYGOGGTYGYYI9RPKPMCTYNYKHHNWQKJTDQDHTRUYQPMCDDLVUUHUBPWGPMNQYPKHDHGIUSXJGNUXIYGZRGVYPTTV9KXJDLGVVXRIWIGKZJVCQ9DUWAYNDRKYCGKZDEOKZQCXELSQXLGLAPBDIWRTKGSIRNAZ9XFEGMWOWLPUA9TSGYRDOU9GKY9JJDKCJKKGJCRARGSNECJ9SEVAGPPJMBTMGNWSLNSFBOEYMIQBKOVSCTDIWCOQTHBVTZOFNNIYKKJLAROKIRFFPCLSOWO9BVNNJSXEYLJASPUEFKCEI9SGWADNGS9MZAKFTCAYNRVKGDIGYDTPGJXWFAEFGG9BX9XCNBZGQULH9IPPIQ9VFVAXGELUMCTE9TOFOGCTFYBYEBFOKKAESIIHEWLYLQKWDHPYNELJKMZHDSDSK9ZWFP99FQFLUXGTSVDMGHIFZFUCYTYPVEFEDM9TOHCQVIBXARYWZEKTWEOVSBYZTJZRUFZJCLRBTOWPTKY99CYQTGPMAKFYALIWPEQLUB9RGANTKDDMSDSJOTNPFZCXKJUGTJWWPK9FAJGPJOEBRHL9ZU9XRBDJBVMFIZIZFGKETH9RJUSDIOWDZIXFOJLT9DSIAWSCEYBNOGOAZQPZKVZTBXGACCBVQGFNGXNQFTVPUGUOHNBKTUERLSTDXGRKZSATIRHDBSXARYATBHOLUHCQGPRMQGSJUAXUCWKDXAUGORHFVVVDZQEYYGSV9IUM9VTMHJCIKBQD9TQLLYTZHAKDHPFGYMRGJOEDJKQTBBNFCKDEPYTPWUJEOPRJWHAILMVW9AXS9HAT9GCGRXZEHWNDOVGKGPWFXFC9IKLVZJCTGZUJFRHGL9FZWZYP9TPOWGOUTQ9INYBVTD9N9OV9AM9GYRJ99MRWRWLOAKJXMDTFNS9NZQAYGVZRJ9WVSIDRRQLGKH9VPUVKFWZMSRVVLKXUGJAZESC9LEYDNNDWS9WTWNFPCR9YKPOMIJAVHCRCJVBDFWSTDN9BPJRDMGZFXWTY9GUX9WEPJQMXSECFPREXAJ9DU9OLMNQFTF99QYZOGDUTMBHMNMCNUQTU9FTNEUNBT9NQO9YADGY9C9LQR9DYVJZE9GMMYAOUSWUIVJ9EAR9EEFCO9SZTQ9JQHPIJGXIOQZHOSUSVMHBOLTYSEONVLRISNAN9KJHHFFISTYIHYVAMXLPNALDELETXVSWGUWOIVKNAKZKNNRVNJKE9WMNQBXFGXSYZQQSIODAKINA9CPBOGAYKJ9V9GS9HERXSVYPEILYXC9GURBREBCXRZJVXHUOPGYFLPIFBCOTMHFTAAUQUZVEKOWYFFGSCXDFDBTSGZRMPQR9EYSZYGQETCWFDRXVOXXCUBOQTBQGVLAONSTSLURFYSDPAVNCXNWVPQOUORMVSLYISQUQKXFYYMJSGHQP9VAAZABEAGJMCPIEBZQSYCPS9CNKFBDRDTDA9C9MVKGUISRX9ODVUJNPDWMZ9ESYXJ99ETDGSTJZMZYJEGRUWTORMCLNHLDQ9YIJWPMDYGGJQHMFPJ9VKINJUESTCBJQXFTCJFNUXPZONVKXJRAYGKIWHXSBZRKBDLRWXSMKW99KPWJOQYPMHB9KWALSVLFNANYSMNWSJLUOCBKAWAJHNWMLPLXHVEPTKBPWLWHMD999999999999999999999999999999999999999999999999999999FDKW9AD99B99999999B99999999RJPQGE9AXNBBLPQ9IFJXFJTXJAIGDDXAWXGAVU9PJQNYFADJDIDBTJKSAEBBX9NWJGZVAVXYWXPCEFFH9XIFVJWCABR9XQKOWCXJAZDZWMWWBVHROBOPISAWDIJTSFPVAUZNJUMNUCOFIBIAAVIOWDTCNIPRVA9999FTXZAEQIKGFJABOGCCQGOMKNASGWCQWMNIMRDTHKPJMTKDGMEQNZOAYARIYEWFZYJALRKFODOITTZ9999999999999999999999999999999LLHDBWNOF999999999K99999999POWSRVIO9VMIJ99UMGMTTTPNNNV", + }; + List transactions = persistAndMapTxs(trytes); + assertEquals("should be valid", BundleValidator.Validity.VALID, BundleValidator.validateBundleTransactionsApproval(transactions)); + } + + @Test + public void checkBundleTransactionsApprovalFailure(){ + //tx1 approves via branch, the branch of tx2 + String[] trytes = { + "999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999GNXKWQPHMFCEZZCKUCCD9PROQVPCTBVVAPHCLVOPYYQLQRMPGTQXBVZLKGGT9NXHUAASFIAVEOZTBSM9DA99999999999999999999999999RENGLE9BEAT9999999999999999FDKW9AD99999999999B99999999RJPQGE9AXNBBLPQ9IFJXFJTXJAIGDDXAWXGAVU9PJQNYFADJDIDBTJKSAEBBX9NWJGZVAVXYWXPCEFFH9DKZYSMJAQRLXZHCNPTJPJLOONNDZHGNTBIINGYKZQAAWF9LWQTHUQSAXMLQN9DKCQWHIJXNGLGQVA9999XIFVJWCABR9XQKOWCXJAZDZWMWWBVHROBOPISAWDIJTSFPVAUZNJUMNUCOFIBIAAVIOWDTCNIPRVA9999TANGLE9BEAT9999999999999999SVIDBWNOF999999999K99999999POWSRVIO9VMIJ99UGNETMNPNNNE", + "YU9WINMHSBIJ9HRBKDEHZYOCDGOZ9HZSSVXAYYOD9AMAFBCROMLSFDFIAQKEXAVFDLJYVABRSONSTTXLCQJTSDRFDEXZIORLRSQDZQODNCHAAFUPGBCEVYNRSJQGUZRAQIIEZPFQGWPQIBMDVNZGQAKCU9VLHGYSNDPHCMOCTRYQOYHFPRQSGHSDEF9MSHGXYGUTHSBSF9SOSJQFOZXMQGCUXAYWLBJHXOHTOM9ITZPISEXLAYAZBHTZDDCOIHKDBL9AAXZEDFHDYCPXLDGR9JTVXDXBC9DRDVREEEVGVPWVEZHJBYQYTGDEWQHVEDTAVLWW9WBXOIGDGUAAAVKFMPVKSYBVOIWPYGCMACEAAHGUIQVFLFMSCPKTYQWJDGMDNLMDIUUYI9SZOFQPLKKACESSWIXPFYZWDHETYUGEVASPHBGQPJPWVESSUUEVUYDYNQUQURSMCEPKIHYXNFHZSHIIDTMEZQ9IPSHTBDK9UHRSIIEJRILBCMVUMGAGBMHKEMUUKQDCYAVIAN9MBWJCAUSSJRSAUEUBGEFFCFSOBVGLXBAIDOH9NXWQUSIFUINEVZUWELLVIOSSQRVHMTDBCATBWFSDJJDLURAUKEQEIRICSCXAOJNPWHQKYVTRLCRKHLFHHHPYSMUEAPMQPMPS9CHCIYXEYRNIOOGRWKVHUGIWJZIGPWGZGBGYTVC9UVEJ9JBIYMDHYXLWIDXHZVFCCPLYXDPQPJGMKNZMMONGNXSNNPCGEGRJTMCPTJONGPAEDMSHMGAPGBDWVCSCTJAECSHTEGBMVCDZMQYZ9IHERWGCKAIMFOJRAEDRDSWJASV9XYS9CTOEETPQHRKJZ9FPWTVCGLEJQJXVVDTYZ9DNSHQAINKROQQIPTFGTABEELYPBQHGNNB9NCL9BVTG9MH99BPIRNNGC9MQQRH9YUDYSUJIDSZKCIGEKFSJ9PXUYKVPUZYFIREUAMUZE9EIMJK9YGAZXZBPRXIRDCEVDHWOCFIJTVRCRZRRJGFLILKVNMJAX9MUMTXCWTUTP9NXBZUMAYYY9DNVZTCROBCMMHVKSQRXMGROCMMCDENWQWBV9LEIJONWTQXOUQZOTGEJHJELYZOPICLDWPHVCMBFSYHPIJYZQDEGYITVPYNQMXPRTPKADLUKW9AEMSMGIWCUMOQMUDN9HZGYKTNVVNLOQAFVETEDJMJVKYCE9RE9AJP9RMYFKGDEC9GIGAFXEXIYXPFBOMRPULVJMYTQEPDMMIABDHJGRNNCKADZAUFV9WCWFYFHXLCED9E9SKKYHVKDTGNCHEKFJL9YJHTSRUVKEPHPCQSFNBXKOJNGBSEOZLVVGNUQTRACVGEKDSORUHVSDSQNUZASWXRADGAUDYDPODDEDNDDT9OAEARSBLPVSYAOEYYZJIZIZDENQOKMXATCTD9NEFVQWNCET9N9IXWCCWHYUBDTDJUZFXWMATRYSGJUQAFKAPIQIIXVFFEFNLGDPAIGKONUWLUTQTKZJYDEGPASTOMM9QTGOMYHFUKMNEVWPCMTLPDSOEEWDBRHZPZJIFMBUTY9QPRLPSVURIRMCWLH9YIZBOTJQMMF9ZP9VCCEGWVKSSQNANP9ZXVCAFGAVBXDJHUMKTKUBZRNKUGJTVUPDZMUK9KZI9EKY9DQDUNA9ZVPCROKYYPISSTDOJZJXMXZWSGZBEPKAUYPBPUTDVQKUYXWYTZXLYTCLLKLJUUJGFFCMZFKDTJET9KEDRMWZSAEFCSXLMRHRLG9EKLRZJ9NZQEONGFQSKSQMWRZXWVEGHCF9ZKGQITDLGFTZLCQMXVGVYIPKSUPPAOIKVWARJHAEJUZOOJFCFJTGQZWROSCEQSITQWZTQDFKECATBWSIRDFVWH9TXXUVEBRRKOTFSGBMGCMZDK9BJRVEUYOVNSLZNNSTWOB9CFNDJHJENDWSTIMMSWD9HSA9LDGTJDJFRGQCWOHYJNMFFLLDMVQEMCMNVQWMOGCEZUTK9MPULTDMKTIVFNVWXDNTRHNREHEDWIZCCRFVM9TXCTLBLYEKTRVVWHKZDOSYOBNLEKPNXMDZGLSVBBNBJIBZYBXZCENKVIXMNGUJUYFGFYFBKELSBZROQWKMESZTWDEEUCSXOWFSNJUGGJANMJFCBJV9GMDDJCAJHWKYQFJLFWZESTSIRBZQWYHGQDFUUWF9F9HXSBZRKBDLRWXSMKW99KPWJOQYPMHB9KWALSVLFNANYSMNWSJLUOCBKAWAJHNWMLPLXHVEPTKBPWLWHMDZ99999999999999999999999999999999999999999999999999999FDKW9AD99A99999999B99999999RJPQGE9AXNBBLPQ9IFJXFJTXJAIGDDXAWXGAVU9PJQNYFADJDIDBTJKSAEBBX9NWJGZVAVXYWXPCEFFH99XJLIVAZYJGPKEHANESX9DORLEIOIFL9WVQBBNUDRZDGJMVSRTSFKOJPIMEXPBCPGKUUEKRGAXOB99999FTXZAEQIKGFJABOGCCQGOMKNASGWCQWMNIMRDTHKPJMTKDGMEQNZOAYARIYEWFZYJALRKFODOITTZ9999999999999999999999999999999RSIDBWNOF999999999K99999999POWSRVIO9VMIJ99FKKNKGPNNNNP", + "COSNPEACSPESTKTUS9CSMOCWVUBLERQJQGLLA9AYRRXMOVOBULQZZZJPLNELEX9EVZDAFOHBB9FBAYOTDB9YGJAVTDWNPJVVGEPFJ9QBYLXAYZEETY9GMYQRIRAIPWMJUFMFRSQRCEIOWISMBJKGCIGIIYNMXAYLXZIBNKANT9DSQXPBUPWGUJTOMD9JKSNFZJJFBZYBWRWQIZFOZXQWNJTRZTUPHVEGTAOLMBEPXOB9TCEBNIWXQUHNQJZHAOWGVOOOTSCTEUEMXJUODZP9CDLCMEXAW9YJGVNREENETEYXOAKZVRJVUSCRUSRCNZUGUOLCNHQITWYPJVJGPVULASTONDZRDVCNGJSN9DMMUORCOIBTITSPBXSAVTOHSAXHMGH99APRTQIVCEI9NWYKDOZCCWBNZGGCUCISSMGJHJ9OVSFBZVFMBODKRKSLIDESGFDQITCYFARWYTLFKSPLNVQ9LTYFODCHBAJKCWVZNBLOJH9ABFGDFOXHDNHZILINMYMVZYWTFJJOLADPTZRPJEMGPFQNYTFDGOKMDTDSKPTHIDWLMRSSACZMTHUCWVZHCYSPJRATABZ9JHWEBGTTQORGFOYDWUIYFYGOGGTYGYYI9RPKPMCTYNYKHHNWQKJTDQDHTRUYQPMCDDLVUUHUBPWGPMNQYPKHDHGIUSXJGNUXIYGZRGVYPTTV9KXJDLGVVXRIWIGKZJVCQ9DUWAYNDRKYCGKZDEOKZQCXELSQXLGLAPBDIWRTKGSIRNAZ9XFEGMWOWLPUA9TSGYRDOU9GKY9JJDKCJKKGJCRARGSNECJ9SEVAGPPJMBTMGNWSLNSFBOEYMIQBKOVSCTDIWCOQTHBVTZOFNNIYKKJLAROKIRFFPCLSOWO9BVNNJSXEYLJASPUEFKCEI9SGWADNGS9MZAKFTCAYNRVKGDIGYDTPGJXWFAEFGG9BX9XCNBZGQULH9IPPIQ9VFVAXGELUMCTE9TOFOGCTFYBYEBFOKKAESIIHEWLYLQKWDHPYNELJKMZHDSDSK9ZWFP99FQFLUXGTSVDMGHIFZFUCYTYPVEFEDM9TOHCQVIBXARYWZEKTWEOVSBYZTJZRUFZJCLRBTOWPTKY99CYQTGPMAKFYALIWPEQLUB9RGANTKDDMSDSJOTNPFZCXKJUGTJWWPK9FAJGPJOEBRHL9ZU9XRBDJBVMFIZIZFGKETH9RJUSDIOWDZIXFOJLT9DSIAWSCEYBNOGOAZQPZKVZTBXGACCBVQGFNGXNQFTVPUGUOHNBKTUERLSTDXGRKZSATIRHDBSXARYATBHOLUHCQGPRMQGSJUAXUCWKDXAUGORHFVVVDZQEYYGSV9IUM9VTMHJCIKBQD9TQLLYTZHAKDHPFGYMRGJOEDJKQTBBNFCKDEPYTPWUJEOPRJWHAILMVW9AXS9HAT9GCGRXZEHWNDOVGKGPWFXFC9IKLVZJCTGZUJFRHGL9FZWZYP9TPOWGOUTQ9INYBVTD9N9OV9AM9GYRJ99MRWRWLOAKJXMDTFNS9NZQAYGVZRJ9WVSIDRRQLGKH9VPUVKFWZMSRVVLKXUGJAZESC9LEYDNNDWS9WTWNFPCR9YKPOMIJAVHCRCJVBDFWSTDN9BPJRDMGZFXWTY9GUX9WEPJQMXSECFPREXAJ9DU9OLMNQFTF99QYZOGDUTMBHMNMCNUQTU9FTNEUNBT9NQO9YADGY9C9LQR9DYVJZE9GMMYAOUSWUIVJ9EAR9EEFCO9SZTQ9JQHPIJGXIOQZHOSUSVMHBOLTYSEONVLRISNAN9KJHHFFISTYIHYVAMXLPNALDELETXVSWGUWOIVKNAKZKNNRVNJKE9WMNQBXFGXSYZQQSIODAKINA9CPBOGAYKJ9V9GS9HERXSVYPEILYXC9GURBREBCXRZJVXHUOPGYFLPIFBCOTMHFTAAUQUZVEKOWYFFGSCXDFDBTSGZRMPQR9EYSZYGQETCWFDRXVOXXCUBOQTBQGVLAONSTSLURFYSDPAVNCXNWVPQOUORMVSLYISQUQKXFYYMJSGHQP9VAAZABEAGJMCPIEBZQSYCPS9CNKFBDRDTDA9C9MVKGUISRX9ODVUJNPDWMZ9ESYXJ99ETDGSTJZMZYJEGRUWTORMCLNHLDQ9YIJWPMDYGGJQHMFPJ9VKINJUESTCBJQXFTCJFNUXPZONVKXJRAYGKIWHXSBZRKBDLRWXSMKW99KPWJOQYPMHB9KWALSVLFNANYSMNWSJLUOCBKAWAJHNWMLPLXHVEPTKBPWLWHMD999999999999999999999999999999999999999999999999999999FDKW9AD99B99999999B99999999RJPQGE9AXNBBLPQ9IFJXFJTXJAIGDDXAWXGAVU9PJQNYFADJDIDBTJKSAEBBX9NWJGZVAVXYWXPCEFFH9XIFVJWCABR9XQKOWCXJAZDZWMWWBVHROBOPISAWDIJTSFPVAUZNJUMNUCOFIBIAAVIOWDTCNIPRVA9999FTXZAEQIKGFJABOGCCQGOMKNASGWCQWMNIMRDTHKPJMTKDGMEQNZOAYARIYEWFZYJALRKFODOITTZ9999999999999999999999999999999LLHDBWNOF999999999K99999999POWSRVIO9VMIJ99UMGMTTTPNNNV", + }; + List transactions = persistAndMapTxs(trytes); + assertEquals("should be invalid", BundleValidator.Validity.INVALID, BundleValidator.validateBundleTransactionsApproval(transactions)); + } + + @Test + public void checkBundleTailApproval() throws Exception { + //tx2 approves via branch and trunk, tail txs + String[] trytes = { + "999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999GNXKWQPHMFCEZZCKUCCD9PROQVPCTBVVAPHCLVOPYYQLQRMPGTQXBVZLKGGT9NXHUAASFIAVEOZTBSM9DA99999999999999999999999999RENGLE9BEAT9999999999999999FDKW9AD99999999999B99999999RJPQGE9AXNBBLPQ9IFJXFJTXJAIGDDXAWXGAVU9PJQNYFADJDIDBTJKSAEBBX9NWJGZVAVXYWXPCEFFH9DKZYSMJAQRLXZHCNPTJPJLOONNDZHGNTBIINGYKZQAAWF9LWQTHUQSAXMLQN9DKCQWHIJXNGLGQVA9999XIFVJWCABR9XQKOWCXJAZDZWMWWBVHROBOPISAWDIJTSFPVAUZNJUMNUCOFIBIAAVIOWDTCNIPRVA9999TANGLE9BEAT9999999999999999SVIDBWNOF999999999K99999999POWSRVIO9VMIJ99UGNETMNPNNNE", + "YU9WINMHSBIJ9HRBKDEHZYOCDGOZ9HZSSVXAYYOD9AMAFBCROMLSFDFIAQKEXAVFDLJYVABRSONSTTXLCQJTSDRFDEXZIORLRSQDZQODNCHAAFUPGBCEVYNRSJQGUZRAQIIEZPFQGWPQIBMDVNZGQAKCU9VLHGYSNDPHCMOCTRYQOYHFPRQSGHSDEF9MSHGXYGUTHSBSF9SOSJQFOZXMQGCUXAYWLBJHXOHTOM9ITZPISEXLAYAZBHTZDDCOIHKDBL9AAXZEDFHDYCPXLDGR9JTVXDXBC9DRDVREEEVGVPWVEZHJBYQYTGDEWQHVEDTAVLWW9WBXOIGDGUAAAVKFMPVKSYBVOIWPYGCMACEAAHGUIQVFLFMSCPKTYQWJDGMDNLMDIUUYI9SZOFQPLKKACESSWIXPFYZWDHETYUGEVASPHBGQPJPWVESSUUEVUYDYNQUQURSMCEPKIHYXNFHZSHIIDTMEZQ9IPSHTBDK9UHRSIIEJRILBCMVUMGAGBMHKEMUUKQDCYAVIAN9MBWJCAUSSJRSAUEUBGEFFCFSOBVGLXBAIDOH9NXWQUSIFUINEVZUWELLVIOSSQRVHMTDBCATBWFSDJJDLURAUKEQEIRICSCXAOJNPWHQKYVTRLCRKHLFHHHPYSMUEAPMQPMPS9CHCIYXEYRNIOOGRWKVHUGIWJZIGPWGZGBGYTVC9UVEJ9JBIYMDHYXLWIDXHZVFCCPLYXDPQPJGMKNZMMONGNXSNNPCGEGRJTMCPTJONGPAEDMSHMGAPGBDWVCSCTJAECSHTEGBMVCDZMQYZ9IHERWGCKAIMFOJRAEDRDSWJASV9XYS9CTOEETPQHRKJZ9FPWTVCGLEJQJXVVDTYZ9DNSHQAINKROQQIPTFGTABEELYPBQHGNNB9NCL9BVTG9MH99BPIRNNGC9MQQRH9YUDYSUJIDSZKCIGEKFSJ9PXUYKVPUZYFIREUAMUZE9EIMJK9YGAZXZBPRXIRDCEVDHWOCFIJTVRCRZRRJGFLILKVNMJAX9MUMTXCWTUTP9NXBZUMAYYY9DNVZTCROBCMMHVKSQRXMGROCMMCDENWQWBV9LEIJONWTQXOUQZOTGEJHJELYZOPICLDWPHVCMBFSYHPIJYZQDEGYITVPYNQMXPRTPKADLUKW9AEMSMGIWCUMOQMUDN9HZGYKTNVVNLOQAFVETEDJMJVKYCE9RE9AJP9RMYFKGDEC9GIGAFXEXIYXPFBOMRPULVJMYTQEPDMMIABDHJGRNNCKADZAUFV9WCWFYFHXLCED9E9SKKYHVKDTGNCHEKFJL9YJHTSRUVKEPHPCQSFNBXKOJNGBSEOZLVVGNUQTRACVGEKDSORUHVSDSQNUZASWXRADGAUDYDPODDEDNDDT9OAEARSBLPVSYAOEYYZJIZIZDENQOKMXATCTD9NEFVQWNCET9N9IXWCCWHYUBDTDJUZFXWMATRYSGJUQAFKAPIQIIXVFFEFNLGDPAIGKONUWLUTQTKZJYDEGPASTOMM9QTGOMYHFUKMNEVWPCMTLPDSOEEWDBRHZPZJIFMBUTY9QPRLPSVURIRMCWLH9YIZBOTJQMMF9ZP9VCCEGWVKSSQNANP9ZXVCAFGAVBXDJHUMKTKUBZRNKUGJTVUPDZMUK9KZI9EKY9DQDUNA9ZVPCROKYYPISSTDOJZJXMXZWSGZBEPKAUYPBPUTDVQKUYXWYTZXLYTCLLKLJUUJGFFCMZFKDTJET9KEDRMWZSAEFCSXLMRHRLG9EKLRZJ9NZQEONGFQSKSQMWRZXWVEGHCF9ZKGQITDLGFTZLCQMXVGVYIPKSUPPAOIKVWARJHAEJUZOOJFCFJTGQZWROSCEQSITQWZTQDFKECATBWSIRDFVWH9TXXUVEBRRKOTFSGBMGCMZDK9BJRVEUYOVNSLZNNSTWOB9CFNDJHJENDWSTIMMSWD9HSA9LDGTJDJFRGQCWOHYJNMFFLLDMVQEMCMNVQWMOGCEZUTK9MPULTDMKTIVFNVWXDNTRHNREHEDWIZCCRFVM9TXCTLBLYEKTRVVWHKZDOSYOBNLEKPNXMDZGLSVBBNBJIBZYBXZCENKVIXMNGUJUYFGFYFBKELSBZROQWKMESZTWDEEUCSXOWFSNJUGGJANMJFCBJV9GMDDJCAJHWKYQFJLFWZESTSIRBZQWYHGQDFUUWF9F9HXSBZRKBDLRWXSMKW99KPWJOQYPMHB9KWALSVLFNANYSMNWSJLUOCBKAWAJHNWMLPLXHVEPTKBPWLWHMDZ99999999999999999999999999999999999999999999999999999FDKW9AD99A99999999B99999999RJPQGE9AXNBBLPQ9IFJXFJTXJAIGDDXAWXGAVU9PJQNYFADJDIDBTJKSAEBBX9NWJGZVAVXYWXPCEFFH99XJLIVAZYJGPKEHANESX9DORLEIOIFL9WVQBBNUDRZDGJMVSRTSFKOJPIMEXPBCPGKUUEKRGAXOB99999XIFVJWCABR9XQKOWCXJAZDZWMWWBVHROBOPISAWDIJTSFPVAUZNJUMNUCOFIBIAAVIOWDTCNIPRVA9999999999999999999999999999999RSIDBWNOF999999999K99999999POWSRVIO9VMIJ99FKKNKGPNNNNP", + "COSNPEACSPESTKTUS9CSMOCWVUBLERQJQGLLA9AYRRXMOVOBULQZZZJPLNELEX9EVZDAFOHBB9FBAYOTDB9YGJAVTDWNPJVVGEPFJ9QBYLXAYZEETY9GMYQRIRAIPWMJUFMFRSQRCEIOWISMBJKGCIGIIYNMXAYLXZIBNKANT9DSQXPBUPWGUJTOMD9JKSNFZJJFBZYBWRWQIZFOZXQWNJTRZTUPHVEGTAOLMBEPXOB9TCEBNIWXQUHNQJZHAOWGVOOOTSCTEUEMXJUODZP9CDLCMEXAW9YJGVNREENETEYXOAKZVRJVUSCRUSRCNZUGUOLCNHQITWYPJVJGPVULASTONDZRDVCNGJSN9DMMUORCOIBTITSPBXSAVTOHSAXHMGH99APRTQIVCEI9NWYKDOZCCWBNZGGCUCISSMGJHJ9OVSFBZVFMBODKRKSLIDESGFDQITCYFARWYTLFKSPLNVQ9LTYFODCHBAJKCWVZNBLOJH9ABFGDFOXHDNHZILINMYMVZYWTFJJOLADPTZRPJEMGPFQNYTFDGOKMDTDSKPTHIDWLMRSSACZMTHUCWVZHCYSPJRATABZ9JHWEBGTTQORGFOYDWUIYFYGOGGTYGYYI9RPKPMCTYNYKHHNWQKJTDQDHTRUYQPMCDDLVUUHUBPWGPMNQYPKHDHGIUSXJGNUXIYGZRGVYPTTV9KXJDLGVVXRIWIGKZJVCQ9DUWAYNDRKYCGKZDEOKZQCXELSQXLGLAPBDIWRTKGSIRNAZ9XFEGMWOWLPUA9TSGYRDOU9GKY9JJDKCJKKGJCRARGSNECJ9SEVAGPPJMBTMGNWSLNSFBOEYMIQBKOVSCTDIWCOQTHBVTZOFNNIYKKJLAROKIRFFPCLSOWO9BVNNJSXEYLJASPUEFKCEI9SGWADNGS9MZAKFTCAYNRVKGDIGYDTPGJXWFAEFGG9BX9XCNBZGQULH9IPPIQ9VFVAXGELUMCTE9TOFOGCTFYBYEBFOKKAESIIHEWLYLQKWDHPYNELJKMZHDSDSK9ZWFP99FQFLUXGTSVDMGHIFZFUCYTYPVEFEDM9TOHCQVIBXARYWZEKTWEOVSBYZTJZRUFZJCLRBTOWPTKY99CYQTGPMAKFYALIWPEQLUB9RGANTKDDMSDSJOTNPFZCXKJUGTJWWPK9FAJGPJOEBRHL9ZU9XRBDJBVMFIZIZFGKETH9RJUSDIOWDZIXFOJLT9DSIAWSCEYBNOGOAZQPZKVZTBXGACCBVQGFNGXNQFTVPUGUOHNBKTUERLSTDXGRKZSATIRHDBSXARYATBHOLUHCQGPRMQGSJUAXUCWKDXAUGORHFVVVDZQEYYGSV9IUM9VTMHJCIKBQD9TQLLYTZHAKDHPFGYMRGJOEDJKQTBBNFCKDEPYTPWUJEOPRJWHAILMVW9AXS9HAT9GCGRXZEHWNDOVGKGPWFXFC9IKLVZJCTGZUJFRHGL9FZWZYP9TPOWGOUTQ9INYBVTD9N9OV9AM9GYRJ99MRWRWLOAKJXMDTFNS9NZQAYGVZRJ9WVSIDRRQLGKH9VPUVKFWZMSRVVLKXUGJAZESC9LEYDNNDWS9WTWNFPCR9YKPOMIJAVHCRCJVBDFWSTDN9BPJRDMGZFXWTY9GUX9WEPJQMXSECFPREXAJ9DU9OLMNQFTF99QYZOGDUTMBHMNMCNUQTU9FTNEUNBT9NQO9YADGY9C9LQR9DYVJZE9GMMYAOUSWUIVJ9EAR9EEFCO9SZTQ9JQHPIJGXIOQZHOSUSVMHBOLTYSEONVLRISNAN9KJHHFFISTYIHYVAMXLPNALDELETXVSWGUWOIVKNAKZKNNRVNJKE9WMNQBXFGXSYZQQSIODAKINA9CPBOGAYKJ9V9GS9HERXSVYPEILYXC9GURBREBCXRZJVXHUOPGYFLPIFBCOTMHFTAAUQUZVEKOWYFFGSCXDFDBTSGZRMPQR9EYSZYGQETCWFDRXVOXXCUBOQTBQGVLAONSTSLURFYSDPAVNCXNWVPQOUORMVSLYISQUQKXFYYMJSGHQP9VAAZABEAGJMCPIEBZQSYCPS9CNKFBDRDTDA9C9MVKGUISRX9ODVUJNPDWMZ9ESYXJ99ETDGSTJZMZYJEGRUWTORMCLNHLDQ9YIJWPMDYGGJQHMFPJ9VKINJUESTCBJQXFTCJFNUXPZONVKXJRAYGKIWHXSBZRKBDLRWXSMKW99KPWJOQYPMHB9KWALSVLFNANYSMNWSJLUOCBKAWAJHNWMLPLXHVEPTKBPWLWHMD999999999999999999999999999999999999999999999999999999FDKW9AD99B99999999B99999999RJPQGE9AXNBBLPQ9IFJXFJTXJAIGDDXAWXGAVU9PJQNYFADJDIDBTJKSAEBBX9NWJGZVAVXYWXPCEFFH9XIFVJWCABR9XQKOWCXJAZDZWMWWBVHROBOPISAWDIJTSFPVAUZNJUMNUCOFIBIAAVIOWDTCNIPRVA9999FTXZAEQIKGFJABOGCCQGOMKNASGWCQWMNIMRDTHKPJMTKDGMEQNZOAYARIYEWFZYJALRKFODOITTZ9999999999999999999999999999999LLHDBWNOF999999999K99999999POWSRVIO9VMIJ99UMGMTTTPNNNV", + }; + List transactions = persistAndMapTxs(trytes); + assertEquals("should be valid because bundle approves tails", BundleValidator.Validity.VALID, BundleValidator.validateBundleTailApproval(tangle, transactions)); + } + + @Test + public void checkBundleNonTailApproval() throws Exception { + //tx with currentIndex = 1 + String[] nonTailTrytes = {"YU9WINMHSBIJ9HRBKDEHZYOCDGOZ9HZSSVXAYYOD9AMAFBCROMLSFDFIAQKEXAVFDLJYVABRSONSTTXLCQJTSDRFDEXZIORLRSQDZQODNCHAAFUPGBCEVYNRSJQGUZRAQIIEZPFQGWPQIBMDVNZGQAKCU9VLHGYSNDPHCMOCTRYQOYHFPRQSGHSDEF9MSHGXYGUTHSBSF9SOSJQFOZXMQGCUXAYWLBJHXOHTOM9ITZPISEXLAYAZBHTZDDCOIHKDBL9AAXZEDFHDYCPXLDGR9JTVXDXBC9DRDVREEEVGVPWVEZHJBYQYTGDEWQHVEDTAVLWW9WBXOIGDGUAAAVKFMPVKSYBVOIWPYGCMACEAAHGUIQVFLFMSCPKTYQWJDGMDNLMDIUUYI9SZOFQPLKKACESSWIXPFYZWDHETYUGEVASPHBGQPJPWVESSUUEVUYDYNQUQURSMCEPKIHYXNFHZSHIIDTMEZQ9IPSHTBDK9UHRSIIEJRILBCMVUMGAGBMHKEMUUKQDCYAVIAN9MBWJCAUSSJRSAUEUBGEFFCFSOBVGLXBAIDOH9NXWQUSIFUINEVZUWELLVIOSSQRVHMTDBCATBWFSDJJDLURAUKEQEIRICSCXAOJNPWHQKYVTRLCRKHLFHHHPYSMUEAPMQPMPS9CHCIYXEYRNIOOGRWKVHUGIWJZIGPWGZGBGYTVC9UVEJ9JBIYMDHYXLWIDXHZVFCCPLYXDPQPJGMKNZMMONGNXSNNPCGEGRJTMCPTJONGPAEDMSHMGAPGBDWVCSCTJAECSHTEGBMVCDZMQYZ9IHERWGCKAIMFOJRAEDRDSWJASV9XYS9CTOEETPQHRKJZ9FPWTVCGLEJQJXVVDTYZ9DNSHQAINKROQQIPTFGTABEELYPBQHGNNB9NCL9BVTG9MH99BPIRNNGC9MQQRH9YUDYSUJIDSZKCIGEKFSJ9PXUYKVPUZYFIREUAMUZE9EIMJK9YGAZXZBPRXIRDCEVDHWOCFIJTVRCRZRRJGFLILKVNMJAX9MUMTXCWTUTP9NXBZUMAYYY9DNVZTCROBCMMHVKSQRXMGROCMMCDENWQWBV9LEIJONWTQXOUQZOTGEJHJELYZOPICLDWPHVCMBFSYHPIJYZQDEGYITVPYNQMXPRTPKADLUKW9AEMSMGIWCUMOQMUDN9HZGYKTNVVNLOQAFVETEDJMJVKYCE9RE9AJP9RMYFKGDEC9GIGAFXEXIYXPFBOMRPULVJMYTQEPDMMIABDHJGRNNCKADZAUFV9WCWFYFHXLCED9E9SKKYHVKDTGNCHEKFJL9YJHTSRUVKEPHPCQSFNBXKOJNGBSEOZLVVGNUQTRACVGEKDSORUHVSDSQNUZASWXRADGAUDYDPODDEDNDDT9OAEARSBLPVSYAOEYYZJIZIZDENQOKMXATCTD9NEFVQWNCET9N9IXWCCWHYUBDTDJUZFXWMATRYSGJUQAFKAPIQIIXVFFEFNLGDPAIGKONUWLUTQTKZJYDEGPASTOMM9QTGOMYHFUKMNEVWPCMTLPDSOEEWDBRHZPZJIFMBUTY9QPRLPSVURIRMCWLH9YIZBOTJQMMF9ZP9VCCEGWVKSSQNANP9ZXVCAFGAVBXDJHUMKTKUBZRNKUGJTVUPDZMUK9KZI9EKY9DQDUNA9ZVPCROKYYPISSTDOJZJXMXZWSGZBEPKAUYPBPUTDVQKUYXWYTZXLYTCLLKLJUUJGFFCMZFKDTJET9KEDRMWZSAEFCSXLMRHRLG9EKLRZJ9NZQEONGFQSKSQMWRZXWVEGHCF9ZKGQITDLGFTZLCQMXVGVYIPKSUPPAOIKVWARJHAEJUZOOJFCFJTGQZWROSCEQSITQWZTQDFKECATBWSIRDFVWH9TXXUVEBRRKOTFSGBMGCMZDK9BJRVEUYOVNSLZNNSTWOB9CFNDJHJENDWSTIMMSWD9HSA9LDGTJDJFRGQCWOHYJNMFFLLDMVQEMCMNVQWMOGCEZUTK9MPULTDMKTIVFNVWXDNTRHNREHEDWIZCCRFVM9TXCTLBLYEKTRVVWHKZDOSYOBNLEKPNXMDZGLSVBBNBJIBZYBXZCENKVIXMNGUJUYFGFYFBKELSBZROQWKMESZTWDEEUCSXOWFSNJUGGJANMJFCBJV9GMDDJCAJHWKYQFJLFWZESTSIRBZQWYHGQDFUUWF9F9HXSBZRKBDLRWXSMKW99KPWJOQYPMHB9KWALSVLFNANYSMNWSJLUOCBKAWAJHNWMLPLXHVEPTKBPWLWHMDZ99999999999999999999999999999999999999999999999999999FDKW9AD99A99999999B99999999RJPQGE9AXNBBLPQ9IFJXFJTXJAIGDDXAWXGAVU9PJQNYFADJDIDBTJKSAEBBX9NWJGZVAVXYWXPCEFFH99XJLIVAZYJGPKEHANESX9DORLEIOIFL9WVQBBNUDRZDGJMVSRTSFKOJPIMEXPBCPGKUUEKRGAXOB99999XIFVJWCABR9XQKOWCXJAZDZWMWWBVHROBOPISAWDIJTSFPVAUZNJUMNUCOFIBIAAVIOWDTCNIPRVA9999999999999999999999999999999RSIDBWNOF999999999K99999999POWSRVIO9VMIJ99FKKNKGPNNNNP"}; + + //approves via head branch, non-tail tx + String[] trytes = { + "999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999GNXKWQPHMFCEZZCKUCCD9PROQVPCTBVVAPHCLVOPYYQLQRMPGTQXBVZLKGGT9NXHUAASFIAVEOZTBSM9DA99999999999999999999999999RENGLE9BEAT9999999999999999FDKW9AD99999999999B99999999ABCDGE9AXNBBLPQ9IFJXFJTXJAIGDDXAWXGAVU9PJQNYFADJDIDBTJKSAEBBX9NWJGZVAVXYWXPCEFFH9DKZYSMJAQRLXZHCNPTJPJLOONNDZHGNTBIINGYKZQAAWF9LWQTHUQSAXMLQN9DKCQWHIJXNGLGQVA9999XIFVJWCABR9XQKOWCXJAZDZWMWWBVHROBOPISAWDIJTSFPVAUZNJUMNUCOFIBIAAVIOWDTCNIPRVA9999TANGLE9BEAT9999999999999999SVIDBWNOF999999999K99999999POWSRVIO9VMIJ99UGNETMNPNNNE", + "YU9WINMHSBIJ9HRBKDEHZYOCDGOZ9HZSSVXAYYOD9AMAFBCROMLSFDFIAQKEXAVFDLJYVABRSONSTTXLCQJTSDRFDEXZIORLRSQDZQODNCHAAFUPGBCEVYNRSJQGUZRAQIIEZPFQGWPQIBMDVNZGQAKCU9VLHGYSNDPHCMOCTRYQOYHFPRQSGHSDEF9MSHGXYGUTHSBSF9SOSJQFOZXMQGCUXAYWLBJHXOHTOM9ITZPISEXLAYAZBHTZDDCOIHKDBL9AAXZEDFHDYCPXLDGR9JTVXDXBC9DRDVREEEVGVPWVEZHJBYQYTGDEWQHVEDTAVLWW9WBXOIGDGUAAAVKFMPVKSYBVOIWPYGCMACEAAHGUIQVFLFMSCPKTYQWJDGMDNLMDIUUYI9SZOFQPLKKACESSWIXPFYZWDHETYUGEVASPHBGQPJPWVESSUUEVUYDYNQUQURSMCEPKIHYXNFHZSHIIDTMEZQ9IPSHTBDK9UHRSIIEJRILBCMVUMGAGBMHKEMUUKQDCYAVIAN9MBWJCAUSSJRSAUEUBGEFFCFSOBVGLXBAIDOH9NXWQUSIFUINEVZUWELLVIOSSQRVHMTDBCATBWFSDJJDLURAUKEQEIRICSCXAOJNPWHQKYVTRLCRKHLFHHHPYSMUEAPMQPMPS9CHCIYXEYRNIOOGRWKVHUGIWJZIGPWGZGBGYTVC9UVEJ9JBIYMDHYXLWIDXHZVFCCPLYXDPQPJGMKNZMMONGNXSNNPCGEGRJTMCPTJONGPAEDMSHMGAPGBDWVCSCTJAECSHTEGBMVCDZMQYZ9IHERWGCKAIMFOJRAEDRDSWJASV9XYS9CTOEETPQHRKJZ9FPWTVCGLEJQJXVVDTYZ9DNSHQAINKROQQIPTFGTABEELYPBQHGNNB9NCL9BVTG9MH99BPIRNNGC9MQQRH9YUDYSUJIDSZKCIGEKFSJ9PXUYKVPUZYFIREUAMUZE9EIMJK9YGAZXZBPRXIRDCEVDHWOCFIJTVRCRZRRJGFLILKVNMJAX9MUMTXCWTUTP9NXBZUMAYYY9DNVZTCROBCMMHVKSQRXMGROCMMCDENWQWBV9LEIJONWTQXOUQZOTGEJHJELYZOPICLDWPHVCMBFSYHPIJYZQDEGYITVPYNQMXPRTPKADLUKW9AEMSMGIWCUMOQMUDN9HZGYKTNVVNLOQAFVETEDJMJVKYCE9RE9AJP9RMYFKGDEC9GIGAFXEXIYXPFBOMRPULVJMYTQEPDMMIABDHJGRNNCKADZAUFV9WCWFYFHXLCED9E9SKKYHVKDTGNCHEKFJL9YJHTSRUVKEPHPCQSFNBXKOJNGBSEOZLVVGNUQTRACVGEKDSORUHVSDSQNUZASWXRADGAUDYDPODDEDNDDT9OAEARSBLPVSYAOEYYZJIZIZDENQOKMXATCTD9NEFVQWNCET9N9IXWCCWHYUBDTDJUZFXWMATRYSGJUQAFKAPIQIIXVFFEFNLGDPAIGKONUWLUTQTKZJYDEGPASTOMM9QTGOMYHFUKMNEVWPCMTLPDSOEEWDBRHZPZJIFMBUTY9QPRLPSVURIRMCWLH9YIZBOTJQMMF9ZP9VCCEGWVKSSQNANP9ZXVCAFGAVBXDJHUMKTKUBZRNKUGJTVUPDZMUK9KZI9EKY9DQDUNA9ZVPCROKYYPISSTDOJZJXMXZWSGZBEPKAUYPBPUTDVQKUYXWYTZXLYTCLLKLJUUJGFFCMZFKDTJET9KEDRMWZSAEFCSXLMRHRLG9EKLRZJ9NZQEONGFQSKSQMWRZXWVEGHCF9ZKGQITDLGFTZLCQMXVGVYIPKSUPPAOIKVWARJHAEJUZOOJFCFJTGQZWROSCEQSITQWZTQDFKECATBWSIRDFVWH9TXXUVEBRRKOTFSGBMGCMZDK9BJRVEUYOVNSLZNNSTWOB9CFNDJHJENDWSTIMMSWD9HSA9LDGTJDJFRGQCWOHYJNMFFLLDMVQEMCMNVQWMOGCEZUTK9MPULTDMKTIVFNVWXDNTRHNREHEDWIZCCRFVM9TXCTLBLYEKTRVVWHKZDOSYOBNLEKPNXMDZGLSVBBNBJIBZYBXZCENKVIXMNGUJUYFGFYFBKELSBZROQWKMESZTWDEEUCSXOWFSNJUGGJANMJFCBJV9GMDDJCAJHWKYQFJLFWZESTSIRBZQWYHGQDFUUWF9F9HXSBZRKBDLRWXSMKW99KPWJOQYPMHB9KWALSVLFNANYSMNWSJLUOCBKAWAJHNWMLPLXHVEPTKBPWLWHMDZ99999999999999999999999999999999999999999999999999999FDKW9AD99A99999999B99999999ABCDGE9AXNBBLPQ9IFJXFJTXJAIGDDXAWXGAVU9PJQNYFADJDIDBTJKSAEBBX9NWJGZVAVXYWXPCEFFH99XJLIVAZYJGPKEHANESX9DORLEIOIFL9WVQBBNUDRZDGJMVSRTSFKOJPIMEXPBCPGKUUEKRGAXOB99999XIFVJWCABR9XQKOWCXJAZDZWMWWBVHROBOPISAWDIJTSFPVAUZNJUMNUCOFIBIAAVIOWDTCNIPRVA9999999999999999999999999999999RSIDBWNOF999999999K99999999POWSRVIO9VMIJ99FKKNKGPNNNNP", + "COSNPEACSPESTKTUS9CSMOCWVUBLERQJQGLLA9AYRRXMOVOBULQZZZJPLNELEX9EVZDAFOHBB9FBAYOTDB9YGJAVTDWNPJVVGEPFJ9QBYLXAYZEETY9GMYQRIRAIPWMJUFMFRSQRCEIOWISMBJKGCIGIIYNMXAYLXZIBNKANT9DSQXPBUPWGUJTOMD9JKSNFZJJFBZYBWRWQIZFOZXQWNJTRZTUPHVEGTAOLMBEPXOB9TCEBNIWXQUHNQJZHAOWGVOOOTSCTEUEMXJUODZP9CDLCMEXAW9YJGVNREENETEYXOAKZVRJVUSCRUSRCNZUGUOLCNHQITWYPJVJGPVULASTONDZRDVCNGJSN9DMMUORCOIBTITSPBXSAVTOHSAXHMGH99APRTQIVCEI9NWYKDOZCCWBNZGGCUCISSMGJHJ9OVSFBZVFMBODKRKSLIDESGFDQITCYFARWYTLFKSPLNVQ9LTYFODCHBAJKCWVZNBLOJH9ABFGDFOXHDNHZILINMYMVZYWTFJJOLADPTZRPJEMGPFQNYTFDGOKMDTDSKPTHIDWLMRSSACZMTHUCWVZHCYSPJRATABZ9JHWEBGTTQORGFOYDWUIYFYGOGGTYGYYI9RPKPMCTYNYKHHNWQKJTDQDHTRUYQPMCDDLVUUHUBPWGPMNQYPKHDHGIUSXJGNUXIYGZRGVYPTTV9KXJDLGVVXRIWIGKZJVCQ9DUWAYNDRKYCGKZDEOKZQCXELSQXLGLAPBDIWRTKGSIRNAZ9XFEGMWOWLPUA9TSGYRDOU9GKY9JJDKCJKKGJCRARGSNECJ9SEVAGPPJMBTMGNWSLNSFBOEYMIQBKOVSCTDIWCOQTHBVTZOFNNIYKKJLAROKIRFFPCLSOWO9BVNNJSXEYLJASPUEFKCEI9SGWADNGS9MZAKFTCAYNRVKGDIGYDTPGJXWFAEFGG9BX9XCNBZGQULH9IPPIQ9VFVAXGELUMCTE9TOFOGCTFYBYEBFOKKAESIIHEWLYLQKWDHPYNELJKMZHDSDSK9ZWFP99FQFLUXGTSVDMGHIFZFUCYTYPVEFEDM9TOHCQVIBXARYWZEKTWEOVSBYZTJZRUFZJCLRBTOWPTKY99CYQTGPMAKFYALIWPEQLUB9RGANTKDDMSDSJOTNPFZCXKJUGTJWWPK9FAJGPJOEBRHL9ZU9XRBDJBVMFIZIZFGKETH9RJUSDIOWDZIXFOJLT9DSIAWSCEYBNOGOAZQPZKVZTBXGACCBVQGFNGXNQFTVPUGUOHNBKTUERLSTDXGRKZSATIRHDBSXARYATBHOLUHCQGPRMQGSJUAXUCWKDXAUGORHFVVVDZQEYYGSV9IUM9VTMHJCIKBQD9TQLLYTZHAKDHPFGYMRGJOEDJKQTBBNFCKDEPYTPWUJEOPRJWHAILMVW9AXS9HAT9GCGRXZEHWNDOVGKGPWFXFC9IKLVZJCTGZUJFRHGL9FZWZYP9TPOWGOUTQ9INYBVTD9N9OV9AM9GYRJ99MRWRWLOAKJXMDTFNS9NZQAYGVZRJ9WVSIDRRQLGKH9VPUVKFWZMSRVVLKXUGJAZESC9LEYDNNDWS9WTWNFPCR9YKPOMIJAVHCRCJVBDFWSTDN9BPJRDMGZFXWTY9GUX9WEPJQMXSECFPREXAJ9DU9OLMNQFTF99QYZOGDUTMBHMNMCNUQTU9FTNEUNBT9NQO9YADGY9C9LQR9DYVJZE9GMMYAOUSWUIVJ9EAR9EEFCO9SZTQ9JQHPIJGXIOQZHOSUSVMHBOLTYSEONVLRISNAN9KJHHFFISTYIHYVAMXLPNALDELETXVSWGUWOIVKNAKZKNNRVNJKE9WMNQBXFGXSYZQQSIODAKINA9CPBOGAYKJ9V9GS9HERXSVYPEILYXC9GURBREBCXRZJVXHUOPGYFLPIFBCOTMHFTAAUQUZVEKOWYFFGSCXDFDBTSGZRMPQR9EYSZYGQETCWFDRXVOXXCUBOQTBQGVLAONSTSLURFYSDPAVNCXNWVPQOUORMVSLYISQUQKXFYYMJSGHQP9VAAZABEAGJMCPIEBZQSYCPS9CNKFBDRDTDA9C9MVKGUISRX9ODVUJNPDWMZ9ESYXJ99ETDGSTJZMZYJEGRUWTORMCLNHLDQ9YIJWPMDYGGJQHMFPJ9VKINJUESTCBJQXFTCJFNUXPZONVKXJRAYGKIWHXSBZRKBDLRWXSMKW99KPWJOQYPMHB9KWALSVLFNANYSMNWSJLUOCBKAWAJHNWMLPLXHVEPTKBPWLWHMD999999999999999999999999999999999999999999999999999999FDKW9AD99B99999999B99999999ABCDGE9AXNBBLPQ9IFJXFJTXJAIGDDXAWXGAVU9PJQNYFADJDIDBTJKSAEBBX9NWJGZVAVXYWXPCEFFH9XIFVJWCABR9XQKOWCXJAZDZWMWWBVHROBOPISAWDIJTSFPVAUZNJUMNUCOFIBIAAVIOWDTCNIPRVA9999DKZYSMJAQRLXZHCNPTJPJLOONNDZHGNTBIINGYKZQAAWF9LWQTHUQSAXMLQN9DKCQWHIJXNGLGQVA9999999999999999999999999999999LLHDBWNOF999999999K99999999POWSRVIO9VMIJ99UMGMTTTPNNNV", + }; + persistAndMapTxs(nonTailTrytes); + List transactions = persistAndMapTxs(trytes); + assertEquals("should be invalid because bundle approves non-tails", BundleValidator.Validity.INVALID, BundleValidator.validateBundleTailApproval(tangle, transactions)); + } + @Test public void validateValidBundle() throws Exception { String[] trytes = {