def _load_from_bytes(self, tx_data: bytes, meta_data: bytes) -> 'BaseTransaction': from hathor.transaction.base_transaction import tx_or_block_from_bytes from hathor.transaction.transaction_metadata import TransactionMetadata tx = tx_or_block_from_bytes(tx_data) tx._metadata = TransactionMetadata.create_from_json( json_loadb(meta_data)) tx.storage = self return tx
def render_POST(self, request): """ Post request /create_tx/ that returns an encoded tx, if valid Expects {"inputs":[{"tx_id": <hex encoded>, "index": <int>, "data": <optional base64 encoded>}], "outputs":[{"value": <int, 1.00 HTR = 100>, "token_uid": <optional omit for HTR, hex encoded>, "address" or "script"}]} as POST data """ request.setHeader(b'content-type', b'application/json; charset=utf-8') set_cors(request, 'POST') body_content = json_loadb(request.content.read()) raw_inputs = body_content.get('inputs', []) raw_outputs = body_content.get('outputs', []) inputs = [TxInput.create_from_dict(i) for i in raw_inputs] tokens = [] outputs = [from_raw_output(i, tokens) for i in raw_outputs] timestamp = int(max(self.manager.tx_storage.latest_timestamp, self.manager.reactor.seconds())) parents = self.manager.get_new_tx_parents(timestamp) # this tx will have to be mined by tx-mining-server or equivalent tx = Transaction( timestamp=timestamp, inputs=inputs, outputs=outputs, parents=parents, storage=self.manager.tx_storage, ) fake_signed_tx = tx.clone() for tx_input in fake_signed_tx.inputs: # conservative estimate of the input data size to estimate a valid weight tx_input.data = b'\0' * 107 tx.weight = minimum_tx_weight(fake_signed_tx) tx.verify_unsigned_skip_pow() if tx.is_double_spending(): raise InvalidNewTransaction('At least one of your inputs has already been spent.') hex_data = bytes(tx).hex() data = tx.to_json() data.pop('hash', None) data.pop('nonce', None) return json_dumpb({ 'success': True, 'hex_data': hex_data, 'data': data, })
def onMessage(self, payload: bytes, isBinary: bool) -> None: self.log.info('message', payload=payload) try: data: Union[List[Dict], Dict] = json_loadb(payload) except JSONDecodeError: return self.send_response(error=JSON_RPC_PARSE_ERROR) try: if isinstance(data, list): for batch_data in data: self._handle_request(batch_data) else: self._handle_request(data) except Exception: self.log.warn('internal error', exc_info=True) return self.send_response(error=JSON_RPC_INTERNAL_ERROR)
def render_POST(self, request): """ POST request for /submit_block/ """ request.setHeader(b'content-type', b'application/json; charset=utf-8') set_cors(request, 'GET') data = json_loadb(request.content.read()) tx = tx_or_block_from_bytes(bytes.fromhex(data['hexdata']), storage=self.manager.tx_storage) if not tx.is_block: self.log.debug('expected Block, received Transaction', data=data) raise APIError('Not a block') if not self.manager.can_start_mining(): self.log.debug('cannot propagate Block, node syncing', data=data) raise APIError('Node syncing') res = self.manager.submit_block(tx) return json_dumpb({'result': res})
def lineReceived(self, line: bytes) -> None: """Receives a line and parses it, checking if it is a valid JSON-RPC 2.0 message. If the message is valid, it calls a request, result or error handler. Otherwise it sends an appropriate error message to the sender. :param line: Bytes of a serialized JSON RPC request :type line: bytes """ self.log.debug('line received', line=line) try: data = json_loadb(line) except JSONDecodeError: return self.send_error(PARSE_ERROR, data={'message': line.decode()}) assert isinstance(data, dict) msgid = data.get('id') if 'method' in data: return self.handle_request(data['method'], data.get('params'), msgid) elif 'result' in data and 'error' in data: if data['result'] and data['error'] is None: return self.handle_result(data['result'], msgid) elif data['error'] and data['result'] is None: return self.handle_error(data['error'], data.get('data'), msgid) elif 'result' in data: return self.handle_result(data['result'], msgid) elif 'error' in data: return self.handle_error(data['error'], data.get('data'), msgid) return self.send_error( INVALID_REQUEST, data={ 'message': data, 'error': 'Could not identify message as request, result or error.' })
def render_POST(self, request: Request) -> bytes: """ POST request for /push_tx/ """ request.setHeader(b'content-type', b'application/json; charset=utf-8') set_cors(request, 'POST') error_ret = json_dumpb({ 'success': False, 'message': 'Missing hexadecimal data', 'can_force': False }) body_content = request.content.read() if not body_content: return error_ret data = json_loadb(body_content) # Need to do that because json_loadb returns an object, which is not compatible with Dict[str, Any] data = cast(Dict[str, Any], data) if 'hex_tx' not in data: return error_ret return self.handle_push_tx(data)
def json_value(self): return json_loadb(self.written[0])
def _from_value_info(self, value: bytes) -> _InfoDict: return cast(_InfoDict, json_loadb(value))