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); }
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 }
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; }