-
Notifications
You must be signed in to change notification settings - Fork 2
/
Adpater.pseudo
168 lines (157 loc) · 7.7 KB
/
Adpater.pseudo
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
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
class Adapter{
struct Network{
SC ACCS;
SC relay;
address myAddress;
pk myPrivKey;
}
mapping(string => Network) networks;
struct Swap{
bytes swapID;
String targetNetwork;
String originNetwork;
bytes secret;
bytes hashedSecret;
address receiver;
int value;
float exchangeRatio;
}
mapping (bytes => Swap) swaps;
enum States {
INVALID,
PRECOMMITED,
COMMITED,
REDEEMED,
REFUNDED,
}
mapping (bytes => States) swapStates;
function getTransactionByHash(bytes txHash) do //Retrieves transaction details from hash
return(string rawTransaction, int transactionIndex, bytes merkleSibling, bytes blockHash)
end
function decodeRawTransaction(string rawTransaction) do //Decode input from raw tx
return(JSON(rawTransaction.data))//returns a JSON object corresponding to the data field of a tx
end
function registerNetwork(SC ACCS, SC relay, string networkName, address myAddress, pk myPrivKey){
//This functions create and registers a new blockchain network
Network network = Network({
this.ACCS = ACCS;
this.relay = relay;
this.myAddress = myAddress;
this.myPrivKey = myPrivKey;
})
this.networks[networkName] = network;
}
//This pre commit function can be called either by the initiator or the participant
//When called by the initiator the parameters swapID, receiver and hashed secret are set to null
//When called by the participant the parameters swapID, receiver and hashed secret are set to the value of the other swap in pre commited state
function preCommit(bytes swapID, string originNetwork, string targetNetwork, int value, float exchangeRatio, bytes hashedSecret, address receiver) do
//Register a new swap
Swap swap = Swap({
if(swapID == null)
//If initiator
this.swapID = random(32);
else
//If participant
this.swapID = swapID;
end if
this.targetNetwork = targetNetwork;
this.originNetwork = originNetwork;
this.value = value;
this.exchangeRatio = exchangeRatio;
this.receiver = receiver;
//If initiator
if(hashedSecret == null)
this.secret = random(32),//Generate random 32 Bytes
this.hashedSecret = SHA256(this.secret)//Hash secret
//Else if participant
else
this.secret = null;
//Set same hashed secret as the other preCommited swap
this.hashedSecret = hashedSecret;
end if
})
string txHash = networks[originNetwork].ACCS.call.preCommit(swap.swapID, swap.hashedSecret, swap.value, swap.exchangeRatio, swap.targetNetwork)
if(txHash != null)//If tx worked
this.swaps[txHash] = swap;
this.swapStates[txHash] = PRECOMMITED;
if(receiver != null)//If the swap is already in preCommit state on the other side
//Request commit on the other side
if(networks[targetNetwork].ACCS.call.reqCommit(this.decodeRawTransaction(txHash) != null))
//Request self commit
network[originNetwork].ACCS.call.commmit(swap.swapID, receiver);
swapStates[swapID] = COMMITED;
//Run the participant cron job to redeem or refund
cronJobParticipant(swap.swapID)
end if
else
//Run initiator cron job
cronJobInitiator(swap.swapID)
end if
end if
end
//Can be called anytime while swap is in precommit state
function refund(bytes swapID) do
this.networks[this.swaps[swapID].originNetwork].ACCS.call.refund(swapID);
this.swapStates[swapID] = REFUNDED;
end
//Participant redeem refund cron job
function cronJobParticipant(bytes swapID) do
//While the swap is not redeemed or refunded
while(this.swapStates[swapID] != (REDEEMED || REFUNDED)) do
//For every new incoming and validated new blocks i.e burried under a sufficient amount of blocks
for(every new valid block of networks[this.swaps[swapID].originNetwork]) do
//Check if the secret key has been revelated i.e the swap has been redeemed
secret = this.networks[this.swaps[swapID].originNetwork].ACCS.call.checkSecretKey(swapID);
if (secret != null) do
//Call the redeem function with the newly revelated key
if(this.networks[this.swaps[swapID].targetNetwork].ACCS.call.redeem(swapID, secret)) do
//If the transaction has been executed, break the loop by passing to redeemed state
this.swapStates[swapID] = REDEEMED;
end if
end if
//If the timelock has expired
if(this.networks[this.swaps[swapID].originNetwork].ACCS.call.checkTimelock(swapID)<= now) do
//Call the refund function
if(this.networks[this.swaps[swapID].originNetwork].ACCS.call.refund(swapID))
//If the transaction has been executed, break the loop by passing to refunded state
this.swapStates[swapID] = REFUNDED;
end if
end if
end for
end while
end
//Initiator redeem refund cron job
function cronJobInitiator(bytes swapID) do
//While the swap is not redeemed or refunded
while(this.swapStates[swapID] != (REDEEMED || REFUNDED)) do
//For every new incoming and validated new blocks i.e burried under a sufficient amount of blocks
for(every new valid block of networks[this.swaps[swapID].targetNetwork]) do
//Check if a swap of corresponding ID is in commited state on the target network
if (this.networks[this.swaps[swapID].targetNetwork].ACCS.call.checkState(swapID) == COMMITED) do
//If timelock is expired call refund
if(this.networks[this.swaps[swapID].targetNetwork].ACCS.call.checkTimelock(swapID) <= now) do
this.networks[this.swaps[swapID].originNetwork].ACCS.call.refund(swapID);
this.swapStates[swapID] = REFUNDED;
end if
//If timelock not expired redeem swap on target network
if(this.networks[this.swaps[swapID].targetNetwork].ACCS.call.redeem(swapID, this.swaps[swapID].secret)) do
this.swapStates[swapID] = REDEEMED;
end if
end if
end for
end while
end
function reqPreCommit(string txHash, string targetNetwork) do
data = this.audit(txHash).data
this.preCommit(data.swapID, data.targetNetwork, data.originNetwork, data.value, 1/data.exchangeRatio, data.hashedSecret, data.receiver)
//In this function call target network and origin network are swapped in the pipe for symetry
//In this function call exchange ratio has been inversed for symetry
end
function audit(string txHash, string targetNetwork) do
//Calls a relay to verify that the provided tx is valid and burried under sufficient blocks
//Decodes the raw TX
//Returns an object containing tx data
requires ralays.targetNetwork.verifyTransaction(this.getTransactionByHash(txHash)) == true
return decodeRawTransaction(this.getTransactionByHash(txHash).rawTransaction)
end
}