123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134(*****************************************************************************)(* *)(* Open Source License *)(* Copyright (c) 2018 Dynamic Ledger Solutions, Inc. <contact@tezos.com> *)(* *)(* Permission is hereby granted, free of charge, to any person obtaining a *)(* copy of this software and associated documentation files (the "Software"),*)(* to deal in the Software without restriction, including without limitation *)(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *)(* and/or sell copies of the Software, and to permit persons to whom the *)(* Software is furnished to do so, subject to the following conditions: *)(* *)(* The above copyright notice and this permission notice shall be included *)(* in all copies or substantial portions of the Software. *)(* *)(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*)(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *)(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *)(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*)(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *)(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *)(* DEALINGS IN THE SOFTWARE. *)(* *)(*****************************************************************************)openProtocolletdefault_constant="\x00\x00\x00\x05"letwith_version_constant=letcommit_hash=matchHex.to_string(`HexTezos_version_value.Current_git_info.commit_hash)with|None->Tezos_version_value.Current_git_info.commit_hash|Somes->sinifString.lengthcommit_hash>=4thenString.subcommit_hash04elsedefault_constantletwith_version_constant_len=String.lengthwith_version_constantletproof_of_work_nonce=letout=Bytes.makeAlpha_context.Constants.proof_of_work_nonce_size'\000'inlet()=Bytes.blit_stringwith_version_constant0out0with_version_constant_leninout(* [proof_of_work_nonce] will be modified in place so we make a clean copy to expose to the outside *)letempty_proof_of_work_nonce=Bytes.copyproof_of_work_nonceletmax_z_len=Alpha_context.Constants.proof_of_work_nonce_size-with_version_constant_len(* Make a string of zeros to restore [proof_of_work_nonce] to its original value in 1 operation *)letzeros=String.makemax_z_len'\000'letmine~proof_of_work_thresholdshellbuilder=letopenLwt_result_syntaxinmatchOption.bind(Data_encoding.Binary.fixed_lengthBlock_payload_hash.encoding)(funpayload->Option.map(funround->letshell=Data_encoding.Binary.lengthBlock_header.shell_header_encodingshellinshell+payload+round+with_version_constant_len)(Data_encoding.Binary.fixed_lengthRound_repr.encoding))(* Where to put the proof of work value is in the bytes of the encoded header *)with|None->failwith"Cannot compute block header offset"|Someoffset->let()=(* Restore proof_of_work_nonce to its original value. *)Bytes.blit_stringzeros0proof_of_work_noncewith_version_constant_lenmax_z_lenin(* Build the binary of the block header with 0 as proof of work and compute its hash. *)letblock_0=builderproof_of_work_nonceinletblock_header=Data_encoding.Binary.to_bytes_exnAlpha_context.Block_header.encodingAlpha_context.Block_header.{shell;protocol_data={contents=block_0;signature=Signature.zero};}inletblock_hash=Block_header.hash_rawblock_headerinletblock_hash_bytes=Block_hash.to_bytesblock_hashin(* The loop edits [block_header] and [block_hash] (by editing its subpart [block_hash_bytes]!) in place. *)letrecloopz=letz_len=(Z.numbitsz+7)/8inifz_len>max_z_lenthenfailwith"Client_baking_pow.mine: couldn't find nonce for required proof of \
work"else(Bytes.blit_string(Z.to_bitsz)0block_headeroffsetz_len;(ifHacl_star.AutoConfig2.(has_featureVEC256)thenHacl_star.Hacl.Blake2b_256.Noalloc.hashelseHacl_star.Hacl.Blake2b_32.Noalloc.hash)~key:Bytes.empty~msg:block_header~digest:block_hash_bytes;ifAlpha_context.Block_header.Proof_of_work.check_hashblock_hashproof_of_work_thresholdthenlet()=Bytes.blit_string(Z.to_bitsz)0proof_of_work_noncewith_version_constant_lenz_leninletblock=builderproof_of_work_nonceinreturnblockelseloop(Z.succz))inloopZ.zero