4 Star 20 Fork 2

WeBank/WeCross-Console

加入 Gitee
与超过 1200万 开发者一起发现、参与优秀开源项目,私有仓库也完全免费 :)
免费加入
文件
克隆/下载
HTLC.sol 18.04 KB
一键复制 编辑 原始数据 按行查看 历史
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673
pragma solidity >=0.4.22 <0.6.0;
contract HTLC {
struct ProposalData {
string secret;
string sender;
string receiver;
string amount;
string timelock; // UNIX timestamp seconds - locked UNTIL this time
bool locked;
bool unlocked;
bool rolledback;
}
mapping(string => string) newProposalTxInfos;
// recode if you're the initiator
mapping(string => bool) htlcRoles;
mapping(string => uint) proposalIndexs;
// initiator is the one who initiates the htlc transaction
mapping(string => ProposalData) initiators;
// participant is the one who makes the deal with initiator
mapping(string => ProposalData) participants;
// record all unfinished proposals
string[] proposalList;
uint256 constant size = 1024; // capacity of proposal list
uint256[] public freeIndexStack;
uint256 depth; // current depth of free index stack [1 - size]
string constant splitSymbol = "##";
string constant nullFlag = "null";
string constant successFlag = "success";
constructor() public {
proposalList = new string[](size);
freeIndexStack = new uint[](size);
depth = size;
for(uint256 i = 0; i < size; i++) {
proposalList[i] = nullFlag;
freeIndexStack[i] = size - i - 1;
}
}
/* please override it
@param: hash
*/
function lock(string memory _hash) public
returns (string memory result)
{
if (!proposalIsExisted(_hash)) {
result = "proposal not exists";
return result;
}
if(getLockState(_hash)) {
result = "done";
return result;
}
uint256 timelock = getTimelock(_hash);
if(getRollbackState(_hash) || timelock <= (now / 1000)) {
result = "has rolled back";
return result;
}
result = "continue";
}
/* please override it
@param: hash | secret
*/
function unlock(string memory _hash, string memory _secret) public
returns (string memory result)
{
if (!proposalIsExisted(_hash)) {
result = "proposal not exists";
return result;
}
if (getUnlockState(_hash)) {
result = "done";
return result;
}
if(!hashMatched(_hash, _secret)) {
result = "hash not matched";
return result;
}
if (!getLockState(_hash)) {
result = "can not unlock until lock is done";
return result;
}
uint256 timelock = getTimelock(_hash);
if(getRollbackState(_hash) || timelock <= (now / 1000)) {
result = "has rolled back";
return result;
}
result = "continue";
}
/* please override it
@param: hash
*/
function rollback(string memory _hash) public
returns (string memory result)
{
if (!proposalIsExisted(_hash)) {
result = "proposal not exists";
return result;
}
if (getRollbackState(_hash)) {
result = "done";
return result;
}
uint256 timelock = getTimelock(_hash);
if(timelock > (now / 1000)) {
result = "not_yet";
return result;
}
if (!getLockState(_hash)) {
result = "no need to rollback unless lock is done";
return result;
}
if (getUnlockState(_hash)) {
result = "can not rollback if unlock is done";
return result;
}
result = "continue";
}
/*
@param:
hash | role |
sender0 | receiver0 | amount0 | timelock0 |
sender1 | receiver1 | amount1 | timelock1 |
*/
function newProposal(string memory _hash, string memory _role, string memory _sender0, string memory _receiver0, string memory _amount0, string memory _timelock0, string memory _sender1, string memory _receiver1, string memory _amount1, string memory _timelock1) public
returns (string memory result)
{
if(depth == 0) {
result = "the proposal queue is full, one moment please";
return result;
}
if (proposalIsExisted(_hash)) {
result = "proposal existed";
return result;
}
if(!rightTimelock(_timelock0, _timelock1)) {
result = "illegal timelocks";
return result;
}
if(sameString(_role, "true")) {
htlcRoles[_hash] = true;
if(stringToAddress(_sender0) != tx.origin) {
result = "only sender can new a proposal";
return result;
}
// initiator is not listed until secret is written
preAddProposal(_hash);
} else {
htlcRoles[_hash] = false;
if(stringToAddress(_sender1) != tx.origin) {
result = "only sender can new a proposal";
return result;
}
preAddProposal(_hash);
addProposal(_hash);
}
initiators[_hash] = ProposalData(
nullFlag,
_sender0,
_receiver0,
_amount0,
_timelock0,
false,
false,
false
);
participants[_hash] = ProposalData(
nullFlag,
_sender1,
_receiver1,
_amount1,
_timelock1,
false,
false,
false
);
result = successFlag;
}
/*
@param: hash | tx-hash | blockNum
*/
function setNewProposalTxInfo(string memory _hash, string memory _txHash, string memory _blockNum) public
{
newProposalTxInfos[_hash] = string(abi.encodePacked(
_txHash,
splitSymbol,
_blockNum)
);
}
/*
@param: hash
*/
function getNewProposalTxInfo(string memory _hash) public view
returns (string memory result)
{
string memory info = newProposalTxInfos[_hash];
if(bytes(info).length == 0) {
result = nullFlag;
} else {
result = info;
}
}
/*
@param: hash
*/
function getNegotiatedData(string memory _hash) public view
returns (string memory result)
{
if (!proposalIsExisted(_hash)) {
result = "proposal not exists";
return result;
}
result = string(abi.encodePacked(
initiators[_hash].sender,
"##",
initiators[_hash].receiver,
"##",
initiators[_hash].amount,
"##",
initiators[_hash].timelock,
"##",
participants[_hash].sender,
"##",
participants[_hash].receiver,
"##",
participants[_hash].amount,
"##",
participants[_hash].timelock)
);
}
/*
@param: hash
*/
function getProposalInfo(string memory _hash) public view
returns (string memory result)
{
if (!proposalIsExisted(_hash)) {
result = nullFlag;
return result;
}
if(htlcRoles[_hash]) {
result = string(abi.encodePacked(
"true##",
initiators[_hash].secret,
"##",
initiators[_hash].timelock,
"##",
boolToString(initiators[_hash].locked),
"##",
boolToString(initiators[_hash].unlocked),
"##",
boolToString(initiators[_hash].rolledback),
"##",
participants[_hash].timelock,
"##",
boolToString(participants[_hash].locked),
"##",
boolToString(participants[_hash].unlocked),
"##",
boolToString(participants[_hash].rolledback))
);
} else {
result = string(abi.encodePacked(
"false##null##",
participants[_hash].timelock,
"##",
boolToString(participants[_hash].locked),
"##",
boolToString(participants[_hash].unlocked),
"##",
boolToString(participants[_hash].rolledback),
"##",
initiators[_hash].timelock,
"##",
boolToString(initiators[_hash].locked),
"##",
boolToString(initiators[_hash].unlocked),
"##",
boolToString(initiators[_hash].rolledback))
);
}
}
/*
@param: hash | secret
*/
function setSecret(string memory _hash, string memory _secret) public
returns (string memory result)
{
if(!hashMatched(_hash, _secret)) {
result = "hash not matched";
return result;
}
if(htlcRoles[_hash]) {
initiators[_hash].secret = _secret;
} else {
participants[_hash].secret = _secret;
}
addProposal(_hash);
result = successFlag;
}
function preAddProposal(string memory _id) internal
{
uint256 index = freeIndexStack[depth - 1];
depth = depth - 1;
proposalIndexs[_id] = index;
}
function addProposal(string memory _id) internal
{
uint256 index = proposalIndexs[_id];
proposalList[index] = _id;
}
function getProposalIDs() public view
returns (string memory result)
{
result = proposalList[0];
for(uint256 i = 1; i < size; i++) {
result = string(abi.encodePacked(result, splitSymbol, proposalList[i]));
}
}
/*
@param: proposal id
*/
function deleteProposalID(string memory _id) public
returns (string memory result)
{
uint256 index = proposalIndexs[_id];
if(!sameString(proposalList[index], _id)) {
result = "invalid operation";
return result;
}
proposalList[index] = nullFlag;
freeIndexStack[depth] = index;
depth = depth + 1;
result = successFlag;
}
function getIndex(string memory _hash) public view
returns (uint256, uint256)
{
return (proposalIndexs[_hash], depth);
}
/*
@param: hash
*/
function setCounterpartyLockState(string memory _hash) public
{
if(!htlcRoles[_hash]) {
initiators[_hash].locked = true;
} else {
participants[_hash].locked = true;
}
}
/*
@param: hash
*/
function setCounterpartyUnlockState(string memory _hash) public
{
if(!htlcRoles[_hash]) {
initiators[_hash].unlocked = true;
} else {
participants[_hash].unlocked = true;
}
}
/*
@param: hash
*/
function setCounterpartyRollbackState(string memory _hash) public
{
if(!htlcRoles[_hash]) {
initiators[_hash].rolledback = true;
} else {
participants[_hash].rolledback = true;
}
}
// the following functions are internal
function getSender(string memory _hash) internal view
returns (address)
{
if(htlcRoles[_hash]) {
return stringToAddress(initiators[_hash].sender);
} else {
return stringToAddress(participants[_hash].sender);
}
}
function getReceiver(string memory _hash) internal view
returns (address)
{
if(htlcRoles[_hash]) {
return stringToAddress(initiators[_hash].receiver);
} else {
return stringToAddress(participants[_hash].receiver);
}
}
function getAmount(string memory _hash) internal view
returns (uint)
{
if(htlcRoles[_hash]) {
return stringToUint256(initiators[_hash].amount);
} else {
return stringToUint256(participants[_hash].amount);
}
}
function getTimelock(string memory _hash) internal view
returns (uint)
{
if(htlcRoles[_hash]) {
return stringToUint256(initiators[_hash].timelock);
} else {
return stringToUint256(participants[_hash].timelock);
}
}
function getLockState(string memory _hash) internal view
returns (bool)
{
if(htlcRoles[_hash]) {
return initiators[_hash].locked;
} else {
return participants[_hash].locked;
}
}
function getUnlockState(string memory _hash) internal view
returns (bool)
{
if(htlcRoles[_hash]) {
return initiators[_hash].unlocked;
} else {
return participants[_hash].unlocked;
}
}
function getRollbackState(string memory _hash) internal view
returns (bool)
{
if(htlcRoles[_hash]) {
return initiators[_hash].rolledback;
} else {
return participants[_hash].rolledback;
}
}
function setLockState(string memory _hash) internal
{
if(htlcRoles[_hash]) {
initiators[_hash].locked = true;
} else {
participants[_hash].locked = true;
}
}
function setUnlockState(string memory _hash) internal
{
if(htlcRoles[_hash]) {
initiators[_hash].unlocked = true;
} else {
participants[_hash].unlocked = true;
}
}
function setRollbackState(string memory _hash) internal
{
if(htlcRoles[_hash]) {
initiators[_hash].rolledback = true;
} else {
participants[_hash].rolledback = true;
}
}
function hashMatched(string memory _hash, string memory _secret) internal pure
returns (bool)
{
bytes memory a = abi.encodePacked(sha256(bytes(_secret)));
bytes memory b = hexStringToBytes(_hash);
return sha256(a) == sha256(b);
}
function proposalIsExisted(string memory _hash) internal view
returns (bool)
{
return (bytes(initiators[_hash].sender).length > 0 &&
bytes(participants[_hash].sender).length > 0);
}
function rightTimelock(string memory _t0, string memory _t1) internal view
returns (bool)
{
uint256 t0 = stringToUint256(_t0);
uint256 t1 = stringToUint256(_t1);
return t0 > (t1 + 200) && t1 > (now / 1000 + 200);
}
function sameString(string memory _str1, string memory _str2) internal pure
returns (bool)
{
return keccak256(bytes(_str1)) == keccak256(bytes(_str2));
}
// these are utilities
function stringToAddress(string memory _address) internal pure
returns (address)
{
bytes memory temp = bytes(_address);
if(temp.length != 42) {
revert(string(abi.encodePacked(_address, " is not a valid BCOS address")));
}
uint160 result = 0;
uint160 b1;
uint160 b2;
for (uint256 i = 2; i < 2 + 2 * 20; i += 2) {
result *= 256;
b1 = uint160(uint8(temp[i]));
b2 = uint160(uint8(temp[i + 1]));
if ((b1 >= 97) && (b1 <= 102)) {
b1 -= 87;
} else if ((b1 >= 65) && (b1 <= 70)) {
b1 -= 55;
} else if ((b1 >= 48) && (b1 <= 57)) {
b1 -= 48;
}
if ((b2 >= 97) && (b2 <= 102)) {
b2 -= 87;
} else if ((b2 >= 65) && (b2 <= 70)) {
b2 -= 55;
} else if ((b2 >= 48) && (b2 <= 57)) {
b2 -= 48;
}
result += (b1 * 16 + b2);
}
return address(result);
}
function stringToUint256(string memory _str) internal pure
returns (uint256)
{
bytes memory bts = bytes(_str);
uint256 result = 0;
uint256 len = bts.length;
for (uint256 i = 0; i < len; i++) {
if (uint8(bts[i]) >= 48 && uint8(bts[i]) <= 57) {
result = result * 10 + (uint8(bts[i]) - 48);
}
}
return result;
}
function hexStringToBytes(string memory _hexStr) internal pure
returns (bytes memory)
{
bytes memory bts = bytes(_hexStr);
require(bts.length%2 == 0);
bytes memory result = new bytes(bts.length/2);
uint256 len = bts.length/2;
for (uint256 i = 0; i < len; ++i) {
result[i] = byte(fromHexChar(uint8(bts[2*i])) * 16 +
fromHexChar(uint8(bts[2*i+1])));
}
return result;
}
function fromHexChar(uint8 _char) internal pure
returns (uint8)
{
if (byte(_char) >= byte('0') && byte(_char) <= byte('9')) {
return _char - uint8(byte('0'));
}
if (byte(_char) >= byte('a') && byte(_char) <= byte('f')) {
return 10 + _char - uint8(byte('a'));
}
if (byte(_char) >= byte('A') && byte(_char) <= byte('F')) {
return 10 + _char - uint8(byte('A'));
}
}
function boolToString(bool _flag) internal pure
returns (string memory)
{
if(_flag) {
return "true";
} else {
return "flase";
}
}
function uint256ToString(uint256 _value) internal pure
returns (string memory)
{
bytes32 result;
if (_value == 0) {
return "0";
} else {
while (_value > 0) {
result = bytes32(uint(result) / (2 ** 8));
result |= bytes32(((_value % 10) + 48) * 2 ** (8 * 31));
_value /= 10;
}
}
return bytes32ToString(result);
}
function bytes32ToString(bytes32 _bts32) internal pure
returns (string memory)
{
bytes memory result = new bytes(_bts32.length);
uint256 len = _bts32.length;
for(uint256 i = 0; i < len; i++) {
result[i] = _bts32[i];
}
return string(result);
}
}
Loading...
马建仓 AI 助手
尝试更多
代码解读
代码找茬
代码优化
Java
1
https://gitee.com/WeBank/WeCross-Console.git
git@gitee.com:WeBank/WeCross-Console.git
WeBank
WeCross-Console
WeCross-Console
master

搜索帮助