Executando verificação de segurança...
Em resposta a [Não disponível]
1

Que interessante! Essa postagem está ganhando pontos negativos "numa velocidade..." (o usuário que a postou está perdendo Tabcoins). Qual seria o motivo de estar sendo negativada com tanta frequência?

Outro detalhe diz respeito à pontuação. No momento em que marcavada -10, o Alt-text indicava -12 | +1 (8% achou relevante). Esta totalização não deveria ser -11 em vez de -10?

Carregando publicação patrocinada...
2

Os conteúdos no TabNews podem iniciar com 1 ou 0 TabCoin. Nesse caso, foi 1 - 12 + 1 = -10, sendo Valor inicial - Negativos + Positivos.

1

Valeu pela explicação, rafael. Acho que agora estou entendendo o motivo deste 1 ou 0 para pontuação inicial (estímulo) do conteúdo.

Fazendo uma busca no repositório do Tabnews, o arquivo pages/faq/index.public.js traz uma breve explicação como funciona esse estímulo inicial.

Como ganhar TabCoins?
As formas de ganho de TabCoins são:

 - **Criando um conteúdo:** existe um algoritmo que leva em consideração os TabCoins dos seus conteúdos mais recentes para definir quantos TabCoins você ganhará ao criar um novo conteúdo.
 - **Recebendo votos positivos:** quando outro usuário avalia positivamente seu conteúdo.
 - **Recompensa diária:** você pode ganhar TabCoins ao acessar o TabNews pelo menos uma vez no dia. Existe um algoritmo que leva em consideração as qualificações dos seus conteúdos mais recentes e também a quantidade de TabCoins que você possui. Quanto melhor avaliados forem seus conteúdos e menos TabCoins você possuir, mais receberá na recompensa diária.
2

Essa pergunta do FAQ é sobre TabCoins do usuário.

O TabCoin inicial do conteúdo tem a ver com a "relevância" dele, que hoje é uma verificação simples (veja o código aqui). Se você tentar criar um comentário ou publicação no site do TabNews com uma única palavra, por exemplo, receberá um aviso assim:

Tem certeza que deseja publicar essa mensagem curta? ⚠ Atenção: Pedimos encarecidamente que leia isso antes de fazer essa publicação.

Se escolher publicar, o conteúdo não terá o TabCoin inicial (começará em 0). O objetivo é desmotivar conteúdos muito rasos e que não precisariam ser publicados, como um comentário de agradecimento Valeu!.

Então, o TabCoin inicial é como um voto de confiança do TabNews no conteúdo publicado. No início do TabNews, essa verificação não existia, então todo conteúdo recebia o TabCoin inicial.

2

Valeu novamente, rafael, por indicar o código específico que faz essa criação de moedas.

Achei útil acompanhar esta postagem que estava sendo drasticamente negativada para entender como os Tabcoins/Tabcash são criados, debitados. No código fonte que indicou é possível entender o mecanismo. Infelizmente a postagem original desapareceu, contudo, pude ver em tempo algo correlacionado na Rede de Qualificações (últimas 300).

image
Timestamp: 20241014T145410Z

Estou quase certo de que o sistema do Tabnews mantém um rastreio de cada tipo de moeda criada e trocada entre pares, como se cada uma delas tivesse um número de série (UUID ou SN). Sabemos que parte dos Tabcoins foram criados como recompensa para os primeiros usuários que acreditaram na ideia da plataforma, compartilhando ideias, sugestões e alguns trabalhando pesado nos bastidores. Atualmente, um novo usuário entra na rede Tabnews com 0/0, ganhando parte com suas próprias publicações de valor e upvotes (distingue-se Tabcoins e Tabcash segundo a documentação). Se fosse permitido, eu faria um scrap para contabilizar toda moeda do ecossistema, pois da forma que estou entendendo, não há limites para criação de riqueza.

Para terminar, noto que a base de informações de tráfego de moeda (entre o gerador do Tabnews e usuários bem como entre usuários) é útil para fazer algumas análises, entender os mecanismos humanos por trás dessa rede de relacionamentos. Parabéns para quem teve a ideia de colocar a constelação de qualificações :).

3

Você pode obter os dados pela API, respeitando o rate limit, mas acho que "contabilizar toda moeda do sistema" é bastante coisa. Não sei uma forma mais adequada, mas você pode criar um issue no repositório. É melhor do que discutir aqui, porque as informações ficam mais fáceis de encontrar, permitindo que outros interessados vejam também.

Como estamos falando sobre análises, vou compartilhar uma que já fizeram aqui no TabNews: Leaderboard Tabnews: Reconhecendo a Excelência na Comunidade.

pois da forma que estou entendendo, não há limites para criação de riqueza.

Não há. Se o sistema ficar desequilibrado, isto é, muitos votos e muitos TabCoins sendo gerados, precisaremos realizar um ajuste manual para "dificultar" a geração. O Felipe Barso (aprendendofelipe) é quem mais trabalhou nesse código/algoritmo.

Parabéns para quem teve a ideia de colocar a constelação de qualificações :).

Também foi o Felipe Barso 👏

2

Grato pela dica, rafael. Devo abrir uma issue no repositório do Tabnews no Github assim que ele voltar ao ar (offline para mim aqui, mas tudo ok para eles). Com certeza será muito melhor finalizar a discussão por lá.

Agradeço por sua atenção, dedicando seu tempo na elaboração de cada resposta e indicação de outros links e experimentos realizados para ajudar sanar minhas dúvidas.

0

Área de rascunho

Por favor, artistas, não pixar 🎨 🔫
Esta é uma postagem sobre postagem, não gerando Tabcoins propositalmente como definido nas regras do algoritmo do Tabnews.

Este conteúdo não tem valor informativo e o espaço é utilizado apenas para criar e testar novas publicações, sua aparência quando publicadas definitivamente no portal.

0

É possível incluir SVG inline em postagens no Tabnews? O formato vetorial para gráficos é mais eficiente e faz parte do markdown, independente de um link para imagens externas. Imagens complexas, como fotos, ainda precisam do armazanamento em formato raster.

<svg
  xmlns="http://www.w3.org/2000/svg"
  width="142px"
  height="23px"
  fill="none"
>
<foreignObject width="142px" height="23px">
<div xmlns="http://www.w3.org/1999/xhtml">
<style>
.pill{
    display: flex;
    background-color: transparent;
    width: max-content;
    font-family: 'Open Sans', sans-serif;
    border-radius: 4px;
}
.pillLabel{
    display: flex;
    width: max-content;
    padding: 4px;
    padding-left: 8px;
    padding-right: 8px;
    border-top-left-radius: 4px;
    border-bottom-left-radius: 4px;
    font-size: 12px;
    color: rgb(254 215 170);
    background-color: rgb(136 19 55);
}
.pillIcon{
  margin-right: 4px;
  width: 14px;
  height: 14px;
}
.pillCount{
    color: rgb(136 19 55);
    background-color: rgb(254 215 170);
    width: max-content;
    border-top-right-radius: 4px;
    border-bottom-right-radius: 4px;
    padding: 4px;
    padding-left: 8px;
    padding-right: 8px;
    letter-spacing: 1px;
    font-size: 12px;
}

@keyframes heartbeat {
  0% {
      transform: scale(1);
  }
  25% {
      transform: scale(1.1);
  }
  40% {
      transform: scale(1);
  }
  60% {
      transform: scale(1.1);
  }
  100% {
      transform: scale(1);
  }
}

.heartbeat {
  display: inline-block;
  animation: heartbeat 1.5s infinite;
  transform-origin: center;
  image-rendering: -webkit-optimize-contrast;
  image-rendering: crisp-edges;
  backface-visibility: hidden;
  will-change: transform;
}

</style>
<div class="pill">
<span class="pillLabel">
<svg xmlns="http://www.w3.org/2000/svg" class="pillIcon heartbeat" fill="none" viewBox="0 0 24 24" stroke="currentColor">
  <path name="bar" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 19v-6a2 2 0 00-2-2H5a2 2 0 00-2 2v6a2 2 0 002 2h2a2 2 0 002-2zm0 0V9a2 2 0 012-2h2a2 2 0 012 2v10m-6 0a2 2 0 002 2h2a2 2 0 002-2m0 0V5a2 2 0 012-2h2a2 2 0 012 2v14a2 2 0 01-2 2h-2a2 2 0 01-2-2z" />
</svg>
Profile Views</span>
<span class="pillCount" > 42 </span>
</div>
</div>
</foreignObject>
</svg>
0

O que são as constantes mágicas encontradas no algoritmo SHA-256?

SHA-256 é uma das funções hash que faz parte da família SHA-2 (sucessora da família SHA-1) definidas no U.S. National Institute of Standards and Technology - Federal Information Processing Standards Publication (FIPS PUB) 180-4 update 1 publicado em agosto de 2015 (sob revisão após receber sugestões) e previamente definido nos padrões anteriores FIPS PUB 180, FIPS PUB 180-1, FIPS PUB 180-2, 180-2 update 1, FIPS PUB 180-3, FIPS PUB 180-4. Outras funções da mesma família são: SHA-224, SHA-256, SHA-384, SHA-512, SHA-512/224, SHA-512/256, sendo o valor numérico o número de bits resultante do resumo ou digest.

Existem diferentes implementações (1, 2, 3) do algoritmo SHA-256, contendo 72 constantes hardcoded para eficiência e padronização. Tais constantes desempenham um papel crucial em determinadas funções internas, sendo 8 delas, denominadas H_j, participantes na etapa de inicialização dos valores de hash e outras 64 constantes, denominadas K_i, participantes na etapa de compressão.

---------------------------------- K ----------------------------------   --- H ---
428A2F98 71374491 B5C0FBCF E9B5DBA5 3956C25B 59F111F1 923F82A4 AB1C5ED5    6A09E667
D807AA98 12835B01 243185BE 550C7DC3 72BE5D74 80DEB1FE 9BDC06A7 C19BF174    BB67AE85
E49B69C1 EFBE4786 0FC19DC6 240CA1CC 2DE92C6F 4A7484AA 5CB0A9DC 76F988DA    3C6EF372
983E5152 A831C66D B00327C8 BF597FC7 C6E00BF3 D5A79147 06CA6351 14292967    A54FF53A
27B70A85 2E1B2138 4D2C6DFC 53380D13 650A7354 766A0ABB 81C2C92E 92722C85    510E527F
A2BFE8A1 A81A664B C24B8B70 C76C51A3 D192E819 D6990624 F40E3585 106AA070    9B05688C
19A4C116 1E376C08 2748774C 34B0BCB5 391C0CB3 4ED8AA4A 5B9CCA4F 682E6FF3    1F83D9AB
748F82EE 78A5636F 84C87814 8CC70208 90BEFFFA A4506CEB BEF9A3F7 C67178F2    5BE0CD19
Código elaborado para cálculo das 72 constantes
echo "" | awk --sandbox '{
    j = 0;  # Inicializacao do indice para constantes H
    
    # Numeros primos de 2 a 317
    primes = "  2,   3,   5,   7,  11,  13,  17,  19,  23,  29,  31,  37,  41,"\
             " 43,  47,  53,  59,  61,  67,  71,  73,  79,  83,  89,  97, 101,"\
             "103, 107, 109, 113, 127, 131, 137, 139, 149, 151, 157, 163, 167,"\
             "173, 179, 181, 191, 193, 197, 199, 211, 223, 227, 229, 233, 239,"\
             "241, 251, 257, 263, 269, 271, 277, 281, 283, 293, 307, 311, 313 ";
    
    n = split(primes, p, ",");  # Transcreve para vetor os números primos dados
    # Imprime um cabecalho
    printf("---------------------------------- K ");
    printf("----------------------------------   --- H ---\n");
    
    for(i = 1; i = 64; i++) {
        # Calcula e imprime as constantes K( 1) até K(64)
        c = p[i]^(1/3); k = int(2^32*(c-int(c))); printf("%08X ", k);
        if(!(i%8)) {
            j++; 
            # Calcula e imprime as constantes H(1) até H(8)
            b = p[j]^(1/2); h = int(2^32*(b - int(b))); printf("   %08X\n", h);
         };
    }
}'

Mas, qual é a origem, o significado e o motivo destas constantes?

Ao utilizar as partes fracionárias das raízes cúbicas dos 64 primeiros números primos (NIST.FIPS.180-4, pag. 11) para geração das constantes K e utilizar as partes fracionárias das raízes quadradas dos 8 primeiros números primos (NIST.FIPS.180-4, pag. 15) para geração das constantes H, cria-se, desta forma, um conjunto de constantes que tornam a função hash resistente a ataques, garantindo um comportamento complexo e menos previsível. Para obter as constantes, aquelas partes fracionárias são então multiplicadas por 2^32, os resultados truncados para inteiros e então impressos na base numérica hexadecimal. Tais valores são então facilmente obtidos de maneira determinística e, para que haja consistência das saídas de hash em diferentes implementações do algoritmo, tais valores devem ser mantidos fixos. Essas constantes mágicas usadas no algoritmo de hash SHA-256 proporcionam uma não-linearidade para a função hash.

Aplicações do SHA-256

SHA-256 é amplamente utilizada como função criptográfica de hash, produzindo uma saída de 256 bits independente do número de bytes fornecidos na sua entrada (um simples caractere ou arquivos inteiros). Outra aplicação relevante é no algoritmo de mineração de um dos ativos digitais mais conhecidos, onde se aplica a função duas vezes, ou seja, sha256(sha256(conteúdo)) e por isso às vezes é denominada sha256d.

Por que sha256(sha256(conteúdo))?

O Bitcoin encadeia o algoritmo de hash SHA-256 duas vezes no processo de criação de um hash para um determinado bloco, especificamente ao cabeçalho do bloco. O cabeçalho do bloco inclui dados importantes como o hash do bloco anterior, a estampa de hora (timestamp), o nonce (um número usado uma vez) entre outros elementos.

Estrutura de um cabeçalho

image

O duplo hash resultante é uma representação compacta do estado de todo o bloco e é usado no mecanismo de prova de trabalho (proof of work), onde os mineradores competem para encontrar um hash que seja inferior a um determinado limite alvo denominado difficult.

O duplo hash serve a vários propósitos:

  • Segurança aprimorada: Ao fazer hash dos dados duas vezes, o Bitcoin adiciona uma camada adicional de segurança. Embora o SHA-256 já seja considerado seguro, o hash duplo torna ainda mais difícil para os "invasores" encontrarem colisões (dois dados diferentes que produzem o mesmo hash) ou pré-imagens (encontrar uma entrada que faz hash para uma saída específica).

  • Saída Determinística: O uso de SHA-256 duplo garante que a saída seja determinística, o que significa que a mesma entrada sempre produzirá a mesma saída. Ao aplicar a mesma função hash duas vezes, quaisquer pequenas alterações na entrada levarão a saídas hash significativamente diferentes.

  • Resistência a certos ataques: o hash duplo pode mitigar certos tipos de ataques, especificamente aqueles que visam a primeira camada do processo de hash. Se um invasor puder interferir (influenciar) a entrada do primeiro hash, deverá também precisará lidar com o segundo hash, tornando-o mais complexo e demorado.

  • Consistência do comprimento de saída: Hashing duas vezes garante um comprimento de saída consistente, o que é crucial para funções criptográficas. Mesmo que a primeira função hash tivesse características diferentes, a segunda camada impõe um comprimento e estrutura de saída uniformes.

Funções hash são construídas de maneira que teoricamente não seja possível reverter o processo a partir das saídas, ou seja, recriar uma entrada (um arquivo) a partir de seu hash. Entretanto, hash de mensagens curtas ou mesmo arquivos estruturados, podem ser revertidos a partir de ataques via força bruta como rainbow tables.


Fontes consultadas...

http://csrc.nist.gov/publications/fips/fips180-3/fips180-3_final.pdf
https://csrc.nist.gov/publications/fips#fips180-4
https://datatracker.ietf.org/doc/html/rfc6234
https://eprint.iacr.org/2011/565.pdf

http://www.hashcash.org/papers/hashcash.pdf
https://bitcoin.org/bitcoin.pdf
https://armantheparman.com/sha256
https://armantheparman.com/dicev1

0

RASCUNHO - Arte em blocos de criptoativo

No começo de 2024, surgiu uma arte num bloco de um dos criptoativos mais conhecidos. A criação foi realizada pela MaraPool explorando algumas possibilidades já que detém seu próprio pool de mineração. Como as transações dentro do bloco podem ser rearranjadas conforme o minerador desejar, se o mesmo for consolidado será permanentemente registrado na blockchain. Agora, quando visualizadas numa matriz considerando o valor das taxas individuais, apresentam claramente um logotipo como mostra a imagem seguinte.

image
Fonte: mempool.space

Esta proeza está permanentemente registrada no bloco 836361


inclusão de arquivos dentro do bloco

Cada bloco comporta aproximadamente 4000 transações individuais de tamanho reduzido...

CenárioTamanho Médio de TransaçãoTamanho Máximo do BlocoMáximo de Transações por Bloco
Bloco tradicional (sem SegWit)250 bytes1MB (1.000.000 bytes)≈ 4.000 transações
Bloco otimizado com SegWit150 bytes4MB (4.000.000 bytes)≈ 26.666 transações
CampoTamanhoFinalidadeDescrição
Versão da Transação4 bytesIdentificação de versãoIndica o formato da transação
Contagem de EntradasVariávelNúmero de entradasDefine quantas entradas serão usadas na transação
Entrada 1Fonte de fundos
- Hash da Transação32 bytesHash da transação anteriorIdentifica a origem dos bitcoins
- Índice da Saída4 bytesÍndice da saída anteriorRefere-se a qual saída da transação anterior
- ScriptSigVariávelAssinatura digitalProva de que o remetente tem a chave para gastar
- Número de Sequência4 bytesAtualização de bloqueioPara operações que envolvem controle temporal
Contagem de SaídasVariávelNúmero de saídasDefine quantas saídas essa transação terá
Saída 1Destino dos fundos
- Valor8 bytesQuantidade de satoshisQuantidade de bitcoins a ser enviada
- ScriptPubKeyVariávelCondições para gastar fundosDefine as regras para gastar os bitcoins
Locktime4 bytesTempo de bloqueioData/bloco em que a transação pode ser confirmada

Cerca de um ano antes, o bloco 774628 teve a inclusão de uma imagem JPG (arquivo com , tornando-a uma data cujo marco está permanente dentro do maior bloco do bitcoin. A imagem original pode ser visualizada a seguir.

![image](https://ordinals.com/content/0301e0480b374b32851a9462db29dc19fe830a7f7d7a88b81612b9d42099c0aei0 =400x400)
Fonte: aqui

Para os leitores céticos fica a sugestão baixar a transação completa e fazer a extração dos cerca de 4 MB que compõem o arquivo JPEG.

Mais detalhes, vejas as matérias que veicularam na época

Qual deverá ser a próxima proeza?

0

RASCUNHO - É possível se livrar dos webcrawlers?


Conteúdo para ser publicado em breve.

Diferentes publicações mostram como baixar o conteúdo estático de um website por completo, usando recursos disponíveis na linha de comando Linux, como wget, curl entre outras possíveis opções programadas em Python, Perl etc.

user_agent="Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/129.0.0.0 Safari/537.36"

wget --verbose --mirror --no-parent --continue --page-requisites \
     --adjust-extension --convert-links --no-clobber --timestamping \
     --server-response --limit-rate=10k --wait=10 --random-wait \
     --no-cache --user-agent="${user_agent}" --no-check-certificate <website.address>

Mas existe alguma maneira de se defender dessa prática quando a mesma se torna nociva para o servidor, aumentando a carga para um propósito realizado por não-humanos? Contratar um proxy que implemente desafios (CAPTCHA) pode ser uma solução.

Mas será que é possível criar uma solução independente de proxy? E se a página web fosse dinâmica, ou seja, montada em tempo de carga usando somente javascript e uma conexão via websocket seguro com o servidor? Por meio do websocket o Javascript obtém o conteúdo a ser montado na página no lado do cliente. Tais recursos dinâmicos ainda não são interpretados pelos crawlers burros.


Esta ideia é possível e o fluxo básico para realizar isso envolve os seguintes passos:

1. Conexão WebSocket com o Servidor

A primeira etapa é estabelecer uma conexão WebSocket com o servidor. O WebSocket permite uma comunicação bidirecional em tempo real, ideal para atualizar e carregar dados dinâmicos.

const socket = new WebSocket('ws://servidor.com:porta');

// Quando a conexão é aberta
socket.onopen = function(event) {
    console.log("Conectado ao servidor via WebSocket.");
    socket.send("Solicitando dados para a página");
};

// Quando uma mensagem é recebida do servidor
socket.onmessage = function(event) {
    const data = JSON.parse(event.data);
    montarPagina(data);
};

// Tratamento de erros
socket.onerror = function(error) {
    console.log("Erro na conexão WebSocket:", error);
};

// Quando a conexão é fechada
socket.onclose = function(event) {
    console.log("Conexão WebSocket fechada.");
};

2. Recebendo o Conteúdo

Quando o servidor envia os dados, eles podem estar no formato JSON (ou outro formato estruturado). Ao receber os dados, o JavaScript no lado do cliente pode processar e montar o conteúdo da página dinamicamente.

3. Construção da Página no Lado do Cliente

Uma vez que os dados são recebidos, você pode manipulá-los e gerar o conteúdo da página dinamicamente usando DOM (Document Object Model) ou técnicas como innerHTML.

Exemplo simples de código:

function montarPagina(data) {
    const body = document.body;

    // Criar elementos de acordo com os dados recebidos
    const titulo = document.createElement('h1');
    titulo.textContent = data.titulo;

    const conteudo = document.createElement('p');
    conteudo.textContent = data.conteudo;

    // Adicionar os elementos na página
    body.appendChild(titulo);
    body.appendChild(conteudo);
}

4. Servidor WebSocket

Do lado do servidor, você precisa configurar um serviço WebSocket que envie os dados requisitados ao cliente. O servidor deve manter a conexão aberta enquanto for necessário para enviar novos dados dinamicamente ou quando solicitado.

Um exemplo básico de servidor WebSocket em Node.js:

const WebSocket = require('ws');
const wss = new WebSocket.Server({ port: 8080 });

wss.on('connection', (ws) => {
    console.log('Cliente conectado');

    ws.on('message', (message) => {
        console.log('Mensagem recebida: %s', message);
        const dadosPagina = {
            titulo: "Bem-vindo à minha página!",
            conteudo: "Este conteúdo foi carregado dinamicamente via WebSocket."
        };
        ws.send(JSON.stringify(dadosPagina));
    });

    ws.on('close', () => {
        console.log('Cliente desconectado');
    });
});

Benefícios:

  • Atualização em tempo real: O WebSocket permite que o servidor envie atualizações em tempo real ao cliente sem a necessidade de recarregar a página.
  • Eficiência: Reduz a sobrecarga de requisições HTTP/HTTPS repetidas, já que a conexão WebSocket permanece aberta.
  • Experiência do usuário: O conteúdo pode ser carregado e atualizado dinamicamente conforme necessário.

Desafios:

  • Gestão de estados e reconexão: É necessário garantir que o cliente possa lidar com a desconexão e reconectar caso a comunicação falhe.
  • Segurança: A comunicação via WebSocket deve ser protegida para evitar ataques como Man-in-the-Middle (usando WSS em vez de WS).

Essa abordagem é útil para aplicações em tempo real ou dinâmicas, como sistemas de votação, chat ou dashboards de monitoramento em tempo real. Por ser um conteúdo dinâmico, os crawlers burros não conseguirão baixar o conteúdo, mas apenas a página principal contendo o mínimo, básico para que o navegador (Chrome, Firefox, Opera etc.) consiga iniciar a carga e montagem da página dinamicamente.

[Keywords: crawler, defeat, dynamic page, javascript, websocket] // for [index|filter]ing purposes

0

RASCUNHO: WhatsApp Web com nova interface

Na última quarta-feira (), ao abrir o WhatsApp Web, notei uma nova janela de pareamento. Será uma novidade ou um ataque man in middle?

image

Caso alguém também notou essa nova janela e possa compartilhar a experiência, enriquecerá esse achado.

0

Rascunho - O que são Merkle trees?

merkle_blk75000.py

# Uses      :  python 2
# Dependency:  hashlib
import hashlib

# Hash pairs of items recursively until a single value is obtained
def merkle(hashList):
    if len(hashList) == 1:
        return hashList[0]
    newHashList = []
    # Process pairs. For odd length, the last is skipped
    for i in range(0, len(hashList)-1, 2):
        newHashList.append(hash2(hashList[i], hashList[i+1]))
    if len(hashList) % 2 == 1: # odd, hash last item twice
        newHashList.append(hash2(hashList[-1], hashList[-1]))
    return merkle(newHashList)

def hash2(a, b):
    # Reverse inputs before and after hashing
    # due to big-endian / little-endian nonsense
    a1 = a.decode('hex')[::-1]
    b1 = b.decode('hex')[::-1]
    h = hashlib.sha256(hashlib.sha256(a1+b1).digest()).digest()
    return h[::-1].encode('hex')

# https://blockexplorer.com/rawblock/0000000000000000e067a478024addfecdc93628978aa52d91fabd4292982a50  (outdated)
# wget -qO- https://mempool.space/api/block/00000000000ace2adaabf1baf9dc0ec54434db11e9fd63c1819d8d77df40afda/txids
# expected Merkle Root
# wget -qO- https://mempool.space/api/block/75000
# ed385c2dbc69aa24965909c7d9d11bbd99faa085cb4ec17865d9b557ffb3a68a
#
txHashes = ["5277cf3790381c2cc2b071038d8c35b3b601207c92f8aec15978a5f01ecf8319",
"182c2ed191a35ea496ce84c42d8beee6f9d82b9f063de2e45a54692bb043696a",
"707e86e5e2356cb53a2edf0be391d56cfc998bcfa05a13a5772ef474c5eba105",
"711e15a9a819de4d1269d71de9744dedf9b6c32bba36bb0196f003f6507d4bb4",
"8c1e409484e30c205698647753cca07d826c34756773bd0432202487f28e2d54",
"abfaf8e7ad6241ca5161e517baade1275cf6333d0d118d221f894813bacb4f78"]

print merkle(txHashes)

Fontes