예제 #1
0
        public void TestGenerateTrytesAndMultiSqueeze()
        {
            var path                 = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);
            var isNetStandard        = path.Contains("Standard");
            var netStandardExtension = isNetStandard ? "../" : "";


            // CSV from Python lib. Thanks alot!
            using (var reader = new StreamReader(@"../" + netStandardExtension + "../Cryptography/generate_trytes_and_multi_squeeze.csv"))
            {
                var i = 0;
                while (!reader.EndOfStream)
                {
                    var line = reader.ReadLine();
                    if (line == null || i == 0)
                    {
                        i++;
                        continue;
                    }

                    var values = line.Split(',');

                    var trytes  = values[0];
                    var hashes1 = values[1];
                    var hashes2 = values[2];
                    var hashes3 = values[3];

                    var trits = Converter.TrytesToTrits(trytes);

                    var kerl = new Kerl();
                    kerl.Absorb(trits);

                    var tritsOut = new int[Constants.TritHashLength];
                    kerl.Squeeze(tritsOut);
                    var trytesOut = Converter.TritsToTrytes(tritsOut);

                    Assert.AreEqual(hashes1, trytesOut);

                    tritsOut = new int[Constants.TritHashLength];
                    kerl.Squeeze(tritsOut);
                    trytesOut = Converter.TritsToTrytes(tritsOut);

                    Assert.AreEqual(hashes2, trytesOut);

                    tritsOut = new int[Constants.TritHashLength];
                    kerl.Squeeze(tritsOut);
                    trytesOut = Converter.TritsToTrytes(tritsOut);

                    Assert.AreEqual(hashes3, trytesOut);
                    i++;
                }
            }
        }
예제 #2
0
        public void TestGenerateTrytesAndMultiSqueeze()
        {
            // CSV from Python lib. Thanks alot!
            using (var reader = new StreamReader(@"../../Tests/Cryptography/generate_trytes_and_multi_squeeze.csv"))
            {
                var i = 0;
                while (!reader.EndOfStream)
                {
                    var line = reader.ReadLine();
                    if (line == null || i == 0)
                    {
                        i++;
                        continue;
                    }

                    var values = line.Split(',');

                    var trytes  = values[0];
                    var hashes1 = values[1];
                    var hashes2 = values[2];
                    var hashes3 = values[3];

                    var trits = Converter.TrytesToTrits(trytes);

                    var kerl = new Kerl();
                    kerl.Absorb(trits);

                    var tritsOut = new int[Kerl.HashLength];
                    kerl.Squeeze(tritsOut);
                    var trytesOut = Converter.TritsToTrytes(tritsOut);

                    Assert.AreEqual(hashes1, trytesOut);

                    tritsOut = new int[Kerl.HashLength];
                    kerl.Squeeze(tritsOut);
                    trytesOut = Converter.TritsToTrytes(tritsOut);

                    Assert.AreEqual(hashes2, trytesOut);

                    tritsOut = new int[Kerl.HashLength];
                    kerl.Squeeze(tritsOut);
                    trytesOut = Converter.TritsToTrytes(tritsOut);

                    Assert.AreEqual(hashes3, trytesOut);
                    i++;
                }
            }
        }
예제 #3
0
        /// <summary>
        /// </summary>
        /// <param name="normalizedBundleFragment"></param>
        /// <param name="signatureFragment"></param>
        /// <returns></returns>
        public int[] Digest(int[] normalizedBundleFragment, int[] signatureFragment)
        {
            _curl.Reset();
            var buffer = new int[243];

            for (var i = 0; i < 27; i++)
            {
                buffer = ArrayUtils.SubArray(signatureFragment, i * 243, (i + 1) * 243);

                var jCurl = new Kerl();

                for (var j = normalizedBundleFragment[i] + 13; j-- > 0;)
                {
                    jCurl.Reset();
                    jCurl.Absorb(buffer);
                    jCurl.Squeeze(buffer);
                }

                _curl.Absorb(buffer);
            }

            _curl.Squeeze(buffer);

            return(buffer);
        }
        bool ValidBundle_SingleItem(string transactionTrytes)
        {
            var tran         = new TransactionItem(transactionTrytes);
            var bundleHash   = tran.Bundle;
            var bundleTrytes = tran.GetBundleTrytes();
            var curl         = new Kerl();

            String trxTrytes = transactionTrytes.Substring(2187, 162);

            Assert.AreEqual(bundleTrytes, trxTrytes);

            // Absorb bundle hash + value + timestamp + lastIndex + currentIndex trytes.
            curl.Absorb(Utils.Converter.ToTrits(trxTrytes));

            int[] bundleFromTrxs = new int[243];
            curl.Squeeze(bundleFromTrxs);
            String bundleFromTxString = Utils.Converter.ToTrytes(bundleFromTrxs);

            // Check if bundle hash is the same as returned by tx object
            if (!bundleFromTxString.Equals(bundleHash))
            {
                throw new ArgumentException($"INVALID_BUNDLE_HASH_ERROR: Expected: {bundleFromTxString} but your bundle is {bundleHash}");
            }

            // Last tx in the bundle should have currentIndex === lastIndex
            //bundle.setLength(bundle.getTransactions().size());
            return(tran.CurrentIndex == tran.LastIndex);
        }
예제 #5
0
        public static void FinalizeBundleHash(this IEnumerable <TransactionItem> transactionItems)
        {
            var validBundle = false;

            while (!validBundle)
            {
                var kerl = new Kerl();
                kerl.Reset();
                var transactionCount = transactionItems.Count();

                for (int i = 0; i < transactionCount; i++)
                {
                    var transaction = transactionItems.ElementAt(i);

                    var valueTrits = Converter.GetTrits(transaction.Value).ToLength(81);

                    var timestampTrits = Converter.GetTrits(transaction.Timestamp).ToLength(27);

                    var currentIndexTrits = Converter.GetTrits(transaction.CurrentIndex = ("" + i)).ToLength(27);

                    var lastIndexTrits = Converter.GetTrits(
                        transaction.LastIndex = ("" + (transactionCount - 1))).ToLength(27);

                    string stringToConvert = transaction.Address
                                             + Converter.GetTrytes(valueTrits)
                                             + transaction.Tag +
                                             Converter.GetTrytes(timestampTrits)
                                             + Converter.GetTrytes(currentIndexTrits) +
                                             Converter.GetTrytes(lastIndexTrits);

                    var t = Converter.GetTrits(stringToConvert);
                    kerl.Absorb(t, 0, t.Length);
                }

                sbyte[] hash = new sbyte[Curl.HASH_LENGTH];
                kerl.Squeeze(hash, 0, hash.Length);
                string hashInTrytes = Converter.GetTrytes(hash);

                foreach (var transaction in transactionItems)
                {
                    transaction.Bundle = hashInTrytes;
                }

                var normalizedHash = NormalizedBundle(hashInTrytes);
                if (normalizedHash.Contains(13))
                {
                    // Insecure bundle. Increment Tag and recompute bundle hash.
                    var firstTransaction = transactionItems.ElementAt(0);
                    var increasedTag     = Adder.Add(Converter.GetTrits(firstTransaction.Tag), new sbyte[1]);
                    firstTransaction.Tag = Converter.GetTrytes(increasedTag);
                }
                else
                {
                    validBundle = true;
                }
            }
        }
예제 #6
0
        public void kurlMultiAbsorbMultiSqueeze()
        {
            int[] initial_value = Converter.ToTrits("G9JYBOMPUXHYHKSNRNMMSSZCSHOFYOYNZRSZMAAYWDYEIMVVOGKPJBVBM9TDPULSFUNMTVXRKFIDOHUXXVYDLFSZYZTWQYTE9SPYYWYTXJYQ9IFGYOLZXWZBKWZN9QOOTBQMWMUBLEWUEEASRHRTNIQWJQNDWRYLCA");
            ICurl k             = new Kerl();

            k.Absorb(initial_value, 0, initial_value.Length);
            int[] hash_value = new int[Curl.HashLength * 2];
            k.Squeeze(hash_value, 0, hash_value.Length);
            String hash = Converter.ToTrytes(hash_value);

            Assert.AreEqual("LUCKQVACOGBFYSPPVSSOXJEKNSQQRQKPZC9NXFSMQNRQCGGUL9OHVVKBDSKEQEBKXRNUJSRXYVHJTXBPDWQGNSCDCBAIRHAQCOWZEBSNHIJIGPZQITIBJQ9LNTDIBTCQ9EUWKHFLGFUVGGUWJONK9GBCDUIMAYMMQX", hash);
        }
예제 #7
0
        public void kurlOneAbsorb()
        {
            int[] initial_value = Converter.ToTrits("EMIDYNHBWMBCXVDEFOFWINXTERALUKYYPPHKP9JJFGJEIUY9MUDVNFZHMMWZUYUSWAIOWEVTHNWMHANBH");
            ICurl k             = new Kerl();

            k.Absorb(initial_value, 0, initial_value.Length);
            int[] hash_value = new int[Curl.HashLength];
            k.Squeeze(hash_value, 0, hash_value.Length);
            String hash = Converter.ToTrytes(hash_value);

            Assert.AreEqual("EJEAOOZYSAWFPZQESYDHZCGYNSTWXUMVJOVDWUNZJXDGWCLUFGIMZRMGCAZGKNPLBRLGUNYWKLJTYEAQX", hash);
        }
예제 #8
0
        public void kurlMultiSqueeze()
        {
            int[]
                  initial_value = Converter.ToTrits("9MIDYNHBWMBCXVDEFOFWINXTERALUKYYPPHKP9JJFGJEIUY9MUDVNFZHMMWZUYUSWAIOWEVTHNWMHANBH");
            ICurl k             = new Kerl();

            k.Absorb(initial_value, 0, initial_value.Length);
            int[]
            hash_value = new int[Curl.HashLength * 2];
            k.Squeeze(hash_value, 0, hash_value.Length);
            String hash = Converter.ToTrytes(hash_value);

            Assert.AreEqual("G9JYBOMPUXHYHKSNRNMMSSZCSHOFYOYNZRSZMAAYWDYEIMVVOGKPJBVBM9TDPULSFUNMTVXRKFIDOHUXXVYDLFSZYZTWQYTE9SPYYWYTXJYQ9IFGYOLZXWZBKWZN9QOOTBQMWMUBLEWUEEASRHRTNIQWJQNDWRYLCA", hash);
        }
예제 #9
0
        private static string CalculateChecksum(string address)
        {
            // TODO inject curl
            ICurl curl = new Kerl();

            curl.Reset();
            curl.Absorb(Converter.ToTrits(address));
            var checksumTrits = new int[Sponge.HashLength];

            curl.Squeeze(checksumTrits);
            var checksum = Converter.ToTrytes(checksumTrits);

            return(checksum.Substring(72, 9));
        }
예제 #10
0
        public void ShouldCreateValidHash1()
        {
            sbyte[] trits =
                Converter.ToTrits("GYOMKVTSNHVJNCNFBBAH9AAMXLPLLLROQY99QN9DLSJUHDPBLCFFAIQXZA9BKMBJCYSFHFPXAHDWZFEIZ");
            Kerl kerl = (Kerl)SpongeFactory.Create(SpongeFactory.Mode.KERL);

            kerl.Reset();
            kerl.Absorb(trits, 0, trits.Length);
            sbyte[] hashTrits = new sbyte[trits.Length];
            kerl.Squeeze(hashTrits, 0, 243);
            string hash = Converter.ToTrytes(hashTrits);

            Assert.AreEqual(hash, "OXJCNFHUNAHWDLKKPELTBFUCVW9KLXKOGWERKTJXQMXTKFKNWNNXYD9DMJJABSEIONOSJTTEVKVDQEWTW");
        }
예제 #11
0
        public void ShouldCreateValidHash2()
        {
            sbyte[] trits =
                Converter.ToTrits("9MIDYNHBWMBCXVDEFOFWINXTERALUKYYPPHKP9JJFGJEIUY9MUDVNFZHMMWZUYUSWAIOWEVTHNWMHANBH");
            Kerl kerl = (Kerl)SpongeFactory.Create(SpongeFactory.Mode.KERL);

            kerl.Reset();
            kerl.Absorb(trits, 0, trits.Length);
            sbyte[] hashTrits = new sbyte[trits.Length * 2];
            kerl.Squeeze(hashTrits, 0, 243 * 2);
            string hash = Converter.ToTrytes(hashTrits);

            Assert.AreEqual(hash,
                            "G9JYBOMPUXHYHKSNRNMMSSZCSHOFYOYNZRSZMAAYWDYEIMVVOGKPJBVBM9TDPULSFUNMTVXRKFIDOHUXXVYDLFSZYZTWQYTE9SPYYWYTXJYQ9IFGYOLZXWZBKWZN9QOOTBQMWMUBLEWUEEASRHRTNIQWJQNDWRYLCA");
        }
예제 #12
0
        public void ShouldCreateValidHash1()
        {
            var trits = Converter.ToTrits(
                "GYOMKVTSNHVJNCNFBBAH9AAMXLPLLLROQY99QN9DLSJUHDPBLCFFAIQXZA9BKMBJCYSFHFPXAHDWZFEIZ");
            var kerl = new Kerl();

            kerl.Reset();
            kerl.Absorb(trits, 0, trits.Length);
            var hashTrits = new int[trits.Length];

            kerl.Squeeze(hashTrits, 0, 243);
            var hash = Converter.ToTrytes(hashTrits);

            Assert.AreEqual(hash, "OXJCNFHUNAHWDLKKPELTBFUCVW9KLXKOGWERKTJXQMXTKFKNWNNXYD9DMJJABSEIONOSJTTEVKVDQEWTW");
        }
예제 #13
0
        public void Test()
        {
            var trits = Converter.GetTrits(input);
            var kerl  = new Kerl();

            kerl.Initialize();
            kerl.Absorb(trits, 0, trits.Length);
            var hashTrits = new sbyte[Curl.HASH_LENGTH];

            kerl.Squeeze(hashTrits, 0, Curl.HASH_LENGTH);
            var hash = Converter.GetTrytes(hashTrits);

            Assert.AreEqual(expected, hash);
            //assert.deepEqual(test.expected, hash);
        }
예제 #14
0
        public void TestKerlOneAbsorb()
        {
            var tritValue = Converter.TrytesToTrits("KFNNRVYTYYYNHJLBTXOEFYBZTHGXHTX9XKXB9KUZDHGLKBQGPQCNHPGDSGYKWGHVXVLHPOEAWREBIVK99");

            var kerl = new Kerl();

            kerl.Absorb(tritValue);

            var hashValue = new int[Kerl.HashLength];

            kerl.Squeeze(hashValue);

            var hash = Converter.TritsToTrytes(hashValue);

            Assert.AreEqual("SHTKPLZWIXLDVHAEAGFSVWNDGVIX9SDVGEHAFGXEIMLWSHDTQYNZZKPBGMUF9GNEWIGIFYWWMSCLJ9RCD", hash);
        }
예제 #15
0
        public void KurlMultiSqueeze()
        {
            var tritValue = Converter.TrytesToTrits("9MIDYNHBWMBCXVDEFOFWINXTERALUKYYPPHKP9JJFGJEIUY9MUDVNFZHMMWZUYUSWAIOWEVTHNWMHANBH");

            var kerl = new Kerl();

            kerl.Absorb(tritValue);

            var hashValue = new int[Constants.TritHashLength * 2];

            kerl.Squeeze(hashValue);

            var hash = Converter.TritsToTrytes(hashValue);

            Assert.AreEqual("G9JYBOMPUXHYHKSNRNMMSSZCSHOFYOYNZRSZMAAYWDYEIMVVOGKPJBVBM9TDPULSFUNMTVXRKFIDOHUXXVYDLFSZYZTWQYTE9SPYYWYTXJYQ9IFGYOLZXWZBKWZN9QOOTBQMWMUBLEWUEEASRHRTNIQWJQNDWRYLCA", hash);
        }
예제 #16
0
        public void KerlOneAbsorbMethod2()
        {
            var input    = "EMIDYNHBWMBCXVDEFOFWINXTERALUKYYPPHKP9JJFGJEIUY9MUDVNFZHMMWZUYUSWAIOWEVTHNWMHANBH";
            var expected = "EJEAOOZYSAWFPZQESYDHZCGYNSTWXUMVJOVDWUNZJXDGWCLUFGIMZRMGCAZGKNPLBRLGUNYWKLJTYEAQX";

            var trits = Converter.GetTrits(input);
            var kerl  = new Kerl();

            kerl.Absorb(trits, 0, trits.Length);
            var hashTrits = new sbyte[Kerl.HASH_LENGTH];

            kerl.Squeeze(hashTrits, 0, Kerl.HASH_LENGTH);
            var hash = Converter.GetTrytes(hashTrits);

            Assert.AreEqual(expected, hash);
        }
예제 #17
0
        public void ShouldCreateValidHash3()
        {
            sbyte[] trits =
                Converter.ToTrits(
                    "G9JYBOMPUXHYHKSNRNMMSSZCSHOFYOYNZRSZMAAYWDYEIMVVOGKPJBVBM9TDPULSFUNMTVXRKFIDOHUXXVYDLFSZYZTWQYTE9SPYYWYTXJYQ9IFGYOLZXWZBKWZN9QOOTBQMWMUBLEWUEEASRHRTNIQWJQNDWRYLCA");
            Kerl kerl = (Kerl)SpongeFactory.Create(SpongeFactory.Mode.KERL);

            kerl.Reset();
            kerl.Absorb(trits, 0, trits.Length);
            sbyte[] hashTrits = new sbyte[trits.Length];
            kerl.Squeeze(hashTrits, 0, 243 * 2);
            string hash = Converter.ToTrytes(hashTrits);

            Assert.AreEqual(hash,
                            "LUCKQVACOGBFYSPPVSSOXJEKNSQQRQKPZC9NXFSMQNRQCGGUL9OHVVKBDSKEQEBKXRNUJSRXYVHJTXBPDWQGNSCDCBAIRHAQCOWZEBSNHIJIGPZQITIBJQ9LNTDIBTCQ9EUWKHFLGFUVGGUWJONK9GBCDUIMAYMMQX");
        }
예제 #18
0
        public void KerlMultiAbsorbMultiSqueeze()
        {
            var input    = "G9JYBOMPUXHYHKSNRNMMSSZCSHOFYOYNZRSZMAAYWDYEIMVVOGKPJBVBM9TDPULSFUNMTVXRKFIDOHUXXVYDLFSZYZTWQYTE9SPYYWYTXJYQ9IFGYOLZXWZBKWZN9QOOTBQMWMUBLEWUEEASRHRTNIQWJQNDWRYLCA";
            var expected = "LUCKQVACOGBFYSPPVSSOXJEKNSQQRQKPZC9NXFSMQNRQCGGUL9OHVVKBDSKEQEBKXRNUJSRXYVHJTXBPDWQGNSCDCBAIRHAQCOWZEBSNHIJIGPZQITIBJQ9LNTDIBTCQ9EUWKHFLGFUVGGUWJONK9GBCDUIMAYMMQX";

            var trits = Converter.GetTrits(input);
            var kerl  = new Kerl();

            kerl.Initialize();
            kerl.Absorb(trits, 0, trits.Length);
            var hashTrits = new sbyte[Kerl.HASH_LENGTH * 2];

            kerl.Squeeze(hashTrits, 0, Kerl.HASH_LENGTH * 2);
            var hash = Converter.GetTrytes(hashTrits);

            Assert.AreEqual(expected, hash);
        }
예제 #19
0
        public void KerlAbsorbMultiSqueeze()
        {
            var input    = "9MIDYNHBWMBCXVDEFOFWINXTERALUKYYPPHKP9JJFGJEIUY9MUDVNFZHMMWZUYUSWAIOWEVTHNWMHANBH";
            var expected = "G9JYBOMPUXHYHKSNRNMMSSZCSHOFYOYNZRSZMAAYWDYEIMVVOGKPJBVBM9TDPULSFUNMTVXRKFIDOHUXXVYDLFSZYZTWQYTE9SPYYWYTXJYQ9IFGYOLZXWZBKWZN9QOOTBQMWMUBLEWUEEASRHRTNIQWJQNDWRYLCA";

            var trits = Converter.GetTrits(input);
            var kerl  = new Kerl();

            kerl.Initialize();
            kerl.Absorb(trits, 0, trits.Length);
            var hashTrits = new sbyte[Kerl.HASH_LENGTH * 2];

            kerl.Squeeze(hashTrits, 0, Kerl.HASH_LENGTH * 2);
            var hash = Converter.GetTrytes(hashTrits);

            Assert.AreEqual(expected, hash);
        }
예제 #20
0
        public void KerlAbsorbSqueeze()
        {
            var input    = "GYOMKVTSNHVJNCNFBBAH9AAMXLPLLLROQY99QN9DLSJUHDPBLCFFAIQXZA9BKMBJCYSFHFPXAHDWZFEIZ";
            var expected = "OXJCNFHUNAHWDLKKPELTBFUCVW9KLXKOGWERKTJXQMXTKFKNWNNXYD9DMJJABSEIONOSJTTEVKVDQEWTW";

            var trits = Converter.GetTrits(input);
            var kerl  = new Kerl();

            kerl.Initialize();
            kerl.Absorb(trits, 0, trits.Length);
            var hashTrits = new sbyte[Kerl.HASH_LENGTH];

            kerl.Squeeze(hashTrits, 0, Kerl.HASH_LENGTH);
            var hash = Converter.GetTrytes(hashTrits);

            Assert.AreEqual(expected, hash);
        }
예제 #21
0
        /// <summary>
        /// The from address.
        /// </summary>
        /// <param name="address">
        /// The address.
        /// </param>
        /// <returns>
        /// The <see cref="Checksum"/>.
        /// </returns>
        public static Checksum FromAddress(Address address)
        {
            var addressTrits = Converter.TrytesToTrits(address.Value);

            var kerl = new Kerl();

            kerl.Absorb(addressTrits);

            var checksumTrits = new int[Constants.TritHashLength];

            kerl.Squeeze(checksumTrits);

            var tritsToTrytes = Converter.TritsToTrytes(checksumTrits);
            var checksum      = tritsToTrytes.Substring(81 - Length, Length);

            return(new Checksum(checksum));
        }
예제 #22
0
        /// <summary>
        /// The compute hash.
        /// </summary>
        /// <returns>
        /// The <see cref="Hash"/>.
        /// </returns>
        private Hash ComputeHash()
        {
            Hash bundleHash;
            var  valid = false;
            var  kerl  = new Kerl();

            do
            {
                kerl.Reset();
                for (var i = 0; i < this.Transactions.Count; i++)
                {
                    this.Transactions[i].CurrentIndex = i;
                    this.Transactions[i].LastIndex    = this.Transactions.Count - 1;

                    var transactionTrits = Converter.TrytesToTrits(this.Transactions[i].SignatureValidationTrytes());
                    kerl.Absorb(transactionTrits);
                }

                var hashTrits = new int[Constants.TritHashLength];
                kerl.Squeeze(hashTrits);
                bundleHash = new Hash(Converter.TritsToTrytes(hashTrits));
                var normalizedBundleValue = Hash.Normalize(bundleHash);

                if (Array.IndexOf(normalizedBundleValue, 13) != -1)
                {
                    var obsoleteTagTrits = Converter.TrytesToTrits(this.Transactions[0].ObsoleteTag.Value);
                    Converter.Increment(obsoleteTagTrits, Hash.Length);
                    this.Transactions[0].ObsoleteTag = new Tag(Converter.TritsToTrytes(obsoleteTagTrits));
                }
                else
                {
                    valid = true;
                }
            }while (!valid);

            return(bundleHash);
        }
예제 #23
0
        /// <summary>
        /// The finalize.
        /// </summary>
        public void Finalize()
        {
            if (this.Hash != null)
            {
                throw new InvalidOperationException("BundleHash is already finalized!");
            }

            if (this.Transactions.Count == 0)
            {
                throw new ArgumentException("At least one transaction must be added before finalizing bundle.");
            }

            var balance = this.Balance;

            if (balance < 0)
            {
                if (this.RemainderAddress != null && !string.IsNullOrEmpty(this.RemainderAddress.Value))
                {
                    this.Transactions.Add(new Transaction {
                        Address = this.RemainderAddress, Tag = Tag.Empty, Value = -balance, ObsoleteTag = Tag.Empty
                    });
                }
                else
                {
                    throw new InvalidOperationException("BundleHash balance is not even. Add remainder address.");
                }
            }

            if (balance > 0)
            {
                throw new InvalidOperationException("Insufficient value submitted.");
            }

            string bundleHashTrytes;
            var    valid = false;
            var    kerl  = new Kerl();

            do
            {
                kerl.Reset();
                for (var i = 0; i < this.Transactions.Count; i++)
                {
                    this.Transactions[i].CurrentIndex = i;
                    this.Transactions[i].LastIndex    = this.Transactions.Count - 1;

                    var transactionTrits = Converter.TrytesToTrits(this.Transactions[i].ToTrytes());
                    kerl.Absorb(transactionTrits);
                }

                var hash = new int[Kerl.HashLength];
                kerl.Squeeze(hash);
                bundleHashTrytes = Converter.TritsToTrytes(hash);
                var normalizedBundleValue = NormalizeBundle(bundleHashTrytes);

                if (Array.IndexOf(normalizedBundleValue, 13) != -1)
                {
                    var obsoleteTagTrits = Converter.TrytesToTrits(this.Transactions[0].ObsoleteTag.Value);
                    Converter.Increment(obsoleteTagTrits, 81);
                    this.Transactions[0].ObsoleteTag = new Tag(Converter.TritsToTrytes(obsoleteTagTrits));
                }
                else
                {
                    valid = true;
                }
            }while (!valid);

            this.Hash = new Hash(bundleHashTrytes);
            foreach (var transaction in this.Transactions)
            {
                transaction.BundleHash = this.Hash;
            }
        }
예제 #24
0
        /// <summary>
        ///     This function returns the bundle which is associated with a transaction. Input can by any type of transaction (tail
        ///     and non-tail).
        ///     If there are conflicting bundles (because of a replay for example) it will return multiple bundles.
        ///     It also does important validation checking (signatures, sum, order) to ensure that the correct bundle is returned.
        /// </summary>
        /// <param name="transaction">the transaction encoded in trytes</param>
        /// <returns>an array of bundle, if there are multiple arrays it means that there are conflicting bundles.</returns>
        public Bundle GetBundle(string transaction)
        {
            if (!InputValidator.IsHash(transaction))
            {
                throw new ArgumentException("Invalid hashes provided.");
            }

            var bundle = TraverseBundle(transaction, null, new Bundle());

            if (bundle == null)
            {
                throw new ArgumentException("Unknown Bundle");
            }

            long totalSum   = 0;
            var  bundleHash = bundle.Transactions[0].Bundle;

            ICurl curl = new Kerl();

            curl.Reset();

            var signaturesToValidate = new List <Signature>();

            for (var index = 0; index < bundle.Transactions.Count; index++)
            {
                var bundleTransaction = bundle.Transactions[index];
                var bundleValue       = bundleTransaction.Value;
                totalSum += bundleValue;

                if (bundleTransaction.CurrentIndex != index)
                {
                    throw new InvalidBundleException("The index of the bundle " + bundleTransaction.CurrentIndex +
                                                     " did not match the expected index " + index);
                }

                // Get the transaction trytes
                var thisTxTrytes = bundleTransaction.ToTransactionTrytes().Substring(2187, 162);

                // Absorb bundle hash + value + timestamp + lastIndex + currentIndex trytes.
                curl.Absorb(Converter.ToTrits(thisTxTrytes));

                // Check if input transaction
                if (bundleValue < 0)
                {
                    var address = bundleTransaction.Address;
                    var sig     = new Signature {
                        Address = address
                    };
                    sig.SignatureFragments.Add(bundleTransaction.SignatureMessageFragment);

                    // Find the subsequent txs with the remaining signature fragment
                    for (var i = index + 1; i < bundle.Transactions.Count; i++)
                    {
                        var newBundleTx = bundle.Transactions[i];

                        // Check if new tx is part of the signature fragment
                        if (newBundleTx.Address == address && newBundleTx.Value == 0)
                        {
                            if (sig.SignatureFragments.IndexOf(newBundleTx.SignatureMessageFragment) == -1)
                            {
                                sig.SignatureFragments.Add(newBundleTx.SignatureMessageFragment);
                            }
                        }
                    }

                    signaturesToValidate.Add(sig);
                }
            }

            // Check for total sum, if not equal 0 return error
            if (totalSum != 0)
            {
                throw new InvalidBundleException("Invalid Bundle Sum");
            }

            var bundleFromTrxs = new int[243];

            curl.Squeeze(bundleFromTrxs);
            var bundleFromTxString = Converter.ToTrytes(bundleFromTrxs);

            // Check if bundle hash is the same as returned by tx object
            if (!bundleFromTxString.Equals(bundleHash))
            {
                throw new InvalidBundleException("Invalid Bundle Hash");
            }
            // Last tx in the bundle should have currentIndex === lastIndex
            bundle.Length = bundle.Transactions.Count;
            if (
                !bundle.Transactions[bundle.Length - 1].CurrentIndex.Equals(
                    bundle.Transactions[bundle.Length - 1].LastIndex))
            {
                throw new InvalidBundleException("Invalid Bundle");
            }

            // Validate the signatures
            foreach (var aSignaturesToValidate in signaturesToValidate)
            {
                var signatureFragments = aSignaturesToValidate.SignatureFragments.ToArray();
                var address            = aSignaturesToValidate.Address;
                var isValidSignature   = new Signing().ValidateSignatures(address, signatureFragments, bundleHash);

                if (!isValidSignature)
                {
                    throw new InvalidSignatureException();
                }
            }

            return(bundle);
        }