OSDN Git Service

fix bug and add tool for claim tx
[bytom/vapor.git] / tools / side_chain_tool / app / api / transaction.py
1 # -*- coding:utf-8 -*-
2 import json
3 from flask import request, jsonify, make_response, current_app, render_template
4 #from sqlalchemy.exc import SQLAlchemyError, IntegrityError
5
6 from . import api
7 from .Connection import Connection, WSClient
8 from .. import db
9 from ..models import KeyPair, PeginAddress
10
11
12 @api.route('/create_key_pair', methods=['POST', 'GET', 'OPTIONS'])
13 def create_key_pair():
14     keypairs = KeyPair.query.all()
15     if len(keypairs) > 5 :
16         return json_contents(jsonify(code=200, msg="There are already 5 private-public key pairs"))
17
18     connection = Connection("http://127.0.0.1:8888")
19     response = connection.request("/create-key-pair")
20     resp_json = json.loads(response.text)
21     if resp_json['status'] == 'success':
22         xprv = resp_json['data']['xprv']
23         xpub = resp_json['data']['xpub']
24         key = KeyPair(xprv=xprv,xpub=xpub)
25         db.session.add(key)
26         db.session.commit()
27     elif resp_json['status'] == 'fail':
28         return json_contents(jsonify(code=-1, msg=resp_json['msg']))
29     else:
30         return json_contents(jsonify(code=-1, msg="create key pair fail"))
31
32     return json_contents(jsonify(code=200, msg=""))
33
34 @api.route('/get_key_pair',methods=['POST', 'GET', 'OPTIONS'])
35 def get_key_pair():
36     keypairs = KeyPair.query.all()
37     json_data = ""
38     index = 0
39     num = len(keypairs)
40     for keypair in keypairs:
41         data = {
42             "xprv":keypair.xprv.encode('utf-8'),
43             "xpub": keypair.xpub.encode('utf-8')
44         }
45         json_data = json_data + json.dumps(data)
46         index = index + 1
47         if index < num:
48             json_data = json_data + ","
49     return json_contents(jsonify(code=200, msg="sucess", data="[" + json_data + "]"))
50
51
52 @api.route('/create_pegin_address', methods=['GET', 'POST', 'OPTIONS'])
53 def create_pegin_address():
54     if not request.json or not 'account_id' in request.json:
55         return json_contents(jsonify(code=-1, msg="The json format is incorrect"))
56     accountID = request.json['account_id']
57     connSide = Connection("http://127.0.0.1:8888")
58     body_json = {"account_id": accountID}
59     response = connSide.request("/get-pegin-contract-address",body_json)
60     resp_json = json.loads(response.text)
61     if resp_json['status'] == 'success':
62         mainchain_address = resp_json['data']['mainchain_address']
63         control_program = resp_json['data']['control_program']
64         claim_script = resp_json['data']['claim_script']
65         pegin = PeginAddress(address=mainchain_address, control_program=control_program, claim_script=claim_script)
66         db.session.add(pegin)
67         db.session.commit()
68     elif resp_json['status'] == 'fail':
69         return json_contents(jsonify(code=-1, msg=resp_json['msg']))
70     else:
71         return json_contents(jsonify(code=-1, msg="get pegin address fail"))
72     #return render_template('peginaddress.html', mainchain_address=mainchain_address,claim_script=claim_script)
73     return json_contents(jsonify(code=200, msg=""))
74
75 @api.route('/get_pegin_address',methods=['POST', 'GET', 'OPTIONS'])
76 def get_pegin_address():
77     peginAddrs = PeginAddress.query.all()
78     json_data = ""
79     index = 0
80     num = len(peginAddrs)
81     for peginAddr in peginAddrs:
82         data = {
83             "mainchain_address":peginAddr.address.encode('utf-8'),
84             "control_program":peginAddr.control_program.encode('utf-8'),
85             "claim_script": peginAddr.claim_script.encode('utf-8')
86         }
87         json_data = json_data + json.dumps(data)
88         index = index + 1
89         if index < num:
90             json_data = json_data + ","
91     return json_contents(jsonify(code=200, msg="sucess", data="[" + json_data + "]"))
92
93
94 @api.route('/claim_tx', methods=['GET', 'POST', 'OPTIONS'])
95 def claim_tx():
96     if not request.json or not 'claim_script' in request.json or not 'block_height' in request.json or not 'tx_id' in request.json or not 'password' in request.json:
97         return json_contents(jsonify(code=-1, msg="The json format is incorrect"))
98     block_height = int(request.json['block_height'])
99     tx_id = request.json['tx_id'].encode('utf-8')
100     password = request.json['password'].encode('utf-8')
101     claim_script = request.json['claim_script'].encode('utf-8')
102     connSide = Connection("http://127.0.0.1:8888")
103     connMain = Connection("http://127.0.0.1:9888")
104     raw_block = ""
105     raw_transaction = ""
106     block_hash = ""
107     proof=""
108     # 从主链获取raw_block
109     body_json = {"block_height": block_height}
110     response = connMain.request("/get-raw-block",body_json)
111     resp_json = json.loads(response.text)
112     if resp_json['status'] == 'success':
113         raw_block = resp_json['data']['raw_block'].encode('utf-8')
114     elif resp_json['status'] == 'fail':
115         print resp_json
116         return json_contents(jsonify(code=-1, msg="get-raw-block: " + resp_json['error_detail']))
117     else:
118         return json_contents(jsonify(code=-1, msg="get raw block fail"))
119
120     # 获取raw transaction
121     body_json = {"tx_id": tx_id,"raw_block": raw_block}
122     response = connSide.request("/get-raw-transaction",body_json)
123     resp_json = json.loads(response.text.encode('utf-8'))
124     if resp_json['status'] == 'success':
125         raw_transaction = resp_json['data']['raw_transaction'].encode('utf-8')
126         block_hash = resp_json['data']['block_hash'].encode('utf-8')
127     elif resp_json['status'] == 'fail':
128         print resp_json
129         return json_contents(jsonify(code=-1, msg="get-raw-transaction: " + resp_json['error_detail']))
130     else:
131         return json_contents(jsonify(code=-1, msg="get raw transaction fail"))
132
133     # 主链获取proof
134     print block_hash
135     body_json = {"tx_id": tx_id,"block_hash": block_hash}
136     response = connMain.request("/get-merkle-proof",body_json)
137     resp_json = json.loads(response.text)
138     if resp_json['status'] == 'success':
139         proof = json.dumps(resp_json['data']).strip('{}')
140     elif resp_json['status'] == 'fail':
141         print resp_json
142         return json_contents(jsonify(code=-1, msg="get-merkle-proof:" + resp_json['error_detail']))
143     else:
144         return json_contents(jsonify(code=-1, msg="get raw transaction fail"))
145
146     # 调用claimtx
147     body_json = '{"password": "%s","raw_transaction": "%s","claim_script":"%s",%s}' % (password,raw_transaction,claim_script,proof)
148     print body_json
149     response = connSide.request("/claim-pegin-transaction",json.loads(body_json))
150     resp_json = json.loads(response.text)
151     if resp_json['status'] == 'success':
152         return json_contents(jsonify(code=200, msg=resp_json['data']))
153     elif resp_json['status'] == 'fail':
154         print resp_json
155         return json_contents(jsonify(code=-1, msg="claim-pegin-transaction: " + resp_json['error_detail']))
156     else:
157         return json_contents(jsonify(code=-1, msg="claim pegin transaction fail"))
158
159
160 @api.route('/send_to_mainchain', methods=['GET', 'POST', 'OPTIONS'])
161 def send_to_mainchain():
162     #if not request.json or not 'claim_script' in request.json or not 'xprvs' in request.json or not 'tx_id' in request.json or not 'id' in request.json or not 'side_tx_id' in request.json or not 'block_height' in request.json or not 'side_block_height' in request.json or not 'alias' in request.json or not 'root_xpubs' in request.json or not 'address' in request.json or not 'control_program' in request.json:
163     if not request.json or not 'claim_script' in request.json or not 'tx_id' in request.json or not 'id' in request.json or not 'side_tx_id' in request.json or not 'block_height' in request.json or not 'side_block_height' in request.json or not 'alias' in request.json or not 'address' in request.json or not 'control_program' in request.json:
164         return json_contents(jsonify(code=-1, msg="The json format is incorrect"))
165
166     connSide = Connection("http://127.0.0.1:8888")
167     connMain = Connection("http://127.0.0.1:9888")
168     tx_id = request.json['tx_id'].encode('utf-8')
169     id = request.json['id'].encode('utf-8')
170     block_height = int(request.json['block_height'])
171     claim_script = request.json['claim_script'].encode('utf-8')
172
173     utxo = ""
174     # 从主链获取raw_block
175     body_json = {"block_height": block_height}
176     response = connMain.request("/get-raw-block",body_json)
177     resp_json = json.loads(response.text)
178     if resp_json['status'] == 'success':
179         raw_block = resp_json['data']['raw_block'].encode('utf-8')
180     elif resp_json['status'] == 'fail':
181         return json_contents(jsonify(code=-1, msg="get-raw-block: " + resp_json['msg']))
182     else:
183         return json_contents(jsonify(code=-1, msg="get raw block fail"))
184
185     # 获取主链上的utxo
186     address = request.json['address'].encode('utf-8')
187     body_json = {"tx_id": tx_id, "id": id, "raw_block": raw_block, "address": address}
188     response = connSide.request("/get-utxo-from-transaction",body_json)
189     resp_json = json.loads(response.text)
190     if resp_json['status'] == 'success':
191         utxo = json.dumps(resp_json['data']).strip('{}')+"}"
192     elif resp_json['status'] == 'fail':
193         return json_contents(jsonify(code=-1, msg="get-utxo-from-transaction: " + resp_json['msg']))
194     else:
195         return json_contents(jsonify(code=-1, msg="fail get utxo from transaction"))
196
197     block_height = int(request.json['side_block_height'])
198     tx_id  = request.json['side_tx_id'].encode('utf-8')
199     alias = request.json['alias'].encode('utf-8')
200     #root_xpubs = json.dumps(request.json['root_xpubs']).strip('{}')
201     root_xpubs = "["
202     control_program = request.json['control_program'].encode('utf-8')
203     key_pair = {}
204     f = open("key_pair","r") 
205     lines = f.readlines()
206     index = 0
207     num = len(lines)
208     for line in lines:
209         tmp = json.loads(line)
210         xprv = tmp['data']['xprv'].encode('utf-8')
211         xpub = tmp['data']['xpub'].encode('utf-8')
212         key_pair[xprv] = xpub
213         root_xpubs += "\"" + xpub + "\""
214         index = index + 1
215         if index < num:
216             root_xpubs = root_xpubs + ","
217
218     root_xpubs = root_xpubs + "]"
219     # 获取侧链raw transaction
220     body_json = {"tx_id": tx_id,"block_height": block_height}
221     response = connSide.request("/get-side-raw-transaction",body_json)
222     resp_json = json.loads(response.text.encode('utf-8'))
223     if resp_json['status'] == 'success':
224         raw_transaction = resp_json['data']['raw_transaction'].encode('utf-8')
225         block_hash = resp_json['data']['block_hash'].encode('utf-8')
226     elif resp_json['status'] == 'fail':
227         return json_contents(jsonify(code=-1, msg="get-side-raw-transaction: " + resp_json['msg']))
228     else:
229         return json_contents(jsonify(code=-1, msg="get side raw transaction fail"))
230
231     # 构建主链交易
232     body_json = '{"claim_script":"%s","raw_transaction": "%s","control_program":"%s","root_xpubs":%s,%s}' % (claim_script,raw_transaction,control_program,root_xpubs,utxo)
233     response = connSide.request("/build-mainchain-tx",json.loads(body_json))
234     resp_json = json.loads(response.text.encode('utf-8'))
235     tmpl = ""
236     if resp_json['status'] == 'success':
237         tmpl = json.dumps(resp_json['data'])
238     elif resp_json['status'] == 'fail':
239         print resp_json
240         return json_contents(jsonify(code=-1, msg="build-mainchain-tx: " + resp_json['msg']))
241     else:
242         return json_contents(jsonify(code=-1, msg="build mainchain transaction fail"))
243
244     # 签名
245     for key,value in key_pair.items():
246         body_json = '{"xprv": "%s","xpub":"%s","transaction":%s,"claim_script":"%s"}' % (key,value,tmpl,claim_script)
247         response = connSide.request("/sign-with-key",json.loads(body_json))
248         resp_json = json.loads(response.text.encode('utf-8'))
249         if resp_json['status'] == 'success':
250             tmpl = json.dumps(resp_json['data']['transaction'])
251             raw_transaction = resp_json['data']['transaction']['raw_transaction'].encode('utf-8')
252         elif resp_json['status'] == 'fail':
253             return json_contents(jsonify(code=-1, msg="sign-with-key: " + resp_json['msg']))
254         else:
255             return json_contents(jsonify(code=-1, msg="sign-with-key fail"))
256     
257     # 提交到主链
258     body_json = '{"raw_transaction": "%s"}' % (raw_transaction)
259     response = connMain.request("/submit-transaction",json.loads(body_json))
260     resp_json = json.loads(response.text.encode('utf-8'))
261     print resp_json
262     if resp_json['status'] == 'success':
263         return json_contents(jsonify(code=200, msg=resp_json['data']))
264     elif resp_json['status'] == 'fail':
265         return json_contents(jsonify(code=-1, msg="submit-transaction: " + resp_json['msg']))
266     else:
267         return json_contents(jsonify(code=-1, msg="submit-transaction fail"))
268
269
270 def json_contents(jsonify):
271     response = make_response(jsonify)
272     response.headers['Access-Control-Allow-Origin'] = '*'
273     response.headers['Access-Control-Allow-Methods'] = '*'
274     response.headers['Access-Control-Allow-Headers'] = '*'
275     return response