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))
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
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=(',', ':'))
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
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
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
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
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
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 }
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
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
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
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)
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
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)
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
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
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
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
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
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
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
def TotalFees(self): amount = Fixed8.Zero() for tx in self.Transactions: amount += tx.SystemFee() return amount
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
def SystemFee(self): if self.AssetType == AssetType.GoverningToken or self.AssetType == AssetType.UtilityToken: return Fixed8.Zero() return Fixed8(int(settings.REGISTER_TX_FEE))
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
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()
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()