def handleLocalScript(self, fromAccount, output, deploy): gasLimit = Config.getIntValue('TRANSACTION_LOCAL_GAS_LIMIT') gasPrice = Config.getIntValue('TRANSACTION_LOCAL_GAS_PRICE') localTx = Transaction(gasLimit, gasPrice) localTx.gasRemaining = Config.getIntValue( 'TRANSACTION_LOCAL_GAS_REMAINING') _input = None if deploy: pass else: scriptData = [] scriptData.append(DataType.zeroFillArray(0, 32)) scriptData.append(DataType.zeroFillArray(0, 32)) scriptData.append(fromAccount.address) scriptData.extend(self.parameters) _input = Input(Config.getValue('SCRIPT_TRANSACTION_ID'), Config.getIntValue('SCRIPT_OUTPUT_INDEX')) _input.witness = scriptData if RVM.run(localTx, _input, output, True, deploy, True): if len(localTx.internalOutputs) > 0: internalOutput = localTx.internalOutputs[-1] if deploy: PersistentStorage.add(internalOutput.address, internalOutput, True) result = 'Script Deployed Locally' else: result = internalOutput.script try: result = DataType.toHex(result) result = DataType.asInt(result, 16) except ValueError: pass return result return None
def getNewBlockBits(chainHeadBlock, chainHeadBlockHeight): newBlockBits = chainHeadBlock.bits if chainHeadBlockHeight > 0: blockRetargeting = getBlockRetargeting() if chainHeadBlockHeight % blockRetargeting == 0: retargetingStartBlock = chainHeadBlock retargeting = None index = 0 while index < blockRetargeting: retargetingBlockTarget = getTargetFromBits( retargetingStartBlock.bits) if retargeting == None: retargeting = retargetingBlockTarget if Config.getBoolValue('DGW3_ENABLED'): if index > 0: retargeting = (retargeting * index + retargetingBlockTarget) // (index + 1) retargetingStartBlock = Chain.getChain().getBlockByHash( retargetingStartBlock.previousHash) index += 1 blockIntervalTime = chainHeadBlock.timestamp - retargetingStartBlock.timestamp blockIntervalTime = math.ceil(blockIntervalTime) adjustedTarget = adjustTarget(retargeting, blockIntervalTime) if adjustedTarget > getTargetFromBits( Config.getIntValue('GENESIS_BLOCK_DIFFICULTY_BITS', 16)): adjustedTarget = getTargetFromBits( Config.getIntValue('GENESIS_BLOCK_DIFFICULTY_BITS', 16)) newBlockBits = getBitsFromTarget(adjustedTarget) return newBlockBits
def isMultiSig(self): if len(self.script) != Config.getIntValue('SCRIPT_MULTISIG_LEN'): return False if self.script[0] != Config.getIntValue('SCRIPT_VERSION', False): return False if self.script[1] != Opcodes.alias('CHECKMULTISIGVERIFY', True): return False return True
def isAtomicLock(self): if len(self.script) != Config.getIntValue('SCRIPT_ATOMIC_SWAP_LEN'): return False if self.script[0] != Config.getIntValue('SCRIPT_VERSION', False): return False if self.script[1] != Opcodes.alias('CHECKATOMICSWAPLOCKVERIFY', True): return False return True
def sendDataByUDP(host, port, data): try: with socket.socket(socket.AF_INET, socket.SOCK_DGRAM, socket.IPPROTO_UDP) as sock: sock.settimeout(Config.getIntValue("CONNECTION_TIMEOUT")) data = DataType.serialize(data) sock.sendto(data, (host, port)) return sock.recvfrom( Config.getIntValue("SOCKET_RECEIVE_BUFFER_SIZE")) except IOError: Log.error('Unable to send data by UDP to host: %s port: %s data: %s' % (host, port, data)) return None, None
def merge(): script = bytearray() script.append(Config.getIntValue("SCRIPT_VERSION")) script.append(Opcodes.alias('MERGE', True)) return DataType.serialize(script)
def verifyAtomicSwapLock(): script = bytearray() script.append(Config.getIntValue("SCRIPT_VERSION")) script.append(Opcodes.alias('CHECKATOMICSWAPLOCKVERIFY', True)) return DataType.serialize(script)
def __init__(self): super().__init__() self.type = MessageType.GETBLOCKS self.version = Config.getIntValue("BLOCK_VERSION") self.blockHashes = [] self.chain = Chain.getChain()
def deploy(self, isLocal, callback): result = None fromAccount = Accounts.getAccountByAddress(self.fromAddress) if fromAccount != None: if isLocal: toAddress = Crypto.generateAddress(fromAccount.address) _script = bytearray() _script.append(Config.getIntValue("EXTENSION_SCRIPT_VERSION")) _script.extend(self.script) _script = DataType.serialize(_script) extraData = None if len(self.parameters) > 0: extraData = self.parameters extraData.append(fromAccount.address) output = Output(toAddress, _script, self.value, extraData) result = self.handleLocalScript(fromAccount, output, True) if result != None: Contracts.addContract(Contract(toAddress), False) else: result = MemoryPool.addUnconfirmedTransaction( fromAccount, None, self.value, self.gasLimit, self.gasPrice, self.script, self.parameters) try: result = DataType.toHex(result) except: pass if result != None: callback(JSONRPC.createResultObject(result, self.id)) else: self.onFailure(callback)
def writeResponse(self, response): response = DataType.serialize(response) responseLen = len(response) responseLen = DataType.intToBytes( responseLen, Config.getIntValue("SOCKET_HEADER_BUFFER_SIZE")) self.request.sendall(responseLen) self.request.sendall(response)
def verifyMultiSignature(): script = bytearray() script.append(Config.getIntValue("SCRIPT_VERSION")) script.append(Opcodes.alias('CHECKMULTISIGVERIFY', True)) return DataType.serialize(script)
def open(self, subDatabase=None): self.lock.acquire() self.db = lmdb.open(self.database, max_dbs=Config.getIntValue('MAX_DATABASES')) subDatabaseBytes = DataType.serialize( self.subDatabase if subDatabase == None else subDatabase) self.subDb = self.db.open_db(subDatabaseBytes)
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 isCoinbase(self): if self.outpoint.txId != Config.getBytesValue( 'COINBASE_TRANSACTION_ID', False): return False if self.outpoint.outputIndex != Config.getIntValue( 'COINBASE_OUTPUT_INDEX'): return False return True
def run(self): Sync.version() Sync.getaddr() Sync.getblocks() Sync.mempool() pingBroadcast = Timer(Config.getIntValue("PING_BROADCAST_SECONDS"), Sync.ping) pingBroadcast.setName('PING_BROADCAST') pingBroadcast.start()
def intToBytes(value, bytesLen=None): if isinstance(value, bytes): return value if bytesLen == None: bytesLen = math.ceil(value.bit_length() / Config.getIntValue("BITS_PER_BYTE")) if bytesLen <= 0: bytesLen = 1 return value.to_bytes(bytesLen, byteorder=Config.getValue("BYTE_ORDER"))
def verifyCoinbaseMaturity(self, transaction): for txIn in transaction.inputs: coin = UXTO.getUnspentTransactionCoin(txIn.outpoint) if coin.isCoinbase(): chainHeadIndexBlock = Chain.getChain().getChainHeadIndexBlock() if Config.getIntValue( 'COINBASE_MATURITY' ) > chainHeadIndexBlock.height - coin.height: return False return True
def __init__(self, gasLimit=None, gasPrice=None): self.version = Config.getIntValue("TRANSACTION_VERSION") self.gasLimit = gasLimit self.gasPrice = gasPrice self.gasRemaining = None self.inputs = [] self.outputs = [] self.internalOutputs = []
def __init__(self): self.version = Config.getIntValue("BLOCK_VERSION") self.previousHash = None self.merkleRoot = None self.witnessRoot = None self.gasLimit = None self.gasUsed = None self.nonce = None self.bits = None self.timestamp = DataType.asTime() self.transactions = []
def validate(self): if self.type != MessageType.GETBLOCKS: return False if self.version != Config.getIntValue("BLOCK_VERSION"): return False if self.blockHashes == None or len(self.blockHashes) == 0: return False for blockHash in self.blockHashes: if not Validator.hash(blockHash): return False return True
def getSocketPayload( socket, bufferSize=Config.getIntValue("SOCKET_HEADER_BUFFER_SIZE")): payload = b'' payloadLen = None hasData = True while hasData: data = socket.recv(bufferSize) if payloadLen == None: payloadLen = DataType.deserialize(data, DataType.INT, 0) bufferSize = Config.getIntValue("SOCKET_RECEIVE_BUFFER_SIZE") else: dataLen = len(data) if dataLen > 0: payload += data if dataLen >= payloadLen: hasData = False else: payloadLen -= dataLen else: hasData = False return payload
def verifySignature(): script = bytearray() script.append(Config.getIntValue("SCRIPT_VERSION")) script.append(Opcodes.alias('DUP1')) script.append(Opcodes.alias('PUBADDR', True)) script.append(Opcodes.alias('ADDRESS')) script.append(Opcodes.alias('EQ')) script.append(Opcodes.alias('VERIFY', True)) script.append(Opcodes.alias('CHECKSIGVERIFY', True)) return DataType.serialize(script)
class SocketNodeServer(TCPServer): executor = ThreadPoolExecutor( max_workers=Config.getIntValue('MAX_INBOUND_PEER_CONNECTIONS')) executor._thread_name_prefix = 'InboundConnection' def server_bind(self): self.socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) self.socket.bind(self.server_address) def process_request(self, request, client_address): SocketNodeServer.executor.submit(super().process_request, request, client_address)
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 _sendData(host, data, hasPayload): try: if ':' in host: host = host.split(':') host[1] = DataType.asInt(host[1]) host = tuple(host) else: host = (host, getSocketPort()) with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as sock: sock.connect(host) sock.settimeout(Config.getIntValue("CONNECTION_TIMEOUT")) data = DataType.serialize(data) dataLen = len(data) dataLen = DataType.intToBytes( dataLen, Config.getIntValue("SOCKET_HEADER_BUFFER_SIZE")) sock.sendall(dataLen) sock.sendall(data) if hasPayload: payload = getSocketPayload(sock) return RLP.decode(payload) except IOError: Log.error('Unable to send data to host: %s data: %s' % (host, data)) return None
def verifyScript(self, transaction): for txOut in transaction.outputs: script = txOut.script if script == None or len(script) == 0: return False if txOut.hasExtScript(): if len(script) < Config.getIntValue('EXTENSION_SCRIPT_LEN'): return False if script[0] != Config.getIntValue('EXTENSION_SCRIPT_VERSION'): return False else: if len(script) > Config.getIntValue('SCRIPT_LEN'): return False if script[0] != Config.getIntValue('SCRIPT_VERSION', False): return False if script[1] == Opcodes.alias('MERGE', True): if len(script) != Config.getIntValue('SCRIPT_MERGE_LEN'): return False elif script[1] == Opcodes.alias('CHECKMULTISIGVERIFY', True): if len(script) != Config.getIntValue( 'SCRIPT_MULTISIG_LEN'): return False elif script[1] == Opcodes.alias('CHECKATOMICSWAPVERIFY', True): if len(script) != Config.getIntValue( 'SCRIPT_ATOMIC_SWAP_LEN'): return False elif script[1] == Opcodes.alias('CHECKATOMICSWAPLOCKVERIFY', True): if len(script) != Config.getIntValue( 'SCRIPT_ATOMIC_SWAP_LEN'): return False else: if script[1] != Opcodes.alias('DUP1'): return False if script[2] != Opcodes.alias('PUBADDR', True): return False if script[3] != Opcodes.alias('ADDRESS'): return False if script[4] != Opcodes.alias('EQ'): return False if script[5] != Opcodes.alias('VERIFY', True): return False if script[6] != Opcodes.alias('CHECKSIGVERIFY', True): return False return True
def verifyWitness(self, transaction): for txIn in transaction.inputs: witness = txIn.witness if witness == None or len(witness) == 0: return False unspentTransactionCoin = UXTO.getUnspentTransactionCoin( txIn.outpoint) txOut = unspentTransactionCoin.output if txOut.hasExtScript(): if len(witness) < Config.getIntValue( 'EXTENSION_INPUT_WITNESS_LEN'): return False if txOut.isMultiSig() or txOut.isAtomicSwap( ) or txOut.isAtomicLock(): if len(witness) % 2 == 0: publicKeys = witness[::2] signatures = witness[1::2] for publicKey, signature in zip(publicKeys, signatures): ''' The unlocking script (witness) can only push numbers on the stack ''' if signature == None or len( signature) != Config.getIntValue( 'SIGNATURE_LEN'): return False if publicKey == None or len( publicKey) != Config.getIntValue('PUBLIC_LEN'): return False else: return False else: if len(witness) != Config.getIntValue('INPUT_WITNESS_LEN'): return False ''' The unlocking script (witness) can only push numbers on the stack ''' if witness[0] == None or len( witness[0]) != Config.getIntValue('SIGNATURE_LEN'): return False if witness[1] == None or len( witness[1]) != Config.getIntValue('PUBLIC_LEN'): return False if txOut.hasExtScript(): address = txOut.address if address == None or len(address) != Config.getIntValue( 'ADDRESS_LEN'): return False return True
def verifyAllowedOutputValueRange(self, transaction): outputValueTotal = 0 for txOut in transaction.outputs: if txOut.hasExtScript(): if txOut.value < 0: return False elif txOut.value <= 0: return False outputValueTotal += txOut.value ''' Check coin supply limit ''' coinSupplyLimit = Config.getIntValue('COIN_SUPPLY_LIMIT') if coinSupplyLimit > 0: if outputValueTotal > coinSupplyLimit: return False return True
def send(url, data=None, doBasicAuth=False, headers=None): try: if not url.startswith("http"): url = "http://" + url if data != None: data = DataType.serialize(data) httpHeaders = {} if doBasicAuth: httpHeaders.update({'Authorization': getBasicAuth()}) if headers != None: httpHeaders.update(headers) req = Request(url, data, httpHeaders) response = urlopen(req, timeout=Config.getIntValue("CONNECTION_TIMEOUT")) return response.read() except IOError: Log.error('Unable to send request to url: %s' % url) return None
def execute(self): success = False try: self.pc = 0 while self.pc < len(self.code): element = self.code[self.pc] self.currOpcode = Opcodes.fetch(element, self.override) self.gasRemaining -= self.currOpcode.gas print(self.currOpcode.method, self.currOpcode.code, self.pc, self.gasRemaining) if self.gasRemaining >= 0: method = getattr(self, self.currOpcode.method) method() self.step() else: self.pc = len(self.code) self.invalid = True if self.invalid: success = False else: if self.output.hasExtScript() or self.merge: _address = self.output.address if self.overrideAddress == None else self.overrideAddress _script = self.output.script if self.overrideScript == None else self.overrideScript _value = self.output.value if self.overrideValue == None else self.overrideValue if self.deploy and not self.merge: script = bytearray() script.append(Config.getIntValue("EXTENSION_SCRIPT_VERSION")) script.extend(_script) _script = DataType.serialize(script) if self.deploy or self.merge or self.localTx: # Output will be stored in the blockchain and not the UXTO self.output.store = False self.transaction.addInternalOutput(_address, _script, _value) self.transaction.gasRemaining = self.gasRemaining success = True if len(self.logs) > 0: key = self.persistentStorageKey + self.transaction.hash() PersistentStorage.add(key, self.logs, True) finally: if not self.readOnly: if success: PersistentStorage.commit(self.persistentStorageKey) else: PersistentStorage.rollback(self.persistentStorageKey) return success