def createUnconfirmedMultiSigTransaction(fromAccount, toAddress, value, gasLimit, gasPrice, threshold): transaction, outpoints = createNewUnconfirmedTransaction( fromAccount, value, gasLimit, gasPrice, Script.verifyMultiSignature()) if transaction != None: #Multi signature value _script = Script.verifyMultiSignature() extraData = threshold transaction.addOutput(toAddress, script, value, extraData) transaction.sign() return transaction
def init(self): if self.getIndexBlockByHash(self.CHAIN_HEAD_INDEX) == None: genesisBlockGasLimit = Config.getIntValue("GENESIS_BLOCK_GAS_LIMIT") genesisBlockGasUsed = Config.getIntValue("GENESIS_BLOCK_GAS_USED") genesisBlockGasPrice = Config.getIntValue("GENESIS_BLOCK_GAS_PRICE") genesisBlock = Block() genesisBlock.previousHash = Config.getBytesValue("GENESIS_BLOCK_PREVIOUS_HASH", False) genesisBlock.gasLimit = genesisBlockGasLimit genesisBlock.gasUsed = genesisBlockGasUsed genesisBlock.nonce = Config.getIntValue("GENESIS_BLOCK_NONCE") genesisBlock.bits = Config.getIntValue("GENESIS_BLOCK_DIFFICULTY_BITS", 16) genesisBlock.timestamp = Config.getIntValue("GENESIS_BLOCK_TIMESTAMP") transaction = Transaction(genesisBlockGasLimit, genesisBlockGasPrice) coinbaseData = [] coinbaseData.append(Config.getValue("GENESIS_BLOCK_COINBASE_DATA")) transaction.addCoinbaseInput(coinbaseData) genesisBlockRewards = Config.getDecimalValue("GENESIS_BLOCK_REWARDS") genesisBlockRewards = Units.toUnits(genesisBlockRewards) genesisBlockPublicAddress = Config.getValue("GENESIS_BLOCK_PUBLIC_ADDRESS") genesisBlockPublicAddress = Address.toAddressBytes(genesisBlockPublicAddress) genesisBlockScript = Script.verifySignature() transaction.addOutput(genesisBlockPublicAddress, genesisBlockScript, genesisBlockRewards) transaction.hash() genesisBlock.transactions.append(transaction) genesisBlock.merkleRoot = MerkleTree.getMerkleRoot(genesisBlock.transactions, False) genesisBlock.witnessRoot = MerkleTree.getMerkleRoot(genesisBlock.transactions, True) self.addBlock(genesisBlock)
def createNewUnconfirmedTransaction(fromAccount, value, gasLimit, gasPrice, script=Script.verifySignature(), extraData=None): spending = 0 outpoints = set() fee = gasLimit * gasPrice try: Accounts.index.open(Accounts.localUxtoSubDb) with Accounts.index.db.begin() as local: for outpointBytes, coinBytes in local.cursor( db=Accounts.index.subDb): outpoint = Outpoint() coin = Coin() outpoint.deserialize(outpointBytes) coin.deserialize(coinBytes) txOut = coin.output if txOut.address != fromAccount.address: continue if outpoint in MemoryPool.spentOutpoints: continue if coin.isCoinbase(): if not Validator.coinbaseMaturity(coin.height): continue outpoints.add(outpoint) spending += txOut.value if spending > value + fee: break except IOError: Log.error('Unable to open accounts local uxto database: %s' % Config.getValue("ACCOUNTS_INDEX_DB")) finally: Accounts.index.close() if spending < value + fee: return None, None transaction = Transaction(gasLimit, gasPrice) for outpoint in outpoints: transaction.addInput(outpoint.txId, outpoint.outputIndex) change = spending - value - fee if change > 0: transaction.addOutput(fromAccount.address, script, change, extraData) return transaction, outpoints
def getNewBlock(self, address, previousHash, bits, extraNonce): previousIndexBlock = self.getIndexBlockByHash(previousHash) block = Block() gasLimit = Config.getIntValue("BLOCK_REWARDS_GAS_LIMIT") gasPrice = Config.getIntValue("BLOCK_REWARDS_GAS_PRICE") transaction = Transaction(gasLimit, gasPrice) height = previousIndexBlock.height + 1 coinbaseData = [ DataType.asString(height), DataType.asString(bits), DataType.asString(extraNonce) ] transaction.addCoinbaseInput(coinbaseData) block.transactions.append(transaction) txFees = 0 totalTxGasUsed = 0 unconfirmedTransactions = MemoryPool.getMemoryPool() for txId in unconfirmedTransactions: unconfirmedTransaction = unconfirmedTransactions[txId] block.transactions.append(unconfirmedTransaction) txFees += unconfirmedTransaction.calculateTxFee() totalTxGasUsed += unconfirmedTransaction.calculateTxGasUsed() blockRewards = Config.getDecimalValue("BLOCK_REWARDS") blockRewards = Units.toUnits(blockRewards) coinbaseValue = blockRewards + txFees script = Script.verifySignature() transaction.addOutput(address, script, coinbaseValue) transaction.hash() #Include coinbase tx gas used totalTxGasUsed += transaction.calculateTxGasUsed() block.merkleRoot = MerkleTree.getMerkleRoot(block.transactions, False) block.witnessRoot = MerkleTree.getMerkleRoot(block.transactions, True) blockGasLimit = previousIndexBlock.gasLimit + (previousIndexBlock.gasLimit * (1 / 1024)) blockGasLimit = math.ceil(blockGasLimit) block.gasLimit = blockGasLimit block.gasUsed = totalTxGasUsed block.nonce = 0 block.bits = bits block.previousHash = previousHash return block
def call(self): gas = self.popAsInt() address = DataType.intToBytes(self.pop()) value = self.popAsInt() argsOffset = self.popAsInt() argsLength = self.popAsInt() retOffset = self.popAsInt() retLength = self.popAsInt() self.transaction.addInternalOutput(address, Script.verifySignature(), value) _address = self.output.address _script = self.output.script _value = self.output.value - value self.transaction.addInternalOutput(_address, _script, _value) #self.memory[retOffset:retOffset + retLength] = self.memory[argsOffset:argsOffset + argsLength] self.stack.append(1)
def selfdestruct(self): address = self.pop() self.overrideAddress = address self.overrideScript = Script.verifySignature() self.pc = len(self.code)
def createAtomicSwapTx(self, callback): fromAccount = Accounts.getAccountByAddress(self.fromAddress) toMultiSigAccount = Accounts.getAccountByAddress(self.toAddress) ''' A picks a random number x ''' hashPrivKey = Crypto.generateHash(toMultiSigAccount.private) ''' A creates TX1: "Pay w BTC to <B's public key> if (x for H(x) known and signed by B) or (signed by A & B)" ''' transactionA1 = MemoryPool.createUnconfirmedAtomicSwapTransaction(fromAccount, toMultiSigAccount.address, self.value, self.gasLimit, self.gasPrice, Script.verifyAtomicSwapSignature(), self.threshold) if transactionA1 != None: ''' A creates TX2: "Pay w BTC from TX1 to <A's public key>, locked 48 hours in the future, signed by A" ''' transactionA2 = MemoryPool.createUnconfirmedAtomicSwapTransaction(fromAccount, toMultiSigAccount.address, self.value, self.gasLimit, self.gasPrice, Script.verifyAtomicSwapLock()) if transactionA2 != None: tx = transactionA1.serialize() unsignedTx = transactionA2.serialize() result = { 'tx': DataType.toHex(tx), 'unsignedTx': DataType.toHex(unsignedTx) } callback( JSONRPC.createResultObject(result, self.id) ) else: self.onFailure(callback) else: self.onFailure(callback)
def createUnconfirmedTransaction(fromAccount, toAddress, value, gasLimit, gasPrice, script=None, parameters=None): transaction, outpoints = createNewUnconfirmedTransaction( fromAccount, value, gasLimit, gasPrice) if transaction != None: if script != None or parameters != None: #smart contract if script == None: #call witness = [] witness.append(fromAccount.address) witness.extend(parameters) unspentTransactionOutpoint = UXTO.getUnspentTransactionOutpointByAddress( toAddress) transaction.addInput(unspentTransactionOutpoint.txId, unspentTransactionOutpoint.outputIndex, witness) if value > 0: #contract value transfer _script = Script.merge() transaction.addOutput(toAddress, _script, value) else: #deploy outpointBytes = bytearray() for outpoint in outpoints: outpointBytes.extend(outpoint.serialize()) extensionAddress = Crypto.generateAddress(outpointBytes) _script = bytearray() _script.append(Config.getIntValue("EXTENSION_SCRIPT_VERSION")) _script.extend(script) _script = DataType.serialize(_script) extraData = None if len(parameters) > 0: extraData = parameters extraData.append(fromAccount.address) transaction.addOutput(extensionAddress, _script, value, extraData) else: _script = None unspentTransactionScript = UXTO.getUnspentTransactionScript( toAddress) if unspentTransactionScript != None: #contract value transfer _script = Script.merge() if _script == None: #value _script = Script.verifySignature() transaction.addOutput(toAddress, _script, value) transaction.sign() return transaction