def pts_address(pubkey, compressed, ver, prefix): if compressed: pubkeybin = PublicKey(pubkey, **{"prefix": prefix}).__bytes__() else: pubkeybin = unhexlify( PublicKey(pubkey, **{ "prefix": prefix }).unCompressed()) #print(hexlify(pubkeybin),len(pubkeybin)) bin = '%02x' % (ver) + hexlify( ripemd160(hexlify(hashlib.sha256(pubkeybin).digest()).decode( 'ascii'))).decode("ascii") checksum = doublesha256(bin) #print('bin',bin) #print('csum1',checksum) hex = bin + hexlify(checksum[:4]).decode('ascii') #print('hex',hex) hash = hexlify(ripemd160(hex)).decode('ascii') #print('hash',hash) checksum2 = ripemd160(hash) #print('csum2',checksum2) b58 = prefix + base58encode(hash + hexlify(checksum2[:4]).decode('ascii')) #print('b58',b58) return b58
def decodeMemo(self, **kwargs): from_pubkey = kwargs.get('from') to_pubkey = kwargs.get('to') nonce = kwargs.get('nonce') cipher_text = kwargs.get('message') # local_privkey = self.privkeys[0] if not isinstance(from_pubkey, PublicKey): from_pubkey = PublicKey(from_pubkey, prefix=from_pubkey[0:3]) if not isinstance(to_pubkey, PublicKey): to_pubkey = PublicKey(to_pubkey, prefix=to_pubkey[0:3]) # if str(self.pubkey) == str(from_pubkey): # other_pubkey = to_pubkey # elif str(self.pubkey) == str(to_pubkey): # other_pubkey = from_pubkey if str(from_pubkey) in self.privkeys: local_privkey = self.privkeys[str(from_pubkey)] other_pubkey = to_pubkey elif str(to_pubkey) in self.privkeys: local_privkey = self.privkeys[str(to_pubkey)] other_pubkey = from_pubkey else: raise MissingKey( "No Private Key found for neither %s nor %s public keys" % (str(from_pubkey), str(to_pubkey))) clear = BTSMemo.decode_memo(local_privkey, other_pubkey, nonce, cipher_text) return clear
def decrypt(self, memo): """ Decrypt a memo :param str memo: encrypted memo message :returns: encrypted memo :rtype: str """ if not memo: return None # We first try to decode assuming we received the memo try: memo_wif = self.blockchain.wallet.getPrivateKeyForPublicKey( memo["to"]) pubkey = memo["from"] except KeyNotFound: try: # if that failed, we assume that we have sent the memo memo_wif = self.blockchain.wallet.getPrivateKeyForPublicKey( memo["from"]) pubkey = memo["to"] except KeyNotFound: # if all fails, raise exception raise MissingKeyError( "Non of the required memo keys are installed!" "Need any of {}".format([memo["to"], memo["from"]])) if not hasattr(self, 'chain_prefix'): self.chain_prefix = self.blockchain.prefix return BtsMemo.decode_memo(PrivateKey(memo_wif), PublicKey(pubkey, prefix=self.chain_prefix), memo.get("nonce"), memo.get("message"))
def encrypt(self, memo): """ Encrypt a memo :param str memo: clear text memo message :returns: encrypted memo :rtype: str """ if not memo: return None nonce = str(random.getrandbits(64)) memo_wif = self.bitshares.wallet.getPrivateKeyForPublicKey( self.from_account["options"]["memo_key"]) if not memo_wif: raise MissingKeyError("Memo key for %s missing!" % self.from_account["name"]) enc = BtsMemo.encode_memo( PrivateKey(memo_wif), PublicKey(self.to_account["options"]["memo_key"], prefix=self.bitshares.prefix), nonce, memo) return { "message": enc, "nonce": nonce, "from": self.from_account["options"]["memo_key"], "to": self.to_account["options"]["memo_key"] }
def create_blind_contact(self): label = self.ui.blindContactLabel.text().strip() public_key = self.ui.blindContactPubkey.text().strip() if len(public_key) == 0: self.ui.blindContactPubkey.setFocus() return if len(label) == 0: self.ui.blindContactLabel.setFocus() return from bitsharesbase.account import PublicKey try: test = PublicKey(public_key) except Exception as e: showerror("Not a valid Public Key: " + str(e)) return try: self.iso.store.blindAccountStorage.add(public_key, label, keys=0) except Exception as e: showexc(e) return table = self.ui.blindAccounts n = table.rowCount() self._insert_blind_account_row(n, label, public_key, 0) self.ui.blindContactLabel.setText("") self.ui.blindContactPubkey.setText("") self.ba_page_balances()
def encodeMemo(self, from_pubkey, to_pubkey, clear_text): from_pubkey = self.guessKey(from_pubkey) privkey = self.privkeys[str(from_pubkey)] if not isinstance(from_pubkey, (PublicKey, GPHPublicKey)): from_pubkey = PublicKey(from_pubkey, prefix=from_pubkey[0:3]) if not isinstance(to_pubkey, (PublicKey, GPHPublicKey)): to_pubkey = PublicKey(to_pubkey, prefix=to_pubkey[0:3]) import random nonce = str(random.getrandbits(64)) cipher = BTSMemo.encode_memo(privkey, to_pubkey, nonce, clear_text) return { "to": str(to_pubkey), "from": str(privkey.pubkey), "nonce": nonce, "message": cipher }
def update_memo_key(self, key, account=None): """ Update an account's memo public key This method does **not** add any private keys to your wallet but merely changes the memo public key. :param str key: New memo public key :param str account: (optional) the account to allow access to (defaults to ``default_account``) """ if not account: if "default_account" in config: account = config["default_account"] if not account: raise ValueError("You need to provide an account") PublicKey(key, prefix=self.rpc.chain_params["prefix"]) account = Account(account, bitshares_instance=self) account["options"]["memo_key"] = key op = operations.Account_update( **{ "fee": { "amount": 0, "asset_id": "1.3.0" }, "account": account["id"], "new_options": account["options"], "extensions": {} }) return self.finalizeOp(op, account["name"], "active")
async def _encrypt_memo(self, to, memo): ''' 加密备注信息 ''' if not memo: return None # 生成nonce nonce = str(random.getrandbits(64)) if SysConfig().memo_key == None: raise MissingKeyError('Memo key {0} missing!'.format(SysConfig().account)) # 加密备注信息 prefix = self.client.chain_params['prefix'] to_account = await self.client.get_account_by_name(to) enc = BtsMemo.encode_memo( PrivateKey(SysConfig().memo_key, prefix=prefix), PublicKey( prefix=prefix, pk=to_account['options']['memo_key'] ), nonce, memo ) # 返回结构信息 memo_data = { 'nonce': nonce, 'message': enc, 'to': to_account['options']['memo_key'], 'from': self.account['options']['memo_key'] } return to_account['id'], memo_data
def test_encrypt(self): for memo in test_cases: enc = encode_memo( PrivateKey(memo["wif"]), PublicKey(memo["to"], prefix="GPH"), memo["nonce"], memo["plain"], ) self.assertEqual(memo["message"], enc)
def test_decrypt_bugged_padding(self): for memo in not_enough_padding: dec = decode_memo( PrivateKey(memo["wif"]), PublicKey(memo["to"], prefix="GPH"), memo["nonce"], memo["message"], ) self.assertEqual(memo["plain"], dec)
def _create_account(account): parent_account = Account(DEFAULT_ACCOUNT, bitshares_instance=bitshares) public_key = PublicKey.from_privkey(PRIVATE_KEYS[0], prefix=bitshares.prefix) bitshares.create_account( account, registrar=DEFAULT_ACCOUNT, referrer=parent_account['id'], referrer_percent=0, owner_key=public_key, active_key=public_key, memo_key=public_key, storekeys=False, )
def approveproposal(self, proposal_ids, account=None, approver=None): """ Approve Proposal :param list proposal_id: Ids of the proposals :param str account: (optional) the account to allow access to (defaults to ``default_account``) """ from .proposal import Proposal if not account: if "default_account" in config: account = config["default_account"] if not account: raise ValueError("You need to provide an account") account = Account(account, bitshares_instance=self) is_key = approver and approver[:3] == self.rpc.chain_params["prefix"] if not approver and not is_key: approver = account elif approver and not is_key: approver = Account(approver, bitshares_instance=self) else: approver = PublicKey(approver) if not isinstance(proposal_ids, (list, set)): proposal_ids = set(proposal_ids) op = [] for proposal_id in proposal_ids: proposal = Proposal(proposal_id, bitshares_instance=self) update_dict = { "fee": { "amount": 0, "asset_id": "1.3.0" }, 'fee_paying_account': account["id"], 'proposal': proposal["id"], "prefix": self.rpc.chain_params["prefix"] } if is_key: update_dict.update({ 'key_approvals_to_add': [str(approver)], }) else: update_dict.update({ 'active_approvals_to_add': [approver["id"]], }) op.append(operations.Proposal_update(**update_dict)) if is_key: self.txbuffer.appendSigner(account["name"], "active") return self.finalizeOp(op, approver, "active") else: return self.finalizeOp(op, approver["name"], "active")
def verify(self, **kwargs): """ Verify a message with an account's memo key :param str account: (optional) the account that owns the bet (defaults to ``default_account``) :returns: True if the message is verified successfully :raises InvalidMessageSignature if the signature is not ok """ # Split message into its parts parts = re.split("|".join(MESSAGE_SPLIT), self.message) parts = [x for x in parts if x.strip()] assert len(parts) > 2, "Incorrect number of message parts" message = parts[0].strip() signature = parts[2].strip() # Parse the meta data meta = dict(re.findall(r'(\S+)=(.*)', parts[1])) # Ensure we have all the data in meta assert "account" in meta assert "memokey" in meta assert "block" in meta assert "timestamp" in meta # Load account from blockchain account = Account(meta.get("account"), bitshares_instance=self.bitshares) # Test if memo key is the same as on the blockchain if not account["options"]["memo_key"] == meta["memokey"]: log.error("Memo Key of account {} on the Blockchain".format( account["name"]) + "differs from memo key in the message: {} != {}".format( account["options"]["memo_key"], meta["memokey"])) # Reformat message message = SIGNED_MESSAGE_META.format(**locals()) # Verify Signature pubkey = verify_message(message, unhexlify(signature)) # Verify pubky pk = PublicKey(hexlify(pubkey).decode("ascii")) if format(pk, self.bitshares.prefix) != meta["memokey"]: raise InvalidMessageSignature return True
def decrypt(self, memo): """ Decrypt a memo :param str memo: encrypted memo message :returns: encrypted memo :rtype: str """ if not memo: return None memo_wif = self.bitshares.wallet.getPrivateKeyForPublicKey( self.to_account["options"]["memo_key"]) if not memo_wif: raise MissingKeyError("Memo key for %s missing!" % self.to_account["name"]) # TODO: Use pubkeys of the message, not pubkeys of account! return BtsMemo.decode_memo( PrivateKey(memo_wif), PublicKey(self.from_account["options"]["memo_key"], prefix=self.bitshares.rpc.chain_params["prefix"]), memo.get("nonce"), memo.get("message"))
def create_account( self, account_name, registrar=None, referrer="1.2.35641", referrer_percent=50, owner_key=None, active_key=None, memo_key=None, password=None, additional_owner_keys=[], additional_active_keys=[], additional_owner_accounts=[], additional_active_accounts=[], proxy_account="proxy-to-self", storekeys=True, ): """ Create new account on BitShares The brainkey/password can be used to recover all generated keys (see `bitsharesbase.account` for more details. By default, this call will use ``default_account`` to register a new name ``account_name`` with all keys being derived from a new brain key that will be returned. The corresponding keys will automatically be installed in the wallet. .. warning:: Don't call this method unless you know what you are doing! Be sure to understand what this method does and where to find the private keys for your account. .. note:: Please note that this imports private keys (if password is present) into the wallet by default. However, it **does not import the owner key** for security reasons. Do NOT expect to be able to recover it from the wallet if you lose your password! :param str account_name: (**required**) new account name :param str registrar: which account should pay the registration fee (defaults to ``default_account``) :param str owner_key: Main owner key :param str active_key: Main active key :param str memo_key: Main memo_key :param str password: Alternatively to providing keys, one can provide a password from which the keys will be derived :param array additional_owner_keys: Additional owner public keys :param array additional_active_keys: Additional active public keys :param array additional_owner_accounts: Additional owner account names :param array additional_active_accounts: Additional acctive account names :param bool storekeys: Store new keys in the wallet (default: ``True``) :raises AccountExistsException: if the account already exists on the blockchain """ if not registrar and config["default_account"]: registrar = config["default_account"] if not registrar: raise ValueError( "Not registrar account given. Define it with " + "registrar=x, or set the default_account using uptick") if password and (owner_key or active_key or memo_key): raise ValueError("You cannot use 'password' AND provide keys!") try: Account(account_name, bitshares_instance=self) raise AccountExistsException except: pass referrer = Account(referrer, bitshares_instance=self) registrar = Account(registrar, bitshares_instance=self) " Generate new keys from password" from bitsharesbase.account import PasswordKey, PublicKey if password: active_key = PasswordKey(account_name, password, role="active") owner_key = PasswordKey(account_name, password, role="owner") memo_key = PasswordKey(account_name, password, role="memo") active_pubkey = active_key.get_public_key() owner_pubkey = owner_key.get_public_key() memo_pubkey = memo_key.get_public_key() active_privkey = active_key.get_private_key() # owner_privkey = owner_key.get_private_key() memo_privkey = memo_key.get_private_key() # store private keys if storekeys: # self.wallet.addPrivateKey(owner_privkey) self.wallet.addPrivateKey(active_privkey) self.wallet.addPrivateKey(memo_privkey) elif (owner_key and active_key and memo_key): active_pubkey = PublicKey(active_key, prefix=self.rpc.chain_params["prefix"]) owner_pubkey = PublicKey(owner_key, prefix=self.rpc.chain_params["prefix"]) memo_pubkey = PublicKey(memo_key, prefix=self.rpc.chain_params["prefix"]) else: raise ValueError( "Call incomplete! Provide either a password or public keys!") owner = format(owner_pubkey, self.rpc.chain_params["prefix"]) active = format(active_pubkey, self.rpc.chain_params["prefix"]) memo = format(memo_pubkey, self.rpc.chain_params["prefix"]) owner_key_authority = [[owner, 1]] active_key_authority = [[active, 1]] owner_accounts_authority = [] active_accounts_authority = [] # additional authorities for k in additional_owner_keys: owner_key_authority.append([k, 1]) for k in additional_active_keys: active_key_authority.append([k, 1]) for k in additional_owner_accounts: addaccount = Account(k, bitshares_instance=self) owner_accounts_authority.append([addaccount["id"], 1]) for k in additional_active_accounts: addaccount = Account(k, bitshares_instance=self) active_accounts_authority.append([addaccount["id"], 1]) # voting account voting_account = Account(proxy_account or "proxy-to-self") op = { "fee": { "amount": 0, "asset_id": "1.3.0" }, "registrar": registrar["id"], "referrer": referrer["id"], "referrer_percent": referrer_percent * 100, "name": account_name, 'owner': { 'account_auths': owner_accounts_authority, 'key_auths': owner_key_authority, "address_auths": [], 'weight_threshold': 1 }, 'active': { 'account_auths': active_accounts_authority, 'key_auths': active_key_authority, "address_auths": [], 'weight_threshold': 1 }, "options": { "memo_key": memo, "voting_account": voting_account["id"], "num_witness": 0, "num_committee": 0, "votes": [], "extensions": [] }, "extensions": {}, "prefix": self.rpc.chain_params["prefix"] } op = operations.Account_create(**op) return self.finalizeOp(op, registrar, "active")
def test_shared_secret(self): for s in test_shared_secrets: priv = PrivateKey(s[0]) pub = PublicKey(s[1], prefix="GPH") shared_secret = get_shared_secret(priv, pub) self.assertEqual(s[2], shared_secret)
def disallow(self, foreign, permission="active", account=None, threshold=None): """ Remove additional access to an account by some other public key or account. :param str foreign: The foreign account that will obtain access :param str permission: (optional) The actual permission to modify (defaults to ``active``) :param str account: (optional) the account to allow access to (defaults to ``default_account``) :param int threshold: The threshold that needs to be reached by signatures to be able to interact """ if not account: if "default_account" in config: account = config["default_account"] if not account: raise ValueError("You need to provide an account") if permission not in ["owner", "active"]: raise ValueError( "Permission needs to be either 'owner', or 'active") account = Account(account, bitshares_instance=self) authority = account[permission] try: pubkey = PublicKey(foreign, prefix=self.rpc.chain_params["prefix"]) affected_items = list( filter(lambda x: x[0] == str(pubkey), authority["key_auths"])) authority["key_auths"] = list( filter(lambda x: x[0] != str(pubkey), authority["key_auths"])) except: try: foreign_account = Account(foreign, bitshares_instance=self) affected_items = list( filter(lambda x: x[0] == foreign_account["id"], authority["account_auths"])) authority["account_auths"] = list( filter(lambda x: x[0] != foreign_account["id"], authority["account_auths"])) except: raise ValueError( "Unknown foreign account or unvalid public key") removed_weight = affected_items[0][1] # Define threshold if threshold: authority["weight_threshold"] = threshold # Correct threshold (at most by the amount removed from the # authority) try: self._test_weights_treshold(authority) except: log.critical("The account's threshold will be reduced by %d" % (removed_weight)) authority["weight_threshold"] -= removed_weight self._test_weights_treshold(authority) op = operations.Account_update( **{ "fee": { "amount": 0, "asset_id": "1.3.0" }, "account": account["id"], permission: authority, "extensions": {} }) if permission == "owner": return self.finalizeOp(op, account["name"], "owner") else: return self.finalizeOp(op, account["name"], "active")
def clean_txs(self, account: Account, symbol: str, transactions: Iterable[dict]) -> Generator[dict, None, None]: """ Filters a list of transactions by the receiving account, yields dict's conforming with :class:`payments.models.Deposit` :param str account: The 'to' account to filter by :param str symbol: The symbol of the token being filtered :param list<dict> transactions: A list<dict> of transactions to filter :return: A generator yielding ``dict`` s conforming to :class:`payments.models.Deposit` """ for tx in transactions: try: data = tx['op'][ 1] # unwrap the transaction structure to get at the data within if data['to'] != account['id'] or data['from'] == account['id']: continue # cache asset data for 5 mins, so we aren't spamming the RPC node for data amount_info = data['amount'] asset_id = amount_info['asset_id'] asset_key = 'btsasset:%s' % (asset_id, ) asset = cache.get(asset_key, default=None) if asset is None: asset_obj = self.get_asset_obj(asset_id) if asset_obj is not None: asset = { 'symbol': asset_obj.symbol, 'precision': asset_obj.precision } cache.set(asset_key, asset, 300) else: continue if asset['symbol'] != symbol: continue raw_amount = Decimal(int(amount_info['amount'])) transfer_quantity = raw_amount / (10**asset['precision']) # cache account data for 5 mins, so we aren't spamming the RPC node for data account_key = 'btsacc:%s' % (data['from'], ) from_account_name = cache.get(account_key, default=data['from']) if from_account_name == data['from']: from_account = self.get_account_obj(data['from']) if from_account is not None: from_account_name = from_account.name cache.set(account_key, from_account_name, 300) else: log.exception( 'From account not found for transaction %s', tx) # decrypt the transaction memo memo_msg = '' if 'memo' in data: memo = data['memo'] try: memokey = self.get_private_key(account.name, 'memo') privkey = PrivateKey(memokey) pubkey = PublicKey(memo['from'], prefix='BTS') memo_msg = decode_memo(privkey, pubkey, memo['nonce'], memo['message']) except Exception as e: memo_msg = '--cannot decode memo--' log.exception( 'Error decoding memo %s, got exception %s', memo['message'], e) # fetch timestamp from the block containing this transaction # (a hugely inefficient lookup but unfortunately no other way to do this) tx_datetime = datetime.fromtimestamp( self.get_block_timestamp(tx['block_num'])) tx_datetime = timezone.make_aware(tx_datetime, pytz.UTC) clean_tx = dict(txid=tx['id'], coin=self.coins[symbol].symbol, tx_timestamp=tx_datetime, from_account=from_account_name, to_account=account.name, memo=memo_msg, amount=transfer_quantity) yield clean_tx except Exception as e: log.exception( 'Error parsing transaction data. Skipping this TX. tx = %s, exception = %s', tx, e) continue
def verify(self, **kwargs): """ Verify a message with an account's memo key :param str account: (optional) the account that owns the bet (defaults to ``default_account``) :returns: True if the message is verified successfully :raises InvalidMessageSignature if the signature is not ok """ # Split message into its parts parts = re.split("|".join(MESSAGE_SPLIT), self.message) parts = [x for x in parts if x.strip()] assert len(parts) > 2, "Incorrect number of message parts" # Strip away all whitespaces before and after the message message = parts[0].strip() signature = parts[2].strip() # Parse the meta data meta = dict(re.findall(r'(\S+)=(.*)', parts[1])) log.info("Message is: {}".format(message)) log.info("Meta is: {}".format(json.dumps(meta))) log.info("Signature is: {}".format(signature)) # Ensure we have all the data in meta assert "account" in meta, "No 'account' could be found in meta data" assert "memokey" in meta, "No 'memokey' could be found in meta data" assert "block" in meta, "No 'block' could be found in meta data" assert "timestamp" in meta, \ "No 'timestamp' could be found in meta data" account_name = meta.get("account").strip() memo_key = meta["memokey"].strip() try: PublicKey(memo_key) except Exception: raise InvalidMemoKeyException( "The memo key in the message is invalid") # Load account from blockchain try: account = Account(account_name, blockchain_instance=self.blockchain) except AccountDoesNotExistsException: raise AccountDoesNotExistsException( "Could not find account {}. Are you connected to the right chain?" .format(account_name)) # Test if memo key is the same as on the blockchain if not account["options"]["memo_key"] == memo_key: raise WrongMemoKey( "Memo Key of account {} on the Blockchain ".format( account["name"]) + "differs from memo key in the message: {} != {}".format( account["options"]["memo_key"], memo_key)) # Reformat message enc_message = SIGNED_MESSAGE_META.format(**locals()) # Verify Signature pubkey = verify_message(enc_message, unhexlify(signature)) # Verify pubky pk = PublicKey(hexlify(pubkey).decode("ascii")) if format(pk, self.blockchain.prefix) != memo_key: raise InvalidMessageSignature return True
print('invalid transaction for bit20 publication: {}'.format( json.dumps(trx, indent=4))) return False for f in account_history_b20: if not is_valid_bit20_publication(f): print('Hijacking attempt of the bit20 feed? trx: {}'.format( json.dumps(f, indent=4))) continue memo = f['op'][1]['memo'] privkey = PrivateKey(wifkey_announce) pubkey = PublicKey(Account(f['op'][1]['from'])['options']['memo_key']) memomsg = BtsMemo.decode_memo(privkey, pubkey, memo["nonce"], memo["message"]) #print(memomsg) if memomsg.startswith('COMPOSITION'): # last_updated = re.search('\((.*)\)', memomsg) # if last_updated: # last_updated = pendulum.from_format(last_updated.group(1), '%Y/%m/%d') # #print(last_updated) bit20 = json.loads(memomsg.split(')', maxsplit=1)[1]) break else: print( "Did not find any bit20 composition in the last {} messages to account bittwenty.feed"
async def _process_transfer_operations(self, client, operation): ''' 处理转账操作 ''' # 筛选操作类型 if operation['op'][0] != self.TRANSFER_OPERATION: return # 操作基本信息 trx = {} op = operation['op'][1] # 获取区块信息 trx['heigth'] = operation['block_num'] block_info = await client.get_block(trx['heigth']) trx['timestamp'] = block_info['timestamp'] # 获取交易ID trx_in_block = operation['trx_in_block'] transaction = block_info['transactions'][trx_in_block] trx['txid'] = await self._get_transaction_id(transaction) # 获取转账金额 asset = await self._get_asset_info(client, op['amount']['asset_id']) trx['asset'] = asset['symbol'] trx['asset_id'] = op['amount']['asset_id'] trx['amount'] = str( float(op['amount']['amount']) / float(10**int(asset['precision']))) # 获取转账手续费 trx['fee'] = {} fee = await self._get_asset_info(client, op['fee']['asset_id']) trx['fee']['asset'] = fee['symbol'] trx['fee']['asset_id'] = op['fee']['asset_id'] trx['fee']['amount'] = str( float(op['fee']['amount']) / float(10**int(fee['precision']))) # 获取涉案账户 trx['to_id'] = op['to'] trx['from_id'] = op['from'] trx['to'] = (await client.get_objects([op['to']]))[0]['name'] trx['from'] = (await client.get_objects([op['from']]))[0]['name'] # 解码备注信息 if 'memo' in op: memo = op['memo'] trx['nonce'] = memo['nonce'] try: privkey = PrivateKey(SysConfig().memo_key) prefix = client.chain_params['prefix'] if trx['to_id'] == self._account['id']: pubkey = PublicKey(memo['from'], prefix=prefix) else: pubkey = PublicKey(memo['to'], prefix=prefix) trx['memo'] = BtsMemo.decode_memo(privkey, pubkey, memo['nonce'], memo['message']) except Exception as e: logging.warn('Failed to decode memo, %s, %s', operation['id'], str(e)) trx['memo'] = None else: trx['memo'] = None trx['nonce'] = None return trx
def __init__(self,pubkey,period): o= GrapheneObject(OrderedDict ([ ("vesting_period",Uint64(period)), ("public_key",PublicKey(pubkey,**{"prefix":"CYB"})) ])) super().__init__(o,1)
def decrypt_msg(priv_key, pub_key, nonce, msg): dec = decode_memo(PrivateKey(priv_key), PublicKey(pub_key, prefix="NEST"), nonce, msg) return dec
async def process_operations(self, op_id): """ 处理操作 """ op_info = await self.node_api.get_objects([op_id]) for operation in op_info[::-1]: if operation["op"][0] != 0: return # 操作基本信息 trx = {} op = operation['op'][1] trx['trx_id'] = operation['id'] # 获取区块信息 trx['block_num'] = operation['block_num'] block_info = await self.node_api.get_block(trx['block_num']) trx['timestamp'] = block_info['timestamp'] # 获取转账金额 asset = await self.get_asset_info(op['amount']['asset_id']) trx['asset'] = asset['symbol'] trx['asset_id'] = op['amount']['asset_id'] trx['amount'] = float(op['amount']['amount']) / float(10**int( asset['precision'])) # 获取转账手续费 trx['fee'] = {} fee = await self.get_asset_info(op['fee']['asset_id']) trx['fee']['asset'] = fee['symbol'] trx['fee']['asset_id'] = op['fee']['asset_id'] trx['fee']['amount'] = float(op['fee']['amount']) / float(10**int( fee['precision'])) # 获取涉案账户 trx['to_id'] = op['to'] trx['from_id'] = op['from'] trx['to'] = (await self.node_api.get_objects([op['to']]))[0]['name'] trx['from'] = (await self.node_api.get_objects([op['from']]))[0]['name'] # 解码备注信息 if 'memo' in op: memo = op['memo'] trx['nonce'] = memo['nonce'] try: privkey = PrivateKey(self.wifkey) prefix = self.node_api.chain_params['prefix'] if trx['to_id'] == self.account['id']: pubkey = PublicKey(memo['from'], prefix=prefix) else: pubkey = PublicKey(memo['to'], prefix=prefix) trx['memo'] = BtsMemo.decode_memo(privkey, pubkey, memo['nonce'], memo['message']) except Exception: trx['memo'] = None else: trx['memo'] = None trx['nonce'] = None # 触发转账事件 if trx['from_id'] == self.account['id']: await self.on_sent(trx) elif trx['to_id'] == self.account['id']: await self.on_receive(trx)
def allow(self, foreign, weight=None, permission="active", account=None, threshold=None): """ Give additional access to an account by some other public key or account. :param str foreign: The foreign account that will obtain access :param int weight: (optional) The weight to use. If not define, the threshold will be used. If the weight is smaller than the threshold, additional signatures will be required. (defaults to threshold) :param str permission: (optional) The actual permission to modify (defaults to ``active``) :param str account: (optional) the account to allow access to (defaults to ``default_account``) :param int threshold: The threshold that needs to be reached by signatures to be able to interact """ from copy import deepcopy if not account: if "default_account" in config: account = config["default_account"] if not account: raise ValueError("You need to provide an account") if permission not in ["owner", "active"]: raise ValueError( "Permission needs to be either 'owner', or 'active") account = Account(account, bitshares_instance=self) if not weight: weight = account[permission]["weight_threshold"] authority = deepcopy(account[permission]) try: pubkey = PublicKey(foreign, prefix=self.rpc.chain_params["prefix"]) authority["key_auths"].append([str(pubkey), weight]) except: try: foreign_account = Account(foreign, bitshares_instance=self) authority["account_auths"].append( [foreign_account["id"], weight]) except: raise ValueError( "Unknown foreign account or invalid public key") if threshold: authority["weight_threshold"] = threshold self._test_weights_treshold(authority) op = operations.Account_update( **{ "fee": { "amount": 0, "asset_id": "1.3.0" }, "account": account["id"], permission: authority, "extensions": {}, "prefix": self.rpc.chain_params["prefix"] }) if permission == "owner": return self.finalizeOp(op, account["name"], "owner") else: return self.finalizeOp(op, account["name"], "active")