erigon-pulse/polygon/bor/spanner.go
battlmonstr 2793ef6ec1
polygon: flatten redundant packages (#9241)
* move mocks to the owner packages
* squash single file packages
* move types to more appropriate files
* remove unused mocks
2024-01-16 09:23:02 +01:00

174 lines
5.1 KiB
Go

package bor
import (
"encoding/hex"
"encoding/json"
"math/big"
"github.com/ledgerwatch/log/v3"
"github.com/ledgerwatch/erigon-lib/chain"
libcommon "github.com/ledgerwatch/erigon-lib/common"
"github.com/ledgerwatch/erigon/consensus"
"github.com/ledgerwatch/erigon/polygon/bor/borcfg"
"github.com/ledgerwatch/erigon/polygon/bor/valset"
"github.com/ledgerwatch/erigon/polygon/heimdall"
"github.com/ledgerwatch/erigon/rlp"
)
//go:generate mockgen -destination=./spanner_mock.go -package=bor . Spanner
type Spanner interface {
GetCurrentSpan(syscall consensus.SystemCall) (*heimdall.Span, error)
GetCurrentValidators(spanId uint64, signer libcommon.Address, chain consensus.ChainHeaderReader) ([]*valset.Validator, error)
GetCurrentProducers(spanId uint64, signer libcommon.Address, chain consensus.ChainHeaderReader) ([]*valset.Validator, error)
CommitSpan(heimdallSpan heimdall.HeimdallSpan, syscall consensus.SystemCall) error
}
type ABI interface {
Pack(name string, args ...interface{}) ([]byte, error)
UnpackIntoInterface(v interface{}, name string, data []byte) error
}
type ChainSpanner struct {
validatorSet ABI
chainConfig *chain.Config
borConfig *borcfg.BorConfig
logger log.Logger
withoutHeimdall bool
}
func NewChainSpanner(validatorSet ABI, chainConfig *chain.Config, withoutHeimdall bool, logger log.Logger) *ChainSpanner {
borConfig := chainConfig.Bor.(*borcfg.BorConfig)
return &ChainSpanner{
validatorSet: validatorSet,
chainConfig: chainConfig,
borConfig: borConfig,
logger: logger,
withoutHeimdall: withoutHeimdall,
}
}
// GetCurrentSpan get current span from contract
func (c *ChainSpanner) GetCurrentSpan(syscall consensus.SystemCall) (*heimdall.Span, error) {
// method
const method = "getCurrentSpan"
data, err := c.validatorSet.Pack(method)
if err != nil {
c.logger.Error("[bor] Unable to pack tx for getCurrentSpan", "error", err)
return nil, err
}
result, err := syscall(libcommon.HexToAddress(c.borConfig.ValidatorContract), data)
if err != nil {
return nil, err
}
// span result
ret := new(struct {
Number *big.Int
StartBlock *big.Int
EndBlock *big.Int
})
if err := c.validatorSet.UnpackIntoInterface(ret, method, result); err != nil {
return nil, err
}
// create new span
span := heimdall.Span{
ID: ret.Number.Uint64(),
StartBlock: ret.StartBlock.Uint64(),
EndBlock: ret.EndBlock.Uint64(),
}
return &span, nil
}
func (c *ChainSpanner) GetCurrentValidators(spanId uint64, signer libcommon.Address, chain consensus.ChainHeaderReader) ([]*valset.Validator, error) {
// Use hardcoded bor devnet valset if chain-name = bor-devnet
if NetworkNameVals[c.chainConfig.ChainName] != nil && c.withoutHeimdall {
return NetworkNameVals[c.chainConfig.ChainName], nil
}
spanBytes := chain.BorSpan(spanId)
var span heimdall.HeimdallSpan
if err := json.Unmarshal(spanBytes, &span); err != nil {
return nil, err
}
return span.ValidatorSet.Validators, nil
}
func (c *ChainSpanner) GetCurrentProducers(spanId uint64, signer libcommon.Address, chain consensus.ChainHeaderReader) ([]*valset.Validator, error) {
// Use hardcoded bor devnet valset if chain-name = bor-devnet
if NetworkNameVals[c.chainConfig.ChainName] != nil && c.withoutHeimdall {
return NetworkNameVals[c.chainConfig.ChainName], nil
}
spanBytes := chain.BorSpan(spanId)
var span heimdall.HeimdallSpan
if err := json.Unmarshal(spanBytes, &span); err != nil {
return nil, err
}
producers := make([]*valset.Validator, len(span.SelectedProducers))
for i := range span.SelectedProducers {
producers[i] = &span.SelectedProducers[i]
}
return producers, nil
}
func (c *ChainSpanner) CommitSpan(heimdallSpan heimdall.HeimdallSpan, syscall consensus.SystemCall) error {
// method
const method = "commitSpan"
// get validators bytes
validators := make([]valset.MinimalVal, 0, len(heimdallSpan.ValidatorSet.Validators))
for _, val := range heimdallSpan.ValidatorSet.Validators {
validators = append(validators, val.MinimalVal())
}
validatorBytes, err := rlp.EncodeToBytes(validators)
if err != nil {
return err
}
// get producers bytes
producers := make([]valset.MinimalVal, 0, len(heimdallSpan.SelectedProducers))
for _, val := range heimdallSpan.SelectedProducers {
producers = append(producers, val.MinimalVal())
}
producerBytes, err := rlp.EncodeToBytes(producers)
if err != nil {
return err
}
c.logger.Debug("[bor] ✅ Committing new span",
"id", heimdallSpan.ID,
"startBlock", heimdallSpan.StartBlock,
"endBlock", heimdallSpan.EndBlock,
"validatorBytes", hex.EncodeToString(validatorBytes),
"producerBytes", hex.EncodeToString(producerBytes),
)
// get packed data
data, err := c.validatorSet.Pack(method,
big.NewInt(0).SetUint64(heimdallSpan.ID),
big.NewInt(0).SetUint64(heimdallSpan.StartBlock),
big.NewInt(0).SetUint64(heimdallSpan.EndBlock),
validatorBytes,
producerBytes,
)
if err != nil {
c.logger.Error("[bor] Unable to pack tx for commitSpan", "error", err)
return err
}
_, err = syscall(libcommon.HexToAddress(c.borConfig.ValidatorContract), data)
return err
}