-
Notifications
You must be signed in to change notification settings - Fork 286
/
prepare_proposal.go
86 lines (74 loc) · 3.15 KB
/
prepare_proposal.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
package app
import (
"github.com/celestiaorg/celestia-app/pkg/da"
"github.com/celestiaorg/celestia-app/pkg/shares"
abci "github.com/tendermint/tendermint/abci/types"
core "github.com/tendermint/tendermint/proto/tendermint/types"
coretypes "github.com/tendermint/tendermint/types"
)
// PrepareProposal fullfills the celestia-core version of the ABCI interface by
// preparing the proposal block data. The square size is determined by first
// estimating it via the size of the passed block data. Then the included
// MsgWirePayForBlob messages are malleated into MsgPayForBlob messages by
// separating the message and transaction that pays for that message. Lastly,
// this method generates the data root for the proposal block and passes it back
// to tendermint via the blockdata.
func (app *App) PrepareProposal(req abci.RequestPrepareProposal) abci.ResponsePrepareProposal {
// parse the txs, extracting any MsgWirePayForBlob and performing basic
// validation for each transaction. Invalid txs are ignored. Original order
// of the txs is maintained.
parsedTxs := parseTxs(app.txConfig, req.BlockData.Txs)
// estimate the square size. This estimation errors on the side of larger
// squares but can only return values within the min and max square size.
squareSize, totalSharesUsed := estimateSquareSize(parsedTxs, req.BlockData.Evidence)
// the totalSharesUsed can be larger that the max number of shares if we
// reach the max square size. In this case, we must prune the deprioritized
// txs (and their messages if they're pfb txs).
if totalSharesUsed > int(squareSize*squareSize) {
parsedTxs = prune(app.txConfig, parsedTxs, totalSharesUsed, int(squareSize))
}
// in this step we are processing any MsgWirePayForBlob transactions into
// MsgPayForBlob and their respective blobPointers. The malleatedTxs contain the
// the new sdk.Msg with the original tx's metadata (sequence number, gas
// price etc).
processedTxs, blobs, err := malleateTxs(app.txConfig, squareSize, parsedTxs, req.BlockData.Evidence)
if err != nil {
panic(err)
}
blockData := core.Data{
Txs: processedTxs,
Evidence: req.BlockData.Evidence,
Blobs: blobs,
SquareSize: squareSize,
}
coreData, err := coretypes.DataFromProto(&blockData)
if err != nil {
panic(err)
}
dataSquare, err := shares.Split(coreData, true)
if err != nil {
panic(err)
}
// erasure the data square which we use to create the data root.
eds, err := da.ExtendShares(squareSize, shares.ToBytes(dataSquare))
if err != nil {
app.Logger().Error(
"failure to erasure the data square while creating a proposal block",
"error",
err.Error(),
)
panic(err)
}
// create the new data root by creating the data availability header (merkle
// roots of each row and col of the erasure data).
dah := da.NewDataAvailabilityHeader(eds)
// We use the block data struct to pass the square size and calculated data
// root to tendermint.
blockData.Hash = dah.Hash()
blockData.SquareSize = squareSize
// tendermint doesn't need to use any of the erasure data, as only the
// protobuf encoded version of the block data is gossiped.
return abci.ResponsePrepareProposal{
BlockData: &blockData,
}
}