# OFMF跨链对接

# 比特币跨链

对比特币跨链是通过检查接收地址(多签地址)OP_RETURN中的附加信息来确定的。对于OFMF系统而言,如果检测到交易输出中包含指定的接收地址,并且在附加信息中解码得到比原地址,这样便可以确定是一笔跨链请求交易。

跨链交易请求:

{
    "jsonrpc":"2.0",
    "method":"createrawtransaction",
    "id":1,
    "params":[
        [
            {
                "txid":"79d2d49cee6a2b37838ac1f2b459f7820a4efdfb91a0d20417b835ae10dea801",
                "vout":0
            }
        ],
        [
            {
                "2N5KvkLV9JzEqVeLpc7tG5LB9ZkzXB8xGLh":49               // 多签地址
            },
            {
                "data":"0014ce6cf18e24407480b22fb086358e8071a672f62a"  // 附加信息(包含比原的control_program)
            },
            {
                "2NAj8SjSVhZL8iry9fRnzcKgp8VotL3T8R2":0.9               // 找零地址
            }
        ]
    ]
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24

跨链交易响应:

{
    "result": "020000000101a8de10ae35b81704d2a091fbfd4e0a82f759b4f2c18a83372b6aee9cd4d2790000000000ffffffff03001110240100000017a91484853295a31883eb9b499f1616d5dfe595ba7650870000000000000000186a160014ce6cf18e24407480b22fb086358e8071a672f62a804a5d050000000017a914bfc128490ae2ee6b91da82fc762445eded61d8ae8700000000",
    "error": null,
    "id": 1
}
1
2
3
4
5

跨链交易详细信息:

{
    "result": {
        "txid": "3af30005081c1fe084872564ff7e1c75fda617c75f6e80987498ce5a84ac8262",
        "hash": "3af30005081c1fe084872564ff7e1c75fda617c75f6e80987498ce5a84ac8262",
        "version": 2,
        "size": 148,
        "vsize": 148,
        "weight": 592,
        "locktime": 0,
        "vin": [
            {
                "txid": "79d2d49cee6a2b37838ac1f2b459f7820a4efdfb91a0d20417b835ae10dea801",
                "vout": 0,
                "scriptSig": {
                    "asm": "",
                    "hex": ""
                },
                "sequence": 4294967295
            }
        ],
        "vout": [
            {
                "value": 49.00000000,
                "n": 0,
                "scriptPubKey": {
                    "asm": "OP_HASH160 84853295a31883eb9b499f1616d5dfe595ba7650 OP_EQUAL",
                    "hex": "a91484853295a31883eb9b499f1616d5dfe595ba765087",
                    "reqSigs": 1,
                    "type": "scripthash",
                    "addresses": [
                        "2N5KvkLV9JzEqVeLpc7tG5LB9ZkzXB8xGLh"
                    ]
                }
            },
            {
                "value": 0.00000000,
                "n": 1,
                "scriptPubKey": {
                    "asm": "OP_RETURN 0014ce6cf18e24407480b22fb086358e8071a672f62a",  // OP_RETURN + 比原地址对应的control_program
                    "hex": "6a160014ce6cf18e24407480b22fb086358e8071a672f62a",
                    "type": "nulldata"
                }
            },
            {
                "value": 0.90000000,
                "n": 2,
                "scriptPubKey": {
                    "asm": "OP_HASH160 bfc128490ae2ee6b91da82fc762445eded61d8ae OP_EQUAL",
                    "hex": "a914bfc128490ae2ee6b91da82fc762445eded61d8ae87",
                    "reqSigs": 1,
                    "type": "scripthash",
                    "addresses": [
                        "2NAj8SjSVhZL8iry9fRnzcKgp8VotL3T8R2"
                    ]
                }
            }
        ]
    },
    "error": null,
    "id": 1
}
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

# 以太坊跨链

以太坊跨链是通过检测多签合约比原地址注册合约两部分来构成的,为了以后兼容以太坊的ERC20系列币种,跨链到比原上的地址都通过注册合约的形式来获取。要构建一笔跨到OFMF系统的交易,首先需要调用注册合约将自己的发送地址跟比原地址绑定起来,然后再发送以太币ether到多签合约地址上。因此,用户只需要在第一次跨链的时候完成跨链地址的注册,便可以在以后的跨链过程中重复使用了。对于OFMF系统而言,如果检测到交易目标地址是多签合约,并且在注册合约中能够找到发送者注册的比原地址,这样便可以确定是一笔跨链请求交易。

转账到多签合约地址

跨链交易请求:(普通转账交易)

{
    "jsonrpc":"2.0",
    "method":"eth_sendTransaction",
    "id":1,
    "params":[
        {
            "from":"0x9ba9ae032a2709efb6eb5651b78058f19f01a38c",   //  用户地址
            "to":"0xd14cedc448bfcd8cc3e1b94786573bd6fbd5c661",     //  多签合约地址
            "gas":"0x83bb",
            "gasPrice":"0x1caf4ad00",
            "value":"0x38d7ea4c68000",
            "data":"0xd46e8dd67c5d32be8d46e8dd67c5d32be8058bb8eb970870f072445675058bb8eb970870f072445675"
        }
    ]
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15

跨链交易响应:

{
    "jsonrpc":"2.0",
    "id":1,
    "result":"0xab6fb2d09cd0b7dc44eb4de86ef43ad19fba2c82df2a495e5bb9d33f2e80561f"
}
1
2
3
4
5

跨链交易详细信息:

{
    "jsonrpc": "2.0",
    "id": 1,
    "result": {
        "blockHash": "0x7e27fee38b0df028f4322e7ebf95d8f47ed0da7733fa1ddbec779d7aaf6fadce",
        "blockNumber": "0x1067230",
        "chainId": "0x2a",
        "condition": null,
        "creates": null,
        "from": "0x9ba9ae032a2709efb6eb5651b78058f19f01a38c",
        "gas": "0x83bb",
        "gasPrice": "0x1caf4ad00",
        "hash": "0xab6fb2d09cd0b7dc44eb4de86ef43ad19fba2c82df2a495e5bb9d33f2e80561f",
        "input": "0x",
        "nonce": "0xdb",
        "publicKey": "0x465a7b51942e0617debaefbfdd9b31a049a19b9068f54587e3a5e737ab191c5783c350d335be550c2c674df94095aa26e5f3bf6535a4a75255ad7db4b60b2eaa",
        "r": "0x29830089f30076d8be18d91bd26afa8044a51f2b32e88533046c54761ddff844",
        "raw": "0xf86c81db8501caf4ad008283bb94d14cedc448bfcd8cc3e1b94786573bd6fbd5c66187038d7ea4c680008077a029830089f30076d8be18d91bd26afa8044a51f2b32e88533046c54761ddff844a0509f817bdcf481fecb526fe686e627287cc9860d44fc300dc3a257a0f394cc8a",
        "s": "0x509f817bdcf481fecb526fe686e627287cc9860d44fc300dc3a257a0f394cc8a",
        "standardV": "0x0",
        "to": "0xd14cedc448bfcd8cc3e1b94786573bd6fbd5c661",
        "transactionIndex": "0x0",
        "v": "0x77",
        "value": "0x38d7ea4c68000"
    }
}
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

# 调用注册比原地址合约

注册比原地址合约为Register,继承了PausableOwnable,拥有暂停调用和权限控制功能。该合约对外提供了3个函数接口:

  • addUser 该函数是供用户注册以太坊地址和比原地址的映射关系
  • OwnerChangeRegistry 该函数供合约拥有者修改注册信息
  • getVapor 该函数用于查询以太坊地址对应的比原地址

注册比原地址合约源代码如下:

pragma solidity ^0.4.16;

contract Ownable {
    address public owner;

    /**
      * @dev Throws if called by any account other than the owner.
      */
    modifier onlyOwner() {
        require(msg.sender == owner);
        _;
    }

    /**
      * @dev The Ownable constructor sets the original `owner` of the contract to the sender
      * account.
      */
    function Ownable() public {
        owner = msg.sender;
    }

    /**
    * @dev Allows the current owner to transfer control of the contract to a newOwner.
    * @param newOwner The address to transfer ownership to.
    */
    function transferOwnership(address newOwner) public onlyOwner {
        if (newOwner != address(0)) {
            owner = newOwner;
        }
    }
}


contract Pausable is Ownable {
    bool public paused = false;

    event Pause();
    event Unpause();
    
    /**
    * @dev Modifier to make a function callable only when the contract is not paused.
    */
    modifier whenNotPaused() {
        require(!paused);
        _;
    }

    /**
    * @dev Modifier to make a function callable only when the contract is paused.
    */
    modifier whenPaused() {
        require(paused);
        _;
    }

    /**
    * @dev called by the owner to pause, triggers stopped state
    */
    function pause() onlyOwner whenNotPaused public {
        paused = true;
        Pause();
    }

    /**
    * @dev called by the owner to unpause, returns to normal state
    */
    function unpause() onlyOwner whenPaused public {
        paused = false;
        Unpause();
    }
}


contract Register is Pausable {
    // eth 地址 ==> vapor 地址的 map
    mapping(address => string) public registry;
    
    // map 中添加新用户, eth 地址为合约调用者,仅未暂停状态下可以调用
    function addUser(string vaporAddress) public whenNotPaused {
        registry[msg.sender] = vaporAddress;
    }

    // 合约所有者可以任意更改 map 中的对应关系,仅合约所有者可以调用
    function OwnerChangeRegistry(address ethAddress,string vaporAddress) public onlyOwner {
        registry[ethAddress] = vaporAddress;
    }
    
    //返回 map 中eth 地址对应的 vapor 地址
    function getVapor(address ethAddress) public constant returns (string) {
        return registry[ethAddress];
    }
}
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

官方开发了一个基于H5开发的以太坊注册比原合约地址的DAPP系统,如果钱包支持H5的嵌入,便可以直接使用(例如imtoken)。此外,钱包还可以根据自己的需求定制该合约的DAPP。

上次更新: 3/30/2020, 11:49:24 AM