123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322(*****************************************************************************)(* *)(* 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. *)(* *)(*****************************************************************************)letmax_block_length=100letmax_operation_data_length=100letvalidation_passes=Updater.[{max_size=1000;max_op=None}]letacceptable_pass_op=Some0typeblock_header_data=Header.ttypeblock_header={shell:Block_header.shell_header;protocol_data:block_header_data;}letblock_header_data_encoding=Header.encodingtypeblock_header_metadata=State.tletblock_header_metadata_encoding=State.encodingtypeoperation_data=Proto_operation.tletoperation_data_encoding=Proto_operation.encodingtypeoperation_receipt=Receipt.tletoperation_receipt_encoding=Receipt.encodingletoperation_data_and_receipt_encoding=(* we could merge data and receipt encoding for a lighter json *)Data_encoding.(obj2(req"data"Proto_operation.encoding)(req"receipt"Receipt.encoding))typeoperation={shell:Operation.shell_header;protocol_data:operation_data;}typevalidation_state={context:Context.t;fitness:Fitness.t}typeapplication_state=validation_statetypemode=|Applicationofblock_header|Partial_validationofblock_header|Constructionof{predecessor_hash:Block_hash.t;timestamp:Time.t;block_header_data:block_header_data;}|Partial_constructionof{predecessor_hash:Block_hash.t;timestamp:Time.t;}letmode_str=function|Application_->"application"|Partial_validation_->"partial_validation"|Construction_->"construction"|Partial_construction_->"partial_construction"letvalidation_or_application_str=function|`Validation->"validation"|`Application->"application"letbegin_any_application_modevalidation_or_applicationmodecontext~(predecessor:Block_header.shell_header)(block_header:block_header)=letfitness=block_header.shell.fitnessinLogging.logNotice"begin_%s (%s mode): pred_fitness = %a block_fitness = %a%!"(validation_or_application_strvalidation_or_application)(mode_strmode)Fitness.pppredecessor.fitnessFitness.ppfitness;(* Note: Logging is only available for debugging purposes and should
not appear in a real protocol. *)return{context;fitness}(* we use here the same fitness format than proto alpha,
but with higher [version_number] to allow testing
migration from alpha to demo_counter. *)letversion_number="\255"letint64_to_bytesi=letb=Bytes.make8'\000'inTzEndian.set_int64b0i;bletfitness_from_levellevel=[Bytes.of_stringversion_number;Bytes.of_string"\000";Bytes.of_string"\000";Bytes.of_string"\000";int64_to_byteslevel;]letbegin_any_construction_modevalidation_or_applicationmodecontext~(predecessor:Block_header.shell_header)=letfitness=fitness_from_levelInt64.(succ(of_int32predecessor.level))inLogging.logNotice"begin_%s (%s mode): pred_fitness = %a constructed fitness = %a%!"(validation_or_application_strvalidation_or_application)(mode_strmode)Fitness.pppredecessor.fitnessFitness.ppfitness;return{context;fitness}letbegin_validation_or_applicationvalidation_or_applicationctxt_chain_idmode~predecessor=matchmodewith|Applicationblock_header|Partial_validationblock_header->begin_any_application_modevalidation_or_applicationmodectxt~predecessorblock_header|Construction_|Partial_construction_->begin_any_construction_modevalidation_or_applicationmodectxt~predecessorletbegin_validation=begin_validation_or_application`Validationletbegin_application=begin_validation_or_application`Applicationletapply_operation_auxapplication_stateoperation=let{context;fitness}=application_stateinState.get_statecontext>>=funstate->matchApply.applystateoperation.protocol_datawith|None->Error_monad.tzfailError.Invalid_operation|Somestate->State.update_statecontextstate>>=funcontext->return{context;fitness}letvalidate_operation?check_signature:_validation_state_ophoperation=Logging.logNotice"validate_operation";apply_operation_auxvalidation_stateoperationletapply_operationapplication_state_ophoperation=Logging.logNotice"apply_operation";apply_operation_auxapplication_stateoperation>>=?funapplication_state->letreceipt=Receipt.create"operation applied successfully"inreturn(application_state,receipt)letlog_finalizevalidation_or_applicationvalidation_state=Logging.logNotice"finalize_%s: fitness = %a%!"(validation_or_application_strvalidation_or_application)Fitness.ppvalidation_state.fitnessletfinalize_validationvalidation_state=log_finalize`Validationvalidation_state;return_unitletfinalize_applicationapplication_state_shell_header=log_finalize`Applicationapplication_state;letfitness=application_state.fitnessinletmessage=Some(Format.asprintf"fitness <- %a"Fitness.ppfitness)inletcontext=application_state.contextinState.get_statecontext>>=funstate->return({Updater.message;context;fitness;max_operations_ttl=0;last_allowed_fork_level=0l;},state)letdecode_jsonjson=matchProto_params.from_jsonjsonwith|exception_->tzfailError.Invalid_protocol_parameters|proto_params->returnproto_paramsletget_init_statecontext:State.ttzresultLwt.t=letprotocol_params_key=["protocol_parameters"]inContext.findcontextprotocol_params_key>>=(function|None->returnProto_params.default|Somebytes->(matchData_encoding.Binary.of_bytes_optData_encoding.jsonbyteswith|None->tzfail(Error.Failed_to_parse_parameterbytes)|Somejson->decode_jsonjson))>>=?function|Proto_params.{init_a;init_b}->(matchState.createinit_ainit_bwith|None->tzfailError.Invalid_protocol_parameters|Somestate->returnstate)letinit_chain_idcontextblock_header=letopenBlock_headerinletfitness=block_header.fitnessinLogging.logNotice"init: fitness = %a%!"Fitness.ppfitness;get_init_statecontext>>=?funinit_state->State.update_statecontextinit_state>>=funinit_context->return{Updater.message=None;context=init_context;fitness;max_operations_ttl=0;last_allowed_fork_level=block_header.level;}letcompare_operations__=0typeContext.Cache.value+=Demoofintletvalue_of_key~chain_id:_~predecessor_context:_~predecessor_timestamp:_~predecessor_level:_~predecessor_fitness:_~predecessor:_~timestamp:_=return(fun_->return(Demo123))letrpc_services=Services.rpc_servicesmoduleMempool=structtypet=State.ttypevalidation_info=unittypeconflict_handler=existing_operation:Operation_hash.t*operation->new_operation:Operation_hash.t*operation->[`Keep|`Replace]typeoperation_conflict=|Operation_conflictof{existing:Operation_hash.t;new_operation:Operation_hash.t;}typeadd_result=|Added|Replacedof{removed:Operation_hash.t}|Unchangedtypeadd_error=|Validation_erroroferrortrace|Add_conflictofoperation_conflicttypemerge_error=|Incompatible_mempool|Merge_conflictofoperation_conflictletinitctxt_chain_id~head_hash:_~(head:Block_header.shell_header)=letopenLwt_result_syntaxinLogging.logNotice"Mempool.init: head fitness = %a%!"Fitness.pphead.fitness;let*!state=State.get_statectxtinreturn((),state)letencoding=State.encodingletadd_operation?check_signature:_?conflict_handler:_(_info:validation_info)state((_oph:Operation_hash.t),op)=matchApply.applystateop.protocol_datawith|None->Lwt.return_error(Validation_error(trace_of_errorError.Invalid_operation))|Somestate->return(state,Added)(* This mempool does not currently support removing an operation. *)letremove_operation__=assertfalse(* This mempool does not currently support merging. *)letmerge?conflict_handler:___=assertfalse(* This function is not currently used in the context of
[proto_demo_counter]. If it is needed in the future, the type [t]
will need to be extended to remember all added operations. *)letoperations_=assertfalseend