Example #1
0
    def process_transaction(self,
                            contract_tx,
                            fee=None,
                            address_from=None,
                            change_addr=None):
        standard_contract = self.wallet.GetStandardAddress()
        signer_contract = self.wallet.GetContract(standard_contract)

        tx = self.wallet.MakeTransaction(tx=contract_tx,
                                         change_address=change_addr,
                                         fee=fee,
                                         from_addr=address_from)
        if tx is None:
            raise JsonRpcError(-300, "Insufficient funds")
        data = standard_contract.Data
        tx.Attributes = [
            TransactionAttribute(usage=TransactionAttributeUsage.Script,
                                 data=data)
        ]
        context = ContractParametersContext(
            tx, isMultiSig=signer_contract.IsMultiSigContract)
        self.wallet.Sign(context)
        if context.Completed:
            tx.scripts = context.GetScripts()
            NodeLeader.Instance().Relay(tx)
            return tx.ToJson()
        else:
            return context.ToJson()
    def send_neo(wallet, address_from, address_to, amount):
        assetId = None

        assetId = Blockchain.Default().SystemShare().Hash

        scripthash_to = wallet.ToScriptHash(address_to)
        scripthash_from = wallet.ToScriptHash(address_from)

        f8amount = Fixed8.TryParse(amount)

        if f8amount.value % pow(10, 8 - Blockchain.Default().GetAssetState(assetId.ToBytes()).Precision) != 0:
            raise Exception("incorrect amount precision")

        fee = Fixed8.Zero()

        output = TransactionOutput(AssetId=assetId, Value=f8amount, script_hash=scripthash_to)
        tx = ContractTransaction(outputs=[output])
        ttx = wallet.MakeTransaction(tx=tx, change_address=None, fee=fee, from_addr=scripthash_from)

        if ttx is None:
            raise Exception("insufficient funds, were funds already moved from multi-sig contract?")

        context = ContractParametersContext(tx, isMultiSig=True)
        wallet.Sign(context)

        if context.Completed:
            raise Exception("Something went wrong, multi-sig transaction failed")

        else:
            print("Transaction initiated")
            return json.dumps(context.ToJson(), separators=(',', ':'))
Example #3
0
    def send_to_address(self, params):
        asset, address, amount, fee = self.parse_send_params(params)
        standard_contract = self.wallet.GetStandardAddress()
        signer_contract = self.wallet.GetContract(standard_contract)

        output = TransactionOutput(AssetId=asset,
                                   Value=amount,
                                   script_hash=address)
        contract_tx = ContractTransaction(outputs=[output])
        tx = self.wallet.MakeTransaction(tx=contract_tx,
                                         change_address=None,
                                         fee=fee)
        if tx is None:
            raise JsonRpcError(-300, "Insufficient funds")

        data = standard_contract.Data
        tx.Attributes = [
            TransactionAttribute(usage=TransactionAttributeUsage.Script,
                                 data=data)
        ]

        context = ContractParametersContext(
            tx, isMultiSig=signer_contract.IsMultiSigContract)
        self.wallet.Sign(context)

        if context.Completed:
            tx.scripts = context.GetScripts()
            NodeLeader.Instance().Relay(tx)
            return tx.ToJson()
        else:
            return context.ToJson()
Example #4
0
    def _make_tx(self, addr_to):
        """
        process transaction
        """
        output1 = TransactionOutput(
            AssetId = Blockchain.SystemCoin().Hash, # hash of the Gas transaction
            Value = Fixed8.FromDecimal(2000), # this is how much gas each request will provide
            script_hash = addr_to # address to send the Gas to
        )
        output2 = TransactionOutput(
            AssetId = Blockchain.SystemShare().Hash, # hash of the NEO token transaction
            Value = Fixed8.FromDecimal(100), # this is how much NEO each request will provide
            script_hash = addr_to # address to send the NEO tokens too
        )

        contract_tx = ContractTransaction() # creates an instance of the transaction
        contract_tx.outputs = [output1, output2] # outputs the data from the transaction
        contract_tx = self.wallet.MakeTransaction(contract_tx) # processes transaction 

        print("tx to json: %s " % json.dumps(contract_tx.ToJson(), indent=4))

        context = ContractParametersContext(contract_tx, isMultiSig=False) # getting the contract context (listed above)
        self.wallet.Sign(context) # signs the contract

        if context.Completed:

            contract_tx.scripts = context.GetScripts() # gets the script hashes from the context 

            self.wallet.SaveTransaction(contract_tx) # update the state of the coins in the wallet

            #            print("will send tx: %s " % json.dumps(tx.ToJson(),indent=4))

            relayed = NodeLeader.Instance().Relay(contract_tx)  # relay the transaction to this instance of the node leader 

            if relayed: # if tx relay was successful, inform the user and return the contract transaction
                print("Relayed Tx: %s " % contract_tx.Hash.ToString())
                return contract_tx
            else:

                print("Could not relay tx %s " % contract_tx.Hash.ToString())

        else:
            print("Transaction initiated, but the signature is incomplete")
            print(json.dumps(context.ToJson(), separators=(',', ':')))
            return False

        return False
Example #5
0
    def _make_tx(self, addr_to):

        output1 = TransactionOutput(
            AssetId = Blockchain.SystemCoin().Hash,
            Value = Fixed8.FromDecimal(2000),
            script_hash = addr_to
        )
        output2 = TransactionOutput(
            AssetId = Blockchain.SystemShare().Hash,
            Value = Fixed8.FromDecimal(100),
            script_hash = addr_to
        )

        contract_tx = ContractTransaction()
        contract_tx.outputs = [output1, output2]
        contract_tx = self.wallet.MakeTransaction(contract_tx)

        print("tx to json: %s " % json.dumps(contract_tx.ToJson(), indent=4))

        context = ContractParametersContext(contract_tx, isMultiSig=False)
        self.wallet.Sign(context)

        if context.Completed:

            contract_tx.scripts = context.GetScripts()

            self.wallet.SaveTransaction(contract_tx)

            #            print("will send tx: %s " % json.dumps(tx.ToJson(),indent=4))

            relayed = NodeLeader.Instance().Relay(contract_tx)

            if relayed:
                print("Relayed Tx: %s " % contract_tx.Hash.ToString())
                return contract_tx
            else:

                print("Could not relay tx %s " % contract_tx.Hash.ToString())

        else:
            print("Transaction initiated, but the signature is incomplete")
            print(json.dumps(context.ToJson(), separators=(',', ':')))
            return False

        return False
Example #6
0
    def process_transaction(self, contract_tx, fee=None, address_from=None, change_addr=None):
        standard_contract = self.wallet.GetStandardAddress()
        signer_contract = self.wallet.GetContract(standard_contract)

        try:
            tx = self.wallet.MakeTransaction(tx=contract_tx,
                                             change_address=change_addr,
                                             fee=fee,
                                             from_addr=address_from)
        except ValueError:
            # if not enough unspents while fully synced
            raise JsonRpcError(-300, "Insufficient funds")

        if tx is None:
            # if not enough unspents while not being fully synced
            raise JsonRpcError(-300, "Insufficient funds")
        data = standard_contract.Data
        tx.Attributes = [
            TransactionAttribute(usage=TransactionAttributeUsage.Script,
                                 data=data)
        ]
        context = ContractParametersContext(
            tx, isMultiSig=signer_contract.IsMultiSigContract
        )
        self.wallet.Sign(context)
        if context.Completed:
            tx.scripts = context.GetScripts()
            passed, reason = validate_simple_policy(tx)
            if not passed:
                raise JsonRpcError(-32602, reason)

            relayed = self.nodemgr.relay(tx)
            if relayed:
                self.wallet.SaveTransaction(tx)
                return tx.ToJson()
            else:
                raise JsonRpcError(-32602, "Invalid params")
        else:
            return context.ToJson()
Example #7
0
def process_transaction(wallet,
                        contract_tx,
                        scripthash_from=None,
                        scripthash_change=None,
                        fee=None,
                        owners=None,
                        user_tx_attributes=None):
    try:
        tx = wallet.MakeTransaction(tx=contract_tx,
                                    change_address=scripthash_change,
                                    fee=fee,
                                    from_addr=scripthash_from)

        if tx is None:
            logger.debug("insufficient funds")
            return False

        # password prompt
        passwd = prompt("[Password]> ", is_password=True)
        if not wallet.ValidatePassword(passwd):
            print("incorrect password")
            return False

        standard_contract = wallet.GetStandardAddress()

        if scripthash_from is not None:
            signer_contract = wallet.GetContract(scripthash_from)
        else:
            signer_contract = wallet.GetContract(standard_contract)

        if not signer_contract.IsMultiSigContract and owners is None:

            data = standard_contract.Data
            tx.Attributes = [
                TransactionAttribute(usage=TransactionAttributeUsage.Script,
                                     data=data)
            ]

        # insert any additional user specified tx attributes
        tx.Attributes = tx.Attributes + user_tx_attributes

        if owners:
            owners = list(owners)
            for owner in owners:
                tx.Attributes.append(
                    TransactionAttribute(
                        usage=TransactionAttributeUsage.Script, data=owner))

        context = ContractParametersContext(
            tx, isMultiSig=signer_contract.IsMultiSigContract)
        wallet.Sign(context)

        if owners:
            owners = list(owners)
            gather_signatures(context, tx, owners)

        print(context.ScriptHashes)
        for s in context.GetScripts():
            print(s.ToJson())
        print(tx.ToJson())

        if context.Completed:

            tx.scripts = context.GetScripts()

            #            print("will send tx: %s " % json.dumps(tx.ToJson(),indent=4))

            relayed = NodeLeader.Instance().Relay(tx)

            if relayed:
                wallet.SaveTransaction(tx)

                print("Relayed Tx: %s " % tx.Hash.ToString())
                return tx
            else:

                print("Could not relay tx %s " % tx.Hash.ToString())

        else:
            print("Transaction initiated, but the signature is incomplete")
            print(json.dumps(context.ToJson(), separators=(',', ':')))
            return False

    except Exception as e:
        print("could not send: %s " % e)
        traceback.print_stack()
        traceback.print_exc()

    return False
def construct_invoke_tx(wallet, params):
    params = params[0]
    from_addr = params['from_addr']
    
    BC = GetBlockchain()

    contract = BC.GetContract(params['addr'])

    if not contract:
        raise Exception('no such contract')

    neo_to_attach = params.get('neo_to_attach', 0)
    gas_to_attach = params.get('gas_to_attach', 0)

    sb = ScriptBuilder()
    contract_parameters = [ContractParameter.FromJson(p) for p in params['contract_params']]
    sb.EmitAppCallWithJsonArgs(contract.Code.ScriptHash(), contract_parameters)
    
    invoke_script = sb.ToArray()

    outputs = []

    if neo_to_attach:

        output = TransactionOutput(AssetId=Blockchain.SystemShare().Hash,
                Value=neo_to_attach,
                script_hash=contract.Code.ScriptHash(),
        )
        outputs.append(output)

    if gas_to_attach:

        output = TransactionOutput(AssetId=Blockchain.SystemCoin().Hash,
                Value=gas_to_attach,
                script_hash=contract.Code.ScriptHash(),
        )

        outputs.append(output)

    bc = GetBlockchain()
    sn = bc._db.snapshot()
    accounts = DBCollection(bc._db, DBPrefix.ST_Account, AccountState)
    assets = DBCollection(bc._db, DBPrefix.ST_Asset, AssetState)
    validators = DBCollection(bc._db, DBPrefix.ST_Validator, ValidatorState)
    contracts = DBCollection(bc._db, DBPrefix.ST_Contract, ContractState)
    storages = DBCollection(bc._db, DBPrefix.ST_Storage, StorageItem)


    tx = InvocationTransaction()
    tx.outputs = outputs
    tx.inputs = []
    tx.Version = 1
    tx.scripts = []
    tx.Script = binascii.unhexlify(invoke_script)

    script_table = CachedScriptTable(contracts)
    service = StateMachine(accounts, validators, assets, contracts, storages, None)
    contract = wallet.GetDefaultContract()
    tx.Attributes = [TransactionAttribute(usage=TransactionAttributeUsage.Script, data=Crypto.ToScriptHash(contract.Script, unhex=False).Data)]
    tx = wallet.MakeTransaction(tx=tx)

    engine = ApplicationEngine(
            trigger_type=TriggerType.Application,
            container=tx,
            table=script_table,
            service=service,
            gas=tx.Gas,
            testMode=True
    )   
    engine.LoadScript(tx.Script, False)
    success = engine.Execute()
    if not success:
        raise Exception('exec failed')
    
    service.ExecutionCompleted(engine, success)

    consumed = engine.GasConsumed() - Fixed8.FromDecimal(10)
    consumed = consumed.Ceil()

    net_fee = None
    tx_gas = None

    if consumed <= Fixed8.Zero():
        net_fee = Fixed8.FromDecimal(.0001)
        tx_gas = Fixed8.Zero()
    else:
        tx_gas = consumed
        net_fee = Fixed8.Zero()
    tx.Gas = tx_gas
    tx.outputs = outputs
    tx.Attributes = []



    # InvokeContract
    from_addr = lookup_addr_str(wallet, from_addr)
    tx = wallet.MakeTransaction(tx=tx, fee=net_fee, use_standard=True, from_addr=from_addr)
    if tx is None:
        raise Exception("no gas")


    context = ContractParametersContext(tx)
    ms = StreamManager.GetStream()
    writer = BinaryWriter(ms)
    tx.Serialize(writer)
    ms.flush()
    binary_tx = ms.ToArray()
    return {'context': context.ToJson(), 'tx': binary_tx.decode()}
def construct_deploy_tx(wallet, params):
    params = params[0]
    from_addr = params['from_addr']
    # load_smart_contract
    contract_params = bytearray(binascii.unhexlify(params['contract_params']))
    return_type = bytearray(binascii.unhexlify(params['return_type']))
    
    contract_properties = 0
    if params.get('needs_storage', True):
        contract_properties += ContractPropertyState.HasStorage
    if params.get('needs_dynamic_invoke', False):
        contract_properties += ContractPropertyState.HasDynamicInvoke

    script = binascii.unhexlify(params['bin'])

    function_code = FunctionCode(
            script = script,
            param_list = contract_params,
            return_type = return_type,
            contract_properties = contract_properties,
    )

    if Blockchain.Default().GetContract(function_code.ScriptHash().To0xString()):
        raise Exception('contract already exists')

    # GatherContractDetails
    details = params['details']
    name = details['name']
    version = details['version']
    author = details['author']
    email = details['email']
    description = details['description']

    contract_script = generate_deploy_script(
            function_code.Script,
            name,
            version,
            author,
            email,
            description,
            function_code.ContractProperties,
            function_code.ReturnType,
            function_code.ParameterList,
    )

    # test_invoke    
    bc = GetBlockchain()
    sn = bc._db.snapshot()
    accounts = DBCollection(bc._db, DBPrefix.ST_Account, AccountState)
    assets = DBCollection(bc._db, DBPrefix.ST_Asset, AssetState)
    validators = DBCollection(bc._db, DBPrefix.ST_Validator, ValidatorState)
    contracts = DBCollection(bc._db, DBPrefix.ST_Contract, ContractState)
    storages = DBCollection(bc._db, DBPrefix.ST_Storage, StorageItem)


    tx = InvocationTransaction()
    tx.outputs = []
    tx.inputs = []
    tx.Version = 1
    tx.scripts = []
    tx.Script = binascii.unhexlify(contract_script)

    script_table = CachedScriptTable(contracts)
    service = StateMachine(accounts, validators, assets, contracts, storages, None)
    contract = wallet.GetDefaultContract()
    tx.Attributes = [TransactionAttribute(usage=TransactionAttributeUsage.Script, data=Crypto.ToScriptHash(contract.Script, unhex=False).Data)]
    tx = wallet.MakeTransaction(tx=tx)

    engine = ApplicationEngine(
            trigger_type=TriggerType.Application,
            container=tx,
            table=script_table,
            service=service,
            gas=tx.Gas,
            testMode=True
    )   
    engine.LoadScript(tx.Script, False)
    success = engine.Execute()
    if not success:
        raise Exception('exec failed')
    
    service.ExecutionCompleted(engine, success)

    consumed = engine.GasConsumed() - Fixed8.FromDecimal(10)
    consumed = consumed.Ceil()

    net_fee = None
    tx_gas = None

    if consumed <= Fixed8.Zero():
        net_fee = Fixed8.FromDecimal(.0001)
        tx_gas = Fixed8.Zero()
    else:
        tx_gas = consumed
        net_fee = Fixed8.Zero()
    tx.Gas = tx_gas
    tx.outputs = []
    tx.Attributes = []

    # InvokeContract
    from_addr = lookup_addr_str(wallet, from_addr)
    tx = wallet.MakeTransaction(tx=tx, fee=net_fee, use_standard=True, from_addr=from_addr)
    if tx is None:
        raise Exception("no gas")


    context = ContractParametersContext(tx)
    ms = StreamManager.GetStream()
    writer = BinaryWriter(ms)
    tx.Serialize(writer)
    ms.flush()
    binary_tx = ms.ToArray()
    return {'context': context.ToJson(), 'tx': binary_tx.decode(), 'hash': function_code.ScriptHash().To0xString()}
def construct_send_tx(wallet, arguments):
        from_address = arguments['from']
        to_send = arguments['asset']
        address_to = arguments['to']
        amount = arguments['amount']

        user_tx_attributes = arguments.get('attrs', [])

        assetId = get_asset_id(wallet, to_send)

        if assetId is None:
            raise Exception("Asset id not found")

        scripthash_to = lookup_addr_str(wallet, address_to)
        if scripthash_to is None:
            raise Exception("invalid address")

        scripthash_from = None

        if from_address is not None:
            scripthash_from = lookup_addr_str(wallet, from_address)

        if type(assetId) is NEP5Token:
            raise Exception("cannot transfer token in this version")

        f8amount = Fixed8.TryParse(amount, require_positive=True)
        if f8amount is None:
            raise Exception("invalid amount format")

        if type(assetId) is UInt256 and f8amount.value % pow(10, 8 - Blockchain.Default().GetAssetState(assetId.ToBytes()).Precision) != 0:
            raise Exception("incorrect amount precision")

        fee = Fixed8.Zero()

        output = TransactionOutput(AssetId=assetId, Value=f8amount, script_hash=scripthash_to)
        tx = ContractTransaction(outputs=[output])
        ttx = wallet.MakeTransaction(tx=tx,
                                     fee=fee,
                                     from_addr=scripthash_from)


        if ttx is None:
            raise Exception("no funds")

        standard_contract = wallet.GetStandardAddress()

        if scripthash_from is not None:
            signer_contract = wallet.GetContract(scripthash_from)
        else:
            signer_contract = wallet.GetContract(standard_contract)

        if not signer_contract.IsMultiSigContract:

            data = standard_contract.Data
            tx.Attributes = [TransactionAttribute(usage=TransactionAttributeUsage.Script,
                                                  data=data)]

        # insert any additional user specified tx attributes
        tx.Attributes = tx.Attributes + user_tx_attributes


        context = ContractParametersContext(tx, isMultiSig=signer_contract.IsMultiSigContract)
       

        logger.info(context.ToJson())
        logger.info('*'*60)
        logger.info(tx.ToJson())
#        import pdb
#        pdb.set_trace()
        ms = StreamManager.GetStream()
        writer = BinaryWriter(ms)
        tx.Serialize(writer)
        ms.flush()
        binary_tx = ms.ToArray()
        print(tx)
        return {'context': context.ToJson(), 'tx': binary_tx.decode()}
Example #11
0
def process_transaction(wallet,
                        contract_tx,
                        scripthash_from=None,
                        scripthash_change=None,
                        fee=None,
                        owners=None,
                        user_tx_attributes=None):
    try:
        tx = wallet.MakeTransaction(tx=contract_tx,
                                    change_address=scripthash_change,
                                    fee=fee,
                                    from_addr=scripthash_from)
    except ValueError:
        print(
            "Insufficient funds. No unspent outputs available for building the transaction.\n"
            "If you are trying to sent multiple transactions in 1 block, then make sure you have enough 'vouts'\n."
            "Use `wallet unspent` and `wallet address split`, or wait until the first transaction is processed before sending another."
        )
        return
    except TXFeeError as e:
        print(e)
        return

    if tx is None:
        logger.debug("insufficient funds")
        return

    try:
        print("Validate your transaction details")
        print("-" * 33)
        input_coinref = wallet.FindCoinsByVins(tx.inputs)[0]
        source_addr = input_coinref.Address
        for order in tx.outputs:
            dest_addr = order.Address
            value = order.Value.ToString()  # fixed8
            if order.AssetId == Blockchain.Default().SystemShare().Hash:
                asset_name = 'NEO'
            else:
                asset_name = 'GAS'

            if source_addr != dest_addr:
                print(
                    f"Sending {value} {asset_name} from {source_addr} to {dest_addr}"
                )
            else:
                print(
                    f"Returning {value} {asset_name} as change to {dest_addr}")
        print(" ")
        print("Enter your password to send to the network")

        try:
            passwd = prompt("[Password]> ", is_password=True)
        except KeyboardInterrupt:
            print("Transaction cancelled")
            return
        if not wallet.ValidatePassword(passwd):
            print("Incorrect password")
            return

        standard_contract = wallet.GetStandardAddress()

        if scripthash_from is not None:
            signer_contract = wallet.GetContract(scripthash_from)
        else:
            signer_contract = wallet.GetContract(standard_contract)

        if not signer_contract.IsMultiSigContract and owners is None:
            data = standard_contract.Data
            tx.Attributes = [
                TransactionAttribute(usage=TransactionAttributeUsage.Script,
                                     data=data)
            ]

        # insert any additional user specified tx attributes
        tx.Attributes = tx.Attributes + user_tx_attributes

        if owners:
            owners = list(owners)
            for owner in owners:
                tx.Attributes.append(
                    TransactionAttribute(
                        usage=TransactionAttributeUsage.Script, data=owner))

        context = ContractParametersContext(
            tx, isMultiSig=signer_contract.IsMultiSigContract)
        wallet.Sign(context)

        if owners:
            owners = list(owners)
            gather_signatures(context, tx, owners)

        if context.Completed:

            tx.scripts = context.GetScripts()
            relayed = NodeLeader.Instance().Relay(tx)

            if relayed:
                wallet.SaveTransaction(tx)

                print("Relayed Tx: %s " % tx.Hash.ToString())
                return tx
            else:

                print("Could not relay tx %s " % tx.Hash.ToString())

        else:
            print(
                "Transaction initiated, but the signature is incomplete. Use the `sign` command with the information below to complete signing."
            )
            print(json.dumps(context.ToJson(), separators=(',', ':')))
            return

    except Exception as e:
        print("Could not send: %s " % e)
        traceback.print_stack()
        traceback.print_exc()

    return
Example #12
0
def construct_and_send(prompter, wallet, arguments, prompt_password=True):
    try:
        if not wallet:
            print("please open a wallet")
            return False
        if len(arguments) < 3:
            print("Not enough arguments")
            return False

        arguments, from_address = get_from_addr(arguments)
        arguments, user_tx_attributes = get_tx_attr_from_args(arguments)
        arguments, owners = get_owners_from_params(arguments)
        arguments, priority_fee = get_fee(arguments)
        to_send = get_arg(arguments)
        address_to = get_arg(arguments, 1)
        amount = get_arg(arguments, 2)

        assetId = get_asset_id(wallet, to_send)

        if assetId is None:
            print("Asset id not found")
            return False

        scripthash_to = lookup_addr_str(wallet, address_to)
        if scripthash_to is None:
            print("invalid address")
            return False

        scripthash_from = None

        if from_address is not None:
            scripthash_from = lookup_addr_str(wallet, from_address)

        # if this is a token, we will use a different
        # transfer mechanism
        if type(assetId) is NEP5Token:
            return do_token_transfer(assetId, wallet, from_address, address_to, amount_from_string(assetId, amount), prompt_passwd=prompt_password, tx_attributes=user_tx_attributes)

        f8amount = Fixed8.TryParse(amount, require_positive=True)
        if f8amount is None:
            print("invalid amount format")
            return False

        if type(assetId) is UInt256 and f8amount.value % pow(10, 8 - Blockchain.Default().GetAssetState(assetId.ToBytes()).Precision) != 0:
            print("incorrect amount precision")
            return False

        fee = Fixed8.Zero()
        if priority_fee is not None:
            fee = priority_fee

        print("sending with fee: %s " % fee.ToString())

        output = TransactionOutput(AssetId=assetId, Value=f8amount, script_hash=scripthash_to)
        tx = ContractTransaction(outputs=[output])

        ttx = wallet.MakeTransaction(tx=tx,
                                     change_address=None,
                                     fee=fee,
                                     from_addr=scripthash_from)

        if ttx is None:
            print("insufficient funds")
            return False

        if prompt_password:
            passwd = prompt("[Password]> ", is_password=True)

            if not wallet.ValidatePassword(passwd):
                print("incorrect password")
                return False

        standard_contract = wallet.GetStandardAddress()

        if scripthash_from is not None:
            signer_contract = wallet.GetContract(scripthash_from)
        else:
            signer_contract = wallet.GetContract(standard_contract)

        if not signer_contract.IsMultiSigContract and owners is None:

            data = standard_contract.Data
            tx.Attributes = [TransactionAttribute(usage=TransactionAttributeUsage.Script,
                                                  data=data)]

        # insert any additional user specified tx attributes
        tx.Attributes = tx.Attributes + user_tx_attributes

        if owners:
            owners = list(owners)
            for owner in owners:
                tx.Attributes.append(
                    TransactionAttribute(usage=TransactionAttributeUsage.Script, data=owner))

        context = ContractParametersContext(tx, isMultiSig=signer_contract.IsMultiSigContract)
        wallet.Sign(context)

        if owners:
            owners = list(owners)
            gather_signatures(context, tx, owners)

        if context.Completed:

            tx.scripts = context.GetScripts()

#            print("will send tx: %s " % json.dumps(tx.ToJson(),indent=4))

            relayed = NodeLeader.Instance().Relay(tx)

            if relayed:
                wallet.SaveTransaction(tx)

                print("Relayed Tx: %s " % tx.Hash.ToString())
                return tx
            else:

                print("Could not relay tx %s " % tx.Hash.ToString())

        else:
            print("Transaction initiated, but the signature is incomplete")
            print(json.dumps(context.ToJson(), separators=(',', ':')))
            return False

    except Exception as e:
        print("could not send: %s " % e)
        traceback.print_stack()
        traceback.print_exc()

    return False
Example #13
0
    def json_rpc_method_handler(self, method, params):

        if method == "getaccountstate":
            acct = Blockchain.Default().GetAccountState(params[0])
            if acct is None:
                try:
                    acct = AccountState(script_hash=Helper.AddrStrToScriptHash(params[0]))
                except Exception as e:
                    raise JsonRpcError(-2146233033, "One of the identified items was in an invalid format.")

            return acct.ToJson()

        elif method == "getassetstate":
            asset_id = UInt256.ParseString(params[0])
            asset = Blockchain.Default().GetAssetState(asset_id.ToBytes())
            if asset:
                return asset.ToJson()
            raise JsonRpcError(-100, "Unknown asset")

        elif method == "getbestblockhash":
            return '0x%s' % Blockchain.Default().CurrentHeaderHash.decode('utf-8')

        elif method == "getblock":
            # this should work for either str or int
            block = Blockchain.Default().GetBlock(params[0])
            if not block:
                raise JsonRpcError(-100, "Unknown block")
            return self.get_block_output(block, params)

        elif method == "getblockcount":
            return Blockchain.Default().Height + 1

        elif method == "getblockhash":
            height = params[0]
            if height >= 0 and height <= Blockchain.Default().Height:
                return '0x%s' % Blockchain.Default().GetBlockHash(height).decode('utf-8')
            else:
                raise JsonRpcError(-100, "Invalid Height")

        elif method == "getblocksysfee":
            height = params[0]
            if height >= 0 and height <= Blockchain.Default().Height:
                return Blockchain.Default().GetSysFeeAmountByHeight(height)
            else:
                raise JsonRpcError(-100, "Invalid Height")

        elif method == "getconnectioncount":
            return len(NodeLeader.Instance().Peers)

        elif method == "getcontractstate":
            script_hash = UInt160.ParseString(params[0])
            contract = Blockchain.Default().GetContract(script_hash.ToBytes())
            if contract is None:
                raise JsonRpcError(-100, "Unknown contract")
            return contract.ToJson()

        elif method == "getrawmempool":
            return list(map(lambda hash: "0x%s" % hash.decode('utf-8'), NodeLeader.Instance().MemPool.keys()))

        elif method == "getversion":
            return {
                "port": self.port,
                "nonce": NodeLeader.Instance().NodeId,
                "useragent": settings.VERSION_NAME
            }

        elif method == "getrawtransaction":
            tx_id = UInt256.ParseString(params[0])
            tx, height = Blockchain.Default().GetTransaction(tx_id)
            if not tx:
                raise JsonRpcError(-100, "Unknown Transaction")
            return self.get_tx_output(tx, height, params)

        elif method == "getLastBlog":

            if len(params) > 0:
                height = params[0]
            else:
                height = Blockchain.Default().Height + 1
            data = self.get_blog_content(height, "")
            return data;
        elif method == "getLastBlogByTag":

            if len(params) > 1:
                height = params[1]
                tag = params[0]
            elif len(params) > 0:
                tag = params[0]
                height = Blockchain.Default().Height + 1
            else:
                raise JsonRpcError(-100, "no enough param")
            data = self.get_blog_content(height, tag)
            return data;
        elif method == "getLastBlogBySender":

            if len(params) > 1:
                height = params[1]
                sender = params[0]
            elif len(params) > 0:
                sender = params[0]
                height = Blockchain.Default().Height + 1
            else:
                raise JsonRpcError(-100, "no enough param")
            data = self.get_blog_content(height, "", sender)
            return data;
        elif method == "getBlogContent":
            tx_id = UInt256.ParseString(params[0])
            tx, height = Blockchain.Default().GetTransaction(tx_id)
            if not tx:
                raise JsonRpcError(-100, "Unknown Transaction")

            for attr in tx.Attributes:
                item = attr.ToJson;
                if item['usage'] == 240:
                    item['content'] = binascii.a2b_hex(item['data']).decode("utf8")
                    return item;
            raise JsonRpcError(-100, "no blog content")


        elif method == "getstorage":
            script_hash = UInt160.ParseString(params[0])
            key = binascii.unhexlify(params[1].encode('utf-8'))
            storage_key = StorageKey(script_hash=script_hash, key=key)
            storage_item = Blockchain.Default().GetStorageItem(storage_key)
            if storage_item:
                return storage_item.Value.hex()
            return None

        elif method == "gettxout":
            hash = params[0].encode('utf-8')
            index = params[1]
            utxo = Blockchain.Default().GetUnspent(hash, index)
            if utxo:
                return utxo.ToJson(index)
            else:
                return None

        elif method == "gettxout":
            hash = params[0].encode('utf-8')
            index = params[1]
            utxo = Blockchain.Default().GetUnspent(hash, index)
            if utxo:
                return utxo.ToJson(index)
            else:
                return None

        elif method == "createAddress":

            private_key = bytes(Random.get_random_bytes(32))
            key = KeyPair(priv_key=private_key)
            self.wallet._keys[key.PublicKeyHash.ToBytes()] = key
            self.wallet.OnCreateAccount(key)
            contract = WalletContract.CreateSignatureContract(key.PublicKey)
            self.wallet.AddContract(contract)
            if key :
                result = {'privateKey': key.Export(),'address':contract.Address}
                return result;
            else:
                return None
        elif method == "invoke":
            shash = UInt160.ParseString(params[0])
            contract_parameters = [ContractParameter.FromJson(p) for p in params[1]]
            sb = ScriptBuilder()
            sb.EmitAppCallWithJsonArgs(shash, contract_parameters)
            return self.get_invoke_result(sb.ToArray())
        # elif method == "sendBlog":
        #     shash = UInt160.ParseString(params[0])
        #     contract_parameters = [ContractParameter.FromJson(p) for p in params[1]]
        #     sb = ScriptBuilder()
        #     sb.EmitAppCallWithJsonArgs(shash, contract_parameters)
        #     script = sb.ToArray();
        #     tx = ContractTransaction()
        #     tx.inputs = []
        #     tx.outputs = []
        #     attribute = TransactionAttribute(240, params[2].encode('utf-8'))
        #     standard_contract = self.wallet.GetStandardAddress()
        #     data = standard_contract.Data
        #     tx.Attributes = [TransactionAttribute(usage=TransactionAttributeUsage.Script,
        #                                           data=data)]
        #
        #     tx.Attributes.append(attribute)
        #     tx.Version = 1
        #     tx.scripts = []
        #     BC = GetBlockchain()
        #     contract = BC.GetContract(params[0])
        #     output = TransactionOutput(AssetId=Blockchain.SystemShare().Hash,
        #                                Value=Fixed8.FromDecimal(float(1)),
        #                                script_hash=contract.Code.ScriptHash(),
        #                                )
        #     tx.outputs.append(output)
        #     logger.info("output %s" % output.ToJson(0))
        #     tx.Script = binascii.unhexlify(script)
        #     print("percentage %s %s" % (self.wallet.WalletHeight, Blockchain.Default().Height))
        #     scripthash_from = None
        #     if not self.wallet.IsSynced:
        #         raise JsonRpcError.invalidRequest("wallet not synced")
        #     private_key = None
        #     if len(params) > 3:
        #         from_address = params[3]
        #         if from_address is not None:
        #             scripthash_from = lookup_addr_str(self.wallet, from_address)
        #     if len(params) > 4:
        #         private_key = params[4]
        #     wallet_tx = SendBlog(self.wallet, tx, from_addr=scripthash_from, privatekey=private_key)
        #     if wallet_tx != False:
        #         return wallet_tx.ToJson();
        #     self.wallet.Rebuild()
        #     raise JsonRpcError.invalidRequest("Field 'no enough asset")
        elif method == 'postblog':
            try:

                if len(params) > 3:
                    from_address = params[3]
                assetId =Blockchain.SystemShare().Hash

                if len(params) > 4:
                    private_key = params[4]

                if assetId is None:
                    print("Asset id not found")
                    return False

                contract_parameters = [ContractParameter.FromJson(p) for p in params[1]]
                sb = ScriptBuilder()
                sb.EmitAppCallWithJsonArgs(UInt160.ParseString(params[0]), contract_parameters)
                script = sb.ToArray();

                scripthash_from = None

                if from_address is not None:
                    scripthash_from = lookup_addr_str(self.wallet, from_address)

                # f8amount = Fixed8.TryParse(0, require_positive=True)
                # if f8amount is None:
                #     print("invalid amount format")
                #     return False
                #
                # if type(assetId) is UInt256 and f8amount.value % pow(10, 8 - Blockchain.Default().GetAssetState(
                #         assetId.ToBytes()).Precision) != 0:
                #     print("incorrect amount precision")
                #     return False
                #
                fee = Fixed8.Zero()
                #
                # output = TransactionOutput(AssetId=assetId, Value=f8amount, script_hash=contract.Code.ScriptHash())
                tx = InvocationTransaction()

                ttx = self.wallet.MakeTransaction(tx=tx,
                                             change_address=None,
                                             fee=fee,
                                             from_addr=scripthash_from)

                if ttx is None:
                    print("insufficient funds")
                    return False
                standard_contract = self.wallet.GetStandardAddress()
                if scripthash_from is not None:
                    signer_contract = self.wallet.GetContract(scripthash_from)
                else:
                    signer_contract = self.wallet.GetContract(standard_contract)

                if not signer_contract.IsMultiSigContract:
                    data = scripthash_from.Data
                    print(data)
                    tx.Attributes = [TransactionAttribute(usage=TransactionAttributeUsage.Script,
                                                          data=data),TransactionAttribute(usage=TransactionAttributeUsage.Remark1,
                                                          data=from_address.encode('utf-8'))]

                # insert any additional user specified tx attributes
                tx.Attributes.append(TransactionAttribute(240, params[2].encode('utf-8')))
                tx.Script = binascii.unhexlify(script)

                context = ContractParametersContext(tx, isMultiSig=signer_contract.IsMultiSigContract)
                if private_key is not None:
                    prikey = KeyPair.PrivateKeyFromWIF(private_key)
                    kp = KeyPair(prikey)
                self.wallet.Sign(context,kp)
                attributes = [attr.ToJson() for attr in tx.Attributes]
                print("attributes %s" %attributes)
                if context.Completed:

                    tx.scripts = context.GetScripts()

                    #            print("will send tx: %s " % json.dumps(tx.ToJson(),indent=4))

                    relayed = NodeLeader.Instance().Relay(tx)

                    if relayed:
                        self.wallet.SaveTransaction(tx)

                        print("Relayed Tx: %s " % tx.Hash.ToString())
                        return tx.ToJson()
                    else:

                        print("Could not relay tx %s " % tx.Hash.ToString())

                else:
                    print("Transaction initiated, but the signature is incomplete")
                    print(json.dumps(context.ToJson(), separators=(',', ':')))
                    return False

            except Exception as e:
                print("could not send: %s " % e)

            return False
        elif method == "invokefunction":
            contract_parameters = []
            if len(params) > 2:
                contract_parameters = [ContractParameter.FromJson(p).ToVM() for p in params[2]]
            sb = ScriptBuilder()
            sb.EmitAppCallWithOperationAndArgs(UInt160.ParseString(params[0]), params[1], contract_parameters)
            return self.get_invoke_result(sb.ToArray())

        elif method == "invokescript":
            script = params[0].encode('utf-8')
            return self.get_invoke_result(script)

        elif method == "sendrawtransaction":
            tx_script = binascii.unhexlify(params[0].encode('utf-8'))
            transaction = Transaction.DeserializeFromBufer(tx_script)
            result = NodeLeader.Instance().Relay(transaction)
            return result

        elif method == "submitblock":
            raise NotImplementedError()

        elif method == "validateaddress":
            return self.validateaddress(params)

        elif method == "getpeers":
            raise NotImplementedError()

        raise JsonRpcError.methodNotFound()