Skip to content

Commit c74827e

Browse files
committed
Implement experimental aggregate signatures
1 parent ebf0851 commit c74827e

File tree

5 files changed

+131
-14
lines changed

5 files changed

+131
-14
lines changed

rolling-shutter/keyperimpl/gnosis/validatorsyncer.go

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -150,7 +150,7 @@ func (v *ValidatorSyncer) filterEvents(
150150
Uint("log-index", event.Raw.Index).
151151
Logger()
152152

153-
msg := new(validatorregistry.RegistrationMessage)
153+
msg := new(validatorregistry.LegacyRegistrationMessage)
154154
err := msg.Unmarshal(event.Message)
155155
if err != nil {
156156
evLog.Warn().
@@ -215,7 +215,7 @@ func (v *ValidatorSyncer) filterEvents(
215215
func (v *ValidatorSyncer) insertEvents(ctx context.Context, tx pgx.Tx, events []*validatorRegistryBindings.ValidatorregistryUpdated) error {
216216
db := database.New(tx)
217217
for _, event := range events {
218-
msg := new(validatorregistry.RegistrationMessage)
218+
msg := new(validatorregistry.LegacyRegistrationMessage)
219219
err := msg.Unmarshal(event.Message)
220220
if err != nil {
221221
return errors.Wrap(err, "failed to unmarshal registration message")
@@ -237,7 +237,7 @@ func (v *ValidatorSyncer) insertEvents(ctx context.Context, tx pgx.Tx, events []
237237
}
238238

239239
func checkStaticRegistrationMessageFields(
240-
msg *validatorregistry.RegistrationMessage,
240+
msg *validatorregistry.LegacyRegistrationMessage,
241241
chainID uint64,
242242
validatorRegistryAddress common.Address,
243243
logger zerolog.Logger,
Lines changed: 34 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,50 @@
11
package validatorregistry
22

33
import (
4+
"fmt"
5+
46
"github.com/ethereum/go-ethereum/crypto"
57
blst "github.com/supranational/blst/bindings/go"
68
)
79

810
var dst = []byte("BLS_SIG_BLS12381G2_XMD:SHA-256_SSWU_RO_POP_")
911

10-
func VerifySignature(sig *blst.P2Affine, pubkey *blst.P1Affine, msg *RegistrationMessage) bool {
12+
func VerifyAggregateSignature(sig *blst.P2Affine, pks []*blst.P1Affine, msg *AggregateRegistrationMessage) bool {
13+
if msg.Version < 1 {
14+
return false
15+
}
16+
if len(pks) != int(msg.Count) {
17+
fmt.Println(len(pks), int(msg.Count))
18+
return false
19+
}
20+
msgHash := crypto.Keccak256(msg.Marshal())
21+
msgs := make([][]byte, len(pks))
22+
for i := range pks {
23+
msgs[i] = msgHash
24+
}
25+
return sig.AggregateVerify(true, pks, true, msgs, dst)
26+
}
27+
28+
func VerifySignature(sig *blst.P2Affine, pubkey *blst.P1Affine, msg *LegacyRegistrationMessage) bool {
1129
msgHash := crypto.Keccak256(msg.Marshal())
1230
return sig.Verify(true, pubkey, true, msgHash, dst)
1331
}
1432

15-
func CreateSignature(sk *blst.SecretKey, msg *RegistrationMessage) *blst.P2Affine {
33+
func CreateAggregateSignature(sks []*blst.SecretKey, msg *AggregateRegistrationMessage) *blst.P2Affine {
34+
msgHash := crypto.Keccak256(msg.Marshal())
35+
aggregate := new(blst.P2Aggregate)
36+
for _, sk := range sks {
37+
aff := new(blst.P2Affine)
38+
sig := aff.Sign(sk, msgHash, dst)
39+
ok := aggregate.Add(sig, true)
40+
if !ok {
41+
panic("failure")
42+
}
43+
}
44+
return aggregate.ToAffine()
45+
}
46+
47+
func CreateSignature(sk *blst.SecretKey, msg *LegacyRegistrationMessage) *blst.P2Affine {
1648
msgHash := crypto.Keccak256(msg.Marshal())
1749
return new(blst.P2Affine).Sign(sk, msgHash, dst)
1850
}

rolling-shutter/medley/validatorregistry/signature_test.go

Lines changed: 32 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ import (
99
)
1010

1111
func TestSignature(t *testing.T) {
12-
msg := &RegistrationMessage{
12+
msg := &LegacyRegistrationMessage{
1313
Version: 1,
1414
ChainID: 2,
1515
ValidatorRegistryAddress: common.HexToAddress("0x1234567890123456789012345678901234567890"),
@@ -30,3 +30,34 @@ func TestSignature(t *testing.T) {
3030
check = VerifySignature(sig, pubkey, msg)
3131
assert.False(t, check)
3232
}
33+
34+
func TestAggSignature(t *testing.T) {
35+
msg := &AggregateRegistrationMessage{
36+
Version: 1,
37+
ChainID: 2,
38+
ValidatorRegistryAddress: common.HexToAddress("0x1234567890123456789012345678901234567890"),
39+
ValidatorIndex: 3,
40+
Nonce: 4,
41+
Count: 2,
42+
IsRegistration: true,
43+
}
44+
45+
var ikm [32]byte
46+
var sks []*blst.SecretKey
47+
var pks []*blst.P1Affine
48+
for i := 0; i < int(msg.Count); i++ {
49+
50+
privkey := blst.KeyGen(ikm[:])
51+
pubkey := new(blst.P1Affine).From(privkey)
52+
sks = append(sks, privkey)
53+
pks = append(pks, pubkey)
54+
}
55+
56+
sig := CreateAggregateSignature(sks, msg)
57+
check := VerifyAggregateSignature(sig, pks, msg)
58+
assert.True(t, check)
59+
60+
msg.IsRegistration = false
61+
check = VerifyAggregateSignature(sig, pks, msg)
62+
assert.False(t, check)
63+
}

rolling-shutter/medley/validatorregistry/validatorregistry.go

Lines changed: 57 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,61 @@ import (
77
"github.com/ethereum/go-ethereum/common"
88
)
99

10-
type RegistrationMessage struct {
10+
type RegistrationMessage interface {
11+
Marshal() []byte
12+
Unmarshal(b []byte) error
13+
}
14+
15+
type AggregateRegistrationMessage struct {
16+
Version uint8
17+
ChainID uint64
18+
ValidatorRegistryAddress common.Address
19+
ValidatorIndex uint64
20+
Nonce uint32
21+
Count uint32
22+
IsRegistration bool
23+
}
24+
25+
func (m *AggregateRegistrationMessage) Marshal() []byte {
26+
b := make([]byte, 0)
27+
b = append(b, m.Version)
28+
b = binary.BigEndian.AppendUint64(b, m.ChainID)
29+
b = append(b, m.ValidatorRegistryAddress.Bytes()...)
30+
b = binary.BigEndian.AppendUint64(b, m.ValidatorIndex)
31+
b = binary.BigEndian.AppendUint32(b, m.Nonce)
32+
b = binary.BigEndian.AppendUint32(b, m.Count)
33+
if m.IsRegistration {
34+
b = append(b, 1)
35+
} else {
36+
b = append(b, 0)
37+
}
38+
return b
39+
}
40+
41+
func (m *AggregateRegistrationMessage) Unmarshal(b []byte) error {
42+
expectedLength := 1 + 8 + 20 + 8 + 8 + 1
43+
if len(b) != expectedLength {
44+
return fmt.Errorf("invalid registration message length %d, expected %d", len(b), expectedLength)
45+
}
46+
47+
m.Version = b[0]
48+
m.ChainID = binary.BigEndian.Uint64(b[1:9])
49+
m.ValidatorRegistryAddress = common.BytesToAddress(b[9:29])
50+
m.ValidatorIndex = binary.BigEndian.Uint64(b[29:37])
51+
m.Nonce = binary.BigEndian.Uint32(b[37:41])
52+
m.Count = binary.BigEndian.Uint32(b[41:45])
53+
switch b[45] {
54+
case 0:
55+
m.IsRegistration = false
56+
case 1:
57+
m.IsRegistration = true
58+
default:
59+
return fmt.Errorf("invalid registration message type byte %d", b[45])
60+
}
61+
return nil
62+
}
63+
64+
type LegacyRegistrationMessage struct {
1165
Version uint8
1266
ChainID uint64
1367
ValidatorRegistryAddress common.Address
@@ -16,7 +70,7 @@ type RegistrationMessage struct {
1670
IsRegistration bool
1771
}
1872

19-
func (m *RegistrationMessage) Marshal() []byte {
73+
func (m *LegacyRegistrationMessage) Marshal() []byte {
2074
b := make([]byte, 0)
2175
b = append(b, m.Version)
2276
b = binary.BigEndian.AppendUint64(b, m.ChainID)
@@ -31,7 +85,7 @@ func (m *RegistrationMessage) Marshal() []byte {
3185
return b
3286
}
3387

34-
func (m *RegistrationMessage) Unmarshal(b []byte) error {
88+
func (m *LegacyRegistrationMessage) Unmarshal(b []byte) error {
3589
expectedLength := 1 + 8 + 20 + 8 + 8 + 1
3690
if len(b) != expectedLength {
3791
return fmt.Errorf("invalid registration message length %d, expected %d", len(b), expectedLength)

rolling-shutter/medley/validatorregistry/validatorregistry_test.go

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ import (
99
)
1010

1111
func TestRegistrationMessageMarshalRoundtrip(t *testing.T) {
12-
m := &RegistrationMessage{
12+
m := &LegacyRegistrationMessage{
1313
Version: 1,
1414
ChainID: 2,
1515
ValidatorRegistryAddress: common.HexToAddress("0x1234567890123456789012345678901234567890"),
@@ -18,30 +18,30 @@ func TestRegistrationMessageMarshalRoundtrip(t *testing.T) {
1818
IsRegistration: true,
1919
}
2020
marshaled := m.Marshal()
21-
unmarshaled := new(RegistrationMessage)
21+
unmarshaled := new(LegacyRegistrationMessage)
2222
err := unmarshaled.Unmarshal(marshaled)
2323
assert.NilError(t, err)
2424
assert.DeepEqual(t, m, unmarshaled)
2525
}
2626

2727
func TestRegistrationMessageInvalidUnmarshal(t *testing.T) {
2828
base := bytes.Repeat([]byte{0}, 46)
29-
assert.NilError(t, new(RegistrationMessage).Unmarshal(base))
29+
assert.NilError(t, new(LegacyRegistrationMessage).Unmarshal(base))
3030

3131
for _, b := range [][]byte{
3232
{},
3333
bytes.Repeat([]byte{0}, 45),
3434
bytes.Repeat([]byte{0}, 47),
3535
bytes.Repeat([]byte{0}, 92),
3636
} {
37-
err := new(RegistrationMessage).Unmarshal(b)
37+
err := new(LegacyRegistrationMessage).Unmarshal(b)
3838
assert.ErrorContains(t, err, "invalid registration message length")
3939
}
4040

4141
for _, isRegistrationByte := range []byte{2, 3, 255} {
4242
b := bytes.Repeat([]byte{0}, 46)
4343
b[45] = isRegistrationByte
44-
err := new(RegistrationMessage).Unmarshal(b)
44+
err := new(LegacyRegistrationMessage).Unmarshal(b)
4545
assert.ErrorContains(t, err, "invalid registration message type byte")
4646
}
4747
}

0 commit comments

Comments
 (0)