Skip to content

Commit

Permalink
tortoise: reuse decoded votes (#5009)
Browse files Browse the repository at this point in the history
related: #3006

it also reduced 300MB of used memory on my machine.

ballot signs opinion hash, and provides sidecar to decode that opinion hash. if node decoded one sidecar it can store it in memory
and reuse for all following ballots with the same opinion hash.
  • Loading branch information
dshulyak committed Sep 20, 2023
1 parent 0962268 commit f629581
Show file tree
Hide file tree
Showing 2 changed files with 36 additions and 12 deletions.
6 changes: 5 additions & 1 deletion tortoise/state.go
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,7 @@ func (s *state) layer(lid types.LayerID) *layerInfo {
layer, exist := s.layers[lid]
if !exist {
layersNumber.Inc()
layer = &layerInfo{lid: lid}
layer = &layerInfo{lid: lid, opinions: map[types.Hash32]votes{}}
s.layers[lid] = layer
}
return layer
Expand Down Expand Up @@ -179,6 +179,10 @@ type layerInfo struct {
verifying verifyingInfo
coinflip sign

// unique opinions recorded from the ballots in this layer.
// ballot votes an opinion and encodes sidecar
opinions map[types.Hash32]votes

opinion types.Hash32
// a pointer to the value stored on the previous layerInfo object
// it is stored as a pointer so that when previous layerInfo is evicted
Expand Down
42 changes: 31 additions & 11 deletions tortoise/tortoise.go
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,7 @@ func newTurtle(logger *zap.Logger, config Config) *turtle {
t.layers[genesis] = &layerInfo{
lid: genesis,
hareTerminated: true,
opinions: map[types.Hash32]votes{},
}
t.verifying = newVerifying(config, t.state)
t.full = newFullTortoise(config, t.state)
Expand Down Expand Up @@ -748,11 +749,23 @@ func (t *turtle) decodeBallot(ballot *types.BallotTortoiseData) (*ballotInfo, ty
zap.Uint32("lid", ballot.Layer.Uint32()),
)

votes, min, err := decodeVotes(t.evicted, binfo.layer, base, ballot.Opinion.Votes)
if err != nil {
return nil, 0, err
layer := t.layer(binfo.layer)

existing, exists := layer.opinions[ballot.Opinion.Hash]
var min types.LayerID
if exists {
binfo.votes = existing
} else {
var (
votes votes
err error
)
votes, min, err = decodeVotes(t.evicted, binfo.layer, base, ballot.Opinion.Votes)
if err != nil {
return nil, 0, err
}
binfo.votes = votes
}
binfo.votes = votes
t.logger.Debug("decoded exceptions",
zap.Stringer("block", binfo.id),
zap.Uint32("lid", binfo.layer.Uint32()),
Expand All @@ -771,15 +784,22 @@ func (t *turtle) storeBallot(ballot *ballotInfo, min types.LayerID) error {
}

t.state.addBallot(ballot)
for current := ballot.votes.tail; current != nil && !current.lid.Before(min); current = current.prev {
for i, block := range current.supported {
existing := t.getBlock(block.header())
if existing != nil {
current.supported[i] = existing
} else {
t.addBlock(block)
layer := t.layer(ballot.layer)
existing, exists := layer.opinions[ballot.opinion()]
if exists {
ballot.votes = existing
} else {
for current := ballot.votes.tail; current != nil && !current.lid.Before(min); current = current.prev {
for i, block := range current.supported {
existing := t.getBlock(block.header())
if existing != nil {
current.supported[i] = existing
} else {
t.addBlock(block)
}
}
}
layer.opinions[ballot.opinion()] = ballot.votes
}
if !ballot.layer.After(t.processed) {
if err := t.countBallot(ballot); err != nil {
Expand Down

0 comments on commit f629581

Please sign in to comment.