コード例 #1
0
def merge():
    script = bytearray()

    script.append(Config.getIntValue("SCRIPT_VERSION"))
    script.append(Opcodes.alias('MERGE', True))

    return DataType.serialize(script)
コード例 #2
0
def verifyMultiSignature():
    script = bytearray()

    script.append(Config.getIntValue("SCRIPT_VERSION"))
    script.append(Opcodes.alias('CHECKMULTISIGVERIFY', True))

    return DataType.serialize(script)
コード例 #3
0
def verifyAtomicSwapLock():
    script = bytearray()

    script.append(Config.getIntValue("SCRIPT_VERSION"))
    script.append(Opcodes.alias('CHECKATOMICSWAPLOCKVERIFY', True))

    return DataType.serialize(script)
コード例 #4
0
def getBasicAuth():
    username = Config.getValue("HTTP_RPC_USERNAME")
    password = Config.getValue("HTTP_RPC_PASSWORD")
    userpass = "******" % (username, password)
    userpassBytes = DataType.serialize(userpass)
    userpassB64 = b64encode(userpassBytes)
    return 'Basic %s' % userpassB64.decode("ascii")
コード例 #5
0
    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)
コード例 #6
0
 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)
コード例 #7
0
 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)
コード例 #8
0
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)
コード例 #9
0
 def writeResponse(self,
                   response,
                   contentType='application/json',
                   doHead=True):
     if doHead:
         self.do_HEAD(contentType)
     else:
         self.do_AUTHHEAD()
     if contentType == "application/json":
         response = json.dumps(response, sort_keys=False)
         response = DataType.serialize(response)
     self.wfile.write(response)
コード例 #10
0
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
コード例 #11
0
 def initialize(self):
     self.code = self.output.script[1:]
     parameters = []
     if self.deploy:
         parameters = [] if self.output.extraData == None else self.output.extraData
     else:
         if self.output.hasExtScript():
             parameters.extend(self.input.witness[3:])
         else:
             self.stack.extend(self.input.witness)
     methodHash = False if self.deploy else True
     for parameter in parameters:
         if not isinstance(parameter, bytes):
             try:
                 if methodHash:
                     parameter = DataType.fromHex(parameter)
                     parameter = DataType.serialize(parameter)
                     methodHash = False
                 else:
                     parameter = DataType.asInt(parameter)
             except ValueError:
                 try:
                     parameter = DataType.fromHex(parameter)
                     parameter = DataType.serialize(parameter)
                 except ValueError:
                     parameter = Address.toAddressBytes(parameter)
         if self.deploy:
             self.code += DataType.zeroFillArray(parameter, 32)
         else:
             if len(self.data) == 0:
                 self.data += parameter
             else:
                 self.data += DataType.zeroFillArray(parameter, 32)
     if len(self.data) > 0 and len(self.data) < 32:
         fillLen = 32 - len(self.data)
         self.data.extend(fillLen * b'\x00')
コード例 #12
0
def addPeers(peers):
    for peer in peers:
        if peer.host != Peers.hostname and peer.host != Peers.ipAddress:
            currPeer = getPeerByHost(peer.host)
            synchronized = False
            if currPeer == None:
                currPeer = peer
            else:
                currPeer.merge(peer)
                synchronized = True
            currPeer.lastUpdate = DataType.asTime()
            hostBytes = DataType.serialize(currPeer.host)
            Peers.peers.set(hostBytes, currPeer.serialize())
            if not synchronized:
                Sync.synchronize(currPeer.host)
                Sync.addr(currPeer.host)
コード例 #13
0
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
コード例 #14
0
 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
コード例 #15
0
class Peers:
    db = Config.getValue("PEERS_DB")
    subDb = Config.getValue("PEERS_SUB_DB")
    peers = Storage(db, subDb)

    hostname = Network.getHostname()
    ipAddress = Network.getIpAddress()

    if Config.getBoolValue('PEERS_ENABLE_SEEDS'):
        with open(Config.getValue('SEEDS_DIR')) as seeds:
            hosts = json.load(seeds)
            for host in hosts:
                if host != hostname and host != ipAddress:
                    hostBytes = DataType.serialize(host)
                    if peers.get(hostBytes) == None:
                        peer = Peer()
                        peer.host = host
                        peer.lastUpdate = DataType.asTime()
                        peers.set(hostBytes, peer.serialize())
コード例 #16
0
 def __init__(self):
     self.db = Config.getFilePath("CHAIN_DIRECTORY", "BLOCKCHAIN_DB")
     self.subDb = Config.getValue("BLOCKS_SUB_DB")
     
     self.storage = Storage(self.db, self.subDb)
        
     self.indexDb = Config.getFilePath("CHAIN_DIRECTORY", "INDEX_DB")
     self.subIndexDb = Config.getValue("INDEX_SUB_DB")
     
     self.index = Storage(self.indexDb, self.subIndexDb)
     
     self.CHAIN_HEAD_INDEX = DataType.serialize("CHAIN_HEAD_INDEX")
     self.BLOCK_HEIGHT_KEY = "BLOCK_HEIGHT_KEY"
     
     self.blkValidator = ValidatorFactory.getInstance(ValidatorType.BLOCK)
     self.txValidator = ValidatorFactory.getInstance(ValidatorType.TX)
     
     self.blkLock = RLock()
     self.orphanLock = RLock()
     
     self.miningPool = {}
コード例 #17
0
 def syncOrphanBlocks(self):
     hasLock = False
     try:
         hasLock = self.acquireOrphanLock(False)
         if hasLock:
             orphanBlocks = []
             for orphanBlockHash in OrphanManager.getBlocks():
                 orphanBlock = OrphanManager.getBlock(orphanBlockHash)
                 previousHash = orphanBlock.previousHash
                 previousHashBytes = DataType.serialize(previousHash)
                 if self.index.get(previousHashBytes) != None:
                     orphanBlocks.append(orphanBlock)
                 elif not OrphanManager.hasBlock(previousHash):
                     Sync.getdata(InventoryType.BLOCK, previousHash)
             for orphanBlock in orphanBlocks:
                 OrphanManager.removeBlock(orphanBlock)
             for orphanBlock in orphanBlocks:
                 self.addBlock(orphanBlock)
     finally:
         if hasLock:
             self.releaseOrphanLock()
コード例 #18
0
ファイル: RLP.py プロジェクト: anthonybuckle/Reciprocity-Core
def encode(item):
    item = DataType.serialize(item)
    encodedItem = b''
    if len(item) > 0:
        if isinstance(item, bytes):
            itemLen = len(item)
            if itemLen == 1 and item[0] <= BYTE_PREFIX_END:
                encodedItem += item
            else:
                encodedItem += encodeItem(item, itemLen, STRING_PREFIX_START)
        elif isinstance(item, list):
            for i in item:
                encodedItem += encode(i)
            itemLen = len(encodedItem)
            encodedItem = encodeItem(encodedItem, itemLen, LIST_PREFIX_START)
    else:
        if isinstance(item, bytes):
            encodedItem += DataType.intToBytes(STRING_PREFIX_START)
        elif isinstance(item, list):
            encodedItem += DataType.intToBytes(LIST_PREFIX_START)
    return encodedItem
コード例 #19
0
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
コード例 #20
0
 def balance(self):
     address = self.pop()
     address = DataType.serialize(address)
     print('balance', address)
     unspentTransactionScript = UXTO.getUnspentTransactionScript(address)
     self.stack.append(unspentTransactionScript.output.value)
コード例 #21
0
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
コード例 #22
0
def handleCommand(command, parameters):
    id = 1
    commands = []
    if command == 'CreateAtomicSwapAccount':
        commands.append(JSONRPC.createMethodObject(command, parameters, id))
    elif command == 'CreateMultiSigAccount':
        commands.append(JSONRPC.createMethodObject(command, parameters, id))
    elif command == 'GetAccounts':
        commands.append(JSONRPC.createMethodObject(command, [], id))
    elif command == 'GetNewAccount':
        commands.append(JSONRPC.createMethodObject(command, [], id))
    elif command == 'DeleteAccounts':
        commands.append(JSONRPC.createMethodObject(command, parameters, id))
    elif command == 'SendTransaction':
        fromAddress = parameters[0]
        toAddress = parameters[1]
        value = DataType.asFloat(parameters[2])
        gasLimit = DataType.asInt(parameters[3])
        gasPrice = DataType.asFloat(parameters[4])
        params = {
            'fromAddress': fromAddress,
            'toAddress': toAddress,
            'value': value,
            'gasLimit': gasLimit,
            'gasPrice': gasPrice
        }
        commands.append(JSONRPC.createMethodObject(command, params, id))
    elif command == 'SendTransactionToMultiSig':
        fromAddress = parameters[0]
        threshold = DataType.asInt(parameters[1])
        toMultiSigAddress = parameters[2]
        value = DataType.asFloat(parameters[3])
        gasLimit = DataType.asInt(parameters[4])
        gasPrice = DataType.asFloat(parameters[5])
        params = {
            'fromAddress': fromAddress,
            'threshold': threshold,
            'toAddress': toMultiSigAddress,
            'value': value,
            'gasLimit': gasLimit,
            'gasPrice': gasPrice
        }
        commands.append(JSONRPC.createMethodObject(command, params, id))
    elif command == 'SendTransactionFromMultiSig':
        fromAddress = parameters[0]
        publicKeys = []
        signatures = []
        idx = 0
        for parameter in parameters[1:-5]:
            if idx % 2 == 0:
                publicKeys.append(parameter)
            else:
                signatures.append(parameter)
            idx += 1
        threshold = DataType.asInt(parameters[-5])
        toAddress = parameters[-4]
        value = DataType.asFloat(parameters[-3])
        gasLimit = DataType.asInt(parameters[-2])
        gasPrice = DataType.asFloat(parameters[-1])
        params = {
            'fromAddress': fromAddress,
            'publicKeys': publicKeys,
            'signatures': signatures,
            'threshold': threshold,
            'toAddress': toAddress,
            'value': value,
            'gasLimit': gasLimit,
            'gasPrice': gasPrice
        }
        commands.append(JSONRPC.createMethodObject(command, params, id))
    elif command == 'SignMultiSigOutput':
        multiSigAddress = parameters[0]
        threshold = DataType.asInt(parameters[1])
        toAddress = parameters[2]
        value = DataType.asFloat(parameters[3])
        gasLimit = DataType.asInt(parameters[4])
        gasPrice = DataType.asFloat(parameters[5])
        params = {
            'fromAddress': multiSigAddress,
            'threshold': threshold,
            'toAddress': toAddress,
            'value': value,
            'gasLimit': gasLimit,
            'gasPrice': gasPrice
        }
        commands.append(JSONRPC.createMethodObject(command, params, id))
    elif command == 'GetMiningWorker':
        address = parameters[0]
        enabled = DataType.asBool(parameters[1])
        params = {'address': address, 'enabled': enabled}
        commands.append(JSONRPC.createMethodObject(command, params, id))
    elif command == 'CreateAtomicSwapTx':
        fromAddress = parameters[0]
        threshold = DataType.asInt(parameters[1])
        toAddress = parameters[2]
        value = DataType.asFloat(parameters[3])
        gasLimit = DataType.asInt(parameters[4])
        gasPrice = DataType.asFloat(parameters[5])
        params = {
            'fromAddress': fromAddress,
            'threshold': threshold,
            'toAddress': toAddress,
            'value': value,
            'gasLimit': gasLimit,
            'gasPrice': gasPrice
        }
        commands.append(JSONRPC.createMethodObject(command, params, id))
    elif command == 'SendAtomicSwapTx':
        fromAddress = parameters[0]
        toAddress = parameters[1]
        value = DataType.asFloat(parameters[2])
        gasLimit = DataType.asInt(parameters[3])
        gasPrice = DataType.asFloat(parameters[4])
        params = {
            'fromAddress': fromAddress,
            'toAddress': toAddress,
            'value': value,
            'gasLimit': gasLimit,
            'gasPrice': gasPrice
        }
        commands.append(JSONRPC.createMethodObject(command, params, id))
    elif command == 'SignAtomicSwapTx':
        commands.append(JSONRPC.createMethodObject(command, parameters, id))
    elif command == 'WatchContracts':
        commands.append(JSONRPC.createMethodObject(command, parameters, id))
    elif command == 'DeleteContracts':
        commands.append(JSONRPC.createMethodObject(command, parameters, id))
    elif command == 'GetContracts':
        commands.append(JSONRPC.createMethodObject(command, [], id))
    elif command == 'GetScriptLogs':
        fromAddress = parameters[0]
        scriptAddress = parameters[1]
        value = DataType.asFloat(parameters[2])
        gasLimit = DataType.asInt(parameters[3])
        gasPrice = DataType.asFloat(parameters[4])
        params = {
            'fromAddress': fromAddress,
            'script': scriptAddress,
            'value': value,
            'gasLimit': gasLimit,
            'gasPrice': gasPrice
        }
        commands.append(JSONRPC.createMethodObject(command, params, id))
    elif command == 'DeployScript' or command == 'DeployLocalScript':
        fromAddress = parameters[0]
        with open(parameters[1], 'r') as scriptFile:
            script = scriptFile.read()
        _parameters = parameters[2:-3]
        value = DataType.asFloat(parameters[-3])
        gasLimit = DataType.asInt(parameters[-2])
        gasPrice = DataType.asFloat(parameters[-1])
        params = {
            'fromAddress': fromAddress,
            'script': script,
            'parameters': _parameters,
            'value': value,
            'gasLimit': gasLimit,
            'gasPrice': gasPrice
        }
        commands.append(JSONRPC.createMethodObject(command, params, id))
    elif command == 'CallTxScript' or command == 'CallLocalScript':
        fromAddress = parameters[0]
        scriptAddress = parameters[1]
        _parameters = parameters[2:-3]
        if _parameters and len(_parameters) > 0:
            _parameters[0] = DataType.serialize(_parameters[0])
            hashFunction = keccak.new(data=_parameters[0], digest_bits=256)
            methodHash = hashFunction.hexdigest()
            _parameters[0] = methodHash[0:8]
        value = DataType.asFloat(parameters[-3])
        gasLimit = DataType.asInt(parameters[-2])
        gasPrice = DataType.asFloat(parameters[-1])
        params = {
            'fromAddress': fromAddress,
            'script': scriptAddress,
            'parameters': _parameters,
            'value': value,
            'gasLimit': gasLimit,
            'gasPrice': gasPrice
        }
        commands.append(JSONRPC.createMethodObject(command, params, id))
    elif command == 'WatchSideChain':
        commands.append(JSONRPC.createMethodObject(command, parameters, id))
    elif command == 'DeleteSideChains':
        commands.append(JSONRPC.createMethodObject(command, parameters, id))
    elif command == 'GetSideChains':
        commands.append(JSONRPC.createMethodObject(command, [], id))
    elif command == 'DeploySideChain':
        fromAddress = parameters[0]
        parameters = parameters[1]
        value = DataType.asFloat(parameters[2])
        gasLimit = DataType.asInt(parameters[3])
        gasPrice = DataType.asFloat(parameters[4])
        params = {
            'fromAddress': fromAddress,
            'parameters': parameters,
            'value': value,
            'gasLimit': gasLimit,
            'gasPrice': gasPrice
        }
        commands.append(JSONRPC.createMethodObject(command, params, id))
    elif command == 'GetPeers':
        commands.append(JSONRPC.createMethodObject(command, [], id))
    elif command == 'AddPeers':
        commands.append(JSONRPC.createMethodObject(command, parameters, id))
    elif command == 'DeletePeers':
        commands.append(JSONRPC.createMethodObject(command, parameters, id))
    else:
        raise ValueError('Unsupported command: ' + command)

    url = '%s:%s' % (Http.getNodeHostname(), Http.getHttpPort())
    for cmd in commands:
        cmd = json.dumps(cmd)
        response = Http.send(url, cmd, doBasicAuth=True)
        if response == None or len(response) == 0:
            print('Empty response from ', url, 'request', cmd)
            continue
        response = json.loads(response)
        value = '\n'
        if 'result' in response:
            result = response['result']
            if isinstance(result, list):
                for item in result:
                    if isinstance(item, dict):
                        for v in item.values():
                            value += ('%s\t' % v)
                        value += '\n'
                    else:
                        value += item
                        value += '\n'
            else:
                value += DataType.asString(result)
                value += '\n'
        elif 'error' in response:
            error = response['error']

            code = error['code']
            message = error['message']
            data = error['data']

            value += '%s %s %s' % (code, message, data)
            value += '\n'
        print(value)
コード例 #23
0
def getPeerByHost(host):
    hostBytes = DataType.serialize(host)
    peerBytes = Peers.peers.get(hostBytes)
    return getPeerFromBytes(peerBytes)
コード例 #24
0
def subtractConfirmedBalanceByAddress(address, value):
    oldConfirmedBalance = getConfirmedBalanceByAddress(address)
    newConfirmedBalance = oldConfirmedBalance - value
    newConfirmedBalanceBytes = DataType.serialize(newConfirmedBalance)
    Accounts.index.set(address, newConfirmedBalanceBytes,
                       Accounts.balancesSubDb)
コード例 #25
0
def removePeers(peers):
    for peer in peers:
        hostBytes = DataType.serialize(peer.host)
        Peers.peers.remove(hostBytes)
    return True
コード例 #26
0
def getBytesValue(key, hexStr=True):
    if hexStr:
        return DataType.fromHex(Config.config[key])
    else:
        return DataType.serialize(Config.config[key])
コード例 #27
0
 def getIndexBlockByHash(self, blockHash):
     blockHashBytes = DataType.serialize(blockHash)
     indexBlockBytes = self.index.get(blockHashBytes)
     return self.getIndexBlockFromBytes(indexBlockBytes)
コード例 #28
0
 def getBlockByHash(self, blockHash):
     blockHashBytes = DataType.serialize(blockHash)
     blockBytes = self.storage.get(blockHashBytes)
     return self.getBlockFromBytes(blockBytes)
コード例 #29
0
 def getBlockHashByHeight(self, height):
     blockHeightKey = "{0}{1}{2}".format(self.BLOCK_HEIGHT_KEY, '_', height)
     blockHeightKey = DataType.serialize(blockHeightKey)
     return self.index.get(blockHeightKey)
コード例 #30
0
    def addBlock(self, block):
        if self.blkValidator.validate(block):
            try:
                self.acquireBlockLock()
            
                blockHash = block.hash()
                blockHashBytes = DataType.serialize(blockHash)
                
                if self.index.get(blockHashBytes) == None:
                    if not OrphanManager.hasBlock(blockHash):
                        bits = block.bits
                        previousChainWork = None
                        previousHash = block.previousHash
                        blockGasLimit = block.gasLimit
                        blockHeight = 0
                        
                        chainHeadBlock = self.getChainHeadBlock()
                        chainHeadIndexBlock = self.getIndexBlockByHash(self.CHAIN_HEAD_INDEX)
                        previousIndexBlock = self.getIndexBlockByHash(previousHash)
                        
                        if chainHeadIndexBlock == None:
                            chainHeadIndexBlock = IndexBlock()
                        if previousIndexBlock != None:
                            blockHeight = previousIndexBlock.height + 1
                            previousChainWork = previousIndexBlock.chainWork
                            
                        if blockHash == Config.getBytesValue('GENESIS_BLOCK_HASH'):
                            previousChainWork = Config.getIntValue('GENESIS_BLOCK_CHAIN_WORK', 16)
                        
                        '''        
                            For case 1, adding to main branch:
                        '''
                        if previousHash == chainHeadIndexBlock.previousHash or blockHash == Config.getBytesValue('GENESIS_BLOCK_HASH'):                
                            '''
                                For all but the coinbase transaction, apply the following:
                            '''
                            if not self.blkValidator.verifyNonCoinbaseTransactions(block):
                                return False
                                 
                            '''
                                Reject if coinbase value > sum of block creation fee and transaction fees
                            '''   
                            if not self.blkValidator.verifyCoinbaseValue(block):
                                return False
                                    
                            for transaction in block.transactions:
                                for txIn in transaction.inputs:
                                    UXTO.removeUnspentTransactionCoin(txIn.outpoint)
                                uxtoOutputs = []
                                uxtoOutputs.extend(transaction.outputs)
                                uxtoOutputs.extend(transaction.internalOutputs)
                                txOutputSize = 0
                                for txOut in uxtoOutputs:
                                    if txOut.store:
                                        txOutputSize += 1
                                outputIndex = 0
                                for txOut in uxtoOutputs:
                                    UXTO.removeStaleUnspentTransactionScript(txOut)
                                    if txOut.store:
                                        coin = Coin()
                                        coin.output = txOut
                                        coin.txOutputSize = txOutputSize
                                        coin.height = blockHeight
                                        coin.coinbase = transaction.isCoinbase()
                                        UXTO.addUnspentTransactionCoin(Outpoint(transaction.hash(), outputIndex), coin)
                                        outputIndex += 1
                                        '''
                                            For each transaction, "Add to wallet if mine"
                                        '''

                                '''
                                    For each transaction in the block, delete any matching transaction from the transaction pool
                                '''
                                MemoryPool.removeTransaction(transaction)
                                
                            chainHeadIndexBlock.chainWork = Bits.getChainworkFromBits(previousChainWork, bits)
                            chainHeadIndexBlock.previousHash = blockHash
                            chainHeadIndexBlock.gasLimit = blockGasLimit
                            chainHeadIndexBlock.height = blockHeight
                            self.index.set(self.CHAIN_HEAD_INDEX, chainHeadIndexBlock.serialize())
                        else:
                            blockChainWork = Bits.getChainworkFromBits(previousChainWork, bits)
                            chainHeadWork = chainHeadIndexBlock.chainWork
                            
                            hasNewMainChain = blockChainWork > chainHeadWork
                            
                            if hasNewMainChain:
                                '''
                                    For case 3, a side branch becoming the main branch:
                                '''
                            else:
                                '''
                                    For case 2, adding to a side branch, we don't do anything.
                                '''
                
                            if hasNewMainChain:
                                '''
                                    Find the fork block on the main branch which this side branch forks off of
                                '''
                                forkBlockHash = self.searchForkBlockHash(previousIndexBlock, chainHeadIndexBlock)
                                
                                '''
                                    Redefine the main branch to only go up to this fork block
                                    
                                    We will set new main chain head below
                                '''
                                
                                isNewMainChainValid = True
                                
                                '''
                                    For each block on the side branch, from the child of the fork block to the leaf, add to the main branch:
                                '''
                                prevBlock = self.getBlockByHash(block.previousHash)
                                while prevBlock.hash() != forkBlockHash:
                                    '''
                                        Do "branch" checks 3-11
                                    '''
                                    '''
                                        3) Transaction list must be non-empty
                                    '''
                                    if not self.blkValidator.verifyTransactionsNonEmpty(prevBlock):
                                        isNewMainChainValid = False
                                    
                                    '''
                                        4) Block hash must satisfy claimed nBits proof of work
                                    '''
                                    if not self.blkValidator.validateBlockBits(prevBlock.serializeHeader(), prevBlock.bits):
                                        isNewMainChainValid = False
                                    
                                    '''
                                        5) Block timestamp must not be more than two hours in the future
                                    '''
                                    if not self.blkValidator.verifyFutureTimestamp(prevBlock):
                                        isNewMainChainValid = False
                                        
                                    '''
                                        6) First transaction must be coinbase (i.e. only 1 input, with hash=0, n=-1), the rest must not be
                                    '''
                                    if not self.blkValidator.verifyInitialCoinbaseTransaction(prevBlock):
                                        isNewMainChainValid = False
                                        
                                    '''
                                        7) For each transaction, apply "tx" checks 2-4
                                            2) Make sure neither in or out lists are empty
                                            3) Size in bytes <= TRANSACTION_SIZE_LIMIT
                                            4) Each output value, as well as the total, must be in legal money range
                                    '''
                                    for transaction in prevBlock.transactions:
                                        if not self.txValidator.verifyInputOutputNonEmpty(transaction):
                                            isNewMainChainValid = False
                                        if not self.txValidator.verifyTransactionSizeLimit(transaction):
                                            isNewMainChainValid = False
                                        if not self.txValidator.verifyAllowedOutputValueRange(transaction):
                                            isNewMainChainValid = False
                                        
                                        '''
                                            8) For the coinbase (first) transaction, scriptSig length must be 2-100
                                        '''
                                        if not self.blkValidator.verifyCoinbaseWitnessLength(transaction):
                                            isNewMainChainValid = False
                                        
                                        '''
                                            9) Reject if sum of transaction sig opcounts > MAX_BLOCK_SIGOPS
                                        '''
                                        if not self.blkValidator.verifyMaxBlockSigOps(transaction):
                                            isNewMainChainValid = False
                                        
                                    '''
                                        10) Verify Merkle hash
                                    '''
                                    if not self.blkValidator.verifyMerkleHash(prevBlock):
                                        isNewMainChainValid = False
                                        
                                    '''
                                        Verify Witness hash
                                    '''
                                    if not self.blkValidator.verifyWitnessHash(prevBlock):
                                        isNewMainChainValid = False
                                        
                                    '''
                                        11) Check if prev block (matching prev hash) is in main branch or side branches. If not, add this to orphan blocks, 
                                        then query peer we got this from for 1st missing orphan block in prev chain; done with block
                                    '''
                                    if blockHash != Config.getBytesValue('GENESIS_BLOCK_HASH') and self.getBlockByHash(prevBlock.previousHash) == None:
                                        OrphanManager.addBlock(prevBlock)
                                        isNewMainChainValid = False
                                
                                    '''
                                        For all but the coinbase transaction, apply the following:
                                    '''
                                    if not self.blkValidator.verifyNonCoinbaseTransactions(prevBlock):
                                        isNewMainChainValid = False
                                    
                                    '''
                                        Reject if coinbase value > sum of block creation fee and transaction fees
                                    '''   
                                    if not self.blkValidator.verifyCoinbaseValue(prevBlock):
                                        isNewMainChainValid = False
                                    
                                    '''
                                        (If we have not rejected):
                                    '''
                                    if not isNewMainChainValid:
                                        break
                                    
                                    '''         
                                        For each transaction, "Add to wallet if mine"
                                    '''
                                        
                                    prevBlock = self.getBlockByHash(prevBlock.previousHash)
                                
                                '''
                                    If we reject at any point, leave the main branch as what it was originally, done with block
                                '''
                                if isNewMainChainValid:
                                    chainHeadIndexBlock.chainWork = blockChainWork
                                    chainHeadIndexBlock.previousHash = blockHash 
                                    chainHeadIndexBlock.gasLimit = blockGasLimit
                                    chainHeadIndexBlock.height = blockHeight
                                    self.index.set(self.CHAIN_HEAD_INDEX, chainHeadIndexBlock.serialize())
                                    
                                    '''
                                        For each block in the old main branch, from the leaf down to the child of the fork block:
                                    '''
                                    oldBlock = chainHeadBlock
                                    while oldBlock.hash() != forkBlockHash:
                                        '''
                                            For each non-coinbase transaction in the block:
                                        '''
                                        for transaction in oldBlock.transactions:
                                            if not transaction.isCoinbase():
                                                '''
                                                    Apply "tx" checks 2-9
                                                '''
                                                isTxValid = True
                                                
                                                '''
                                                    2) Make sure neither in or out lists are empty
                                                '''
                                                if not self.txValidator.verifyInputOutputNonEmpty(transaction):
                                                    isTxValid = False
                                                
                                                '''
                                                    3) Size in bytes <= TRANSACTION_SIZE_LIMIT
                                                '''
                                                if not self.txValidator.verifyTransactionSizeLimit(transaction):
                                                    isTxValid = False
                                                
                                                '''
                                                    4) Each output value, as well as the total, must be in legal money range
                                                '''
                                                if not self.txValidator.verifyAllowedOutputValueRange(transaction):
                                                    isTxValid = False
                                                
                                                '''
                                                    5) Make sure none of the inputs have hash=0, n=-1 (coinbase transactions)
                                                '''
                                                if not self.txValidator.verifyInputsNonCoinbase(transaction):
                                                    isTxValid = False
                                                
                                                '''
                                                    6) size in bytes >= 100[2]
                                                '''
                                                if not self.txValidator.verifyTransactionRequiredSize(transaction):
                                                    isTxValid = False
                                                
                                                '''
                                                    sig opcount <= 2[3]
                                                    3) The number of signature operands in the signature (no, that is not redundant) for standard transactions will never exceed two
                                                    7) Reject "nonstandard" transactions: scriptSig doing anything other than pushing numbers on the stack, 
                                                    or script not matching the two usual forms[4]
                                                '''
                                                if not self.txValidator.verifyAddress(transaction):
                                                    isTxValid = False
                                                if not self.txValidator.verifyExtraData(transaction):
                                                    isTxValid = False
                                                if not self.txValidator.verifyScript(transaction):
                                                    isTxValid = False
                                                if not self.txValidator.verifyWitness(transaction):
                                                    isTxValid = False
                                                
                                                '''
                                                    8) Reject if we already have matching tx in the pool,
                                                    except in step 8, only look in the transaction pool for duplicates, not the main branch
                                                '''
                                                if not self.txValidator.verifyTransactionDuplicateInPool(transaction):
                                                    isTxValid = False
                                                
                                                '''
                                                    9) For each input, if the referenced output exists in any other tx in the pool, reject this transaction
                                                '''
                                                if not self.txValidator.verifyTxOutputDuplicateInPool(transaction):
                                                    isTxValid = False
                                                
                                                '''
                                                    Add to transaction pool if accepted, else go on to next transaction
                                                '''
                                                if isTxValid:
                                                    MemoryPool.addSignedTransaction(transaction)

                                            outputIndex = 0
                                            for txOut in transaction.outputs:
                                                UXTO.removeUnspentTransactionCoin(Outpoint(transaction.hash(), outputIndex))
                                                outputIndex += 1

                                        oldBlock = self.getBlockByHash(oldBlock.previousHash)
                                    
                                    '''
                                        For each block in the new main branch, from the child of the fork node to the leaf:
                                    '''
                                    newMainBranchBlocks = []
                                        
                                    prevBlock = block
                                    while prevBlock.hash() != forkBlockHash:
                                        newMainBranchBlocks.insert(0, prevBlock)
                                        prevBlock = self.getBlockByHash(prevBlock.previousHash)
                                        
                                    for newMainBranchBlock in newMainBranchBlocks:
                                        newMainBranchBlockHash = newMainBranchBlock.hash()
                                        newMainBranchIndexBlock = None
                                        if newMainBranchBlockHash == blockHash:
                                            newMainBranchIndexBlock = chainHeadIndexBlock
                                        else:
                                            newMainBranchIndexBlock = self.getIndexBlockByHash(newMainBranchBlockHash)
                                        for transaction in newMainBranchBlock.transactions:
                                            for txIn in transaction.inputs:
                                                UXTO.removeUnspentTransactionCoin(txIn.outpoint)
                                            uxtoOutputs = []
                                            uxtoOutputs.extend(transaction.outputs)
                                            uxtoOutputs.extend(transaction.internalOutputs)
                                            txOutputSize = 0
                                            for txOut in uxtoOutputs:
                                                if txOut.store:
                                                    txOutputSize += 1
                                            outputIndex = 0
                                            for txOut in uxtoOutputs:
                                                UXTO.removeStaleUnspentTransactionScript(txOut)
                                                if txOut.store:
                                                    coin = Coin()
                                                    coin.output = txOut
                                                    coin.txOutputSize = txOutputSize
                                                    coin.height = newMainBranchIndexBlock.height
                                                    coin.coinbase = transaction.isCoinbase()
                                                    UXTO.addUnspentTransactionCoin(Outpoint(transaction.hash(), outputIndex), coin)
                                                    outputIndex += 1
                                                    '''
                                                        For each transaction, "Add to wallet if mine"
                                                    '''

                                            '''
                                                For each transaction in the block, delete any matching transaction from the transaction pool
                                            '''
                                            MemoryPool.removeTransaction(transaction)
                        '''
                            (If we have not rejected):
                        '''
                        self.storage.set(blockHashBytes, block.serialize())

                        blockHeightKey = "{0}{1}{2}".format(self.BLOCK_HEIGHT_KEY, '_', blockHeight)
                        blockHeightKey = DataType.serialize(blockHeightKey)
                        self.index.set(blockHeightKey, blockHashBytes)
                        
                        indexBlock = IndexBlock()
                        indexBlock.chainWork = Bits.getChainworkFromBits(previousChainWork, bits)
                        indexBlock.previousHash = previousHash 
                        indexBlock.gasLimit = blockGasLimit
                        indexBlock.height = blockHeight
                        self.index.set(blockHashBytes, indexBlock.serialize())
        
                        '''
                            Relay block to our peers
                        '''
                        Sync.inv(InventoryType.BLOCK, blockHash)
                    
                    '''
                        For each orphan block for which this block is its prev, run all these steps (including this one) recursively on that orphan
                    '''
                    self.syncOrphanBlocks()
                    
                    return True
            finally:
                self.releaseBlockLock()
        '''
            For each orphan block for which this block is its prev, run all these steps (including this one) recursively on that orphan
        '''
        self.syncOrphanBlocks()
            
        '''     
            If we rejected, the block is not counted as part of the main branch
        '''
        return False