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),
|
||||
}
|
||||
|
||||
unsigned, err := msg.Serialize()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
sig, err := cg.w.Sign(context.TODO(), cg.banker, unsigned)
|
||||
sig, err := cg.w.Sign(context.TODO(), cg.banker, msg.Cid().Bytes())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
@ -1,7 +1,6 @@
|
||||
package chain
|
||||
|
||||
import (
|
||||
"encoding/base64"
|
||||
"sync"
|
||||
|
||||
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 {
|
||||
data, err := m.Message.Serialize()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
log.Debugf("mpooladd: %s %s", m.Message.From, m.Message.Nonce)
|
||||
|
||||
log.Debugf("mpooladd: %d %s", m.Message.Nonce, base64.StdEncoding.EncodeToString(data))
|
||||
|
||||
if err := m.Signature.Verify(m.Message.From, data); err != nil {
|
||||
if err := m.Signature.Verify(m.Message.From, m.Message.Cid().Bytes()); err != nil {
|
||||
log.Warnf("mpooladd signature verification failed: %s", err)
|
||||
return err
|
||||
}
|
||||
|
@ -14,6 +14,7 @@ import (
|
||||
cbg "github.com/whyrusleeping/cbor-gen"
|
||||
"golang.org/x/xerrors"
|
||||
|
||||
bls "github.com/filecoin-project/go-bls-sigs"
|
||||
"github.com/ipfs/go-cid"
|
||||
hamt "github.com/ipfs/go-hamt-ipld"
|
||||
logging "github.com/ipfs/go-log"
|
||||
@ -233,3 +234,43 @@ func (sm *StateManager) LoadActorState(ctx context.Context, a address.Address, o
|
||||
|
||||
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"
|
||||
"time"
|
||||
|
||||
"github.com/filecoin-project/go-bls-sigs"
|
||||
"github.com/filecoin-project/go-lotus/api"
|
||||
"github.com/filecoin-project/go-lotus/build"
|
||||
"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())
|
||||
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 {
|
||||
if err := checkMsg(m); err != nil {
|
||||
return xerrors.Errorf("block had invalid bls message at index %d: %w", i, err)
|
||||
}
|
||||
|
||||
sigCids = append(sigCids, m.Cid())
|
||||
c := cbg.CborCid(m.Cid())
|
||||
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 {
|
||||
return xerrors.Errorf("failed to build amt from bls msg cids: %w", err)
|
||||
|
||||
if err := syncer.verifyBlsAggregate(h.BLSAggregate, sigCids, pubks); err != nil {
|
||||
return xerrors.Errorf("bls aggregate signature was invalid: %w", err)
|
||||
}
|
||||
|
||||
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 {
|
||||
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())
|
||||
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)
|
||||
if err != nil {
|
||||
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
|
||||
}
|
||||
|
||||
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) {
|
||||
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) {
|
||||
msgbytes, err := msg.Serialize()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
mcid := msg.Cid()
|
||||
|
||||
sig, err := a.WalletSign(ctx, k, msgbytes)
|
||||
sig, err := a.WalletSign(ctx, k, mcid.Bytes())
|
||||
if err != nil {
|
||||
return nil, xerrors.Errorf("failed to sign message: %w", err)
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user