I just analysed the reasons for why my pool minted an orphaned block.
Here is the sequence of events:
My pool minted block No=1 in its allocated slot=28 at T=28.050 seconds. This block propagated across the network and was received by other, not directly connected, relays within 1 second (ie. by T=29 seconds).
My pool and other relays received block No=0 which was generated in slot=0 at T=30s. This block is 30 seconds delayed; it arrived 30 seconds after it was produced at T=30. However, this block predates my block and contains transactions which my block included. This results in the cardano node switching tip to this block No=0 and invalidating my block.
So here is the problem:
Lets say I wanted to increase my stake pool rewards.
Every time my pool is due to mint a block I could disconnect my relays from the block producer. Then wait for the block to be minted and wait another 30 seconds or more. Then connect my relays to the block producer. The relays would then pull the freshly minted block and other connected nodes would in turn pull the minted block and it would propagate across the network. The net result is a block delayed by 30 seconds or more.
Any other pools that mint a block during this 30 second or more window of time will get their blocks invalidated.
Thus selfish mining / denial of service on Cardano ??????????
Timestamp seconds are actual values and last 2 digits of block and slot numbers are also actual values.
... xx:xx:45 cardano-node: TraceNodeIsLeader xx:xx:45 cardano-node: block String "yyyy" Number 48 blockPrev "wwww" xx:xx:45 cardano-node: Chain extended, new tip:yyyy at slot 74 xx:xx:45 cardano-node: TraceAdoptedBlock xx:xx:45 cncli-sync: block 48 of 48, 100.00% synced xx:xx:46 cardano-node: TraceNodeNotLeader xx:xx:47 cardano-node: TraceNodeNotLeader xx:xx:47 cardano-node: BlockFetchDecision SlotNo 45 blockPointHash = zzzz xx:xx:47 cardano-node: Block fits onto some fork: xxxx at slot 45 xx:xx:47 cncli-sync rollback to slot 19 xx:xx:47 cardano-node: Valid candidate xxxx at slot 45 xx:xx:47 cardano-node: Switched to a fork, new tip xxxx at slot 45 xx:xx:47 cardano-node: Ignoring block already in DB: xxxx at slot 45 xx:xx:47 cncli-sync block 48 of 48, 100.00% synced xx:xx:48 cardano-node: TraceNodeNotLeader xx:xx:49 cardano-node: TraceNodeNotLeader ...
Note that my block was produced at time = 45 seconds for slot = 74. The delayed block was produced 29 seconds before this (at time = 16 seconds) for slot = 45 but was received at time = 47 seconds.
Upon receiving this delayed block, the cardano-node rolls back to the block prior to this delayed block (block at slot = 19) and then adds the delayed block for slot = 45.
Now my block for slot 74 is invalid - presumably because it contains transactions that were in the delayed block and it has the same block number of 48.
Note: Cardano slots occur every 1 second.
Immediately after seeing these logs I did the following cncli query:
cncli validate --db db/cncli.db --hash yyyy
My block is orphaned!
cncli database records:
select id, block_number, slot_number, hash, orphaned from chain where block_number > 40 and block_number < 52;
id|block_number|slot_number|hash|orphaned 35| 46| xx|vvvv|0 36| 47| 19|wwww|0 37| 48| 74|yyyy|1 38| 48| 45|xxxx|0 39| 49| xx|zzzz|0 40| 50| xx|aaaa|0 41| 51| xx|bbbb|0