Ejemplo n.º 1
0
        public async Task SaveAndLoadUint256_ToDatabase_ShouldBeStoreAsBigEndian(string data)
        {
            var binary = Encoders.Hex.DecodeData(data); // Big endian
            var parsed = uint256.Parse(data);

            var entity = new Ztm.Data.Entity.Contexts.Main.Block
            {
                Height     = 0,
                Hash       = parsed,
                Version    = 0,
                Bits       = new Target(0),
                Nonce      = 0,
                Time       = DateTime.UtcNow,
                MerkleRoot = uint256.Zero
            };

            try
            {
                // Store to database.
                await this.subject.Blocks.AddAsync(entity, CancellationToken.None);

                await this.subject.SaveChangesAsync();

                // Assert Endianness.
                using (var command = this.subject.Database.GetDbConnection().CreateCommand())
                {
                    command.CommandText = "SELECT \"Hash\" FROM \"Blocks\" LIMIT 1;";
                    this.subject.Database.OpenConnection();
                    using (var result = command.ExecuteReader())
                    {
                        Assert.True(result.Read(), "No available data");
                        var record = (IDataRecord)result;
                        var hash   = record[0] as byte[]; // Get raw data.

                        Assert.Equal(binary, hash);
                    }
                }

                // Get uint256 back.
                var block = await this.subject.Blocks.FirstOrDefaultAsync();

                Assert.NotNull(block);
                Assert.Equal(parsed, block.Hash);
            }
            finally
            {
                this.subject.Database.ExecuteSqlCommand("TRUNCATE TABLE \"Blocks\" CASCADE");
            }
        }
Ejemplo n.º 2
0
        Block ToDomain(Ztm.Data.Entity.Contexts.Main.Block data, Ztm.Data.Entity.Contexts.Main.Block previous = null)
        {
            var block = Block.CreateBlock(this.zcoinNetwork);

            // Block properties.
            block.Header.Version        = data.Version;
            block.Header.HashMerkleRoot = data.MerkleRoot;
            block.Header.BlockTime      = DateTime.SpecifyKind(data.Time, DateTimeKind.Utc);
            block.Header.Bits           = data.Bits;
            block.Header.Nonce          = (uint)data.Nonce;

            if (data.MtpVersion != null)
            {
                if (!block.Header.IsMtp())
                {
                    throw new ArgumentException(
                              "The data is MTP-enabled but the consensus not activated for this data.",
                              nameof(data)
                              );
                }

                if (data.MtpHashValue == null || data.Reserved1 == null || data.Reserved2 == null)
                {
                    throw new ArgumentException(
                              "The data has MtpVersion but some other required properties is null.",
                              nameof(data)
                              );
                }

                block.Header.SetMtpVersion(data.MtpVersion.Value);
                block.Header.SetMtpHashValue(data.MtpHashValue);
                block.Header.SetReserved1(data.Reserved1);
                block.Header.SetReserved2(data.Reserved2);
            }

            if (previous != null)
            {
                block.Header.HashPrevBlock = previous.Hash;
            }

            block.Transactions = data.Transactions
                                 .Select(e => ToDomain(e.Transaction))
                                 .Cast <Transaction>()
                                 .ToList();

            return(block);
        }
Ejemplo n.º 3
0
        public async Task SaveAndLoadUint256_ToDatabase_ShouldBeStoreAsBigEndian(string data)
        {
            using (var db = this.fixture.CreateDbContext())
            {
                var binary = Encoders.Hex.DecodeData(data); // Big endian
                var parsed = uint256.Parse(data);

                var entity = new Ztm.Data.Entity.Contexts.Main.Block
                {
                    Height     = 0,
                    Hash       = parsed,
                    Version    = 0,
                    Bits       = new Target(0),
                    Nonce      = 0,
                    Time       = DateTime.UtcNow,
                    MerkleRoot = uint256.Zero
                };

                // Store to database.
                await db.Blocks.AddAsync(entity, CancellationToken.None);

                await db.SaveChangesAsync();

                // Assert Endianness.
                var blockHashes = this.fixture.ExecuteSql("SELECT \"Hash\" FROM \"Blocks\" LIMIT 1;")
                                  .Select(r => r[0] as byte[]);

                var hash = Assert.Single(blockHashes);
                Assert.Equal(binary, hash);

                // Get uint256 back.
                var block = await db.Blocks.FirstOrDefaultAsync();

                Assert.NotNull(block);
                Assert.Equal(parsed, block.Hash);
            }
        }
Ejemplo n.º 4
0
        async Task StoreBlockAsync(Block block, int height)
        {
            var entity = new Ztm.Data.Entity.Contexts.Main.Block()
            {
                Height     = height,
                Hash       = block.GetHash(),
                Version    = block.Header.Version,
                Bits       = block.Header.Bits,
                Nonce      = block.Header.Nonce,
                Time       = block.Header.BlockTime.UtcDateTime,
                MerkleRoot = block.Header.HashMerkleRoot,
            };

            for (var i = 0; i < block.Transactions.Count; i++)
            {
                var tx = new Ztm.Data.Entity.Contexts.Main.Transaction()
                {
                    Hash     = block.Transactions[i].GetHash(),
                    Version  = block.Transactions[i].Version,
                    LockTime = block.Transactions[i].LockTime,
                };

                for (var j = 0; j < block.Transactions[i].Inputs.Count; j++)
                {
                    var input = block.Transactions[i].Inputs[j];

                    tx.Inputs.Add(new Ztm.Data.Entity.Contexts.Main.Input()
                    {
                        TransactionHash = tx.Hash,
                        Index           = j,
                        OutputHash      = input.PrevOut.Hash,
                        OutputIndex     = input.PrevOut.N,
                        Script          = input.ScriptSig,
                        Sequence        = input.Sequence,
                    });
                }

                for (var j = 0; j < block.Transactions[i].Outputs.Count; j++)
                {
                    var output = block.Transactions[i].Outputs[j];

                    tx.Outputs.Add(new Ztm.Data.Entity.Contexts.Main.Output()
                    {
                        TransactionHash = tx.Hash,
                        Index           = j,
                        Value           = output.Value,
                        Script          = output.ScriptPubKey,
                    });
                }

                entity.Transactions.Add(new Ztm.Data.Entity.Contexts.Main.BlockTransaction()
                {
                    BlockHash       = entity.Hash,
                    TransactionHash = tx.Hash,
                    Index           = i,
                    Transaction     = tx,
                });
            }

            using (var db = this.db.CreateDbContext())
            {
                await db.Blocks.AddAsync(entity);

                await db.SaveChangesAsync();
            }
        }
Ejemplo n.º 5
0
        Ztm.Data.Entity.Contexts.Main.Block ToEntity(Block block, int height)
        {
            var header = block.Header;

            var entity = new Ztm.Data.Entity.Contexts.Main.Block()
            {
                Height     = height,
                Hash       = block.GetHash(),
                Version    = header.Version,
                Bits       = header.Bits,
                Nonce      = header.Nonce,
                Time       = header.BlockTime.UtcDateTime,
                MerkleRoot = header.HashMerkleRoot
            };

            if (header.IsMtp())
            {
                if (header.GetMtpHashValue() == null || header.GetReserved1() == null || header.GetReserved2() == null)
                {
                    throw new ArgumentException(
                              "Block is MTP-enabled but some required fields is null.",
                              nameof(block)
                              );
                }

                entity.MtpVersion   = header.GetMtpVersion();
                entity.MtpHashValue = header.GetMtpHashValue();
                entity.Reserved1    = header.GetReserved1();
                entity.Reserved2    = header.GetReserved2();
            }

            // Transactions.
            var transactions = new Dictionary <uint256, Ztm.Data.Entity.Contexts.Main.Transaction>();

            for (int i = 0; i < block.Transactions.Count; i++)
            {
                Ztm.Data.Entity.Contexts.Main.Transaction tx;

                block.Transactions[i].PrecomputeHash(invalidateExisting: true, lazily: false);

                var hash    = block.Transactions[i].GetHash();
                var blockTx = new Ztm.Data.Entity.Contexts.Main.BlockTransaction()
                {
                    BlockHash       = block.GetHash(),
                    TransactionHash = hash,
                    Index           = i,
                    Block           = entity
                };

                if (!transactions.TryGetValue(hash, out tx))
                {
                    tx = ToEntity(block.Transactions[i]);
                    transactions.Add(hash, tx);

                    blockTx.Transaction = tx;
                    tx.Blocks.Add(blockTx);
                }

                entity.Transactions.Add(blockTx);
            }

            return(entity);
        }