-
Notifications
You must be signed in to change notification settings - Fork 13
/
contract.sol
91 lines (73 loc) · 2.49 KB
/
contract.sol
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
contract Channel {
struct PaymentChannel {
address owner;
uint256 value;
uint validUntil;
bool valid;
}
mapping(bytes32 => PaymentChannel) public channels;
uint id;
event NewChannel(address indexed owner, bytes32 channel);
event Deposit(address indexed owner, bytes32 indexed channel);
event Claim(address indexed who, bytes32 indexed channel);
event Reclaim(bytes32 indexed channel);
function Channel() {
id = 0;
}
function createChannel() {
bytes32 channel = sha3(id++);
channels[channel] = PaymentChannel(msg.sender, msg.value, block.timestamp + 1 days, true);
NewChannel(msg.sender, channel);
}
// creates a hash using the recipient and value.
function getHash(bytes32 channel, address recipient, uint value) constant returns(bytes32) {
return sha3(channel, recipient, value);
}
// verify a message (receipient || value) with the provided signature
function verify(bytes32 channel, address recipient, uint value, uint8 v, bytes32 r, bytes32 s) constant returns(bool) {
PaymentChannel ch = channels[channel];
return ch.valid && ch.validUntil > block.timestamp && ch.owner == ecrecover(getHash(channel, recipient, value), v, r, s);
}
// claim funds
function claim(bytes32 channel, address recipient, uint value, uint8 v, bytes32 r, bytes32 s) {
if( !verify(channel, recipient, value, v, r, s) ) return;
PaymentChannel ch = channels[channel];
if( value > ch.value ) {
recipient.send(ch.value);
ch.value = 0;
} else {
recipient.send(value);
ch.value -= value;
}
// channel is no longer valid
channels[channel].valid = false;
Claim(recipient, channel);
}
function deposit(bytes32 channel) {
if( !isValidChannel(channel) ) throw;
PaymentChannel ch = channels[channel];
ch.value += msg.value;
Deposit(msg.sender, channel);
}
// reclaim a channel
function reclaim(bytes32 channel) {
PaymentChannel ch = channels[channel];
if( ch.value > 0 && ch.validUntil < block.timestamp ) {
ch.owner.send(ch.value);
delete channels[channel];
}
}
function getChannelValue(bytes32 channel) constant returns(uint256) {
return channels[channel].value;
}
function getChannelOwner(bytes32 channel) constant returns(address) {
return channels[channel].owner;
}
function getChannelValidUntil(bytes32 channel) constant returns(uint) {
return channels[channel].validUntil;
}
function isValidChannel(bytes32 channel) constant returns(bool) {
PaymentChannel ch = channels[channel];
return ch.valid && ch.validUntil >= block.timestamp;
}
}