-
Notifications
You must be signed in to change notification settings - Fork 170
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add parsing correct format in btccheckpoint #102
Conversation
KonradStaniec
commented
Aug 22, 2022
•
edited
Loading
edited
- Add parsing op return data in btccheckpoint according to format defined in txformatter (i.e requiring headers and proper linking)
- add tools necessary to generate proper btc transactions (first step toward fuzzing). It was necessary as there are no valid babylon opreturns on any btc chain, therefore we need to generate our own txs for testing.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks great, you put a lot of effort in it! Looks like I missed the previous PR that added the formatter :-/
I only submitted comments where it wasn't obvious what the code was going to do when I first saw it. Maybe some extra comments will help future readers.
// TODO take from config | ||
chaincfg.MainNetParams.PowLimit, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Great, it's almost configurable now! 🏁 @SebastianElvis tests already fail with this error.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
yep making this thingy configurable is next in line :)
lowFee = btcutil.Amount(1) | ||
) | ||
|
||
func standardCoinbaseScript(blockHeight int32, extraNonce uint64) ([]byte, error) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do you have a link for why this is the standard? What is extra nonce?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this the the thing which btcd use when adding coinbase transaction during mining (without the btcd specific coinbase flag CoinbaseFlags = "/P2SH/btcd/"
). I will add comment from code base which look like:
// standardCoinbaseScript returns a standard script suitable for use as the
// signature script of the coinbase transaction of a new block. In particular,
// it starts with the block height that is required by version 2 blocks
Not sure though what the extra nonce is necessary for.
testutil/datagen/btc_transaction.go
Outdated
// opReturnScript returns a provably-pruneable OP_RETURN script with the | ||
// provided data. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What does it mean to be provably pruneable?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this is how, op_return which will not pollute unspent transaction outputs set, should look like.
return script | ||
} | ||
|
||
func solveBlock(header *wire.BlockHeader) bool { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This method could do with a short docstring. What does it mean to solve a block, and what does the return value mean? Only after reading it fully did I see that it modifies the input.
// TODO this will be deterministic without seed but for now it is not that | ||
// important | ||
idx := rand.Uint32() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You mean non-deterministic?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
actually deterministic, as if we do not call rand.Seed(time.now)
or something similar then it will always return the same random number.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks, I learn something new every day about Go :)
testutil/datagen/btc_transaction.go
Outdated
} | ||
|
||
func createSpendTx(spend *spendableOut, fee btcutil.Amount) *wire.MsgTx { | ||
spendTx := wire.NewMsgTx(1) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
1 like a magic number. I see in the docs it's a version; maybe it could be moved next to opTrueScript
?
spendTx.AddTxOut(wire.NewTxOut(int64(spend.amount-fee), | ||
opTrueScript)) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What does this achieve exactly?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
each output need to have some script, and from what I understand this is simplest valid script. We could probably leave it as empty byte array, but that way we closer mirror btc.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks, especially the part that makes PoWLimit configurable! Some minor comments and no blocker from my side.
@@ -358,6 +359,8 @@ func NewBabylonApp( | |||
// from some global config | |||
6, | |||
10, | |||
// TODO take from config | |||
chaincfg.MainNetParams.PowLimit, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do you think making this a module parameter is better? Like EpochInterval
in https://github.com/babylonchain/babylon/blob/main/proto/babylon/epoching/v1/params.proto.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
tbh I am on the fence here. There are two things against having it as module param:
- this is used it btclightclient and btccheckpoint, so i would need to be defined in two modules and kept consisten between them. (or defined in one and shared, not sure this is possible though)
- we are validating pow before including tx in mempool i.e in
ValidateBasic
which does not have access to genesis. (or at least I am not aware how to make it aware of genesis)
Taking both into account I was thinking of making this a global configurable constant similar to how addresss prefixes are global constants which are accesible from every place, even from ValidateBasic
. Downside of this, that it will always need to corrsedpond to btc light client btc genesis header, but I think I can live with it at this moment.
return script | ||
} | ||
|
||
func solveBlock(header *wire.BlockHeader) bool { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Will we try to solve a block when testing Babylon? 😨
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
added docstring that this should be headers with low diff (like from simnet) as otherwise this would take too much time. It necessary as in both btclightclient and btccheckpoint we always validate proof of work of provided headers.
One thing I wanted to mention but forgot is that this check is no longer correct:
Originally when we wanted the two transactions to be connected via UTxO, it made sense that there's the first part, spent into the second, so the block the first one is in must be an ancestor of the second, for them to always be finalized together. Now, however, we don't need this linking, the transactions can go in any order into BTC, as long as they are on the same fork. Say the 1st half has too low fee and only the 2nd half gets included in the ledger. Maybe then the submitter will do it again with a different transaction, same content, but later. So the correct check is now |
Sure makes sense, I will update it to it now. Although I wonder if we cannot just remove |
That sounds correct as well. At least if they are on different forks, they can't both have valid results from the main chain depth method 👍 |