Full BLS Validatition for lightclient update (#5751)

This commit is contained in:
Giulio rebuffo 2022-10-14 20:32:33 +02:00 committed by GitHub
parent 497d414b36
commit f6e7cc4d3e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 61 additions and 91 deletions

View File

@ -7,7 +7,7 @@ import (
"github.com/ledgerwatch/erigon/cmd/lightclient/fork"
"github.com/ledgerwatch/erigon/cmd/lightclient/utils"
"github.com/ledgerwatch/erigon/common"
//"github.com/prysmaticlabs/go-bls"
blst "github.com/supranational/blst/bindings/go"
)
const (
@ -15,7 +15,10 @@ const (
FinalizedRootIndex = 105
)
var DomainSyncCommittee = common.Hex2Bytes("07000000")
var (
DomainSyncCommittee = common.Hex2Bytes("07000000")
dst = []byte("BLS_SIG_BLS12381G2_XMD:SHA-256_SSWU_RO_POP_")
)
func (l *LightClient) validateLegacyUpdate(update *cltypes.LightClientUpdate, finalityUpdate bool) (bool, error) {
if update.SyncAggregate.Sum() < MinSyncCommitteeParticipants {
@ -112,24 +115,23 @@ func (l *LightClient) validateLegacyUpdate(update *cltypes.LightClientUpdate, fi
if err != nil {
return false, err
}
// Create signature objects
/*var signature bls.Sign
if err := signature.Deserialize(update.SyncAggregate.SyncCommiteeSignature[:]); err != nil {
_ = signingRoot
signature, err := utils.SignatureFromBytes(update.SyncAggregate.SyncCommiteeSignature[:])
if err != nil {
return false, err
}
// Aggreggate public keys
var pubKey bls.PublicKey
pks := []*blst.P1Affine{}
for _, key := range pubkeys {
var currPubKey bls.PublicKey
if err := currPubKey.Deserialize(key[:]); err != nil {
pk, err := utils.PublicKeyFromBytes(key[:])
if err != nil {
return false, err
}
pubKey.Add(&currPubKey)
}*/
_ = signingRoot
_ = pubkeys
return true, nil
// return signature.Verify(&pubKey, signingRoot[:]), nil
pks = append(pks, pk)
}
return signature.FastAggregateVerify(true, pks, signingRoot[:], dst), nil
}
func (l *LightClient) validateOptimisticUpdate(update *cltypes.LightClientOptimisticUpdate) (bool, error) {
@ -139,78 +141,3 @@ func (l *LightClient) validateOptimisticUpdate(update *cltypes.LightClientOptimi
func (l *LightClient) validateFinalityUpdate(update *cltypes.LightClientFinalityUpdate) (bool, error) {
return true, nil
}
/*def validate_light_client_update(store: LightClientStore,
update: LightClientUpdate,
current_slot: Slot,
genesis_validators_root: Root) -> None:
# Verify sync committee has sufficient participants
sync_aggregate = update.sync_aggregate
assert sum(sync_aggregate.sync_committee_bits) >= MIN_SYNC_COMMITTEE_PARTICIPANTS
# Verify update does not skip a sync committee period
assert current_slot >= update.signature_slot > update.attested_header.slot >= update.finalized_header.slot
store_period = compute_sync_committee_period_at_slot(store.finalized_header.slot)
update_signature_period = compute_sync_committee_period_at_slot(update.signature_slot)
if is_next_sync_committee_known(store):
assert update_signature_period in (store_period, store_period + 1)
else:
assert update_signature_period == store_period
# Verify update is relevant
update_attested_period = compute_sync_committee_period_at_slot(update.attested_header.slot)
update_has_next_sync_committee = not is_next_sync_committee_known(store) and (
is_sync_committee_update(update) and update_attested_period == store_period
)
assert (
update.attested_header.slot > store.finalized_header.slot
or update_has_next_sync_committee
)
# Verify that the `finality_branch`, if present, confirms `finalized_header`
# to match the finalized checkpoint root saved in the state of `attested_header`.
# Note that the genesis finalized checkpoint root is represented as a zero hash.
if not is_finality_update(update):
assert update.finalized_header == BeaconBlockHeader()
else:
if update.finalized_header.slot == GENESIS_SLOT:
assert update.finalized_header == BeaconBlockHeader()
finalized_root = Bytes32()
else:
finalized_root = hash_tree_root(update.finalized_header)
assert is_valid_merkle_branch(
leaf=finalized_root,
branch=update.finality_branch,
depth=floorlog2(FINALIZED_ROOT_INDEX),
index=get_subtree_index(FINALIZED_ROOT_INDEX),
root=update.attested_header.state_root,
)
# Verify that the `next_sync_committee`, if present, actually is the next sync committee saved in the
# state of the `attested_header`
if not is_sync_committee_update(update):
assert update.next_sync_committee == SyncCommittee()
else:
if update_attested_period == store_period and is_next_sync_committee_known(store):
assert update.next_sync_committee == store.next_sync_committee
assert is_valid_merkle_branch(
leaf=hash_tree_root(update.next_sync_committee),
branch=update.next_sync_committee_branch,
depth=floorlog2(NEXT_SYNC_COMMITTEE_INDEX),
index=get_subtree_index(NEXT_SYNC_COMMITTEE_INDEX),
root=update.attested_header.state_root,
)
# Verify sync committee aggregate signature
if update_signature_period == store_period:
sync_committee = store.current_sync_committee
else:
sync_committee = store.next_sync_committee
participant_pubkeys = [
pubkey for (bit, pubkey) in zip(sync_aggregate.sync_committee_bits, sync_committee.pubkeys)
if bit
]
fork_version = compute_fork_version(compute_epoch_at_slot(update.signature_slot))
domain = compute_domain(DOMAIN_SYNC_COMMITTEE, fork_version, genesis_validators_root)
signing_root = compute_signing_root(update.attested_header, domain)
assert bls.FastAggregateVerify(participant_pubkeys, signing_root, sync_aggregate.sync_committee_signature)*/

View File

@ -32,6 +32,7 @@ var (
const DefaultUri = "https://beaconstate.ethstaker.cc/eth/v2/debug/beacon/states/finalized"
func main() {
ctx := context.Background()
log.Root().SetHandler(log.LvlFilterHandler(log.LvlInfo, log.StderrHandler))
addr := "localhost:7777"

View File

@ -199,7 +199,6 @@ func readUvarint(r io.Reader) (x uint64, err error) {
func DecodeLightClientUpdate(data []byte) (*cltypes.LightClientUpdate, error) {
resp := &cltypes.LightClientUpdate{}
singleLen := resp.SizeSSZ()
fmt.Println(len(data[7:]))
r := bytes.NewReader(data[7:])
sr := snappy.NewReader(r)

View File

@ -15,8 +15,12 @@ package utils
import (
"crypto/sha256"
"errors"
"fmt"
"hash"
"sync"
blst "github.com/supranational/blst/bindings/go"
)
var hasherPool = sync.Pool{
@ -40,3 +44,39 @@ func Keccak256(data []byte) [32]byte {
return b
}
// PublicKeyFromBytes creates a BLS public key from a BigEndian byte slice.
func PublicKeyFromBytes(pubKey []byte) (*blst.P1Affine, error) {
if len(pubKey) != 48 {
return nil, fmt.Errorf("public key must be 48 bytes")
}
// Subgroup check NOT done when decompressing pubkey.
p := new(blst.P1Affine).Uncompress(pubKey)
if p == nil {
return nil, errors.New("could not unmarshal bytes into public key")
}
// Subgroup and infinity check
if !p.KeyValidate() {
return nil, fmt.Errorf("infinite key")
}
return p, nil
}
// SignatureFromBytes creates a BLS signature from a LittleEndian byte slice.
func SignatureFromBytes(sig []byte) (*blst.P2Affine, error) {
if len(sig) != 96 {
return nil, fmt.Errorf("signature must be 96 bytes")
}
signature := new(blst.P2Affine).Uncompress(sig)
if signature == nil {
return nil, errors.New("could not unmarshal bytes into signature")
}
// Group check signature. Do not check for infinity since an aggregated signature
// could be infinite.
if !signature.SigValidate(false) {
return nil, errors.New("signature not in group")
}
return signature, nil
}

1
go.mod
View File

@ -63,6 +63,7 @@ require (
github.com/spf13/cobra v1.5.0
github.com/spf13/pflag v1.0.5
github.com/stretchr/testify v1.8.0
github.com/supranational/blst v0.3.10
github.com/tendermint/go-amino v0.14.1
github.com/tendermint/tendermint v0.31.12
github.com/torquem-ch/mdbx-go v0.26.1

2
go.sum
View File

@ -939,6 +939,8 @@ github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/
github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.8.0 h1:pSgiaMZlXftHpm5L7V1+rVB+AZJydKsMxsQBIJw4PKk=
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
github.com/supranational/blst v0.3.10 h1:CMciDZ/h4pXDDXQASe8ZGTNKUiVNxVVA5hpci2Uuhuk=
github.com/supranational/blst v0.3.10/go.mod h1:jZJtfjgudtNl4en1tzwPIV3KjUnQUvG3/j+w+fVonLw=
github.com/tarm/serial v0.0.0-20180830185346-98f6abe2eb07/go.mod h1:kDXzergiv9cbyO7IOYJZWg1U88JhDg3PB6klq9Hg2pA=
github.com/tendermint/go-amino v0.14.1 h1:o2WudxNfdLNBwMyl2dqOJxiro5rfrEaU0Ugs6offJMk=
github.com/tendermint/go-amino v0.14.1/go.mod h1:i/UKE5Uocn+argJJBb12qTZsCDBcAYMbR92AaJVmKso=