mirror of
https://github.com/lightninglabs/pool.git
synced 2026-08-14 12:43:03 +02:00
In this commit, we overhaul the keys used in the multi-sig construction of an account to prevent script reuse and provide plausible deniability between account outputs to third parties. This is done by tweaking the trader's key with two new components: 1. A per-batch key, which is obtained from the auctioneer during account creation. Every time the account is modified or participates in a cleared batch within the system, the per-batch key is incremented by the curve's base point, resulting in a different key used in the account script. 2. A shared secret derived using Diffie-Hellman between the trader's and auctioneer's base keys. By using this secret, we provide plausible deniability to third parties with knowledge of the base keys and per-batch key. The resulting tweaked key for the trader is then used as the tweak for the auctioneer's base key.
170 lines
3.8 KiB
Go
170 lines
3.8 KiB
Go
package clientdb
|
|
|
|
import (
|
|
"encoding/binary"
|
|
"io"
|
|
|
|
"github.com/lightninglabs/agora/client/account"
|
|
"github.com/lightninglabs/agora/client/order"
|
|
"github.com/lightningnetwork/lnd/keychain"
|
|
"github.com/lightningnetwork/lnd/lntypes"
|
|
"github.com/lightningnetwork/lnd/lnwallet/chainfee"
|
|
"github.com/lightningnetwork/lnd/lnwire"
|
|
)
|
|
|
|
// WriteElements is writes each element in the elements slice to the passed
|
|
// io.Writer using WriteElement.
|
|
func WriteElements(w io.Writer, elements ...interface{}) error {
|
|
for _, element := range elements {
|
|
err := WriteElement(w, element)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
}
|
|
return nil
|
|
}
|
|
|
|
// WriteElement is a one-stop shop to write the big endian representation of
|
|
// any element which is to be serialized. The passed io.Writer should be backed
|
|
// by an appropriately sized byte slice, or be able to dynamically expand to
|
|
// accommodate additional data.
|
|
func WriteElement(w io.Writer, element interface{}) error {
|
|
switch e := element.(type) {
|
|
case account.State:
|
|
return lnwire.WriteElement(w, uint8(e))
|
|
|
|
case order.Version:
|
|
return lnwire.WriteElement(w, uint32(e))
|
|
|
|
case order.Type:
|
|
return lnwire.WriteElement(w, uint8(e))
|
|
|
|
case order.State:
|
|
return lnwire.WriteElement(w, uint8(e))
|
|
|
|
case order.SupplyUnit:
|
|
return lnwire.WriteElement(w, uint64(e))
|
|
|
|
case chainfee.SatPerKWeight:
|
|
return lnwire.WriteElement(w, uint64(e))
|
|
|
|
case *keychain.KeyDescriptor:
|
|
if err := WriteElements(w, e.KeyLocator, e.PubKey); err != nil {
|
|
return err
|
|
}
|
|
|
|
case keychain.KeyLocator:
|
|
if err := binary.Write(w, byteOrder, e.Family); err != nil {
|
|
return err
|
|
}
|
|
if err := binary.Write(w, byteOrder, e.Index); err != nil {
|
|
return err
|
|
}
|
|
|
|
case lntypes.Preimage:
|
|
return lnwire.WriteElement(w, e[:])
|
|
|
|
case [32]byte:
|
|
return lnwire.WriteElement(w, e[:])
|
|
|
|
default:
|
|
return lnwire.WriteElement(w, element)
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
// ReadElements deserializes a variable number of elements into the passed
|
|
// io.Reader, with each element being deserialized according to the ReadElement
|
|
// function.
|
|
func ReadElements(r io.Reader, elements ...interface{}) error {
|
|
for _, element := range elements {
|
|
err := ReadElement(r, element)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
}
|
|
return nil
|
|
}
|
|
|
|
// ReadElement is a one-stop utility function to deserialize any data structure.
|
|
func ReadElement(r io.Reader, element interface{}) error {
|
|
switch e := element.(type) {
|
|
case *account.State:
|
|
var s uint8
|
|
if err := lnwire.ReadElement(r, &s); err != nil {
|
|
return err
|
|
}
|
|
*e = account.State(s)
|
|
|
|
case *order.Version:
|
|
var v uint32
|
|
if err := lnwire.ReadElement(r, &v); err != nil {
|
|
return err
|
|
}
|
|
*e = order.Version(v)
|
|
|
|
case *order.Type:
|
|
var v uint8
|
|
if err := lnwire.ReadElement(r, &v); err != nil {
|
|
return err
|
|
}
|
|
*e = order.Type(v)
|
|
|
|
case *order.State:
|
|
var s uint8
|
|
if err := lnwire.ReadElement(r, &s); err != nil {
|
|
return err
|
|
}
|
|
*e = order.State(s)
|
|
|
|
case *order.SupplyUnit:
|
|
var s uint64
|
|
if err := lnwire.ReadElement(r, &s); err != nil {
|
|
return err
|
|
}
|
|
*e = order.SupplyUnit(s)
|
|
|
|
case *chainfee.SatPerKWeight:
|
|
var v uint64
|
|
if err := lnwire.ReadElement(r, &v); err != nil {
|
|
return err
|
|
}
|
|
*e = chainfee.SatPerKWeight(v)
|
|
|
|
case **keychain.KeyDescriptor:
|
|
var keyDesc keychain.KeyDescriptor
|
|
err := ReadElements(r, &keyDesc.KeyLocator, &keyDesc.PubKey)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
*e = &keyDesc
|
|
|
|
case *keychain.KeyLocator:
|
|
if err := binary.Read(r, byteOrder, &e.Family); err != nil {
|
|
return err
|
|
}
|
|
if err := binary.Read(r, byteOrder, &e.Index); err != nil {
|
|
return err
|
|
}
|
|
|
|
case *lntypes.Preimage:
|
|
var preimage lntypes.Preimage
|
|
if err := lnwire.ReadElement(r, preimage[:]); err != nil {
|
|
return err
|
|
}
|
|
*e = preimage
|
|
|
|
case *[32]byte:
|
|
var b [32]byte
|
|
if err := lnwire.ReadElement(r, b[:]); err != nil {
|
|
return err
|
|
}
|
|
*e = b
|
|
|
|
default:
|
|
return lnwire.ReadElement(r, element)
|
|
}
|
|
|
|
return nil
|
|
}
|