diff --git a/bob/protocol.go b/bob/protocol.go index 0a1d526c..2098f72c 100644 --- a/bob/protocol.go +++ b/bob/protocol.go @@ -16,6 +16,8 @@ import ( "github.com/noot/atomic-swap/swap-contract" ) +const defaultDaemonEndpoint = "http://127.0.0.1:18081/json_rpc" + var _ Bob = &bob{} // Bob contains the functions that will be called by a user who owns XMR @@ -50,7 +52,7 @@ type Bob interface { // (S_a + S_b), viewable with (V_a + V_b) // It accepts the amount to lock as the input // TODO: units - LockFunds(amount uint) error + LockFunds(amount uint) (monero.Address, error) // ClaimFunds redeem's Bob's funds on ethereum ClaimFunds() error @@ -63,6 +65,7 @@ type bob struct { privkeys *monero.PrivateKeyPair pubkeys *monero.PublicKeyPair client monero.Client + daemonClient monero.DaemonClient contract *swap.Swap ethPrivKey *ecdsa.PrivateKey alicePublicKeys *monero.PublicKeyPair @@ -89,11 +92,12 @@ func NewBob(moneroEndpoint, ethEndpoint, ethPrivKey string) (*bob, error) { } return &bob{ - ctx: context.Background(), // TODO: add cancel - client: monero.NewClient(moneroEndpoint), - ethClient: ec, - ethPrivKey: pk, - auth: auth, + ctx: context.Background(), // TODO: add cancel + client: monero.NewClient(moneroEndpoint), + daemonClient: monero.NewClient(defaultDaemonEndpoint), // TODO: pass through flags + ethClient: ec, + ethPrivKey: pk, + auth: auth, }, nil } @@ -198,17 +202,37 @@ func (b *bob) WatchForRefund() (<-chan *monero.PrivateKeyPair, error) { return out, nil } -func (b *bob) LockFunds(amount uint) error { +func (b *bob) LockFunds(amount uint) (monero.Address, error) { kp := monero.SumSpendAndViewKeys(b.alicePublicKeys, b.pubkeys) + fmt.Println("Bob: going to lock funds...") + + balance, err := b.client.GetBalance(0) + if err != nil { + return "", err + } + + fmt.Println("balance: ", balance.Balance) + fmt.Println("unlocked balance: ", balance.UnlockedBalance) + fmt.Println("blocks to unlock: ", balance.BlocksToUnlock) + address := kp.Address() if err := b.client.Transfer(address, 0, amount); err != nil { - return err + return "", err + } + + bobAddr, err := b.client.GetAddress(0) + if err != nil { + return "", err + } + + if err := b.daemonClient.GenerateBlocks(bobAddr.Address, 1); err != nil { + return "", err } fmt.Println("Bob: successfully locked funds") fmt.Println("address: ", address) - return nil + return address, nil } func (b *bob) ClaimFunds() error { diff --git a/cmd/alice.go b/cmd/alice.go index 558cd748..5e300143 100644 --- a/cmd/alice.go +++ b/cmd/alice.go @@ -29,7 +29,7 @@ func (n *node) doProtocolAlice() error { select { case <-n.done: case msg := <-n.inCh: - if err := n.handleMessageAlice(msg.Who, msg.Message); err != nil { + if err := n.handleMessageAlice(msg.Who, msg.Message, setupDone); err != nil { fmt.Printf("failed to handle message: error=%s\n", err) } case <-setupDone: @@ -62,7 +62,7 @@ func (n *node) doProtocolAlice() error { return nil } -func (n *node) handleMessageAlice(who peer.ID, msg net.Message) error { +func (n *node) handleMessageAlice(who peer.ID, msg net.Message, setupDone chan struct{}) error { switch msg := msg.(type) { case *net.WantMessage: if msg.Want != "ETH" { @@ -111,6 +111,16 @@ func (n *node) handleMessageAlice(who peer.ID, msg net.Message) error { } fmt.Printf("deployed Swap contract: address=%s\n", address) + + out := &net.NotifyContractDeployed{ + Address: address.String(), + } + + n.outCh <- &net.MessageInfo{ + Message: out, + Who: who, + } + case *net.NotifyXMRLock: if msg.Address == "" { return errors.New("got empty address for locked XMR") @@ -119,6 +129,12 @@ func (n *node) handleMessageAlice(who peer.ID, msg net.Message) error { // check that XMR was locked in expected account, and confirm amount n.host.SetNextExpectedMessage(nil) + + if err := n.alice.Ready(); err != nil { + return fmt.Errorf("failed to call Ready: %w", err) + } + + close(setupDone) default: return errors.New("unexpected message type") } diff --git a/cmd/bob.go b/cmd/bob.go index 1b9157d9..6ebaa4c5 100644 --- a/cmd/bob.go +++ b/cmd/bob.go @@ -114,12 +114,25 @@ func (n *node) handleMessageBob(who peer.ID, msg net.Message, setupDone chan str } n.host.SetNextExpectedMessage(nil) - fmt.Println("got Swap contract address!") + fmt.Printf("got Swap contract address! address=%s\n", msg.Address) if err := n.bob.SetContract(ethcommon.HexToAddress(msg.Address)); err != nil { return fmt.Errorf("failed to instantiate contract instance: %w", err) } + addrAB, err := n.bob.LockFunds(n.amount) + if err != nil { + return err + } + + out := &net.NotifyXMRLock{ + Address: string(addrAB), + } + + n.outCh <- &net.MessageInfo{ + Message: out, + Who: who, + } close(setupDone) default: return errors.New("unexpected message type") diff --git a/cmd/main.go b/cmd/main.go index 1c2fba15..5cd246e5 100644 --- a/cmd/main.go +++ b/cmd/main.go @@ -14,8 +14,8 @@ import ( ) const ( - defaultAliceMoneroEndpoint = "http://127.0.0.1:18080/json_rpc" - defaultBobMoneroEndpoint = "http://127.0.0.1:18083/json_rpc" + defaultAliceMoneroEndpoint = "http://127.0.0.1:18083/json_rpc" + defaultBobMoneroEndpoint = "http://127.0.0.1:18080/json_rpc" defaultEthEndpoint = "http://localhost:8545" defaultPrivKeyAlice = "4f3edf983ac636a65a842ce7c78d9aa706d3b113bce9c46f30d7d21715b23b1d" defaultPrivKeyBob = "6cbed15c793ce57650b9877cf6fa156fbef513c4e6134f022a85b1ffdd59b2a1" diff --git a/monero/client.go b/monero/client.go index 7d6ec7f2..2672b1c9 100644 --- a/monero/client.go +++ b/monero/client.go @@ -5,6 +5,7 @@ import ( ) type Client interface { + GetAddress(idx uint) (*getAddressResponse, error) GetBalance(idx uint) (*getBalanceResponse, error) Transfer(to Address, accountIdx, amount uint) error GenerateFromKeys(kp *PrivateKeyPair, filename, password string) error @@ -39,3 +40,7 @@ func (c *client) GenerateFromKeys(kp *PrivateKeyPair, filename, password string) address := kp.Address() return c.callGenerateFromKeys(kp.sk, kp.vk, address, filename, password) } + +func (c *client) GetAddress(idx uint) (*getAddressResponse, error) { + return c.callGetAddress(idx) +} diff --git a/monero/daemon.go b/monero/daemon.go new file mode 100644 index 00000000..187be73a --- /dev/null +++ b/monero/daemon.go @@ -0,0 +1,58 @@ +package monero + +import ( + "encoding/json" +) + +type DaemonClient interface { + GenerateBlocks(address string, amount uint) error +} + +type generateBlocksRequest struct { + Address string `json:"wallet_address"` + AmountOfBlocks uint `json:"amount_of_blocks"` +} + +func (c *client) GenerateBlocks(address string, amount uint) error { + return c.callGenerateBlocks(address, amount) +} + +func (c *client) callGenerateBlocks(address string, amount uint) error { + const method = "generateblocks" + + req := &generateBlocksRequest{ + Address: address, + AmountOfBlocks: amount, + } + + params, err := json.Marshal(req) + if err != nil { + return err + } + + resp, err := postRPC(c.endpoint, method, string(params)) + if err != nil { + return err + } + + if resp.Error != nil { + return resp.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 +} diff --git a/monero/rpc.go b/monero/rpc.go index ef8b14af..07c17ed8 100644 --- a/monero/rpc.go +++ b/monero/rpc.go @@ -208,48 +208,3 @@ func (c *client) callGetAddress(idx uint) (*getAddressResponse, error) { return res, nil } - -type generateBlocksRequest struct { - Address string `json:"wallet_address"` - AmountOfBlocks uint `json:"amount_of_blocks"` -} - -func (c *client) callGenerateBlocks(address string, amount uint) error { - const method = "generateblocks" - - req := &generateBlocksRequest{ - Address: address, - AmountOfBlocks: amount, - } - - params, err := json.Marshal(req) - if err != nil { - return err - } - - resp, err := postRPC(c.endpoint, method, string(params)) - if err != nil { - return err - } - - if resp.Error != nil { - return resp.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 -}