예제 #1
0
    def SystemFee(self):

        if self.Version >= 1:
            return Fixed8.Zero()

        # if all outputs are NEO or gas, return 0
        all_neo_gas = True
        for output in self.outputs:
            if output.AssetId != GetSystemCoin().Hash and output.AssetId != GetSystemShare().Hash:
                all_neo_gas = False
        if all_neo_gas:
            return Fixed8.Zero()

        return Fixed8(int(settings.ISSUE_TX_FEE))
예제 #2
0
    def Run(script, container=None):

        from neo.Core.Blockchain import Blockchain
        from neo.SmartContract.StateMachine import StateMachine

        bc = Blockchain.Default()

        sn = bc._db.snapshot()

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

        script_table = CachedScriptTable(contracts)
        service = StateMachine(accounts, validators, assets, contracts, storages, None)

        engine = ApplicationEngine(
            trigger_type=TriggerType.Application,
            container=container,
            table=script_table,
            service=service,
            gas=Fixed8.Zero(),
            testMode=True
        )

        engine.LoadScript(script, False)
        engine.Execute()
        return engine
예제 #3
0
    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=(',', ':'))
예제 #4
0
    def Account_SetVotes(self, engine):

        try:
            account = engine.EvaluationStack.Pop().GetInterface()

            vote_list = engine.EvaluationStack.Pop().GetArray()
        except Exception as e:
            logger.error("could not get account or votes: %s " % e)
            return False

        if account is None or len(vote_list) > 1024:
            return False

        if account.IsFrozen:
            return False

        balance = account.BalanceFor(Blockchain.SystemShare().Hash)

        if balance == Fixed8.Zero() and len(vote_list) > 0:
            return False

        acct = self._accounts.GetAndChange(account.AddressBytes)
        voteset = []
        for v in vote_list:
            if v not in voteset:
                voteset.append(v.GetByteArray())
        acct.Votes = voteset

        # print("*****************************************************")
        # print("SET ACCOUNT VOTES %s " % json.dumps(acct.ToJson(), indent=4))
        # print("*****************************************************")
        return True
예제 #5
0
def InvokeWithTokenVerificationScript(wallet, tx, token, fee=Fixed8.Zero()):

    wallet_tx = wallet.MakeTransaction(tx=tx, fee=fee, use_standard=True)

    if wallet_tx:

        token_contract_state = Blockchain.Default().GetContract(
            token.ScriptHash.ToString())
        print("token contract  %s " % token_contract_state)

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

        reedeem_script = token_contract_state.Code.Script.hex()

        # there has to be at least 1 param, and the first
        # one needs to be a signature param
        param_list = bytearray(b'\x00\x00')

        verification_contract = Contract.Create(
            reedeem_script, param_list,
            wallet.GetDefaultContract().PublicKeyHash)

        context = ContractParametersContext(wallet_tx)

        wallet.Sign(context)

        context.Add(verification_contract, 0, 0)

        if context.Completed:

            wallet_tx.scripts = context.GetScripts()

            relayed = False

            #            print("full wallet tx: %s " % json.dumps(wallet_tx.ToJson(), indent=4))

            # check if we can save the tx first
            save_tx = wallet.SaveTransaction(wallet_tx)

            if save_tx:
                relayed = NodeLeader.Instance().Relay(wallet_tx)
            else:
                print("Could not save tx to wallet, will not send tx")

            if relayed:
                print("Relayed Tx: %s " % wallet_tx.Hash.ToString())
                return wallet_tx
            else:
                print("Could not relay tx %s " % wallet_tx.Hash.ToString())
        else:

            print("Incomplete signature")

    else:
        print("Insufficient funds")

    return False
예제 #6
0
def InvokeContract(wallet, tx, fee=Fixed8.Zero()):

    wallet_tx = wallet.MakeTransaction(tx=tx, fee=fee)

    if wallet_tx:

        context = ContractParametersContext(wallet_tx)

        wallet.Sign(context)

        if context.Completed:

            wallet_tx.scripts = context.GetScripts()

            wallet.SaveTransaction(wallet_tx)

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

            if relayed:
                print("Relayed Tx: %s " % tx.Hash.ToString())
                return True
            else:
                print("Could not relay tx %s " % tx.Hash.ToString())
        else:

            print("Incomplete signature")

    else:
        print("Insufficient funds")

    return False
예제 #7
0
    def Account_SetVotes(self, engine):

        try:
            account = engine.EvaluationStack.Pop().GetInterface(
                'neo.Core.State.AccountState.AccountState')

            vote_list = engine.EvaluationStack.Pop().GetArray()
        except Exception as e:
            self.__log.debug("could not get account or votes: %s " % e)
            return False

        if account is None or len(vote_list) > 1024:
            return False

        if account.IsFrozen:
            return False

        balance = account.BalanceFor(Blockchain.SystemShare().Hash)

        if balance == Fixed8.Zero() and len(vote_list) > 0:
            print("no balance, return false!")
            return False

        print("Setting votes!!!")

        acct = self._accounts.GetAndChange(account.AddressBytes)
        voteset = set()
        for v in vote_list:
            voteset.add(v.GetByteArray())
        acct.Votes = list(voteset)
        print("*****************************************************")
        print("SET ACCOUNT VOTES %s " % json.dumps(acct.ToJson(), indent=4))
        print("*****************************************************")
        return True
예제 #8
0
    def Account_SetVotes(self, engine):

        try:
            account = engine.EvaluationStack.Pop().GetInterface(
                'neo.Core.State.AccountState.AccountState')

            vote_list = engine.EvaluationStack.Pop().GetArray()
        except Exception as e:
            self.__log.debug("could not get account or votes: %s " % e)
            return False

        if account is None or len(vote_list) > 1024:
            return False

        if account.IsFrozen:
            return False

        balance = account.BalanceFor(Blockchain.SystemShare().Hash)

        if balance == Fixed8.Zero() and len(vote_list) > 0:
            return False

#       disable setting votes for now until further testing to make sure we're not duplicating votes
#
#        acct = self._accounts.GetAndChange(account.AddressBytes)
#        voteset = set()
#        for v in vote_list:
#            voteset.add(v.GetByteArray())
#        acct.Votes = list(voteset)
#        self.__log.debug("SET ACCOUNT VOTES %s " % json.dumps(acct.ToJson(), indent=4))
        return True
예제 #9
0
파일: faucet.py 프로젝트: pefish/neo-faucet
    def _get_context(self):

        neo_balance = Fixed8.Zero()
        for coin in self.wallet.FindUnspentCoinsByAsset(Blockchain.SystemShare().Hash):
            neo_balance += coin.Output.Value

        gas_balance = Fixed8.Zero()
        for coin in self.wallet.FindUnspentCoinsByAsset(Blockchain.SystemCoin().Hash):
            gas_balance += coin.Output.Value

        return {
            'message':'Hello',
            'height':Blockchain.Default().Height,
            'neo': neo_balance.ToInt(),
            'gas': gas_balance.ToInt(),
            'wallet_height': self.wallet.WalletHeight
        }
예제 #10
0
    def CalculateBonusInternal(unclaimed):

        amount_claimed = Fixed8.Zero()

        decInterval = Blockchain.DECREMENT_INTERVAL
        genAmount = Blockchain.GENERATION_AMOUNT
        genLen = len(genAmount)

        for coinheight, group in groupby(unclaimed, lambda x: x.Heights):
            amount = 0
            ustart = int(coinheight.start / decInterval)

            if ustart < genLen:

                istart = coinheight.start % decInterval
                uend = int(coinheight.end / decInterval)
                iend = coinheight.end % decInterval

                if uend >= genLen:
                    iend = 0

                if iend == 0:
                    uend -= 1
                    iend = decInterval

                while ustart < uend:

                    amount += (decInterval - istart) * genAmount[ustart]
                    ustart += 1
                    istart = 0

                amount += (iend - istart) * genAmount[ustart]

            endamount = Blockchain.Default().GetSysFeeAmountByHeight(
                coinheight.end - 1)
            startamount = 0 if coinheight.start == 0 else Blockchain.Default(
            ).GetSysFeeAmountByHeight(coinheight.start - 1)
            amount += endamount - startamount

            outputSum = 0

            for spentcoin in group:
                outputSum += spentcoin.Value.value

            outputSum = outputSum / 100000000
            outputSumFixed8 = Fixed8(int(outputSum * amount))
            amount_claimed += outputSumFixed8

        return amount_claimed
예제 #11
0
    def VerifyScripts(verifiable):

        try:
            hashes = verifiable.GetScriptHashesForVerifying()
        except Exception as e:
            logger.error("couldn't get script hashes %s " % e)
            return False

        if len(hashes) != len(verifiable.Scripts):
            return False

        state_reader = GetStateReader()
        blockchain = GetBlockchain()

        for i in range(0, len(hashes)):
            verification = verifiable.Scripts[i].VerificationScript

            if len(verification) == 0:
                #                logger.info("VERIFICATION IS 0, EMITTING APP CALL")
                sb = ScriptBuilder()
                sb.EmitAppCall(hashes[i].Data)
                verification = sb.ToArray()

            else:
                verification_hash = Crypto.ToScriptHash(verification,
                                                        unhex=False)
                if hashes[i] != verification_hash:
                    return False

            engine = ApplicationEngine(TriggerType.Verification, verifiable,
                                       blockchain, state_reader, Fixed8.Zero())
            engine.LoadScript(verification, False)
            invoction = verifiable.Scripts[i].InvocationScript
            engine.LoadScript(invoction, True)

            try:
                success = engine.Execute()
                state_reader.ExecutionCompleted(engine, success)

            except Exception as e:
                state_reader.ExecutionCompleted(engine, False, e)

#            pdb.set_trace()
            if engine.EvaluationStack.Count != 1 or not engine.EvaluationStack.Pop(
            ).GetBoolean():
                return False

        return True
예제 #12
0
    def VerifyScripts(verifiable):

        try:
            hashes = verifiable.GetScriptHashesForVerifying()
        except Exception as e:
            print("couldng get script hashes %s " % e)
            return False

        if len(hashes) != len(verifiable.Scripts):
            print("hashes not same length as verifiable scripts")
            return False
        print("hello!!!! %s " % hashes)

        for i in range(0, len(hashes)):
            verification = verifiable.Scripts[i].VerificationScript

            print("verifying script: %s %s " % (hashes[i], verification))

            if len(verification) == 0:
                sb = ScriptBuilder()
                sb.EmitAppCall(hashes[i].Data)
                verification = sb.ToArray()

            else:
                if hashes[i] != verification:
                    print("hashes not equal to script hash!")
                    return False

            engine = ApplicationEngine(TriggerType.Verification, verifiable,
                                       GetBlockchain(), GetStateReader(),
                                       Fixed8.Zero())
            engine.LoadScript(verification, False)
            engine.LoadScript(verifiable.Scripts[i].InvocationScript, True)

            res = engine.Execute()
            if not res:
                print("engine did not execune")
                return False
            else:

                print("engine did execute!")

            if engine.EvaluationStack.Count != 1 or not engine.EvaluationStack.Pop(
            ).GetBoolean():
                print("stack not one, or stack false")
                return False

        return True
예제 #13
0
    def DeserializeExclusiveData(self, reader):

        if self.Version > 1:
            raise Exception('Invalid format')

        self.Script = reader.ReadVarBytes()

        if len(self.Script) == 0:
            raise Exception('Invalid Format')

        if self.Version >= 1:
            self.Gas = reader.ReadFixed8()
            if self.Gas < Fixed8.Zero():
                raise Exception("Invalid Format")
        else:
            self.Gas = Fixed8(0)
예제 #14
0
    def load_smart_contract(self, args):

        if not self.Wallet:
            print("please open wallet")
            return

        function_code = LoadContract(args[1:])

        if function_code:

            contract_script = GatherContractDetails(function_code, self)

            if contract_script is not None:

                tx, fee, results, num_ops = test_invoke(
                    contract_script, self.Wallet, [])

                if tx is not None and results is not None:
                    print(
                        "\n-------------------------------------------------------------------------------------------------------------------------------------"
                    )
                    print("Test deploy invoke successful")
                    print("Total operations executed: %s " % num_ops)
                    print("Results %s " % [str(item) for item in results])
                    print("Deploy Invoke TX gas cost: %s " %
                          (tx.Gas.value / Fixed8.D))
                    print("Deploy Invoke TX Fee: %s " % (fee.value / Fixed8.D))
                    print(
                        "-------------------------------------------------------------------------------------------------------------------------------------\n"
                    )
                    print(
                        "Enter your password to continue and deploy this contract"
                    )

                    passwd = prompt("[password]> ", is_password=True)
                    if not self.Wallet.ValidatePassword(passwd):
                        return print("Incorrect password")

                    result = InvokeContract(self.Wallet, tx, Fixed8.Zero())

                    return
                else:
                    print("test ivoke failed")
                    print("tx is, results are %s %s " % (tx, results))
                    return
예제 #15
0
    def test_1_no_available_claim(self):

        wallet = self.GetWallet1()

        unspents = wallet.FindUnspentCoinsByAsset(self.NEO)

        self.assertEqual(1, len(unspents))

        unavailable_bonus = wallet.GetUnavailableBonus()

        self.assertEqual(Fixed8.FromDecimal(0.124316), unavailable_bonus)

        unclaimed_coins = wallet.GetUnclaimedCoins()

        self.assertEqual(0, len(unclaimed_coins))

        available_bonus = wallet.GetAvailableClaimTotal()

        self.assertEqual(Fixed8.Zero(), available_bonus)
예제 #16
0
def InvokeContract(wallet, tx, fee=Fixed8.Zero()):

    wallet_tx = wallet.MakeTransaction(tx=tx, fee=fee, use_standard=True)

    #    pdb.set_trace()

    if wallet_tx:

        context = ContractParametersContext(wallet_tx)

        wallet.Sign(context)

        if context.Completed:

            wallet_tx.scripts = context.GetScripts()

            relayed = False

            #            print("SENDING TX: %s " % json.dumps(wallet_tx.ToJson(), indent=4))

            # check if we can save the tx first
            save_tx = wallet.SaveTransaction(wallet_tx)

            if save_tx:
                relayed = NodeLeader.Instance().Relay(wallet_tx)
            else:
                print("Could not save tx to wallet, will not send tx")

            if relayed:
                print("Relayed Tx: %s " % wallet_tx.Hash.ToString())
                return wallet_tx
            else:
                print("Could not relay tx %s " % wallet_tx.Hash.ToString())
        else:

            print("Incomplete signature")

    else:
        print("Insufficient funds")

    return False
예제 #17
0
    def GetTransactionResults(self):
        if self.References is None: return None

        results = []
        realresults = []
        for ref_output in self.References.values():
            results.append(TransactionResult(ref_output.AssetId, ref_output.Value))

        for output in self.outputs:
            results.append(TransactionResult(output.AssetId, output.Value * Fixed8(-1)))

        for key, group in groupby(results, lambda x: x.AssetId):
            sum=Fixed8(0)
            for item in group:
                sum = sum + item.Amount

            if sum != Fixed8.Zero():

                realresults.append( TransactionResult(key, sum))

        return realresults
예제 #18
0
    def Asset_Create(self, engine):

        tx = engine.ScriptContainer

        asset_type = int(engine.EvaluationStack.Pop().GetBigInteger())

        if asset_type not in AssetType.AllTypes() or \
                asset_type == AssetType.CreditFlag or \
                asset_type == AssetType.DutyFlag or \
                asset_type == AssetType.GoverningToken or \
                asset_type == AssetType.UtilityToken:

            return False

        if len(engine.EvaluationStack.Peek().GetByteArray()) > 1024:
            return False

        name = engine.EvaluationStack.Pop().GetByteArray().decode('utf-8')

        amount = Fixed8(engine.EvaluationStack.Pop().GetBigInteger())

        if amount == Fixed8.Zero() or amount < Fixed8.NegativeSatoshi():
            return False

        if asset_type == AssetType.Invoice and amount != Fixed8.NegativeSatoshi(
        ):
            return False

        precision = int(engine.EvaluationStack.Pop().GetBigInteger())

        if precision > 8:
            return False

        if asset_type == AssetType.Share and precision != 0:
            return False

        if amount != Fixed8.NegativeSatoshi() and amount.value % pow(
                10, 8 - precision) != 0:
            return False

        ownerData = engine.EvaluationStack.Pop().GetByteArray()

        owner = ECDSA.decode_secp256r1(ownerData, unhex=False).G

        if owner.IsInfinity:
            return False

        if not self.CheckWitnessPubkey(engine, owner):
            logger.error("check witness false...")
            return False

        admin = UInt160(data=engine.EvaluationStack.Pop().GetByteArray())

        issuer = UInt160(data=engine.EvaluationStack.Pop().GetByteArray())

        new_asset = AssetState(asset_id=tx.Hash,
                               asset_type=asset_type,
                               name=name,
                               amount=amount,
                               available=Fixed8.Zero(),
                               precision=precision,
                               fee_mode=0,
                               fee=Fixed8.Zero(),
                               fee_addr=UInt160(),
                               owner=owner,
                               admin=admin,
                               issuer=issuer,
                               expiration=Blockchain.Default().Height + 1 +
                               2000000,
                               is_frozen=False)

        asset = self._assets.GetOrAdd(tx.Hash.ToBytes(), new_asset)

        # print("*****************************************************")
        # print("CREATED ASSET %s " % tx.Hash.ToBytes())
        # print("*****************************************************")
        engine.EvaluationStack.PushT(StackItem.FromInterface(asset))

        return True
예제 #19
0
    def MakeTransaction(self, tx, change_address=None, fee=Fixed8(0)):

        tx.ResetReferences()

        if not tx.outputs: tx.outputs = []
        if not tx.inputs: tx.inputs = []

        fee = fee + tx.SystemFee()

        paytotal = {}
        if tx.Type != int.from_bytes(TransactionType.IssueTransaction,
                                     'little'):

            for key, group in groupby(tx.outputs, lambda x: x.AssetId):
                sum = Fixed8(0)
                for item in group:
                    sum = sum + item.Value
                paytotal[key] = sum
        else:
            paytotal = {}

        if fee > Fixed8.Zero():

            if Blockchain.SystemCoin().Hash in paytotal.keys():
                paytotal[Blockchain.SystemCoin().
                         Hash] = paytotal[Blockchain.SystemCoin().Hash] + fee
            else:
                paytotal[Blockchain.SystemCoin().Hash] = fee

        paycoins = {}

        for assetId, amount in paytotal.items():
            paycoins[assetId] = self.FindUnspentCoinsByAssetAndTotal(
                assetId, amount)

        for key, unspents in paycoins.items():
            if unspents == None:
                print("insufficient funds for asset id: %s " % key)
                return None

        input_sums = {}

        for assetId, unspents in paycoins.items():
            sum = Fixed8(0)
            for coin in unspents:
                sum = sum + coin.Output.Value
            input_sums[assetId] = sum

        if not change_address:
            change_address = self.GetChangeAddress()

        new_outputs = []

        for assetId, sum in input_sums.items():
            if sum > paytotal[assetId]:
                difference = sum - paytotal[assetId]
                output = TransactionOutput(AssetId=assetId,
                                           Value=difference,
                                           script_hash=change_address)
                new_outputs.append(output)

        inputs = []

        for item in paycoins.values():
            for ref in item:
                inputs.append(ref.Reference)

        tx.inputs = inputs
        tx.outputs = tx.outputs + new_outputs

        return tx
예제 #20
0
def ClaimGas(wallet, require_password=True):

    unclaimed_coins = wallet.GetUnclaimedCoins()
    unclaimed_coin_refs = [coin.Reference for coin in unclaimed_coins]

    if len(unclaimed_coin_refs) == 0:
        print("no claims to process")
        return False

    available_bonus = Blockchain.Default().CalculateBonusIgnoreClaimed(
        unclaimed_coin_refs)

    if available_bonus == Fixed8.Zero():

        print("No gas to claim")
        return False

    claim_tx = ClaimTransaction()
    claim_tx.Claims = unclaimed_coin_refs
    claim_tx.Attributes = []
    claim_tx.inputs = []
    claim_tx.outputs = [
        TransactionOutput(AssetId=Blockchain.SystemCoin().Hash,
                          Value=available_bonus,
                          script_hash=wallet.GetChangeAddress())
    ]

    context = ContractParametersContext(claim_tx)
    wallet.Sign(context)

    print("\n---------------------------------------------------------------")
    print("Will make claim for %s GAS" % available_bonus.ToString())
    print(
        "------------------------------------------------------------------\n")

    if require_password:
        print("Enter your password to complete this claim")

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

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

    if context.Completed:

        claim_tx.scripts = context.GetScripts()
        wallet.SaveTransaction(claim_tx)

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

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

            print("Could not relay tx %s " % claim_tx.Hash.ToString())
        return claim_tx, relayed

    else:

        print("could not sign tx")

    return None, False
예제 #21
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)

        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)

        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()

        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:

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

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

        if context.Completed:

            tx.scripts = context.GetScripts()

            wallet.SaveTransaction(tx)

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

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

            if relayed:
                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
예제 #22
0
    def MakeTransaction(self,
                        tx,
                        change_address=None,
                        fee=Fixed8(0),
                        from_addr=None,
                        use_standard=False,
                        watch_only_val=0,
                        exclude_vin=None,
                        use_vins_for_asset=None):
        """
        This method is used to to calculate the necessary TransactionInputs (CoinReferences) and TransactionOutputs to
        be used when creating a transaction that involves an exchange of system assets, ( NEO, Gas, etc )

        Args:
            tx: (Transaction) The Transaction to be used
            change_address: (UInt160) The address any change for the transaction should be returned to
            fee: (Fixed8) A fee to be attached to the Transaction for network processing purposes
            from_addr: (UInt160) If present, all CoinReferences selected will only come from this address
            use_standard: (bool) If true, only CoinReferences from standard addresses ( not contracts that are smart contracts ) will be used
            watch_only_val: (int) 0 or CoinState.WATCH_ONLY, if present only choose coins that are in a WatchOnly address
            exclude_vin: (list) A list of CoinReferences to NOT use in the making of this tx
            use_vins_for_asset: (list) A list of CoinReferences to use

        Returns:
            tx: (Transaction) Returns the transaction with oupdated inputs and outputs
        """

        tx.ResetReferences()

        if not tx.outputs:
            tx.outputs = []
        if not tx.inputs:
            tx.inputs = []

        fee = fee + (tx.SystemFee() * Fixed8.FD())

        #        pdb.set_trace()

        paytotal = {}
        if tx.Type != int.from_bytes(TransactionType.IssueTransaction,
                                     'little'):

            for key, group in groupby(tx.outputs, lambda x: x.AssetId):
                sum = Fixed8(0)
                for item in group:
                    sum = sum + item.Value
                paytotal[key] = sum
        else:
            paytotal = {}

        if fee > Fixed8.Zero():

            if Blockchain.SystemCoin().Hash in paytotal.keys():
                paytotal[Blockchain.SystemCoin().
                         Hash] = paytotal[Blockchain.SystemCoin().Hash] + fee
            else:
                paytotal[Blockchain.SystemCoin().Hash] = fee

        paycoins = {}

        self._vin_exclude = exclude_vin

        for assetId, amount in paytotal.items():

            if use_vins_for_asset is not None and len(
                    use_vins_for_asset
            ) > 0 and use_vins_for_asset[1] == assetId:
                paycoins[assetId] = self.FindCoinsByVins(use_vins_for_asset[0])
            else:
                paycoins[assetId] = self.FindUnspentCoinsByAssetAndTotal(
                    assetId,
                    amount,
                    from_addr=from_addr,
                    use_standard=use_standard,
                    watch_only_val=watch_only_val)

        self._vin_exclude = None

        for key, unspents in paycoins.items():
            if unspents is None:
                print("insufficient funds for asset id: %s " % key)
                return None

        input_sums = {}

        for assetId, unspents in paycoins.items():
            sum = Fixed8(0)
            for coin in unspents:
                sum = sum + coin.Output.Value
            input_sums[assetId] = sum

        if not change_address:
            change_address = self.GetChangeAddress(from_addr=from_addr)

        new_outputs = []

        for assetId, sum in input_sums.items():
            if sum > paytotal[assetId]:
                difference = sum - paytotal[assetId]
                output = TransactionOutput(AssetId=assetId,
                                           Value=difference,
                                           script_hash=change_address)
                new_outputs.append(output)

        inputs = []

        for item in paycoins.values():
            for ref in item:
                inputs.append(ref.Reference)

        tx.inputs = inputs
        tx.outputs = tx.outputs + new_outputs

        return tx
예제 #23
0
 def TotalFees(self):
     amount = Fixed8.Zero()
     for tx in self.Transactions:
         amount += tx.SystemFee()
     return amount
예제 #24
0
def RequestWithdraw(prompter, wallet, args):

    if not wallet:
        print("please open a wallet")
        return

    withdrawal_tx = construct_contract_withdrawal_request(wallet,
                                                          args,
                                                          fee=Fixed8.Zero(),
                                                          check_holds=True)

    if withdrawal_tx:

        # below we are going to mimic a test invoke from the prompt

        invoke_args = []

        contract_addr = args[0]
        contract_hash = Helper.AddrStrToScriptHash(contract_addr).ToString()

        # add contract hash
        invoke_args.append(contract_hash)

        # add 'withdrawRequest' method
        invoke_args.append(parse_param('withdrawalRequest'))

        invoke_args_array = []

        requestor = parse_param(args[2])
        invoke_args_array.append(requestor)

        for input in withdrawal_tx.inputs:
            invoke_args_array.append(bytearray(input.PrevHash.Data))
            invoke_args_array.append(input.PrevIndex)

        invoke_args.append(invoke_args_array)

        print("invoke args array %s " % invoke_args)

        tx, fee, results, num_ops = TestInvokeContract(wallet, invoke_args,
                                                       None, False)

        if tx is not None and results is not None:
            print(
                "\n-------------------------------------------------------------------------------------------------------------------------------------"
            )
            print("Request Withdraw successful")
            print("Total operations: %s " % num_ops)
            print("Results %s " % [str(item) for item in results])
            print("Withdraw Request gas cost: %s " % (tx.Gas.value / Fixed8.D))
            print("Withdraw Request Fee: %s " % (fee.value / Fixed8.D))
            print(
                "-------------------------------------------------------------------------------------------------------------------------------------\n"
            )
            print("Enter your password to complete this withdrawal request")

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

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

            result = InvokeContract(wallet, tx, fee)

            return result
        else:
            print("Error testing contract invoke")
            return
예제 #25
0
    def SystemFee(self):

        if self.AssetType == AssetType.GoverningToken or self.AssetType == AssetType.UtilityToken:
            return Fixed8.Zero()

        return Fixed8(int(settings.REGISTER_TX_FEE))
예제 #26
0
def test_invoke(script, wallet, outputs, withdrawal_tx=None):

    #    print("invoke script %s " % script)

    bc = GetBlockchain()

    sn = bc._db.snapshot()

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

    # if we are using a withdrawal tx, don't recreate the invocation tx
    # also, we don't want to reset the inputs / outputs
    # since those were already calculated
    if withdrawal_tx is not None:
        tx = withdrawal_tx

    else:
        tx = InvocationTransaction()
        tx.outputs = outputs
        tx.inputs = []

    tx.Version = 1
    tx.scripts = []
    tx.Script = binascii.unhexlify(script)

    script_table = CachedScriptTable(contracts)
    service = StateMachine(accounts, validators, assets, contracts, storages,
                           None)

    if len(outputs) < 1:
        contract = wallet.GetDefaultContract()
        tx.Attributes = [
            TransactionAttribute(usage=TransactionAttributeUsage.Script,
                                 data=Crypto.ToScriptHash(
                                     contract.Script).Data)
        ]

    # same as above. we don't want to re-make the transaction if it is a withdrawal tx
    if withdrawal_tx is not None:
        wallet_tx = tx
    else:
        wallet_tx = wallet.MakeTransaction(tx=tx)

    if wallet_tx:

        context = ContractParametersContext(wallet_tx)
        wallet.Sign(context)
        if context.Completed:
            wallet_tx.scripts = context.GetScripts()

    engine = ApplicationEngine(trigger_type=TriggerType.Application,
                               container=wallet_tx,
                               table=script_table,
                               service=service,
                               gas=wallet_tx.Gas,
                               testMode=True)

    engine.LoadScript(wallet_tx.Script, False)

    try:
        # drum roll?
        success = engine.Execute()

        if success:

            service.TestCommit()

            if len(service.notifications) > 0:
                for n in service.notifications:
                    Blockchain.Default().OnNotify(n)

            consumed = engine.GasConsumed() - Fixed8.FromDecimal(10)
            consumed.value = int(consumed.value)

            net_fee = None
            tx_gas = None

            if consumed < Fixed8.FromDecimal(10.0):
                net_fee = Fixed8.FromDecimal(.001)
                tx_gas = Fixed8.Zero()
            else:
                tx_gas = consumed
                net_fee = Fixed8.Zero()

            # set the amount of gas the tx will need
            wallet_tx.Gas = tx_gas
            # reset the wallet outputs
            wallet_tx.outputs = outputs
            wallet_tx.Attributes = []

            return wallet_tx, net_fee, engine.EvaluationStack.Items, engine.ops_processed
        else:
            print("error executing contract.....")
            return None, None, None, None

    except Exception as e:
        print("COULD NOT EXECUTE %s " % e)

    return None, None, None, None
예제 #27
0
def construct_and_send(prompter, wallet, arguments):
    try:
        if not wallet:
            print("please open a wallet")
            return
        if len(arguments) < 3:
            print("Not enough arguments")
            return

        to_send = get_arg(arguments)
        address_to = get_arg(arguments, 1)
        amount = get_arg(arguments, 2)
        address_from = get_arg(arguments, 3)

        assetId = None

        if to_send.lower() == 'neo':
            assetId = Blockchain.Default().SystemShare().Hash
        elif to_send.lower() == 'gas':
            assetId = Blockchain.Default().SystemCoin().Hash
        elif Blockchain.Default().GetAssetState(to_send):
            assetId = Blockchain.Default().GetAssetState(to_send).AssetId

        scripthash = wallet.ToScriptHash(address_to)
        if scripthash is None:
            print("invalid address")
            return

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

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

        fee = Fixed8.Zero()
        if get_arg(arguments, 3):
            fee = Fixed8.TryParse(get_arg(arguments, 3))

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

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


        passwd = prompt("[Password]> ",
                   completer=prompter.completer,
                   is_password=True,
                   history=prompter.history,
                   get_bottom_toolbar_tokens=prompter.get_bottom_toolbar,
                   style=prompter.token_style)

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

        context = ContractParametersContext(tx)
        wallet.Sign(context)

        if context.Completed:

            tx.scripts = context.GetScripts()

            wallet.SaveTransaction(tx)

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

            if relayed:
                print("Relayed Tx: %s " % tx.Hash.ToString())
            else:
                print("Could not relay tx %s " % tx.Hash.ToString())

        else:
            print("Could not sign transaction")
            return




    except Exception as e:
        print("could not send: %s " % e)
        traceback.print_stack()
        traceback.print_exc()
예제 #28
0
    def do_send(self, arguments):
        try:
            if not self.Wallet:
                print("please open a wallet")
                return
            if len(arguments) < 3:
                print("Not enough arguments")
                return

            to_send = get_arg(arguments)
            address = get_arg(arguments, 1)
            amount = get_arg(arguments, 2)

            assetId = None

            if to_send.lower() == 'neo':
                assetId = Blockchain.Default().SystemShare().Hash
            elif to_send.lower() == 'gas':
                assetId = Blockchain.Default().SystemCoin().Hash
            elif Blockchain.Default().GetAssetState(to_send):
                assetId = Blockchain.Default().GetAssetState(to_send).AssetId

            scripthash = self.Wallet.ToScriptHash(address)
            if scripthash is None:
                print("invalid address")
                return

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

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

            fee = Fixed8.Zero()
            if get_arg(arguments, 3):
                fee = Fixed8.TryParse(get_arg(arguments, 3))

            output = TransactionOutput(AssetId=assetId,
                                       Value=f8amount,
                                       script_hash=scripthash)
            tx = ContractTransaction(outputs=[output])
            ttx = self.Wallet.MakeTransaction(tx=tx,
                                              change_address=None,
                                              fee=fee)

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

            self._wallet_send_tx = ttx

            self._num_passwords_req = 1
            self._gathered_passwords = []
            self._gathering_password = True
            self._gather_password_action = self.do_send_created_tx

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