[wip] integrate DKG and DSS

This commit is contained in:
Roy Crihfield 2025-01-18 11:55:22 +08:00
parent fa9a7dfbad
commit 01204261b7
28 changed files with 1202 additions and 196 deletions

View File

@ -426,7 +426,7 @@ func (x *fastReflection_Params) ProtoMethods() *protoiface.Methods {
var (
md_Participant protoreflect.MessageDescriptor
fd_Participant_cosmos_address protoreflect.FieldDescriptor
fd_Participant_nitro_address protoreflect.FieldDescriptor
fd_Participant_public_key protoreflect.FieldDescriptor
fd_Participant_role protoreflect.FieldDescriptor
fd_Participant_kyc_id protoreflect.FieldDescriptor
)
@ -435,7 +435,7 @@ func init() {
file_cerc_onboarding_v1_onboarding_proto_init()
md_Participant = File_cerc_onboarding_v1_onboarding_proto.Messages().ByName("Participant")
fd_Participant_cosmos_address = md_Participant.Fields().ByName("cosmos_address")
fd_Participant_nitro_address = md_Participant.Fields().ByName("nitro_address")
fd_Participant_public_key = md_Participant.Fields().ByName("public_key")
fd_Participant_role = md_Participant.Fields().ByName("role")
fd_Participant_kyc_id = md_Participant.Fields().ByName("kyc_id")
}
@ -511,9 +511,9 @@ func (x *fastReflection_Participant) Range(f func(protoreflect.FieldDescriptor,
return
}
}
if x.NitroAddress != "" {
value := protoreflect.ValueOfString(x.NitroAddress)
if !f(fd_Participant_nitro_address, value) {
if len(x.PublicKey) != 0 {
value := protoreflect.ValueOfBytes(x.PublicKey)
if !f(fd_Participant_public_key, value) {
return
}
}
@ -546,8 +546,8 @@ func (x *fastReflection_Participant) Has(fd protoreflect.FieldDescriptor) bool {
switch fd.FullName() {
case "cerc.onboarding.v1.Participant.cosmos_address":
return x.CosmosAddress != ""
case "cerc.onboarding.v1.Participant.nitro_address":
return x.NitroAddress != ""
case "cerc.onboarding.v1.Participant.public_key":
return len(x.PublicKey) != 0
case "cerc.onboarding.v1.Participant.role":
return x.Role != ""
case "cerc.onboarding.v1.Participant.kyc_id":
@ -570,8 +570,8 @@ func (x *fastReflection_Participant) Clear(fd protoreflect.FieldDescriptor) {
switch fd.FullName() {
case "cerc.onboarding.v1.Participant.cosmos_address":
x.CosmosAddress = ""
case "cerc.onboarding.v1.Participant.nitro_address":
x.NitroAddress = ""
case "cerc.onboarding.v1.Participant.public_key":
x.PublicKey = nil
case "cerc.onboarding.v1.Participant.role":
x.Role = ""
case "cerc.onboarding.v1.Participant.kyc_id":
@ -595,9 +595,9 @@ func (x *fastReflection_Participant) Get(descriptor protoreflect.FieldDescriptor
case "cerc.onboarding.v1.Participant.cosmos_address":
value := x.CosmosAddress
return protoreflect.ValueOfString(value)
case "cerc.onboarding.v1.Participant.nitro_address":
value := x.NitroAddress
return protoreflect.ValueOfString(value)
case "cerc.onboarding.v1.Participant.public_key":
value := x.PublicKey
return protoreflect.ValueOfBytes(value)
case "cerc.onboarding.v1.Participant.role":
value := x.Role
return protoreflect.ValueOfString(value)
@ -626,8 +626,8 @@ func (x *fastReflection_Participant) Set(fd protoreflect.FieldDescriptor, value
switch fd.FullName() {
case "cerc.onboarding.v1.Participant.cosmos_address":
x.CosmosAddress = value.Interface().(string)
case "cerc.onboarding.v1.Participant.nitro_address":
x.NitroAddress = value.Interface().(string)
case "cerc.onboarding.v1.Participant.public_key":
x.PublicKey = value.Bytes()
case "cerc.onboarding.v1.Participant.role":
x.Role = value.Interface().(string)
case "cerc.onboarding.v1.Participant.kyc_id":
@ -654,8 +654,8 @@ func (x *fastReflection_Participant) Mutable(fd protoreflect.FieldDescriptor) pr
switch fd.FullName() {
case "cerc.onboarding.v1.Participant.cosmos_address":
panic(fmt.Errorf("field cosmos_address of message cerc.onboarding.v1.Participant is not mutable"))
case "cerc.onboarding.v1.Participant.nitro_address":
panic(fmt.Errorf("field nitro_address of message cerc.onboarding.v1.Participant is not mutable"))
case "cerc.onboarding.v1.Participant.public_key":
panic(fmt.Errorf("field public_key of message cerc.onboarding.v1.Participant is not mutable"))
case "cerc.onboarding.v1.Participant.role":
panic(fmt.Errorf("field role of message cerc.onboarding.v1.Participant is not mutable"))
case "cerc.onboarding.v1.Participant.kyc_id":
@ -675,8 +675,8 @@ func (x *fastReflection_Participant) NewField(fd protoreflect.FieldDescriptor) p
switch fd.FullName() {
case "cerc.onboarding.v1.Participant.cosmos_address":
return protoreflect.ValueOfString("")
case "cerc.onboarding.v1.Participant.nitro_address":
return protoreflect.ValueOfString("")
case "cerc.onboarding.v1.Participant.public_key":
return protoreflect.ValueOfBytes(nil)
case "cerc.onboarding.v1.Participant.role":
return protoreflect.ValueOfString("")
case "cerc.onboarding.v1.Participant.kyc_id":
@ -754,7 +754,7 @@ func (x *fastReflection_Participant) ProtoMethods() *protoiface.Methods {
if l > 0 {
n += 1 + l + runtime.Sov(uint64(l))
}
l = len(x.NitroAddress)
l = len(x.PublicKey)
if l > 0 {
n += 1 + l + runtime.Sov(uint64(l))
}
@ -809,10 +809,10 @@ func (x *fastReflection_Participant) ProtoMethods() *protoiface.Methods {
i--
dAtA[i] = 0x1a
}
if len(x.NitroAddress) > 0 {
i -= len(x.NitroAddress)
copy(dAtA[i:], x.NitroAddress)
i = runtime.EncodeVarint(dAtA, i, uint64(len(x.NitroAddress)))
if len(x.PublicKey) > 0 {
i -= len(x.PublicKey)
copy(dAtA[i:], x.PublicKey)
i = runtime.EncodeVarint(dAtA, i, uint64(len(x.PublicKey)))
i--
dAtA[i] = 0x12
}
@ -906,9 +906,9 @@ func (x *fastReflection_Participant) ProtoMethods() *protoiface.Methods {
iNdEx = postIndex
case 2:
if wireType != 2 {
return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, fmt.Errorf("proto: wrong wireType = %d for field NitroAddress", wireType)
return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, fmt.Errorf("proto: wrong wireType = %d for field PublicKey", wireType)
}
var stringLen uint64
var byteLen int
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, runtime.ErrIntOverflow
@ -918,23 +918,25 @@ func (x *fastReflection_Participant) ProtoMethods() *protoiface.Methods {
}
b := dAtA[iNdEx]
iNdEx++
stringLen |= uint64(b&0x7F) << shift
byteLen |= int(b&0x7F) << shift
if b < 0x80 {
break
}
}
intStringLen := int(stringLen)
if intStringLen < 0 {
if byteLen < 0 {
return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, runtime.ErrInvalidLength
}
postIndex := iNdEx + intStringLen
postIndex := iNdEx + byteLen
if postIndex < 0 {
return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, runtime.ErrInvalidLength
}
if postIndex > l {
return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, io.ErrUnexpectedEOF
}
x.NitroAddress = string(dAtA[iNdEx:postIndex])
x.PublicKey = append(x.PublicKey[:0], dAtA[iNdEx:postIndex]...)
if x.PublicKey == nil {
x.PublicKey = []byte{}
}
iNdEx = postIndex
case 3:
if wireType != 2 {
@ -1577,8 +1579,8 @@ type Participant struct {
// participant's cosmos (laconic) address
CosmosAddress string `protobuf:"bytes,1,opt,name=cosmos_address,json=cosmosAddress,proto3" json:"cosmos_address,omitempty"`
// participant's Nitro address
NitroAddress string `protobuf:"bytes,2,opt,name=nitro_address,json=nitroAddress,proto3" json:"nitro_address,omitempty"`
// full public key used to derive participant's Nitro address
PublicKey []byte `protobuf:"bytes,2,opt,name=public_key,json=publicKey,proto3" json:"public_key,omitempty"`
// participant's role (participant | validator)
Role string `protobuf:"bytes,3,opt,name=role,proto3" json:"role,omitempty"`
// participant's KYC receipt ID
@ -1612,11 +1614,11 @@ func (x *Participant) GetCosmosAddress() string {
return ""
}
func (x *Participant) GetNitroAddress() string {
func (x *Participant) GetPublicKey() []byte {
if x != nil {
return x.NitroAddress
return x.PublicKey
}
return ""
return nil
}
func (x *Participant) GetRole() string {
@ -1692,46 +1694,43 @@ var file_cerc_onboarding_v1_onboarding_proto_rawDesc = []byte{
0x6c, 0x65, 0x64, 0x22, 0x20, 0x79, 0x61, 0x6d, 0x6c, 0x3a, 0x22, 0x6f, 0x6e, 0x62, 0x6f, 0x61,
0x72, 0x64, 0x69, 0x6e, 0x67, 0x5f, 0x65, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x22, 0x52, 0x11,
0x6f, 0x6e, 0x62, 0x6f, 0x61, 0x72, 0x64, 0x69, 0x6e, 0x67, 0x45, 0x6e, 0x61, 0x62, 0x6c, 0x65,
0x64, 0x22, 0xa2, 0x02, 0x0a, 0x0b, 0x50, 0x61, 0x72, 0x74, 0x69, 0x63, 0x69, 0x70, 0x61, 0x6e,
0x64, 0x22, 0xed, 0x01, 0x0a, 0x0b, 0x50, 0x61, 0x72, 0x74, 0x69, 0x63, 0x69, 0x70, 0x61, 0x6e,
0x74, 0x12, 0x56, 0x0a, 0x0e, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x5f, 0x61, 0x64, 0x64, 0x72,
0x65, 0x73, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x42, 0x2f, 0xf2, 0xde, 0x1f, 0x2b, 0x6a,
0x73, 0x6f, 0x6e, 0x3a, 0x22, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x5f, 0x61, 0x64, 0x64, 0x72,
0x65, 0x73, 0x73, 0x22, 0x20, 0x79, 0x61, 0x6d, 0x6c, 0x3a, 0x22, 0x63, 0x6f, 0x73, 0x6d, 0x6f,
0x73, 0x5f, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x22, 0x52, 0x0d, 0x63, 0x6f, 0x73, 0x6d,
0x6f, 0x73, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x12, 0x52, 0x0a, 0x0d, 0x6e, 0x69, 0x74,
0x72, 0x6f, 0x5f, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09,
0x42, 0x2d, 0xf2, 0xde, 0x1f, 0x29, 0x6a, 0x73, 0x6f, 0x6e, 0x3a, 0x22, 0x6e, 0x69, 0x74, 0x72,
0x6f, 0x5f, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x22, 0x20, 0x79, 0x61, 0x6d, 0x6c, 0x3a,
0x22, 0x6e, 0x69, 0x74, 0x72, 0x6f, 0x5f, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x22, 0x52,
0x0c, 0x6e, 0x69, 0x74, 0x72, 0x6f, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x12, 0x2f, 0x0a,
0x04, 0x72, 0x6f, 0x6c, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x42, 0x1b, 0xf2, 0xde, 0x1f,
0x17, 0x6a, 0x73, 0x6f, 0x6e, 0x3a, 0x22, 0x72, 0x6f, 0x6c, 0x65, 0x22, 0x20, 0x79, 0x61, 0x6d,
0x6c, 0x3a, 0x22, 0x72, 0x6f, 0x6c, 0x65, 0x22, 0x52, 0x04, 0x72, 0x6f, 0x6c, 0x65, 0x12, 0x36,
0x0a, 0x06, 0x6b, 0x79, 0x63, 0x5f, 0x69, 0x64, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x42, 0x1f,
0xf2, 0xde, 0x1f, 0x1b, 0x6a, 0x73, 0x6f, 0x6e, 0x3a, 0x22, 0x6b, 0x79, 0x63, 0x5f, 0x69, 0x64,
0x22, 0x20, 0x79, 0x61, 0x6d, 0x6c, 0x3a, 0x22, 0x6b, 0x79, 0x63, 0x5f, 0x69, 0x64, 0x22, 0x52,
0x05, 0x6b, 0x79, 0x63, 0x49, 0x64, 0x22, 0x76, 0x0a, 0x0a, 0x45, 0x74, 0x68, 0x50, 0x61, 0x79,
0x6c, 0x6f, 0x61, 0x64, 0x12, 0x3b, 0x0a, 0x07, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x18,
0x01, 0x20, 0x01, 0x28, 0x09, 0x42, 0x21, 0xf2, 0xde, 0x1f, 0x1d, 0x6a, 0x73, 0x6f, 0x6e, 0x3a,
0x22, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x22, 0x20, 0x79, 0x61, 0x6d, 0x6c, 0x3a, 0x22,
0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x22, 0x52, 0x07, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73,
0x73, 0x12, 0x2b, 0x0a, 0x03, 0x6d, 0x73, 0x67, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x42, 0x19,
0xf2, 0xde, 0x1f, 0x15, 0x6a, 0x73, 0x6f, 0x6e, 0x3a, 0x22, 0x6d, 0x73, 0x67, 0x22, 0x20, 0x79,
0x61, 0x6d, 0x6c, 0x3a, 0x22, 0x6d, 0x73, 0x67, 0x22, 0x52, 0x03, 0x6d, 0x73, 0x67, 0x42, 0xd4,
0x01, 0x0a, 0x16, 0x63, 0x6f, 0x6d, 0x2e, 0x63, 0x65, 0x72, 0x63, 0x2e, 0x6f, 0x6e, 0x62, 0x6f,
0x61, 0x72, 0x64, 0x69, 0x6e, 0x67, 0x2e, 0x76, 0x31, 0x42, 0x0f, 0x4f, 0x6e, 0x62, 0x6f, 0x61,
0x72, 0x64, 0x69, 0x6e, 0x67, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x50, 0x01, 0x5a, 0x3f, 0x67, 0x69,
0x74, 0x2e, 0x76, 0x64, 0x62, 0x2e, 0x74, 0x6f, 0x2f, 0x63, 0x65, 0x72, 0x63, 0x2d, 0x69, 0x6f,
0x2f, 0x6c, 0x61, 0x63, 0x6f, 0x6e, 0x69, 0x63, 0x64, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x63, 0x65,
0x72, 0x63, 0x2f, 0x6f, 0x6e, 0x62, 0x6f, 0x61, 0x72, 0x64, 0x69, 0x6e, 0x67, 0x2f, 0x76, 0x31,
0x3b, 0x6f, 0x6e, 0x62, 0x6f, 0x61, 0x72, 0x64, 0x69, 0x6e, 0x67, 0x76, 0x31, 0xa2, 0x02, 0x03,
0x43, 0x4f, 0x58, 0xaa, 0x02, 0x12, 0x43, 0x65, 0x72, 0x63, 0x2e, 0x4f, 0x6e, 0x62, 0x6f, 0x61,
0x72, 0x64, 0x69, 0x6e, 0x67, 0x2e, 0x56, 0x31, 0xca, 0x02, 0x12, 0x43, 0x65, 0x72, 0x63, 0x5c,
0x4f, 0x6e, 0x62, 0x6f, 0x61, 0x72, 0x64, 0x69, 0x6e, 0x67, 0x5c, 0x56, 0x31, 0xe2, 0x02, 0x1e,
0x43, 0x65, 0x72, 0x63, 0x5c, 0x4f, 0x6e, 0x62, 0x6f, 0x61, 0x72, 0x64, 0x69, 0x6e, 0x67, 0x5c,
0x56, 0x31, 0x5c, 0x47, 0x50, 0x42, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0xea, 0x02,
0x14, 0x43, 0x65, 0x72, 0x63, 0x3a, 0x3a, 0x4f, 0x6e, 0x62, 0x6f, 0x61, 0x72, 0x64, 0x69, 0x6e,
0x67, 0x3a, 0x3a, 0x56, 0x31, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
0x6f, 0x73, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x12, 0x1d, 0x0a, 0x0a, 0x70, 0x75, 0x62,
0x6c, 0x69, 0x63, 0x5f, 0x6b, 0x65, 0x79, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x09, 0x70,
0x75, 0x62, 0x6c, 0x69, 0x63, 0x4b, 0x65, 0x79, 0x12, 0x2f, 0x0a, 0x04, 0x72, 0x6f, 0x6c, 0x65,
0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x42, 0x1b, 0xf2, 0xde, 0x1f, 0x17, 0x6a, 0x73, 0x6f, 0x6e,
0x3a, 0x22, 0x72, 0x6f, 0x6c, 0x65, 0x22, 0x20, 0x79, 0x61, 0x6d, 0x6c, 0x3a, 0x22, 0x72, 0x6f,
0x6c, 0x65, 0x22, 0x52, 0x04, 0x72, 0x6f, 0x6c, 0x65, 0x12, 0x36, 0x0a, 0x06, 0x6b, 0x79, 0x63,
0x5f, 0x69, 0x64, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x42, 0x1f, 0xf2, 0xde, 0x1f, 0x1b, 0x6a,
0x73, 0x6f, 0x6e, 0x3a, 0x22, 0x6b, 0x79, 0x63, 0x5f, 0x69, 0x64, 0x22, 0x20, 0x79, 0x61, 0x6d,
0x6c, 0x3a, 0x22, 0x6b, 0x79, 0x63, 0x5f, 0x69, 0x64, 0x22, 0x52, 0x05, 0x6b, 0x79, 0x63, 0x49,
0x64, 0x22, 0x76, 0x0a, 0x0a, 0x45, 0x74, 0x68, 0x50, 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64, 0x12,
0x3b, 0x0a, 0x07, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09,
0x42, 0x21, 0xf2, 0xde, 0x1f, 0x1d, 0x6a, 0x73, 0x6f, 0x6e, 0x3a, 0x22, 0x61, 0x64, 0x64, 0x72,
0x65, 0x73, 0x73, 0x22, 0x20, 0x79, 0x61, 0x6d, 0x6c, 0x3a, 0x22, 0x61, 0x64, 0x64, 0x72, 0x65,
0x73, 0x73, 0x22, 0x52, 0x07, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x12, 0x2b, 0x0a, 0x03,
0x6d, 0x73, 0x67, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x42, 0x19, 0xf2, 0xde, 0x1f, 0x15, 0x6a,
0x73, 0x6f, 0x6e, 0x3a, 0x22, 0x6d, 0x73, 0x67, 0x22, 0x20, 0x79, 0x61, 0x6d, 0x6c, 0x3a, 0x22,
0x6d, 0x73, 0x67, 0x22, 0x52, 0x03, 0x6d, 0x73, 0x67, 0x42, 0xd4, 0x01, 0x0a, 0x16, 0x63, 0x6f,
0x6d, 0x2e, 0x63, 0x65, 0x72, 0x63, 0x2e, 0x6f, 0x6e, 0x62, 0x6f, 0x61, 0x72, 0x64, 0x69, 0x6e,
0x67, 0x2e, 0x76, 0x31, 0x42, 0x0f, 0x4f, 0x6e, 0x62, 0x6f, 0x61, 0x72, 0x64, 0x69, 0x6e, 0x67,
0x50, 0x72, 0x6f, 0x74, 0x6f, 0x50, 0x01, 0x5a, 0x3f, 0x67, 0x69, 0x74, 0x2e, 0x76, 0x64, 0x62,
0x2e, 0x74, 0x6f, 0x2f, 0x63, 0x65, 0x72, 0x63, 0x2d, 0x69, 0x6f, 0x2f, 0x6c, 0x61, 0x63, 0x6f,
0x6e, 0x69, 0x63, 0x64, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x63, 0x65, 0x72, 0x63, 0x2f, 0x6f, 0x6e,
0x62, 0x6f, 0x61, 0x72, 0x64, 0x69, 0x6e, 0x67, 0x2f, 0x76, 0x31, 0x3b, 0x6f, 0x6e, 0x62, 0x6f,
0x61, 0x72, 0x64, 0x69, 0x6e, 0x67, 0x76, 0x31, 0xa2, 0x02, 0x03, 0x43, 0x4f, 0x58, 0xaa, 0x02,
0x12, 0x43, 0x65, 0x72, 0x63, 0x2e, 0x4f, 0x6e, 0x62, 0x6f, 0x61, 0x72, 0x64, 0x69, 0x6e, 0x67,
0x2e, 0x56, 0x31, 0xca, 0x02, 0x12, 0x43, 0x65, 0x72, 0x63, 0x5c, 0x4f, 0x6e, 0x62, 0x6f, 0x61,
0x72, 0x64, 0x69, 0x6e, 0x67, 0x5c, 0x56, 0x31, 0xe2, 0x02, 0x1e, 0x43, 0x65, 0x72, 0x63, 0x5c,
0x4f, 0x6e, 0x62, 0x6f, 0x61, 0x72, 0x64, 0x69, 0x6e, 0x67, 0x5c, 0x56, 0x31, 0x5c, 0x47, 0x50,
0x42, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0xea, 0x02, 0x14, 0x43, 0x65, 0x72, 0x63,
0x3a, 0x3a, 0x4f, 0x6e, 0x62, 0x6f, 0x61, 0x72, 0x64, 0x69, 0x6e, 0x67, 0x3a, 0x3a, 0x56, 0x31,
0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
}
var (

View File

@ -19,9 +19,11 @@ import (
govkeeper "cosmossdk.io/x/gov/keeper"
slashingkeeper "cosmossdk.io/x/slashing/keeper"
stakingkeeper "cosmossdk.io/x/staking/keeper"
"git.vdb.to/cerc-io/laconicd/server/distsig"
"git.vdb.to/cerc-io/laconicd/utils"
auctionkeeper "git.vdb.to/cerc-io/laconicd/x/auction/keeper"
bondkeeper "git.vdb.to/cerc-io/laconicd/x/bond/keeper"
nitrokeeper "git.vdb.to/cerc-io/laconicd/x/nitrobank/keeper"
onboardingkeeper "git.vdb.to/cerc-io/laconicd/x/onboarding/keeper"
registrykeeper "git.vdb.to/cerc-io/laconicd/x/registry/keeper"
"github.com/cosmos/cosmos-sdk/client"
@ -30,12 +32,10 @@ import (
"github.com/cosmos/cosmos-sdk/std"
authkeeper "github.com/cosmos/cosmos-sdk/x/auth/keeper"
_ "cosmossdk.io/api/cosmos/tx/config/v1" // import for side-effects
_ "cosmossdk.io/x/accounts" // import for side-effects
_ "cosmossdk.io/x/bank" // import for side-effects
// _ "cosmossdk.io/x/bank/v2" // import for side-effects
_ "cosmossdk.io/api/cosmos/tx/config/v1" // import for side-effects
_ "cosmossdk.io/runtime/v2/services" // import for side-effects
_ "cosmossdk.io/x/accounts" // import for side-effects
_ "cosmossdk.io/x/bank" // import for side-effects
_ "cosmossdk.io/x/consensus" // import for side-effects
_ "cosmossdk.io/x/distribution" // import for side-effects
_ "cosmossdk.io/x/gov" // import for side-effects
@ -56,7 +56,7 @@ var (
//go:embed app.yaml
AppConfigYAML []byte
_ = basedepinject.ProvideAccount // TODO
_ = basedepinject.ProvideAccount // TODO: build consensus controlled module accounts
)
type (
@ -75,7 +75,9 @@ type LaconicApp[T Tx] struct {
interfaceRegistry codectypes.InterfaceRegistry
store store.RootStore
// keepers
distsigManager *distsig.Manager
// basic keepers
AccountKeeper authkeeper.AccountKeeper
BankKeeper bankkeeper.Keeper
StakingKeeper *stakingkeeper.Keeper
@ -89,6 +91,7 @@ type LaconicApp[T Tx] struct {
BondKeeper *bondkeeper.Keeper
RegistryKeeper registrykeeper.Keeper
OnboardingKeeper *onboardingkeeper.Keeper
NitroKeeper *nitrokeeper.Keeper
}
// AppConfig returns the default app config.
@ -107,6 +110,7 @@ func AppConfig() depinject.Config {
codec.ProvideProtoCodec,
codec.ProvideLegacyAmino, // note: needed by ProvideAppBuilder (runtime/v2)
ProvideRootStoreConfig,
distsig.ProvideManager,
// // inject desired account types:
// basedepinject.ProvideAccount,
@ -142,6 +146,7 @@ func NewLaconicApp[T Tx](
// &app.legacyAmino,
&app.txConfig,
&app.interfaceRegistry,
&app.distsigManager,
&app.StakingKeeper,
&app.AccountKeeper,
&app.BankKeeper,
@ -162,8 +167,6 @@ func NewLaconicApp[T Tx](
return nil, err
}
// // TODO: db config correct?
// // TODO: store tracer injection?
app.App, err = appBuilder.Build()
if err != nil {
return nil, err
@ -174,9 +177,10 @@ func NewLaconicApp[T Tx](
return nil, fmt.Errorf("store builder did not return a db")
}
// TODO: review streaming services
// Note: upgrade handlers are registered here in simapp
// TODO: db config correct?
// TODO: store metrics, tracer?
// TODO: streaming services?
// TODO: upgrade handlers?
if err = app.LoadLatest(); err != nil {
return nil, err
@ -197,6 +201,10 @@ func (app *LaconicApp[T]) AppCodec() codec.Codec {
return app.appCodec
}
func (app *LaconicApp[T]) DistSigManager() *distsig.Manager {
return app.distsigManager
}
func ProvideRootStoreConfig(config runtime.GlobalConfig) (*root.Config, error) {
return serverstore.UnmarshalConfig(config)
}

107
app/app_abci.go Normal file
View File

@ -0,0 +1,107 @@
package app
import (
"bytes"
"context"
"encoding/gob"
"cosmossdk.io/core/store"
abci "github.com/cometbft/cometbft/api/cometbft/abci/v1"
"git.vdb.to/cerc-io/laconicd/server/distsig"
"git.vdb.to/cerc-io/laconicd/x/onboarding"
)
func (app *LaconicApp[T]) ExtendVote(
ctx context.Context, _ store.ReaderMap, req *abci.ExtendVoteRequest,
) (*abci.ExtendVoteResponse, error) {
dsm := app.DistSigManager()
ourEthAddress := dsm.LongtermEthAddress()
us, err := app.OnboardingKeeper.GetParticipantByNitroAddress(ctx, ourEthAddress.String())
if err != nil {
return nil, err
}
if us == nil { // if we are not a participant, we don't need to do anything
return nil, nil
}
// // If any OnboardParticipant tx (or any tx that changes validator set) has been processed,
// // begin DKG for the new participants. The extension will contain our DKG deals.
// newParticipants := false
// for _, tx := range req.Txs {
// var opMsg onboarding.MsgOnboardParticipant
// if err := opMsg.Unmarshal(tx); err != nil {
// // we've already processed the tx, so we don't need to look at the message; we know the
// // participant set has changed and we need to run DKG.
// newParticipants = true
// }
// }
// // TODO: check if responses are processed, generate commits
// if !newParticipants {
// return nil, nil
// }
// Get public keys of participants
var pubkeys []distsig.Point
if err := app.OnboardingKeeper.Participants.Walk(ctx, nil, func(_ string, p onboarding.Participant) (bool, error) {
var pubkey distsig.Point
if err := pubkey.UnmarshalBinary(p.PublicKey); err != nil {
return false, err
}
pubkeys = append(pubkeys, pubkey)
return false, nil
}); err != nil {
return nil, err
}
if !dsm.NeedDKG(pubkeys) {
app.Logger().Debug("No change in DSS participants")
return nil, nil
}
if err = dsm.StartDKG(req.Height, pubkeys); err != nil {
return nil, err
}
buf := new(bytes.Buffer)
enc := gob.NewEncoder(buf)
if err := enc.Encode(dsm.FlushDKGMessages()); err != nil {
return nil, err
}
var extension []byte
if len(buf.Bytes()) != 0 {
extension = buf.Bytes()
}
return &abci.ExtendVoteResponse{
VoteExtension: extension,
}, nil
}
func (app *LaconicApp[T]) VerifyVoteExtension(
ctx context.Context, _ store.ReaderMap, req *abci.VerifyVoteExtensionRequest,
) (*abci.VerifyVoteExtensionResponse, error) {
dec := gob.NewDecoder(bytes.NewReader(req.VoteExtension))
var messages distsig.DkgMessages
if err := dec.Decode(&messages); err != nil {
return nil, err
}
// // This method must be deterministic, so just check that there is a deal for each participant
// numParticipants := 0
// app.OnboardingKeeper.Participants.Walk(ctx, nil, func(string, onboarding.Participant) (bool, error) {
// numParticipants++
// return false, nil
// })
// if len(deals) != numParticipants {
// return &abci.VerifyVoteExtensionResponse{
// Status: abci.VERIFY_VOTE_EXTENSION_STATUS_REJECT,
// }, nil
// }
err := app.DistSigManager().ProcessDKGMessages(&messages)
if err != nil {
return nil, err
}
// This method must be deterministic, so just accept whatever for now (TODO: actually verify)
return &abci.VerifyVoteExtensionResponse{
Status: abci.VERIFY_VOTE_EXTENSION_STATUS_ACCEPT,
}, nil
}

View File

@ -26,15 +26,14 @@ import (
"cosmossdk.io/store/v2/db"
banktypes "cosmossdk.io/x/bank/types"
codectestutil "github.com/cosmos/cosmos-sdk/codec/testutil"
"github.com/cosmos/cosmos-sdk/crypto/keyring"
"github.com/cosmos/cosmos-sdk/crypto/keys/secp256k1"
"github.com/cosmos/cosmos-sdk/testutil"
sdktestutil "github.com/cosmos/cosmos-sdk/testutil"
"github.com/cosmos/cosmos-sdk/testutil/mock"
simtestutil "github.com/cosmos/cosmos-sdk/testutil/sims"
sdk "github.com/cosmos/cosmos-sdk/types"
modtestutil "github.com/cosmos/cosmos-sdk/types/module/testutil"
authtypes "github.com/cosmos/cosmos-sdk/x/auth/types"
"git.vdb.to/cerc-io/laconicd/testutil"
)
func NewTestApp(t *testing.T) (*LaconicApp[Tx], context.Context) {
@ -47,10 +46,8 @@ func NewTestApp(t *testing.T) (*LaconicApp[Tx], context.Context) {
vp.Set(serverv2.FlagHome, t.TempDir())
// set up long-term distsig key
codecOpts := codectestutil.NewCodecOptionsWithCodecs(utils.NewAddressCodec(), utils.NewValAddressCodec())
encCfg := modtestutil.MakeTestEncodingConfig(codecOpts)
kr := keyring.NewInMemory(encCfg.Codec)
accounts := testutil.CreateKeyringAccounts(t, kr, 1)
kr := testutil.NewKeyring()
accounts := sdktestutil.CreateKeyringAccounts(t, kr, 1)
vp.Set(distsig.FlagLongtermKey, accounts[0].Name)
app, err := NewLaconicApp[Tx](depinject.Configs(

View File

@ -17,6 +17,7 @@ import (
"cosmossdk.io/server/v2/cometbft"
serverstore "cosmossdk.io/server/v2/store"
confixcmd "cosmossdk.io/tools/confix/cmd"
// "cosmossdk.io/x/accounts"
// "cosmossdk.io/x/accounts"
@ -35,7 +36,8 @@ import (
"git.vdb.to/cerc-io/laconicd/app"
"git.vdb.to/cerc-io/laconicd/gql"
"git.vdb.to/cerc-io/laconicd/nitro"
"git.vdb.to/cerc-io/laconicd/server/distsig"
"git.vdb.to/cerc-io/laconicd/server/nitro"
// "git.vdb.to/cerc-io/laconicd/x/nitrobank"
)
@ -43,11 +45,11 @@ import (
// an alternative design could fetch these even later from the command context
type CommandDependencies[T app.Tx] struct {
GlobalConfig coreserver.ConfigMap
TxConfig client.TxConfig
ModuleManager *runtimev2.MM[T]
LaconicApp *app.LaconicApp[T]
ConsensusServer *cometbft.CometBFTServer[T]
ClientContext client.Context
DistSigManager *distsig.Manager
}
func InitRootCmd[T app.Tx](
@ -90,8 +92,9 @@ func InitRootCmd[T app.Tx](
&serverstore.Server[T]{},
&telemetry.Server[T]{},
&rest.Server[T]{},
&nitro.Server{},
&gql.Server{},
&nitro.Server{},
&distsig.Manager{},
)
}
@ -116,13 +119,13 @@ func InitRootCmd[T app.Tx](
app.App.AppManager,
cometbft.AppCodecs[T]{
AppCodec: app.AppCodec(),
TxCodec: &client.DefaultTxDecoder[T]{TxConfig: deps.TxConfig},
TxCodec: &client.DefaultTxDecoder[T]{TxConfig: deps.ClientContext.TxConfig},
LegacyAmino: deps.ClientContext.LegacyAmino,
ConsensusAddressCodec: deps.ClientContext.ConsensusAddressCodec,
},
app.App.QueryHandlers(),
app.App.SchemaDecoderResolver(),
initCometOptions[T](),
initCometOptions[T](app),
deps.GlobalConfig,
)
if err != nil {
@ -151,14 +154,11 @@ func InitRootCmd[T app.Tx](
return nil, err
}
// nitrobank := deps.ModuleManager.Modules()[nitrobank.ModuleName].(nitrobank.AppModule)
// accounts := deps.ModuleManager.Modules()[accounts.ModuleName]
nitroServer, err := nitro.NewServer(logger, deps.GlobalConfig, deps.ClientContext)
gqlServer, err := gql.New(logger, deps.GlobalConfig, deps.ClientContext)
if err != nil {
return nil, err
}
gqlServer, err := gql.New(logger, deps.GlobalConfig, deps.ClientContext)
nitroServer, err := nitro.NewServer(logger, deps.GlobalConfig, deps.ClientContext.Keyring)
if err != nil {
return nil, err
}
@ -175,8 +175,9 @@ func InitRootCmd[T app.Tx](
storeComponent,
telemetryServer,
restServer,
nitroServer,
gqlServer,
nitroServer,
deps.DistSigManager,
)
}

View File

@ -5,11 +5,12 @@ import (
cmtcfg "github.com/cometbft/cometbft/config"
"cosmossdk.io/core/transaction"
serverv2 "cosmossdk.io/server/v2"
"cosmossdk.io/server/v2/cometbft"
sdk "github.com/cosmos/cosmos-sdk/types"
"cosmossdk.io/core/transaction"
"git.vdb.to/cerc-io/laconicd/app"
)
// initAppConfig helps to override default client config template and configs.
@ -49,12 +50,19 @@ func initCometConfig() cometbft.CfgOption {
cfg.Consensus.TimeoutCommit = 3 * time.Second
// overwrite default pprof listen address
cfg.RPC.PprofListenAddress = "localhost:6060"
// use previous db backend
cfg.DBBackend = "goleveldb"
return cometbft.OverwriteDefaultConfigTomlConfig(cfg)
}
func initCometOptions[T transaction.Tx]() cometbft.ServerOptions[T] {
func initCometOptions[T transaction.Tx](laconic *app.LaconicApp[T]) cometbft.ServerOptions[T] {
serverOptions := cometbft.DefaultServerOptions[T]()
// Implement custom handlers (e.g. for Vote Extensions)
// serverOptions.PrepareProposalHandler = CustomPrepareProposal[T]()
// serverOptions.ProcessProposalHandler = CustomProcessProposalHandler[T]()
serverOptions.ExtendVoteHandler = laconic.ExtendVote
serverOptions.VerifyVoteExtensionHandler = laconic.VerifyVoteExtension
// overwrite app mempool, using max-txs option
// serverOptions.Mempool = func(cfg map[string]any) mempool.Mempool[T] {
@ -63,7 +71,6 @@ func initCometOptions[T transaction.Tx]() cometbft.ServerOptions[T] {
// sdkmempool.SenderNonceMaxTxOpt(maxTxs),
// )
// }
// return mempool.NoOpMempool[T]{}
// }

View File

@ -6,13 +6,14 @@ import (
"cosmossdk.io/core/address"
runtime "cosmossdk.io/runtime/v2"
serverv2 "cosmossdk.io/server/v2"
"github.com/cosmos/cosmos-sdk/client"
"github.com/cosmos/cosmos-sdk/client/config"
"github.com/cosmos/cosmos-sdk/codec"
codectypes "github.com/cosmos/cosmos-sdk/codec/types"
"github.com/cosmos/cosmos-sdk/crypto/keyring"
"github.com/cosmos/cosmos-sdk/x/auth/types"
"git.vdb.to/cerc-io/laconicd/server/nitro"
)
func ProvideClientContext(
@ -63,3 +64,7 @@ func ProvideClientContext(
func ProvideKeyring(clientCtx client.Context) keyring.Keyring {
return clientCtx.Keyring
}
func ProvideNitroService(configMap runtime.GlobalConfig) (nitro.Service, error) {
return nil, nil
}

View File

@ -17,6 +17,7 @@ import (
nodeservice "github.com/cosmos/cosmos-sdk/client/grpc/node"
"git.vdb.to/cerc-io/laconicd/app"
"git.vdb.to/cerc-io/laconicd/server/distsig"
)
const (
@ -74,14 +75,21 @@ func NewRootCmd[T app.Tx](
moduleManager *runtime.MM[T]
clientCtx client.Context
laconic *app.LaconicApp[T]
dsManager *distsig.Manager
depinjectConfig = depinject.Configs(
depinject.Supply(logger, runtime.GlobalConfig(configMap)),
depinject.Provide(ProvideClientContext),
depinject.Provide(
ProvideClientContext,
ProvideKeyring,
),
)
)
if serverv2.IsAppRequired(subCommand) {
// server construction
laconic, err = app.NewLaconicApp[T](depinjectConfig, &autoCliOpts, &moduleManager, &clientCtx)
laconic, err = app.NewLaconicApp[T](
depinjectConfig,
&autoCliOpts, &moduleManager, &clientCtx, &dsManager,
)
if err != nil {
return nil, err
}
@ -92,18 +100,18 @@ func NewRootCmd[T app.Tx](
app.AppConfig(),
depinjectConfig,
),
&autoCliOpts, &moduleManager, &clientCtx,
&autoCliOpts, &moduleManager, &clientCtx, &dsManager,
); err != nil {
return nil, err
}
}
commandDeps := CommandDependencies[T]{
GlobalConfig: configMap,
TxConfig: clientCtx.TxConfig,
ModuleManager: moduleManager,
LaconicApp: laconic,
ClientContext: clientCtx,
GlobalConfig: configMap,
ModuleManager: moduleManager,
LaconicApp: laconic,
ClientContext: clientCtx,
DistSigManager: dsManager,
}
rootCommand = &cobra.Command{
Use: "laconicd",

16
go.mod
View File

@ -26,6 +26,7 @@ require (
cosmossdk.io/store v1.10.0-rc.1
cosmossdk.io/store/v2 v2.0.0-beta.1
cosmossdk.io/tools/confix v0.1.0
git.vdb.to/cerc-io/chainsig v0.1.0
github.com/99designs/gqlgen v0.17.22
github.com/cometbft/cometbft v1.0.0
github.com/cosmos/cosmos-proto v1.0.0-beta.5
@ -40,6 +41,7 @@ require (
github.com/grpc-ecosystem/grpc-gateway v1.16.0
github.com/ipfs/go-cid v0.4.1
github.com/ipld/go-ipld-prime v0.21.0
github.com/lmittmann/tint v1.0.2
github.com/rs/cors v1.11.1
github.com/spf13/cobra v1.8.1
github.com/spf13/pflag v1.0.5
@ -48,6 +50,7 @@ require (
github.com/tidwall/gjson v1.14.4
github.com/tidwall/sjson v1.2.5
github.com/vektah/gqlparser/v2 v2.5.11
go.dedis.ch/kyber/v3 v3.1.0
go.uber.org/mock v0.5.0 // indirect
google.golang.org/genproto/googleapis/api v0.0.0-20240903143218-8af14fe29dc1
google.golang.org/grpc v1.68.1
@ -67,7 +70,7 @@ require (
cosmossdk.io/x/protocolpool v1.0.0-alpha.4
cosmossdk.io/x/slashing v0.0.0-20241007000829-38662ecb209f
cosmossdk.io/x/staking v1.0.0-alpha.4
github.com/lmittmann/tint v1.0.2
github.com/cometbft/cometbft/api v1.0.0
)
require (
@ -112,7 +115,6 @@ require (
github.com/cockroachdb/redact v1.1.5 // indirect
github.com/cockroachdb/tokenbucket v0.0.0-20230807174530-cc333fc44b06 // indirect
github.com/cometbft/cometbft-db v1.0.1 // indirect
github.com/cometbft/cometbft/api v1.0.0 // indirect
github.com/consensys/bavard v0.1.13 // indirect
github.com/consensys/gnark-crypto v0.12.1 // indirect
github.com/containerd/cgroups v1.1.0 // indirect
@ -321,6 +323,8 @@ require (
github.com/zondax/ledger-go v0.14.3 // indirect
gitlab.com/yawning/secp256k1-voi v0.0.0-20230925100816-f2616030848b // indirect
gitlab.com/yawning/tuplehash v0.0.0-20230713102510-df83abbf9a02 // indirect
go.dedis.ch/fixbuf v1.0.3 // indirect
go.dedis.ch/protobuf v1.0.11 // indirect
go.etcd.io/bbolt v1.4.0-alpha.0.0.20240404170359-43604f3112c5 // indirect
go.opencensus.io v0.24.0 // indirect
go.opentelemetry.io/otel v1.24.0 // indirect
@ -354,8 +358,11 @@ require (
sigs.k8s.io/yaml v1.4.0 // indirect
)
// github.com/statechannels/go-nitro v0.1.2 => github.com/cerc-io/go-nitro v0.1.3-ts-port-0.1.10
replace github.com/statechannels/go-nitro => ../mod/go-nitro
replace (
git.vdb.to/cerc-io/chainsig => ../mod/chainsig
// github.com/statechannels/go-nitro v0.1.2 => github.com/cerc-io/go-nitro v0.1.3-ts-port-0.1.10
github.com/statechannels/go-nitro => ../mod/go-nitro
)
// replace (
// cosmossdk.io/core v0.7.6 => github.com/roysc/cosmos-sdk/core v0.0.0-20241001191620-a3729c1ad6ba
@ -410,6 +417,7 @@ replace (
replace (
github.com/cometbft/cometbft => ../mod/cometbft
github.com/cosmos/cosmos-sdk => ../mod/cosmos-sdk
go.dedis.ch/kyber/v3 => ../mod/kyber
)
// replace google.golang.org/protobuf => /Users/roy/clone/protobuf-go

6
go.sum
View File

@ -935,6 +935,10 @@ gitlab.com/yawning/secp256k1-voi v0.0.0-20230925100816-f2616030848b h1:CzigHMRyS
gitlab.com/yawning/secp256k1-voi v0.0.0-20230925100816-f2616030848b/go.mod h1:/y/V339mxv2sZmYYR64O07VuCpdNZqCTwO8ZcouTMI8=
gitlab.com/yawning/tuplehash v0.0.0-20230713102510-df83abbf9a02 h1:qwDnMxjkyLmAFgcfgTnfJrmYKWhHnci3GjDqcZp1M3Q=
gitlab.com/yawning/tuplehash v0.0.0-20230713102510-df83abbf9a02/go.mod h1:JTnUj0mpYiAsuZLmKjTx/ex3AtMowcCgnE7YNyCEP0I=
go.dedis.ch/fixbuf v1.0.3 h1:hGcV9Cd/znUxlusJ64eAlExS+5cJDIyTyEG+otu5wQs=
go.dedis.ch/fixbuf v1.0.3/go.mod h1:yzJMt34Wa5xD37V5RTdmp38cz3QhMagdGoem9anUalw=
go.dedis.ch/protobuf v1.0.11 h1:FTYVIEzY/bfl37lu3pR4lIj+F9Vp1jE8oh91VmxKgLo=
go.dedis.ch/protobuf v1.0.11/go.mod h1:97QR256dnkimeNdfmURz0wAMNVbd1VmLXhG1CrTYrJ4=
go.etcd.io/bbolt v1.4.0-alpha.0.0.20240404170359-43604f3112c5 h1:qxen9oVGzDdIRP6ejyAJc760RwW4SnVDiTYTzwnXuxo=
go.etcd.io/bbolt v1.4.0-alpha.0.0.20240404170359-43604f3112c5/go.mod h1:eW0HG9/oHQhvRCvb1/pIXW4cOvtDqeQK+XSi3TnwaXY=
go.opencensus.io v0.18.0/go.mod h1:vKdFvxhtzZ9onBp9VKHK8z/sRpBMnKAsufL7wlDrCOA=
@ -974,6 +978,7 @@ golang.org/x/arch v0.12.0/go.mod h1:FEVrYAQjsQXMVJ1nsMoVVXPZg6p2JE2mx8psSWTDQys=
golang.org/x/build v0.0.0-20190111050920-041ab4dc3f9d/go.mod h1:OWs+y06UdEOHN4y+MfF/py+xQ/tYqIWW03b70/CG9Rw=
golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
golang.org/x/crypto v0.0.0-20181030102418-4d3f4d9ffa16/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
golang.org/x/crypto v0.0.0-20190123085648-057139ce5d2b/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20190313024323-a1f597ede03a/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
@ -1064,6 +1069,7 @@ golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5h
golang.org/x/sys v0.0.0-20181029174526-d69651ed3497/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20181122145206-62eef0e2fa9b/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190124100055-b90733256f2e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190316082340-a2f829d7f35f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=

View File

@ -13,6 +13,7 @@ import (
authtypes "github.com/cosmos/cosmos-sdk/x/auth/types"
"git.vdb.to/cerc-io/laconicd/gql/schema"
"git.vdb.to/cerc-io/laconicd/utils"
auctiontypes "git.vdb.to/cerc-io/laconicd/x/auction"
bondtypes "git.vdb.to/cerc-io/laconicd/x/bond"
onboardingTypes "git.vdb.to/cerc-io/laconicd/x/onboarding"
@ -407,9 +408,13 @@ func (q queryResolver) GetParticipants(ctx context.Context) ([]*schema.Participa
participants := make([]*schema.Participant, len(participantResp.GetParticipants()))
for i, p := range participantResp.Participants {
nitroAddress, err := utils.EthAddressFromPubKey(p.PublicKey)
if err != nil {
return nil, err
}
participants[i] = &schema.Participant{
CosmosAddress: p.CosmosAddress,
NitroAddress: p.NitroAddress,
NitroAddress: nitroAddress.String(),
Role: p.Role,
KycID: p.KycId,
}
@ -426,9 +431,13 @@ func (q queryResolver) GetParticipantByAddress(ctx context.Context, address stri
}
p := participantResp.Participant
nitroAddress, err := utils.EthAddressFromPubKey(p.PublicKey)
if err != nil {
return nil, err
}
participant := &schema.Participant{
CosmosAddress: p.CosmosAddress,
NitroAddress: p.NitroAddress,
NitroAddress: nitroAddress.String(),
Role: p.Role,
KycID: p.KycId,
}
@ -451,7 +460,7 @@ func (q queryResolver) GetParticipantByNitroAddress(ctx context.Context, nitroAd
p := participantResp.Participant
participant := &schema.Participant{
CosmosAddress: p.CosmosAddress,
NitroAddress: p.NitroAddress,
NitroAddress: nitroAddress,
Role: p.Role,
KycID: p.KycId,
}

View File

@ -43,6 +43,8 @@ message MsgOpenChannel {
message MsgOpenChannelResponse {}
service Msg {
option (cosmos.msg.v1.service) = true;
rpc ProposeChannel(MsgProposeChannel) returns (MsgProposeChannelResponse) {
option (google.api.http).post = "/cerc/nitrobank/v1/propose_channel";
}

View File

@ -21,10 +21,8 @@ message Participant {
[ (gogoproto.moretags) =
"json:\"cosmos_address\" yaml:\"cosmos_address\"" ];
// participant's Nitro address
string nitro_address = 2
[ (gogoproto.moretags) =
"json:\"nitro_address\" yaml:\"nitro_address\"" ];
// full public key used to derive participant's Nitro address
bytes public_key = 2;
// participant's role (participant | validator)
string role = 3 [ (gogoproto.moretags) = "json:\"role\" yaml:\"role\"" ];

13
server/distsig/config.go Normal file
View File

@ -0,0 +1,13 @@
package distsig
type Config struct {
LongtermKey string `mapstructure:"longterm-key" toml:"longterm-key" comment:"The long-term key used in distributed signatures"`
// TODO: set this in genesis
ThresholdRatio float64 `mapstructure:"threshold-ratio" toml:"threshold-ratio" comment:"The ratio of signers required to sign a message"`
}
func DefaultConfig() *Config {
return &Config{
ThresholdRatio: 4. / 7,
}
}

View File

@ -0,0 +1,175 @@
package distsig
import (
"errors"
"math/big"
"testing"
"cosmossdk.io/log"
"git.vdb.to/cerc-io/chainsig/ethschnorr"
sdktestutil "github.com/cosmos/cosmos-sdk/testutil"
"github.com/stretchr/testify/require"
"git.vdb.to/cerc-io/laconicd/testutil"
)
func NewTestManager(t *testing.T) (*Manager, Point) {
logger := log.NewTestLogger(t)
kr := testutil.NewKeyring()
accounts := sdktestutil.CreateKeyringAccounts(t, kr, 1)
cfg := DefaultConfig()
cfg.LongtermKey = accounts[0].Name
dsm, err := New(logger, cfg, kr)
require.NoError(t, err)
longterm, err := kr.Key(cfg.LongtermKey)
require.NoError(t, err)
longtermPoint, err := KeyRecordToPoint(longterm)
require.NoError(t, err)
return dsm, longtermPoint
}
type round struct {
name string
verify func(*Manager) error
tweak func([]PeerMessages)
}
var (
dkgRounds = []round{
{
name: "deal",
},
{
name: "response",
verify: func(m *Manager) error {
if !m.currentDkg().Certified() {
return errors.New("not certified")
}
return nil
},
},
{
name: "commit",
verify: func(m *Manager) error {
if !m.currentDkg().Finished() {
return errors.New("run not finished")
}
if m.currentDkg().share == nil {
return errors.New("dist key share is absent")
}
return nil
},
},
}
dssRounds = []round{
{
name: "sign",
verify: func(m *Manager) error {
dss := m.sigs[m.completeSigs[0]]
if dss.sig == nil {
return errors.New("signature is nil")
}
dkg, err := m.getDkg(dss.dkgID)
if err != nil {
return err
}
return ethschnorr.Verify(dkg.share.Public(), dss.Message(), dss.sig)
},
},
}
)
func runRound(t *testing.T, r round, members []*Manager) {
buf := make([]PeerMessages, len(members))
for i := range members {
buf[i] = members[i].FlushMessages()
}
if r.tweak != nil {
r.tweak(buf)
}
for i := range members {
for j := range members {
if i == j {
continue
}
require.NoError(t, members[i].ProcessMessages(&buf[j]),
"round=%s, i=%d, j=%d", r.name, i, j)
}
}
if r.verify != nil {
for i, m := range members {
require.NoError(t, r.verify(m), "round=%s, i=%d", r.name, i)
}
}
}
func TestDkgBasic(t *testing.T) {
numMembers := 2
blockHeight := int64(1)
members := make([]*Manager, numMembers)
pubkeys := make([]Point, numMembers)
for i := range members {
members[i], pubkeys[i] = NewTestManager(t)
}
t.Logf("DKG with %d members", numMembers)
for i, m := range members {
require.NoError(t, m.StartDKG(blockHeight, pubkeys), "i=%d", i)
}
for _, r := range dkgRounds {
runRound(t, r, members)
}
require.False(t, members[0].NeedDKG(pubkeys))
require.Error(t, members[0].StartDKG(blockHeight, pubkeys))
// add participants and refresh DKG
for len(members) < 7 {
blockHeight++
m, pub := NewTestManager(t)
members = append(members, m)
pubkeys = append(pubkeys, pub)
t.Logf("DKG with %d members", len(members))
for i, m := range members {
require.True(t, m.NeedDKG(pubkeys), "i=%d", i)
require.NoError(t, m.StartDKG(blockHeight, pubkeys), "i=%d", i)
}
for _, r := range dkgRounds {
runRound(t, r, members)
}
}
}
func TestSignatureBasic(t *testing.T) {
numMembers := 7
members := make([]*Manager, numMembers)
pubkeys := make([]Point, numMembers)
for i := range members {
members[i], pubkeys[i] = NewTestManager(t)
}
for _, m := range members {
require.NoError(t, m.StartDKG(1, pubkeys))
}
for _, r := range dkgRounds {
runRound(t, r, members)
}
msg := big.NewInt(42)
for _, m := range members {
require.NoError(t, m.StartSignature(m.currentDkgID, msg))
}
runRound(t, dssRounds[0], members)
require.Error(t, members[0].StartSignature(0, msg))
require.NoError(t, members[0].StartDKG(2, pubkeys[:3]))
require.Error(t, members[0].StartSignature(2, msg))
}

224
server/distsig/keygen.go Normal file
View File

@ -0,0 +1,224 @@
package distsig
import (
"fmt"
dkg "go.dedis.ch/kyber/v3/share/dkg/rabin"
)
// DkgMessages collects local DKG messages that are pending broadcast.
type DkgMessages struct {
runID DkgRunID
messages []dkgMessage
}
// DKG steps (actions) that are executed by the DKG protocol
type dkgStep int
const (
dkg_deal dkgStep = iota
dkg_certify
dkg_commit
dkg_finish
dkg_done
)
type dkgRun struct {
*dkg.DistKeyGenerator
// runID RunID
msgBuffer []dkgMessage
step dkgStep
share *dkg.DistKeyShare
}
type dkgMessage interface {
send(*dkgRun) (dkgMessage, error)
from() uint32
target() uint32
}
// prepareMessages produces DKG state transitions that don't rely on peer inputs, i.e. the deal or
// commit steps. This is called during ExtendVote by all validators.
func (d *dkgRun) prepareMessages() error {
out, err := d.handleMessage(nil)
if err != nil {
return err
}
if out != nil {
d.msgBuffer = append(d.msgBuffer, out...)
}
return nil
}
func (d *dkgRun) flushMessages() []dkgMessage {
buf := d.msgBuffer
d.msgBuffer = nil
return buf
}
// processMessages processes incoming DKG messages and produces outgoing messages. This is called
// during VerifyVoteExtension by all validators (TODO: verify).
func (d *dkgRun) processMessages(in []dkgMessage) error {
for _, msg := range in {
out, err := d.handleMessage(msg)
if err != nil {
return err
}
if out != nil {
d.msgBuffer = append(d.msgBuffer, out...)
}
}
return nil
}
func (d *dkgRun) handleMessage(in dkgMessage) ([]dkgMessage, error) {
// fmt.Printf("[%d, %7s] handle: %T", d.index, d.step, in)
// if in != nil {
// fmt.Printf(" (from %d to %+v)", in.from(), in.target())
// }
// fmt.Println()
// nil input means we try to execute a step requiring no peer input
if in == nil {
var out []dkgMessage
switch d.step {
case dkg_deal:
deals, err := d.Deals()
if err != nil {
return nil, err
}
for index, deal := range deals {
out = append(out, msgDeal{index: uint32(index), msg: deal})
}
case dkg_commit:
sc, err := d.SecretCommits()
if err != nil {
return nil, err
}
out = []dkgMessage{msgSecretCommits{msg: sc}}
case dkg_done:
dks, err := d.DistKeyShare()
if err != nil {
return nil, err
}
d.share = dks
default:
return nil, fmt.Errorf("unexpected stage: %v", d.step)
}
d.step = nextStep(d.step)
return out, nil
}
var out []dkgMessage
if msg, err := in.send(d); err != nil {
return nil, err
} else if msg != nil {
out = []dkgMessage{msg}
}
if (d.step == dkg_certify && d.Certified()) ||
(d.step == dkg_finish && d.Finished()) {
d.step = nextStep(d.step)
msgs, err := d.handleMessage(nil)
if err != nil {
return nil, err
}
out = append(out, msgs...)
}
return out, nil
}
func nextStep(step dkgStep) dkgStep {
if step == dkg_done {
return dkg_done
}
return step + 1
}
type (
msgDeal struct {
msg *dkg.Deal
index uint32 // recipient index
}
msgResponse struct{ msg *dkg.Response }
msgJustification struct{ msg *dkg.Justification }
msgSecretCommits struct{ msg *dkg.SecretCommits }
msgComplaintCommits struct{ msg *dkg.ComplaintCommits }
msgReconstructCommits struct{ msg *dkg.ReconstructCommits }
)
func (m msgDeal) send(d *dkgRun) (dkgMessage, error) {
if m.index != uint32(d.Index()) {
return nil, nil
}
out, err := d.ProcessDeal(m.msg)
if err != nil {
return nil, err
}
return msgResponse{out}, nil
}
func (m msgResponse) send(d *dkgRun) (dkgMessage, error) {
if out, err := d.ProcessResponse(m.msg); err != nil {
return nil, err
} else if out != nil {
return msgJustification{out}, nil
}
return nil, nil
}
func (m msgJustification) send(d *dkgRun) (dkgMessage, error) {
return nil, d.ProcessJustification(m.msg)
}
func (m msgSecretCommits) send(d *dkgRun) (dkgMessage, error) {
if out, err := d.ProcessSecretCommits(m.msg); err != nil {
return nil, err
} else if out != nil {
return msgComplaintCommits{out}, nil
}
return nil, nil
}
func (m msgComplaintCommits) send(d *dkgRun) (dkgMessage, error) {
out, err := d.ProcessComplaintCommits(m.msg)
if err != nil {
return nil, err
}
return msgReconstructCommits{out}, nil
}
func (m msgReconstructCommits) send(d *dkgRun) (dkgMessage, error) {
return nil, d.ProcessReconstructCommits(m.msg)
}
func (d dkgStep) String() string {
switch d {
case dkg_deal:
return "deal"
case dkg_certify:
return "certify"
case dkg_commit:
return "commit"
case dkg_finish:
return "finish"
case dkg_done:
return "done"
default:
return "unknown"
}
}
// for debugging
func (m msgDeal) from() uint32 { return m.msg.Index }
func (m msgResponse) from() uint32 { return m.msg.Response.Index }
func (m msgJustification) from() uint32 { return m.msg.Justification.Index }
func (m msgSecretCommits) from() uint32 { return m.msg.Index }
func (m msgComplaintCommits) from() uint32 { return m.msg.Index }
func (m msgReconstructCommits) from() uint32 { return m.msg.Index }
func (m msgDeal) target() uint32 { return m.index }
func (m msgResponse) target() uint32 { return m.msg.Index }
func (m msgJustification) target() uint32 { return m.msg.Index }
func (m msgSecretCommits) target() uint32 { return 0 }
func (m msgComplaintCommits) target() uint32 { return m.msg.DealerIndex }
func (m msgReconstructCommits) target() uint32 { return m.msg.DealerIndex }

280
server/distsig/manager.go Normal file
View File

@ -0,0 +1,280 @@
package distsig
import (
"context"
"fmt"
"math"
"math/big"
"github.com/ethereum/go-ethereum/common"
dkg "go.dedis.ch/kyber/v3/share/dkg/rabin"
"cosmossdk.io/log"
"cosmossdk.io/runtime/v2"
serverv2 "cosmossdk.io/server/v2"
"github.com/cosmos/cosmos-sdk/crypto/keyring"
cryptotypes "github.com/cosmos/cosmos-sdk/crypto/types"
clientdss "git.vdb.to/cerc-io/chainsig/ethdss"
"git.vdb.to/cerc-io/chainsig/ethschnorr"
"git.vdb.to/cerc-io/laconicd/utils"
)
type (
DealMap = map[int]*dkg.Deal
DkgRunID int64
SigRunID string
)
const (
componentName = "distsig"
)
type Manager struct {
config *Config
logger log.Logger
longterm Scalar
longtermPubKey cryptotypes.PubKey
dkgs map[DkgRunID]*dkgRun
currentDkgID DkgRunID // zero indicates no current run
sigs map[SigRunID]*sigRun
completeSigs []SigRunID
}
type PeerMessages struct {
dkg *DkgMessages
dss []SigMessages
}
func New(logger log.Logger, cfg *Config, kr keyring.Keyring) (*Manager, error) {
longtermPrivKey, err := utils.ExtractPrivateKey(kr, cfg.LongtermKey)
if err != nil {
return nil, fmt.Errorf("failed to extract longterm key: %w", err)
}
m := &Manager{
longterm: suite.Scalar().SetBytes(longtermPrivKey.Bytes()),
longtermPubKey: longtermPrivKey.PubKey(),
config: cfg,
dkgs: make(map[DkgRunID]*dkgRun),
sigs: make(map[SigRunID]*sigRun),
}
m.logger = logger.With(log.ModuleKey, m.Name())
return m, nil
}
func (m *Manager) getDkg(runid DkgRunID) (*dkgRun, error) {
if runid == 0 {
// runid = m.currentDkg
return nil, fmt.Errorf("invalid run ID")
}
if run, ok := m.dkgs[runid]; ok {
return run, nil
}
return nil, fmt.Errorf("DKG not initialized for run: %v", runid)
}
func (m *Manager) currentDkg() *dkgRun {
run, err := m.getDkg(m.currentDkgID)
if err != nil {
panic(err)
}
return run
}
func (m *Manager) LongtermPublicKey() cryptotypes.PubKey {
return m.longtermPubKey
}
func (m *Manager) LongtermEthAddress() common.Address {
pubkey, err := SuitePublicKeyFromBytes(m.LongtermPublicKey().Bytes())
if err != nil {
panic(fmt.Errorf("failed to parse longterm pubkey: %w", err))
}
return pubkey.Address()
}
func thresholdForRatio(m int, tr float64) int {
return int(math.Ceil(float64(m) * tr))
}
func (m *Manager) initDKG(members []Point) (*dkgRun, error) {
t := thresholdForRatio(len(members), m.config.ThresholdRatio)
keygen, err := dkg.NewDistKeyGenerator(suite.(dkg.Suite), m.longterm, members, t)
if err != nil {
return nil, err
}
return &dkgRun{DistKeyGenerator: keygen}, nil
}
// NeedDKG returns true if DKG needs to be run for the given participants.
func (m *Manager) NeedDKG(pubkeys []Point) bool {
return m.currentDkgID == 0 || !equalPoints(m.currentDkg().Participants(), pubkeys)
}
// StartDKG begins a new DKG run including the given participants.
func (m *Manager) StartDKG(block int64, pubkeys []Point) error {
// TODO: generate runid from block height and hash of pubkeys?
runid := DkgRunID(block)
if _, ok := m.dkgs[runid]; ok {
return fmt.Errorf("DKG run %v already exists", runid)
}
if len(pubkeys) < 2 {
m.currentDkgID = 0
m.logger.Debug("Too few participants for distributed signature")
return nil
}
run, err := m.initDKG(pubkeys)
if err != nil {
return err
}
m.dkgs[runid] = run
m.currentDkgID = runid
return run.prepareMessages()
}
func (m *Manager) initDSS(dkgid DkgRunID, msg *big.Int) (*sigRun, error) {
run, err := m.getDkg(dkgid)
if err != nil {
return nil, err
}
if !run.Finished() {
return nil, fmt.Errorf("DKG run has not finished: %v", dkgid)
}
random, err := run.DistKeyShare()
if err != nil {
return nil, err
}
dss, err := clientdss.NewDSS(clientdss.DSSArgs{
Secret: m.longterm,
Participants: run.Participants(),
Long: run.share,
Random: random,
Msg: msg,
T: run.Threshold(),
// Qualified: run.QUAL(),
})
if err != nil {
return nil, err
}
return &sigRun{DSS: dss, dkgID: dkgid}, nil
}
// StartSignature begins a DSS run for the given message and DKG state.
func (m *Manager) StartSignature(msg *big.Int) error {
if m.currentDkgID == 0 {
return fmt.Errorf("no distributed key prepared")
}
run, err := m.initDSS(m.currentDkgID, msg)
if err != nil {
return err
}
sigid := run.SigRunID()
m.sigs[sigid] = run
return run.prepareMessages()
}
func (m *Manager) CompletedSignatures() map[SigRunID]ethschnorr.Signature {
var ret map[SigRunID]ethschnorr.Signature
for _, id := range m.completeSigs {
run, ok := m.sigs[id]
if !ok {
panic(fmt.Errorf("DSS run not found: %v", id))
}
if run.sig == nil {
panic(fmt.Errorf("DSS signature not completed: %v", id))
}
// Deterministically pick a participant responsible for submitting the signature
session := new(big.Int).SetBytes(run.SessionID()[:8])
submitterIdx := session.Uint64() % uint64(len(run.Participants()))
if run.Index() == int(submitterIdx) {
ret[id] = run.sig
}
}
return ret
}
// FlushMessages flushes the message buffers for any active DKG and DSS runs.
func (m *Manager) FlushMessages() PeerMessages {
var ret PeerMessages
if buf := m.currentDkg().flushMessages(); len(buf) != 0 {
ret.dkg = &DkgMessages{runID: m.currentDkgID, messages: buf}
}
for id, run := range m.sigs {
if buf := run.flushMessages(); buf != nil {
ret.dss = append(ret.dss, SigMessages{id, buf})
}
}
return ret
}
// ProcessMessages processes DKG and DSS peer messages.
func (m *Manager) ProcessMessages(dm *PeerMessages) error {
if dkg := dm.dkg; dkg != nil {
run, err := m.getDkg(dkg.runID)
if err != nil {
return err
}
if err := run.processMessages(dkg.messages); err != nil {
return err
}
}
for _, dss := range dm.dss {
run, ok := m.sigs[dss.runID]
if !ok {
return fmt.Errorf("DSS not initialized for run: %v", dss.runID)
}
if err := run.processMessage(dss.messages); err != nil {
return err
}
if run.sig != nil {
m.completeSigs = append(m.completeSigs, dss.runID)
}
}
return nil
}
func equalPoints(a, b []Point) bool {
if len(a) != len(b) {
return false
}
for i, p := range a {
if !p.Equal(b[i]) {
return false
}
}
return true
}
func (*Manager) Name() string { return componentName }
func (*Manager) Start(context.Context) error { return nil }
func (*Manager) Stop(context.Context) error { return nil }
func (m *Manager) Config() any {
if m.config == nil {
return DefaultConfig()
}
return m.config
}
func (pm PeerMessages) Empty() bool {
return pm.dkg == nil && len(pm.dss) == 0
}
func UnmarshalConfig(cfg map[string]any) (*Config, error) {
config := DefaultConfig()
if err := serverv2.UnmarshalSubConfig(cfg, componentName, config); err != nil {
return nil, fmt.Errorf("failed to unmarshal %T: %w", config, err)
}
return config, nil
}
func ProvideManager(logger log.Logger, globalConfig runtime.GlobalConfig, kr keyring.Keyring) (*Manager, error) {
config, err := UnmarshalConfig(globalConfig)
if err != nil {
return nil, err
}
return New(logger, config, kr)
}

View File

@ -0,0 +1,61 @@
package distsig
import (
"fmt"
clientdss "git.vdb.to/cerc-io/chainsig/ethdss"
"git.vdb.to/cerc-io/chainsig/ethschnorr"
)
type SigMessages struct {
runID SigRunID
messages sigMessage
}
type sigStep int
const (
sig_partial sigStep = iota
sig_complete
)
type sigRun struct {
*clientdss.DSS
msgBuffer sigMessage
dkgID DkgRunID
step sigStep
sig ethschnorr.Signature
}
type sigMessage = *clientdss.PartialSig
func (d *sigRun) SigRunID() SigRunID {
return SigRunID(fmt.Sprintf("%020d-%x", d.dkgID, d.SessionID()[:10]))
}
func (d *sigRun) prepareMessages() error {
var err error
d.msgBuffer, err = d.PartialSig()
return err
}
func (d *sigRun) flushMessages() sigMessage {
buf := d.msgBuffer
d.msgBuffer = nil
return buf
}
func (d *sigRun) processMessage(in sigMessage) error {
err := d.ProcessPartialSig(in)
if err != nil {
return err
}
// return d.EnoughPartialSig(), nil
if d.EnoughPartialSig() {
d.sig, err = d.Signature()
return err
}
return nil
}

37
server/distsig/suite.go Normal file
View File

@ -0,0 +1,37 @@
package distsig
import (
"fmt"
"git.vdb.to/cerc-io/chainsig/secp256k1"
"github.com/cosmos/cosmos-sdk/crypto/keyring"
"go.dedis.ch/kyber/v3"
"go.dedis.ch/kyber/v3/suites"
)
type (
Scalar = kyber.Scalar
Point = kyber.Point
PublicKey = secp256k1.PublicKey
)
var (
suite suites.Suite = secp256k1.NewBlakeKeccackSecp256k1()
// Note: the compressed encoding of pubkeys used by the SDK and our library are the same.
// See gitlab.com/yawning/secp256k1-voi/secec
SuitePublicKeyFromBytes = secp256k1.NewPublicKeyFromBytes
)
func KeyRecordToPoint(longterm *keyring.Record) (kyber.Point, error) {
pubkey, err := longterm.GetPubKey()
if err != nil {
return nil, fmt.Errorf("failed to access public key: %w", err)
}
suitePubkey, err := SuitePublicKeyFromBytes(pubkey.Bytes())
if err != nil {
return nil, fmt.Errorf("failed to decode public key: %w", err)
}
return suitePubkey.Point()
}

26
server/distsig/utils.go Normal file
View File

@ -0,0 +1,26 @@
package distsig
import "encoding/hex"
type BlockHash [32]byte
func (bh BlockHash) String() string {
return hex.EncodeToString(bh[:])
}
func (bh BlockHash) Bytes() []byte {
return bh[:]
}
func (bh BlockHash) Equal(other BlockHash) bool {
return bh == other
}
func BlockHashFromBytes(b []byte) BlockHash {
if len(b) != 32 {
panic("invalid block hash length")
}
var bh BlockHash
copy(bh[:], b)
return bh
}

View File

@ -12,6 +12,7 @@ import (
"github.com/ethereum/go-ethereum/common"
"github.com/spf13/cobra"
"github.com/spf13/pflag"
"github.com/statechannels/go-nitro/crypto"
"github.com/statechannels/go-nitro/node"
"github.com/statechannels/go-nitro/node/engine"
"github.com/statechannels/go-nitro/node/engine/chainservice"
@ -57,7 +58,8 @@ type Server struct {
// path to Nitro store directory
storeDir string
ScAddr nitrotypes.PartyAddress
// EthAddress common.Address
StateChannelAddress nitrotypes.PartyAddress
}
func NewServer(logger log.Logger, cfg server.ConfigMap, kr keyring.Keyring) (*Server, error) {
@ -69,7 +71,7 @@ func NewServer(logger log.Logger, cfg server.ConfigMap, kr keyring.Keyring) (*Se
s.config = s.Config().(*Config)
if len(cfg) > 0 {
if err := serverv2.UnmarshalSubConfig(cfg, s.Name(), &s.config); err != nil {
if err := serverv2.UnmarshalSubConfig(cfg, s.Name(), s.config); err != nil {
return nil, fmt.Errorf("failed to unmarshal config: %w", err)
}
}
@ -91,7 +93,7 @@ func (s *Server) init(kr keyring.Keyring) error {
// Sign(message) only passes once validator's signature is prepared
storeOpts := store.StoreOpts{
PkBytes: sckey,
PkBytes: sckey.Bytes(),
UseDurableStore: true,
DurableStoreFolder: s.storeDir,
}
@ -100,7 +102,7 @@ func (s *Server) init(kr keyring.Keyring) error {
bootPeers = strings.Split(c.BootPeers, ",")
}
messageOpts := p2pms.MessageOpts{
PkBytes: sckey,
PkBytes: sckey.Bytes(),
TcpPort: c.MsgPort,
WsMsgPort: c.WsMsgPort,
BootPeers: bootPeers,
@ -111,11 +113,13 @@ func (s *Server) init(kr keyring.Keyring) error {
ChainUrl: c.EthUrl,
ChainStartBlockNum: c.EthStartBlock,
ChainAuthToken: c.EthAuthToken,
ChainPk: hex.EncodeToString(ethkey),
NaAddress: common.HexToAddress(c.EthNaAddress),
VpaAddress: common.HexToAddress(c.EthVpaAddress),
CaAddress: common.HexToAddress(c.EthCaAddress),
// TODO delegation to distsig
// ChainPk: hex.EncodeToString(ethkey),
NaAddress: common.HexToAddress(c.EthNaAddress),
VpaAddress: common.HexToAddress(c.EthVpaAddress),
CaAddress: common.HexToAddress(c.EthCaAddress),
}
// Inject SDK logger into slog, which Nitro uses
loggerImpl, ok := s.logger.Impl().(*slog.Logger)
if !ok {
return errors.New("logger does not have slog implementation")
@ -127,7 +131,8 @@ func (s *Server) init(kr keyring.Keyring) error {
return err
}
s.Node = node
s.ScAddr = *store.GetAddress()
// s.EthAddress = crypto.GetAddressFromSecretKeyBytes(ethkey)
s.StateChannelAddress = *store.GetAddress()
return nil
}

View File

@ -8,7 +8,6 @@ import (
)
// Service represents a service which triggers Nitro state channel actions
// TODO
type Service interface {
// CreatePaymentChannel creates a new virtual payment channel with the specified intermediaries,
// counterparty, ChallengeDuration, and outcome

15
testutil/keyring.go Normal file
View File

@ -0,0 +1,15 @@
package testutil
import (
codectestutil "github.com/cosmos/cosmos-sdk/codec/testutil"
"github.com/cosmos/cosmos-sdk/crypto/keyring"
modtestutil "github.com/cosmos/cosmos-sdk/types/module/testutil"
"git.vdb.to/cerc-io/laconicd/utils"
)
func NewKeyring() keyring.Keyring {
codecOpts := codectestutil.NewCodecOptionsWithCodecs(utils.NewAddressCodec(), utils.NewValAddressCodec())
encCfg := modtestutil.MakeTestEncodingConfig(codecOpts)
return keyring.NewInMemory(encCfg.Codec)
}

View File

@ -1,4 +1,4 @@
package nitro
package utils
import (
errorsmod "cosmossdk.io/errors"
@ -19,14 +19,10 @@ func extractPrivKeyFromLocal(rl *keyring.Record_Local) (cryptotypes.PrivKey, err
return priv, nil
}
func extractPrivKeyBytes(kr keyring.Keyring, uid string) ([]byte, error) {
func ExtractPrivateKey(kr keyring.Keyring, uid string) (cryptotypes.PrivKey, error) {
ethkr, err := kr.Key(uid)
if err != nil {
return nil, err
}
ethkey, err := extractPrivKeyFromLocal(ethkr.GetLocal())
if err != nil {
return nil, err
}
return ethkey.Bytes(), nil
return extractPrivKeyFromLocal(ethkr.GetLocal())
}

View File

@ -2,17 +2,33 @@ package utils
import (
"github.com/ethereum/go-ethereum/common"
ethcrypto "github.com/ethereum/go-ethereum/crypto"
"github.com/statechannels/go-nitro/crypto"
)
func DecodeEthereumAddress(message []byte, sig string) (string, error) {
func DecodeEthereumAddress(message []byte, sig string) (common.Address, error) {
if len(sig) > 2 && sig[:2] == "0x" {
sig = sig[2:]
}
signature := crypto.SplitSignature(common.Hex2Bytes(sig))
ethereumAddress, err := crypto.RecoverEthereumMessageSigner(message, signature)
return ethereumAddress.String(), err
return crypto.RecoverEthMessageSignerAddress(message, signature)
}
func DecodeEthereumPubKey(message []byte, sig string) ([]byte, error) {
if len(sig) > 2 && sig[:2] == "0x" {
sig = sig[2:]
}
signature := crypto.SplitSignature(common.Hex2Bytes(sig))
return crypto.RecoverEthMessageSignerPubKey(message, signature)
}
func EthAddressFromPubKey(pubkey []byte) (common.Address, error) {
ecdsaPubKey, err := ethcrypto.UnmarshalPubkey(pubkey)
if err != nil {
return common.Address{}, err
}
return ethcrypto.PubkeyToAddress(*ecdsaPubKey), nil
}

View File

@ -5,7 +5,6 @@ import (
appmodule "cosmossdk.io/core/appmodule/v2"
banktypes "cosmossdk.io/x/bank/types"
sdk "github.com/cosmos/cosmos-sdk/types"
)

View File

@ -86,24 +86,27 @@ func (k Keeper) OnboardParticipant(
return nil, errorsmod.Wrap(sdkerrors.ErrInvalidRequest, "Invalid format for payload")
}
// Decode eth address from signature which should be the nitro address of the participant
nitroAddress, err := utils.DecodeEthereumAddress(message, msg.EthSignature)
// Decode eth pubkey from signature. The derived address should be the nitro address of the participant
nitroPubKey, err := utils.DecodeEthereumPubKey(message, msg.EthSignature)
if err != nil {
return nil, errorsmod.Wrap(sdkerrors.ErrInvalidRequest, "Failed to decode Ethereum address")
return nil, errorsmod.Wrap(sdkerrors.ErrInvalidRequest, "Failed to decode Ethereum public key")
}
nitroAddress, err := utils.EthAddressFromPubKey(nitroPubKey)
if err != nil {
return nil, errorsmod.Wrap(sdkerrors.ErrInvalidRequest, "Failed to derive Ethereum address from public key")
}
if nitroAddress != msg.EthPayload.Address {
return nil, errorsmod.Wrap(sdkerrors.ErrInvalidRequest, "Recovered ethereum address does not match the address set in payload")
if nitroAddress.String() != msg.EthPayload.Address {
return nil, errorsmod.Wrap(sdkerrors.ErrInvalidRequest, "Recovered Ethereum address does not match the address set in payload")
}
// TODO: redundant
cosmosAddr, err := k.addressCodec.BytesToString(signerAddress)
if err != nil {
return nil, err
}
participant := &onboarding.Participant{
CosmosAddress: cosmosAddr,
NitroAddress: nitroAddress,
PublicKey: nitroPubKey,
Role: msg.Role,
KycId: msg.KycId,
}

View File

@ -73,8 +73,8 @@ func (m *Params) GetOnboardingEnabled() bool {
type Participant struct {
// participant's cosmos (laconic) address
CosmosAddress string `protobuf:"bytes,1,opt,name=cosmos_address,json=cosmosAddress,proto3" json:"cosmos_address,omitempty" json:"cosmos_address" yaml:"cosmos_address"`
// participant's Nitro address
NitroAddress string `protobuf:"bytes,2,opt,name=nitro_address,json=nitroAddress,proto3" json:"nitro_address,omitempty" json:"nitro_address" yaml:"nitro_address"`
// full public key used to derive participant's Nitro address
PublicKey []byte `protobuf:"bytes,2,opt,name=public_key,json=publicKey,proto3" json:"public_key,omitempty"`
// participant's role (participant | validator)
Role string `protobuf:"bytes,3,opt,name=role,proto3" json:"role,omitempty" json:"role" yaml:"role"`
// participant's KYC receipt ID
@ -121,11 +121,11 @@ func (m *Participant) GetCosmosAddress() string {
return ""
}
func (m *Participant) GetNitroAddress() string {
func (m *Participant) GetPublicKey() []byte {
if m != nil {
return m.NitroAddress
return m.PublicKey
}
return ""
return nil
}
func (m *Participant) GetRole() string {
@ -206,32 +206,32 @@ func init() {
}
var fileDescriptor_59afed779274eaf0 = []byte{
// 399 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x6c, 0x92, 0xc1, 0xce, 0xd2, 0x40,
0x14, 0x85, 0xe9, 0x0f, 0xa2, 0x8e, 0x62, 0xe2, 0x44, 0x23, 0x4a, 0xec, 0x60, 0xdd, 0x60, 0x08,
0x9d, 0x10, 0x12, 0x4d, 0x74, 0x65, 0x13, 0x16, 0xee, 0x48, 0x17, 0x2e, 0xdc, 0x90, 0xe9, 0x4c,
0xad, 0x23, 0x6d, 0x87, 0xcc, 0x34, 0x8d, 0x7d, 0x0b, 0x9f, 0xc1, 0xa7, 0x71, 0xc9, 0xd2, 0x55,
0x63, 0xe0, 0x0d, 0xfa, 0x04, 0xa6, 0x33, 0x14, 0x28, 0xfe, 0xbb, 0x7b, 0xcf, 0x3d, 0xe7, 0xbb,
0xd3, 0xe6, 0x82, 0xd7, 0x34, 0x94, 0x14, 0x8b, 0x34, 0x10, 0x44, 0x32, 0x9e, 0x46, 0x38, 0x9f,
0x5f, 0x74, 0xee, 0x56, 0x8a, 0x4c, 0x40, 0x58, 0x9b, 0xdc, 0x0b, 0x39, 0x9f, 0xbf, 0x78, 0x12,
0x89, 0x48, 0xe8, 0x31, 0xae, 0x2b, 0xe3, 0x74, 0xb6, 0xa0, 0xbf, 0x22, 0x92, 0x24, 0x0a, 0x7e,
0x05, 0xf0, 0x1c, 0x58, 0x87, 0x29, 0x09, 0xe2, 0x90, 0x0d, 0xad, 0xb1, 0x35, 0xb9, 0xe7, 0xbd,
0xab, 0x4a, 0xb4, 0xf8, 0xae, 0x44, 0xfa, 0xde, 0xf9, 0xdf, 0xe3, 0x8c, 0x0b, 0x92, 0xc4, 0xb7,
0x4e, 0xfc, 0xc7, 0x67, 0x71, 0x79, 0xd4, 0x7e, 0xdd, 0x80, 0x07, 0x2b, 0x22, 0x33, 0x4e, 0xf9,
0x96, 0xa4, 0x19, 0xfc, 0x0c, 0x1e, 0x51, 0xa1, 0x12, 0xa1, 0xd6, 0x84, 0x31, 0x19, 0x2a, 0xa5,
0x77, 0xde, 0xf7, 0x70, 0x55, 0xa2, 0xa9, 0xd9, 0xd9, 0x9e, 0x37, 0xfb, 0xae, 0x54, 0x7f, 0x60,
0x84, 0x8f, 0xa6, 0x87, 0x3e, 0x18, 0xa4, 0x3c, 0x93, 0xe2, 0x84, 0xbd, 0xd1, 0xd8, 0x59, 0x55,
0xa2, 0x37, 0x06, 0xdb, 0x1a, 0x37, 0xd4, 0xb6, 0xe8, 0x3f, 0xd4, 0x7d, 0xc3, 0xc4, 0xa0, 0x27,
0x45, 0x1c, 0x0e, 0xbb, 0x1a, 0x35, 0xaa, 0x4a, 0xf4, 0xcc, 0xa0, 0x6a, 0xb5, 0x21, 0xe8, 0xda,
0xd7, 0x46, 0xf8, 0x16, 0xf4, 0x37, 0x05, 0x5d, 0x73, 0x36, 0xec, 0xe9, 0x08, 0xaa, 0x4a, 0x34,
0x32, 0x11, 0xa3, 0x37, 0xa1, 0x63, 0xe7, 0xdf, 0xd9, 0x14, 0xf4, 0x13, 0x73, 0x72, 0x00, 0x96,
0xd9, 0xb7, 0x15, 0x29, 0x62, 0x41, 0x18, 0xfc, 0x00, 0xee, 0xb6, 0xff, 0xcd, 0xab, 0xaa, 0x44,
0x2f, 0x0d, 0xe6, 0xea, 0xf9, 0xa7, 0x87, 0x37, 0x09, 0x38, 0x05, 0xdd, 0x44, 0x45, 0xc7, 0xaf,
0x7f, 0x5e, 0x95, 0xe8, 0xa9, 0x09, 0x26, 0x2a, 0x6a, 0x42, 0x75, 0xe9, 0xd7, 0x2e, 0xcf, 0xfb,
0xbd, 0xb7, 0xad, 0xdd, 0xde, 0xb6, 0xfe, 0xee, 0x6d, 0xeb, 0xe7, 0xc1, 0xee, 0xec, 0x0e, 0x76,
0xe7, 0xcf, 0xc1, 0xee, 0x7c, 0x99, 0x44, 0x3c, 0x73, 0x73, 0x16, 0xb8, 0x99, 0xc0, 0xf5, 0x75,
0xcd, 0xb8, 0xc0, 0x31, 0xa1, 0x22, 0xe5, 0x94, 0xe1, 0x1f, 0x17, 0x27, 0x18, 0xf4, 0xf5, 0x65,
0x2d, 0xfe, 0x05, 0x00, 0x00, 0xff, 0xff, 0x87, 0xe5, 0xd5, 0x6b, 0xaa, 0x02, 0x00, 0x00,
// 397 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x6c, 0x92, 0x3f, 0x8b, 0xdb, 0x30,
0x18, 0xc6, 0xe3, 0x26, 0x4d, 0x1b, 0xf5, 0x0f, 0x54, 0xb4, 0xd4, 0x6d, 0x88, 0x9d, 0xba, 0x4b,
0x20, 0xd4, 0x22, 0x04, 0x5a, 0x68, 0xa7, 0x1a, 0x32, 0x94, 0x2e, 0xc1, 0x43, 0x87, 0x2e, 0x46,
0x96, 0x5c, 0x57, 0x17, 0xdb, 0x32, 0x96, 0xcf, 0x9c, 0xbf, 0xc5, 0x7d, 0xac, 0x1b, 0x33, 0xde,
0x64, 0x8e, 0x64, 0xbe, 0xc5, 0x9f, 0xe0, 0xb0, 0x14, 0x5f, 0xfe, 0xdc, 0x6d, 0x7a, 0x7f, 0xef,
0xf3, 0xe8, 0xe1, 0x81, 0x17, 0x7c, 0x26, 0x41, 0x46, 0x10, 0x4f, 0x7c, 0x8e, 0x33, 0xca, 0x92,
0x10, 0x15, 0xb3, 0x83, 0xc9, 0x4e, 0x33, 0x9e, 0x73, 0x08, 0x1b, 0x91, 0x7d, 0x80, 0x8b, 0xd9,
0xc7, 0xb7, 0x21, 0x0f, 0xb9, 0x5c, 0xa3, 0xe6, 0xa5, 0x94, 0x56, 0x0a, 0xfa, 0x4b, 0x9c, 0xe1,
0x58, 0xc0, 0x7f, 0x00, 0xee, 0x0d, 0x5e, 0x90, 0x60, 0x3f, 0x0a, 0xa8, 0xae, 0x8d, 0xb5, 0xc9,
0x73, 0xe7, 0x5b, 0x5d, 0x99, 0xf3, 0x33, 0xc1, 0x93, 0xef, 0xd6, 0x43, 0x8d, 0x35, 0x2e, 0x71,
0x1c, 0x3d, 0xba, 0x71, 0xdf, 0xec, 0xe1, 0x62, 0xc7, 0x6e, 0x35, 0xf0, 0x62, 0x89, 0xb3, 0x9c,
0x11, 0x96, 0xe2, 0x24, 0x87, 0x7f, 0xc0, 0x6b, 0xc2, 0x45, 0xcc, 0x85, 0x87, 0x29, 0xcd, 0x02,
0x21, 0x64, 0xe6, 0xc0, 0x41, 0x75, 0x65, 0x4e, 0x55, 0xe6, 0xf1, 0xbe, 0xcd, 0x3b, 0xa1, 0xee,
0x2b, 0x05, 0x7e, 0xaa, 0x19, 0x8e, 0x00, 0x48, 0xcf, 0xfd, 0x88, 0x11, 0x6f, 0x15, 0x94, 0xfa,
0x93, 0xb1, 0x36, 0x79, 0xe9, 0x0e, 0x14, 0xf9, 0x1d, 0x94, 0x10, 0x81, 0x5e, 0xc6, 0xa3, 0x40,
0xef, 0xca, 0xb0, 0x61, 0x5d, 0x99, 0xef, 0x55, 0x58, 0x43, 0xdb, 0x08, 0xf9, 0x76, 0xa5, 0x10,
0x7e, 0x05, 0xfd, 0x55, 0x49, 0x3c, 0x46, 0xf5, 0x9e, 0xb4, 0x98, 0x75, 0x65, 0x0e, 0x95, 0x45,
0xf1, 0xd6, 0xb4, 0x9b, 0xdc, 0xa7, 0xab, 0x92, 0xfc, 0xa2, 0x56, 0x01, 0xc0, 0x22, 0xff, 0xbf,
0xc4, 0x65, 0xc4, 0x31, 0x85, 0x3f, 0xc0, 0xb3, 0xe3, 0x9a, 0x9f, 0xea, 0xca, 0x1c, 0xa9, 0x6f,
0x4e, 0xfa, 0xdd, 0x17, 0x6b, 0x1d, 0x70, 0x0a, 0xba, 0xb1, 0x08, 0x65, 0x97, 0x81, 0xf3, 0xa1,
0xae, 0xcc, 0x77, 0xca, 0x18, 0x8b, 0xb0, 0x35, 0x35, 0x4f, 0xb7, 0x51, 0x39, 0xce, 0xd5, 0xc6,
0xd0, 0xd6, 0x1b, 0x43, 0xbb, 0xd9, 0x18, 0xda, 0xe5, 0xd6, 0xe8, 0xac, 0xb7, 0x46, 0xe7, 0x7a,
0x6b, 0x74, 0xfe, 0x4e, 0x42, 0x96, 0xdb, 0x05, 0xf5, 0xed, 0x9c, 0xa3, 0xe6, 0x50, 0xbe, 0x30,
0x8e, 0x22, 0x4c, 0x78, 0xc2, 0x08, 0x45, 0x17, 0x07, 0xd7, 0xe4, 0xf7, 0xe5, 0x91, 0xcc, 0xef,
0x02, 0x00, 0x00, 0xff, 0xff, 0xdb, 0xbd, 0x79, 0xd2, 0x75, 0x02, 0x00, 0x00,
}
func (m *Params) Marshal() (dAtA []byte, err error) {
@ -301,10 +301,10 @@ func (m *Participant) MarshalToSizedBuffer(dAtA []byte) (int, error) {
i--
dAtA[i] = 0x1a
}
if len(m.NitroAddress) > 0 {
i -= len(m.NitroAddress)
copy(dAtA[i:], m.NitroAddress)
i = encodeVarintOnboarding(dAtA, i, uint64(len(m.NitroAddress)))
if len(m.PublicKey) > 0 {
i -= len(m.PublicKey)
copy(dAtA[i:], m.PublicKey)
i = encodeVarintOnboarding(dAtA, i, uint64(len(m.PublicKey)))
i--
dAtA[i] = 0x12
}
@ -388,7 +388,7 @@ func (m *Participant) Size() (n int) {
if l > 0 {
n += 1 + l + sovOnboarding(uint64(l))
}
l = len(m.NitroAddress)
l = len(m.PublicKey)
if l > 0 {
n += 1 + l + sovOnboarding(uint64(l))
}
@ -559,9 +559,9 @@ func (m *Participant) Unmarshal(dAtA []byte) error {
iNdEx = postIndex
case 2:
if wireType != 2 {
return fmt.Errorf("proto: wrong wireType = %d for field NitroAddress", wireType)
return fmt.Errorf("proto: wrong wireType = %d for field PublicKey", wireType)
}
var stringLen uint64
var byteLen int
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowOnboarding
@ -571,23 +571,25 @@ func (m *Participant) Unmarshal(dAtA []byte) error {
}
b := dAtA[iNdEx]
iNdEx++
stringLen |= uint64(b&0x7F) << shift
byteLen |= int(b&0x7F) << shift
if b < 0x80 {
break
}
}
intStringLen := int(stringLen)
if intStringLen < 0 {
if byteLen < 0 {
return ErrInvalidLengthOnboarding
}
postIndex := iNdEx + intStringLen
postIndex := iNdEx + byteLen
if postIndex < 0 {
return ErrInvalidLengthOnboarding
}
if postIndex > l {
return io.ErrUnexpectedEOF
}
m.NitroAddress = string(dAtA[iNdEx:postIndex])
m.PublicKey = append(m.PublicKey[:0], dAtA[iNdEx:postIndex]...)
if m.PublicKey == nil {
m.PublicKey = []byte{}
}
iNdEx = postIndex
case 3:
if wireType != 2 {