Пример #1
0
        public bool CheckBlock(Block block)
        {
            // These are checks that are independent of context
            // that can be verified before saving an orphan block.

            // Size limits
            if (block.Transactions.Length == 0 || block.Transactions.Length > MAX_BLOCK_SIZE || block.Length > MAX_BLOCK_SIZE)
            {
                return(DoS(100, Error("CheckBlock() : size limits failed"),
                           RejectCode.INVALID, "bad-blk-length"));
            }

            // Check proof of work matches claimed amount
            if (CheckProofOfWork && !CheckProofOfWorkCore(block))
            {
                return(DoS(50, Error("CheckBlock() : proof of work failed"),
                           RejectCode.INVALID, "high-hash"));
            }

            // Check timestamp
            if (block.Header.BlockTime > Now + TimeSpan.FromSeconds(2 * 60 * 60))
            {
                return(Invalid(Error("CheckBlock() : block timestamp too far in the future"),
                               RejectCode.INVALID, "time-too-new"));
            }

            // First transaction must be coinbase, the rest must not be
            if (block.Transactions.Length == 0 || !block.Transactions[0].IsCoinBase)
            {
                return(DoS(100, Error("CheckBlock() : first tx is not coinbase"),
                           RejectCode.INVALID, "bad-cb-missing"));
            }
            for (int i = 1; i < block.Transactions.Length; i++)
            {
                if (block.Transactions[i].IsCoinBase)
                {
                    return(DoS(100, Error("CheckBlock() : more than one coinbase"),
                               RejectCode.INVALID, "bad-cb-multiple"));
                }
            }

            // Check transactions
            foreach (var tx in block.Transactions)
            {
                if (!CheckTransaction(tx))
                {
                    return(Error("CheckBlock() : CheckTransaction failed"));
                }
            }

            // Build the merkle tree already. We need it anyway later, and it makes the
            // block cache the transaction hashes, which means they don't need to be
            // recalculated many times during this block's validation.
            block.ComputeMerkleRoot();

            // Check for duplicate txids. This is caught by ConnectInputs(),
            // but catching it earlier avoids a potential DoS attack:
            HashSet <uint256> uniqueTx = new HashSet <uint256>();

            for (int i = 0; i < block.Transactions.Length; i++)
            {
                uniqueTx.Add(block.GetTxHash(i));
            }
            if (uniqueTx.Count != block.Transactions.Length)
            {
                return(DoS(100, Error("CheckBlock() : duplicate transaction"),
                           RejectCode.INVALID, "bad-txns-duplicate", true));
            }

            int nSigOps = 0;

            foreach (var tx in block.Transactions)
            {
                nSigOps += GetLegacySigOpCount(tx);
            }
            if (nSigOps > MAX_BLOCK_SIGOPS)
            {
                return(DoS(100, Error("CheckBlock() : out-of-bounds SigOpCount"),
                           RejectCode.INVALID, "bad-blk-sigops", true));
            }

            // Check merkle root
            if (CheckMerkleRoot && block.Header.HashMerkleRoot != block.vMerkleTree.Last())
            {
                return(DoS(100, Error("CheckBlock() : hashMerkleRoot mismatch"),
                           RejectCode.INVALID, "bad-txnmrklroot", true));
            }

            return(true);
        }
Пример #2
0
        private void InitMain()
        {
            SpendableCoinbaseDepth = 100;
            name = "Main";
            // The message start string is designed to be unlikely to occur in normal data.
            // The characters are rarely used upper ASCII, not valid as UTF-8, and produce
            // a large 4-byte int at any alignment.
            magic                   = 0xD9B4BEF9;
            vAlertPubKey            = DataEncoders.Encoders.Hex.DecodeData("04fc9702847840aaf195de8442ebecedf5b095cdbb9bc716bda9110971b28a49e0ead8564ff0db22209e0374782c093bb899692d524e9d6a6956e7c5ecbcd68284");
            nDefaultPort            = 8333;
            nRPCPort                = 8332;
            _ProofOfLimit           = new Target(~new uint256(0) >> 32);
            nSubsidyHalvingInterval = 210000;

            Transaction txNew = new Transaction();

            txNew.Version = 1;
            txNew.Inputs.Add(new TxIn());
            txNew.Outputs.Add(new TxOut());
            txNew.Inputs[0].ScriptSig     = new Script(DataEncoders.Encoders.Hex.DecodeData("04ffff001d0104455468652054696d65732030332f4a616e2f32303039204368616e63656c6c6f72206f6e206272696e6b206f66207365636f6e64206261696c6f757420666f722062616e6b73"));
            txNew.Outputs[0].Value        = 50 * Money.COIN;
            txNew.Outputs[0].ScriptPubKey = new Script() + DataEncoders.Encoders.Hex.DecodeData("04678afdb0fe5548271967f1a67130b7105cd6a828e03909a67962e0ea1f61deb649f6bc3f4cef38c4f35504e51ec112de5c384df7ba0b8d578a4c702b6bf11d5f") + OpcodeType.OP_CHECKSIG;
            genesis.Transactions.Add(txNew);
            genesis.Header.HashPrevBlock  = 0;
            genesis.Header.HashMerkleRoot = genesis.ComputeMerkleRoot();
            genesis.Header.Version        = 1;
            genesis.Header.BlockTime      = Utils.UnixTimeToDateTime(1231006505);
            genesis.Header.Bits           = 0x1d00ffff;
            genesis.Header.Nonce          = 2083236893;

            hashGenesisBlock = genesis.GetHash();
            assert(hashGenesisBlock == new uint256("0x000000000019d6689c085ae165831e934ff763ae46a2a6c172b3f1b60a8ce26f"));
            assert(genesis.Header.HashMerkleRoot == new uint256("0x4a5e1e4baab89f3a32518a88c31bc87f618f76673e2cc77ab2127b7afdeda33b"));
#if !PORTABLE
            vSeeds.Add(new DNSSeedData("bitcoin.sipa.be", "seed.bitcoin.sipa.be"));
            vSeeds.Add(new DNSSeedData("bluematt.me", "dnsseed.bluematt.me"));
            vSeeds.Add(new DNSSeedData("dashjr.org", "dnsseed.bitcoin.dashjr.org"));
            vSeeds.Add(new DNSSeedData("bitcoinstats.com", "seed.bitcoinstats.com"));
            vSeeds.Add(new DNSSeedData("bitnodes.io", "seed.bitnodes.io"));
            vSeeds.Add(new DNSSeedData("xf2.org", "bitseed.xf2.org"));
#endif
            base58Prefixes[(int)Base58Type.PUBKEY_ADDRESS]             = new byte[] { (0) };
            base58Prefixes[(int)Base58Type.SCRIPT_ADDRESS]             = new byte[] { (5) };
            base58Prefixes[(int)Base58Type.SECRET_KEY]                 = new byte[] { (128) };
            base58Prefixes[(int)Base58Type.ENCRYPTED_SECRET_KEY_NO_EC] = new byte[] { 0x01, 0x42 };
            base58Prefixes[(int)Base58Type.ENCRYPTED_SECRET_KEY_EC]    = new byte[] { 0x01, 0x43 };
            base58Prefixes[(int)Base58Type.EXT_PUBLIC_KEY]             = new byte[] { (0x04), (0x88), (0xB2), (0x1E) };
            base58Prefixes[(int)Base58Type.EXT_SECRET_KEY]             = new byte[] { (0x04), (0x88), (0xAD), (0xE4) };
            base58Prefixes[(int)Base58Type.PASSPHRASE_CODE]            = new byte[] { 0x2C, 0xE9, 0xB3, 0xE1, 0xFF, 0x39, 0xE2 };
            base58Prefixes[(int)Base58Type.CONFIRMATION_CODE]          = new byte[] { 0x64, 0x3B, 0xF6, 0xA8, 0x9A };
            base58Prefixes[(int)Base58Type.STEALTH_ADDRESS]            = new byte[] { 0x2a };
            base58Prefixes[(int)Base58Type.ASSET_ID]        = new byte[] { 23 };
            base58Prefixes[(int)Base58Type.COLORED_ADDRESS] = new byte[] { 0x13 };

            // Convert the pnSeeds array into usable address objects.
            Random   rand     = new Random();
            TimeSpan nOneWeek = TimeSpan.FromDays(7);
#if !PORTABLE
            for (int i = 0; i < pnSeed.Length; i++)
            {
                // It'll only connect to one or two seed nodes because once it connects,
                // it'll get a pile of addresses with newer timestamps.
                IPAddress      ip   = IPAddress.Parse(pnSeed[i]);
                NetworkAddress addr = new NetworkAddress();
                // Seed nodes are given a random 'last seen time' of between one and two
                // weeks ago.
                addr.Time     = DateTime.UtcNow - (TimeSpan.FromSeconds(rand.NextDouble() * nOneWeek.TotalSeconds)) - nOneWeek;
                addr.Endpoint = new IPEndPoint(ip, DefaultPort);
                vFixedSeeds.Add(addr);
            }
#endif
        }
Пример #3
0
        public bool CheckBlock(Block block)
        {
            // These are checks that are independent of context
            // that can be verified before saving an orphan block.

            // Size limits
            if(block.Transactions.Count == 0 || block.Transactions.Count > MAX_BLOCK_SIZE || block.Length > MAX_BLOCK_SIZE)
                return DoS(100, Error("CheckBlock() : size limits failed"),
                                 RejectCode.INVALID, "bad-blk-length");

            // Check proof of work matches claimed amount
            if(CheckProofOfWork && !CheckProofOfWorkCore(block))
                return DoS(50, Error("CheckBlock() : proof of work failed"),
                                 RejectCode.INVALID, "high-hash");

            // Check timestamp
            if(block.Header.BlockTime > Now + TimeSpan.FromSeconds(2 * 60 * 60))
                return Invalid(Error("CheckBlock() : block timestamp too far in the future"),
                                     RejectCode.INVALID, "time-too-new");

            // First transaction must be coinbase, the rest must not be
            if(block.Transactions.Count == 0 || !block.Transactions[0].IsCoinBase)
                return DoS(100, Error("CheckBlock() : first tx is not coinbase"),
                                 RejectCode.INVALID, "bad-cb-missing");
            for(int i = 1 ; i < block.Transactions.Count ; i++)
                if(block.Transactions[i].IsCoinBase)
                    return DoS(100, Error("CheckBlock() : more than one coinbase"),
                                     RejectCode.INVALID, "bad-cb-multiple");

            // Check transactions
            foreach(var tx in block.Transactions)
                if(!CheckTransaction(tx))
                    return Error("CheckBlock() : CheckTransaction failed");

            // Build the merkle tree already. We need it anyway later, and it makes the
            // block cache the transaction hashes, which means they don't need to be
            // recalculated many times during this block's validation.
            block.ComputeMerkleRoot();

            // Check for duplicate txids. This is caught by ConnectInputs(),
            // but catching it earlier avoids a potential DoS attack:
            HashSet<uint256> uniqueTx = new HashSet<uint256>();
            for(int i = 0 ; i < block.Transactions.Count ; i++)
            {
                uniqueTx.Add(block.GetTxHash(i));
            }
            if(uniqueTx.Count != block.Transactions.Count)
                return DoS(100, Error("CheckBlock() : duplicate transaction"),
                                 RejectCode.INVALID, "bad-txns-duplicate", true);

            int nSigOps = 0;
            foreach(var tx in block.Transactions)
            {
                nSigOps += GetLegacySigOpCount(tx);
            }
            if(nSigOps > MAX_BLOCK_SIGOPS)
                return DoS(100, Error("CheckBlock() : out-of-bounds SigOpCount"),
                                 RejectCode.INVALID, "bad-blk-sigops", true);

            // Check merkle root
            if(CheckMerkleRoot && block.Header.HashMerkleRoot != block.vMerkleTree.Last())
                return DoS(100, Error("CheckBlock() : hashMerkleRoot mismatch"),
                                 RejectCode.INVALID, "bad-txnmrklroot", true);

            return true;
        }