diff options
author | Özgür Kesim <oec@codeblau.de> | 2024-04-05 18:06:35 +0200 |
---|---|---|
committer | Özgür Kesim <oec@codeblau.de> | 2024-04-05 18:06:35 +0200 |
commit | 5733f293044bfe0d3210e7c4688172d53d54a7e0 (patch) | |
tree | b8f3da57d83410a9b3f7efe0b856729ca48d804b | |
parent | e735cff1d63145b89c4c48b9d73f037d3a4305f4 (diff) |
client: started work on API for client, wip
- auction defines description of an auction
- client creates auction object, given a description
- commitment/* merged into client
-rw-r--r-- | auction.go | 44 | ||||
-rw-r--r-- | client/bid.go | 62 | ||||
-rw-r--r-- | client/bid_test.go | 27 | ||||
-rw-r--r-- | client/client.go | 54 | ||||
-rw-r--r-- | client/option.go | 18 | ||||
-rw-r--r-- | commitment/commitment.go | 59 | ||||
-rw-r--r-- | main.go | 35 |
7 files changed, 205 insertions, 94 deletions
diff --git a/auction.go b/auction.go new file mode 100644 index 0000000..50d6a2b --- /dev/null +++ b/auction.go @@ -0,0 +1,44 @@ +package seal + +import ( + "crypto" + "net/url" + "time" +) + +type Type int + +const ( + TypHighest = iota + TypSecondHighest +) + +// Auction describes the asset of an auction and other +// relevant meta-data +type Description struct { + DashboardUrl *url.URL // can be empty + Start time.Time + End time.Time + RoundTimeout time.Duration // Timeout per round by which all responses must have arrived + BitLength uint8 // Length of the price encoding + Currency string + Type Type + SellerPublicKey crypto.PublicKey // Public key of the Seller +} + +// The SignedAuction contains an Auction and the signature, +// signed by the seller's public key off the SHA512 hash of +// the normalized JSON-object. +// TODO(oec): normalized? +type SignedDesciption struct { + Description + SellerSignature string +} + +// Bidder is the interface that the Auction engine uses to communicate +// with an bidder implementation +type Bidder interface { + Result() + Broadcast() + Unicast() +} diff --git a/client/bid.go b/client/bid.go new file mode 100644 index 0000000..3651d1d --- /dev/null +++ b/client/bid.go @@ -0,0 +1,62 @@ +package client + +import ( + "crypto/ed25519" + "fmt" + + . "kesim.org/seal/nizk" + + "kesim.org/seal/nizk/commit" +) + +type bid struct { + id ed25519.PrivateKey + ID ed25519.PublicKey + + price uint64 // bigendian encoding of the bid + n uint8 // number of bits encoded in zbid. + + // bits are derived from zbid and the zero element in + // the slice corresponds to the highest bit in zbid + bits []*commit.Statement +} + +// NewBid creates a new Bidder for the given price, using the lower bits up to bitlength +func newBid(price uint64, bitlength uint8) (*bid, error) { + if bitlength > 63 { + return nil, fmt.Errorf("bitlength too large, maximum is 63") + } else if 0 != (price >> bitlength) { + return nil, fmt.Errorf("price %d too large for given bitlength %d", price, bitlength) + } + + var ( + e error + bid = &bid{ + price: price, + } + ) + + bid.ID, bid.id, e = ed25519.GenerateKey(nil) + if e != nil { + return nil, e + } + + bid.bits = make([]*commit.Statement, bitlength) + for i := bitlength; i > 0; i-- { + set := (price>>(i-1)&1 != 0) + a, b := Curve.RandomScalar(), Curve.RandomScalar() + bid.bits[i-1] = commit.NewStatement(a, b, set) + } + + return bid, nil +} + +// Commit returns the public commitment to the bits and a signature +// TODO: return signature over bid +func (bid *bid) Commit() (c []*commit.Commitment, pub ed25519.PublicKey, sig []byte) { + c = make([]*commit.Commitment, len(bid.bits)) + for i := range bid.bits { + c[i] = bid.bits[i].Commit() + } + return c, bid.ID, nil +}
\ No newline at end of file diff --git a/client/bid_test.go b/client/bid_test.go new file mode 100644 index 0000000..52c4c3c --- /dev/null +++ b/client/bid_test.go @@ -0,0 +1,27 @@ +package client + +import ( + "testing" +) + +func TestBitlengthTooLarge(t *testing.T) { + bid, e := newBid(0xFFFFFF, 70) + if e == nil { + t.Fatalf("failure expected, but got bid: %#v", bid) + } +} + +func TestPriceTooLarge(t *testing.T) { + bid, e := newBid(0xFFFFFF, 8) + if e == nil { + t.Fatalf("failure expected, but got bid: %#v", bid) + } +} + +func TestBidOK(t *testing.T) { + bid, e := newBid(102400, 24) + if e != nil { + t.Fatalf("unexpected error: %v", e) + } + t.Logf("Bid: %+v", bid) +}
\ No newline at end of file diff --git a/client/client.go b/client/client.go new file mode 100644 index 0000000..19f0d35 --- /dev/null +++ b/client/client.go @@ -0,0 +1,54 @@ +package client + +import ( + "fmt" + "log" + "os" + + "kesim.org/seal" +) + +type Auction struct { + description *seal.Description + + bid *bid + + log func(string, ...any) + verbose func(string, ...any) + debug func(string, ...any) +} + +func nullf(string, ...any) {} + +func NewAuction(description *seal.Description, options ...Option) (auction *Auction, e error) { + if description.BitLength > 63 { + return nil, fmt.Errorf("Invalid BitLength in description: %d", description.BitLength) + } + + logger := log.New(os.Stdout, "[seal::client] ", log.LstdFlags) + + auction = &Auction{ + description: description, + log: logger.Printf, + verbose: nullf, + debug: nullf, + } + + for _, opt := range options { + opt(auction) + } + + return auction, nil +} + +func (a *Auction) Join(price uint64) error { + bid, e := newBid(price, a.description.BitLength) + if e != nil { + return e + } + + a.debug("created bid: %#v\n", bid) + + a.bid = bid + return nil +} diff --git a/client/option.go b/client/option.go new file mode 100644 index 0000000..c2b1e5d --- /dev/null +++ b/client/option.go @@ -0,0 +1,18 @@ +package client + +import ( + "log" + "os" +) + +type Option func(auction *Auction) + +func OptVerbose(a *Auction) { + logger := log.New(os.Stdout, "[seal::client][verbose] ", log.LstdFlags) + a.verbose = logger.Printf +} + +func OptDebug(a *Auction) { + logger := log.New(os.Stdout, "[seal::client][debug] ", log.LstdFlags) + a.debug = logger.Printf +} diff --git a/commitment/commitment.go b/commitment/commitment.go deleted file mode 100644 index c958987..0000000 --- a/commitment/commitment.go +++ /dev/null @@ -1,59 +0,0 @@ -// Implements the data structures and methods for -// creating a commitment for the SEAL protocol -package commitment - -import ( - "fmt" - - "kesim.org/seal/curve" -) - -type Scalar = curve.Curve25519Scalar -type Point = curve.Curve25519Point - -var Curve = curve.Curve25519 - -type Bidder struct { - private struct { - id *Scalar - } - Id *Point -} - -type Bid struct { - Bidder *Point - zbid uint64 // bigendian encoding of the bid - n uint8 // number of bits encoded in zbid. - bits []Bit // derived from zbid -} - -type Bit struct { - set bool - a *Scalar - b *Scalar - com *BitCommitment -} - -type BitCommitment struct { - Gab *Point - A *Point - B *Point - - Proofs struct { - A *Proof - B *Proof - } -} - -type Proof struct { - V *Point `json:"V"` - R *Scalar `json:"r"` -} - -func NewBid(price uint64, bitlength uint8) (*Bidder, error) { - if bitlength > 63 { - return nil, fmt.Errorf("bitlength too large, maximum is 63") - } - - return nil, fmt.Errorf("NewBid not implemented") -}
\ No newline at end of file diff --git a/main.go b/main.go deleted file mode 100644 index 4d497a8..0000000 --- a/main.go +++ /dev/null @@ -1,35 +0,0 @@ -package seal - -import ( - "crypto" - "time" -) - -// Auction describes the asset of an auction and other -// relevant meta-data -type Auction struct { - // Start date - Start time.Time - // End date - End time.Time - // Timeout per round by which all responses must have arrived - RoundTimeout time.Duration - - // Sha512 Hash of the Asset - AssetHash string - - // Public key of the Seller - SellerPublicKey crypto.PublicKey -} - -// The SignedAuction contains an Auction and the signature, -// signed by the seller's public key off the SHA512 hash of -// the normalized JSON-object. TODO(oec): normalized? -type SignedAuction struct { - Auction - SellerSignature string -} - -// The published commiment of a participant -type Commitment struct { -} |