コード例 #1
0
        public bool AcceptBlock(ref CBlock block)
        {
            uint256 nHash = block.header.Hash;

            if (blockMap.ContainsKey(nHash))
            {
                // Already have this block.
                return false;
            }

            CBlockStoreItem prevBlockCursor;
            if (!blockMap.TryGetValue(block.header.prevHash, out prevBlockCursor))
            {
                // Unable to get the cursor.
                return false;
            }

            var prevBlockHeader = prevBlockCursor.BlockHeader;

            uint nHeight = prevBlockCursor.nHeight + 1;

            // Check timestamp against prev
            if (NetInfo.FutureDrift(block.header.nTime) < prevBlockHeader.nTime)
            {
                // block's timestamp is too early
                return false;
            }

            // Check that all transactions are finalized
            foreach (var tx in block.vtx)
            {
                if (!tx.IsFinal(nHeight, block.header.nTime))
                {
                    return false;
                }
            }

            // Check that the block chain matches the known block chain up to a checkpoint
            if (!HashCheckpoints.Verify(nHeight, nHash))
            {
                return false;  // rejected by checkpoint lock-in
            }

            // Enforce rule that the coinbase starts with serialized block height
            var expect = new CScript();
            expect.AddNumber((int)nHeight);

            byte[] expectBytes = expect;
            byte[] scriptSig = block.vtx[0].vin[0].scriptSig;

            if (!expectBytes.SequenceEqual(scriptSig.Take(expectBytes.Length)))
            {
                return false; // coinbase doesn't start with serialized height.
            }

            // Write block to file.
            var newCursor = new CBlockStoreItem()
            {
                nHeight = nHeight,
            };

            newCursor.FillHeader(block.header);

            if (!AddItemToIndex(ref newCursor, ref block))
            {
                dbConn.Rollback();

                return false;
            }

            return true;
        }
コード例 #2
0
        /// <summary>
        /// Init the block storage manager.
        /// </summary>
        /// <param name="IndexDB">Path to index database</param>
        /// <param name="BlockFile">Path to block file</param>
        public CBlockStore(string IndexDB = "blockstore.dat", string BlockFile = "blk0001.dat")
        {
            strDbFile = IndexDB;
            strBlockFile = BlockFile;

            bool firstInit = !File.Exists(strDbFile);
            dbPlatform = new SQLitePlatformGeneric();
            dbConn = new SQLiteConnection(dbPlatform, strDbFile);

            fStreamReadWrite = File.Open(strBlockFile, FileMode.OpenOrCreate, FileAccess.ReadWrite);

            Instance = this;

            if (firstInit)
            {
                lock (LockObj)
                {
                    // Create tables
                    dbConn.CreateTable<CBlockStoreItem>(CreateFlags.AutoIncPK);
                    dbConn.CreateTable<CMerkleNode>(CreateFlags.AutoIncPK);
                    dbConn.CreateTable<TxOutItem>(CreateFlags.ImplicitPK);
                    dbConn.CreateTable<ChainState>(CreateFlags.AutoIncPK);

                    ChainParams = new ChainState()
                    {
                        nBestChainTrust = 0,
                        nBestHeight = 0,
                        nHashBestChain = 0
                    };

                    dbConn.Insert(ChainParams);

                    var genesisBlock = new CBlock(
                        Interop.HexToArray(
                            "01000000" + // nVersion=1
                            "0000000000000000000000000000000000000000000000000000000000000000" + // prevhash is zero
                            "7b0502ad2f9f675528183f83d6385794fbcaa914e6d385c6cb1d866a3b3bb34c" + // merkle root
                            "398e1151" + // nTime=1360105017
                            "ffff0f1e" + // nBits=0x1e0fffff
                            "d3091800" + // nNonce=1575379
                            "01" +       // nTxCount=1
                            "01000000" + // nVersion=1
                            "398e1151" + // nTime=1360105017
                            "01" +       // nInputs=1
                            "0000000000000000000000000000000000000000000000000000000000000000" + // input txid is zero
                            "ffffffff" + // n=uint.maxValue
                            "4d" +       // scriptSigLen=77
                            "04ffff001d020f274468747470733a2f2f626974636f696e74616c6b2e6f72672f696e6465782e7068703f746f7069633d3133343137392e6d736731353032313936236d736731353032313936" + // scriptSig
                            "ffffffff" + // nSequence=uint.maxValue
                            "01" +       // nOutputs=1
                            "0000000000000000" + // nValue=0
                            "00" +       // scriptPubkeyLen=0
                            "00000000" + // nLockTime=0
                            "00"         // sigLen=0
                    ));

                    // Write block to file.
                    var rootCursor = new CBlockStoreItem()
                    {
                        nHeight = 0
                    };

                    rootCursor.FillHeader(genesisBlock.header);

                    if (!AddItemToIndex(ref rootCursor, ref genesisBlock))
                    {
                        throw new Exception("Unable to write genesis block");
                    }
                }
            }
            else
            {
                var blockTreeItems = dbConn.Query<CBlockStoreItem>("select * from [BlockStorage] order by [ItemId] asc");

                // Init list of block items
                foreach (var item in blockTreeItems)
                {
                    item.nStakeModifierChecksum = StakeModifier.GetModifierChecksum(item);

                    blockMap.TryAdd(item.Hash, item);

                    if (item.IsProofOfStake)
                    {
                        // build mapStakeSeen
                        mapStakeSeen.TryAdd(item.prevoutStake, item.nStakeTime);
                    }
                }

                // Load data about the top node.
                ChainParams = dbConn.Table<ChainState>().First();

                genesisBlockCursor = dbConn.Query<CBlockStoreItem>("select * from [BlockStorage] where [Hash] = ?", (byte[])NetInfo.nHashGenesisBlock).First();
                bestBlockCursor = dbConn.Query<CBlockStoreItem>("select * from [BlockStorage] where [Hash] = ?", ChainParams.HashBestChain).First();
            }
        }