-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathp2p.cash
147 lines (132 loc) · 5.28 KB
/
p2p.cash
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
pragma cashscript ^0.7.4;
/*
* Create an Escrow contract between two parties with arbiter as the third party.
* @param: arbiterPk: Public Key of the arbiter.
* @param: buyerPk: Public Key of the buyer.
* @param: sellerPk: Public Key of the seller.
* @param: recipientBuyerPk: Public Key of the recipient buyer.
* @param: recipientSellerPk: Public Key of the recipient seller.
* @param: arbiterFee: Fee for arbiter.
*/
contract Escrow(
pubkey arbiterPk,
pubkey buyerPk,
pubkey sellerPk,
pubkey recipientBuyerPk,
pubkey recipientSellerPk,
int arbiterFee
) {
/*
* Can be called by anyone but the signature is done by the seller
* - Message: 'x'
* - Check signature of: Seller
* - Pay to: Buyer
* - Reason: Successful trade, check the signature of the seller to release the escrow
*
* @param: message: Message that is signed by the seller.
* @param: signature: Data signature and if valid, release the funds
*/
function execute(
bytes message,
datasig signature
) {
// Check that only single input is being used in this transaction
require(tx.inputs.length == 1);
// 'x' in ascii chart is 120
require(message == bytes(120));
// Set the miner fee to 900 sats
int minerFee = 900;
// Amount being spent to one of the parties.
int spendingAmount = tx.inputs[0].value - minerFee - arbiterFee;
// // Pay to party is buyer's primary address
bytes25 payToPartyLockingBytecode = new LockingBytecodeP2PKH(hash160(recipientBuyerPk));
bytes25 arbiterLockingBytecode = new LockingBytecodeP2PKH(hash160(arbiterPk));
// In case of successful transaction, make sure that the second output is arbiter fee
require(tx.outputs[1].value == arbiterFee);
require(tx.outputs[1].lockingBytecode == arbiterLockingBytecode);
// Make sure that the first output has the correct amount
require(tx.outputs[0].value == spendingAmount);
require(tx.outputs[0].lockingBytecode == payToPartyLockingBytecode);
require(checkDataSig(signature, message, sellerPk));
}
/*
* Can be called by anyone and the signature is done by Buyer
* - Message: 'c'
* - Check signature of: Buyer
* - Pay to: Seller
* - Reason: Trade cancelled, check the signature of the buyer to release
* the escrow funds back to the seller
*
* @param: message: Message that is signed by the buyer.
* @param: signature: Data signature and if valid, release the funds
*/
function cancel(
bytes message,
datasig signature
) {
// Check that only single input is being used in this transaction
require(tx.inputs.length == 1);
// 'c' is the ascii chart is 99
require(message == bytes(99));
// Set the miner fee to 800 sats
int minerFee = 800;
// Amount being spent to one of the parties.
int spendingAmount = tx.inputs[0].value - minerFee;
bytes25 payToPartyLockingBytecode = new LockingBytecodeP2PKH(hash160(recipientSellerPk));
// Make sure that the first output has the correct amount
require(tx.outputs[0].value == spendingAmount);
require(tx.outputs[0].lockingBytecode == payToPartyLockingBytecode);
require(checkDataSig(signature, message, buyerPk));
}
/*
* Can be called by anyone but the signature is done by the arbiter and one of the parties
* Case 1:
* Message: 'b'
* Check signature of: Buyer and Arbiter
* Pay to: Buyer
* Case 2:
* Message: 's'
* Check signature of: Seller and Arbiter
* Pay to: Seller
*
* @param: message: Message that is signed by both of the parties
* @param: sigParty: Check the signature of buyer or seller as per dispute resolution result
* @param: sigArbiter: Check the signature of the arbiter
*/
function resolveDispute(
bytes message,
datasig sigParty,
datasig sigArbiter
) {
// Check that only single input is being used in this transaction
require(tx.inputs.length == 1);
// 'b' is the ascii chart is 98
// 's' is the ascii chart is 115
require(message == bytes(98) || message == bytes(115));
// Set the miner fee to 800 sats
int minerFee = 800;
// Amount being spent to the authorised party.
int spendingAmount = tx.inputs[0].value - minerFee - arbiterFee;
// Make sure the amount being spent is correct.
require(tx.outputs[0].value == spendingAmount);
require(tx.outputs[1].value == arbiterFee);
// Default values of case 'b' here. i.e Buyer gets the funds
bytes25 payToPartyLockingBytecode = new LockingBytecodeP2PKH(hash160(recipientBuyerPk));
// For default case of 'b', check signature of the buyer
pubkey checkSignatureOf = buyerPk;
if (message == bytes(115)){
payToPartyLockingBytecode = new LockingBytecodeP2PKH(hash160(recipientSellerPk));
// Check signature of the seller
checkSignatureOf = sellerPk;
}
bytes25 arbiterLockingBytecode = new LockingBytecodeP2PKH(hash160(arbiterPk));
// First output goes to one of the parties
require(tx.outputs[0].lockingBytecode == payToPartyLockingBytecode);
// Second output goes to arbiter
require(tx.outputs[1].lockingBytecode == arbiterLockingBytecode);
// Check signature of the party receiving the money
require(checkDataSig(sigParty, message, checkSignatureOf));
// Check signature of the arbiter
require(checkDataSig(sigArbiter, message, arbiterPk));
}
}