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 get(self, callback = None): accounts = [] # Account Types standard = [] multisig = [] atomicswap = [] for account in Accounts.getAccounts(): confirmedBalance = Accounts.getConfirmedBalanceByAddress(account.address) confirmedBalance = Units.toValue(confirmedBalance) confirmedBalance = DataType.asFloat(confirmedBalance) address = Address.to0xAddress(account.address) accountInfo = { 'address': address, 'type': account.type, 'balance': confirmedBalance } if account.type == AccountType.STANDARD: standard.append(accountInfo) elif account.type == AccountType.MULTISIGNATURE: multisig.append(accountInfo) elif account.type == AccountType.ATOMIC_SWAP: atomicswap.append(accountInfo) accounts.extend(standard) accounts.extend(multisig) accounts.extend(atomicswap) callback( JSONRPC.createResultObject(accounts, self.id) )
def deserialize(self, payload): if self.validatePayload(payload): self.deserializePayload(payload) keys = None if self.isMultiSig(): if self.isTxFromMultiSig(): keys = [ 'fromAddress', 'publicKeys', 'signatures', 'threshold', 'toAddress', 'value', 'gasLimit', 'gasPrice' ] else: keys = [ 'fromAddress', 'threshold', 'toAddress', 'value', 'gasLimit', 'gasPrice' ] else: keys = [ 'fromAddress', 'toAddress', 'value', 'gasLimit', 'gasPrice' ] if self.validateParameters(keys): self.fromAddress = Address.toAddressBytes( self.params['fromAddress']) if self.isMultiSig(): if self.isTxFromMultiSig(): self.publicKeys = [] _publicKeys = self.params['publicKeys'] for publicKey in _publicKeys: publicKey = DataType.fromHex(publicKey) self.publicKeys.append(publicKey) self.signatures = [] _signatures = self.params['signatures'] for signature in _signatures: signature = DataType.fromHex(signature) self.signatures.append(signature) self.threshold = self.params['threshold'] self.toAddress = Address.toAddressBytes( self.params['toAddress']) self.value = Units.toUnits(self.params['value']) self.gasLimit = self.params['gasLimit'] self.gasPrice = Units.toUnits(self.params['gasPrice']) if self.validate(): return True return False
def deserialize(self, payload): if self.validatePayload(payload): self.deserializePayload(payload) keys = [ 'fromAddress', 'script', 'parameters', 'value', 'gasLimit', 'gasPrice' ] if self.validateParameters(keys): self.fromAddress = Address.toAddressBytes( self.params['fromAddress']) if self.isDeploy(): self.script = DataType.fromHex(self.params['script']) else: self.script = Address.toAddressBytes(self.params['script']) self.parameters = self.params['parameters'] self.value = Units.toUnits(self.params['value']) self.gasLimit = self.params['gasLimit'] self.gasPrice = Units.toUnits(self.params['gasPrice']) if self.validate(): return True return False
def deserialize(self, payload): if self.validatePayload(payload): self.deserializePayload(payload) keys = None if self.isSignAtomicSwapTx(): keys = [] else: keys = ['fromAddress', 'threshold', 'toAddress', 'value', 'gasLimit', 'gasPrice'] if self.validateParameters(keys): if self.isSignAtomicSwapTx(): self.unsignedTx = self.params else: self.fromAddress = Address.toAddressBytes(self.params['fromAddress']) self.threshold = self.params['threshold'] self.toAddress = Address.toAddressBytes(self.params['toAddress']) self.value = Units.toUnits(self.params['value']) self.gasLimit = self.params['gasLimit'] self.gasPrice = Units.toUnits(self.params['gasPrice']) if self.validate(): return True return False
def verifyCoinbaseValue(self, block): coinbaseValue = 0.0 blkCreationTxFees = Config.getDecimalValue("BLOCK_REWARDS") blkCreationTxFees = Units.toUnits(blkCreationTxFees) for transaction in block.transactions: if transaction.isCoinbase(): output = transaction.outputs[0] coinbaseValue = output.value else: blkCreationTxFees += transaction.calculateTxFee() if coinbaseValue > blkCreationTxFees: return False return True
def get(self, callback=None): contracts = [] for contract in Contracts.getContracts(): confirmedBalance = 0 unspentTransactionScript = UXTO.getUnspentTransactionScript( contract.address) if unspentTransactionScript != None: txOut = unspentTransactionScript.output confirmedBalance = txOut.value confirmedBalance = Units.toValue(confirmedBalance) confirmedBalance = DataType.asFloat(confirmedBalance) address = Address.to0xAddress(contract.address) contracts.append({'address': address, 'balance': confirmedBalance}) callback(JSONRPC.createResultObject(contracts, self.id))
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 validate(self, transaction): if transaction == None: return False ''' The transaction’s syntax and data structure must be correct ''' if transaction.version == None or transaction.version != Config.getIntValue( 'TRANSACTION_VERSION'): return False if not self.verifyInputOutputNonEmpty(transaction): return False for txIn in transaction.inputs: ''' Check outpoint ''' if txIn.outpoint == None: return False outpoint = txIn.outpoint if outpoint.txId == None or len( outpoint.txId) != Config.getIntValue('HASH_LEN'): return False if outpoint.outputIndex == None or outpoint.outputIndex < 0: return False ''' Check Output Value ''' for txOut in transaction.outputs: if txOut.value == None: return False if txOut.hasExtScript(): if not txOut.value >= 0: return False elif not txOut.value > 0: return False ''' Check tx gas price and gas limit ''' if transaction.gasPrice == None or transaction.gasPrice < 0: return False if transaction.gasLimit == None or transaction.gasLimit < 0: return False ''' Internal Outputs are created from the result of a smart contract. Only the RVM should create them. ''' if len(transaction.internalOutputs) > 0: return False if not self.verifyAddress(transaction): return False if not self.verifyExtraData(transaction): return False if not self.verifyScript(transaction): return False if not self.verifyWitness(transaction): return False if not self.verifyTransactionSizeLimit(transaction): return False ''' Check for duplicate outpoints. ''' outpoints = set() for txIn in transaction.inputs: if txIn.outpoint in outpoints: return False outpoints.add(txIn.outpoint) if not self.verifyAllowedOutputValueRange(transaction): return False if not self.verifyInputsNonCoinbase(transaction): return False if not self.verifyTransactionRequiredSize(transaction): return False if not self.verifyTransactionDuplicateInPool(transaction): return False ''' or txId in a block in the main branch ''' txId = transaction.hash() try: UXTOStorage.uxto.open() with UXTOStorage.uxto.db.begin() as uxto: cursor = uxto.cursor(db=UXTOStorage.uxto.subDb) while cursor.next(): outpointBytes = cursor.key() outpoint = Outpoint() outpoint.deserialize(outpointBytes) if txId == outpoint.txId: return False except IOError: Log.error( 'Unable to determine if txId is in a block in the main branch.' ) finally: UXTOStorage.uxto.close() if not self.verifyTxOutputDuplicateInPool(transaction): return False ''' For each input, look in the main branch and the transaction pool to find the referenced output transaction. If the output transaction is missing for any input, this will be an orphan transaction. Add to the orphan transactions, if a matching transaction is not in there already. ''' for txIn in transaction.inputs: outpoint = txIn.outpoint if not UXTO.hasUnspentTransactionCoin(outpoint): tx = MemoryPool.getTransactionById(outpoint.txId) if tx == None or len(tx.outputs) - 1 < outpoint.outputIndex: OrphanManager.addTransaction(transaction) return False if not self.verifyCoinbaseMaturity(transaction): return False if not self.verifyUxtoReferencedOutput(transaction): return False if not self.verifyAllowedInputValueRange(transaction): return False if not self.verifySumInputOutputValues(transaction): return False if not self.verifyUnlockingScripts(transaction): return False ''' 7) Note that when the transaction is accepted into the memory pool, an additional check is made to ensure that the coinbase value does not exceed the transaction fees plus the expected BTC value (25BTC as of this writing). ''' if transaction.isCoinbase(): txOut = transaction.outputs blockRewards = Config.getDecimalValue("BLOCK_REWARDS") blockRewards = Units.toUnits(blockRewards) if txOut.value > blockRewards: return False return True