# Synchronous two-party payment channel
We assume that on each machine you have already setted up your private key in key/ folder.
We use this private keys to sign messages offchain and onchain
You can use any private key, but you firstly need a wallet that have grams if you want to deploy contract using it
## Running
What do you need to run it:
You need to create catalog with `wallet.addr `and `wallet.pk` files (account with Grams).
1. Deploy Smart contract on TON
```
bash deploy.sh
```
For server you need to run with port like:
1) First terminal window:
```
docker run -it -p port:port -v path_to_catalog_with_files:/app/data buttonwallet/synchannel
```
2) Second terminal window:
```
docker run -it -v path_to_another_catalog_with_files:/app/data buttonwallet/synchannel
```
3) Enter smart contract address:
```
0:E6DE901D76CDC66C2269201280658DA017D04A75619D8BE5E63E104FA5F6F477
```
4) Setup peer to peer connection
Person who deployed Smart Contract needs to serve connection with command
Terminal 1:
```
serve
```
Than you need to chose a port where your connection will be served:
```
Please, enter a source port or enter "exit": 3000
To make connection use this address in LAN:
/ip4/172.17.0.3/tcp/3000/p2p/QmeZ1Ykwj57BGqeSjU66pvh5iDfSYjW2EugqaFkZ5UENYw
To make connection use this address in WAN (if you have public IP):
/ip4/178.140.100.51/tcp/3000/p2p/QmeZ1Ykwj57BGqeSjU66pvh5iDfSYjW2EugqaFkZ5UENYw
Waiting for incoming connection
```
Later you need to copy this link and sent it to your partner (person 2)
LAN for local
or
WAN for public
```
/ip4/172.17.0.3/tcp/3000/p2p/QmeZ1Ykwj57BGqeSjU66pvh5iDfSYjW2EugqaFkZ5UENYw
```
Partner needs to run
```
connect
```
And enter connection string there
```
/ip4/172.17.0.3/tcp/3000/p2p/QmeZ1Ykwj57BGqeSjU66pvh5iDfSYjW2EugqaFkZ5UENYw
```
If connection is successfull, you will automatically send partner your address and your signature that prove that it is your address
You will got something like this:
```
Partner signature: 78FB74C5FDD013648BF060663AF55DE25566D310021D5F448403168890F85C80D6339A1EC63C6917823B9CAA3F6EB95819334C0F7AB70FD34F54A733FCF2010A
Partner address: kQDI-VEsKDl-v8HFpyl51HrNmwWX-37ZXLNu9PvsHglupowG
```
5) We have a smart contract, let's deposit money to it from each terminal:
Terminal 1:
```
deposit
```
You will see your wallet balance in GRAMS
```
Your account balance now: 38.433277 Gram
Enter amount to put on contract or "exit"
```
Next, you need to enter GRAMs amount that you will send to the contract
Your partner need to repeat the same operation
After notification
```
❗ Received initial state❗
```
The last of 2 people who made the deposit needs to sign initial state with command
```
sign
```
And after that you can run command **showAll** will see something like this
```
Sender A
A [3.000000 4.000000] B
Step 1
Signs A [F 3] B
```
All commands:
```
serve create connection token
connect connect to other peer
deposit make deposit
send send some amount
sign sign last state
balanceContract show balance of contract in workchain
balanceChan show balance in sync chan
balanceTon show balance in workchain
getAccount show user ton account
getPartnerAccount show partner ton account
getSmartContractAccount show smart contract address
getSeqno show seqno of your acc in workchain
createEmpty create empty state
requestEmpty request empty state from your partner
showAll show all states
showLast show last state
withdraw push actual state in to workchain
exit exit from app
```
6) Right now you can send an offchain transaction from Terminal 1 (The first state num can be sent only from it)
Terminal 2:
```
send 1 or send .1 or send 0.1
```
You will get inforamation at Terminal 1:
```
❗ Received new state❗
```
and than you need to approve and sign new state that Terminal 2 sent to you:
```
showLast
sign
showAll
```
```
Sender A
A [3.000000 4.000000] B
Step 1
Signs A [F 3] B
Sender B
A [3.200000 3.800000] B
Step 2
Signs A [7 9] B
```
So, at Terminal 1 you will see a confirmation, now it is Terminal 2 turn to send transaction
```
❗ Last state signed successful❗
```
If you want sent tx to your partner but now is not your turn you can use command `requestEmpty`
Than your partner will see notification:
```
❗ Your partner request empty state❗
```
If you agree with that you can create empty state by command `createEmpty`
and your partner should sign it
7) Let's do a withdraw:
Terminal 1:
```
withdrawal
```
Than you need to enter step number that you wanna send to the contract:
```
Enter step number: 2
Signature A: 73A6FADA9F3FA985BB000404AD1FAC434FE12AE310EC2390522AA9B42843C3301FA52026BF7BFEA460E2FC7413D6CD67DDB76BB455DCD634A1C9437843B9AA0A
Signature B: 97A45EDC329F58B6B50C9D78CFEE2AC2D9C6A160D806E6D8C0F5CC5E36537FE73156DF834102CD84953A3AE133D3E47897652D7F0AFB24F50A4FE5136801E003
Balance A: 3.200000
Balance B: 3.800000
Account signature: 78FB74C5FDD013648BF060663AF55DE25566D310021D5F448403168890F85C80D6339A1EC63C6917823B9CAA3F6EB95819334C0F7AB70FD34F54A733FCF2010A
Partner signature: 6C6A86A1A5D1CCA53FD60620B0871AA0F8CCEA00655F0B1AEEF4D2F5F981C4AE6937988D42C423DFF43F81C6D0F49ABB9966F0984D4FE4362338479457B78609
Step: 2
Contract seqno: 3
Are you sure[y/n]:y
```
Than if transaction completed, your partner will see notification:
```
❗ Your partner sent the state to the smart contract❗
```
And than he can do withdrawal it too
After that two person will see all information about result balances:
```
Success withdrawal!
Your balance in workchain now: 37.014310
Partner balance in workchain now: 52.548630
Smart contract balance in workchain now: 0.932511
```
With CLI you can withdraw peacfully, however, it could be another option:
If there is a confilct on smart contract, you can withdraw it by applying the latest state
You can see all the states by:
```
showAll
```
## Details of implementation
TON WP was used is theortical base.
We have:
User 1 (A),
User 2 (B)
Smart contract (SC)
### 1 Beofore deposit (Onchain + Offchain):
We assume that A and B will have a secure p2p connection between each other. We use our own implmentation on Goland.
A and B needs to exchange the public keys, ton wallet addresses and signatures that prooves, that it is a correct address.
Also someone needs to deploy and pay for gas on SC, so we assume that A and B already reached agreement about that.
### 2 Deposit (Onchain):
A and B send a query from TON Wallet to SC. They need to send GRAMS and initial details of state.
**Initial details of state:**
| Variables | Description |
|-------------------|--------------------------------------------------|
| Public Key A | Needs to check signatures and owners of contract |
| Public Key B | Needs to check signatures and owners of contract |
| Amount A | Needs to check that total sum A + B during exit will be correct |
| Amount B | Needs to check that total sum A + B during exit will be correct |
*Amount A and B are calculated based on amount that A and B will send to SC*
### 3 Sending GRAMs to each other (Offchain):
It is Sync Channel, so onlu one of A and B can send GRAMs to each other.
But we implemented a possibility to request your turn. If you will request it, B needs just to sign to old state with new state_num +=1
We use our client to send GRAMs as well
### 4 Withdraw (Onchain)
Case with the same states:
Each of A and B needs to send:
| Variables | Description |
|-------------------|--------------------------------------------------|
| Amount A | Amount of GRAMs that will be sent to A |
| Amount B | Amount of GRAMs that will be sent to B |
| State_num | Current amount of all transactions between A and B offchain |
| pool_address | Address of current SC to make signature unique per contract|
| slice_ref with signature A | Check that A agreed with current state|
| slice_ref with signature B | Check that A agreed with current state|
Case with confilct:
If A applied to withdraw and then B applied with confilct.
A have option to send another state that have state_num > than current
If it will be provided, withdraw will be executed with this state
## Authors
Nick Kozlov - CTO and Co-founder of BUTTON Wallet (@enormousrage, nk@buttonwallet.com)
Kirill Kuznecov - Co-founder of BUTTON Wallet (@krboktv, kk@buttonwallet.com)
Alexey Prazdnikov - Fullstack developer at BUTTON Wallet (@noprazd, ap@buttonwallet.com)
Max Spiridonov - Backend developer at BUTTON Wallet (@maxSpt, ms@buttonwallet.com)
Roman Semenov - One of founders of Copperbits community, co-author of Tornado.cash Ethereum mixer (@poma, semenov.roma@gmail.com)
Igor Gulamov Blockchain Researcher and Entrepreneur (@igor_gulamov, igor.gulamov@gmail.com)