# Nimbus # Copyright (c) 2018-2024 Status Research & Development GmbH # Licensed under either of # * Apache License, version 2.0, ([LICENSE-APACHE](LICENSE-APACHE) or # http://www.apache.org/licenses/LICENSE-2.0) # * MIT license ([LICENSE-MIT](LICENSE-MIT) or # http://opensource.org/licenses/MIT) # at your option. This file may not be copied, modified, or distributed except # according to those terms. import stew/byteutils, ../nimbus/common, ../nimbus/config, ../nimbus/utils/utils, ../nimbus/core/chain/forked_chain, ../nimbus/db/ledger, unittest2 const genesisFile = "tests/customgenesis/cancun123.json" senderAddr = hexToByteArray[20]("73cf19657412508833f618a15e8251306b3e6ee5") type TestEnv = object conf: NimbusConf proc setupEnv(): TestEnv = let conf = makeConfig(@[ "--custom-network:" & genesisFile ]) TestEnv(conf: conf) proc newCom(env: TestEnv): CommonRef = let com = CommonRef.new( newCoreDbRef DefaultDbMemory, env.conf.networkId, env.conf.networkParams ) com.initializeEmptyDb() com proc makeBlk(com: CommonRef, number: BlockNumber, parentBlk: EthBlock): EthBlock = template parent(): BlockHeader = parentBlk.header var wds = newSeqOfCap[Withdrawal](number.int) for i in 0.. head -> error check chain.forkChoice(blk1.blockHash, blk3.blockHash).isErr # blk4 is not part of chain check chain.forkChoice(blk4.blockHash, blk2.blockHash).isErr # finalized > head -> error check chain.forkChoice(blk1.blockHash, blk2.blockHash).isErr # blk4 is not part of chain check chain.forkChoice(blk2.blockHash, blk4.blockHash).isErr # finalized < head -> ok check chain.forkChoice(blk2.blockHash, blk1.blockHash).isOk check com.headHash == blk2.blockHash check chain.latestHash == blk2.blockHash # finalized == head -> ok check chain.forkChoice(blk2.blockHash, blk2.blockHash).isOk check com.headHash == blk2.blockHash check chain.latestHash == blk2.blockHash # no baggage written check com.wdWritten(blk1) == 0 check com.wdWritten(blk2) == 0 test "newBase == cursor": let com = env.newCom() var chain = newForkedChain(com, com.genesisHeader, baseDistance = 3) check chain.importBlock(blk1).isOk check chain.importBlock(blk2).isOk check chain.importBlock(blk3).isOk check chain.importBlock(blk4).isOk check chain.importBlock(blk5).isOk check chain.importBlock(blk6).isOk check chain.importBlock(blk7).isOk check chain.importBlock(blk4).isOk # newbase == cursor check chain.forkChoice(blk7.blockHash, blk6.blockHash).isOk check com.headHash == blk7.blockHash check chain.latestHash == blk7.blockHash check com.wdWritten(blk7) == 0 # head - baseDistance must been finalized check com.wdWritten(blk4) == 4 # make sure aristo not wiped out baggage check com.wdWritten(blk3) == 3 test "newBase between oldBase and cursor": let com = env.newCom() var chain = newForkedChain(com, com.genesisHeader, baseDistance = 3) check chain.importBlock(blk1).isOk check chain.importBlock(blk2).isOk check chain.importBlock(blk3).isOk check chain.importBlock(blk4).isOk check chain.importBlock(blk5).isOk check chain.importBlock(blk6).isOk check chain.importBlock(blk7).isOk check chain.forkChoice(blk7.blockHash, blk6.blockHash).isOk check com.headHash == blk7.blockHash check chain.latestHash == blk7.blockHash check com.wdWritten(blk6) == 0 check com.wdWritten(blk7) == 0 # head - baseDistance must been finalized check com.wdWritten(blk4) == 4 # make sure aristo not wiped out baggage check com.wdWritten(blk3) == 3 test "newBase == oldBase, fork and keep on that fork": let com = env.newCom() var chain = newForkedChain(com, com.genesisHeader) check chain.importBlock(blk1).isOk check chain.importBlock(blk2).isOk check chain.importBlock(blk3).isOk check chain.importBlock(blk4).isOk check chain.importBlock(blk5).isOk check chain.importBlock(blk6).isOk check chain.importBlock(blk7).isOk check chain.importBlock(B4).isOk check chain.importBlock(B5).isOk check chain.importBlock(B6).isOk check chain.importBlock(B7).isOk check chain.forkChoice(B7.blockHash, B5.blockHash).isOk check com.headHash == B7.blockHash check chain.latestHash == B7.blockHash test "newBase == cursor, fork and keep on that fork": let com = env.newCom() var chain = newForkedChain(com, com.genesisHeader, baseDistance = 3) check chain.importBlock(blk1).isOk check chain.importBlock(blk2).isOk check chain.importBlock(blk3).isOk check chain.importBlock(blk4).isOk check chain.importBlock(blk5).isOk check chain.importBlock(blk6).isOk check chain.importBlock(blk7).isOk check chain.importBlock(B4).isOk check chain.importBlock(B5).isOk check chain.importBlock(B6).isOk check chain.importBlock(B7).isOk check chain.importBlock(B4).isOk check chain.forkChoice(B7.blockHash, B6.blockHash).isOk check com.headHash == B7.blockHash check chain.latestHash == B7.blockHash test "newBase between oldBase and cursor, fork and keep on that fork": let com = env.newCom() var chain = newForkedChain(com, com.genesisHeader, baseDistance = 3) check chain.importBlock(blk1).isOk check chain.importBlock(blk2).isOk check chain.importBlock(blk3).isOk check chain.importBlock(blk4).isOk check chain.importBlock(blk5).isOk check chain.importBlock(blk6).isOk check chain.importBlock(blk7).isOk check chain.importBlock(B4).isOk check chain.importBlock(B5).isOk check chain.importBlock(B6).isOk check chain.importBlock(B7).isOk check chain.forkChoice(B7.blockHash, B5.blockHash).isOk check com.headHash == B7.blockHash check chain.latestHash == B7.blockHash test "newBase == oldBase, fork and return to old chain": let com = env.newCom() var chain = newForkedChain(com, com.genesisHeader) check chain.importBlock(blk1).isOk check chain.importBlock(blk2).isOk check chain.importBlock(blk3).isOk check chain.importBlock(blk4).isOk check chain.importBlock(blk5).isOk check chain.importBlock(blk6).isOk check chain.importBlock(blk7).isOk check chain.importBlock(B4).isOk check chain.importBlock(B5).isOk check chain.importBlock(B6).isOk check chain.importBlock(B7).isOk check chain.forkChoice(blk7.blockHash, blk5.blockHash).isOk check com.headHash == blk7.blockHash check chain.latestHash == blk7.blockHash test "newBase == cursor, fork and return to old chain": let com = env.newCom() var chain = newForkedChain(com, com.genesisHeader, baseDistance = 3) check chain.importBlock(blk1).isOk check chain.importBlock(blk2).isOk check chain.importBlock(blk3).isOk check chain.importBlock(blk4).isOk check chain.importBlock(blk5).isOk check chain.importBlock(blk6).isOk check chain.importBlock(blk7).isOk check chain.importBlock(B4).isOk check chain.importBlock(B5).isOk check chain.importBlock(B6).isOk check chain.importBlock(B7).isOk check chain.importBlock(blk4).isOk check chain.forkChoice(blk7.blockHash, blk5.blockHash).isOk check com.headHash == blk7.blockHash check chain.latestHash == blk7.blockHash test "newBase between oldBase and cursor, fork and return to old chain, switch to new chain": let com = env.newCom() var chain = newForkedChain(com, com.genesisHeader, baseDistance = 3) check chain.importBlock(blk1).isOk check chain.importBlock(blk2).isOk check chain.importBlock(blk3).isOk check chain.importBlock(blk4).isOk check chain.importBlock(blk5).isOk check chain.importBlock(blk6).isOk check chain.importBlock(blk7).isOk check chain.importBlock(B4).isOk check chain.importBlock(B5).isOk check chain.importBlock(B6).isOk check chain.importBlock(B7).isOk check chain.importBlock(blk4).isOk check chain.forkChoice(B7.blockHash, B5.blockHash).isOk check com.headHash == B7.blockHash check chain.latestHash == B7.blockHash test "newBase between oldBase and cursor, fork and return to old chain": let com = env.newCom() var chain = newForkedChain(com, com.genesisHeader, baseDistance = 3) check chain.importBlock(blk1).isOk check chain.importBlock(blk2).isOk check chain.importBlock(blk3).isOk check chain.importBlock(blk4).isOk check chain.importBlock(blk5).isOk check chain.importBlock(blk6).isOk check chain.importBlock(blk7).isOk check chain.importBlock(B4).isOk check chain.importBlock(B5).isOk check chain.importBlock(B6).isOk check chain.importBlock(B7).isOk check chain.forkChoice(blk7.blockHash, blk5.blockHash).isOk check com.headHash == blk7.blockHash check chain.latestHash == blk7.blockHash test "headerByNumber": let com = env.newCom() var chain = newForkedChain(com, com.genesisHeader, baseDistance = 3) check chain.importBlock(blk1).isOk check chain.importBlock(blk2).isOk check chain.importBlock(blk3).isOk check chain.importBlock(blk4).isOk check chain.importBlock(blk5).isOk check chain.importBlock(blk6).isOk check chain.importBlock(blk7).isOk check chain.importBlock(B4).isOk check chain.importBlock(B5).isOk check chain.importBlock(B6).isOk check chain.importBlock(B7).isOk check chain.forkChoice(blk7.blockHash, blk5.blockHash).isOk # cursor check chain.headerByNumber(8).isErr check chain.headerByNumber(7).expect("OK").number == 7 check chain.headerByNumber(7).expect("OK").blockHash == blk7.blockHash # from db check chain.headerByNumber(3).expect("OK").number == 3 check chain.headerByNumber(3).expect("OK").blockHash == blk3.blockHash # base check chain.headerByNumber(4).expect("OK").number == 4 check chain.headerByNumber(4).expect("OK").blockHash == blk4.blockHash # from cache check chain.headerByNumber(5).expect("OK").number == 5 check chain.headerByNumber(5).expect("OK").blockHash == blk5.blockHash when isMainModule: forkedChainMain()