update alice/bob protocol

This commit is contained in:
noot
2021-10-23 19:42:27 -04:00
parent 1f3681392f
commit dd868d8a19
9 changed files with 174 additions and 111 deletions

View File

@@ -9,14 +9,19 @@ Start ganache-cli with determinstic keys:
ganache-cli -d
```
Start monerod for stagenet:
Start monerod for regtest:
```
monerod --stagenet
./monerod --regtest --fixed-difficulty=1 --rpc-bind-port 18081 --offline
```
Start monero-wallet-rpc:
Start monero-wallet-rpc for Bob with some wallet that has regtest monero:
```
./monero-wallet-rpc --stagenet --rpc-bind-port 18082 --password "" --disable-rpc-login --wallet-dir .
./monero-wallet-rpc --rpc-bind-port 18083 --password "" --disable-rpc-login --wallet-file test-wallet
```
Start monero-wallet-rpc for Alice:
```
./monero-wallet-rpc --rpc-bind-port 18084 --password "" --disable-rpc-login --wallet-dir .
```
##### Compiling contract bindings
@@ -28,7 +33,6 @@ Set `SOLC_BIN` to the downloaded binary
export SOLC_BIN=solc
```
Generate the bindings
```
./scripts/generate-bindings.sh

View File

@@ -159,31 +159,40 @@ func (a *alice) WatchForClaim() (<-chan *monero.PrivateKeyPair, error) {
defer sub.Unsubscribe()
go func() {
select {
case claim := <-ch:
// got Bob's secret
sbBytes := claim.S.Bytes()
var sb [32]byte
copy(sb[:], sbBytes)
for {
select {
case claim := <-ch:
fmt.Println("got claim", claim)
if claim == nil || claim.S == nil {
continue
}
skB, err := monero.NewPrivateSpendKey(sb[:])
if err != nil {
fmt.Printf("failed to convert Bob's secret into a key: %w", err)
// got Bob's secret
sbBytes := claim.S.Bytes()
var sb [32]byte
copy(sb[:], sbBytes)
skB, err := monero.NewPrivateSpendKey(sb[:])
if err != nil {
fmt.Printf("failed to convert Bob's secret into a key: %w", err)
return
}
vkA, err := skB.View()
if err != nil {
fmt.Printf("failed to get view key from Bob's secret spend key: %w", err)
return
}
skAB := monero.SumPrivateSpendKeys(skB, a.privkeys.SpendKey())
vkAB := monero.SumPrivateViewKeys(vkA, a.privkeys.ViewKey())
kpAB := monero.NewPrivateKeyPair(skAB, vkAB)
out <- kpAB
return
case <-a.ctx.Done():
return
}
vkA, err := skB.View()
if err != nil {
fmt.Printf("failed to get view key from Bob's secret spend key: %w", err)
return
}
skAB := monero.SumPrivateSpendKeys(skB, a.privkeys.SpendKey())
vkAB := monero.SumPrivateViewKeys(vkA, a.privkeys.ViewKey())
kpAB := monero.NewPrivateKeyPair(skAB, vkAB)
out <- kpAB
case <-a.ctx.Done():
return
}
}()

View File

@@ -141,12 +141,18 @@ func (b *bob) WatchForReady() (<-chan struct{}, error) {
defer sub.Unsubscribe()
go func() {
select {
case <-ch:
// contract is ready!!
close(done)
case <-b.ctx.Done():
return
for {
select {
case event := <-ch:
if !event.B {
continue
}
// contract is ready!!
close(done)
case <-b.ctx.Done():
return
}
}
}()
@@ -236,6 +242,10 @@ func (b *bob) LockFunds(amount uint) (monero.Address, error) {
return "", err
}
if err := b.client.Refresh(); err != nil {
return "", err
}
fmt.Println("Bob: successfully locked funds")
fmt.Println("address: ", address)
return address, nil
@@ -249,6 +259,21 @@ func (b *bob) ClaimFunds() error {
// call swap.Swap.Claim() w/ b.privkeys.sk, revealing Bob's secret spend key
secret := b.privkeys.Bytes()
s := big.NewInt(0).SetBytes(secret)
_, err := b.contract.Claim(txOpts, s)
return err
tx, err := b.contract.Claim(txOpts, s)
if err != nil {
return err
}
fmt.Println("success! Bob claimed funds")
fmt.Println("tx hash: ", tx.Hash())
receipt, err := b.ethClient.TransactionReceipt(b.ctx, tx.Hash())
if err != nil {
return err
}
//fmt.Println("tx logs: ", fmt.Sprintf("0x%x", receipt.Logs[0].Data))
fmt.Println("included in block number: ", receipt.Logs[0].BlockNumber)
//fmt.Println("expected secret: ", fmt.Sprintf("0x%x", secret))
return nil
}

View File

@@ -37,28 +37,6 @@ func (n *node) doProtocolAlice() error {
}
}
claim, err := n.alice.WatchForClaim()
if err != nil {
return err
}
for {
// TODO: add t1 timeout case
select {
case <-n.done:
return nil
case kp := <-claim:
fmt.Printf("Bob claimed ether! got secret: %v", kp)
address, err := n.alice.CreateMoneroWallet(kp)
if err != nil {
return err
}
fmt.Printf("successfully created monero wallet from our secrets: address=%s", address)
// TODO: get and print balance
}
}
n.wait()
return nil
}
@@ -113,6 +91,36 @@ func (n *node) handleMessageAlice(who peer.ID, msg net.Message, setupDone chan s
fmt.Printf("deployed Swap contract: address=%s\n", address)
claim, err := n.alice.WatchForClaim()
if err != nil {
return err
}
go func() {
for {
// TODO: add t1 timeout case
select {
case <-n.done:
fmt.Println("done")
return
case kp := <-claim:
if kp == nil {
continue
}
fmt.Printf("Bob claimed ether! got secret: %v", kp)
address, err := n.alice.CreateMoneroWallet(kp)
if err != nil {
fmt.Println("failed to create monero address: %w", err)
return
}
fmt.Printf("successfully created monero wallet from our secrets: address=%s", address)
// TODO: get and print balance
}
}
}()
out := &net.NotifyContractDeployed{
Address: address.String(),
}

View File

@@ -40,34 +40,6 @@ func (n *node) doProtocolBob() error {
}
}
// ready, err := n.bob.WatchForReady()
// if err != nil {
// return err
// }
// refund, err := n.bob.WatchForRefund()
// if err != nil {
// return err
// }
// for {
// // TODO: add t0 timeout case
// select {
// case <-n.done:
// return nil
// case <-ready:
// fmt.Println("Alice called Ready!")
// // contract ready, let's claim our ether
// if err := n.bob.ClaimFunds(); err != nil {
// return fmt.Errorf("failed to redeem ether: %w", err)
// }
// case kp := <-refund:
// fmt.Println("Alice refunded, got monero account key", kp)
// // TODO: generate wallet
// }
// }
n.wait()
return nil
}
@@ -140,19 +112,25 @@ func (n *node) handleMessageBob(who peer.ID, msg net.Message, setupDone chan str
return
case <-ready:
fmt.Println("Alice called Ready!")
fmt.Println("attempting to claim funds...")
time.Sleep(time.Second)
time.Sleep(time.Second * 3)
// contract ready, let's claim our ether
if err := n.bob.ClaimFunds(); err != nil {
fmt.Printf("failed to redeem ether: %w", err)
return
}
fmt.Println("funds claimed!!")
return
case kp := <-refund:
if kp == nil {
continue
}
fmt.Println("Alice refunded, got monero account key", kp)
return
// TODO: generate wallet
}
}

View File

@@ -14,8 +14,8 @@ import (
)
const (
defaultAliceMoneroEndpoint = "http://127.0.0.1:18083/json_rpc"
defaultBobMoneroEndpoint = "http://127.0.0.1:18080/json_rpc"
defaultAliceMoneroEndpoint = "http://127.0.0.1:18084/json_rpc"
defaultBobMoneroEndpoint = "http://127.0.0.1:18083/json_rpc"
defaultEthEndpoint = "ws://localhost:8545"
defaultPrivKeyAlice = "4f3edf983ac636a65a842ce7c78d9aa706d3b113bce9c46f30d7d21715b23b1d"
defaultPrivKeyBob = "6cbed15c793ce57650b9877cf6fa156fbef513c4e6134f022a85b1ffdd59b2a1"

View File

@@ -9,6 +9,7 @@ type Client interface {
GetBalance(idx uint) (*getBalanceResponse, error)
Transfer(to Address, accountIdx, amount uint) error
GenerateFromKeys(kp *PrivateKeyPair, filename, password string) error
Refresh() error
}
type client struct {
@@ -44,3 +45,22 @@ func (c *client) GenerateFromKeys(kp *PrivateKeyPair, filename, password string)
func (c *client) GetAddress(idx uint) (*getAddressResponse, error) {
return c.callGetAddress(idx)
}
func (c *client) Refresh() error {
return c.refresh()
}
func (c *client) refresh() error {
const method = "refresh"
resp, err := postRPC(c.endpoint, method, "{}")
if err != nil {
return err
}
if resp.Error != nil {
return resp.Error
}
return nil
}

View File

@@ -41,18 +41,3 @@ func (c *client) callGenerateBlocks(address string, amount uint) error {
return nil
}
func (c *client) refresh() error {
const method = "refresh"
resp, err := postRPC(c.endpoint, method, "{}")
if err != nil {
return err
}
if resp.Error != nil {
return resp.Error
}
return nil
}

View File

@@ -1,9 +1,12 @@
package swap
import (
"context"
"crypto/ecdsa"
"fmt"
"math/big"
"testing"
"time"
"github.com/ethereum/go-ethereum/accounts/abi/bind"
"github.com/ethereum/go-ethereum/crypto"
@@ -18,10 +21,15 @@ const (
keyBob = "6cbed15c793ce57650b9877cf6fa156fbef513c4e6134f022a85b1ffdd59b2a1"
)
func setBigIntLE(s []byte) *big.Int {
func reverse(s []byte) []byte {
for i, j := 0, len(s)-1; i < j; i, j = i+1, j-1 {
s[i], s[j] = s[j], s[i]
}
return s
}
func setBigIntLE(s []byte) *big.Int {
s = reverse(s)
return big.NewInt(0).SetBytes(s)
}
@@ -67,7 +75,7 @@ func TestSwap_Claim(t *testing.T) {
secretBob := keyPairBob.Bytes()
// setup
conn, err := ethclient.Dial("http://127.0.0.1:8545")
conn, err := ethclient.Dial("ws://127.0.0.1:8545")
require.NoError(t, err)
pk_a, err := crypto.HexToECDSA(keyAlice)
@@ -84,7 +92,7 @@ func TestSwap_Claim(t *testing.T) {
copy(pkAliceFixed[:], pubKeyAlice)
var pkBobFixed [32]byte
copy(pkBobFixed[:], pubKeyBob)
_, _, swap, err := DeploySwap(authAlice, conn, pkAliceFixed, pkBobFixed)
_, _, swap, err := DeploySwap(authAlice, conn, pkBobFixed, pkAliceFixed)
require.NoError(t, err)
txOpts := &bind.TransactOpts{
@@ -97,11 +105,8 @@ func TestSwap_Claim(t *testing.T) {
Signer: authBob.Signer,
}
// callOpts := &bind.CallOpts{From: address}
// Bob tries to claim before Alice has called ready, should fail
// _, err = swap.Claim(txOptsBob, setBigIntLE(secretBob))
s := big.NewInt(0).SetBytes(secretBob)
s := big.NewInt(0).SetBytes(reverse(secretBob))
_, err = swap.Claim(txOptsBob, s)
require.Errorf(t, err, "'isReady == false' cannot claim yet!")
@@ -109,13 +114,42 @@ func TestSwap_Claim(t *testing.T) {
_, err = swap.SetReady(txOpts)
require.NoError(t, err)
// Bob tries to claim before Alice has called ready, should fail
watchForEvent(t, swap)
_, err = swap.Claim(txOptsBob, s)
require.NoError(t, err)
time.Sleep(time.Second * 10)
// TODO check whether Bob's account balance has increased
}
func TestSwap_Refund(t *testing.T) {
}
func watchForEvent(t *testing.T, contract *Swap) {
watchOpts := &bind.WatchOpts{
Context: context.Background(),
}
ch := make(chan *SwapCalculatedPublicKey)
sub, err := contract.WatchCalculatedPublicKey(watchOpts, ch)
require.NoError(t, err)
defer sub.Unsubscribe()
go func() {
for event := range ch {
if event == nil {
continue
}
fmt.Println("got event")
fmt.Println(event.Px, event.Py)
return
}
}()
}