Inside Bitcoin
Opening the selected file…
Opening the selected file…
The code behind the network, with room to understand it.
Release published 2026-10-28 · Snapshot fetched 2026-11-01. Latest stable release at fetch time; development branches and Git history are excluded. Only the selected code window and visible folders load here.
1// Copyright (c) 2022-present The Bitcoin Core developers2// Distributed under the MIT software license, see the accompanying3// file COPYING or http://www.opensource.org/licenses/mit-license.php.4//5// Based on https://github.com/noloader/SHA-Intrinsics/blob/master/sha256-arm.c,6// Written and placed in public domain by Jeffrey Walton.7// Based on code from ARM, and by Johannes Schneiders, Skip Hovsmith and8// Barry O'Rourke for the mbedTLS project.9// Variant specialized for 64-byte inputs added by Pieter Wuille.11#ifdef ENABLE_ARM_SHANI13#include <array>14#include <cstdint>15#include <cstddef>16#include <arm_neon.h>18namespace {19alignas(uint32x4_t) static constexpr std::array<uint32_t, 64> K =20{210x428A2F98, 0x71374491, 0xB5C0FBCF, 0xE9B5DBA5,220x3956C25B, 0x59F111F1, 0x923F82A4, 0xAB1C5ED5,230xD807AA98, 0x12835B01, 0x243185BE, 0x550C7DC3,240x72BE5D74, 0x80DEB1FE, 0x9BDC06A7, 0xC19BF174,250xE49B69C1, 0xEFBE4786, 0x0FC19DC6, 0x240CA1CC,260x2DE92C6F, 0x4A7484AA, 0x5CB0A9DC, 0x76F988DA,270x983E5152, 0xA831C66D, 0xB00327C8, 0xBF597FC7,280xC6E00BF3, 0xD5A79147, 0x06CA6351, 0x14292967,290x27B70A85, 0x2E1B2138, 0x4D2C6DFC, 0x53380D13,300x650A7354, 0x766A0ABB, 0x81C2C92E, 0x92722C85,310xA2BFE8A1, 0xA81A664B, 0xC24B8B70, 0xC76C51A3,320xD192E819, 0xD6990624, 0xF40E3585, 0x106AA070,330x19A4C116, 0x1E376C08, 0x2748774C, 0x34B0BCB5,340x391C0CB3, 0x4ED8AA4A, 0x5B9CCA4F, 0x682E6FF3,350x748F82EE, 0x78A5636F, 0x84C87814, 0x8CC70208,360x90BEFFFA, 0xA4506CEB, 0xBEF9A3F7, 0xC67178F2,37};38}40namespace sha256_arm_shani {41void Transform(uint32_t* s, const unsigned char* chunk, size_t blocks)42{43uint32x4_t STATE0, STATE1, ABCD_SAVE, EFGH_SAVE;44uint32x4_t MSG0, MSG1, MSG2, MSG3;45uint32x4_t TMP0, TMP2;47// Load state48STATE0 = vld1q_u32(&s[0]);49STATE1 = vld1q_u32(&s[4]);51while (blocks--)52{53// Save state54ABCD_SAVE = STATE0;55EFGH_SAVE = STATE1;57// Load and convert input chunk to Big Endian58MSG0 = vreinterpretq_u32_u8(vrev32q_u8(vld1q_u8(chunk + 0)));59MSG1 = vreinterpretq_u32_u8(vrev32q_u8(vld1q_u8(chunk + 16)));60MSG2 = vreinterpretq_u32_u8(vrev32q_u8(vld1q_u8(chunk + 32)));61MSG3 = vreinterpretq_u32_u8(vrev32q_u8(vld1q_u8(chunk + 48)));62chunk += 64;64// Original implementation preloaded message and constant addition which was 1-3% slower.65// Now included as first step in quad round code saving one Q Neon register66// "TMP0 = vaddq_u32(MSG0, vld1q_u32(&K[0]));"68// Rounds 1-469TMP0 = vaddq_u32(MSG0, vld1q_u32(&K[0]));70TMP2 = STATE0;71MSG0 = vsha256su0q_u32(MSG0, MSG1);72STATE0 = vsha256hq_u32(STATE0, STATE1, TMP0);73STATE1 = vsha256h2q_u32(STATE1, TMP2, TMP0);74MSG0 = vsha256su1q_u32(MSG0, MSG2, MSG3);76// Rounds 5-877TMP0 = vaddq_u32(MSG1, vld1q_u32(&K[4]));78TMP2 = STATE0;79MSG1 = vsha256su0q_u32(MSG1, MSG2);80STATE0 = vsha256hq_u32(STATE0, STATE1, TMP0);81STATE1 = vsha256h2q_u32(STATE1, TMP2, TMP0);82MSG1 = vsha256su1q_u32(MSG1, MSG3, MSG0);84// Rounds 9-1285TMP0 = vaddq_u32(MSG2, vld1q_u32(&K[8]));86TMP2 = STATE0;87MSG2 = vsha256su0q_u32(MSG2, MSG3);88STATE0 = vsha256hq_u32(STATE0, STATE1, TMP0);89STATE1 = vsha256h2q_u32(STATE1, TMP2, TMP0);90MSG2 = vsha256su1q_u32(MSG2, MSG0, MSG1);92// Rounds 13-1693TMP0 = vaddq_u32(MSG3, vld1q_u32(&K[12]));94TMP2 = STATE0;95MSG3 = vsha256su0q_u32(MSG3, MSG0);96STATE0 = vsha256hq_u32(STATE0, STATE1, TMP0);97STATE1 = vsha256h2q_u32(STATE1, TMP2, TMP0);98MSG3 = vsha256su1q_u32(MSG3, MSG1, MSG2);100// Rounds 17-20101TMP0 = vaddq_u32(MSG0, vld1q_u32(&K[16]));102TMP2 = STATE0;103MSG0 = vsha256su0q_u32(MSG0, MSG1);104STATE0 = vsha256hq_u32(STATE0, STATE1, TMP0);105STATE1 = vsha256h2q_u32(STATE1, TMP2, TMP0);106MSG0 = vsha256su1q_u32(MSG0, MSG2, MSG3);108// Rounds 21-24109TMP0 = vaddq_u32(MSG1, vld1q_u32(&K[20]));110TMP2 = STATE0;111MSG1 = vsha256su0q_u32(MSG1, MSG2);112STATE0 = vsha256hq_u32(STATE0, STATE1, TMP0);113STATE1 = vsha256h2q_u32(STATE1, TMP2, TMP0);114MSG1 = vsha256su1q_u32(MSG1, MSG3, MSG0);116// Rounds 25-28117TMP0 = vaddq_u32(MSG2, vld1q_u32(&K[24]));118TMP2 = STATE0;119MSG2 = vsha256su0q_u32(MSG2, MSG3);120STATE0 = vsha256hq_u32(STATE0, STATE1, TMP0);121STATE1 = vsha256h2q_u32(STATE1, TMP2, TMP0);122MSG2 = vsha256su1q_u32(MSG2, MSG0, MSG1);124// Rounds 29-32125TMP0 = vaddq_u32(MSG3, vld1q_u32(&K[28]));126TMP2 = STATE0;127MSG3 = vsha256su0q_u32(MSG3, MSG0);128STATE0 = vsha256hq_u32(STATE0, STATE1, TMP0);129STATE1 = vsha256h2q_u32(STATE1, TMP2, TMP0);130MSG3 = vsha256su1q_u32(MSG3, MSG1, MSG2);132// Rounds 33-36133TMP0 = vaddq_u32(MSG0, vld1q_u32(&K[32]));134TMP2 = STATE0;135MSG0 = vsha256su0q_u32(MSG0, MSG1);136STATE0 = vsha256hq_u32(STATE0, STATE1, TMP0);137STATE1 = vsha256h2q_u32(STATE1, TMP2, TMP0);138MSG0 = vsha256su1q_u32(MSG0, MSG2, MSG3);140// Rounds 37-40141TMP0 = vaddq_u32(MSG1, vld1q_u32(&K[36]));142TMP2 = STATE0;143MSG1 = vsha256su0q_u32(MSG1, MSG2);144STATE0 = vsha256hq_u32(STATE0, STATE1, TMP0);145STATE1 = vsha256h2q_u32(STATE1, TMP2, TMP0);146MSG1 = vsha256su1q_u32(MSG1, MSG3, MSG0);148// Rounds 41-44149TMP0 = vaddq_u32(MSG2, vld1q_u32(&K[40]));150TMP2 = STATE0;151MSG2 = vsha256su0q_u32(MSG2, MSG3);152STATE0 = vsha256hq_u32(STATE0, STATE1, TMP0);153STATE1 = vsha256h2q_u32(STATE1, TMP2, TMP0);154MSG2 = vsha256su1q_u32(MSG2, MSG0, MSG1);156// Rounds 45-48157TMP0 = vaddq_u32(MSG3, vld1q_u32(&K[44]));158TMP2 = STATE0;159MSG3 = vsha256su0q_u32(MSG3, MSG0);160STATE0 = vsha256hq_u32(STATE0, STATE1, TMP0);161STATE1 = vsha256h2q_u32(STATE1, TMP2, TMP0);162MSG3 = vsha256su1q_u32(MSG3, MSG1, MSG2);164// Rounds 49-52165TMP0 = vaddq_u32(MSG0, vld1q_u32(&K[48]));166TMP2 = STATE0;167STATE0 = vsha256hq_u32(STATE0, STATE1, TMP0);168STATE1 = vsha256h2q_u32(STATE1, TMP2, TMP0);170// Rounds 53-56171TMP0 = vaddq_u32(MSG1, vld1q_u32(&K[52]));172TMP2 = STATE0;173STATE0 = vsha256hq_u32(STATE0, STATE1, TMP0);174STATE1 = vsha256h2q_u32(STATE1, TMP2, TMP0);176// Rounds 57-60177TMP0 = vaddq_u32(MSG2, vld1q_u32(&K[56]));178TMP2 = STATE0;179STATE0 = vsha256hq_u32(STATE0, STATE1, TMP0);180STATE1 = vsha256h2q_u32(STATE1, TMP2, TMP0);182// Rounds 61-64183TMP0 = vaddq_u32(MSG3, vld1q_u32(&K[60]));184TMP2 = STATE0;185STATE0 = vsha256hq_u32(STATE0, STATE1, TMP0);186STATE1 = vsha256h2q_u32(STATE1, TMP2, TMP0);188// Update state189STATE0 = vaddq_u32(STATE0, ABCD_SAVE);190STATE1 = vaddq_u32(STATE1, EFGH_SAVE);191}193// Save final state194vst1q_u32(&s[0], STATE0);195vst1q_u32(&s[4], STATE1);196}197}199namespace sha256d64_arm_shani {200void Transform_2way(unsigned char* output, const unsigned char* input)201{202/* Initial state. */203alignas(uint32x4_t) static constexpr std::array<uint32_t, 8> INIT = {2040x6a09e667, 0xbb67ae85, 0x3c6ef372, 0xa54ff53a,2050x510e527f, 0x9b05688c, 0x1f83d9ab, 0x5be0cd19206};208/* Precomputed message schedule for the 2nd transform. */209alignas(uint32x4_t) static constexpr std::array<uint32_t, 64> MIDS = {2100xc28a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5,2110x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5,2120xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3,2130x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf374,2140x649b69c1, 0xf0fe4786, 0x0fe1edc6, 0x240cf254,2150x4fe9346f, 0x6cc984be, 0x61b9411e, 0x16f988fa,2160xf2c65152, 0xa88e5a6d, 0xb019fc65, 0xb9d99ec7,2170x9a1231c3, 0xe70eeaa0, 0xfdb1232b, 0xc7353eb0,2180x3069bad5, 0xcb976d5f, 0x5a0f118f, 0xdc1eeefd,2190x0a35b689, 0xde0b7a04, 0x58f4ca9d, 0xe15d5b16,2200x007f3e86, 0x37088980, 0xa507ea32, 0x6fab9537,2210x17406110, 0x0d8cd6f1, 0xcdaa3b6d, 0xc0bbbe37,2220x83613bda, 0xdb48a363, 0x0b02e931, 0x6fd15ca7,2230x521afaca, 0x31338431, 0x6ed41a95, 0x6d437890,2240xc39c91f2, 0x9eccabbd, 0xb5c9a0e6, 0x532fb63c,2250xd2c741c6, 0x07237ea3, 0xa4954b68, 0x4c191d76226};228/* A few precomputed message schedule values for the 3rd transform. */229alignas(uint32x4_t) static constexpr std::array<uint32_t, 12> FINS = {2300x5807aa98, 0x12835b01, 0x243185be, 0x550c7dc3,2310x80000000, 0x00000000, 0x00000000, 0x00000000,2320x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf274233};235/* Padding processed in the 3rd transform (byteswapped). */236alignas(uint32x4_t) static constexpr std::array<uint32_t, 8> FINAL = {0x80000000, 0, 0, 0, 0, 0, 0, 0x100};238uint32x4_t STATE0A, STATE0B, STATE1A, STATE1B, ABCD_SAVEA, ABCD_SAVEB, EFGH_SAVEA, EFGH_SAVEB;239uint32x4_t MSG0A, MSG0B, MSG1A, MSG1B, MSG2A, MSG2B, MSG3A, MSG3B;240uint32x4_t TMP0A, TMP0B, TMP2A, TMP2B, TMP;242// Transform 1: Load state243STATE0A = vld1q_u32(&INIT[0]);244STATE0B = STATE0A;245STATE1A = vld1q_u32(&INIT[4]);246STATE1B = STATE1A;248// Transform 1: Load and convert input chunk to Big Endian249MSG0A = vreinterpretq_u32_u8(vrev32q_u8(vld1q_u8(input + 0)));250MSG1A = vreinterpretq_u32_u8(vrev32q_u8(vld1q_u8(input + 16)));
Independent explanations by MyBitcoinExplorer. Not affiliated with or endorsed by Bitcoin Core. Guides are educational and do not replace the source or its tests.
Bitcoin Core source © its contributors, distributed under the MIT license. Original notices and bundled third-party licenses are retained in the source tree.