def parsear(cls, s): '''Toma un stream de bytes y parsea el bloque merkle. Devuelve un objeto Bloque Merkle''' # s.read(n) leerá n bytes desde el stream # versión - 4 bytes, little endian, interpretalo como int versión = little_endian_a_int(s.read(4)) # bloque_previo - 32 bytes, little endian (usa [::-1] para darle la vuelta) bloque_previo = s.read(32)[::-1] # raíz_merkle - 32 bytes, little endian (usa [::-1] para darle la vuelta) raíz_merkle = s.read(32)[::-1] # timestamp - 4 bytes, little endian, interpretalo como int timestamp = little_endian_a_int(s.read(4)) # bits - 4 bytes bits = s.read(4) # nonce - 4 bytes nonce = s.read(4) # número total de transacciones (4 bytes, little endian) total = little_endian_a_int(s.read(4)) # el número de hashes es un varint num_txs = read_varint(s) # inicializa el array de hashes hashes = [] # haz un bucle tantas veces como el número de hashes for _ in range(num_txs): # cada hash es 32 bytes, little endian hashes.append(s.read(32)[::-1]) # obtén la longitud del campo flags como un varint longitud_flags = read_varint(s) # lee el campo flags flags = s.read(longitud_flags) # inicializa la clase return cls(versión, bloque_previo, raíz_merkle, timestamp, bits, nonce, total, hashes, flags)
def parsear(cls, s): # obtén la longitud del campo completo longitud = read_varint(s) # inicializa el array de cosas cosas = [] # inicializa el número de bytes que hemos leído a 0 contador = 0 # haz un bucle hasta que leamos la longitud en bytes while contador < longitud: # obtén el byte actual actual = s.read(1) # aumenta los bytes que hemos leído contador += 1 # convierte el byte actual a un entero byte_actual = actual[0] # si el byte actual está entre 1 y 75 ambos incluidos if byte_actual >= 1 and byte_actual <= 75: # tenemos una cosa como n para ser el byte actual n = byte_actual # añade los siguientes n bytes como una cosa cosas.append(s.read(n)) # aumenta el contador en n contador += n else: # tenemos un op code. establece el byte actual a op_code op_code = byte_actual # añade el op_code a la lista de cosas cosas.append(op_code) return cls(cosas)
def parsear(cls, stream): # el número de cabeceras está en un varint num_cabeceras = read_varint(stream) # inicializa el array de bloques bloques = [] # haz un bucle tantas veces como número de cabeceras for _ in range(num_cabeceras): # añade un bloque al array de bloques a base de parsear el stream bloques.append(Bloque.parsear(stream)) # lee el siguiente varint (num_txs) num_txs = read_varint(stream) # num_txs debería ser 0 o dar un RuntimeError if num_txs != 0: raise RuntimeError('el número de txs no es 0') # devuelve una instancia de la clase return cls(bloques)
def parsear(cls, s): '''Toma un stream de bytes y parsea el tx_output al comienzo devuelve un objeto TxOut ''' # s.read(n) devolverá n bytes # la cantidad es 8 bytes, little endian, interprétalo como int cantidad = little_endian_a_int(s.read(8)) # script_pubkey es un campo variable (la longitud seguida de la fecha) # obtén la longitud usando read_varint(s) script_pubkey_longitud = read_varint(s) script_pubkey = s.read(script_pubkey_longitud) # devuelve una instancia de la clase (cls(...)) return cls(cantidad, script_pubkey)
def parsear(cls, s, testnet=False): '''Toma un stream de bytes y parsea la transacción al comienzo devuelve un objeto Tx ''' # s.read(n) devolverá n bytes # la versión tiene 4 bytes, little-endian, interprétalo como int versión = little_endian_a_int(s.read(4)) # num_inputs es un varint, usa read_varint(s) num_inputs = read_varint(s) # cada input necesita parseo inputs = [] for _ in range(num_inputs): inputs.append(TxIn.parsear(s)) # num_outputs es un varint, usa read_varint(s) num_outputs = read_varint(s) # cada output necesita parseo outputs = [] for _ in range(num_outputs): outputs.append(TxOut.parsear(s)) # locktime es 4 bytes, little-endian locktime = little_endian_a_int(s.read(4)) # devuelve una instancia de la clase (cls(...)) return cls(versión, inputs, outputs, locktime, testnet=testnet)
def parsear(cls, s): '''Toma un stream de bytes y parsea la transacción al principio devuelve un objeto Tx ''' # s.read(n) devolverá n bytes # la version tiene 4 bytes, little-endian, interprétalo como int version = little_endian_a_int(s.read(4)) # num_inputs es un varint, usa read_varint(s) num_inputs = read_varint(s) # cada input necesita parseo inputs = [] for _ in range(num_inputs): inputs.append(TxIn.parsear(s)) # num_outputs es un varint, usa read_varint(s) num_outputs = read_varint(s) # cada output necesita ser parseado outputs = [] for _ in range(num_outputs): outputs.append(TxOut.parsear(s)) # locktime is 4 bytes, little-endian locktime = little_endian_a_int(s.read(4)) # return an instance of the class (cls(...)) return cls(version, inputs, outputs, locktime)
def parsear(cls, s): '''Toma un byte stream y parsea el tx_input al comienzo devuelve un objeto TxIn ''' # s.read(n) devolverá n bytes # tx_previa es 32 bytes, little endian tx_previa = s.read(32)[::-1] # indice_previo es 4 bytes, little endian, interpreta como int indice_previo = little_endian_a_int(s.read(4)) # script_sig es un campo variable (longitud seguida de los datos) # obtén la longitud usando read_varint(s) script_sig_longitud = read_varint(s) script_sig = s.read(script_sig_longitud) # sequence es 4 bytes, little-endian, interprétalo como int sequence = little_endian_a_int(s.read(4)) # devuelve una instancia de la clase (cls(...)) return cls(tx_previa, indice_previo, script_sig, sequence)
def parsear(cls, s): '''Toma un stream de bytes y parsea el tx_input al comienzo devuelve un objeto TxIn ''' # s.read(n) devolverá n bytes # prev_tx es 32 bytes, little endian prev_tx = s.read(32)[::-1] # prev_index es 4 bytes, little endian, interprétalo como int prev_index = little_endian_a_int(s.read(4)) # script_sig es un campo variable (longitud seguida de los datos) # obtén la longitud usando read_varint(s) script_sig_longitud = read_varint(s) script_sig = s.read(script_sig_longitud) # sequence tiene 4 bytes, little-endian, interprétalo como int sequence = little_endian_a_int(s.read(4)) # devuelve una instancia de la clase (cls(...)) return cls(prev_tx, prev_index, script_sig, sequence)