Files
atomic-swap/dleq/dleq.go
Dmitry Holodov adfb0fa602 Test cleanup (#135)
* version independent monerod path with localhost-only binding

* fixed lint target and install script

* created 3rd ETH key constant to avoid race condition in tests

* updated run-integration-tests.sh with the same changes made to run-unit-tests.sh

* new design for paritioning out 2 unique keys to test packages

* restored accidentally deleted tests/alice.key

* removed websocket connection leaks from tests

* made file paths unique between tests with better file cleanup

* fix for the websocket connection leak commit

* reverted increase of GenerateBlocks (didn't mean to commit that)

* fixed maker/taker key that I had reversed

* fixed incorrect zero-balance check

* fixed comment on ClaimOrRefund

* added back sample script for installing go in /usr/local/go

* etchclient creation cleanup using t.Cleanup()

* minor cleanup to ganache_test_keys code

* initial dynamic monero-wallet-rpc implementation for tests

* converted monero tests to use dynamic monero-wallet-rpc services

* unit tests all using dynamic monero-wallet-rpc services

* fixed 2 tests that failed after moving to dynamic monero-wallet-rpc services

* fixed low balance issues in TestSwapState_NotifyClaimed

Co-authored-by: noot <36753753+noot@users.noreply.github.com>
2022-06-29 13:36:03 -04:00

166 lines
3.6 KiB
Go

package dleq
import (
"encoding/hex"
"errors"
"fmt"
"io/ioutil"
"os"
"os/exec"
"path/filepath"
"strings"
"time"
"github.com/noot/atomic-swap/crypto/secp256k1"
)
// Interface ...
type Interface interface {
Prove() (*Proof, error)
Verify(*Proof) (*VerifyResult, error)
}
// Proof represents a DLEq proof
type Proof struct {
secret [32]byte
proof []byte
}
// NewProofWithoutSecret returns a new Proof without a secret from the given proof slice
func NewProofWithoutSecret(p []byte) *Proof {
return &Proof{
proof: p,
}
}
// NewProofWithSecret returns a new Proof with the given secret.
// Note that the returned proof actually lacks the `proof` field.
func NewProofWithSecret(s [32]byte) *Proof {
return &Proof{
secret: s,
}
}
// Secret returns the proof's 32-byte secret
func (p *Proof) Secret() [32]byte {
return p.secret
}
// Proof returns the encoded DLEq proof
func (p *Proof) Proof() []byte {
return p.proof
}
// VerifyResult contains the public keys resulting from verifying a DLEq proof
type VerifyResult struct {
ed25519Pub [32]byte
secp256k1Pub *secp256k1.PublicKey
}
// Secp256k1PublicKey returns the secp256k1 public key associated with the DLEq verification
func (r *VerifyResult) Secp256k1PublicKey() *secp256k1.PublicKey {
return r.secp256k1Pub
}
var (
dleqGenBinPath = getFarcasterDLEqBinaryPath() + "dleq-gen"
dleqVerifyBinPath = getFarcasterDLEqBinaryPath() + "dleq-verify"
defaultProofPath = "/tmp/dleq_proof"
)
// TODO: this is kinda sus, make it actually find the bin better. maybe env vars?
func getFarcasterDLEqBinaryPath() string {
bin := "./farcaster-dleq/target/release/dleq-gen"
_, err := os.Stat(bin)
if !errors.Is(err, os.ErrNotExist) {
return "./farcaster-dleq/target/release/"
}
bin = "../farcaster-dleq/target/release/dleq-gen"
_, err = os.Stat(bin)
if !errors.Is(err, os.ErrNotExist) {
return "../farcaster-dleq/target/release/"
}
return "../../farcaster-dleq/target/release/"
}
// FarcasterDLEq is a wrapper around the binaries in farcaster-dleq
type FarcasterDLEq struct{}
// Prove generates a new DLEq proof
func (d *FarcasterDLEq) Prove() (*Proof, error) {
t := time.Now().Format("2006-01-02-15:04:05.999999999")
path := fmt.Sprintf("%s-%s", defaultProofPath, t)
cmd := exec.Command(dleqGenBinPath, path)
if err := cmd.Run(); err != nil {
return nil, err
}
secret, err := ioutil.ReadFile(filepath.Clean(path + ".key"))
if err != nil {
return nil, err
}
var sc [32]byte
copy(sc[:], secret)
proof, err := ioutil.ReadFile(filepath.Clean(path))
if err != nil {
return nil, err
}
return &Proof{
secret: sc,
proof: proof,
}, nil
}
// Verify verifies a DLEq proof
func (d *FarcasterDLEq) Verify(p *Proof) (*VerifyResult, error) {
t := time.Now().Format("2006-01-02-15:04:05.999999999")
path := fmt.Sprintf("%s-verify-%s", defaultProofPath, t)
if err := ioutil.WriteFile(path, p.proof, os.ModePerm); err != nil {
return nil, err
}
cmd := exec.Command(dleqVerifyBinPath, path)
output, err := cmd.Output()
if err != nil {
return nil, err
}
// slice off \n at the end of string
out := strings.Split(string(output[:len(output)-1]), " ")
if len(out) != 3 {
return nil, errors.New("invalid output from dleq-verify")
}
ed25519Pub, err := hex.DecodeString(out[0])
if err != nil {
return nil, err
}
secp256k1X, err := hex.DecodeString(out[1])
if err != nil {
return nil, err
}
secp256k1Y, err := hex.DecodeString(out[2])
if err != nil {
return nil, err
}
res := &VerifyResult{}
copy(res.ed25519Pub[:], ed25519Pub)
var x, y [32]byte
copy(x[:], secp256k1X)
copy(y[:], secp256k1Y)
res.secp256k1Pub = secp256k1.NewPublicKey(x, y)
return res, nil
}