Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Multisig Promotion #1014

Draft
wants to merge 6 commits into
base: master
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
109 changes: 109 additions & 0 deletions common/factoid/fullsignatureblock.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@
package factoid

import (
"github.com/FactomProject/factomd/common/interfaces"
"github.com/FactomProject/factomd/common/primitives"
)

type FullSignatureBlock struct {
Signatures []interfaces.IFullSignature `json:"signatures"`
}

var _ interfaces.IFullSignatureBlock = (*FullSignatureBlock)(nil)

func (fsb *FullSignatureBlock) AddSignature(sig interfaces.IFullSignature) {
fsb.Signatures = append(fsb.Signatures, sig)
}

func (fsb *FullSignatureBlock) GetSignature(index int) interfaces.IFullSignature {
if index < 0 || index >= len(fsb.Signatures) {
return nil
}
return fsb.Signatures[index]
}
func (fsb *FullSignatureBlock) GetSignatures() []interfaces.IFullSignature {
return fsb.Signatures
}
func (fsb *FullSignatureBlock) IsSameAs(other interfaces.IFullSignatureBlock) bool {
sigs := other.GetSignatures()
if len(fsb.Signatures) != len(sigs) {
return false
}

for i := range fsb.Signatures {
if !fsb.Signatures[i].IsSameAs(sigs[i]) {
return false
}
}
return true
}

func (fsb *FullSignatureBlock) JSONByte() ([]byte, error) {
return primitives.EncodeJSON(fsb)
}

func (fsb *FullSignatureBlock) JSONString() (string, error) {
return primitives.EncodeJSONString(fsb)
}

func (fsb FullSignatureBlock) MarshalBinary() ([]byte, error) {
sigs := fsb.GetSignatures()
buf := primitives.NewBuffer(nil)
buf.PushVarInt(uint64(len(sigs)))
for _, sig := range sigs {
err := buf.PushBinaryMarshallable(sig)
if err != nil {
return nil, err
}
}
return buf.DeepCopyBytes(), nil
}

func (fsb *FullSignatureBlock) UnmarshalBinary(data []byte) error {
if _, err := fsb.UnmarshalBinaryData(data); err != nil {
return err
}
return nil
}

func (fsb *FullSignatureBlock) UnmarshalBinaryData(data []byte) ([]byte, error) {
buf := primitives.NewBuffer(data)

length, err := buf.PopVarInt()
if err != nil {
return nil, err
}

fsb.Signatures = make([]interfaces.IFullSignature, length)
for i := uint64(0); i < length; i++ {
fsb.Signatures[i] = new(primitives.Signature)
if err := buf.PopBinaryMarshallable(fsb.Signatures[i]); err != nil {
return nil, err
}
}

return buf.DeepCopyBytes(), nil
}

func (fsb *FullSignatureBlock) String() string {
var out primitives.Buffer

out.WriteString("Signature Block: \n")
for _, sig := range fsb.Signatures {
out.WriteString(" signature: ")
if txt, err := sig.CustomMarshalText(); err != nil {
out.WriteString("<error> ")
out.WriteString(err.Error())
} else {
out.Write(txt)
}
out.WriteString("\n ")
}

return out.String()
}

func NewFullSignatureBlock() *FullSignatureBlock {
fsb := new(FullSignatureBlock)
return fsb
}
50 changes: 50 additions & 0 deletions common/factoid/fullsignatureblock_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
package factoid_test

import (
"math/rand"
"testing"

"github.com/FactomProject/factomd/common/factoid"
"github.com/FactomProject/factomd/common/interfaces"
"github.com/FactomProject/factomd/common/primitives"
)

func testSig() interfaces.IFullSignature {
sig := new(primitives.Signature)
sig.Init()
rand.Read(sig.Pub[:])
rand.Read(sig.Sig[:])
return sig
}

func TestFullSignatureBlock_AddGetSignature(t *testing.T) {
block := factoid.NewFullSignatureBlock()
other := factoid.NewFullSignatureBlock()
sigs := make([]interfaces.IFullSignature, 32)
for i := range sigs {
sigs[i] = testSig()
block.AddSignature(sigs[i])
other.AddSignature(sigs[i])
}

if !block.IsSameAs(other) {
t.Errorf("two equal blocks did not match")
}

allsigs := block.GetSignatures()

if len(allsigs) != len(sigs) {
t.Fatalf("not enough sigs in block. got = %d, want = %d", len(allsigs), len(sigs))
}

for i := range sigs {
if !sigs[i].IsSameAs(block.GetSignature(i)) {
t.Errorf("Signature index mismatch. index = %d, got = %v, want = %v", i, block.GetSignature(i), sigs[i])
}

if !sigs[i].IsSameAs(allsigs[i]) {
t.Errorf("Signature mismatch. index = %d, got = %v, want = %v", i, block.GetSignature(i), sigs[i])
}
}

}
7 changes: 7 additions & 0 deletions common/interfaces/msgFactory.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,3 +14,10 @@ type Signable interface {
IsValid() bool // Signature already checked
SetValid() // Mark as validated so we don't have to repeat.
}

type MultiSignable interface {
AddSignature(Signer) error
MarshalForSignature() ([]byte, error)
GetSignatures() []IFullSignature
VerifySignatures() ([]IFullSignature, error)
}
10 changes: 10 additions & 0 deletions common/interfaces/signature.go
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,16 @@ type ISignatureBlock interface {
IsSameAs(ISignatureBlock) bool
}

type IFullSignatureBlock interface {
BinaryMarshallable
Printable

AddSignature(sig IFullSignature)
GetSignature(int) IFullSignature
GetSignatures() []IFullSignature
IsSameAs(IFullSignatureBlock) bool
}

type ISignable interface {
Sign(privateKey []byte) error
MarshalBinarySig() ([]byte, error)
Expand Down
Loading