Closed antiochp closed 6 years ago
I think this is explained by - 1) the wallet failing somehow (I think a large tx with many inputs was involved) 2) the wallet failed to store the coinbase output locally 3) subsequent block mined attempted to reuse this coinbase output from the wallet
Figured out how to reproduce this very easily.
-Start new blockchain -Start new wallet.dat -Start waller receiver -Note 'unconfirmed' potential coinbase in wallet -Run miner -Delete wallet.dat -Let miner find block -Duplicate commitment error, as described -Note output with same key appears in wallet, except showing up as 'unspent', even though it should be 'unconfirmed'.
Stopping and restarting grin sometimes gives the same error again, but works after a few attempts
Okay, 'twould appear that the root of this is within in the next_available_key method in the wallet receiver.rs. If you delete the wallet contents.. (or presumably switch to a new wallet.dat file with the same seed after successfully mining a block), the coinbase output gets added as n_child=1.. since the child count is reset, you end up using the same derivation and hence end up with a duplicate key and duplicate coinbase commitment (same amount, same blinding factor), which is rejected by the sumtree...
In other words, if for some reason the next child in your wallet corresponds to an output that's already been accepted by the sumtree (because you've deleted the original potential coinbase or for some reason it was never written to wallet.dat), you won't be able to append the next coinbase transaction to the chain (if you win it), because the same commitment already exists.
thinking about how this should be fixed now.
Right, deleting wallet.dat is not really fair game ;-) I think this should require a restore step, where the wallet scans the chain for existing outputs, presumably using the hashed switch commitments. I think @antiochp had something like that on his list.
That being said, maybe step 1 would be a nicer error message in this case. The miner could maybe check that the coinbase returned by the wallet doesn't exist yet?
That would definitely do it - the wallet has no way of knowing (today) if any keys have previously been used outside of this specific wallet instance.
I think I have seen this without deleting wallet.dat
though (which is more subtle).
All's fair in love and QA :P But I think the easiest way to fix this for now is as you say, instead of vomiting just reject the coinbase in the miner and move on to the next one... and hopefully switch commitment reconstruction will fix the underlying issue.
https://github.com/mimblewimble/grin/pull/266 attempts to move on to the next ID if you delete your wallet.dat file, until it finds a key id that creates a commit that's not already in the sum tree.
Actually just realised it's trivial to restore your coinbase transactions for a given wallet seed from the chain because of this.
Closing this as the wallet restore is tracked separately.
I had a miner fall over with the following error. Not sure what actually caused this - I think I had recently sent a txn, but also possibly restarted this mining node.