Merge pull request #296 from filecoin-project/feat/verify-block-msg-signatures
Feat/verify block msg signatures
This commit is contained in:
commit
b8bc54fd5b
@ -336,12 +336,7 @@ func (cg *ChainGen) getRandomMessages() ([]*types.SignedMessage, error) {
|
|||||||
GasPrice: types.NewInt(0),
|
GasPrice: types.NewInt(0),
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned, err := msg.Serialize()
|
sig, err := cg.w.Sign(context.TODO(), cg.banker, msg.Cid().Bytes())
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
sig, err := cg.w.Sign(context.TODO(), cg.banker, unsigned)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
@ -1,7 +1,6 @@
|
|||||||
package chain
|
package chain
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"encoding/base64"
|
|
||||||
"sync"
|
"sync"
|
||||||
|
|
||||||
pubsub "github.com/libp2p/go-libp2p-pubsub"
|
pubsub "github.com/libp2p/go-libp2p-pubsub"
|
||||||
@ -82,14 +81,9 @@ func (mp *MessagePool) Add(m *types.SignedMessage) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (mp *MessagePool) addLocked(m *types.SignedMessage) error {
|
func (mp *MessagePool) addLocked(m *types.SignedMessage) error {
|
||||||
data, err := m.Message.Serialize()
|
log.Debugf("mpooladd: %s %s", m.Message.From, m.Message.Nonce)
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
log.Debugf("mpooladd: %d %s", m.Message.Nonce, base64.StdEncoding.EncodeToString(data))
|
if err := m.Signature.Verify(m.Message.From, m.Message.Cid().Bytes()); err != nil {
|
||||||
|
|
||||||
if err := m.Signature.Verify(m.Message.From, data); err != nil {
|
|
||||||
log.Warnf("mpooladd signature verification failed: %s", err)
|
log.Warnf("mpooladd signature verification failed: %s", err)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -14,6 +14,7 @@ import (
|
|||||||
cbg "github.com/whyrusleeping/cbor-gen"
|
cbg "github.com/whyrusleeping/cbor-gen"
|
||||||
"golang.org/x/xerrors"
|
"golang.org/x/xerrors"
|
||||||
|
|
||||||
|
bls "github.com/filecoin-project/go-bls-sigs"
|
||||||
"github.com/ipfs/go-cid"
|
"github.com/ipfs/go-cid"
|
||||||
hamt "github.com/ipfs/go-hamt-ipld"
|
hamt "github.com/ipfs/go-hamt-ipld"
|
||||||
logging "github.com/ipfs/go-log"
|
logging "github.com/ipfs/go-log"
|
||||||
@ -233,3 +234,43 @@ func (sm *StateManager) LoadActorState(ctx context.Context, a address.Address, o
|
|||||||
|
|
||||||
return act, nil
|
return act, nil
|
||||||
}
|
}
|
||||||
|
func (sm *StateManager) ResolveToKeyAddress(ctx context.Context, addr address.Address, ts *types.TipSet) (address.Address, error) {
|
||||||
|
switch addr.Protocol() {
|
||||||
|
case address.BLS, address.SECP256K1:
|
||||||
|
return addr, nil
|
||||||
|
case address.Actor:
|
||||||
|
return address.Undef, xerrors.New("cannot resolve actor address to key address")
|
||||||
|
default:
|
||||||
|
}
|
||||||
|
|
||||||
|
if ts == nil {
|
||||||
|
ts = sm.cs.GetHeaviestTipSet()
|
||||||
|
}
|
||||||
|
|
||||||
|
st, _, err := sm.TipSetState(ts)
|
||||||
|
if err != nil {
|
||||||
|
return address.Undef, xerrors.Errorf("resolve address failed to get tipset state: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
cst := hamt.CSTFromBstore(sm.cs.Blockstore())
|
||||||
|
tree, err := state.LoadStateTree(cst, st)
|
||||||
|
if err != nil {
|
||||||
|
return address.Undef, xerrors.Errorf("failed to load state tree")
|
||||||
|
}
|
||||||
|
|
||||||
|
return vm.ResolveToKeyAddr(tree, cst, addr)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (sm *StateManager) GetBlsPublicKey(ctx context.Context, addr address.Address, ts *types.TipSet) (pubk bls.PublicKey, err error) {
|
||||||
|
kaddr, err := sm.ResolveToKeyAddress(ctx, addr, ts)
|
||||||
|
if err != nil {
|
||||||
|
return pubk, xerrors.Errorf("failed to resolve address to key address: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if kaddr.Protocol() != address.BLS {
|
||||||
|
return pubk, xerrors.Errorf("address must be BLS address to load bls public key")
|
||||||
|
}
|
||||||
|
|
||||||
|
copy(pubk[:], kaddr.Payload())
|
||||||
|
return pubk, nil
|
||||||
|
}
|
||||||
|
@ -6,6 +6,7 @@ import (
|
|||||||
"sync"
|
"sync"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"github.com/filecoin-project/go-bls-sigs"
|
||||||
"github.com/filecoin-project/go-lotus/api"
|
"github.com/filecoin-project/go-lotus/api"
|
||||||
"github.com/filecoin-project/go-lotus/build"
|
"github.com/filecoin-project/go-lotus/build"
|
||||||
"github.com/filecoin-project/go-lotus/chain/actors"
|
"github.com/filecoin-project/go-lotus/chain/actors"
|
||||||
@ -520,16 +521,28 @@ func (syncer *Syncer) ValidateBlock(ctx context.Context, b *types.FullBlock) err
|
|||||||
|
|
||||||
bs := amt.WrapBlockstore(syncer.store.Blockstore())
|
bs := amt.WrapBlockstore(syncer.store.Blockstore())
|
||||||
var blsCids []cbg.CBORMarshaler
|
var blsCids []cbg.CBORMarshaler
|
||||||
|
var sigCids []cid.Cid // this is what we get for people not wanting the marshalcbor method on the cid type
|
||||||
|
|
||||||
|
var pubks []bls.PublicKey
|
||||||
for i, m := range b.BlsMessages {
|
for i, m := range b.BlsMessages {
|
||||||
if err := checkMsg(m); err != nil {
|
if err := checkMsg(m); err != nil {
|
||||||
return xerrors.Errorf("block had invalid bls message at index %d: %w", i, err)
|
return xerrors.Errorf("block had invalid bls message at index %d: %w", i, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
sigCids = append(sigCids, m.Cid())
|
||||||
c := cbg.CborCid(m.Cid())
|
c := cbg.CborCid(m.Cid())
|
||||||
blsCids = append(blsCids, &c)
|
blsCids = append(blsCids, &c)
|
||||||
|
|
||||||
|
pubk, err := syncer.sm.GetBlsPublicKey(ctx, m.From, baseTs)
|
||||||
|
if err != nil {
|
||||||
|
return xerrors.Errorf("failed to load bls public to validate block: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
pubks = append(pubks, pubk)
|
||||||
}
|
}
|
||||||
bmroot, err := amt.FromArray(bs, blsCids)
|
|
||||||
if err != nil {
|
if err := syncer.verifyBlsAggregate(h.BLSAggregate, sigCids, pubks); err != nil {
|
||||||
return xerrors.Errorf("failed to build amt from bls msg cids: %w", err)
|
return xerrors.Errorf("bls aggregate signature was invalid: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
var secpkCids []cbg.CBORMarshaler
|
var secpkCids []cbg.CBORMarshaler
|
||||||
@ -537,9 +550,25 @@ func (syncer *Syncer) ValidateBlock(ctx context.Context, b *types.FullBlock) err
|
|||||||
if err := checkMsg(&m.Message); err != nil {
|
if err := checkMsg(&m.Message); err != nil {
|
||||||
return xerrors.Errorf("block had invalid secpk message at index %d: %w", i, err)
|
return xerrors.Errorf("block had invalid secpk message at index %d: %w", i, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
kaddr, err := syncer.sm.ResolveToKeyAddress(ctx, m.Message.From, baseTs)
|
||||||
|
if err != nil {
|
||||||
|
return xerrors.Errorf("failed to resolve key addr: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := m.Signature.Verify(kaddr, m.Message.Cid().Bytes()); err != nil {
|
||||||
|
return xerrors.Errorf("secpk message %s has invalid signature: %w", m.Cid(), err)
|
||||||
|
}
|
||||||
|
|
||||||
c := cbg.CborCid(m.Cid())
|
c := cbg.CborCid(m.Cid())
|
||||||
secpkCids = append(secpkCids, &c)
|
secpkCids = append(secpkCids, &c)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bmroot, err := amt.FromArray(bs, blsCids)
|
||||||
|
if err != nil {
|
||||||
|
return xerrors.Errorf("failed to build amt from bls msg cids: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
smroot, err := amt.FromArray(bs, secpkCids)
|
smroot, err := amt.FromArray(bs, secpkCids)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return xerrors.Errorf("failed to build amt from bls msg cids: %w", err)
|
return xerrors.Errorf("failed to build amt from bls msg cids: %w", err)
|
||||||
@ -560,6 +589,21 @@ func (syncer *Syncer) ValidateBlock(ctx context.Context, b *types.FullBlock) err
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (syncer *Syncer) verifyBlsAggregate(sig types.Signature, msgs []cid.Cid, pubks []bls.PublicKey) error {
|
||||||
|
var digests []bls.Digest
|
||||||
|
for _, c := range msgs {
|
||||||
|
digests = append(digests, bls.Hash(bls.Message(c.Bytes())))
|
||||||
|
}
|
||||||
|
|
||||||
|
var bsig bls.Signature
|
||||||
|
copy(bsig[:], sig.Data)
|
||||||
|
if !bls.Verify(bsig, digests, pubks) {
|
||||||
|
return xerrors.New("bls aggregate signature failed to verify")
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
func (syncer *Syncer) collectHeaders(ctx context.Context, from *types.TipSet, to *types.TipSet) ([]*types.TipSet, error) {
|
func (syncer *Syncer) collectHeaders(ctx context.Context, from *types.TipSet, to *types.TipSet) ([]*types.TipSet, error) {
|
||||||
blockSet := []*types.TipSet{from}
|
blockSet := []*types.TipSet{from}
|
||||||
|
|
||||||
|
@ -40,12 +40,9 @@ func (a *WalletAPI) WalletSign(ctx context.Context, k address.Address, msg []byt
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (a *WalletAPI) WalletSignMessage(ctx context.Context, k address.Address, msg *types.Message) (*types.SignedMessage, error) {
|
func (a *WalletAPI) WalletSignMessage(ctx context.Context, k address.Address, msg *types.Message) (*types.SignedMessage, error) {
|
||||||
msgbytes, err := msg.Serialize()
|
mcid := msg.Cid()
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
sig, err := a.WalletSign(ctx, k, msgbytes)
|
sig, err := a.WalletSign(ctx, k, mcid.Bytes())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, xerrors.Errorf("failed to sign message: %w", err)
|
return nil, xerrors.Errorf("failed to sign message: %w", err)
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user