-
Notifications
You must be signed in to change notification settings - Fork 4
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #761 from oasisprotocol/andrew7234/misc-fixes
Post-reindex hotfixes
- Loading branch information
Showing
11 changed files
with
477 additions
and
945 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
post-reindex fixes | ||
|
||
This PR combines several minor fixes that were applied during | ||
the reindex of production. | ||
|
||
1. Damask-style proposals are now unmarshalled correctly | ||
2. Cobalt PVSS txs are now unmarshalled correctly using vendored | ||
oasis-core types. | ||
3. TakeEscrow events are now indexed properly. | ||
4. minor bump in oapi-codegen version to v1.12. A subsequent PR | ||
will bump it to v2 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,105 @@ | ||
// Package pvss implements a PVSS backed commit-reveal scheme loosely | ||
// based on the Scalable Randomness Attested by Public Entities | ||
// protocol by Casudo and David. | ||
// | ||
// In practice this implementation omits the things that make SCRAPE | ||
// scalable/fast, and is just a consensus backed PVSS based beacon. | ||
// The differences are as follows: | ||
// | ||
// - The coding theory based share verification mechanism is not | ||
// implemented. The check is as in Schoenmakers' paper. This | ||
// could be added at a future date for a performance gain. | ||
// | ||
// - The commit/reveal based fast path that skips having to recover | ||
// each participant's secret if they submitted a protocol level | ||
// reveal is omitted. It is possible to game the system by | ||
// publishing shares for one secret and a commitment for another | ||
// secret, and then choosing to reveal or not after everyone else | ||
// has revealed. While this behavior is detectable, it either | ||
// involves having to recover the secret from the shares anyway | ||
// rendering the optimization moot, or having a userbase that | ||
// understands that slashing is integral to the security of the | ||
// system. | ||
// | ||
// See: https://eprint.iacr.org/2017/216.pdf | ||
package pvss | ||
|
||
import "go.dedis.ch/kyber/v3/group/nist" | ||
|
||
var ( | ||
// Yes, this uses the NIST P-256 curve, due to vastly superior | ||
// performance compared to kyber's Ed25519 implementation. In | ||
// theory Ed25519 should be faster, but the runtime library's | ||
// P-256 scalar multiply is optimized, and kyber's Ed25519 | ||
// is basically ref10. | ||
suite = nist.NewBlakeSHA256P256() | ||
) | ||
|
||
// Config is the configuration for an execution of the PVSS protocol. | ||
// removed type | ||
|
||
// Instance is an instance of the PVSS protocol. | ||
// removed type | ||
|
||
// SetScalar sets the private scalar belonging to an instance. Under | ||
// most circumstances this will be handled by the constructor. | ||
// removed func | ||
|
||
// Commit executes the commit phase of the protocol, generating a commitment | ||
// message to be broadcasted to all participants. | ||
// removed func | ||
|
||
// OnCommit processes a commitment message received from a participant. | ||
// | ||
// Note: This assumes that the commit is authentic and attributable. | ||
// removed func | ||
|
||
// MayReveal returns true iff it is possible to proceed to the reveal | ||
// step, and the total number of distinct valid commitments received. | ||
// removed func | ||
|
||
// Reveal executes the reveal phase of the protocol, generating a reveal | ||
// message to be broadcasted to all participants. | ||
// removed func | ||
|
||
// OnReveal processes a reveal message received from a participant. | ||
// | ||
// Note: This assumes that the reveal is authentic and attributable. | ||
// removed func | ||
|
||
// MayRecover returns true iff it is possible to proceed to the recovery | ||
// step, and the total number of distinct valid reveals received. | ||
// removed func | ||
|
||
// Recover executes the recovery phase of the protocol, returning the resulting | ||
// composite entropy and the indexes of the participants that contributed fully. | ||
// removed func | ||
|
||
// New creates a new protocol instance with the provided configuration. | ||
// removed func | ||
|
||
// removed func | ||
|
||
// removed func | ||
|
||
// NewKeyPair creates a new scalar/point pair for use with a PVSS instance. | ||
// removed func | ||
|
||
// Commit is a PVSS commit. | ||
type Commit struct { | ||
Index int `json:"index"` | ||
Shares []*CommitShare `json:"shares"` | ||
} | ||
|
||
// Reveal is a PVSS reveal. | ||
type Reveal struct { | ||
Index int `json:"index"` | ||
DecryptedShares map[int]*PubVerShare `json:"decrypted_shares"` | ||
} | ||
|
||
// CommitState is a PVSS commit and the corresponding decrypted share, | ||
// if any. | ||
type CommitState struct { | ||
Commit *Commit `json:"commit"` | ||
DecryptedShare *PubVerShare `json:"decrypted_share,omitempty"` | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,232 @@ | ||
package pvss | ||
|
||
import ( | ||
"crypto/elliptic" | ||
"encoding/base64" | ||
"fmt" | ||
|
||
"go.dedis.ch/kyber/v3" | ||
) | ||
|
||
// As convenient as it is to use kyber's PVSS implementation, scalars and | ||
// points being interfaces makes s11n a huge pain, and mandates using | ||
// wrapper types so that this can play nice with CBOR/JSON etc. | ||
// | ||
// Aut viam inveniam aut faciam. | ||
|
||
// Point is an elliptic curve point. | ||
type Point struct { | ||
inner kyber.Point | ||
} | ||
|
||
// Inner returns the actual kyber.Point. | ||
// removed func | ||
|
||
// UnmarshalBinary implements the encoding.BinaryUnmarshaler interface. | ||
func (p *Point) UnmarshalBinary(data []byte) error { | ||
inner := suite.Point() | ||
if err := inner.UnmarshalBinary(data); err != nil { | ||
return fmt.Errorf("pvss/s11n: failed to deserialize point: %w", err) | ||
} | ||
|
||
checkPoint := Point{inner: inner} | ||
if err := checkPoint.isWellFormed(); err != nil { | ||
return fmt.Errorf("pvss/s11n: deserialized point is invalid: %w", err) | ||
} | ||
if checkPoint2, ok := inner.(isCanonicalAble); ok { | ||
// edwards25519.Point.IsCanonical takes a buffer, since points | ||
// that get serialized are always in canonical form. | ||
if !checkPoint2.IsCanonical(data) { | ||
return fmt.Errorf("pvss/s11n: point is not in canonical form") | ||
} | ||
} | ||
|
||
p.inner = inner | ||
|
||
return nil | ||
} | ||
|
||
// UnmarshalPEM decodes a PEM marshaled point. | ||
// removed func | ||
|
||
// UnmarshalText decodes a text marshaled point. | ||
func (p *Point) UnmarshalText(text []byte) error { | ||
b, err := base64.StdEncoding.DecodeString(string(text)) | ||
if err != nil { | ||
return fmt.Errorf("pvss/s11n: failed to deserialize base64 encoded point: %w", err) | ||
} | ||
|
||
return p.UnmarshalBinary(b) | ||
} | ||
|
||
// MarshalBinary implements the encoding.BinaryMarshaler interface. | ||
func (p Point) MarshalBinary() ([]byte, error) { | ||
if err := p.isWellFormed(); err != nil { | ||
return nil, fmt.Errorf("pvss/s11n: refusing to serialize invalid point: %w", err) | ||
} | ||
|
||
data, err := p.inner.MarshalBinary() | ||
if err != nil { | ||
return nil, fmt.Errorf("pvss/s11n: failed to serialize point: %w", err) | ||
} | ||
|
||
return data, nil | ||
} | ||
|
||
// MarshalPEM encodes a point into PEM form. | ||
// removed func | ||
|
||
// MarshalText encodes a point into text form. | ||
func (p *Point) MarshalText() ([]byte, error) { | ||
b, err := p.MarshalBinary() | ||
if err != nil { | ||
return nil, err | ||
} | ||
|
||
return []byte(base64.StdEncoding.EncodeToString(b)), nil | ||
} | ||
|
||
// LoadPEM loads a point from a PEM file on disk. Iff the point is missing | ||
// and a Scalar is provided, the Scalar's corresponding point will be written | ||
// and loaded. | ||
// removed func | ||
|
||
func (p *Point) isWellFormed() error { | ||
// Can never happen(?), but check anyway. | ||
if p.inner == nil { | ||
return fmt.Errorf("pvss/s11n: point is missing") | ||
} | ||
|
||
if !pointIsValid(p.inner) { | ||
return fmt.Errorf("pvss/s11n: point is invalid") | ||
} | ||
|
||
return nil | ||
} | ||
|
||
type validAble interface { | ||
Valid() bool | ||
} | ||
|
||
type hasSmallOrderAble interface { | ||
HasSmallOrder() bool | ||
} | ||
|
||
type isCanonicalAble interface { | ||
IsCanonical([]byte) bool | ||
} | ||
|
||
func pointIsValid(point kyber.Point) bool { | ||
switch validator := point.(type) { | ||
case validAble: | ||
// P-256 point validation (ensures point is on curve) | ||
// | ||
// Note: Kyber's idea of a valid point includes the point at | ||
// infinity, which does not ensure contributory behavior when | ||
// doing ECDH. | ||
|
||
// We write out the point to binary data, and unmarshal | ||
// it with elliptic.Unmarshal, which checks to see if the | ||
// point is on the curve (while rejecting the point at | ||
// infinity). | ||
// | ||
// In theory, we could just examine the x/y coordinates, but | ||
// there's no way to get at those without reflection hacks. | ||
// | ||
// WARNING: If this ever needs to support NIST curves other | ||
// than P-256, this will need to get significantly more | ||
// involved. | ||
b, err := point.MarshalBinary() | ||
if err != nil { | ||
return false | ||
} | ||
if x, _ := elliptic.Unmarshal(elliptic.P256(), b); x == nil { | ||
return false | ||
} | ||
return true | ||
case hasSmallOrderAble: | ||
// Ed25519 point validation (rejects small-order points) | ||
return !validator.HasSmallOrder() | ||
default: | ||
return false | ||
} | ||
} | ||
|
||
// removed func | ||
|
||
// Scalar is a scalar. | ||
type Scalar struct { | ||
inner kyber.Scalar | ||
} | ||
|
||
// Inner returns the actual kyber.Scalar. | ||
// removed func | ||
|
||
// Point returns the corresponding point. | ||
// removed func | ||
|
||
// UnmarshalBinary implements the encoding.BinaryUnmarshaler interface. | ||
func (s *Scalar) UnmarshalBinary(data []byte) error { | ||
inner := suite.Scalar() | ||
if err := inner.UnmarshalBinary(data); err != nil { | ||
return fmt.Errorf("pvss/s11n: failed to deserialize scalar: %w", err) | ||
} | ||
|
||
s.inner = inner | ||
|
||
return nil | ||
} | ||
|
||
// UnmarshalPEM decodes a PEM marshaled scalar. | ||
// removed func | ||
|
||
// MarshalBinary implements the encoding.BinaryMarshaler interface. | ||
func (s Scalar) MarshalBinary() ([]byte, error) { | ||
data, err := s.inner.MarshalBinary() | ||
if err != nil { | ||
return nil, fmt.Errorf("pvss/s11n: failed to serialize scalar: %w", err) | ||
} | ||
|
||
return data, nil | ||
} | ||
|
||
// MarshalPEM encodes a scalar into PEM form. | ||
// removed func | ||
|
||
// LoadOrGeneratePEM loads a scalar from a PEM file on disk. Iff the | ||
// scalar is missing, a new one will be generated, written, and loaded. | ||
// removed func | ||
|
||
// removed func | ||
|
||
// removed func | ||
|
||
// PubVerShare is a public verifiable share (`pvss.PubVerShare`) | ||
type PubVerShare struct { | ||
V Point `json:"v"` // Encrypted/decrypted share | ||
|
||
C Scalar `json:"c"` // Challenge | ||
R Scalar `json:"r"` // Response | ||
VG Point `json:"vg"` // Public commitment with respect to base point G | ||
VH Point `json:"vh"` // Public commitment with respect to base point H | ||
} | ||
|
||
// removed func | ||
|
||
// removed func | ||
|
||
// removed func | ||
|
||
// CommitShare is a commit share. | ||
type CommitShare struct { | ||
PolyV Point `json:"poly_v"` // Share of the public commitment polynomial | ||
PubVerShare | ||
} | ||
|
||
// removed func | ||
|
||
// removed func | ||
|
||
// removed func | ||
|
||
// removed func |
Oops, something went wrong.