| 1880 | } |
| 1881 | |
| 1882 | bool AcceptBlock(CBlock &block, CValidationState &state, CDiskBlockPos *dbp, bool mining) { |
| 1883 | AssertLockHeld(cs_main); |
| 1884 | |
| 1885 | uint256 blockHash = block.GetHash(); |
| 1886 | uint32_t blockHeight = block.GetHeight(); |
| 1887 | LogPrint(BCLog::INFO, "[%d] %s, miner: %s, ts: %u\n", |
| 1888 | block.GetHeight(), blockHash.GetHex(), block.GetMinerUserID().ToString(), block.GetBlockTime()); |
| 1889 | |
| 1890 | // Check for duplicated block |
| 1891 | if (mapBlockIndex.count(blockHash)) |
| 1892 | return state.Invalid(ERRORMSG("[%d] block already in mapBlockIndex", blockHeight), 0, "duplicated"); |
| 1893 | |
| 1894 | assert(block.GetHeight() == 0 || mapBlockIndex.count(block.GetPrevBlockHash())); |
| 1895 | |
| 1896 | if (block.GetHeight() != 0 && block.GetFuelRate() != GetElementForBurn(mapBlockIndex[block.GetPrevBlockHash()])) |
| 1897 | return state.DoS(100, ERRORMSG("[%d] block fuel rate unmatched", blockHeight), REJECT_INVALID, "fuel-rate-unmatched"); |
| 1898 | |
| 1899 | // Get prev block index |
| 1900 | CBlockIndex *pPrevBlockIndex = nullptr; |
| 1901 | int32_t height = 0; |
| 1902 | if (block.GetHeight() != 0 || blockHash != SysCfg().GetGenesisBlockHash()) { |
| 1903 | map<uint256, CBlockIndex *>::iterator mi = mapBlockIndex.find(block.GetPrevBlockHash()); |
| 1904 | if (mi == mapBlockIndex.end()) |
| 1905 | return state.DoS(10, ERRORMSG("[%d] prev block not found", blockHeight), 0, "bad-prevblk"); |
| 1906 | |
| 1907 | pPrevBlockIndex = (*mi).second; |
| 1908 | height = pPrevBlockIndex->height + 1; |
| 1909 | |
| 1910 | if (blockHeight != (uint32_t)height) { |
| 1911 | return state.DoS(100, ERRORMSG("[%d] height given in block mismatches with its actual height", blockHeight), |
| 1912 | REJECT_INVALID, "incorrect-height"); |
| 1913 | } |
| 1914 | |
| 1915 | // Check timestamp against prev |
| 1916 | if (block.GetBlockTime() <= pPrevBlockIndex->GetBlockTime() || |
| 1917 | (block.GetBlockTime() - pPrevBlockIndex->GetBlockTime()) < GetBlockInterval(blockHeight)) { |
| 1918 | return state.Invalid(ERRORMSG("[%d] the new block came in too early", blockHeight), |
| 1919 | REJECT_INVALID, "time-too-early"); |
| 1920 | } |
| 1921 | |
| 1922 | if (pPrevBlockIndex->GetBlockHash() != chainActive.Tip()->GetBlockHash()) { |
| 1923 | if (!ProcessForkedChain(block, pPrevBlockIndex, state)) { |
| 1924 | return state.DoS(100, ERRORMSG("[%d] failed to process forked chain", blockHeight), REJECT_INVALID, |
| 1925 | "failed-to-process-forked-chain"); |
| 1926 | } |
| 1927 | } |
| 1928 | |
| 1929 | // Reject block.nVersion=1 blocks when 95% (75% on testnet) of the network has been upgraded: |
| 1930 | if (block.GetVersion() < 2) { |
| 1931 | if ((!TestNet() && CBlockIndex::IsSuperMajority(2, pPrevBlockIndex, 950, 1000)) || |
| 1932 | (TestNet() && CBlockIndex::IsSuperMajority(2, pPrevBlockIndex, 75, 100))) { |
| 1933 | return state.Invalid(ERRORMSG("[%d] rejected nVersion=1 block", blockHeight), REJECT_OBSOLETE, "bad-version"); |
| 1934 | } |
| 1935 | } |
| 1936 | } |
| 1937 | |
| 1938 | // Write block to history file |
| 1939 | try { |
no test coverage detected