Merge branch 'web-client' into 'master'
Template for the server part of the webclient See merge request !119
This commit is contained in:
commit
9ece98167a
10
.gitignore
vendored
10
.gitignore
vendored
@ -2,7 +2,9 @@
|
|||||||
/tezos-node
|
/tezos-node
|
||||||
/tezos-protocol-compiler
|
/tezos-protocol-compiler
|
||||||
/tezos-client
|
/tezos-client
|
||||||
|
/tezos-webclient
|
||||||
|
|
||||||
|
/src/webclient_static.ml
|
||||||
/src/.depend
|
/src/.depend
|
||||||
|
|
||||||
/src/node/updater/environment_gen
|
/src/node/updater/environment_gen
|
||||||
@ -19,6 +21,12 @@
|
|||||||
/src/client/embedded/bootstrap/concrete_lexer.ml
|
/src/client/embedded/bootstrap/concrete_lexer.ml
|
||||||
/src/client/embedded/bootstrap/concrete_parser.ml
|
/src/client/embedded/bootstrap/concrete_parser.ml
|
||||||
/src/client/embedded/bootstrap/concrete_parser.mli
|
/src/client/embedded/bootstrap/concrete_parser.mli
|
||||||
|
/src/client/embedded/bootstrap/webclient_proto_static.ml
|
||||||
|
/src/client/embedded/bootstrap/main.byte
|
||||||
|
/src/client/embedded/bootstrap/webclient_static/main.js
|
||||||
|
/src/client/embedded/bootstrap/webclient/browser/main.byte
|
||||||
|
/src/client/embedded/bootstrap/webclient/static/main.js
|
||||||
|
/src/client/embedded/bootstrap/webclient/webclient_proto_static.ml
|
||||||
|
|
||||||
/test/.depend
|
/test/.depend
|
||||||
/test/reports
|
/test/reports
|
||||||
@ -44,6 +52,8 @@
|
|||||||
*.cmp
|
*.cmp
|
||||||
*.mli.deps
|
*.mli.deps
|
||||||
*.ml.deps
|
*.ml.deps
|
||||||
|
*.mli.deps.byte
|
||||||
|
*.ml.deps.byte
|
||||||
|
|
||||||
bisect*.out
|
bisect*.out
|
||||||
|
|
||||||
|
107
src/Makefile
107
src/Makefile
@ -4,8 +4,9 @@ include Makefile.config
|
|||||||
TZCOMPILER=../tezos-protocol-compiler
|
TZCOMPILER=../tezos-protocol-compiler
|
||||||
TZNODE=../tezos-node
|
TZNODE=../tezos-node
|
||||||
TZCLIENT=../tezos-client
|
TZCLIENT=../tezos-client
|
||||||
|
TZWEBCLIENT=../tezos-webclient
|
||||||
|
|
||||||
all: ${TZCOMPILER} ${TZNODE} ${TZCLIENT}
|
all: ${TZCOMPILER} ${TZNODE} ${TZCLIENT} ${TZWEBCLIENT}
|
||||||
|
|
||||||
|
|
||||||
############################################################################
|
############################################################################
|
||||||
@ -131,6 +132,17 @@ minutils.cmxa: ${MINUTILS_LIB_IMPLS:.ml=.cmx}
|
|||||||
@echo LINK $(notdir $@)
|
@echo LINK $(notdir $@)
|
||||||
@${OCAMLOPT} ${OCAMLFLAGS} -a -o $@ $^
|
@${OCAMLOPT} ${OCAMLFLAGS} -a -o $@ $^
|
||||||
|
|
||||||
|
MINUTILS_OBJS_BYTECODE := \
|
||||||
|
${MINUTILS_LIB_IMPLS:.ml=.cmo} ${MINUTILS_LIB_IMPLS:.ml=.ml.deps.byte}
|
||||||
|
${MINUTILS_OBJS_BYTECODE}: PACKAGES=${MINUTILS_PACKAGES}
|
||||||
|
${MINUTILS_OBJS_BYTECODE}: SOURCE_DIRECTORIES=minutils
|
||||||
|
${MINUTILS_OBJS_BYTECODE}: TARGET="(minutils.cma)"
|
||||||
|
${MINUTILS_OBJS_BYTECODE}: OPENED_MODULES=
|
||||||
|
|
||||||
|
minutils.cma: ${MINUTILS_LIB_IMPLS:.ml=.cmo}
|
||||||
|
@echo LINK $(notdir $@)
|
||||||
|
@${OCAMLC} ${OCAMLFLAGS} -a -o $@ $^
|
||||||
|
|
||||||
############################################################################
|
############################################################################
|
||||||
## Utils library
|
## Utils library
|
||||||
############################################################################
|
############################################################################
|
||||||
@ -366,13 +378,12 @@ proto/client_embedded_proto_%.cmxa: \
|
|||||||
clean::
|
clean::
|
||||||
rm -f ${TZNODE}
|
rm -f ${TZNODE}
|
||||||
|
|
||||||
|
|
||||||
############################################################################
|
############################################################################
|
||||||
## Client program
|
## Client program
|
||||||
############################################################################
|
############################################################################
|
||||||
|
|
||||||
CLIENT_LIB_INTFS := \
|
CLIENT_LIB_INTFS := \
|
||||||
client/client_version.mli \
|
client/client_commands.mli \
|
||||||
client/client_node_rpcs.mli \
|
client/client_node_rpcs.mli \
|
||||||
client/client_generic_rpcs.mli \
|
client/client_generic_rpcs.mli \
|
||||||
client/client_helpers.mli \
|
client/client_helpers.mli \
|
||||||
@ -381,7 +392,7 @@ CLIENT_LIB_INTFS := \
|
|||||||
client/client_protocols.mli \
|
client/client_protocols.mli \
|
||||||
|
|
||||||
CLIENT_LIB_IMPLS := \
|
CLIENT_LIB_IMPLS := \
|
||||||
client/client_version.ml \
|
client/client_commands.ml \
|
||||||
client/client_config.ml \
|
client/client_config.ml \
|
||||||
client/client_node_rpcs.ml \
|
client/client_node_rpcs.ml \
|
||||||
client/client_generic_rpcs.ml \
|
client/client_generic_rpcs.ml \
|
||||||
@ -390,55 +401,108 @@ CLIENT_LIB_IMPLS := \
|
|||||||
client/client_keys.ml \
|
client/client_keys.ml \
|
||||||
client/client_protocols.ml \
|
client/client_protocols.ml \
|
||||||
|
|
||||||
|
WEBCLIENT_LIB_INTFS := \
|
||||||
|
|
||||||
|
WEBCLIENT_LIB_IMPLS := \
|
||||||
|
client/webclient_version.ml \
|
||||||
|
|
||||||
CLIENT_IMPLS := \
|
CLIENT_IMPLS := \
|
||||||
client_main.ml
|
client_main.ml
|
||||||
|
|
||||||
|
WEBCLIENT_IMPLS := \
|
||||||
|
webclient_static.ml \
|
||||||
|
webclient_main.ml
|
||||||
|
|
||||||
CLIENT_PACKAGES := \
|
CLIENT_PACKAGES := \
|
||||||
${NODE_PACKAGES}
|
${NODE_PACKAGES}
|
||||||
|
|
||||||
EMBEDDED_CLIENT_PROTOCOLS := \
|
EMBEDDED_CLIENT_PROTOCOLS := \
|
||||||
$(patsubst client/embedded/%/, \
|
$(patsubst client/embedded/%/, \
|
||||||
proto/client_embedded_proto_%.cmxa, \
|
proto/client_embedded_proto_%.cmxa, \
|
||||||
$(shell ls -d client/embedded/*/)) \
|
$(shell ls -d client/embedded/*/))
|
||||||
|
|
||||||
|
EMBEDDED_CLIENT_VERSIONS := \
|
||||||
$(patsubst client/embedded/%/, \
|
$(patsubst client/embedded/%/, \
|
||||||
client/embedded/client_%.cmx, \
|
client/embedded/client_%.cmx, \
|
||||||
$(shell ls -d client/embedded/*/))
|
$(shell ls -d client/embedded/*/))
|
||||||
|
|
||||||
|
EMBEDDED_WEBCLIENT_VERSIONS := \
|
||||||
|
$(patsubst client/embedded/%/, \
|
||||||
|
client/embedded/webclient_%.cmx, \
|
||||||
|
$(shell ls -d client/embedded/*/))
|
||||||
|
|
||||||
CLIENT_OBJS := \
|
CLIENT_OBJS := \
|
||||||
${CLIENT_IMPLS:.ml=.cmx} ${CLIENT_IMPLS:.ml=.ml.deps} \
|
${CLIENT_IMPLS:.ml=.cmx} ${CLIENT_IMPLS:.ml=.ml.deps} \
|
||||||
|
${WEBCLIENT_IMPLS:.ml=.cmx} ${WEBCLIENT_IMPLS:.ml=.ml.deps} \
|
||||||
${CLIENT_LIB_IMPLS:.ml=.cmx} ${CLIENT_LIB_IMPLS:.ml=.ml.deps} \
|
${CLIENT_LIB_IMPLS:.ml=.cmx} ${CLIENT_LIB_IMPLS:.ml=.ml.deps} \
|
||||||
${CLIENT_LIB_INTFS:.mli=.cmi} ${CLIENT_LIB_INTFS:.mli=.mli.deps} \
|
${CLIENT_LIB_INTFS:.mli=.cmi} ${CLIENT_LIB_INTFS:.mli=.mli.deps} \
|
||||||
${TZCLIENT}
|
${WEBCLIENT_LIB_IMPLS:.ml=.cmx} ${WEBCLIENT_LIB_IMPLS:.ml=.ml.deps} \
|
||||||
|
${WEBCLIENT_LIB_INTFS:.mli=.cmi} ${WEBCLIENT_LIB_INTFS:.mli=.mli.deps} \
|
||||||
|
${TZCLIENT} \
|
||||||
|
${TZWEBCLIENT}
|
||||||
${CLIENT_OBJS}: PACKAGES=${CLIENT_PACKAGES}
|
${CLIENT_OBJS}: PACKAGES=${CLIENT_PACKAGES}
|
||||||
${CLIENT_OBJS}: SOURCE_DIRECTORIES=client client/embedded minutils utils node/net node/shell node/updater node/db compiler
|
${CLIENT_OBJS}: SOURCE_DIRECTORIES=client client/embedded minutils utils node/net node/shell node/updater node/db compiler
|
||||||
${CLIENT_OBJS}: TARGET="(client.cmxa)"
|
|
||||||
${CLIENT_OBJS}: OPENED_MODULES=Error_monad Hash Utils
|
${CLIENT_OBJS}: OPENED_MODULES=Error_monad Hash Utils
|
||||||
|
|
||||||
|
${CLIENT_LIB_IMPLS:.ml=.cmx} ${CLIENT_LIB_IMPLS:.ml=.ml.deps}: TARGET="(client.cmxa)"
|
||||||
|
${CLIENT_LIB_INTFS:.mli=.cmi} ${CLIENT_LIB_INTFS:.mli=.mli.deps}: TARGET="(client.cmxa)"
|
||||||
|
${WEBCLIENT_LIB_IMPLS:.ml=.cmx} ${WEBCLIENT_LIB_IMPLS:.ml=.ml.deps}: TARGET="(webclient.cmxa)"
|
||||||
|
${WEBCLIENT_LIB_INTFS:.mli=.cmi} ${WEBCLIENT_LIB_INTFS:.mli=.mli.deps}: TARGET="(webclient.cmxa)"
|
||||||
|
|
||||||
client.cmxa: ${CLIENT_LIB_IMPLS:.ml=.cmx}
|
client.cmxa: ${CLIENT_LIB_IMPLS:.ml=.cmx}
|
||||||
@echo LINK $(notdir $@)
|
@echo LINK $(notdir $@)
|
||||||
@${OCAMLOPT} ${OCAMLFLAGS} -a -o $@ $^
|
@${OCAMLOPT} ${OCAMLFLAGS} -a -o $@ $^
|
||||||
|
|
||||||
${EMBEDDED_CLIENT_PROTOCOLS}: client.cmxa
|
webclient.cmxa: ${WEBCLIENT_LIB_IMPLS:.ml=.cmx} client.cmxa
|
||||||
${CLIENT_IMPLS:.ml=.cmx}: ${EMBEDDED_CLIENT_PROTOCOLS}
|
@echo LINK $(notdir $@)
|
||||||
|
${OCAMLOPT} ${OCAMLFLAGS} -a -o $@ ${WEBCLIENT_LIB_IMPLS:.ml=.cmx}
|
||||||
|
|
||||||
|
${EMBEDDED_CLIENT_VERSIONS}: client.cmxa
|
||||||
|
${CLIENT_IMPLS:.ml=.cmx}: ${EMBEDDED_CLIENT_VERSIONS}
|
||||||
|
|
||||||
|
${EMBEDDED_WEBCLIENT_VERSIONS}: webclient.cmxa
|
||||||
|
${WEBCLIENT_IMPLS:.ml=.cmx}: ${EMBEDDED_CLIENT_VERSIONS} ${EMBEDDED_WEBCLIENT_VERSIONS}
|
||||||
|
|
||||||
${TZCLIENT}: minutils.cmxa utils.cmxa compiler.cmxa node.cmxa \
|
${TZCLIENT}: minutils.cmxa utils.cmxa compiler.cmxa node.cmxa \
|
||||||
client.cmxa ${EMBEDDED_CLIENT_PROTOCOLS} \
|
client.cmxa \
|
||||||
|
${EMBEDDED_CLIENT_PROTOCOLS} \
|
||||||
|
${EMBEDDED_CLIENT_VERSIONS} \
|
||||||
${CLIENT_IMPLS:.ml=.cmx}
|
${CLIENT_IMPLS:.ml=.cmx}
|
||||||
@echo LINK $(notdir $@)
|
@echo LINK $(notdir $@)
|
||||||
@${OCAMLOPT} -linkpkg ${OCAMLFLAGS} -o $@ $^
|
@${OCAMLOPT} -linkpkg ${OCAMLFLAGS} -o $@ $^
|
||||||
|
|
||||||
|
${TZWEBCLIENT}: minutils.cmxa utils.cmxa compiler.cmxa node.cmxa \
|
||||||
|
client.cmxa webclient.cmxa \
|
||||||
|
${EMBEDDED_CLIENT_PROTOCOLS} \
|
||||||
|
${EMBEDDED_CLIENT_VERSIONS} \
|
||||||
|
${EMBEDDED_WEBCLIENT_VERSIONS} \
|
||||||
|
${WEBCLIENT_IMPLS:.ml=.cmx}
|
||||||
|
@echo LINK $(notdir $@)
|
||||||
|
@${OCAMLOPT} -linkpkg ${OCAMLFLAGS} -o $@ $^
|
||||||
|
|
||||||
|
webclient_static.ml: $$(shell find webclient_static/)
|
||||||
|
ocp-ocamlres webclient_static -o $@
|
||||||
|
|
||||||
clean::
|
clean::
|
||||||
-rm -f ${TZCLIENT}
|
-rm -f ${TZCLIENT} $(TZWEBCLIENT)
|
||||||
|
|
||||||
## Embedded client protocol modules
|
## Embedded client protocol modules
|
||||||
|
|
||||||
.SECONDEXPANSION:
|
.SECONDEXPANSION:
|
||||||
|
|
||||||
client/embedded/client_%.cmx: \
|
client/embedded/client_%.cmx: \
|
||||||
$(patsubst %.ml, %.cmx, $(NODE_LIB_IMPLS) $(CLIENT_LIB_IMPLS)) \
|
$(patsubst %.ml, %.cmx, $(NODE_LIB_IMPLS) $(CLIENT_LIB_IMPLS)) \
|
||||||
proto/client_embedded_proto_%.cmxa \
|
proto/client_embedded_proto_%.cmxa \
|
||||||
$$(shell find client/embedded/% -name \*.ml -or -name \*.mli)
|
$$(shell find client/embedded/% -name \*.ml -or -name \*.mli)
|
||||||
@$(MAKE) -C client/embedded/$* ../client_$*.cmx
|
@$(MAKE) -C client/embedded/$* ../client_$*.cmx
|
||||||
|
|
||||||
|
client/embedded/webclient_%.cmx: \
|
||||||
|
client/embedded/client_%.cmx \
|
||||||
|
minutils.cma \
|
||||||
|
$$(shell find client/embedded/%/webclient -name \*.ml -or -name \*.mli) \
|
||||||
|
$$(shell find client/embedded/%/webclient/static/)
|
||||||
|
@$(MAKE) -C client/embedded/$* ../webclient_$*.cmx
|
||||||
|
|
||||||
clean::
|
clean::
|
||||||
-for d in $$(ls -d client/embedded/*/) ; do make clean -C $$d ; done
|
-for d in $$(ls -d client/embedded/*/) ; do make clean -C $$d ; done
|
||||||
-rm -f client/embedded/*.cm* client/embedded/*.o
|
-rm -f client/embedded/*.cm* client/embedded/*.o
|
||||||
@ -450,7 +514,7 @@ clean::
|
|||||||
@$(OCAMLOPT) ${OCAMLFLAGS} -c $<
|
@$(OCAMLOPT) ${OCAMLFLAGS} -c $<
|
||||||
|
|
||||||
%.cmo: %.ml
|
%.cmo: %.ml
|
||||||
@echo OCAMLOPT ${TARGET} $(notdir $@)
|
@echo OCAMLC ${TARGET} $(notdir $@)
|
||||||
@$(OCAMLC) ${OCAMLFLAGS} -c $<
|
@$(OCAMLC) ${OCAMLFLAGS} -c $<
|
||||||
|
|
||||||
%.cmi: %.mli
|
%.cmi: %.mli
|
||||||
@ -472,9 +536,10 @@ compiler/embedded_cmis.cmx compiler/embedded_cmis.cmi: OPENED_MODULES=
|
|||||||
|
|
||||||
ifneq ($(MAKECMDGOALS),clean)
|
ifneq ($(MAKECMDGOALS),clean)
|
||||||
ifneq ($(MAKECMDGOALS),build-deps)
|
ifneq ($(MAKECMDGOALS),build-deps)
|
||||||
-include .depend
|
include .depend
|
||||||
endif
|
endif
|
||||||
endif
|
endif
|
||||||
|
|
||||||
DEPENDS := $(filter-out $(NO_DEPS), $(MINUTILS_LIB_INTFS) $(MINUTILS_LIB_IMPLS) \
|
DEPENDS := $(filter-out $(NO_DEPS), $(MINUTILS_LIB_INTFS) $(MINUTILS_LIB_IMPLS) \
|
||||||
$(UTILS_LIB_INTFS) $(UTILS_LIB_IMPLS) \
|
$(UTILS_LIB_INTFS) $(UTILS_LIB_IMPLS) \
|
||||||
$(COMPILER_LIB_INTFS) $(COMPILER_LIB_IMPLS) \
|
$(COMPILER_LIB_INTFS) $(COMPILER_LIB_IMPLS) \
|
||||||
@ -482,14 +547,18 @@ DEPENDS := $(filter-out $(NO_DEPS), $(MINUTILS_LIB_INTFS) $(MINUTILS_LIB_IMPLS)
|
|||||||
$(NODE_LIB_INTFS) $(NODE_LIB_IMPLS) \
|
$(NODE_LIB_INTFS) $(NODE_LIB_IMPLS) \
|
||||||
$(NODE_INTFS) $(NODE_IMPLS) \
|
$(NODE_INTFS) $(NODE_IMPLS) \
|
||||||
$(CLIENT_LIB_INTFS) $(CLIENT_LIB_IMPLS) \
|
$(CLIENT_LIB_INTFS) $(CLIENT_LIB_IMPLS) \
|
||||||
$(CLIENT_INTFS) $(CLIENT_IMPLS))
|
$(WEBCLIENT_LIB_INTFS) $(WEBCLIENT_LIB_IMPLS) \
|
||||||
|
$(CLIENT_INTFS) $(CLIENT_IMPLS) \
|
||||||
|
$(WEBCLIENT_INTFS) $(WEBCLIENT_IMPLS))
|
||||||
|
|
||||||
|
DEPENDS_BYTECODE := $(filter-out $(NO_DEPS), $(MINUTILS_LIB_INTFS) $(MINUTILS_LIB_IMPLS))
|
||||||
|
|
||||||
predepend: node/updater/proto_environment.mli
|
predepend: node/updater/proto_environment.mli
|
||||||
compiler/tezos_compiler.cmo compiler/tezos_compiler.cmx: \
|
compiler/tezos_compiler.cmo compiler/tezos_compiler.cmx: \
|
||||||
compiler/embedded_cmis.cmi compiler/embedded_cmis.cmx
|
compiler/embedded_cmis.cmi compiler/embedded_cmis.cmx
|
||||||
|
|
||||||
.SECONDARY: $(patsubst %,%.deps,${DEPENDS})
|
.SECONDARY: $(patsubst %,%.deps,${DEPENDS}) $(patsubst %,%.deps.byte,${DEPENDS_BYTECODE})
|
||||||
.depend: $(patsubst %,%.deps,${DEPENDS})
|
.depend: $(patsubst %,%.deps,${DEPENDS}) $(patsubst %,%.deps.byte,${DEPENDS_BYTECODE})
|
||||||
@cat $^ > .depend
|
@cat $^ > .depend
|
||||||
%.ml.deps: %.ml | predepend
|
%.ml.deps: %.ml | predepend
|
||||||
@echo OCAMLDEP ${TARGET} $(notdir $^)
|
@echo OCAMLDEP ${TARGET} $(notdir $^)
|
||||||
@ -497,6 +566,12 @@ compiler/tezos_compiler.cmo compiler/tezos_compiler.cmx: \
|
|||||||
%.mli.deps: %.mli | predepend
|
%.mli.deps: %.mli | predepend
|
||||||
@echo OCAMLDEP ${TARGET} $(notdir $^)
|
@echo OCAMLDEP ${TARGET} $(notdir $^)
|
||||||
@$(OCAMLDEP) -native $(INCLUDES) $^ > $@
|
@$(OCAMLDEP) -native $(INCLUDES) $^ > $@
|
||||||
|
%.ml.deps.byte: %.ml | predepend
|
||||||
|
@echo OCAMLDEP ${TARGET} $(notdir $^)
|
||||||
|
@$(OCAMLDEP) $(INCLUDES) $^ > $@
|
||||||
|
%.mli.deps.byte: %.mli | predepend
|
||||||
|
@echo OCAMLDEP ${TARGET} $(notdir $^)
|
||||||
|
@$(OCAMLDEP) $(INCLUDES) $^ > $@
|
||||||
|
|
||||||
clean::
|
clean::
|
||||||
-rm -f .depend
|
-rm -f .depend
|
||||||
|
@ -15,36 +15,62 @@ open Cli_entries
|
|||||||
module type Entity = sig
|
module type Entity = sig
|
||||||
type t
|
type t
|
||||||
val encoding : t Data_encoding.t
|
val encoding : t Data_encoding.t
|
||||||
val of_source : string -> t Lwt.t
|
val of_source :
|
||||||
val to_source : t -> string Lwt.t
|
Client_commands.context ->
|
||||||
|
string -> t Lwt.t
|
||||||
|
val to_source :
|
||||||
|
Client_commands.context ->
|
||||||
|
t -> string Lwt.t
|
||||||
val name : string
|
val name : string
|
||||||
end
|
end
|
||||||
|
|
||||||
module type Alias = sig
|
module type Alias = sig
|
||||||
type t
|
type t
|
||||||
val load : unit -> (Lwt_io.file_name * t) list Lwt.t
|
val load :
|
||||||
val find : Lwt_io.file_name -> t Lwt.t
|
Client_commands.context ->
|
||||||
val find_opt : Lwt_io.file_name -> t option Lwt.t
|
(string * t) list Lwt.t
|
||||||
val rev_find : t -> Lwt_io.file_name option Lwt.t
|
val find :
|
||||||
val name : t -> string Lwt.t
|
Client_commands.context ->
|
||||||
val mem : Lwt_io.file_name -> bool Lwt.t
|
string -> t Lwt.t
|
||||||
val add : Lwt_io.file_name -> t -> unit Lwt.t
|
val find_opt :
|
||||||
val del : Lwt_io.file_name -> unit Lwt.t
|
Client_commands.context ->
|
||||||
val save : (Lwt_io.file_name * t) list -> unit Lwt.t
|
string -> t option Lwt.t
|
||||||
val to_source : t -> string Lwt.t
|
val rev_find :
|
||||||
|
Client_commands.context ->
|
||||||
|
t -> string option Lwt.t
|
||||||
|
val name :
|
||||||
|
Client_commands.context ->
|
||||||
|
t -> string Lwt.t
|
||||||
|
val mem :
|
||||||
|
Client_commands.context ->
|
||||||
|
string -> bool Lwt.t
|
||||||
|
val add :
|
||||||
|
Client_commands.context ->
|
||||||
|
string -> t -> unit Lwt.t
|
||||||
|
val del :
|
||||||
|
Client_commands.context ->
|
||||||
|
string -> unit Lwt.t
|
||||||
|
val save :
|
||||||
|
Client_commands.context ->
|
||||||
|
(string * t) list -> unit Lwt.t
|
||||||
|
val to_source :
|
||||||
|
Client_commands.context ->
|
||||||
|
t -> string Lwt.t
|
||||||
val alias_param :
|
val alias_param :
|
||||||
?name:string ->
|
?name:string ->
|
||||||
?desc:string ->
|
?desc:string ->
|
||||||
'a Cli_entries.params ->
|
('a, Client_commands.context, 'ret) Cli_entries.params ->
|
||||||
(Lwt_io.file_name * t -> 'a) Cli_entries.params
|
(string * t -> 'a, Client_commands.context, 'ret) Cli_entries.params
|
||||||
val fresh_alias_param :
|
val fresh_alias_param :
|
||||||
?name:string ->
|
?name:string ->
|
||||||
?desc:string ->
|
?desc:string ->
|
||||||
'a Cli_entries.params -> (string -> 'a) Cli_entries.params
|
('a, Client_commands.context, 'ret) Cli_entries.params ->
|
||||||
|
(string -> 'a, Client_commands.context, 'ret) Cli_entries.params
|
||||||
val source_param :
|
val source_param :
|
||||||
?name:string ->
|
?name:string ->
|
||||||
?desc:string ->
|
?desc:string ->
|
||||||
'a Cli_entries.params -> (t -> 'a) Cli_entries.params
|
('a, Client_commands.context, 'ret) Cli_entries.params ->
|
||||||
|
(t -> 'a, Client_commands.context, 'ret) Cli_entries.params
|
||||||
end
|
end
|
||||||
|
|
||||||
module Alias = functor (Entity : Entity) -> struct
|
module Alias = functor (Entity : Entity) -> struct
|
||||||
@ -58,43 +84,46 @@ module Alias = functor (Entity : Entity) -> struct
|
|||||||
let filename () =
|
let filename () =
|
||||||
Client_config.(base_dir#get // Entity.name ^ "s")
|
Client_config.(base_dir#get // Entity.name ^ "s")
|
||||||
|
|
||||||
let load () =
|
let load cctxt =
|
||||||
let filename = filename () in
|
let filename = filename () in
|
||||||
if not (Sys.file_exists filename) then return [] else
|
if not (Sys.file_exists filename) then return [] else
|
||||||
Data_encoding_ezjsonm.read_file filename >>= function
|
Data_encoding_ezjsonm.read_file filename >>= function
|
||||||
| None ->
|
| None ->
|
||||||
error "couldn't to read the %s alias file" Entity.name
|
cctxt.Client_commands.error
|
||||||
|
"couldn't to read the %s alias file" Entity.name
|
||||||
| Some json ->
|
| Some json ->
|
||||||
match Data_encoding.Json.destruct encoding json with
|
match Data_encoding.Json.destruct encoding json with
|
||||||
| exception _ -> (* TODO print_error *)
|
| exception _ -> (* TODO print_error *)
|
||||||
error "didn't understand the %s alias file" Entity.name
|
cctxt.Client_commands.error
|
||||||
|
"didn't understand the %s alias file" Entity.name
|
||||||
| list ->
|
| list ->
|
||||||
return list
|
return list
|
||||||
|
|
||||||
let find_opt name =
|
let find_opt cctxt name =
|
||||||
load () >>= fun list ->
|
load cctxt >>= fun list ->
|
||||||
try return (Some (List.assoc name list))
|
try return (Some (List.assoc name list))
|
||||||
with Not_found -> return None
|
with Not_found -> return None
|
||||||
|
|
||||||
let find name =
|
let find cctxt name =
|
||||||
load () >>= fun list ->
|
load cctxt >>= fun list ->
|
||||||
try return (List.assoc name list)
|
try return (List.assoc name list)
|
||||||
with Not_found -> error "no %s alias named %s" Entity.name name
|
with Not_found ->
|
||||||
|
cctxt.Client_commands.error "no %s alias named %s" Entity.name name
|
||||||
|
|
||||||
let rev_find v =
|
let rev_find cctxt v =
|
||||||
load () >>= fun list ->
|
load cctxt >>= fun list ->
|
||||||
try return (Some (List.find (fun (_, v') -> v = v') list |> fst))
|
try return (Some (List.find (fun (_, v') -> v = v') list |> fst))
|
||||||
with Not_found -> return None
|
with Not_found -> return None
|
||||||
|
|
||||||
let mem name =
|
let mem cctxt name =
|
||||||
load () >>= fun list ->
|
load cctxt >>= fun list ->
|
||||||
try
|
try
|
||||||
ignore (List.assoc name list) ;
|
ignore (List.assoc name list) ;
|
||||||
Lwt.return true
|
Lwt.return true
|
||||||
with
|
with
|
||||||
| Not_found -> Lwt.return false
|
| Not_found -> Lwt.return false
|
||||||
|
|
||||||
let save list =
|
let save cctxt list =
|
||||||
catch
|
catch
|
||||||
(fun () ->
|
(fun () ->
|
||||||
let dirname = Client_config.base_dir#get in
|
let dirname = Client_config.base_dir#get in
|
||||||
@ -106,21 +135,25 @@ module Alias = functor (Entity : Entity) -> struct
|
|||||||
| false -> fail (Failure "Json.write_file")
|
| false -> fail (Failure "Json.write_file")
|
||||||
| true -> return ())
|
| true -> return ())
|
||||||
(fun exn ->
|
(fun exn ->
|
||||||
error "could not write the %s alias file: %s."
|
cctxt.Client_commands.error
|
||||||
|
"could not write the %s alias file: %s."
|
||||||
Entity.name (Printexc.to_string exn))
|
Entity.name (Printexc.to_string exn))
|
||||||
|
|
||||||
let add name value =
|
let add cctxt name value =
|
||||||
let keep = ref false in
|
let keep = ref false in
|
||||||
load () >>= fun list ->
|
load cctxt >>= fun list ->
|
||||||
(if not Client_config.force#get then
|
(if not Client_config.force#get then
|
||||||
Lwt_list.iter_s (fun (n, v) ->
|
Lwt_list.iter_s (fun (n, v) ->
|
||||||
if n = name && v = value then
|
if n = name && v = value then
|
||||||
(keep := true ;
|
(keep := true ;
|
||||||
message "The %s alias %s already exists with the same value." Entity.name n)
|
cctxt.Client_commands.message
|
||||||
|
"The %s alias %s already exists with the same value." Entity.name n)
|
||||||
else if n = name && v <> value then
|
else if n = name && v <> value then
|
||||||
error "another %s is already aliased as %s, use -force true to update" Entity.name n
|
cctxt.Client_commands.error
|
||||||
|
"another %s is already aliased as %s, use -force true to update" Entity.name n
|
||||||
else if n <> name && v = value then
|
else if n <> name && v = value then
|
||||||
error "this %s is already aliased as %s, use -force true to insert duplicate" Entity.name n
|
cctxt.Client_commands.error
|
||||||
|
"this %s is already aliased as %s, use -force true to insert duplicate" Entity.name n
|
||||||
else return ())
|
else return ())
|
||||||
list else return ()) >>= fun () ->
|
list else return ()) >>= fun () ->
|
||||||
let list = List.filter (fun (n, _) -> n <> name) list in
|
let list = List.filter (fun (n, _) -> n <> name) list in
|
||||||
@ -128,70 +161,73 @@ module Alias = functor (Entity : Entity) -> struct
|
|||||||
if !keep then
|
if !keep then
|
||||||
return ()
|
return ()
|
||||||
else
|
else
|
||||||
save list >>= fun () ->
|
save cctxt list >>= fun () ->
|
||||||
message "New %s alias '%s' saved." Entity.name name
|
cctxt.Client_commands.message
|
||||||
|
"New %s alias '%s' saved." Entity.name name
|
||||||
|
|
||||||
let del name =
|
let del cctxt name =
|
||||||
load () >>= fun list ->
|
load cctxt >>= fun list ->
|
||||||
let list = List.filter (fun (n, _) -> n <> name) list in
|
let list = List.filter (fun (n, _) -> n <> name) list in
|
||||||
save list
|
save cctxt list
|
||||||
|
|
||||||
let save list =
|
let save cctxt list =
|
||||||
save list >>= fun () ->
|
save cctxt list >>= fun () ->
|
||||||
message "Successful update of the %s alias file." Entity.name
|
cctxt.Client_commands.message
|
||||||
|
"Successful update of the %s alias file." Entity.name
|
||||||
|
|
||||||
include Entity
|
include Entity
|
||||||
|
|
||||||
let alias_param ?(name = "name") ?(desc = "existing " ^ name ^ " alias") next =
|
let alias_param ?(name = "name") ?(desc = "existing " ^ Entity.name ^ " alias") next =
|
||||||
param ~name ~desc
|
param ~name ~desc
|
||||||
(fun s -> find s >>= fun v -> return (s, v))
|
(fun cctxt s -> find cctxt s >>= fun v -> return (s, v))
|
||||||
next
|
next
|
||||||
|
|
||||||
let fresh_alias_param ?(name = "new") ?(desc = "new " ^ name ^ " alias") next =
|
let fresh_alias_param ?(name = "new") ?(desc = "new " ^ Entity.name ^ " alias") next =
|
||||||
param ~name ~desc
|
param ~name ~desc
|
||||||
(fun s ->
|
(fun cctxt s ->
|
||||||
load () >>= fun list ->
|
load cctxt >>= fun list ->
|
||||||
if not Client_config.force#get then
|
if not Client_config.force#get then
|
||||||
Lwt_list.iter_s (fun (n, _v) ->
|
Lwt_list.iter_s (fun (n, _v) ->
|
||||||
if n = name then
|
if n = s then
|
||||||
error "the %s alias %s already exists, use -force true to update" Entity.name n
|
cctxt.Client_commands.error
|
||||||
|
"the %s alias %s already exists, use -force true to update" Entity.name n
|
||||||
else return ())
|
else return ())
|
||||||
list >>= fun () ->
|
list >>= fun () ->
|
||||||
return s
|
return s
|
||||||
else return s)
|
else return s)
|
||||||
next
|
next
|
||||||
|
|
||||||
let source_param ?(name = "src") ?(desc = "source " ^ name) next =
|
let source_param ?(name = "src") ?(desc = "source " ^ Entity.name) next =
|
||||||
let desc =
|
let desc =
|
||||||
desc ^ "\n"
|
desc ^ "\n"
|
||||||
^ "can be an alias, file or literal (autodetected in this order)\n\
|
^ "can be an alias, file or literal (autodetected in this order)\n\
|
||||||
use 'file:path', 'text:literal' or 'alias:name' to force" in
|
use 'file:path', 'text:literal' or 'alias:name' to force" in
|
||||||
param ~name ~desc
|
param ~name ~desc
|
||||||
(fun s ->
|
(fun cctxt s ->
|
||||||
let read path =
|
let read path =
|
||||||
catch
|
catch
|
||||||
(fun () -> Lwt_io.(with_file ~mode:Input path read))
|
(fun () -> Lwt_io.(with_file ~mode:Input path read))
|
||||||
(fun exn -> Lwt.fail_with @@ Format.asprintf "cannot read file (%s)" (Printexc.to_string exn))
|
(fun exn -> Lwt.fail_with @@ Format.asprintf "cannot read file (%s)" (Printexc.to_string exn))
|
||||||
>>= of_source in
|
>>= of_source cctxt in
|
||||||
match Utils.split ~limit:1 ':' s with
|
match Utils.split ~limit:1 ':' s with
|
||||||
| [ "alias" ; alias ]->
|
| [ "alias" ; alias ]->
|
||||||
find alias
|
find cctxt alias
|
||||||
| [ "text" ; text ] ->
|
| [ "text" ; text ] ->
|
||||||
of_source text
|
of_source cctxt text
|
||||||
| [ "file" ; path ] ->
|
| [ "file" ; path ] ->
|
||||||
read path
|
read path
|
||||||
| _ ->
|
| _ ->
|
||||||
catch
|
catch
|
||||||
(fun () -> find s)
|
(fun () -> find cctxt s)
|
||||||
(fun _ ->
|
(fun _ ->
|
||||||
catch
|
catch
|
||||||
(fun () -> read s)
|
(fun () -> read s)
|
||||||
(fun _ -> of_source s)))
|
(fun _ -> of_source cctxt s)))
|
||||||
next
|
next
|
||||||
|
|
||||||
let name d =
|
let name cctxt d =
|
||||||
rev_find d >>= function
|
rev_find cctxt d >>= function
|
||||||
| None -> Entity.to_source d
|
| None -> Entity.to_source cctxt d
|
||||||
| Some name -> Lwt.return name
|
| Some name -> Lwt.return name
|
||||||
|
|
||||||
end
|
end
|
||||||
|
@ -11,35 +11,61 @@
|
|||||||
module type Entity = sig
|
module type Entity = sig
|
||||||
type t
|
type t
|
||||||
val encoding : t Data_encoding.t
|
val encoding : t Data_encoding.t
|
||||||
val of_source : string -> t Lwt.t
|
val of_source :
|
||||||
val to_source : t -> string Lwt.t
|
Client_commands.context ->
|
||||||
|
string -> t Lwt.t
|
||||||
|
val to_source :
|
||||||
|
Client_commands.context ->
|
||||||
|
t -> string Lwt.t
|
||||||
val name : string
|
val name : string
|
||||||
end
|
end
|
||||||
|
|
||||||
module type Alias = sig
|
module type Alias = sig
|
||||||
type t
|
type t
|
||||||
val load : unit -> (Lwt_io.file_name * t) list Lwt.t
|
val load :
|
||||||
val find : Lwt_io.file_name -> t Lwt.t
|
Client_commands.context ->
|
||||||
val find_opt : Lwt_io.file_name -> t option Lwt.t
|
(string * t) list Lwt.t
|
||||||
val rev_find : t -> Lwt_io.file_name option Lwt.t
|
val find :
|
||||||
val name : t -> string Lwt.t
|
Client_commands.context ->
|
||||||
val mem : Lwt_io.file_name -> bool Lwt.t
|
string -> t Lwt.t
|
||||||
val add : Lwt_io.file_name -> t -> unit Lwt.t
|
val find_opt :
|
||||||
val del : Lwt_io.file_name -> unit Lwt.t
|
Client_commands.context ->
|
||||||
val save : (Lwt_io.file_name * t) list -> unit Lwt.t
|
string -> t option Lwt.t
|
||||||
val to_source : t -> string Lwt.t
|
val rev_find :
|
||||||
|
Client_commands.context ->
|
||||||
|
t -> string option Lwt.t
|
||||||
|
val name :
|
||||||
|
Client_commands.context ->
|
||||||
|
t -> string Lwt.t
|
||||||
|
val mem :
|
||||||
|
Client_commands.context ->
|
||||||
|
string -> bool Lwt.t
|
||||||
|
val add :
|
||||||
|
Client_commands.context ->
|
||||||
|
string -> t -> unit Lwt.t
|
||||||
|
val del :
|
||||||
|
Client_commands.context ->
|
||||||
|
string -> unit Lwt.t
|
||||||
|
val save :
|
||||||
|
Client_commands.context ->
|
||||||
|
(string * t) list -> unit Lwt.t
|
||||||
|
val to_source :
|
||||||
|
Client_commands.context ->
|
||||||
|
t -> string Lwt.t
|
||||||
val alias_param :
|
val alias_param :
|
||||||
?name:string ->
|
?name:string ->
|
||||||
?desc:string ->
|
?desc:string ->
|
||||||
'a Cli_entries.params ->
|
('a, Client_commands.context, 'ret) Cli_entries.params ->
|
||||||
(Lwt_io.file_name * t -> 'a) Cli_entries.params
|
(string * t -> 'a, Client_commands.context, 'ret) Cli_entries.params
|
||||||
val fresh_alias_param :
|
val fresh_alias_param :
|
||||||
?name:string ->
|
?name:string ->
|
||||||
?desc:string ->
|
?desc:string ->
|
||||||
'a Cli_entries.params -> (string -> 'a) Cli_entries.params
|
('a, Client_commands.context, 'ret) Cli_entries.params ->
|
||||||
|
(string -> 'a, Client_commands.context, 'ret) Cli_entries.params
|
||||||
val source_param :
|
val source_param :
|
||||||
?name:string ->
|
?name:string ->
|
||||||
?desc:string ->
|
?desc:string ->
|
||||||
'a Cli_entries.params -> (t -> 'a) Cli_entries.params
|
('a, Client_commands.context, 'ret) Cli_entries.params ->
|
||||||
|
(t -> 'a, Client_commands.context, 'ret) Cli_entries.params
|
||||||
end
|
end
|
||||||
module Alias (Entity : Entity) : Alias with type t = Entity.t
|
module Alias (Entity : Entity) : Alias with type t = Entity.t
|
||||||
|
@ -7,8 +7,42 @@
|
|||||||
(* *)
|
(* *)
|
||||||
(**************************************************************************)
|
(**************************************************************************)
|
||||||
|
|
||||||
|
type ('a, 'b) lwt_format =
|
||||||
|
('a, Format.formatter, unit, 'b Lwt.t) format4
|
||||||
|
|
||||||
(* A global store for version indexed commands. *)
|
type context =
|
||||||
|
{ error : 'a 'b. ('a, 'b) lwt_format -> 'a ;
|
||||||
|
warning : 'a. ('a, unit) lwt_format -> 'a ;
|
||||||
|
message : 'a. ('a, unit) lwt_format -> 'a ;
|
||||||
|
answer : 'a. ('a, unit) lwt_format -> 'a ;
|
||||||
|
log : 'a. string -> ('a, unit) lwt_format -> 'a }
|
||||||
|
|
||||||
|
type command = (context, unit) Cli_entries.command
|
||||||
|
|
||||||
|
let make_context log =
|
||||||
|
let error fmt =
|
||||||
|
Format.kasprintf
|
||||||
|
(fun msg ->
|
||||||
|
Lwt.fail (Failure msg))
|
||||||
|
fmt in
|
||||||
|
let warning fmt =
|
||||||
|
Format.kasprintf
|
||||||
|
(fun msg -> log "stderr" msg)
|
||||||
|
fmt in
|
||||||
|
let message fmt =
|
||||||
|
Format.kasprintf
|
||||||
|
(fun msg -> log "stdout" msg)
|
||||||
|
fmt in
|
||||||
|
let answer =
|
||||||
|
message in
|
||||||
|
let log name fmt =
|
||||||
|
Format.kasprintf
|
||||||
|
(fun msg -> log name msg)
|
||||||
|
fmt in
|
||||||
|
{ error ; warning ; message ; answer ; log }
|
||||||
|
|
||||||
|
let ignore_context =
|
||||||
|
make_context (fun _ _ -> Lwt.return ())
|
||||||
|
|
||||||
exception Version_not_found
|
exception Version_not_found
|
||||||
|
|
30
src/client/client_commands.mli
Normal file
30
src/client/client_commands.mli
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
(**************************************************************************)
|
||||||
|
(* *)
|
||||||
|
(* Copyright (c) 2014 - 2016. *)
|
||||||
|
(* Dynamic Ledger Solutions, Inc. <contact@tezos.com> *)
|
||||||
|
(* *)
|
||||||
|
(* All rights reserved. No warranty, explicit or implicit, provided. *)
|
||||||
|
(* *)
|
||||||
|
(**************************************************************************)
|
||||||
|
|
||||||
|
type ('a, 'b) lwt_format =
|
||||||
|
('a, Format.formatter, unit, 'b Lwt.t) format4
|
||||||
|
|
||||||
|
type context =
|
||||||
|
{ error : 'a 'b. ('a, 'b) lwt_format -> 'a ;
|
||||||
|
warning : 'a. ('a, unit) lwt_format -> 'a ;
|
||||||
|
message : 'a. ('a, unit) lwt_format -> 'a ;
|
||||||
|
answer : 'a. ('a, unit) lwt_format -> 'a ;
|
||||||
|
log : 'a. string -> ('a, unit) lwt_format -> 'a }
|
||||||
|
|
||||||
|
val make_context : (string -> string -> unit Lwt.t) -> context
|
||||||
|
|
||||||
|
val ignore_context : context
|
||||||
|
|
||||||
|
type command = (context, unit) Cli_entries.command
|
||||||
|
|
||||||
|
exception Version_not_found
|
||||||
|
|
||||||
|
val register: Protocol_hash.t -> command list -> unit
|
||||||
|
val commands_for_version: Protocol_hash.t -> command list
|
||||||
|
val get_versions: unit -> (Protocol_hash.t * (command list)) list
|
@ -102,53 +102,64 @@ let register_config_option version option =
|
|||||||
|
|
||||||
(* Entry point *)
|
(* Entry point *)
|
||||||
|
|
||||||
let parse_args ?version usage dispatcher =
|
let parse_args ?version usage dispatcher argv cctxt =
|
||||||
let open Lwt in
|
let open Lwt in
|
||||||
try begin match version with
|
catch
|
||||||
|
(fun () ->
|
||||||
|
let args = ref (cli_group#command_line_args "-") in
|
||||||
|
begin match version with
|
||||||
| None -> ()
|
| None -> ()
|
||||||
| Some version ->
|
| Some version ->
|
||||||
try
|
try
|
||||||
!(Protocol_hash_table.find contextual_options version) ()
|
!(Protocol_hash_table.find contextual_options version) ()
|
||||||
with Not_found -> () end ;
|
with Not_found -> () end ;
|
||||||
let base_args = cli_group#command_line_args "-" in
|
|
||||||
let args = ref base_args in
|
|
||||||
let anon dispatch n = match dispatch (`Arg n) with
|
let anon dispatch n = match dispatch (`Arg n) with
|
||||||
| `Nop -> ()
|
| `Nop -> ()
|
||||||
| `Args nargs -> args := nargs @ !args
|
| `Args nargs -> args := nargs @ !args
|
||||||
| `Fail exn -> raise exn
|
| `Fail exn -> raise exn
|
||||||
| `Res _ -> assert false in
|
| `Res _ -> assert false in
|
||||||
Arg.parse_argv_dynamic
|
Arg.parse_argv_dynamic
|
||||||
~current:(ref 0) Sys.argv args (anon (dispatcher ())) (usage base_args) ;
|
~current:(ref 0) argv args (anon (dispatcher ())) "\000" ;
|
||||||
let dispatch = dispatcher () in
|
let dispatch = dispatcher () in
|
||||||
(if Sys.file_exists config_file#get then begin
|
(if Sys.file_exists config_file#get then begin
|
||||||
try
|
try
|
||||||
file_group#read config_file#get ;
|
file_group#read config_file#get ;
|
||||||
(* parse once again to overwrite file options by cli ones *)
|
(* parse once again to overwrite file options by cli ones *)
|
||||||
Arg.parse_argv_dynamic
|
Arg.parse_argv_dynamic
|
||||||
~current:(ref 0) Sys.argv args (anon dispatch) (usage base_args) ;
|
~current:(ref 0) argv args (anon dispatch) "\000" ;
|
||||||
Lwt.return ()
|
Lwt.return ()
|
||||||
with Sys_error msg ->
|
with Sys_error msg ->
|
||||||
Cli_entries.error
|
cctxt.Client_commands.error
|
||||||
"Error: can't read the configuration file: %s\n%!" msg
|
"Error: can't read the configuration file: %s\n%!" msg
|
||||||
end else begin
|
end else begin
|
||||||
try
|
try
|
||||||
(* parse once again with contextual options *)
|
(* parse once again with contextual options *)
|
||||||
Arg.parse_argv_dynamic
|
Arg.parse_argv_dynamic
|
||||||
~current:(ref 0) Sys.argv args (anon dispatch) (usage base_args) ;
|
~current:(ref 0) argv args (anon dispatch) "\000" ;
|
||||||
Lwt_utils.create_dir (Filename.dirname config_file#get) >>= fun () ->
|
Lwt_utils.create_dir (Filename.dirname config_file#get) >>= fun () ->
|
||||||
file_group#write config_file#get ;
|
file_group#write config_file#get ;
|
||||||
Lwt.return ()
|
Lwt.return ()
|
||||||
with Sys_error msg ->
|
with Sys_error msg ->
|
||||||
Cli_entries.warning
|
cctxt.Client_commands.warning
|
||||||
"Warning: can't create the default configuration file: %s\n%!" msg
|
"Warning: can't create the default configuration file: %s\n%!" msg
|
||||||
end) >>= fun () ->
|
end) >>= fun () ->
|
||||||
begin match dispatch `End with
|
begin match dispatch `End with
|
||||||
| `Res res ->
|
| `Res res -> Lwt.return res
|
||||||
res
|
|
||||||
| `Fail exn -> fail exn
|
| `Fail exn -> fail exn
|
||||||
| `Nop | `Args _ -> assert false
|
| `Nop | `Args _ -> assert false
|
||||||
end
|
end)
|
||||||
with exn -> Lwt.fail exn
|
(function
|
||||||
|
| Arg.Bad msg ->
|
||||||
|
(* FIXME: this is an ugly hack to circumvent [Arg]
|
||||||
|
spuriously printing options at the end of the error
|
||||||
|
message. *)
|
||||||
|
let args = cli_group#command_line_args "-" in
|
||||||
|
let msg = List.hd (Utils.split '\000' msg) in
|
||||||
|
Lwt.fail (Arg.Help (msg ^ usage args ^ "\n"))
|
||||||
|
| Arg.Help _ ->
|
||||||
|
let args = cli_group#command_line_args "-" in
|
||||||
|
Lwt.fail (Arg.Help (usage args ^ "\n"))
|
||||||
|
| exn -> Lwt.fail exn)
|
||||||
|
|
||||||
exception Found of string
|
exception Found of string
|
||||||
let preparse name argv =
|
let preparse name argv =
|
||||||
@ -160,14 +171,14 @@ let preparse name argv =
|
|||||||
None
|
None
|
||||||
with Found s -> Some s
|
with Found s -> Some s
|
||||||
|
|
||||||
let preparse_args () : Node_rpc_services.Blocks.block Lwt.t =
|
let preparse_args argv cctxt : Node_rpc_services.Blocks.block Lwt.t =
|
||||||
begin
|
begin
|
||||||
match preparse "-base-dir" Sys.argv with
|
match preparse "-base-dir" argv with
|
||||||
| None -> ()
|
| None -> ()
|
||||||
| Some dir -> base_dir#set dir
|
| Some dir -> base_dir#set dir
|
||||||
end ;
|
end ;
|
||||||
begin
|
begin
|
||||||
match preparse "-config-file" Sys.argv with
|
match preparse "-config-file" argv with
|
||||||
| None -> config_file#set @@ base_dir#get // "config"
|
| None -> config_file#set @@ base_dir#get // "config"
|
||||||
| Some file -> config_file#set file
|
| Some file -> config_file#set file
|
||||||
end ;
|
end ;
|
||||||
@ -176,24 +187,24 @@ let preparse_args () : Node_rpc_services.Blocks.block Lwt.t =
|
|||||||
(file_group#read config_file#get ;
|
(file_group#read config_file#get ;
|
||||||
Lwt.return ())
|
Lwt.return ())
|
||||||
with Sys_error msg ->
|
with Sys_error msg ->
|
||||||
Cli_entries.error
|
cctxt.Client_commands.error
|
||||||
"Error: can't read the configuration file: %s\n%!" msg
|
"Error: can't read the configuration file: %s\n%!" msg
|
||||||
else Lwt.return ()
|
else Lwt.return ()
|
||||||
end >>= fun () ->
|
end >>= fun () ->
|
||||||
begin
|
begin
|
||||||
match preparse "-addr" Sys.argv with
|
match preparse "-addr" argv with
|
||||||
| None -> ()
|
| None -> ()
|
||||||
| Some addr -> incoming_addr#set addr
|
| Some addr -> incoming_addr#set addr
|
||||||
end ;
|
end ;
|
||||||
begin
|
begin
|
||||||
match preparse "-port" Sys.argv with
|
match preparse "-port" argv with
|
||||||
| None -> Lwt.return ()
|
| None -> Lwt.return ()
|
||||||
| Some port ->
|
| Some port ->
|
||||||
try
|
try
|
||||||
incoming_port#set (int_of_string port) ;
|
incoming_port#set (int_of_string port) ;
|
||||||
Lwt.return ()
|
Lwt.return ()
|
||||||
with _ ->
|
with _ ->
|
||||||
Cli_entries.error
|
cctxt.Client_commands.error
|
||||||
"Error: can't parse the -port option: %S.\n%!" port
|
"Error: can't parse the -port option: %S.\n%!" port
|
||||||
end >>= fun () ->
|
end >>= fun () ->
|
||||||
match preparse "-block" Sys.argv with
|
match preparse "-block" Sys.argv with
|
||||||
@ -201,6 +212,6 @@ let preparse_args () : Node_rpc_services.Blocks.block Lwt.t =
|
|||||||
| Some x ->
|
| Some x ->
|
||||||
match Node_rpc_services.Blocks.parse_block x with
|
match Node_rpc_services.Blocks.parse_block x with
|
||||||
| Error _ ->
|
| Error _ ->
|
||||||
Cli_entries.error
|
cctxt.Client_commands.error
|
||||||
"Error: can't parse the -block option: %S.\n%!" x
|
"Error: can't parse the -block option: %S.\n%!" x
|
||||||
| Ok b -> Lwt.return b
|
| Ok b -> Lwt.return b
|
||||||
|
@ -192,9 +192,9 @@ let rec count =
|
|||||||
|
|
||||||
(*-- Commands ---------------------------------------------------------------*)
|
(*-- Commands ---------------------------------------------------------------*)
|
||||||
|
|
||||||
let list url () =
|
let list url cctxt =
|
||||||
let args = Utils.split '/' url in
|
let args = Utils.split '/' url in
|
||||||
Client_node_rpcs.describe ~recurse:true args >>= fun tree ->
|
Client_node_rpcs.describe cctxt ~recurse:true args >>= fun tree ->
|
||||||
let open RPC.Description in
|
let open RPC.Description in
|
||||||
let collected_args = ref [] in
|
let collected_args = ref [] in
|
||||||
let collect arg =
|
let collect arg =
|
||||||
@ -272,24 +272,24 @@ let list url () =
|
|||||||
Format.pp_print_list
|
Format.pp_print_list
|
||||||
(fun ppf (n,t) -> display ppf ([ n ], tpath @ [ n ], t))
|
(fun ppf (n,t) -> display ppf ([ n ], tpath @ [ n ], t))
|
||||||
in
|
in
|
||||||
Cli_entries.message "@ @[<v 2>Available services:@ @ %a@]@."
|
cctxt.message "@ @[<v 2>Available services:@ @ %a@]@."
|
||||||
display (args, args, tree) >>= fun () ->
|
display (args, args, tree) >>= fun () ->
|
||||||
if !collected_args <> [] then
|
if !collected_args <> [] then
|
||||||
Cli_entries.message "@,@[<v 2>Dynamic parameter description:@ @ %a@]@."
|
cctxt.message "@,@[<v 2>Dynamic parameter description:@ @ %a@]@."
|
||||||
(Format.pp_print_list display_arg) !collected_args
|
(Format.pp_print_list display_arg) !collected_args
|
||||||
else Lwt.return ()
|
else Lwt.return ()
|
||||||
|
|
||||||
|
|
||||||
let schema url () =
|
let schema url cctxt =
|
||||||
let args = Utils.split '/' url in
|
let args = Utils.split '/' url in
|
||||||
let open RPC.Description in
|
let open RPC.Description in
|
||||||
Client_node_rpcs.describe ~recurse:false args >>= function
|
Client_node_rpcs.describe cctxt ~recurse:false args >>= function
|
||||||
| Static { service = Some { input ; output } } ->
|
| Static { service = Some { input ; output } } ->
|
||||||
Cli_entries.message "Input schema:\n%s\nOutput schema:\n%s\n%!"
|
cctxt.message "Input schema:\n%s\nOutput schema:\n%s\n%!"
|
||||||
(Data_encoding_ezjsonm.to_string (Json_schema.to_json input))
|
(Data_encoding_ezjsonm.to_string (Json_schema.to_json input))
|
||||||
(Data_encoding_ezjsonm.to_string (Json_schema.to_json output))
|
(Data_encoding_ezjsonm.to_string (Json_schema.to_json output))
|
||||||
| _ ->
|
| _ ->
|
||||||
Cli_entries.message
|
cctxt.message
|
||||||
"No service found at this URL (but this is a valid prefix)\n%!"
|
"No service found at this URL (but this is a valid prefix)\n%!"
|
||||||
|
|
||||||
let fill_in schema =
|
let fill_in schema =
|
||||||
@ -299,60 +299,43 @@ let fill_in schema =
|
|||||||
| Any | Object { properties = [] } -> Lwt.return (Ok (`O []))
|
| Any | Object { properties = [] } -> Lwt.return (Ok (`O []))
|
||||||
| _ -> editor_fill_in schema
|
| _ -> editor_fill_in schema
|
||||||
|
|
||||||
let call url () =
|
let call url cctxt =
|
||||||
let args = Utils.split '/' url in
|
let args = Utils.split '/' url in
|
||||||
let open RPC.Description in
|
let open RPC.Description in
|
||||||
Client_node_rpcs.describe ~recurse:false args >>= function
|
Client_node_rpcs.describe cctxt ~recurse:false args >>= function
|
||||||
| Static { service = Some { input } } -> begin
|
| Static { service = Some { input } } -> begin
|
||||||
fill_in input >>= function
|
fill_in input >>= function
|
||||||
| Error msg ->
|
| Error msg ->
|
||||||
error "%s" msg
|
cctxt.error "%s" msg
|
||||||
| Ok json ->
|
| Ok json ->
|
||||||
Client_node_rpcs.get_json args json >>= fun json ->
|
Client_node_rpcs.get_json cctxt args json >>= fun json ->
|
||||||
Cli_entries.message "Output:\n%s\n%!" (Data_encoding_ezjsonm.to_string json)
|
cctxt.message "Output:\n%s\n%!" (Data_encoding_ezjsonm.to_string json)
|
||||||
end
|
end
|
||||||
| _ ->
|
| _ ->
|
||||||
Cli_entries.message
|
cctxt.message
|
||||||
"No service found at this URL (but this is a valid prefix)\n%!"
|
"No service found at this URL (but this is a valid prefix)\n%!"
|
||||||
|
|
||||||
let () =
|
let group =
|
||||||
let open Cli_entries in
|
{ Cli_entries.name = "rpc" ;
|
||||||
register_tag "low-level" "low level commands for advanced users" ;
|
title = "Commands for the low level RPC layer" }
|
||||||
register_tag "local" "commands that do not require a running node" ;
|
|
||||||
register_tag "debug" "commands mostly useful for debugging" ;
|
|
||||||
register_group "rpc" "Commands for the low level RPC layer"
|
|
||||||
|
|
||||||
let commands = Cli_entries.([
|
let commands = [
|
||||||
command
|
command ~desc: "list all understood protocol versions"
|
||||||
~tags: [ "local" ]
|
|
||||||
~desc: "list all understood protocol versions"
|
|
||||||
(fixed [ "list" ; "versions" ])
|
(fixed [ "list" ; "versions" ])
|
||||||
(fun () ->
|
(fun cctxt ->
|
||||||
Lwt_list.iter_s
|
Lwt_list.iter_s
|
||||||
(fun (ver, _) -> message "%a" Protocol_hash.pp_short ver)
|
(fun (ver, _) -> cctxt.Client_commands.message "%a" Protocol_hash.pp_short ver)
|
||||||
(Client_version.get_versions ())) ;
|
(Client_commands.get_versions ())) ;
|
||||||
command
|
command ~group ~desc: "list available RPCs (low level command for advanced users)"
|
||||||
~tags: [ "low-level" ; "local" ]
|
|
||||||
~group: "rpc"
|
|
||||||
~desc: "list available RPCs (low level command for advanced users)"
|
|
||||||
(prefixes [ "rpc" ; "list" ] @@ stop)
|
(prefixes [ "rpc" ; "list" ] @@ stop)
|
||||||
(list "/");
|
(list "/");
|
||||||
command
|
command ~group ~desc: "list available RPCs (low level command for advanced users)"
|
||||||
~tags: [ "low-level" ; "local" ]
|
(prefixes [ "rpc" ; "list" ] @@ string ~name:"url" ~desc: "the RPC's prefix to be described" @@ stop)
|
||||||
~group: "rpc"
|
|
||||||
~desc: "list available RPCs (low level command for advanced users)"
|
|
||||||
(prefixes [ "rpc" ; "list" ] @@ string "url" "the RPC's prefix to be described" @@ stop)
|
|
||||||
list ;
|
list ;
|
||||||
command
|
command ~group ~desc: "get the schemas of an RPC"
|
||||||
~tags: [ "low-level" ; "local" ]
|
(prefixes [ "rpc" ; "schema" ] @@ string ~name: "url" ~desc: "the RPC's URL" @@ stop)
|
||||||
~group: "rpc"
|
|
||||||
~desc: "get the schemas of an RPC"
|
|
||||||
(prefixes [ "rpc" ; "schema" ] @@ string "url" "the RPC's URL" @@ stop)
|
|
||||||
schema ;
|
schema ;
|
||||||
command
|
command ~group ~desc: "call an RPC (low level command for advanced users)"
|
||||||
~tags: [ "low-level" ; "local" ]
|
(prefixes [ "rpc" ; "call" ] @@ string ~name: "url" ~desc: "the RPC's URL" @@ stop)
|
||||||
~group: "rpc"
|
|
||||||
~desc: "call an RPC (low level command for advanced users)"
|
|
||||||
(prefixes [ "rpc" ; "call" ] @@ string "url" "the RPC's URL" @@ stop)
|
|
||||||
call
|
call
|
||||||
])
|
]
|
||||||
|
@ -7,4 +7,4 @@
|
|||||||
(* *)
|
(* *)
|
||||||
(**************************************************************************)
|
(**************************************************************************)
|
||||||
|
|
||||||
val commands: Cli_entries.command list
|
val commands: Client_commands.command list
|
||||||
|
@ -9,10 +9,6 @@
|
|||||||
|
|
||||||
open Client_config
|
open Client_config
|
||||||
|
|
||||||
let () =
|
|
||||||
let open Cli_entries in
|
|
||||||
register_group "helpers" "Various helpers"
|
|
||||||
|
|
||||||
let unique = ref false
|
let unique = ref false
|
||||||
let unique_arg =
|
let unique_arg =
|
||||||
"-unique",
|
"-unique",
|
||||||
@ -26,9 +22,13 @@ let commands () = Cli_entries.[
|
|||||||
works only for blocks, operations, public key and contract \
|
works only for blocks, operations, public key and contract \
|
||||||
identifiers."
|
identifiers."
|
||||||
~args: [unique_arg]
|
~args: [unique_arg]
|
||||||
(prefixes [ "complete" ] @@ string "prefix" "the prefix of the Base48Check-encoded hash to be completed" @@ stop)
|
(prefixes [ "complete" ] @@
|
||||||
(fun prefix () ->
|
string
|
||||||
Client_node_rpcs.complete ~block:(block ()) prefix >>= fun completions ->
|
~name: "prefix"
|
||||||
|
~desc: "the prefix of the Base48Check-encoded hash to be completed" @@
|
||||||
|
stop)
|
||||||
|
(fun prefix cctxt ->
|
||||||
|
Client_node_rpcs.complete cctxt ~block:(block ()) prefix >>= fun completions ->
|
||||||
match completions with
|
match completions with
|
||||||
| [] -> Pervasives.exit 3
|
| [] -> Pervasives.exit 3
|
||||||
| _ :: _ :: _ when !unique -> Pervasives.exit 3
|
| _ :: _ :: _ when !unique -> Pervasives.exit 3
|
||||||
|
@ -7,4 +7,4 @@
|
|||||||
(* *)
|
(* *)
|
||||||
(**************************************************************************)
|
(**************************************************************************)
|
||||||
|
|
||||||
val commands: unit -> Cli_entries.command list
|
val commands: unit -> Client_commands.command list
|
||||||
|
@ -12,18 +12,18 @@ module Ed25519 = Environment.Ed25519
|
|||||||
module Public_key_hash = Client_aliases.Alias (struct
|
module Public_key_hash = Client_aliases.Alias (struct
|
||||||
type t = Ed25519.Public_key_hash.t
|
type t = Ed25519.Public_key_hash.t
|
||||||
let encoding = Ed25519.Public_key_hash.encoding
|
let encoding = Ed25519.Public_key_hash.encoding
|
||||||
let of_source s = Lwt.return (Ed25519.Public_key_hash.of_b48check s)
|
let of_source _ s = Lwt.return (Ed25519.Public_key_hash.of_b48check s)
|
||||||
let to_source p = Lwt.return (Ed25519.Public_key_hash.to_b48check p)
|
let to_source _ p = Lwt.return (Ed25519.Public_key_hash.to_b48check p)
|
||||||
let name = "public key hash"
|
let name = "public key hash"
|
||||||
end)
|
end)
|
||||||
|
|
||||||
module Public_key = Client_aliases.Alias (struct
|
module Public_key = Client_aliases.Alias (struct
|
||||||
type t = Ed25519.public_key
|
type t = Ed25519.public_key
|
||||||
let encoding = Ed25519.public_key_encoding
|
let encoding = Ed25519.public_key_encoding
|
||||||
let of_source s =
|
let of_source _ s =
|
||||||
Lwt.return (Sodium.Sign.Bytes.to_public_key
|
Lwt.return (Sodium.Sign.Bytes.to_public_key
|
||||||
(Bytes.of_string B64.(decode ~alphabet:uri_safe_alphabet s)))
|
(Bytes.of_string B64.(decode ~alphabet:uri_safe_alphabet s)))
|
||||||
let to_source p =
|
let to_source _ p =
|
||||||
Lwt.return B64.(encode ~alphabet:uri_safe_alphabet
|
Lwt.return B64.(encode ~alphabet:uri_safe_alphabet
|
||||||
(Bytes.to_string (Sodium.Sign.Bytes.of_public_key p)))
|
(Bytes.to_string (Sodium.Sign.Bytes.of_public_key p)))
|
||||||
let name = "public key"
|
let name = "public key"
|
||||||
@ -32,106 +32,99 @@ module Public_key = Client_aliases.Alias (struct
|
|||||||
module Secret_key = Client_aliases.Alias (struct
|
module Secret_key = Client_aliases.Alias (struct
|
||||||
type t = Ed25519.secret_key
|
type t = Ed25519.secret_key
|
||||||
let encoding = Ed25519.secret_key_encoding
|
let encoding = Ed25519.secret_key_encoding
|
||||||
let of_source s =
|
let of_source _ s =
|
||||||
Lwt.return (Sodium.Sign.Bytes.to_secret_key
|
Lwt.return (Sodium.Sign.Bytes.to_secret_key
|
||||||
(Bytes.of_string B64.(decode ~alphabet:uri_safe_alphabet s)))
|
(Bytes.of_string B64.(decode ~alphabet:uri_safe_alphabet s)))
|
||||||
let to_source p =
|
let to_source _ p =
|
||||||
Lwt.return B64.(encode ~alphabet:uri_safe_alphabet
|
Lwt.return B64.(encode ~alphabet:uri_safe_alphabet
|
||||||
(Bytes.to_string (Sodium.Sign.Bytes.of_secret_key p)))
|
(Bytes.to_string (Sodium.Sign.Bytes.of_secret_key p)))
|
||||||
let name = "secret key"
|
let name = "secret key"
|
||||||
end)
|
end)
|
||||||
|
|
||||||
let gen_keys name =
|
let gen_keys cctxt name =
|
||||||
let secret_key, public_key = Sodium.Sign.random_keypair () in
|
let secret_key, public_key = Sodium.Sign.random_keypair () in
|
||||||
Secret_key.add name secret_key >>= fun () ->
|
Secret_key.add cctxt name secret_key >>= fun () ->
|
||||||
Public_key.add name public_key >>= fun () ->
|
Public_key.add cctxt name public_key >>= fun () ->
|
||||||
Public_key_hash.add name (Ed25519.hash public_key) >>= fun () ->
|
Public_key_hash.add cctxt name (Ed25519.hash public_key) >>= fun () ->
|
||||||
Cli_entries.message "I generated a brand new pair of keys under the name '%s'." name
|
cctxt.message "I generated a brand new pair of keys under the name '%s'." name
|
||||||
|
|
||||||
let check_keys_consistency pk sk =
|
let check_keys_consistency pk sk =
|
||||||
let message = MBytes.of_string "Voulez-vous coucher avec moi, ce soir ?" in
|
let message = MBytes.of_string "Voulez-vous coucher avec moi, ce soir ?" in
|
||||||
let signature = Ed25519.sign sk message in
|
let signature = Ed25519.sign sk message in
|
||||||
Ed25519.check_signature pk signature message
|
Ed25519.check_signature pk signature message
|
||||||
|
|
||||||
let get_key pkh =
|
let get_key cctxt pkh =
|
||||||
Public_key_hash.rev_find pkh >>= function
|
Public_key_hash.rev_find cctxt pkh >>= function
|
||||||
| None -> Cli_entries.error "no keys for the source contract manager"
|
| None -> cctxt.error "no keys for the source contract manager"
|
||||||
| Some n ->
|
| Some n ->
|
||||||
Public_key.find n >>= fun pk ->
|
Public_key.find cctxt n >>= fun pk ->
|
||||||
Secret_key.find n >>= fun sk ->
|
Secret_key.find cctxt n >>= fun sk ->
|
||||||
return (n, pk, sk)
|
return (n, pk, sk)
|
||||||
|
|
||||||
|
let group =
|
||||||
|
{ Cli_entries.name = "keys" ;
|
||||||
|
title = "Commands for managing cryptographic keys" }
|
||||||
|
|
||||||
let commands () =
|
let commands () =
|
||||||
let open Cli_entries in
|
let open Cli_entries in
|
||||||
register_group "keys" "Commands for managing cryptographic keys" ;
|
[ command ~group ~desc: "generate a pair of keys"
|
||||||
[ command
|
|
||||||
~group: "keys"
|
|
||||||
~desc: "generate a pair of keys"
|
|
||||||
(prefixes [ "gen" ; "keys" ]
|
(prefixes [ "gen" ; "keys" ]
|
||||||
@@ Secret_key.fresh_alias_param
|
@@ Secret_key.fresh_alias_param
|
||||||
@@ stop)
|
@@ stop)
|
||||||
(fun name () -> gen_keys name) ;
|
(fun name cctxt -> gen_keys cctxt name) ;
|
||||||
command
|
command ~group ~desc: "add a secret key to the wallet"
|
||||||
~group: "keys"
|
|
||||||
~desc: "add a secret key to the wallet"
|
|
||||||
(prefixes [ "add" ; "secret" ; "key" ]
|
(prefixes [ "add" ; "secret" ; "key" ]
|
||||||
@@ Secret_key.fresh_alias_param
|
@@ Secret_key.fresh_alias_param
|
||||||
@@ Secret_key.source_param
|
@@ Secret_key.source_param
|
||||||
@@ stop)
|
@@ stop)
|
||||||
(fun name sk () ->
|
(fun name sk cctxt ->
|
||||||
Lwt.catch (fun () ->
|
Lwt.catch (fun () ->
|
||||||
Public_key.find name >>= fun pk ->
|
Public_key.find cctxt name >>= fun pk ->
|
||||||
if check_keys_consistency pk sk || Client_config.force#get then
|
if check_keys_consistency pk sk || Client_config.force#get then
|
||||||
Secret_key.add name sk
|
Secret_key.add cctxt name sk
|
||||||
else
|
else
|
||||||
error "public and secret keys '%s' don't correspond, \
|
cctxt.error
|
||||||
|
"public and secret keys '%s' don't correspond, \
|
||||||
please don't use -force true" name)
|
please don't use -force true" name)
|
||||||
(function
|
(function
|
||||||
| Not_found ->
|
| Not_found ->
|
||||||
error "no public key named '%s', add it before adding the secret key" name
|
cctxt.error
|
||||||
|
"no public key named '%s', add it before adding the secret key" name
|
||||||
| exn -> Lwt.fail exn)) ;
|
| exn -> Lwt.fail exn)) ;
|
||||||
command
|
command ~group ~desc: "add a public key to the wallet"
|
||||||
~group: "keys"
|
|
||||||
~desc: "add a public key to the wallet"
|
|
||||||
(prefixes [ "add" ; "public" ; "key" ]
|
(prefixes [ "add" ; "public" ; "key" ]
|
||||||
@@ Public_key.fresh_alias_param
|
@@ Public_key.fresh_alias_param
|
||||||
@@ Public_key.source_param
|
@@ Public_key.source_param
|
||||||
@@ stop)
|
@@ stop)
|
||||||
(fun name key () ->
|
(fun name key cctxt ->
|
||||||
Public_key_hash.add name (Ed25519.hash key) >>= fun () ->
|
Public_key_hash.add cctxt name (Ed25519.hash key) >>= fun () ->
|
||||||
Public_key.add name key) ;
|
Public_key.add cctxt name key) ;
|
||||||
command
|
command ~group ~desc: "add an ID a public key hash to the wallet"
|
||||||
~group: "keys"
|
|
||||||
~desc: "add an ID a public key hash to the wallet"
|
|
||||||
(prefixes [ "add" ; "identity" ]
|
(prefixes [ "add" ; "identity" ]
|
||||||
@@ Public_key_hash.fresh_alias_param
|
@@ Public_key_hash.fresh_alias_param
|
||||||
@@ Public_key_hash.source_param
|
@@ Public_key_hash.source_param
|
||||||
@@ stop)
|
@@ stop)
|
||||||
(fun name hash () ->
|
(fun name hash cctxt ->
|
||||||
Public_key_hash.add name hash) ;
|
Public_key_hash.add cctxt name hash) ;
|
||||||
command
|
command ~group ~desc: "list all public key hashes and associated keys"
|
||||||
~group: "keys"
|
|
||||||
~desc: "list all public key hashes and associated keys"
|
|
||||||
(fixed [ "list" ; "known" ; "identities" ])
|
(fixed [ "list" ; "known" ; "identities" ])
|
||||||
(fun () ->
|
(fun cctxt ->
|
||||||
Public_key_hash.load () >>= fun l ->
|
Public_key_hash.load cctxt >>= fun l ->
|
||||||
Lwt_list.iter_s (fun (name, pkh) ->
|
Lwt_list.iter_s (fun (name, pkh) ->
|
||||||
Public_key.mem name >>= fun pkm ->
|
Public_key.mem cctxt name >>= fun pkm ->
|
||||||
Secret_key.mem name >>= fun pks ->
|
Secret_key.mem cctxt name >>= fun pks ->
|
||||||
Public_key_hash.to_source pkh >>= fun v ->
|
Public_key_hash.to_source cctxt pkh >>= fun v ->
|
||||||
message "%s: %s%s%s" name v
|
cctxt.message "%s: %s%s%s" name v
|
||||||
(if pkm then " (public key known)" else "")
|
(if pkm then " (public key known)" else "")
|
||||||
(if pks then " (secret key known)" else ""))
|
(if pks then " (secret key known)" else ""))
|
||||||
l) ;
|
l) ;
|
||||||
command
|
command ~group ~desc: "forget all keys"
|
||||||
~group: "keys"
|
|
||||||
~desc: "forget all keys"
|
|
||||||
(fixed [ "forget" ; "all" ; "keys" ])
|
(fixed [ "forget" ; "all" ; "keys" ])
|
||||||
(fun () ->
|
(fun cctxt ->
|
||||||
if not Client_config.force#get then
|
if not Client_config.force#get then
|
||||||
error "this can only used with option -force true"
|
cctxt.Client_commands.error "this can only used with option -force true"
|
||||||
else
|
else
|
||||||
Public_key.save [] >>= fun () ->
|
Public_key.save cctxt [] >>= fun () ->
|
||||||
Secret_key.save [] >>= fun () ->
|
Secret_key.save cctxt [] >>= fun () ->
|
||||||
Public_key_hash.save []) ;
|
Public_key_hash.save cctxt []) ;
|
||||||
]
|
]
|
||||||
|
@ -15,8 +15,9 @@ module Public_key : Client_aliases.Alias with type t = Ed25519.public_key
|
|||||||
module Secret_key : Client_aliases.Alias with type t = Ed25519.secret_key
|
module Secret_key : Client_aliases.Alias with type t = Ed25519.secret_key
|
||||||
|
|
||||||
val get_key:
|
val get_key:
|
||||||
|
Client_commands.context ->
|
||||||
Public_key_hash.t ->
|
Public_key_hash.t ->
|
||||||
( string * Public_key.t * Secret_key.t ) tzresult Lwt.t
|
( string * Public_key.t * Secret_key.t ) tzresult Lwt.t
|
||||||
|
|
||||||
|
|
||||||
val commands: unit -> Cli_entries.command list
|
val commands: unit -> Client_commands.command list
|
||||||
|
@ -11,18 +11,17 @@
|
|||||||
|
|
||||||
open Lwt
|
open Lwt
|
||||||
open Cli_entries
|
open Cli_entries
|
||||||
|
open Client_commands
|
||||||
open Logging.RPC
|
open Logging.RPC
|
||||||
|
|
||||||
let log_request cpt url req =
|
let log_request { log } cpt url req =
|
||||||
Cli_entries.log "requests"
|
log "requests" ">>>>%d: %s\n%s\n" cpt url req
|
||||||
">>>>%d: %s\n%s\n" cpt url req
|
|
||||||
|
|
||||||
let log_response cpt code ans =
|
let log_response { log } cpt code ans =
|
||||||
Cli_entries.log "requests"
|
log "requests" "<<<<%d: %s\n%s\n" cpt (Cohttp.Code.string_of_status code) ans
|
||||||
"<<<<%d: %s\n%s\n" cpt (Cohttp.Code.string_of_status code) ans
|
|
||||||
|
|
||||||
let cpt = ref 0
|
let cpt = ref 0
|
||||||
let make_request service json =
|
let make_request cctxt service json =
|
||||||
incr cpt ;
|
incr cpt ;
|
||||||
let cpt = !cpt in
|
let cpt = !cpt in
|
||||||
let serv = "http://" ^ Client_config.incoming_addr#get
|
let serv = "http://" ^ Client_config.incoming_addr#get
|
||||||
@ -35,22 +34,22 @@ let make_request service json =
|
|||||||
(fun () ->
|
(fun () ->
|
||||||
let body = Cohttp_lwt_body.of_string reqbody in
|
let body = Cohttp_lwt_body.of_string reqbody in
|
||||||
Cohttp_lwt_unix.Client.post ~body uri >>= fun (code, ansbody) ->
|
Cohttp_lwt_unix.Client.post ~body uri >>= fun (code, ansbody) ->
|
||||||
log_request cpt string_uri reqbody >>= fun () ->
|
log_request cctxt cpt string_uri reqbody >>= fun () ->
|
||||||
return (cpt, Unix.gettimeofday () -. tzero,
|
return (cpt, Unix.gettimeofday () -. tzero,
|
||||||
code.Cohttp.Response.status, ansbody))
|
code.Cohttp.Response.status, ansbody))
|
||||||
(fun e ->
|
(fun e ->
|
||||||
let msg = match e with
|
let msg = match e with
|
||||||
| Unix.Unix_error (e, _, _) -> Unix.error_message e
|
| Unix.Unix_error (e, _, _) -> Unix.error_message e
|
||||||
| e -> Printexc.to_string e in
|
| e -> Printexc.to_string e in
|
||||||
error "cannot connect to the RPC server (%s)" msg)
|
cctxt.error "cannot connect to the RPC server (%s)" msg)
|
||||||
|
|
||||||
let get_streamed_json service json =
|
let get_streamed_json cctxt service json =
|
||||||
make_request service json >>= fun (_cpt, time, code, ansbody) ->
|
make_request cctxt service json >>= fun (_cpt, time, code, ansbody) ->
|
||||||
let ansbody = Cohttp_lwt_body.to_stream ansbody in
|
let ansbody = Cohttp_lwt_body.to_stream ansbody in
|
||||||
match code, ansbody with
|
match code, ansbody with
|
||||||
| #Cohttp.Code.success_status, ansbody ->
|
| #Cohttp.Code.success_status, ansbody ->
|
||||||
(if Client_config.print_timings#get then
|
(if Client_config.print_timings#get then
|
||||||
message "Request to /%s succeeded in %gs"
|
cctxt.message "Request to /%s succeeded in %gs"
|
||||||
(String.concat "/" service) time
|
(String.concat "/" service) time
|
||||||
else Lwt.return ()) >>= fun () ->
|
else Lwt.return ()) >>= fun () ->
|
||||||
Lwt.return (
|
Lwt.return (
|
||||||
@ -64,88 +63,92 @@ let get_streamed_json service json =
|
|||||||
(Data_encoding_ezjsonm.from_stream ansbody))
|
(Data_encoding_ezjsonm.from_stream ansbody))
|
||||||
| err, _ansbody ->
|
| err, _ansbody ->
|
||||||
(if Client_config.print_timings#get then
|
(if Client_config.print_timings#get then
|
||||||
message "Request to /%s failed in %gs"
|
cctxt.message "Request to /%s failed in %gs"
|
||||||
(String.concat "/" service) time
|
(String.concat "/" service) time
|
||||||
else Lwt.return ()) >>= fun () ->
|
else Lwt.return ()) >>= fun () ->
|
||||||
message "Request to /%s failed, server returned %s"
|
cctxt.message "Request to /%s failed, server returned %s"
|
||||||
(String.concat "/" service) (Cohttp.Code.string_of_status err) >>= fun () ->
|
(String.concat "/" service) (Cohttp.Code.string_of_status err) >>= fun () ->
|
||||||
error "the RPC server returned a non-success status (%s)"
|
cctxt.error "the RPC server returned a non-success status (%s)"
|
||||||
(Cohttp.Code.string_of_status err)
|
(Cohttp.Code.string_of_status err)
|
||||||
|
|
||||||
let get_json service json =
|
let get_json cctxt service json =
|
||||||
make_request service json >>= fun (cpt, time, code, ansbody) ->
|
make_request cctxt service json >>= fun (cpt, time, code, ansbody) ->
|
||||||
Cohttp_lwt_body.to_string ansbody >>= fun ansbody ->
|
Cohttp_lwt_body.to_string ansbody >>= fun ansbody ->
|
||||||
match code, ansbody with
|
match code, ansbody with
|
||||||
| #Cohttp.Code.success_status, ansbody -> begin
|
| #Cohttp.Code.success_status, ansbody -> begin
|
||||||
(if Client_config.print_timings#get then
|
(if Client_config.print_timings#get then
|
||||||
message "Request to /%s succeeded in %gs"
|
cctxt.message "Request to /%s succeeded in %gs"
|
||||||
(String.concat "/" service) time
|
(String.concat "/" service) time
|
||||||
else Lwt.return ()) >>= fun () ->
|
else Lwt.return ()) >>= fun () ->
|
||||||
log_response cpt code ansbody >>= fun () ->
|
log_response cctxt cpt code ansbody >>= fun () ->
|
||||||
if ansbody = "" then Lwt.return `Null
|
if ansbody = "" then Lwt.return `Null
|
||||||
else match Data_encoding_ezjsonm.from_string ansbody with
|
else match Data_encoding_ezjsonm.from_string ansbody with
|
||||||
| Error _ -> error "the RPC server returned malformed JSON"
|
| Error _ -> cctxt.error "the RPC server returned malformed JSON"
|
||||||
| Ok res -> Lwt.return res
|
| Ok res -> Lwt.return res
|
||||||
end
|
end
|
||||||
| err, _ansbody ->
|
| err, _ansbody ->
|
||||||
(if Client_config.print_timings#get then
|
(if Client_config.print_timings#get then
|
||||||
message "Request to /%s failed in %gs"
|
cctxt.message "Request to /%s failed in %gs"
|
||||||
(String.concat "/" service) time
|
(String.concat "/" service) time
|
||||||
else Lwt.return ()) >>= fun () ->
|
else Lwt.return ()) >>= fun () ->
|
||||||
message "Request to /%s failed, server returned %s"
|
cctxt.message "Request to /%s failed, server returned %s"
|
||||||
(String.concat "/" service) (Cohttp.Code.string_of_status err) >>= fun () ->
|
(String.concat "/" service) (Cohttp.Code.string_of_status err) >>= fun () ->
|
||||||
error "the RPC server returned a non-success status (%s)"
|
cctxt.error "the RPC server returned a non-success status (%s)"
|
||||||
(Cohttp.Code.string_of_status err)
|
(Cohttp.Code.string_of_status err)
|
||||||
|
|
||||||
exception Unknown_error of Data_encoding.json
|
exception Unknown_error of Data_encoding.json
|
||||||
|
|
||||||
let parse_answer service path json =
|
let parse_answer cctxt service path json =
|
||||||
match RPC.read_answer service json with
|
match RPC.read_answer service json with
|
||||||
| Error msg -> (* TODO print_error *)
|
| Error msg -> (* TODO print_error *)
|
||||||
error "request to /%s returned wrong JSON (%s)\n%s"
|
cctxt.error "request to /%s returned wrong JSON (%s)\n%s"
|
||||||
(String.concat "/" path) msg (Data_encoding_ezjsonm.to_string json)
|
(String.concat "/" path) msg (Data_encoding_ezjsonm.to_string json)
|
||||||
| Ok v -> return v
|
| Ok v -> return v
|
||||||
|
|
||||||
let call_service0 service arg =
|
let call_service0 cctxt service arg =
|
||||||
let path, arg = RPC.forge_request service () arg in
|
let path, arg = RPC.forge_request service () arg in
|
||||||
get_json path arg >>= parse_answer service path
|
get_json cctxt path arg >>= fun json ->
|
||||||
|
parse_answer cctxt service path json
|
||||||
|
|
||||||
let call_service1 service a1 arg =
|
let call_service1 cctxt service a1 arg =
|
||||||
let path, arg = RPC.forge_request service ((), a1) arg in
|
let path, arg = RPC.forge_request service ((), a1) arg in
|
||||||
get_json path arg >>= parse_answer service path
|
get_json cctxt path arg >>= fun json ->
|
||||||
|
parse_answer cctxt service path json
|
||||||
|
|
||||||
let call_service2 service a1 a2 arg =
|
let call_service2 cctxt service a1 a2 arg =
|
||||||
let path, arg = RPC.forge_request service (((), a1), a2) arg in
|
let path, arg = RPC.forge_request service (((), a1), a2) arg in
|
||||||
get_json path arg >>= parse_answer service path
|
get_json cctxt path arg >>= fun json ->
|
||||||
|
parse_answer cctxt service path json
|
||||||
|
|
||||||
let call_streamed_service0 service arg =
|
let call_streamed_service0 cctxt service arg =
|
||||||
let path, arg = RPC.forge_request service () arg in
|
let path, arg = RPC.forge_request service () arg in
|
||||||
get_streamed_json path arg >|= fun st ->
|
get_streamed_json cctxt path arg >|= fun st ->
|
||||||
Lwt_stream.map_s (parse_answer service path) st
|
Lwt_stream.map_s (parse_answer cctxt service path) st
|
||||||
|
|
||||||
module Services = Node_rpc_services
|
module Services = Node_rpc_services
|
||||||
let errors = call_service0 Services.Error.service
|
let errors cctxt =
|
||||||
let forge_block ?net ?predecessor ?timestamp fitness ops header =
|
call_service0 cctxt Services.Error.service ()
|
||||||
call_service0 Services.forge_block
|
let forge_block cctxt ?net ?predecessor ?timestamp fitness ops header =
|
||||||
|
call_service0 cctxt Services.forge_block
|
||||||
(net, predecessor, timestamp, fitness, ops, header)
|
(net, predecessor, timestamp, fitness, ops, header)
|
||||||
let validate_block net block =
|
let validate_block cctxt net block =
|
||||||
call_service0 Services.validate_block (net, block)
|
call_service0 cctxt Services.validate_block (net, block)
|
||||||
let inject_block ?(wait = true) ?force block =
|
let inject_block cctxt ?(wait = true) ?force block =
|
||||||
call_service0 Services.inject_block (block, wait, force)
|
call_service0 cctxt Services.inject_block (block, wait, force)
|
||||||
let inject_operation ?(wait = true) ?force operation =
|
let inject_operation cctxt ?(wait = true) ?force operation =
|
||||||
call_service0 Services.inject_operation (operation, wait, force)
|
call_service0 cctxt Services.inject_operation (operation, wait, force)
|
||||||
let inject_protocol ?(wait = true) ?force protocol =
|
let inject_protocol cctxt ?(wait = true) ?force protocol =
|
||||||
call_service0 Services.inject_protocol (protocol, wait, force)
|
call_service0 cctxt Services.inject_protocol (protocol, wait, force)
|
||||||
let complete ?block prefix =
|
let complete cctxt ?block prefix =
|
||||||
match block with
|
match block with
|
||||||
| None ->
|
| None ->
|
||||||
call_service1 Services.complete prefix ()
|
call_service1 cctxt Services.complete prefix ()
|
||||||
| Some block ->
|
| Some block ->
|
||||||
call_service2 Services.Blocks.complete block prefix ()
|
call_service2 cctxt Services.Blocks.complete block prefix ()
|
||||||
let describe ?recurse path =
|
let describe cctxt ?recurse path =
|
||||||
let prefix, arg = RPC.forge_request Services.describe () recurse in
|
let prefix, arg = RPC.forge_request Services.describe () recurse in
|
||||||
get_json (prefix @ path) arg >>=
|
get_json cctxt (prefix @ path) arg >>=
|
||||||
parse_answer Services.describe prefix
|
parse_answer cctxt Services.describe prefix
|
||||||
|
|
||||||
type net = Services.Blocks.net = Net of Block_hash.t
|
type net = Services.Blocks.net = Net of Block_hash.t
|
||||||
|
|
||||||
@ -173,42 +176,42 @@ module Blocks = struct
|
|||||||
fitness: MBytes.t list ;
|
fitness: MBytes.t list ;
|
||||||
timestamp: Time.t ;
|
timestamp: Time.t ;
|
||||||
}
|
}
|
||||||
let net h = call_service1 Services.Blocks.net h ()
|
let net cctxt h = call_service1 cctxt Services.Blocks.net h ()
|
||||||
let predecessor h = call_service1 Services.Blocks.predecessor h ()
|
let predecessor cctxt h = call_service1 cctxt Services.Blocks.predecessor h ()
|
||||||
let hash h = call_service1 Services.Blocks.hash h ()
|
let hash cctxt h = call_service1 cctxt Services.Blocks.hash h ()
|
||||||
let timestamp h = call_service1 Services.Blocks.timestamp h ()
|
let timestamp cctxt h = call_service1 cctxt Services.Blocks.timestamp h ()
|
||||||
let fitness h = call_service1 Services.Blocks.fitness h ()
|
let fitness cctxt h = call_service1 cctxt Services.Blocks.fitness h ()
|
||||||
let operations h = call_service1 Services.Blocks.operations h ()
|
let operations cctxt h = call_service1 cctxt Services.Blocks.operations h ()
|
||||||
let protocol h = call_service1 Services.Blocks.protocol h ()
|
let protocol cctxt h = call_service1 cctxt Services.Blocks.protocol h ()
|
||||||
let test_protocol h = call_service1 Services.Blocks.test_protocol h ()
|
let test_protocol cctxt h = call_service1 cctxt Services.Blocks.test_protocol h ()
|
||||||
let test_network h = call_service1 Services.Blocks.test_network h ()
|
let test_network cctxt h = call_service1 cctxt Services.Blocks.test_network h ()
|
||||||
let preapply h ?timestamp ?(sort = false) operations =
|
let preapply cctxt h ?timestamp ?(sort = false) operations =
|
||||||
call_service1 Services.Blocks.preapply h { operations ; sort ; timestamp }
|
call_service1 cctxt Services.Blocks.preapply h { operations ; sort ; timestamp }
|
||||||
let pending_operations block =
|
let pending_operations cctxt block =
|
||||||
call_service1 Services.Blocks.pending_operations block ()
|
call_service1 cctxt Services.Blocks.pending_operations block ()
|
||||||
let info ?(operations = false) h =
|
let info cctxt ?(operations = false) h =
|
||||||
call_service1 Services.Blocks.info h operations
|
call_service1 cctxt Services.Blocks.info h operations
|
||||||
let complete block prefix =
|
let complete cctxt block prefix =
|
||||||
call_service2 Services.Blocks.complete block prefix ()
|
call_service2 cctxt Services.Blocks.complete block prefix ()
|
||||||
let list ?operations ?length ?heads ?delay ?min_date ?min_heads () =
|
let list cctxt ?operations ?length ?heads ?delay ?min_date ?min_heads () =
|
||||||
call_service0 Services.Blocks.list
|
call_service0 cctxt Services.Blocks.list
|
||||||
{ operations; length ; heads ; monitor = Some false ; delay ;
|
{ operations; length ; heads ; monitor = Some false ; delay ;
|
||||||
min_date ; min_heads }
|
min_date ; min_heads }
|
||||||
let monitor ?operations ?length ?heads ?delay ?min_date ?min_heads () =
|
let monitor cctxt ?operations ?length ?heads ?delay ?min_date ?min_heads () =
|
||||||
call_streamed_service0 Services.Blocks.list
|
call_streamed_service0 cctxt Services.Blocks.list
|
||||||
{ operations; length ; heads ; monitor = Some true ; delay ;
|
{ operations; length ; heads ; monitor = Some true ; delay ;
|
||||||
min_date ; min_heads }
|
min_date ; min_heads }
|
||||||
end
|
end
|
||||||
|
|
||||||
module Operations = struct
|
module Operations = struct
|
||||||
let monitor ?contents () =
|
let monitor cctxt ?contents () =
|
||||||
call_streamed_service0 Services.Operations.list
|
call_streamed_service0 cctxt Services.Operations.list
|
||||||
{ monitor = Some true ; contents }
|
{ monitor = Some true ; contents }
|
||||||
end
|
end
|
||||||
|
|
||||||
module Protocols = struct
|
module Protocols = struct
|
||||||
let bytes hash =
|
let bytes cctxt hash =
|
||||||
call_service1 Services.Protocols.bytes hash ()
|
call_service1 cctxt Services.Protocols.bytes hash ()
|
||||||
let list ?contents () =
|
let list cctxt ?contents () =
|
||||||
call_service0 Services.Protocols.list { contents; monitor = Some false }
|
call_service0 cctxt Services.Protocols.list { contents; monitor = Some false }
|
||||||
end
|
end
|
||||||
|
@ -9,8 +9,12 @@
|
|||||||
|
|
||||||
type net = State.net_id = Net of Block_hash.t
|
type net = State.net_id = Net of Block_hash.t
|
||||||
|
|
||||||
val errors: unit -> Json_schema.schema Lwt.t
|
val errors:
|
||||||
|
Client_commands.context ->
|
||||||
|
Json_schema.schema Lwt.t
|
||||||
|
|
||||||
val forge_block:
|
val forge_block:
|
||||||
|
Client_commands.context ->
|
||||||
?net:Updater.net_id ->
|
?net:Updater.net_id ->
|
||||||
?predecessor:Block_hash.t ->
|
?predecessor:Block_hash.t ->
|
||||||
?timestamp:Time.t ->
|
?timestamp:Time.t ->
|
||||||
@ -19,14 +23,28 @@ val forge_block:
|
|||||||
MBytes.t ->
|
MBytes.t ->
|
||||||
MBytes.t Lwt.t
|
MBytes.t Lwt.t
|
||||||
|
|
||||||
val validate_block: net -> Block_hash.t -> unit tzresult Lwt.t
|
val validate_block:
|
||||||
|
Client_commands.context ->
|
||||||
|
net -> Block_hash.t ->
|
||||||
|
unit tzresult Lwt.t
|
||||||
|
|
||||||
val inject_block:
|
val inject_block:
|
||||||
?wait:bool -> ?force:bool -> MBytes.t ->
|
Client_commands.context ->
|
||||||
|
?wait:bool -> ?force:bool ->
|
||||||
|
MBytes.t ->
|
||||||
Block_hash.t tzresult Lwt.t
|
Block_hash.t tzresult Lwt.t
|
||||||
|
|
||||||
val inject_operation:
|
val inject_operation:
|
||||||
?wait:bool -> ?force:bool -> MBytes.t -> Operation_hash.t tzresult Lwt.t
|
Client_commands.context ->
|
||||||
|
?wait:bool -> ?force:bool ->
|
||||||
|
MBytes.t ->
|
||||||
|
Operation_hash.t tzresult Lwt.t
|
||||||
|
|
||||||
val inject_protocol:
|
val inject_protocol:
|
||||||
?wait:bool -> ?force:bool -> Tezos_compiler.Protocol.t -> Protocol_hash.t tzresult Lwt.t
|
Client_commands.context ->
|
||||||
|
?wait:bool -> ?force:bool ->
|
||||||
|
Tezos_compiler.Protocol.t ->
|
||||||
|
Protocol_hash.t tzresult Lwt.t
|
||||||
|
|
||||||
module Blocks : sig
|
module Blocks : sig
|
||||||
|
|
||||||
@ -37,17 +55,36 @@ module Blocks : sig
|
|||||||
| `Hash of Block_hash.t
|
| `Hash of Block_hash.t
|
||||||
]
|
]
|
||||||
|
|
||||||
val net: block -> net Lwt.t
|
val net:
|
||||||
val predecessor: block -> Block_hash.t Lwt.t
|
Client_commands.context ->
|
||||||
val hash: block -> Block_hash.t Lwt.t
|
block -> net Lwt.t
|
||||||
val timestamp: block -> Time.t Lwt.t
|
val predecessor:
|
||||||
val fitness: block -> MBytes.t list Lwt.t
|
Client_commands.context ->
|
||||||
val operations: block -> Operation_hash.t list Lwt.t
|
block -> Block_hash.t Lwt.t
|
||||||
val protocol: block -> Protocol_hash.t Lwt.t
|
val hash:
|
||||||
val test_protocol: block -> Protocol_hash.t option Lwt.t
|
Client_commands.context ->
|
||||||
val test_network: block -> (net * Time.t) option Lwt.t
|
block -> Block_hash.t Lwt.t
|
||||||
|
val timestamp:
|
||||||
|
Client_commands.context ->
|
||||||
|
block -> Time.t Lwt.t
|
||||||
|
val fitness:
|
||||||
|
Client_commands.context ->
|
||||||
|
block -> MBytes.t list Lwt.t
|
||||||
|
val operations:
|
||||||
|
Client_commands.context ->
|
||||||
|
block -> Operation_hash.t list Lwt.t
|
||||||
|
val protocol:
|
||||||
|
Client_commands.context ->
|
||||||
|
block -> Protocol_hash.t Lwt.t
|
||||||
|
val test_protocol:
|
||||||
|
Client_commands.context ->
|
||||||
|
block -> Protocol_hash.t option Lwt.t
|
||||||
|
val test_network:
|
||||||
|
Client_commands.context ->
|
||||||
|
block -> (net * Time.t) option Lwt.t
|
||||||
|
|
||||||
val pending_operations:
|
val pending_operations:
|
||||||
|
Client_commands.context ->
|
||||||
block -> (error Updater.preapply_result * Operation_hash_set.t) Lwt.t
|
block -> (error Updater.preapply_result * Operation_hash_set.t) Lwt.t
|
||||||
|
|
||||||
type block_info = {
|
type block_info = {
|
||||||
@ -63,14 +100,17 @@ module Blocks : sig
|
|||||||
}
|
}
|
||||||
|
|
||||||
val info:
|
val info:
|
||||||
|
Client_commands.context ->
|
||||||
?operations:bool -> block -> block_info Lwt.t
|
?operations:bool -> block -> block_info Lwt.t
|
||||||
|
|
||||||
val list:
|
val list:
|
||||||
|
Client_commands.context ->
|
||||||
?operations:bool -> ?length:int -> ?heads:Block_hash.t list ->
|
?operations:bool -> ?length:int -> ?heads:Block_hash.t list ->
|
||||||
?delay:int -> ?min_date:Time.t -> ?min_heads:int ->
|
?delay:int -> ?min_date:Time.t -> ?min_heads:int ->
|
||||||
unit -> block_info list list Lwt.t
|
unit -> block_info list list Lwt.t
|
||||||
|
|
||||||
val monitor:
|
val monitor:
|
||||||
|
Client_commands.context ->
|
||||||
?operations:bool -> ?length:int -> ?heads:Block_hash.t list ->
|
?operations:bool -> ?length:int -> ?heads:Block_hash.t list ->
|
||||||
?delay:int -> ?min_date:Time.t -> ?min_heads:int ->
|
?delay:int -> ?min_date:Time.t -> ?min_heads:int ->
|
||||||
unit -> block_info list list Lwt_stream.t Lwt.t
|
unit -> block_info list list Lwt_stream.t Lwt.t
|
||||||
@ -82,6 +122,7 @@ module Blocks : sig
|
|||||||
}
|
}
|
||||||
|
|
||||||
val preapply:
|
val preapply:
|
||||||
|
Client_commands.context ->
|
||||||
block ->
|
block ->
|
||||||
?timestamp:Time.t ->
|
?timestamp:Time.t ->
|
||||||
?sort:bool ->
|
?sort:bool ->
|
||||||
@ -91,30 +132,42 @@ end
|
|||||||
|
|
||||||
module Operations : sig
|
module Operations : sig
|
||||||
val monitor:
|
val monitor:
|
||||||
|
Client_commands.context ->
|
||||||
?contents:bool -> unit ->
|
?contents:bool -> unit ->
|
||||||
(Operation_hash.t * Store.operation option) list Lwt_stream.t Lwt.t
|
(Operation_hash.t * Store.operation option) list Lwt_stream.t Lwt.t
|
||||||
end
|
end
|
||||||
|
|
||||||
module Protocols : sig
|
module Protocols : sig
|
||||||
val bytes:
|
val bytes:
|
||||||
|
Client_commands.context ->
|
||||||
Protocol_hash.t -> Store.protocol tzresult Time.timed_data Lwt.t
|
Protocol_hash.t -> Store.protocol tzresult Time.timed_data Lwt.t
|
||||||
|
|
||||||
val list:
|
val list:
|
||||||
|
Client_commands.context ->
|
||||||
?contents:bool -> unit ->
|
?contents:bool -> unit ->
|
||||||
(Protocol_hash.t * Store.protocol option) list Lwt.t
|
(Protocol_hash.t * Store.protocol option) list Lwt.t
|
||||||
end
|
end
|
||||||
|
|
||||||
val complete: ?block:Blocks.block -> string -> string list Lwt.t
|
val complete:
|
||||||
|
Client_commands.context ->
|
||||||
|
?block:Blocks.block -> string -> string list Lwt.t
|
||||||
|
|
||||||
val describe: ?recurse:bool -> string list -> RPC.Description.directory_descr Lwt.t
|
val describe:
|
||||||
|
Client_commands.context ->
|
||||||
|
?recurse:bool -> string list -> RPC.Description.directory_descr Lwt.t
|
||||||
|
|
||||||
(** Low-level *)
|
(** Low-level *)
|
||||||
|
|
||||||
val get_json: string list -> Data_encoding.json -> Data_encoding.json Lwt.t
|
val get_json:
|
||||||
|
Client_commands.context ->
|
||||||
|
string list -> Data_encoding.json -> Data_encoding.json Lwt.t
|
||||||
|
|
||||||
val call_service0:
|
val call_service0:
|
||||||
|
Client_commands.context ->
|
||||||
(unit, unit, 'i, 'o) RPC.service -> 'i -> 'o Lwt.t
|
(unit, unit, 'i, 'o) RPC.service -> 'i -> 'o Lwt.t
|
||||||
val call_service1:
|
val call_service1:
|
||||||
|
Client_commands.context ->
|
||||||
(unit, unit * 'a, 'i, 'o) RPC.service -> 'a -> 'i -> 'o Lwt.t
|
(unit, unit * 'a, 'i, 'o) RPC.service -> 'a -> 'i -> 'o Lwt.t
|
||||||
val call_service2:
|
val call_service2:
|
||||||
|
Client_commands.context ->
|
||||||
(unit, (unit * 'a) * 'b, 'i, 'o) RPC.service -> 'a -> 'b -> 'i -> 'o Lwt.t
|
(unit, (unit * 'a) * 'b, 'i, 'o) RPC.service -> 'a -> 'b -> 'i -> 'o Lwt.t
|
||||||
|
@ -1,51 +1,60 @@
|
|||||||
|
(**************************************************************************)
|
||||||
|
(* *)
|
||||||
|
(* Copyright (c) 2014 - 2016. *)
|
||||||
|
(* Dynamic Ledger Solutions, Inc. <contact@tezos.com> *)
|
||||||
|
(* *)
|
||||||
|
(* All rights reserved. No warranty, explicit or implicit, provided. *)
|
||||||
|
(* *)
|
||||||
|
(**************************************************************************)
|
||||||
|
|
||||||
|
let group =
|
||||||
|
{ Cli_entries.name = "protocols" ;
|
||||||
|
title = "Commands for managing protocols" }
|
||||||
|
|
||||||
let commands () =
|
let commands () =
|
||||||
let open Cli_entries in
|
let open Cli_entries in
|
||||||
let check_dir dn =
|
let check_dir _ dn =
|
||||||
if Sys.is_directory dn then Lwt.return dn else Lwt.fail_invalid_arg "not a directory"
|
if Sys.is_directory dn then
|
||||||
in
|
Lwt.return dn
|
||||||
let check_hash ph = Lwt.wrap1 Protocol_hash.of_b48check ph in
|
else
|
||||||
register_group "protocols" "Commands for managing protocols" ;
|
Lwt.fail_with (dn ^ " is not a directory") in
|
||||||
|
let check_hash _ ph =
|
||||||
|
Lwt.wrap1 Protocol_hash.of_b48check ph in
|
||||||
[
|
[
|
||||||
command
|
command ~group ~desc: "list known protocols"
|
||||||
~group: "protocols"
|
|
||||||
~desc: "list known protocols"
|
|
||||||
(prefixes [ "list" ; "protocols" ] stop)
|
(prefixes [ "list" ; "protocols" ] stop)
|
||||||
(fun () ->
|
(fun cctxt ->
|
||||||
Client_node_rpcs.Protocols.list ~contents:false () >>= fun protos ->
|
Client_node_rpcs.Protocols.list cctxt ~contents:false () >>= fun protos ->
|
||||||
Lwt_list.iter_s (fun (ph, _p) -> message "%a" Protocol_hash.pp ph) protos
|
Lwt_list.iter_s (fun (ph, _p) -> cctxt.message "%a" Protocol_hash.pp ph) protos
|
||||||
);
|
);
|
||||||
command
|
command ~group ~desc: "inject a new protocol to the shell database"
|
||||||
~group: "protocols"
|
|
||||||
~desc: "inject a new protocol to the shell database"
|
|
||||||
(prefixes [ "inject" ; "protocol" ]
|
(prefixes [ "inject" ; "protocol" ]
|
||||||
@@ param ~name:"directory containing a protocol" ~desc:"" check_dir
|
@@ param ~name:"dir" ~desc:"directory containing a protocol" check_dir
|
||||||
@@ stop)
|
@@ stop)
|
||||||
(fun dirname () ->
|
(fun dirname cctxt ->
|
||||||
Lwt.catch
|
Lwt.catch
|
||||||
(fun () ->
|
(fun () ->
|
||||||
let proto = Tezos_compiler.Protocol.of_dir dirname in
|
let proto = Tezos_compiler.Protocol.of_dir dirname in
|
||||||
Client_node_rpcs.inject_protocol proto >>= function
|
Client_node_rpcs.inject_protocol cctxt proto >>= function
|
||||||
| Ok hash ->
|
| Ok hash ->
|
||||||
message "Injected protocol %a successfully" Protocol_hash.pp_short hash
|
cctxt.message "Injected protocol %a successfully" Protocol_hash.pp_short hash
|
||||||
| Error err ->
|
| Error err ->
|
||||||
error "Error while injecting protocol from %s: %a"
|
cctxt.error "Error while injecting protocol from %s: %a"
|
||||||
dirname Error_monad.pp_print_error err)
|
dirname Error_monad.pp_print_error err)
|
||||||
(fun exn ->
|
(fun exn ->
|
||||||
error "Error while injecting protocol from %s: %a"
|
cctxt.error "Error while injecting protocol from %s: %a"
|
||||||
dirname Error_monad.pp_print_error [Error_monad.Exn exn])
|
dirname Error_monad.pp_print_error [Error_monad.Exn exn])
|
||||||
);
|
);
|
||||||
command
|
command ~group ~desc: "dump a protocol from the shell database"
|
||||||
~group: "protocols"
|
|
||||||
~desc: "dump a protocol from the shell database"
|
|
||||||
(prefixes [ "dump" ; "protocol" ]
|
(prefixes [ "dump" ; "protocol" ]
|
||||||
@@ param ~name:"protocol hash" ~desc:"" check_hash
|
@@ param ~name:"protocol hash" ~desc:"" check_hash
|
||||||
@@ stop)
|
@@ stop)
|
||||||
(fun ph () ->
|
(fun ph cctxt ->
|
||||||
Client_node_rpcs.Protocols.bytes ph >>= fun { data } -> match data with
|
Client_node_rpcs.Protocols.bytes cctxt ph >>= fun { data } -> match data with
|
||||||
| Ok proto ->
|
| Ok proto ->
|
||||||
Updater.extract "" ph proto >>= fun () ->
|
Updater.extract "" ph proto >>= fun () ->
|
||||||
message "Extracted protocol %a" Protocol_hash.pp_short ph
|
cctxt.message "Extracted protocol %a" Protocol_hash.pp_short ph
|
||||||
| Error err ->
|
| Error err ->
|
||||||
error "Error while dumping protocol %a: %a"
|
cctxt.error "Error while dumping protocol %a: %a"
|
||||||
Protocol_hash.pp_short ph Error_monad.pp_print_error err);
|
Protocol_hash.pp_short ph Error_monad.pp_print_error err);
|
||||||
]
|
]
|
||||||
|
@ -1,2 +1,10 @@
|
|||||||
|
(**************************************************************************)
|
||||||
|
(* *)
|
||||||
|
(* Copyright (c) 2014 - 2016. *)
|
||||||
|
(* Dynamic Ledger Solutions, Inc. <contact@tezos.com> *)
|
||||||
|
(* *)
|
||||||
|
(* All rights reserved. No warranty, explicit or implicit, provided. *)
|
||||||
|
(* *)
|
||||||
|
(**************************************************************************)
|
||||||
|
|
||||||
val commands: unit -> Cli_entries.command list
|
val commands: unit -> Client_commands.command list
|
||||||
|
@ -1,5 +1,7 @@
|
|||||||
|
|
||||||
all: ../client_$(PROTO_VERSION).cmx
|
all: \
|
||||||
|
../client_$(PROTO_VERSION).cmx \
|
||||||
|
../webclient_$(PROTO_VERSION).cmx
|
||||||
|
|
||||||
include ../../../Makefile.config
|
include ../../../Makefile.config
|
||||||
|
|
||||||
@ -26,25 +28,56 @@ OPENED_MODULES := \
|
|||||||
${OPENED_MODULES}
|
${OPENED_MODULES}
|
||||||
|
|
||||||
OBJS := \
|
OBJS := \
|
||||||
${IMPLS:.ml=.cmx} ${IMPLS:.ml=.ml.deps} \
|
${CLIENT_IMPLS:.ml=.cmx} ${CLIENT_INTFS:.mli=.cmi}
|
||||||
${INTFS:.mli=.cmi} ${INTFS:.mli=.mli.deps} \
|
OBJS_DEPS := \
|
||||||
../client_$(PROTO_VERSION).cmx
|
${CLIENT_IMPLS:.ml=.ml.deps} ${CLIENT_INTFS:.mli=.mli.deps}
|
||||||
${OBJS}: TARGET="(client_$(PROTO_VERSION).cmx)"
|
|
||||||
${OBJS}: PACKAGES=lwt ocplib-json-typed config-file sodium
|
|
||||||
${OBJS}: ../../../proto/client_embedded_proto_${PROTO_VERSION}.cmxa
|
|
||||||
|
|
||||||
../client_$(PROTO_VERSION).cmx: $(patsubst %.ml, %.cmx, ${IMPLS})
|
${OBJS} ${OBJS_DEPS}: TARGET="(client_$(PROTO_VERSION).cmx)"
|
||||||
|
${OBJS}: EXTRA_OCAMLFLAGS = -for-pack Client_$(PROTO_VERSION)
|
||||||
|
../client_$(PROTO_VERSION).cmx: EXTRA_OCAMLFLAGS =
|
||||||
|
${OBJS} ${OBJS_DEPS} ../client_$(PROTO_VERSION).cmx: \
|
||||||
|
PACKAGES=lwt ocplib-json-typed config-file sodium ocplib-ocamlres
|
||||||
|
${OBJS} ${OBJS_DEPS} ../client_$(PROTO_VERSION).cmx: \
|
||||||
|
../../../proto/client_embedded_proto_${PROTO_VERSION}.cmxa
|
||||||
|
|
||||||
|
WEBOBJS := \
|
||||||
|
${WEBCLIENT_IMPLS:.ml=.cmx} ${WEBCLIENT_INTFS:.mli=.cmi}
|
||||||
|
WEBOBJS_DEPENDS := \
|
||||||
|
${WEBCLIENT_IMPLS:.ml=.ml.deps} ${WEBCLIENT_INTFS:.mli=.mli.deps}
|
||||||
|
|
||||||
|
${WEBOBJS} ${WEBOBJS_DEPS}: TARGET="(webclient_$(PROTO_VERSION).cmx)"
|
||||||
|
${WEBOBJS} ${WEBOBJS_DEPS}: SOURCE_DIRECTORIES += ..
|
||||||
|
${WEBOBJS} ${WEBOBJS_DEPS}: OPENED_MODULES += Client_${PROTO_VERSION}
|
||||||
|
${WEBOBJS}: EXTRA_OCAMLFLAGS = -for-pack Webclient_$(PROTO_VERSION)
|
||||||
|
../client_$(PROTO_VERSION).cmx: EXTRA_OCAMLFLAGS =
|
||||||
|
${WEBOBJS} ${WEBOBJS_DEPS} ../webclient_$(PROTO_VERSION).cmx: \
|
||||||
|
PACKAGES=lwt ocplib-json-typed config-file sodium ocplib-ocamlres
|
||||||
|
${WEBOBJS} ${WEBOBJS_DEPS} ../webclient_$(PROTO_VERSION).cmx: \
|
||||||
|
../../../proto/client_embedded_proto_${PROTO_VERSION}.cmxa
|
||||||
|
${WEBOBJS} ../webclient_$(PROTO_VERSION).cmx: \
|
||||||
|
../client_${PROTO_VERSION}.cmx
|
||||||
|
|
||||||
|
../client_$(PROTO_VERSION).cmx: $(patsubst %.ml, %.cmx, ${CLIENT_IMPLS})
|
||||||
@echo LINK $(notdir $@)
|
@echo LINK $(notdir $@)
|
||||||
@$(OCAMLOPT) -linkall ${OCAMLFLAGS} -pack -o $@ \
|
@$(OCAMLOPT) -linkall ${OCAMLFLAGS} -pack -o $@ \
|
||||||
$(patsubst %.ml, %.cmx, ${IMPLS})
|
$(patsubst %.ml, %.cmx, ${CLIENT_IMPLS})
|
||||||
|
|
||||||
|
../webclient_$(PROTO_VERSION).cmx: $(patsubst %.ml, %.cmx, ${WEBCLIENT_IMPLS})
|
||||||
|
@echo LINK $(notdir $@)
|
||||||
|
@$(OCAMLOPT) -linkall ${OCAMLFLAGS} -pack -o $@ \
|
||||||
|
$(patsubst %.ml, %.cmx, ${WEBCLIENT_IMPLS})
|
||||||
|
|
||||||
%.cmx: %.ml
|
%.cmx: %.ml
|
||||||
@echo OCAMLOPT ${TARGET} $(notdir $@)
|
@echo OCAMLOPT ${TARGET} $(notdir $@)
|
||||||
@$(OCAMLOPT) ${OCAMLFLAGS} -for-pack Client_$(PROTO_VERSION) -c $<
|
@$(OCAMLOPT) ${OCAMLFLAGS} -c $<
|
||||||
|
|
||||||
|
%.cmo: %.ml
|
||||||
|
@echo OCAMLC ${TARGET} $(notdir $@)
|
||||||
|
@$(OCAMLC) ${OCAMLFLAGS} -c $<
|
||||||
|
|
||||||
%.cmi: %.mli
|
%.cmi: %.mli
|
||||||
@echo OCAMLOPT ${TARGET} $(notdir $@)
|
@echo OCAMLOPT ${TARGET} $(notdir $@)
|
||||||
@$(OCAMLOPT) ${OCAMLFLAGS} -for-pack Client_$(PROTO_VERSION) -c $<
|
@$(OCAMLOPT) ${OCAMLFLAGS} -c $<
|
||||||
|
|
||||||
%.ml: %.mll
|
%.ml: %.mll
|
||||||
@echo OCAMLLEX ${TARGET} $(notdir $@)
|
@echo OCAMLLEX ${TARGET} $(notdir $@)
|
||||||
@ -57,23 +90,39 @@ ${OBJS}: ../../../proto/client_embedded_proto_${PROTO_VERSION}.cmxa
|
|||||||
.PHONY: clean
|
.PHONY: clean
|
||||||
clean::
|
clean::
|
||||||
-rm -f ../client_$(PROTO_VERSION).cm* ../client_$(PROTO_VERSION).o
|
-rm -f ../client_$(PROTO_VERSION).cm* ../client_$(PROTO_VERSION).o
|
||||||
-rm -f *.cm* *~ *.o *.a *.deps
|
-rm -f ../webclient_$(PROTO_VERSION).cm* ../webclient_$(PROTO_VERSION).o
|
||||||
|
-rm -f *.cm* *~ *.o *.a *.deps *.deps.byte
|
||||||
-rm -rf _tzbuild
|
-rm -rf _tzbuild
|
||||||
-rm -f .depend
|
-rm -f .depend
|
||||||
|
|
||||||
ifneq ($(MAKECMDGOALS),clean)
|
ifneq ($(MAKECMDGOALS),clean)
|
||||||
-include .depend
|
include .depend
|
||||||
endif
|
endif
|
||||||
|
|
||||||
predepend:
|
predepend:
|
||||||
|
|
||||||
DEPENDS := ${INTFS} ${IMPLS}
|
DEPENDS += \
|
||||||
.SECONDARY: $(patsubst %,%.deps,${DEPENDS})
|
$(patsubst %,%.deps,${CLIENT_INTFS} ${CLIENT_IMPLS}) \
|
||||||
.depend: $(patsubst %,%.deps,${DEPENDS})
|
$(patsubst %,%.deps,${WEBCLIENT_INTFS} ${WEBCLIENT_IMPLS})
|
||||||
|
DEPENDS := $(filter-out ${NODEPENDS}, ${DEPENDS})
|
||||||
|
|
||||||
|
.SECONDARY: ${DEPENDS}
|
||||||
|
|
||||||
|
.depend: ${DEPENDS}
|
||||||
@cat $^ > .depend
|
@cat $^ > .depend
|
||||||
|
|
||||||
%.ml.deps: %.ml | predepend
|
%.ml.deps: %.ml | predepend
|
||||||
@echo OCAMLDEP ${TARGET} $(notdir $<)
|
@echo OCAMLDEP ${TARGET} $(notdir $<)
|
||||||
@$(OCAMLDEP) -native $(INCLUDES) ${EXTRA_OCAMLFLAGS} $^ > $@
|
@$(OCAMLDEP) -native $(INCLUDES) ${EXTRA_OCAMLFLAGS} $< > $@
|
||||||
|
|
||||||
%.mli.deps: %.mli | predepend
|
%.mli.deps: %.mli | predepend
|
||||||
@echo OCAMLDEP ${TARGET} $(notdir $<)
|
@echo OCAMLDEP ${TARGET} $(notdir $<)
|
||||||
@$(OCAMLDEP) -native $(INCLUDES) ${EXTRA_OCAMLFLAGS} $^ > $@
|
@$(OCAMLDEP) -native $(INCLUDES) ${EXTRA_OCAMLFLAGS} $< > $@
|
||||||
|
|
||||||
|
%.ml.deps.byte: %.ml | predepend
|
||||||
|
@echo OCAMLDEP ${TARGET} $(notdir $<)
|
||||||
|
@$(OCAMLDEP) $(INCLUDES) ${EXTRA_OCAMLFLAGS} $< > $@
|
||||||
|
|
||||||
|
%.mli.deps.byte: %.mli | predepend
|
||||||
|
@echo OCAMLDEP ${TARGET} $(notdir $<)
|
||||||
|
@$(OCAMLDEP) $(INCLUDES) ${EXTRA_OCAMLFLAGS} $< > $@
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
|
|
||||||
PROTO_VERSION := bootstrap
|
PROTO_VERSION := bootstrap
|
||||||
|
|
||||||
INTFS := \
|
CLIENT_INTFS := \
|
||||||
concrete_parser.mli \
|
concrete_parser.mli \
|
||||||
client_proto_rpcs.mli \
|
client_proto_rpcs.mli \
|
||||||
client_proto_args.mli \
|
client_proto_args.mli \
|
||||||
@ -11,7 +11,7 @@ INTFS := \
|
|||||||
client_proto_nonces.mli \
|
client_proto_nonces.mli \
|
||||||
client_proto_main.mli
|
client_proto_main.mli
|
||||||
|
|
||||||
IMPLS := \
|
CLIENT_IMPLS := \
|
||||||
script_located_ir.ml \
|
script_located_ir.ml \
|
||||||
concrete_parser.ml concrete_lexer.ml \
|
concrete_parser.ml concrete_lexer.ml \
|
||||||
client_proto_rpcs.ml \
|
client_proto_rpcs.ml \
|
||||||
@ -22,10 +22,74 @@ IMPLS := \
|
|||||||
client_proto_nonces.ml \
|
client_proto_nonces.ml \
|
||||||
client_proto_main.ml
|
client_proto_main.ml
|
||||||
|
|
||||||
OPENED_MODULES := Tezos_context
|
WEBCLIENT_INTFS := \
|
||||||
|
webclient/shared/webclient_proto_services.mli
|
||||||
|
|
||||||
predepend: concrete_parser.ml concrete_lexer.ml
|
WEBCLIENT_IMPLS := \
|
||||||
|
webclient/webclient_proto_static.ml \
|
||||||
|
webclient/shared/webclient_proto_services.ml \
|
||||||
|
webclient/webclient_proto_service_directory.ml \
|
||||||
|
webclient/webclient_proto_main.ml
|
||||||
|
|
||||||
|
SOURCE_DIRECTORIES := webclient/shared webclient/browser webclient
|
||||||
|
|
||||||
-include mining/Makefile
|
-include mining/Makefile
|
||||||
|
|
||||||
|
JS_IMPLS := \
|
||||||
|
webclient/shared/webclient_proto_services.ml \
|
||||||
|
webclient/browser/webclient_main.ml
|
||||||
|
|
||||||
|
JS_INTFS := \
|
||||||
|
webclient/shared/webclient_proto_services.mli
|
||||||
|
|
||||||
|
JS_DEPS := $(patsubst %,%.deps.byte,${JS_IMPLS} ${JS_INTFS})
|
||||||
|
|
||||||
|
DEPENDS += ${JS_DEPS}
|
||||||
|
|
||||||
|
# the generated .ml depends on the result of the bytecode compilation
|
||||||
|
NODEPENDS := webclient/webclient_proto_static.ml.deps
|
||||||
|
|
||||||
include ../Makefile.shared
|
include ../Makefile.shared
|
||||||
|
|
||||||
|
${WEBOBJS}: OPENED_MODULES += Tezos_context
|
||||||
|
${OBJS}: OPENED_MODULES += Tezos_context
|
||||||
|
|
||||||
|
predepend: concrete_parser.ml concrete_lexer.ml
|
||||||
|
|
||||||
|
webclient/webclient_proto_static.ml: $(shell find webclient/static/*) webclient/static/main.js
|
||||||
|
ocp-ocamlres webclient/static -o $@
|
||||||
|
|
||||||
|
webclient/webclient_proto_main.cmx: webclient/webclient_proto_static.cmx
|
||||||
|
|
||||||
|
.PHONY: clean
|
||||||
|
clean::
|
||||||
|
-rm -f webclient/webclient_proto_static.ml
|
||||||
|
-rm -f webclient/*/*.cm* webclient/*/*~ webclient/*/*.o webclient/*/*.a
|
||||||
|
-rm -f webclient/*/*.deps webclient/*/*.deps.byte
|
||||||
|
-rm -f mining/*.cm* mining/*~ mining/*.o mining/*.a
|
||||||
|
-rm -f mining/*.deps mining/*.deps.byte
|
||||||
|
|
||||||
|
JS_PACKAGES := \
|
||||||
|
lwt \
|
||||||
|
cstruct \
|
||||||
|
ocplib-json-typed.browser \
|
||||||
|
ocplib-json-typed.bson \
|
||||||
|
ocplib-resto.directory \
|
||||||
|
js_of_ocaml.tyxml \
|
||||||
|
js_of_ocaml.ppx
|
||||||
|
${JS_DEPS} ${JS_IMPLS:.ml=.cmo} ${JS_INTFS:.mli=.cmi} webclient/browser/main.byte: \
|
||||||
|
PACKAGES=${JS_PACKAGES}
|
||||||
|
${JS_DEPS} ${JS_IMPLS:.ml=.cmo} ${JS_INTFS:.mli=.cmi} webclient/browser/main.byte: \
|
||||||
|
OPENED_MODULES=
|
||||||
|
${JS_DEPS} ${JS_IMPLS:.ml=.cmo} ${JS_INTFS:.mli=.cmi} webclient/browser/main.byte: \
|
||||||
|
SOURCE_DIRECTORIES=../../../minutils webclient/shared webclient/browser
|
||||||
|
|
||||||
|
webclient/static/main.js: webclient/browser/main.byte
|
||||||
|
@echo JS_OF_OCAML $(notdir $@)
|
||||||
|
@js_of_ocaml +weak.js $< -o $@
|
||||||
|
|
||||||
|
webclient/browser/main.byte: \
|
||||||
|
../../../minutils.cma \
|
||||||
|
${JS_IMPLS:.ml=.cmo}
|
||||||
|
@echo LINK $(notdir $@)
|
||||||
|
${OCAMLC} ${OCAMLFLAGS} -o $@ $^ -linkpkg
|
||||||
|
@ -86,7 +86,7 @@ let tez_param ~name ~desc next =
|
|||||||
name
|
name
|
||||||
(desc ^ " in \xEA\x9C\xA9\n\
|
(desc ^ " in \xEA\x9C\xA9\n\
|
||||||
text format: D,DDD,DDD.DD (centiles and comas are optional)")
|
text format: D,DDD,DDD.DD (centiles and comas are optional)")
|
||||||
(fun s ->
|
(fun _ s ->
|
||||||
try Lwt.return (tez_of_string s)
|
try Lwt.return (tez_of_string s)
|
||||||
with _ -> Lwt.fail_with "invalid \xEA\x9C\xA9 notation")
|
with _ -> Lwt.fail_with "invalid \xEA\x9C\xA9 notation")
|
||||||
next
|
next
|
||||||
|
@ -25,7 +25,8 @@ val endorsement_delay_arg: string * Arg.spec * string
|
|||||||
val tez_param :
|
val tez_param :
|
||||||
name:string ->
|
name:string ->
|
||||||
desc:string ->
|
desc:string ->
|
||||||
'a Cli_entries.params -> (Tez.t -> 'a) Cli_entries.params
|
('a, Client_commands.context, unit) Cli_entries.params ->
|
||||||
|
(Tez.t -> 'a, Client_commands.context, unit) Cli_entries.params
|
||||||
|
|
||||||
val delegate: string option ref
|
val delegate: string option ref
|
||||||
val source: string option ref
|
val source: string option ref
|
||||||
|
@ -13,43 +13,40 @@ open Client_proto_programs
|
|||||||
open Client_keys
|
open Client_keys
|
||||||
module Ed25519 = Environment.Ed25519
|
module Ed25519 = Environment.Ed25519
|
||||||
|
|
||||||
let handle_error f () =
|
let check_contract cctxt neu =
|
||||||
f () >>= Client_proto_rpcs.handle_error
|
RawContractAlias.mem cctxt neu >>= function
|
||||||
|
|
||||||
let check_contract neu =
|
|
||||||
RawContractAlias.mem neu >>= function
|
|
||||||
| true ->
|
| true ->
|
||||||
Cli_entries.error "contract '%s' already exists" neu
|
cctxt.error "contract '%s' already exists" neu
|
||||||
| false ->
|
| false ->
|
||||||
Lwt.return ()
|
Lwt.return ()
|
||||||
|
|
||||||
let get_delegate_pkh = function
|
let get_delegate_pkh cctxt = function
|
||||||
| None -> Lwt.return None
|
| None -> Lwt.return None
|
||||||
| Some delegate ->
|
| Some delegate ->
|
||||||
Lwt.catch
|
Lwt.catch
|
||||||
(fun () ->
|
(fun () ->
|
||||||
Public_key_hash.find delegate >>= fun r ->
|
Public_key_hash.find cctxt delegate >>= fun r ->
|
||||||
Lwt.return (Some r))
|
Lwt.return (Some r))
|
||||||
(fun _ -> Lwt.return None)
|
(fun _ -> Lwt.return None)
|
||||||
|
|
||||||
let get_timestamp block () =
|
let get_timestamp cctxt block =
|
||||||
Client_node_rpcs.Blocks.timestamp block >>= fun v ->
|
Client_node_rpcs.Blocks.timestamp cctxt block >>= fun v ->
|
||||||
Cli_entries.message "%s" (Time.to_notation v)
|
cctxt.message "%s" (Time.to_notation v)
|
||||||
|
|
||||||
let list_contracts block () =
|
let list_contracts cctxt block =
|
||||||
Client_proto_rpcs.Context.Contract.list block >>=? fun contracts ->
|
Client_proto_rpcs.Context.Contract.list cctxt block >>=? fun contracts ->
|
||||||
iter_s (fun h ->
|
iter_s (fun h ->
|
||||||
begin match Contract.is_default h with
|
begin match Contract.is_default h with
|
||||||
| Some m -> begin
|
| Some m -> begin
|
||||||
Public_key_hash.rev_find m >>= function
|
Public_key_hash.rev_find cctxt m >>= function
|
||||||
| None -> Lwt.return ""
|
| None -> Lwt.return ""
|
||||||
| Some nm ->
|
| Some nm ->
|
||||||
RawContractAlias.find_opt nm >|= function
|
RawContractAlias.find_opt cctxt nm >|= function
|
||||||
| None -> " (known as " ^ nm ^ ")"
|
| None -> " (known as " ^ nm ^ ")"
|
||||||
| Some _ -> " (known as key:" ^ nm ^ ")"
|
| Some _ -> " (known as key:" ^ nm ^ ")"
|
||||||
end
|
end
|
||||||
| None -> begin
|
| None -> begin
|
||||||
RawContractAlias.rev_find h >|= function
|
RawContractAlias.rev_find cctxt h >|= function
|
||||||
| None -> ""
|
| None -> ""
|
||||||
| Some nm -> " (known as " ^ nm ^ ")"
|
| Some nm -> " (known as " ^ nm ^ ")"
|
||||||
end
|
end
|
||||||
@ -57,134 +54,129 @@ let list_contracts block () =
|
|||||||
let kind = match Contract.is_default h with
|
let kind = match Contract.is_default h with
|
||||||
| Some _ -> " (default)"
|
| Some _ -> " (default)"
|
||||||
| None -> "" in
|
| None -> "" in
|
||||||
Cli_entries.message "%s%s%s" (Contract.to_b48check h) kind nm >>= fun () ->
|
cctxt.message "%s%s%s" (Contract.to_b48check h) kind nm >>= fun () ->
|
||||||
return ())
|
return ())
|
||||||
contracts
|
contracts
|
||||||
|
|
||||||
let transfer block ?force
|
let transfer cctxt
|
||||||
|
block ?force
|
||||||
~source ~src_pk ~src_sk ~destination ?arg ~amount ~fee () =
|
~source ~src_pk ~src_sk ~destination ?arg ~amount ~fee () =
|
||||||
let open Cli_entries in
|
let open Cli_entries in
|
||||||
Client_node_rpcs.Blocks.net block >>= fun net ->
|
Client_node_rpcs.Blocks.net cctxt block >>= fun net ->
|
||||||
begin match arg with
|
begin match arg with
|
||||||
| Some arg ->
|
| Some arg ->
|
||||||
Client_proto_programs.parse_data arg >>= fun arg ->
|
Client_proto_programs.parse_data cctxt arg >>= fun arg ->
|
||||||
Lwt.return (Some arg)
|
Lwt.return (Some arg)
|
||||||
| None -> Lwt.return None
|
| None -> Lwt.return None
|
||||||
end >>= fun parameters ->
|
end >>= fun parameters ->
|
||||||
Client_proto_rpcs.Context.Contract.counter block source >>=? fun pcounter ->
|
Client_proto_rpcs.Context.Contract.counter cctxt block source >>=? fun pcounter ->
|
||||||
let counter = Int32.succ pcounter in
|
let counter = Int32.succ pcounter in
|
||||||
message "Acquired the source's sequence counter (%ld -> %ld)."
|
cctxt.message "Acquired the source's sequence counter (%ld -> %ld)."
|
||||||
pcounter counter >>= fun () ->
|
pcounter counter >>= fun () ->
|
||||||
Client_proto_rpcs.Helpers.Forge.Manager.transaction block
|
Client_proto_rpcs.Helpers.Forge.Manager.transaction cctxt block
|
||||||
~net ~source ~sourcePubKey:src_pk ~counter ~amount
|
~net ~source ~sourcePubKey:src_pk ~counter ~amount
|
||||||
~destination ?parameters ~fee () >>=? fun bytes ->
|
~destination ?parameters ~fee () >>=? fun bytes ->
|
||||||
message "Forged the raw transaction frame." >>= fun () ->
|
cctxt.message "Forged the raw transaction frame." >>= fun () ->
|
||||||
let signed_bytes = Ed25519.append_signature src_sk bytes in
|
let signed_bytes = Ed25519.append_signature src_sk bytes in
|
||||||
Client_node_rpcs.inject_operation ?force ~wait:true signed_bytes >>=? fun oph ->
|
Client_node_rpcs.inject_operation cctxt ?force ~wait:true signed_bytes >>=? fun oph ->
|
||||||
answer "Operation successfully injected in the node." >>= fun () ->
|
cctxt.answer "Operation successfully injected in the node." >>= fun () ->
|
||||||
answer "Operation hash is '%a'." Operation_hash.pp oph >>= fun () ->
|
cctxt.answer "Operation hash is '%a'." Operation_hash.pp oph >>= fun () ->
|
||||||
return ()
|
return ()
|
||||||
|
|
||||||
let originate_account block ?force
|
let originate_account cctxt
|
||||||
|
block ?force
|
||||||
~source ~src_pk ~src_sk ~manager_pkh ?delegatable ?spendable ?delegate ~balance ~fee () =
|
~source ~src_pk ~src_sk ~manager_pkh ?delegatable ?spendable ?delegate ~balance ~fee () =
|
||||||
let open Cli_entries in
|
let open Cli_entries in
|
||||||
Client_node_rpcs.Blocks.net block >>= fun net ->
|
Client_node_rpcs.Blocks.net cctxt block >>= fun net ->
|
||||||
Client_proto_rpcs.Context.Contract.counter block source >>=? fun pcounter ->
|
Client_proto_rpcs.Context.Contract.counter cctxt block source >>=? fun pcounter ->
|
||||||
let counter = Int32.succ pcounter in
|
let counter = Int32.succ pcounter in
|
||||||
message "Acquired the source's sequence counter (%ld -> %ld)."
|
cctxt.message "Acquired the source's sequence counter (%ld -> %ld)."
|
||||||
pcounter counter >>= fun () ->
|
pcounter counter >>= fun () ->
|
||||||
Client_proto_rpcs.Helpers.Forge.Manager.origination block
|
Client_proto_rpcs.Helpers.Forge.Manager.origination cctxt block
|
||||||
~net ~source ~sourcePubKey:src_pk ~managerPubKey:manager_pkh
|
~net ~source ~sourcePubKey:src_pk ~managerPubKey:manager_pkh
|
||||||
~counter ~balance ?spendable
|
~counter ~balance ?spendable
|
||||||
?delegatable ?delegatePubKey:delegate ~fee () >>=? fun (contract, bytes) ->
|
?delegatable ?delegatePubKey:delegate ~fee () >>=? fun (contract, bytes) ->
|
||||||
message "Forged the raw origination frame." >>= fun () ->
|
cctxt.message "Forged the raw origination frame." >>= fun () ->
|
||||||
let signed_bytes = Ed25519.append_signature src_sk bytes in
|
let signed_bytes = Ed25519.append_signature src_sk bytes in
|
||||||
Client_node_rpcs.inject_operation ?force ~wait:true signed_bytes >>=? fun oph ->
|
Client_node_rpcs.inject_operation cctxt ?force ~wait:true signed_bytes >>=? fun oph ->
|
||||||
message "Operation successfully injected in the node." >>= fun () ->
|
cctxt.message "Operation successfully injected in the node." >>= fun () ->
|
||||||
message "Operation hash is '%a'." Operation_hash.pp oph >>= fun () ->
|
cctxt.message "Operation hash is '%a'." Operation_hash.pp oph >>= fun () ->
|
||||||
return contract
|
return contract
|
||||||
|
|
||||||
let originate_contract
|
let originate_contract cctxt
|
||||||
block ?force
|
block ?force
|
||||||
~source ~src_pk ~src_sk ~manager_pkh ~balance ?delegatable ?delegatePubKey
|
~source ~src_pk ~src_sk ~manager_pkh ~balance ?delegatable ?delegatePubKey
|
||||||
~(code:Script.code) ~init ~fee () =
|
~(code:Script.code) ~init ~fee () =
|
||||||
let open Cli_entries in
|
let open Cli_entries in
|
||||||
Client_proto_programs.parse_data init >>= fun storage ->
|
Client_proto_programs.parse_data cctxt init >>= fun storage ->
|
||||||
let init = Script.{ storage ; storage_type = code.storage_type } in
|
let init = Script.{ storage ; storage_type = code.storage_type } in
|
||||||
Client_proto_rpcs.Context.Contract.counter block source >>=? fun pcounter ->
|
Client_proto_rpcs.Context.Contract.counter cctxt block source >>=? fun pcounter ->
|
||||||
let counter = Int32.succ pcounter in
|
let counter = Int32.succ pcounter in
|
||||||
message "Acquired the source's sequence counter (%ld -> %ld)."
|
cctxt.message "Acquired the source's sequence counter (%ld -> %ld)."
|
||||||
pcounter counter >>= fun () ->
|
pcounter counter >>= fun () ->
|
||||||
Client_node_rpcs.Blocks.net block >>= fun net ->
|
Client_node_rpcs.Blocks.net cctxt block >>= fun net ->
|
||||||
Client_proto_rpcs.Helpers.Forge.Manager.origination block
|
Client_proto_rpcs.Helpers.Forge.Manager.origination cctxt block
|
||||||
~net ~source ~sourcePubKey:src_pk ~managerPubKey:manager_pkh
|
~net ~source ~sourcePubKey:src_pk ~managerPubKey:manager_pkh
|
||||||
~counter ~balance ~spendable:!spendable
|
~counter ~balance ~spendable:!spendable
|
||||||
?delegatable ?delegatePubKey
|
?delegatable ?delegatePubKey
|
||||||
~script:(code, init) ~fee () >>=? fun (contract, bytes) ->
|
~script:(code, init) ~fee () >>=? fun (contract, bytes) ->
|
||||||
message "Forged the raw origination frame." >>= fun () ->
|
cctxt.message "Forged the raw origination frame." >>= fun () ->
|
||||||
let signed_bytes = Ed25519.append_signature src_sk bytes in
|
let signed_bytes = Ed25519.append_signature src_sk bytes in
|
||||||
Client_node_rpcs.inject_operation ?force ~wait:true signed_bytes >>=? fun oph ->
|
Client_node_rpcs.inject_operation cctxt ?force ~wait:true signed_bytes >>=? fun oph ->
|
||||||
message "Operation successfully injected in the node." >>= fun () ->
|
cctxt.message "Operation successfully injected in the node." >>= fun () ->
|
||||||
message "Operation hash is '%a'." Operation_hash.pp oph >>= fun () ->
|
cctxt.message "Operation hash is '%a'." Operation_hash.pp oph >>= fun () ->
|
||||||
return contract
|
return contract
|
||||||
|
|
||||||
|
let group =
|
||||||
|
{ Cli_entries.name = "context" ;
|
||||||
|
title = "Block contextual commands (see option -block)" }
|
||||||
|
|
||||||
let commands () =
|
let commands () =
|
||||||
let open Cli_entries in
|
let open Cli_entries in
|
||||||
register_group "context" "Block contextual commands (see option -block)" ;
|
[ command ~group ~desc: "access the timestamp of the block"
|
||||||
[ command
|
|
||||||
~group: "context"
|
|
||||||
~desc: "access the timestamp of the block"
|
|
||||||
(fixed [ "get" ; "timestamp" ])
|
(fixed [ "get" ; "timestamp" ])
|
||||||
(get_timestamp (block ())) ;
|
(fun cctxt -> get_timestamp cctxt (block ())) ;
|
||||||
command
|
command ~group ~desc: "lists all non empty contracts of the block"
|
||||||
~group: "context"
|
|
||||||
~desc: "lists all non empty contracts of the block"
|
|
||||||
(fixed [ "list" ; "contracts" ])
|
(fixed [ "list" ; "contracts" ])
|
||||||
(handle_error (list_contracts (block ()))) ;
|
(fun cctxt ->
|
||||||
command
|
list_contracts cctxt (block ()) >>= fun res ->
|
||||||
~group: "context"
|
Client_proto_rpcs.handle_error cctxt res) ;
|
||||||
~desc: "get the bootstrap keys and bootstrap contract handle"
|
command ~group ~desc: "get the bootstrap keys and bootstrap contract handle"
|
||||||
(fixed [ "bootstrap" ])
|
(fixed [ "bootstrap" ])
|
||||||
(fun () ->
|
(fun cctxt ->
|
||||||
Client_proto_rpcs.Constants.bootstrap `Genesis >>= fun accounts ->
|
Client_proto_rpcs.Constants.bootstrap cctxt `Genesis >>= fun accounts ->
|
||||||
let cpt = ref 0 in
|
let cpt = ref 0 in
|
||||||
Lwt_list.iter_s
|
Lwt_list.iter_s
|
||||||
(fun { Bootstrap.public_key_hash = pkh ;
|
(fun { Bootstrap.public_key_hash = pkh ;
|
||||||
public_key = pk ; secret_key = sk } ->
|
public_key = pk ; secret_key = sk } ->
|
||||||
incr cpt ;
|
incr cpt ;
|
||||||
let name = Printf.sprintf "bootstrap%d" !cpt in
|
let name = Printf.sprintf "bootstrap%d" !cpt in
|
||||||
Public_key_hash.add name pkh >>= fun () ->
|
Public_key_hash.add cctxt name pkh >>= fun () ->
|
||||||
Public_key.add name pk >>= fun () ->
|
Public_key.add cctxt name pk >>= fun () ->
|
||||||
Secret_key.add name sk >>= fun () ->
|
Secret_key.add cctxt name sk >>= fun () ->
|
||||||
message "Bootstrap keys added under the name '%s'." name)
|
cctxt.message "Bootstrap keys added under the name '%s'." name)
|
||||||
accounts >>= fun () ->
|
accounts >>= fun () ->
|
||||||
Lwt.return_unit) ;
|
Lwt.return_unit) ;
|
||||||
command
|
command ~group ~desc: "get the balance of a contract"
|
||||||
~group: "context"
|
|
||||||
~desc: "get the balance of a contract"
|
|
||||||
(prefixes [ "get" ; "balance" ]
|
(prefixes [ "get" ; "balance" ]
|
||||||
@@ ContractAlias.destination_param ~name:"src" ~desc:"source contract"
|
@@ ContractAlias.destination_param ~name:"src" ~desc:"source contract"
|
||||||
@@ stop)
|
@@ stop)
|
||||||
(fun (_, contract) () ->
|
(fun (_, contract) cctxt ->
|
||||||
Client_proto_rpcs.Context.Contract.balance (block ()) contract
|
Client_proto_rpcs.Context.Contract.balance cctxt (block ()) contract
|
||||||
>>= Client_proto_rpcs.handle_error >>= fun amount ->
|
>>= Client_proto_rpcs.handle_error cctxt >>= fun amount ->
|
||||||
answer "%a %s" Tez.pp amount tez_sym);
|
cctxt.answer "%a %s" Tez.pp amount tez_sym);
|
||||||
command
|
command ~group ~desc: "get the manager of a block"
|
||||||
~group: "context"
|
|
||||||
~desc: "get the manager of a block"
|
|
||||||
(prefixes [ "get" ; "manager" ]
|
(prefixes [ "get" ; "manager" ]
|
||||||
@@ ContractAlias.destination_param ~name:"src" ~desc:"source contract"
|
@@ ContractAlias.destination_param ~name:"src" ~desc:"source contract"
|
||||||
@@ stop)
|
@@ stop)
|
||||||
(fun (_, contract) () ->
|
(fun (_, contract) cctxt ->
|
||||||
Client_proto_rpcs.Context.Contract.manager (block ()) contract
|
Client_proto_rpcs.Context.Contract.manager cctxt (block ()) contract
|
||||||
>>= Client_proto_rpcs.handle_error >>= fun manager ->
|
>>= Client_proto_rpcs.handle_error cctxt >>= fun manager ->
|
||||||
Public_key_hash.rev_find manager >>= fun mn ->
|
Public_key_hash.rev_find cctxt manager >>= fun mn ->
|
||||||
Public_key_hash.to_source manager >>= fun m ->
|
Public_key_hash.to_source cctxt manager >>= fun m ->
|
||||||
message "%s (%s)" m
|
cctxt.message "%s (%s)" m
|
||||||
(match mn with None -> "unknown" | Some n -> "known as " ^ n));
|
(match mn with None -> "unknown" | Some n -> "known as " ^ n));
|
||||||
command
|
command ~group ~desc: "open a new account"
|
||||||
~group: "context"
|
|
||||||
~desc: "open a new account"
|
|
||||||
~args: ([ fee_arg ; delegate_arg ; force_arg ]
|
~args: ([ fee_arg ; delegate_arg ; force_arg ]
|
||||||
@ delegatable_args @ spendable_args)
|
@ delegatable_args @ spendable_args)
|
||||||
(prefixes [ "originate" ; "account" ]
|
(prefixes [ "originate" ; "account" ]
|
||||||
@ -200,22 +192,18 @@ let commands () =
|
|||||||
@@ ContractAlias.alias_param
|
@@ ContractAlias.alias_param
|
||||||
~name:"src" ~desc: "name of the source contract"
|
~name:"src" ~desc: "name of the source contract"
|
||||||
@@ stop)
|
@@ stop)
|
||||||
(fun neu (_, manager) balance (_, source) ->
|
(fun neu (_, manager) balance (_, source) cctxt ->
|
||||||
handle_error @@ fun () ->
|
check_contract cctxt neu >>= fun () ->
|
||||||
check_contract neu >>= fun () ->
|
get_delegate_pkh cctxt !delegate >>= fun delegate ->
|
||||||
get_delegate_pkh !delegate >>= fun delegate ->
|
(Client_proto_contracts.get_manager cctxt (block ()) source >>=? fun src_pkh ->
|
||||||
Client_proto_contracts.get_manager (block ()) source >>=? fun src_pkh ->
|
Client_keys.get_key cctxt src_pkh >>=? fun (src_name, src_pk, src_sk) ->
|
||||||
Client_keys.get_key src_pkh >>=? fun (src_name, src_pk, src_sk) ->
|
cctxt.message "Got the source's manager keys (%s)." src_name >>= fun () ->
|
||||||
message "Got the source's manager keys (%s)." src_name >>= fun () ->
|
originate_account cctxt (block ()) ~force:!force
|
||||||
originate_account (block ()) ~force:!force
|
|
||||||
~source ~src_pk ~src_sk ~manager_pkh:manager ~balance ~fee:!fee
|
~source ~src_pk ~src_sk ~manager_pkh:manager ~balance ~fee:!fee
|
||||||
~delegatable:!delegatable ~spendable:!spendable ?delegate:delegate
|
~delegatable:!delegatable ~spendable:!spendable ?delegate:delegate
|
||||||
() >>=? fun contract ->
|
()) >>= Client_proto_rpcs.handle_error cctxt >>= fun contract ->
|
||||||
RawContractAlias.add neu contract >>= fun () ->
|
RawContractAlias.add cctxt neu contract) ;
|
||||||
return ()) ;
|
command ~group ~desc: "open a new scripted account"
|
||||||
command
|
|
||||||
~group: "context"
|
|
||||||
~desc: "open a new scripted account"
|
|
||||||
~args: ([ fee_arg ; delegate_arg ; force_arg ] @
|
~args: ([ fee_arg ; delegate_arg ; force_arg ] @
|
||||||
delegatable_args @ spendable_args @ [ init_arg ])
|
delegatable_args @ spendable_args @ [ init_arg ])
|
||||||
(prefixes [ "originate" ; "contract" ]
|
(prefixes [ "originate" ; "contract" ]
|
||||||
@ -235,22 +223,18 @@ let commands () =
|
|||||||
~name:"prg" ~desc: "script of the account\n\
|
~name:"prg" ~desc: "script of the account\n\
|
||||||
combine with -init if the storage type is non void"
|
combine with -init if the storage type is non void"
|
||||||
@@ stop)
|
@@ stop)
|
||||||
(fun neu (_, manager) balance (_, source) code ->
|
(fun neu (_, manager) balance (_, source) code cctxt ->
|
||||||
handle_error @@ fun () ->
|
check_contract cctxt neu >>= fun () ->
|
||||||
check_contract neu >>= fun () ->
|
get_delegate_pkh cctxt !delegate >>= fun delegate ->
|
||||||
get_delegate_pkh !delegate >>= fun delegate ->
|
(Client_proto_contracts.get_manager cctxt (block ()) source >>=? fun src_pkh ->
|
||||||
Client_proto_contracts.get_manager (block ()) source >>=? fun src_pkh ->
|
Client_keys.get_key cctxt src_pkh >>=? fun (src_name, src_pk, src_sk) ->
|
||||||
Client_keys.get_key src_pkh >>=? fun (src_name, src_pk, src_sk) ->
|
cctxt.message "Got the source's manager keys (%s)." src_name >>= fun () ->
|
||||||
message "Got the source's manager keys (%s)." src_name >>= fun () ->
|
originate_contract cctxt (block ()) ~force:!force
|
||||||
originate_contract (block ()) ~force:!force
|
|
||||||
~source ~src_pk ~src_sk ~manager_pkh:manager ~balance ~fee:!fee
|
~source ~src_pk ~src_sk ~manager_pkh:manager ~balance ~fee:!fee
|
||||||
~delegatable:!delegatable ?delegatePubKey:delegate ~code ~init:!init ()
|
~delegatable:!delegatable ?delegatePubKey:delegate ~code ~init:!init
|
||||||
>>=? fun contract ->
|
()) >>= Client_proto_rpcs.handle_error cctxt >>= fun contract ->
|
||||||
RawContractAlias.add neu contract >>= fun () ->
|
RawContractAlias.add cctxt neu contract) ;
|
||||||
return ()) ;
|
command ~group ~desc: "transfer tokens"
|
||||||
command
|
|
||||||
~group: "context"
|
|
||||||
~desc: "transfer tokens"
|
|
||||||
~args: [ fee_arg ; arg_arg ; force_arg ]
|
~args: [ fee_arg ; arg_arg ; force_arg ]
|
||||||
(prefixes [ "transfer" ]
|
(prefixes [ "transfer" ]
|
||||||
@@ tez_param
|
@@ tez_param
|
||||||
@ -262,11 +246,11 @@ let commands () =
|
|||||||
@@ ContractAlias.destination_param
|
@@ ContractAlias.destination_param
|
||||||
~name: "dst" ~desc: "name/literal of the destination contract"
|
~name: "dst" ~desc: "name/literal of the destination contract"
|
||||||
@@ stop)
|
@@ stop)
|
||||||
(fun amount (_, source) (_, destination) ->
|
(fun amount (_, source) (_, destination) cctxt ->
|
||||||
handle_error @@ fun () ->
|
(Client_proto_contracts.get_manager cctxt (block ()) source >>=? fun src_pkh ->
|
||||||
Client_proto_contracts.get_manager (block ()) source >>=? fun src_pkh ->
|
Client_keys.get_key cctxt src_pkh >>=? fun (src_name, src_pk, src_sk) ->
|
||||||
Client_keys.get_key src_pkh >>=? fun (src_name, src_pk, src_sk) ->
|
cctxt.message "Got the source's manager keys (%s)." src_name >>= fun () ->
|
||||||
message "Got the source's manager keys (%s)." src_name >>= fun () ->
|
transfer cctxt (block ()) ~force:!force
|
||||||
transfer (block ()) ~force:!force
|
~source ~src_pk ~src_sk ~destination ?arg:!arg ~amount ~fee:!fee ()) >>=
|
||||||
~source ~src_pk ~src_sk ~destination ?arg:!arg ~amount ~fee:!fee ())
|
Client_proto_rpcs.handle_error cctxt)
|
||||||
]
|
]
|
||||||
|
@ -8,6 +8,7 @@
|
|||||||
(**************************************************************************)
|
(**************************************************************************)
|
||||||
|
|
||||||
val transfer:
|
val transfer:
|
||||||
|
Client_commands.context ->
|
||||||
Client_proto_rpcs.block ->
|
Client_proto_rpcs.block ->
|
||||||
?force:bool ->
|
?force:bool ->
|
||||||
source:Contract.t ->
|
source:Contract.t ->
|
||||||
@ -20,6 +21,7 @@ val transfer:
|
|||||||
unit -> unit tzresult Lwt.t
|
unit -> unit tzresult Lwt.t
|
||||||
|
|
||||||
val originate_account:
|
val originate_account:
|
||||||
|
Client_commands.context ->
|
||||||
Client_proto_rpcs.block ->
|
Client_proto_rpcs.block ->
|
||||||
?force:bool ->
|
?force:bool ->
|
||||||
source:Contract.t ->
|
source:Contract.t ->
|
||||||
@ -34,6 +36,7 @@ val originate_account:
|
|||||||
unit -> Contract.t tzresult Lwt.t
|
unit -> Contract.t tzresult Lwt.t
|
||||||
|
|
||||||
val originate_contract:
|
val originate_contract:
|
||||||
|
Client_commands.context ->
|
||||||
Client_proto_rpcs.block ->
|
Client_proto_rpcs.block ->
|
||||||
?force:bool ->
|
?force:bool ->
|
||||||
source:Contract.t ->
|
source:Contract.t ->
|
||||||
@ -48,4 +51,4 @@ val originate_contract:
|
|||||||
fee:Tez.t ->
|
fee:Tez.t ->
|
||||||
unit -> Contract.t tzresult Lwt.t
|
unit -> Contract.t tzresult Lwt.t
|
||||||
|
|
||||||
val commands: unit -> Cli_entries.command list
|
val commands: unit -> Client_commands.command list
|
||||||
|
@ -12,44 +12,44 @@ module Ed25519 = Environment.Ed25519
|
|||||||
module RawContractAlias = Client_aliases.Alias (struct
|
module RawContractAlias = Client_aliases.Alias (struct
|
||||||
type t = Contract.t
|
type t = Contract.t
|
||||||
let encoding = Contract.encoding
|
let encoding = Contract.encoding
|
||||||
let of_source s =
|
let of_source _ s =
|
||||||
match Contract.of_b48check s with
|
match Contract.of_b48check s with
|
||||||
| Error _ -> Lwt.fail (Failure "bad contract notation")
|
| Error _ -> Lwt.fail (Failure "bad contract notation")
|
||||||
| Ok s -> Lwt.return s
|
| Ok s -> Lwt.return s
|
||||||
let to_source s =
|
let to_source _ s =
|
||||||
Lwt.return (Contract.to_b48check s)
|
Lwt.return (Contract.to_b48check s)
|
||||||
let name = "contract"
|
let name = "contract"
|
||||||
end)
|
end)
|
||||||
|
|
||||||
module ContractAlias = struct
|
module ContractAlias = struct
|
||||||
let find s =
|
let find cctxt s =
|
||||||
RawContractAlias.find_opt s >>= function
|
RawContractAlias.find_opt cctxt s >>= function
|
||||||
| Some v -> Lwt.return (s, v)
|
| Some v -> Lwt.return (s, v)
|
||||||
| None ->
|
| None ->
|
||||||
Client_keys.Public_key_hash.find_opt s >>= function
|
Client_keys.Public_key_hash.find_opt cctxt s >>= function
|
||||||
| Some v ->
|
| Some v ->
|
||||||
Lwt.return (s, Contract.default_contract v)
|
Lwt.return (s, Contract.default_contract v)
|
||||||
| None ->
|
| None ->
|
||||||
Cli_entries.error
|
cctxt.error
|
||||||
"no contract alias nor key alias names %s" s
|
"no contract alias nor key alias names %s" s
|
||||||
let find_key name =
|
let find_key cctxt name =
|
||||||
Client_keys.Public_key_hash.find name >>= fun v ->
|
Client_keys.Public_key_hash.find cctxt name >>= fun v ->
|
||||||
Lwt.return (name, Contract.default_contract v)
|
Lwt.return (name, Contract.default_contract v)
|
||||||
|
|
||||||
let rev_find c =
|
let rev_find cctxt c =
|
||||||
match Contract.is_default c with
|
match Contract.is_default c with
|
||||||
| Some hash -> begin
|
| Some hash -> begin
|
||||||
Client_keys.Public_key_hash.rev_find hash >>= function
|
Client_keys.Public_key_hash.rev_find cctxt hash >>= function
|
||||||
| Some name -> Lwt.return (Some ("key:" ^ name))
|
| Some name -> Lwt.return (Some ("key:" ^ name))
|
||||||
| None -> Lwt.return_none
|
| None -> Lwt.return_none
|
||||||
end
|
end
|
||||||
| None -> RawContractAlias.rev_find c
|
| None -> RawContractAlias.rev_find cctxt c
|
||||||
|
|
||||||
let get_contract s =
|
let get_contract cctxt s =
|
||||||
match Utils.split ~limit:1 ':' s with
|
match Utils.split ~limit:1 ':' s with
|
||||||
| [ "key" ; key ]->
|
| [ "key" ; key ]->
|
||||||
find_key key
|
find_key cctxt key
|
||||||
| _ -> find s
|
| _ -> find cctxt s
|
||||||
|
|
||||||
let alias_param ?(name = "name") ?(desc = "existing contract alias") next =
|
let alias_param ?(name = "name") ?(desc = "existing contract alias") next =
|
||||||
let desc =
|
let desc =
|
||||||
@ -64,42 +64,42 @@ module ContractAlias = struct
|
|||||||
^ "can be an alias, a key alias, or a literal (autodetected in this order)\n\
|
^ "can be an alias, a key alias, or a literal (autodetected in this order)\n\
|
||||||
use 'text:literal', 'alias:name', 'key:name' to force" in
|
use 'text:literal', 'alias:name', 'key:name' to force" in
|
||||||
Cli_entries.param ~name ~desc
|
Cli_entries.param ~name ~desc
|
||||||
(fun s ->
|
(fun cctxt s ->
|
||||||
match Utils.split ~limit:1 ':' s with
|
match Utils.split ~limit:1 ':' s with
|
||||||
| [ "alias" ; alias ]->
|
| [ "alias" ; alias ]->
|
||||||
find alias
|
find cctxt alias
|
||||||
| [ "key" ; text ] ->
|
| [ "key" ; text ] ->
|
||||||
Client_keys.Public_key_hash.find text >>= fun v ->
|
Client_keys.Public_key_hash.find cctxt text >>= fun v ->
|
||||||
Lwt.return (s, Contract.default_contract v)
|
Lwt.return (s, Contract.default_contract v)
|
||||||
| _ ->
|
| _ ->
|
||||||
Lwt.catch
|
Lwt.catch
|
||||||
(fun () -> find s)
|
(fun () -> find cctxt s)
|
||||||
(fun _ ->
|
(fun _ ->
|
||||||
match Contract.of_b48check s with
|
match Contract.of_b48check s with
|
||||||
| Error _ -> Lwt.fail (Failure "bad contract notation")
|
| Error _ -> Lwt.fail (Failure "bad contract notation")
|
||||||
| Ok v -> Lwt.return (s, v)))
|
| Ok v -> Lwt.return (s, v)))
|
||||||
next
|
next
|
||||||
|
|
||||||
let name contract =
|
let name cctxt contract =
|
||||||
rev_find contract >|= function
|
rev_find cctxt contract >|= function
|
||||||
| None -> Contract.to_b48check contract
|
| None -> Contract.to_b48check contract
|
||||||
| Some name -> name
|
| Some name -> name
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
let get_manager block source =
|
let get_manager cctxt block source =
|
||||||
match Contract.is_default source with
|
match Contract.is_default source with
|
||||||
| Some hash -> return hash
|
| Some hash -> return hash
|
||||||
| None -> Client_proto_rpcs.Context.Contract.manager block source
|
| None -> Client_proto_rpcs.Context.Contract.manager cctxt block source
|
||||||
|
|
||||||
let get_delegate block source =
|
let get_delegate cctxt block source =
|
||||||
let open Client_keys in
|
let open Client_keys in
|
||||||
match Contract.is_default source with
|
match Contract.is_default source with
|
||||||
| Some hash -> return hash
|
| Some hash -> return hash
|
||||||
| None ->
|
| None ->
|
||||||
Client_proto_rpcs.Context.Contract.delegate block source >>=? function
|
Client_proto_rpcs.Context.Contract.delegate cctxt block source >>=? function
|
||||||
| Some delegate -> return delegate
|
| Some delegate -> return delegate
|
||||||
| None -> Client_proto_rpcs.Context.Contract.manager block source
|
| None -> Client_proto_rpcs.Context.Contract.manager cctxt block source
|
||||||
|
|
||||||
let may_check_key sourcePubKey sourcePubKeyHash =
|
let may_check_key sourcePubKey sourcePubKeyHash =
|
||||||
match sourcePubKey with
|
match sourcePubKey with
|
||||||
@ -111,8 +111,8 @@ let may_check_key sourcePubKey sourcePubKeyHash =
|
|||||||
return ()
|
return ()
|
||||||
| None -> return ()
|
| None -> return ()
|
||||||
|
|
||||||
let check_public_key block ?src_pk src_pk_hash =
|
let check_public_key cctxt block ?src_pk src_pk_hash =
|
||||||
Client_proto_rpcs.Context.Key.get block src_pk_hash >>= function
|
Client_proto_rpcs.Context.Key.get cctxt block src_pk_hash >>= function
|
||||||
| Error errors ->
|
| Error errors ->
|
||||||
begin
|
begin
|
||||||
match src_pk with
|
match src_pk with
|
||||||
@ -125,59 +125,51 @@ let check_public_key block ?src_pk src_pk_hash =
|
|||||||
end
|
end
|
||||||
| Ok _ -> return None
|
| Ok _ -> return None
|
||||||
|
|
||||||
|
let group =
|
||||||
|
{ Cli_entries.name = "contracts" ;
|
||||||
|
title = "Commands for managing the record of known contracts" }
|
||||||
|
|
||||||
let commands () =
|
let commands () =
|
||||||
let open Cli_entries in
|
let open Cli_entries in
|
||||||
register_group "contracts"
|
|
||||||
"Commands for managing the record of known contracts" ;
|
|
||||||
[
|
[
|
||||||
command
|
command ~group ~desc: "add a contract to the wallet"
|
||||||
~group: "contracts"
|
|
||||||
~desc: "add a contract to the wallet"
|
|
||||||
(prefixes [ "remember" ; "contract" ]
|
(prefixes [ "remember" ; "contract" ]
|
||||||
@@ RawContractAlias.fresh_alias_param
|
@@ RawContractAlias.fresh_alias_param
|
||||||
@@ RawContractAlias.source_param
|
@@ RawContractAlias.source_param
|
||||||
@@ stop)
|
@@ stop)
|
||||||
(fun name hash () -> RawContractAlias.add name hash) ;
|
(fun name hash cctxt -> RawContractAlias.add cctxt name hash) ;
|
||||||
command
|
command ~group ~desc: "remove a contract from the wallet"
|
||||||
~group: "contracts"
|
|
||||||
~desc: "remove a contract from the wallet"
|
|
||||||
(prefixes [ "forget" ; "contract" ]
|
(prefixes [ "forget" ; "contract" ]
|
||||||
@@ RawContractAlias.alias_param
|
@@ RawContractAlias.alias_param
|
||||||
@@ stop)
|
@@ stop)
|
||||||
(fun (name, _) () -> RawContractAlias.del name) ;
|
(fun (name, _) cctxt -> RawContractAlias.del cctxt name) ;
|
||||||
command
|
command ~group ~desc: "lists all known contracts"
|
||||||
~group: "contracts"
|
|
||||||
~desc: "lists all known contracts"
|
|
||||||
(fixed [ "list" ; "known" ; "contracts" ])
|
(fixed [ "list" ; "known" ; "contracts" ])
|
||||||
(fun () ->
|
(fun cctxt ->
|
||||||
RawContractAlias.load () >>= fun list ->
|
RawContractAlias.load cctxt >>= fun list ->
|
||||||
Lwt_list.iter_s (fun (n, v) ->
|
Lwt_list.iter_s (fun (n, v) ->
|
||||||
let v = Contract.to_b48check v in
|
let v = Contract.to_b48check v in
|
||||||
message "%s: %s" n v)
|
cctxt.message "%s: %s" n v)
|
||||||
list >>= fun () ->
|
list >>= fun () ->
|
||||||
Client_keys.Public_key_hash.load () >>= fun list ->
|
Client_keys.Public_key_hash.load cctxt >>= fun list ->
|
||||||
Lwt_list.iter_s (fun (n, v) ->
|
Lwt_list.iter_s (fun (n, v) ->
|
||||||
RawContractAlias.mem n >>= fun mem ->
|
RawContractAlias.mem cctxt n >>= fun mem ->
|
||||||
let p = if mem then "key:" else "" in
|
let p = if mem then "key:" else "" in
|
||||||
let v = Contract.to_b48check (Contract.default_contract v) in
|
let v = Contract.to_b48check (Contract.default_contract v) in
|
||||||
message "%s%s: %s" p n v)
|
cctxt.message "%s%s: %s" p n v)
|
||||||
list >>= fun () ->
|
list >>= fun () ->
|
||||||
Lwt.return ()) ;
|
Lwt.return ()) ;
|
||||||
command
|
command ~group ~desc: "forget all known contracts"
|
||||||
~group: "contracts"
|
|
||||||
~desc: "forget all known contracts"
|
|
||||||
(fixed [ "forget" ; "all" ; "contracts" ])
|
(fixed [ "forget" ; "all" ; "contracts" ])
|
||||||
(fun () ->
|
(fun cctxt ->
|
||||||
if not Client_config.force#get then
|
if not Client_config.force#get then
|
||||||
error "this can only used with option -force true"
|
cctxt.Client_commands.error "this can only used with option -force true"
|
||||||
else
|
else
|
||||||
RawContractAlias.save []) ;
|
RawContractAlias.save cctxt []) ;
|
||||||
command
|
command ~group ~desc: "display a contract from the wallet"
|
||||||
~group: "contracts"
|
|
||||||
~desc: "display a contract from the wallet"
|
|
||||||
(prefixes [ "show" ; "known" ; "contract" ]
|
(prefixes [ "show" ; "known" ; "contract" ]
|
||||||
@@ RawContractAlias.alias_param
|
@@ RawContractAlias.alias_param
|
||||||
@@ stop)
|
@@ stop)
|
||||||
(fun (_, contract) () ->
|
(fun (_, contract) cctxt ->
|
||||||
Cli_entries.message "%a\n%!" Contract.pp contract) ;
|
cctxt.message "%a\n%!" Contract.pp contract) ;
|
||||||
]
|
]
|
||||||
|
@ -11,35 +11,44 @@ module RawContractAlias :
|
|||||||
Client_aliases.Alias with type t = Contract.t
|
Client_aliases.Alias with type t = Contract.t
|
||||||
|
|
||||||
module ContractAlias : sig
|
module ContractAlias : sig
|
||||||
val get_contract: string -> (string * Contract.t) Lwt.t
|
val get_contract:
|
||||||
|
Client_commands.context ->
|
||||||
|
string -> (string * Contract.t) Lwt.t
|
||||||
val alias_param:
|
val alias_param:
|
||||||
?name:string ->
|
?name:string ->
|
||||||
?desc:string ->
|
?desc:string ->
|
||||||
'a Cli_entries.params ->
|
('a, Client_commands.context, unit) Cli_entries.params ->
|
||||||
(Lwt_io.file_name * Contract.t -> 'a) Cli_entries.params
|
(Lwt_io.file_name * Contract.t -> 'a, Client_commands.context, unit) Cli_entries.params
|
||||||
val destination_param:
|
val destination_param:
|
||||||
?name:string ->
|
?name:string ->
|
||||||
?desc:string ->
|
?desc:string ->
|
||||||
'a Cli_entries.params ->
|
('a, Client_commands.context, unit) Cli_entries.params ->
|
||||||
(Lwt_io.file_name * Contract.t -> 'a) Cli_entries.params
|
(Lwt_io.file_name * Contract.t -> 'a, Client_commands.context, unit) Cli_entries.params
|
||||||
val rev_find: Contract.t -> string option Lwt.t
|
val rev_find:
|
||||||
val name: Contract.t -> string Lwt.t
|
Client_commands.context ->
|
||||||
|
Contract.t -> string option Lwt.t
|
||||||
|
val name:
|
||||||
|
Client_commands.context ->
|
||||||
|
Contract.t -> string Lwt.t
|
||||||
end
|
end
|
||||||
|
|
||||||
val get_manager:
|
val get_manager:
|
||||||
|
Client_commands.context ->
|
||||||
Client_proto_rpcs.block ->
|
Client_proto_rpcs.block ->
|
||||||
Contract.t ->
|
Contract.t ->
|
||||||
public_key_hash tzresult Lwt.t
|
public_key_hash tzresult Lwt.t
|
||||||
|
|
||||||
val get_delegate:
|
val get_delegate:
|
||||||
|
Client_commands.context ->
|
||||||
Client_proto_rpcs.block ->
|
Client_proto_rpcs.block ->
|
||||||
Contract.t ->
|
Contract.t ->
|
||||||
public_key_hash tzresult Lwt.t
|
public_key_hash tzresult Lwt.t
|
||||||
|
|
||||||
val check_public_key :
|
val check_public_key :
|
||||||
|
Client_commands.context ->
|
||||||
Client_proto_rpcs.block ->
|
Client_proto_rpcs.block ->
|
||||||
?src_pk:public_key ->
|
?src_pk:public_key ->
|
||||||
public_key_hash ->
|
public_key_hash ->
|
||||||
public_key option tzresult Lwt.t
|
public_key option tzresult Lwt.t
|
||||||
|
|
||||||
val commands: unit -> Cli_entries.command list
|
val commands: unit -> Client_commands.command list
|
||||||
|
@ -12,7 +12,7 @@ let protocol =
|
|||||||
"4p64VagsbXchSF88eaPy5XrkqMLEjBCaSnaGv2vQkhv8e37Nnqmrd"
|
"4p64VagsbXchSF88eaPy5XrkqMLEjBCaSnaGv2vQkhv8e37Nnqmrd"
|
||||||
|
|
||||||
let () =
|
let () =
|
||||||
Client_version.register protocol @@
|
Client_commands.register protocol @@
|
||||||
Client_proto_programs.commands () @
|
Client_proto_programs.commands () @
|
||||||
Client_proto_contracts.commands () @
|
Client_proto_contracts.commands () @
|
||||||
Client_proto_context.commands ()
|
Client_proto_context.commands ()
|
||||||
|
@ -23,17 +23,17 @@ let encoding : t Data_encoding.t =
|
|||||||
let filename () =
|
let filename () =
|
||||||
Client_config.(base_dir#get // "nonces")
|
Client_config.(base_dir#get // "nonces")
|
||||||
|
|
||||||
let load () =
|
let load cctxt =
|
||||||
let filename = filename () in
|
let filename = filename () in
|
||||||
if not (Sys.file_exists filename) then
|
if not (Sys.file_exists filename) then
|
||||||
Lwt.return []
|
Lwt.return []
|
||||||
else
|
else
|
||||||
Data_encoding_ezjsonm.read_file filename >>= function
|
Data_encoding_ezjsonm.read_file filename >>= function
|
||||||
| None -> error "couldn't to read the nonces file"
|
| None -> cctxt.Client_commands.error "couldn't to read the nonces file"
|
||||||
| Some json ->
|
| Some json ->
|
||||||
match Data_encoding.Json.destruct encoding json with
|
match Data_encoding.Json.destruct encoding json with
|
||||||
| exception _ -> (* TODO print_error *)
|
| exception _ -> (* TODO print_error *)
|
||||||
error "didn't understand the nonces file"
|
cctxt.Client_commands.error "didn't understand the nonces file"
|
||||||
| list ->
|
| list ->
|
||||||
Lwt.return list
|
Lwt.return list
|
||||||
|
|
||||||
@ -43,7 +43,7 @@ let check_dir dirname =
|
|||||||
else
|
else
|
||||||
Lwt.return ()
|
Lwt.return ()
|
||||||
|
|
||||||
let save list =
|
let save cctxt list =
|
||||||
Lwt.catch
|
Lwt.catch
|
||||||
(fun () ->
|
(fun () ->
|
||||||
let dirname = Client_config.base_dir#get in
|
let dirname = Client_config.base_dir#get in
|
||||||
@ -54,29 +54,30 @@ let save list =
|
|||||||
| false -> failwith "Json.write_file"
|
| false -> failwith "Json.write_file"
|
||||||
| true -> return ())
|
| true -> return ())
|
||||||
(fun exn ->
|
(fun exn ->
|
||||||
error "could not write the nonces file: %s." (Printexc.to_string exn))
|
cctxt.Client_commands.error
|
||||||
|
"could not write the nonces file: %s." (Printexc.to_string exn))
|
||||||
|
|
||||||
let mem block_hash =
|
let mem cctxt block_hash =
|
||||||
load () >|= fun data ->
|
load cctxt >|= fun data ->
|
||||||
List.mem_assoc block_hash data
|
List.mem_assoc block_hash data
|
||||||
|
|
||||||
let find block_hash =
|
let find cctxt block_hash =
|
||||||
load () >|= fun data ->
|
load cctxt >|= fun data ->
|
||||||
try Some (List.assoc block_hash data)
|
try Some (List.assoc block_hash data)
|
||||||
with Not_found -> None
|
with Not_found -> None
|
||||||
|
|
||||||
let add block_hash nonce =
|
let add cctxt block_hash nonce =
|
||||||
load () >>= fun data ->
|
load cctxt >>= fun data ->
|
||||||
save ((block_hash, nonce) ::
|
save cctxt ((block_hash, nonce) ::
|
||||||
List.remove_assoc block_hash data)
|
List.remove_assoc block_hash data)
|
||||||
|
|
||||||
let del block_hash =
|
let del cctxt block_hash =
|
||||||
load () >>= fun data ->
|
load cctxt >>= fun data ->
|
||||||
save (List.remove_assoc block_hash data)
|
save cctxt (List.remove_assoc block_hash data)
|
||||||
|
|
||||||
let dels hashes =
|
let dels cctxt hashes =
|
||||||
load () >>= fun data ->
|
load cctxt >>= fun data ->
|
||||||
save @@
|
save cctxt @@
|
||||||
List.fold_left
|
List.fold_left
|
||||||
(fun data hash -> List.remove_assoc hash data)
|
(fun data hash -> List.remove_assoc hash data)
|
||||||
data hashes
|
data hashes
|
||||||
|
@ -7,8 +7,18 @@
|
|||||||
(* *)
|
(* *)
|
||||||
(**************************************************************************)
|
(**************************************************************************)
|
||||||
|
|
||||||
val mem: Block_hash.t -> bool Lwt.t
|
val mem:
|
||||||
val find: Block_hash.t -> Nonce.t option Lwt.t
|
Client_commands.context ->
|
||||||
val add: Block_hash.t -> Nonce.t -> unit tzresult Lwt.t
|
Block_hash.t -> bool Lwt.t
|
||||||
val del: Block_hash.t -> unit tzresult Lwt.t
|
val find:
|
||||||
val dels: Block_hash.t list -> unit tzresult Lwt.t
|
Client_commands.context ->
|
||||||
|
Block_hash.t -> Nonce.t option Lwt.t
|
||||||
|
val add:
|
||||||
|
Client_commands.context ->
|
||||||
|
Block_hash.t -> Nonce.t -> unit tzresult Lwt.t
|
||||||
|
val del:
|
||||||
|
Client_commands.context ->
|
||||||
|
Block_hash.t -> unit tzresult Lwt.t
|
||||||
|
val dels:
|
||||||
|
Client_commands.context ->
|
||||||
|
Block_hash.t list -> unit tzresult Lwt.t
|
||||||
|
@ -10,7 +10,7 @@
|
|||||||
module Ed25519 = Environment.Ed25519
|
module Ed25519 = Environment.Ed25519
|
||||||
open Client_proto_args
|
open Client_proto_args
|
||||||
|
|
||||||
let report_parse_error _prefix exn _lexbuf =
|
let report_parse_error cctxt _prefix exn _lexbuf =
|
||||||
let open Lexing in
|
let open Lexing in
|
||||||
let open Script_located_ir in
|
let open Script_located_ir in
|
||||||
let print_loc ppf ((sl, sc), (el, ec)) =
|
let print_loc ppf ((sl, sc), (el, ec)) =
|
||||||
@ -29,17 +29,17 @@ let report_parse_error _prefix exn _lexbuf =
|
|||||||
sl sc el ec in
|
sl sc el ec in
|
||||||
match exn with
|
match exn with
|
||||||
| Missing_program_field n ->
|
| Missing_program_field n ->
|
||||||
Cli_entries.error "missing script %s" n
|
cctxt.Client_commands.error "missing script %s" n
|
||||||
| Illegal_character (loc, c) ->
|
| Illegal_character (loc, c) ->
|
||||||
Cli_entries.error "%a, illegal character %C" print_loc loc c
|
cctxt.Client_commands.error "%a, illegal character %C" print_loc loc c
|
||||||
| Illegal_escape (loc, c) ->
|
| Illegal_escape (loc, c) ->
|
||||||
Cli_entries.error "%a, illegal escape sequence %S" print_loc loc c
|
cctxt.Client_commands.error "%a, illegal escape sequence %S" print_loc loc c
|
||||||
| Failure s ->
|
| Failure s ->
|
||||||
Cli_entries.error "%s" s
|
cctxt.Client_commands.error "%s" s
|
||||||
| exn ->
|
| exn ->
|
||||||
Cli_entries.error "%s" @@ Printexc.to_string exn
|
cctxt.Client_commands.error "%s" @@ Printexc.to_string exn
|
||||||
|
|
||||||
let parse_program s =
|
let parse_program cctxt s =
|
||||||
let lexbuf = Lexing.from_string s in
|
let lexbuf = Lexing.from_string s in
|
||||||
try
|
try
|
||||||
Lwt.return
|
Lwt.return
|
||||||
@ -55,7 +55,7 @@ let parse_program s =
|
|||||||
storage_type = get_field "storage" fields }
|
storage_type = get_field "storage" fields }
|
||||||
)
|
)
|
||||||
with
|
with
|
||||||
| exn -> report_parse_error "program: " exn lexbuf
|
| exn -> report_parse_error cctxt "program: " exn lexbuf
|
||||||
|
|
||||||
let rec print_ir locations ppf node =
|
let rec print_ir locations ppf node =
|
||||||
let open Script in
|
let open Script in
|
||||||
@ -99,23 +99,23 @@ let print_program locations ppf c =
|
|||||||
"@[<v 2>code@,%a@]"
|
"@[<v 2>code@,%a@]"
|
||||||
(print_ir locations) (c : Script.code).Script.code
|
(print_ir locations) (c : Script.code).Script.code
|
||||||
|
|
||||||
let parse_data s =
|
let parse_data cctxt s =
|
||||||
let lexbuf = Lexing.from_string s in
|
let lexbuf = Lexing.from_string s in
|
||||||
try
|
try
|
||||||
match Concrete_parser.tree Concrete_lexer.(token (init_state ())) lexbuf with
|
match Concrete_parser.tree Concrete_lexer.(token (init_state ())) lexbuf with
|
||||||
| [node] -> Lwt.return (Script_located_ir.strip_locations node)
|
| [node] -> Lwt.return (Script_located_ir.strip_locations node)
|
||||||
| _ -> Cli_entries.error "single data expression expected"
|
| _ -> cctxt.Client_commands.error "single data expression expected"
|
||||||
with
|
with
|
||||||
| exn -> report_parse_error "data: " exn lexbuf
|
| exn -> report_parse_error cctxt "data: " exn lexbuf
|
||||||
|
|
||||||
let parse_data_type s =
|
let parse_data_type cctxt s =
|
||||||
let lexbuf = Lexing.from_string s in
|
let lexbuf = Lexing.from_string s in
|
||||||
try
|
try
|
||||||
match Concrete_parser.tree Concrete_lexer.(token (init_state ())) lexbuf with
|
match Concrete_parser.tree Concrete_lexer.(token (init_state ())) lexbuf with
|
||||||
| [node] -> Lwt.return (Script_located_ir.strip_locations node)
|
| [node] -> Lwt.return (Script_located_ir.strip_locations node)
|
||||||
| _ -> Cli_entries.error "single type expression expected"
|
| _ -> cctxt.Client_commands.error "single type expression expected"
|
||||||
with
|
with
|
||||||
| exn -> report_parse_error "data_type: " exn lexbuf
|
| exn -> report_parse_error cctxt "data_type: " exn lexbuf
|
||||||
|
|
||||||
let unexpand_macros type_map program =
|
let unexpand_macros type_map program =
|
||||||
let open Script in
|
let open Script in
|
||||||
@ -159,11 +159,15 @@ let unexpand_macros type_map program =
|
|||||||
module Program = Client_aliases.Alias (struct
|
module Program = Client_aliases.Alias (struct
|
||||||
type t = Script.code
|
type t = Script.code
|
||||||
let encoding = Script.code_encoding
|
let encoding = Script.code_encoding
|
||||||
let of_source s = parse_program s
|
let of_source cctxt s = parse_program cctxt s
|
||||||
let to_source p = Lwt.return (Format.asprintf "%a" (print_program (fun _ -> false)) p)
|
let to_source _ p = Lwt.return (Format.asprintf "%a" (print_program (fun _ -> false)) p)
|
||||||
let name = "program"
|
let name = "program"
|
||||||
end)
|
end)
|
||||||
|
|
||||||
|
let group =
|
||||||
|
{ Cli_entries.name = "programs" ;
|
||||||
|
title = "Commands for managing the record of known programs" }
|
||||||
|
|
||||||
let commands () =
|
let commands () =
|
||||||
let open Cli_entries in
|
let open Cli_entries in
|
||||||
let show_types = ref false in
|
let show_types = ref false in
|
||||||
@ -176,41 +180,32 @@ let commands () =
|
|||||||
"-trace-stack",
|
"-trace-stack",
|
||||||
Arg.Set trace_stack,
|
Arg.Set trace_stack,
|
||||||
"Show the stack after each step" in
|
"Show the stack after each step" in
|
||||||
register_group "programs" "Commands for managing the record of known programs" ;
|
|
||||||
[
|
[
|
||||||
command
|
command ~group ~desc: "lists all known programs"
|
||||||
~group: "programs"
|
|
||||||
~desc: "lists all known programs"
|
|
||||||
(fixed [ "list" ; "known" ; "programs" ])
|
(fixed [ "list" ; "known" ; "programs" ])
|
||||||
(fun () -> Program.load () >>= fun list ->
|
(fun cctxt -> Program.load cctxt >>= fun list ->
|
||||||
Lwt_list.iter_s (fun (n, _) -> message "%s" n) list) ;
|
Lwt_list.iter_s (fun (n, _) -> cctxt.message "%s" n) list) ;
|
||||||
command
|
command ~group ~desc: "remember a program under some name"
|
||||||
~group: "programs"
|
|
||||||
~desc: "remember a program under some name"
|
|
||||||
(prefixes [ "remember" ; "program" ]
|
(prefixes [ "remember" ; "program" ]
|
||||||
@@ Program.fresh_alias_param
|
@@ Program.fresh_alias_param
|
||||||
@@ Program.source_param
|
@@ Program.source_param
|
||||||
@@ stop)
|
@@ stop)
|
||||||
(fun name hash () -> Program.add name hash) ;
|
(fun name hash cctxt ->
|
||||||
command
|
Program.add cctxt name hash) ;
|
||||||
~group: "programs"
|
command ~group ~desc: "forget a remembered program"
|
||||||
~desc: "forget a remembered program"
|
|
||||||
(prefixes [ "forget" ; "program" ]
|
(prefixes [ "forget" ; "program" ]
|
||||||
@@ Program.alias_param
|
@@ Program.alias_param
|
||||||
@@ stop)
|
@@ stop)
|
||||||
(fun (name, _) () -> Program.del name) ;
|
(fun (name, _) cctxt ->
|
||||||
command
|
Program.del cctxt name) ;
|
||||||
~group: "programs"
|
command ~group ~desc: "display a program"
|
||||||
~desc: "display a program"
|
|
||||||
(prefixes [ "show" ; "known" ; "program" ]
|
(prefixes [ "show" ; "known" ; "program" ]
|
||||||
@@ Program.alias_param
|
@@ Program.alias_param
|
||||||
@@ stop)
|
@@ stop)
|
||||||
(fun (_, program) () ->
|
(fun (_, program) cctxt ->
|
||||||
Program.to_source program >>= fun source ->
|
Program.to_source cctxt program >>= fun source ->
|
||||||
Cli_entries.message "%s\n" source) ;
|
cctxt.message "%s\n" source) ;
|
||||||
command
|
command ~group ~desc: "ask the node to run a program"
|
||||||
~group: "programs"
|
|
||||||
~desc: "ask the node to run a program"
|
|
||||||
~args: [ trace_stack_arg ]
|
~args: [ trace_stack_arg ]
|
||||||
(prefixes [ "run" ; "program" ]
|
(prefixes [ "run" ; "program" ]
|
||||||
@@ Program.source_param
|
@@ Program.source_param
|
||||||
@ -219,12 +214,13 @@ let commands () =
|
|||||||
@@ prefixes [ "and" ; "input" ]
|
@@ prefixes [ "and" ; "input" ]
|
||||||
@@ Cli_entries.param ~name:"storage" ~desc:"the untagged input data" parse_data
|
@@ Cli_entries.param ~name:"storage" ~desc:"the untagged input data" parse_data
|
||||||
@@ stop)
|
@@ stop)
|
||||||
(fun program storage input () ->
|
(fun program storage input cctxt ->
|
||||||
let open Data_encoding in
|
let open Data_encoding in
|
||||||
if !trace_stack then
|
if !trace_stack then
|
||||||
Client_proto_rpcs.Helpers.trace_code (block ()) program (storage, input) >>= function
|
Client_proto_rpcs.Helpers.trace_code cctxt
|
||||||
|
(block ()) program (storage, input) >>= function
|
||||||
| Ok (storage, output, trace) ->
|
| Ok (storage, output, trace) ->
|
||||||
Cli_entries.message "@[<v 0>@[<v 2>storage@,%a@]@,@[<v 2>output@,%a@]@,@[<v 2>trace@,%a@]@]@."
|
cctxt.message "@[<v 0>@[<v 2>storage@,%a@]@,@[<v 2>output@,%a@]@,@[<v 2>trace@,%a@]@]@."
|
||||||
(print_ir (fun _ -> false)) storage
|
(print_ir (fun _ -> false)) storage
|
||||||
(print_ir (fun _ -> false)) output
|
(print_ir (fun _ -> false)) output
|
||||||
(Format.pp_print_list
|
(Format.pp_print_list
|
||||||
@ -237,37 +233,36 @@ let commands () =
|
|||||||
trace
|
trace
|
||||||
| Error errs ->
|
| Error errs ->
|
||||||
pp_print_error Format.err_formatter errs ;
|
pp_print_error Format.err_formatter errs ;
|
||||||
error "error running program"
|
cctxt.error "error running program"
|
||||||
else
|
else
|
||||||
Client_proto_rpcs.Helpers.run_code (block ()) program (storage, input) >>= function
|
Client_proto_rpcs.Helpers.run_code cctxt
|
||||||
|
(block ()) program (storage, input) >>= function
|
||||||
| Ok (storage, output) ->
|
| Ok (storage, output) ->
|
||||||
Cli_entries.message "@[<v 0>@[<v 2>storage@,%a@]@,@[<v 2>output@,%a@]@]@."
|
cctxt.message "@[<v 0>@[<v 2>storage@,%a@]@,@[<v 2>output@,%a@]@]@."
|
||||||
(print_ir (fun _ -> false)) storage
|
(print_ir (fun _ -> false)) storage
|
||||||
(print_ir (fun _ -> false)) output
|
(print_ir (fun _ -> false)) output
|
||||||
| Error errs ->
|
| Error errs ->
|
||||||
pp_print_error Format.err_formatter errs ;
|
pp_print_error Format.err_formatter errs ;
|
||||||
error "error running program") ;
|
cctxt.error "error running program") ;
|
||||||
command
|
command ~group ~desc: "ask the node to typecheck a program"
|
||||||
~group: "programs"
|
|
||||||
~desc: "ask the node to typecheck a program"
|
|
||||||
~args: [ show_types_arg ]
|
~args: [ show_types_arg ]
|
||||||
(prefixes [ "typecheck" ; "program" ]
|
(prefixes [ "typecheck" ; "program" ]
|
||||||
@@ Program.source_param
|
@@ Program.source_param
|
||||||
@@ stop)
|
@@ stop)
|
||||||
(fun program () ->
|
(fun program cctxt ->
|
||||||
let open Data_encoding in
|
let open Data_encoding in
|
||||||
Client_proto_rpcs.Helpers.typecheck_code (block ()) program >>= function
|
Client_proto_rpcs.Helpers.typecheck_code cctxt (block ()) program >>= function
|
||||||
| Ok type_map ->
|
| Ok type_map ->
|
||||||
let type_map, program = unexpand_macros type_map program in
|
let type_map, program = unexpand_macros type_map program in
|
||||||
message "Well typed" >>= fun () ->
|
cctxt.message "Well typed" >>= fun () ->
|
||||||
if !show_types then begin
|
if !show_types then begin
|
||||||
print_program
|
print_program
|
||||||
(fun l -> List.mem_assoc l type_map)
|
(fun l -> List.mem_assoc l type_map)
|
||||||
Format.std_formatter program ;
|
Format.std_formatter program ;
|
||||||
Cli_entries.message "@." >>= fun () ->
|
cctxt.message "@." >>= fun () ->
|
||||||
Lwt_list.iter_s
|
Lwt_list.iter_s
|
||||||
(fun (loc, (before, after)) ->
|
(fun (loc, (before, after)) ->
|
||||||
Cli_entries.message
|
cctxt.message
|
||||||
"%3d@[<v 0> : [ @[<v 0>%a ]@]@,-> [ @[<v 0>%a ]@]@]@."
|
"%3d@[<v 0> : [ @[<v 0>%a ]@]@,-> [ @[<v 0>%a ]@]@]@."
|
||||||
loc
|
loc
|
||||||
(Format.pp_print_list (print_ir (fun _ -> false)))
|
(Format.pp_print_list (print_ir (fun _ -> false)))
|
||||||
@ -279,41 +274,38 @@ let commands () =
|
|||||||
else Lwt.return ()
|
else Lwt.return ()
|
||||||
| Error errs ->
|
| Error errs ->
|
||||||
pp_print_error Format.err_formatter errs ;
|
pp_print_error Format.err_formatter errs ;
|
||||||
error "ill-typed program") ;
|
cctxt.error "ill-typed program") ;
|
||||||
command
|
command ~group ~desc: "ask the node to typecheck a tagged data expression"
|
||||||
~group: "programs"
|
|
||||||
~desc: "ask the node to typecheck a tagged data expression"
|
|
||||||
(prefixes [ "typecheck" ; "data" ]
|
(prefixes [ "typecheck" ; "data" ]
|
||||||
@@ Cli_entries.param ~name:"data" ~desc:"the data to typecheck" parse_data
|
@@ Cli_entries.param ~name:"data" ~desc:"the data to typecheck" parse_data
|
||||||
@@ prefixes [ "against" ; "type" ]
|
@@ prefixes [ "against" ; "type" ]
|
||||||
@@ Cli_entries.param ~name:"type" ~desc:"the expected type" parse_data
|
@@ Cli_entries.param ~name:"type" ~desc:"the expected type" parse_data
|
||||||
@@ stop)
|
@@ stop)
|
||||||
(fun data exp_ty () ->
|
(fun data exp_ty cctxt ->
|
||||||
let open Data_encoding in
|
let open Data_encoding in
|
||||||
Client_proto_rpcs.Helpers.typecheck_untagged_data
|
Client_proto_rpcs.Helpers.typecheck_untagged_data cctxt
|
||||||
(block ()) (data, exp_ty) >>= function
|
(block ()) (data, exp_ty) >>= function
|
||||||
| Ok () ->
|
| Ok () ->
|
||||||
message "Well typed"
|
cctxt.message "Well typed"
|
||||||
| Error errs ->
|
| Error errs ->
|
||||||
pp_print_error Format.err_formatter errs ;
|
pp_print_error Format.err_formatter errs ;
|
||||||
error "ill-typed data") ;
|
cctxt.error "ill-typed data") ;
|
||||||
command
|
command ~group
|
||||||
~group: "programs"
|
|
||||||
~desc: "ask the node to compute the hash of an untagged data expression \
|
~desc: "ask the node to compute the hash of an untagged data expression \
|
||||||
using the same algorithm as script instruction H"
|
using the same algorithm as script instruction H"
|
||||||
(prefixes [ "hash" ; "data" ]
|
(prefixes [ "hash" ; "data" ]
|
||||||
@@ Cli_entries.param ~name:"data" ~desc:"the data to hash" parse_data
|
@@ Cli_entries.param ~name:"data" ~desc:"the data to hash" parse_data
|
||||||
@@ stop)
|
@@ stop)
|
||||||
(fun data () ->
|
(fun data cctxt ->
|
||||||
let open Data_encoding in
|
let open Data_encoding in
|
||||||
Client_proto_rpcs.Helpers.hash_data (block ()) data >>= function
|
Client_proto_rpcs.Helpers.hash_data cctxt
|
||||||
|
(block ()) data >>= function
|
||||||
| Ok hash ->
|
| Ok hash ->
|
||||||
message "%S" hash
|
cctxt.message "%S" hash
|
||||||
| Error errs ->
|
| Error errs ->
|
||||||
pp_print_error Format.err_formatter errs ;
|
pp_print_error Format.err_formatter errs ;
|
||||||
error "ill-formed data") ;
|
cctxt.error "ill-formed data") ;
|
||||||
command
|
command ~group
|
||||||
~group: "programs"
|
|
||||||
~desc: "ask the node to compute the hash of an untagged data expression \
|
~desc: "ask the node to compute the hash of an untagged data expression \
|
||||||
using the same algorithm as script instruction H, sign it using \
|
using the same algorithm as script instruction H, sign it using \
|
||||||
a given secret key, and display it using the format expected by \
|
a given secret key, and display it using the format expected by \
|
||||||
@ -323,17 +315,18 @@ let commands () =
|
|||||||
@@ prefixes [ "for" ]
|
@@ prefixes [ "for" ]
|
||||||
@@ Client_keys.Secret_key.alias_param
|
@@ Client_keys.Secret_key.alias_param
|
||||||
@@ stop)
|
@@ stop)
|
||||||
(fun data (_, key) () ->
|
(fun data (_, key) cctxt ->
|
||||||
let open Data_encoding in
|
let open Data_encoding in
|
||||||
Client_proto_rpcs.Helpers.hash_data (block ()) data >>= function
|
Client_proto_rpcs.Helpers.hash_data cctxt
|
||||||
|
(block ()) data >>= function
|
||||||
| Ok hash ->
|
| Ok hash ->
|
||||||
let signature = Ed25519.sign key (MBytes.of_string hash) in
|
let signature = Ed25519.sign key (MBytes.of_string hash) in
|
||||||
message "Hash: %S@.Signature: %S"
|
cctxt.message "Hash: %S@.Signature: %S"
|
||||||
hash
|
hash
|
||||||
(signature |>
|
(signature |>
|
||||||
Data_encoding.Binary.to_bytes Ed25519.signature_encoding |>
|
Data_encoding.Binary.to_bytes Ed25519.signature_encoding |>
|
||||||
Hex_encode.hex_of_bytes)
|
Hex_encode.hex_of_bytes)
|
||||||
| Error errs ->
|
| Error errs ->
|
||||||
pp_print_error Format.err_formatter errs ;
|
pp_print_error Format.err_formatter errs ;
|
||||||
error "ill-formed data") ;
|
cctxt.error "ill-formed data") ;
|
||||||
]
|
]
|
||||||
|
@ -7,10 +7,16 @@
|
|||||||
(* *)
|
(* *)
|
||||||
(**************************************************************************)
|
(**************************************************************************)
|
||||||
|
|
||||||
val parse_program: string -> Script.code Lwt.t
|
val parse_program:
|
||||||
val parse_data: string -> Script.expr Lwt.t
|
Client_commands.context ->
|
||||||
val parse_data_type: string -> Script.expr Lwt.t
|
string -> Script.code Lwt.t
|
||||||
|
val parse_data:
|
||||||
|
Client_commands.context ->
|
||||||
|
string -> Script.expr Lwt.t
|
||||||
|
val parse_data_type:
|
||||||
|
Client_commands.context ->
|
||||||
|
string -> Script.expr Lwt.t
|
||||||
|
|
||||||
module Program : Client_aliases.Alias with type t = Script.code
|
module Program : Client_aliases.Alias with type t = Script.code
|
||||||
|
|
||||||
val commands: unit -> Cli_entries.command list
|
val commands: unit -> Client_commands.command list
|
||||||
|
@ -10,11 +10,11 @@
|
|||||||
let string_of_errors exns =
|
let string_of_errors exns =
|
||||||
Format.asprintf " @[<v>%a@]" pp_print_error exns
|
Format.asprintf " @[<v>%a@]" pp_print_error exns
|
||||||
|
|
||||||
let handle_error = function
|
let handle_error cctxt = function
|
||||||
| Ok res -> Lwt.return res
|
| Ok res -> Lwt.return res
|
||||||
| Error exns ->
|
| Error exns ->
|
||||||
pp_print_error Format.err_formatter exns ;
|
pp_print_error Format.err_formatter exns ;
|
||||||
Cli_entries.error "cannot continue"
|
cctxt.Client_commands.error "%s" "cannot continue"
|
||||||
|
|
||||||
type net = State.net_id = Net of Block_hash.t
|
type net = State.net_id = Net of Block_hash.t
|
||||||
type block = [
|
type block = [
|
||||||
@ -24,42 +24,46 @@ type block = [
|
|||||||
| `Hash of Block_hash.t
|
| `Hash of Block_hash.t
|
||||||
]
|
]
|
||||||
|
|
||||||
let call_service1 s block a1 =
|
let call_service1 cctxt s block a1 =
|
||||||
Client_node_rpcs.call_service1
|
Client_node_rpcs.call_service1 cctxt
|
||||||
(s Node_rpc_services.Blocks.proto_path) block a1
|
(s Node_rpc_services.Blocks.proto_path) block a1
|
||||||
let call_error_service1 s block a1 =
|
let call_error_service1 cctxt s block a1 =
|
||||||
call_service1 s block a1 >|= wrap_error
|
call_service1 cctxt s block a1 >|= wrap_error
|
||||||
let call_service2 s block a1 a2 =
|
let call_service2 cctxt s block a1 a2 =
|
||||||
Client_node_rpcs.call_service2
|
Client_node_rpcs.call_service2 cctxt
|
||||||
(s Node_rpc_services.Blocks.proto_path) block a1 a2
|
(s Node_rpc_services.Blocks.proto_path) block a1 a2
|
||||||
let call_error_service2 s block a1 a2 =
|
let call_error_service2 cctxt s block a1 a2 =
|
||||||
call_service2 s block a1 a2 >|= wrap_error
|
call_service2 cctxt s block a1 a2 >|= wrap_error
|
||||||
|
|
||||||
module Constants = struct
|
module Constants = struct
|
||||||
let bootstrap block = call_service1 Services.Constants.bootstrap block ()
|
let bootstrap cctxt block =
|
||||||
let errors block = call_service1 Services.Constants.errors block ()
|
call_service1 cctxt Services.Constants.bootstrap block ()
|
||||||
let cycle_length block =
|
let errors cctxt block =
|
||||||
call_error_service1 Services.Constants.cycle_length block ()
|
call_service1 cctxt Services.Constants.errors block ()
|
||||||
let voting_period_length block =
|
let cycle_length cctxt block =
|
||||||
call_error_service1 Services.Constants.voting_period_length block ()
|
call_error_service1 cctxt Services.Constants.cycle_length block ()
|
||||||
let time_before_reward block =
|
let voting_period_length cctxt block =
|
||||||
call_error_service1 Services.Constants.time_before_reward block ()
|
call_error_service1 cctxt Services.Constants.voting_period_length block ()
|
||||||
let time_between_slots block =
|
let time_before_reward cctxt block =
|
||||||
call_error_service1 Services.Constants.time_between_slots block ()
|
call_error_service1 cctxt Services.Constants.time_before_reward block ()
|
||||||
let first_free_mining_slot block =
|
let time_between_slots cctxt block =
|
||||||
call_error_service1 Services.Constants.first_free_mining_slot block ()
|
call_error_service1 cctxt Services.Constants.time_between_slots block ()
|
||||||
let max_signing_slot block =
|
let first_free_mining_slot cctxt block =
|
||||||
call_error_service1 Services.Constants.max_signing_slot block ()
|
call_error_service1 cctxt Services.Constants.first_free_mining_slot block ()
|
||||||
let instructions_per_transaction block =
|
let max_signing_slot cctxt block =
|
||||||
call_error_service1 Services.Constants.instructions_per_transaction block ()
|
call_error_service1 cctxt Services.Constants.max_signing_slot block ()
|
||||||
let stamp_threshold block =
|
let instructions_per_transaction cctxt block =
|
||||||
call_error_service1 Services.Constants.proof_of_work_threshold block ()
|
call_error_service1 cctxt Services.Constants.instructions_per_transaction block ()
|
||||||
|
let stamp_threshold cctxt block =
|
||||||
|
call_error_service1 cctxt Services.Constants.proof_of_work_threshold block ()
|
||||||
end
|
end
|
||||||
|
|
||||||
module Context = struct
|
module Context = struct
|
||||||
|
|
||||||
let level block = call_error_service1 Services.Context.level block ()
|
let level cctxt block =
|
||||||
let next_level block = call_error_service1 Services.Context.next_level block ()
|
call_error_service1 cctxt Services.Context.level block ()
|
||||||
|
let next_level cctxt block =
|
||||||
|
call_error_service1 cctxt Services.Context.next_level block ()
|
||||||
|
|
||||||
module Nonce = struct
|
module Nonce = struct
|
||||||
|
|
||||||
@ -68,27 +72,27 @@ module Context = struct
|
|||||||
| Missing of Nonce_hash.t
|
| Missing of Nonce_hash.t
|
||||||
| Forgotten
|
| Forgotten
|
||||||
|
|
||||||
let get block level =
|
let get cctxt block level =
|
||||||
call_error_service2 Services.Context.Nonce.get block level ()
|
call_error_service2 cctxt Services.Context.Nonce.get block level ()
|
||||||
|
|
||||||
let hash block =
|
let hash cctxt block =
|
||||||
call_error_service1 Services.Context.Nonce.hash block ()
|
call_error_service1 cctxt Services.Context.Nonce.hash block ()
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
module Key = struct
|
module Key = struct
|
||||||
|
|
||||||
let get block pk_h =
|
let get cctxt block pk_h =
|
||||||
call_error_service2 Services.Context.Key.get block pk_h ()
|
call_error_service2 cctxt Services.Context.Key.get block pk_h ()
|
||||||
|
|
||||||
let list block =
|
let list cctxt block =
|
||||||
call_error_service1 Services.Context.Key.list block ()
|
call_error_service1 cctxt Services.Context.Key.list block ()
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
module Contract = struct
|
module Contract = struct
|
||||||
let list b =
|
let list cctxt b =
|
||||||
call_error_service1 Services.Context.Contract.list b ()
|
call_error_service1 cctxt Services.Context.Contract.list b ()
|
||||||
type info = Services.Context.Contract.info = {
|
type info = Services.Context.Contract.info = {
|
||||||
manager: public_key_hash ;
|
manager: public_key_hash ;
|
||||||
balance: Tez.t ;
|
balance: Tez.t ;
|
||||||
@ -98,64 +102,68 @@ module Context = struct
|
|||||||
assets: Asset.Map.t ;
|
assets: Asset.Map.t ;
|
||||||
counter: int32 ;
|
counter: int32 ;
|
||||||
}
|
}
|
||||||
let get b c =
|
let get cctxt b c =
|
||||||
call_error_service2 Services.Context.Contract.get b c ()
|
call_error_service2 cctxt Services.Context.Contract.get b c ()
|
||||||
let balance b c =
|
let balance cctxt b c =
|
||||||
call_error_service2 Services.Context.Contract.balance b c ()
|
call_error_service2 cctxt Services.Context.Contract.balance b c ()
|
||||||
let manager b c =
|
let manager cctxt b c =
|
||||||
call_error_service2 Services.Context.Contract.manager b c ()
|
call_error_service2 cctxt Services.Context.Contract.manager b c ()
|
||||||
let delegate b c =
|
let delegate cctxt b c =
|
||||||
call_error_service2 Services.Context.Contract.delegate b c ()
|
call_error_service2 cctxt Services.Context.Contract.delegate b c ()
|
||||||
let counter b c =
|
let counter cctxt b c =
|
||||||
call_error_service2 Services.Context.Contract.counter b c ()
|
call_error_service2 cctxt Services.Context.Contract.counter b c ()
|
||||||
let spendable b c =
|
let spendable cctxt b c =
|
||||||
call_error_service2 Services.Context.Contract.spendable b c ()
|
call_error_service2 cctxt Services.Context.Contract.spendable b c ()
|
||||||
let delegatable b c =
|
let delegatable cctxt b c =
|
||||||
call_error_service2 Services.Context.Contract.delegatable b c ()
|
call_error_service2 cctxt Services.Context.Contract.delegatable b c ()
|
||||||
let script b c =
|
let script cctxt b c =
|
||||||
call_error_service2 Services.Context.Contract.script b c ()
|
call_error_service2 cctxt Services.Context.Contract.script b c ()
|
||||||
let assets b c =
|
let assets cctxt b c =
|
||||||
call_error_service2 Services.Context.Contract.assets b c ()
|
call_error_service2 cctxt Services.Context.Contract.assets b c ()
|
||||||
end
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
module Helpers = struct
|
module Helpers = struct
|
||||||
|
|
||||||
let minimal_time block ?prio () =
|
let minimal_time cctxt block ?prio () =
|
||||||
call_error_service1 Services.Helpers.minimal_timestamp block prio
|
call_error_service1 cctxt Services.Helpers.minimal_timestamp block prio
|
||||||
|
|
||||||
let typecheck_code = call_error_service1 Services.Helpers.typecheck_code
|
let typecheck_code cctxt =
|
||||||
|
call_error_service1 cctxt Services.Helpers.typecheck_code
|
||||||
|
|
||||||
let run_code block code (storage, input) =
|
let run_code cctxt block code (storage, input) =
|
||||||
call_error_service1 Services.Helpers.run_code
|
call_error_service1 cctxt Services.Helpers.run_code
|
||||||
block (code, storage, input, None, None)
|
block (code, storage, input, None, None)
|
||||||
|
|
||||||
let trace_code block code (storage, input) =
|
let trace_code cctxt block code (storage, input) =
|
||||||
call_error_service1 Services.Helpers.trace_code
|
call_error_service1 cctxt Services.Helpers.trace_code
|
||||||
block (code, storage, input, None, None)
|
block (code, storage, input, None, None)
|
||||||
|
|
||||||
let typecheck_tagged_data = call_error_service1 Services.Helpers.typecheck_tagged_data
|
let typecheck_tagged_data cctxt =
|
||||||
|
call_error_service1 cctxt Services.Helpers.typecheck_tagged_data
|
||||||
|
|
||||||
let typecheck_untagged_data = call_error_service1 Services.Helpers.typecheck_untagged_data
|
let typecheck_untagged_data cctxt =
|
||||||
|
call_error_service1 cctxt Services.Helpers.typecheck_untagged_data
|
||||||
|
|
||||||
let hash_data = call_error_service1 Services.Helpers.hash_data
|
let hash_data cctxt =
|
||||||
|
call_error_service1 cctxt Services.Helpers.hash_data
|
||||||
|
|
||||||
let level block ?offset lvl =
|
let level cctxt block ?offset lvl =
|
||||||
call_error_service2 Services.Helpers.level block lvl offset
|
call_error_service2 cctxt Services.Helpers.level block lvl offset
|
||||||
|
|
||||||
let levels block cycle =
|
let levels cctxt block cycle =
|
||||||
call_error_service2 Services.Helpers.levels block cycle ()
|
call_error_service2 cctxt Services.Helpers.levels block cycle ()
|
||||||
|
|
||||||
module Rights = struct
|
module Rights = struct
|
||||||
type slot = Raw_level.t * int * Time.t option
|
type slot = Raw_level.t * int * Time.t option
|
||||||
let mining_rights_for_delegate
|
let mining_rights_for_delegate cctxt
|
||||||
b c ?max_priority ?first_level ?last_level () =
|
b c ?max_priority ?first_level ?last_level () =
|
||||||
call_error_service2 Services.Helpers.Rights.mining_rights_for_delegate
|
call_error_service2 cctxt Services.Helpers.Rights.mining_rights_for_delegate
|
||||||
b c (max_priority, first_level, last_level)
|
b c (max_priority, first_level, last_level)
|
||||||
let endorsement_rights_for_delegate
|
let endorsement_rights_for_delegate cctxt
|
||||||
b c ?max_priority ?first_level ?last_level () =
|
b c ?max_priority ?first_level ?last_level () =
|
||||||
call_error_service2 Services.Helpers.Rights.endorsement_rights_for_delegate
|
call_error_service2 cctxt Services.Helpers.Rights.endorsement_rights_for_delegate
|
||||||
b c (max_priority, first_level, last_level)
|
b c (max_priority, first_level, last_level)
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -168,24 +176,24 @@ module Helpers = struct
|
|||||||
open Operation
|
open Operation
|
||||||
|
|
||||||
module Manager = struct
|
module Manager = struct
|
||||||
let operations
|
let operations cctxt
|
||||||
block ~net ~source ?sourcePubKey ~counter ~fee operations =
|
block ~net ~source ?sourcePubKey ~counter ~fee operations =
|
||||||
let ops =
|
let ops =
|
||||||
Manager_operations { source ; public_key = sourcePubKey ;
|
Manager_operations { source ; public_key = sourcePubKey ;
|
||||||
counter ; operations ; fee } in
|
counter ; operations ; fee } in
|
||||||
(call_error_service1 Services.Helpers.Forge.operations block
|
(call_error_service1 cctxt Services.Helpers.Forge.operations block
|
||||||
({net_id=net}, Sourced_operations ops))
|
({net_id=net}, Sourced_operations ops))
|
||||||
>>=? fun (bytes, contracts) ->
|
>>=? fun (bytes, contracts) ->
|
||||||
return (bytes, match contracts with None -> [] | Some l -> l)
|
return (bytes, match contracts with None -> [] | Some l -> l)
|
||||||
let transaction
|
let transaction cctxt
|
||||||
block ~net ~source ?sourcePubKey ~counter
|
block ~net ~source ?sourcePubKey ~counter
|
||||||
~amount ~destination ?parameters ~fee ()=
|
~amount ~destination ?parameters ~fee ()=
|
||||||
operations block ~net ~source ?sourcePubKey ~counter ~fee
|
operations cctxt block ~net ~source ?sourcePubKey ~counter ~fee
|
||||||
Tezos_context.[Transaction { amount ; parameters ; destination }]
|
Tezos_context.[Transaction { amount ; parameters ; destination }]
|
||||||
>>=? fun (bytes, contracts) ->
|
>>=? fun (bytes, contracts) ->
|
||||||
assert (contracts = []) ;
|
assert (contracts = []) ;
|
||||||
return bytes
|
return bytes
|
||||||
let origination
|
let origination cctxt
|
||||||
block ~net
|
block ~net
|
||||||
~source ?sourcePubKey ~counter
|
~source ?sourcePubKey ~counter
|
||||||
~managerPubKey ~balance
|
~managerPubKey ~balance
|
||||||
@ -193,7 +201,7 @@ module Helpers = struct
|
|||||||
?(delegatable = true)
|
?(delegatable = true)
|
||||||
?delegatePubKey ?script ~fee () =
|
?delegatePubKey ?script ~fee () =
|
||||||
let script = script_of_option script in
|
let script = script_of_option script in
|
||||||
operations block ~net ~source ?sourcePubKey ~counter ~fee
|
operations cctxt block ~net ~source ?sourcePubKey ~counter ~fee
|
||||||
Tezos_context.[
|
Tezos_context.[
|
||||||
Origination { manager = managerPubKey ;
|
Origination { manager = managerPubKey ;
|
||||||
delegate = delegatePubKey ;
|
delegate = delegatePubKey ;
|
||||||
@ -206,54 +214,56 @@ module Helpers = struct
|
|||||||
match contracts with
|
match contracts with
|
||||||
| [contract] -> return (contract, bytes)
|
| [contract] -> return (contract, bytes)
|
||||||
| _ -> assert false
|
| _ -> assert false
|
||||||
let issuance
|
let issuance cctxt
|
||||||
block ~net ~source ?sourcePubKey ~counter ~assetType ~quantity ~fee ()=
|
block ~net ~source ?sourcePubKey ~counter ~assetType ~quantity ~fee ()=
|
||||||
operations block ~net ~source ?sourcePubKey ~counter ~fee
|
operations cctxt block ~net ~source ?sourcePubKey ~counter ~fee
|
||||||
Tezos_context.[Issuance { asset = assetType ; amount = quantity }]
|
Tezos_context.[Issuance { asset = assetType ; amount = quantity }]
|
||||||
>>=? fun (bytes, contracts) ->
|
>>=? fun (bytes, contracts) ->
|
||||||
assert (contracts = []) ;
|
assert (contracts = []) ;
|
||||||
return bytes
|
return bytes
|
||||||
let delegation
|
let delegation cctxt
|
||||||
block ~net ~source ?sourcePubKey ~counter ~fee delegate =
|
block ~net ~source ?sourcePubKey ~counter ~fee delegate =
|
||||||
operations block ~net ~source ?sourcePubKey ~counter ~fee
|
operations cctxt block ~net ~source ?sourcePubKey ~counter ~fee
|
||||||
Tezos_context.[Delegation delegate]
|
Tezos_context.[Delegation delegate]
|
||||||
>>=? fun (bytes, contracts) ->
|
>>=? fun (bytes, contracts) ->
|
||||||
assert (contracts = []) ;
|
assert (contracts = []) ;
|
||||||
return bytes
|
return bytes
|
||||||
end
|
end
|
||||||
module Delegate = struct
|
module Delegate = struct
|
||||||
let operations
|
let operations cctxt
|
||||||
block ~net ~source operations =
|
block ~net ~source operations =
|
||||||
let ops = Delegate_operations { source ; operations } in
|
let ops = Delegate_operations { source ; operations } in
|
||||||
(call_error_service1 Services.Helpers.Forge.operations block
|
(call_error_service1 cctxt Services.Helpers.Forge.operations block
|
||||||
({net_id=net}, Sourced_operations ops))
|
({net_id=net}, Sourced_operations ops))
|
||||||
>>=? fun (hash, _contracts) ->
|
>>=? fun (hash, _contracts) ->
|
||||||
return hash
|
return hash
|
||||||
let endorsement b ~net ~source ~block ~slot () =
|
let endorsement cctxt
|
||||||
operations b ~net ~source
|
b ~net ~source ~block ~slot () =
|
||||||
|
operations cctxt b ~net ~source
|
||||||
Tezos_context.[Endorsement { block ; slot }]
|
Tezos_context.[Endorsement { block ; slot }]
|
||||||
end
|
end
|
||||||
module Anonymous = struct
|
module Anonymous = struct
|
||||||
let operations block ~net operations =
|
let operations cctxt block ~net operations =
|
||||||
(call_error_service1 Services.Helpers.Forge.operations block
|
(call_error_service1 cctxt Services.Helpers.Forge.operations block
|
||||||
({net_id=net}, Anonymous_operations operations))
|
({net_id=net}, Anonymous_operations operations))
|
||||||
>>=? fun (hash, _contracts) ->
|
>>=? fun (hash, _contracts) ->
|
||||||
return hash
|
return hash
|
||||||
let seed_nonce_revelation
|
let seed_nonce_revelation cctxt
|
||||||
block ~net ~level ~nonce () =
|
block ~net ~level ~nonce () =
|
||||||
operations block ~net [Seed_nonce_revelation { level ; nonce }]
|
operations cctxt block ~net [Seed_nonce_revelation { level ; nonce }]
|
||||||
end
|
end
|
||||||
let block
|
let block cctxt
|
||||||
block ~net ~predecessor ~timestamp ~fitness ~operations
|
block ~net ~predecessor ~timestamp ~fitness ~operations
|
||||||
~level ~priority ~seed_nonce_hash ~proof_of_work_nonce () =
|
~level ~priority ~seed_nonce_hash ~proof_of_work_nonce () =
|
||||||
call_error_service1 Services.Helpers.Forge.block block
|
call_error_service1 cctxt Services.Helpers.Forge.block block
|
||||||
(net, predecessor, timestamp, fitness, operations,
|
(net, predecessor, timestamp, fitness, operations,
|
||||||
level, priority, seed_nonce_hash, proof_of_work_nonce)
|
level, priority, seed_nonce_hash, proof_of_work_nonce)
|
||||||
end
|
end
|
||||||
|
|
||||||
module Parse = struct
|
module Parse = struct
|
||||||
let operations block ?check shell bytes =
|
let operations cctxt
|
||||||
call_error_service1 Services.Helpers.Parse.operations block (shell, bytes, check)
|
block ?check shell bytes =
|
||||||
|
call_error_service1 cctxt Services.Helpers.Parse.operations block (shell, bytes, check)
|
||||||
end
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
|
@ -8,7 +8,7 @@
|
|||||||
(**************************************************************************)
|
(**************************************************************************)
|
||||||
|
|
||||||
val string_of_errors: error list -> string
|
val string_of_errors: error list -> string
|
||||||
val handle_error: 'a tzresult -> 'a Lwt.t
|
val handle_error: Client_commands.context -> 'a tzresult -> 'a Lwt.t
|
||||||
|
|
||||||
type net = State.net_id = Net of Block_hash.t
|
type net = State.net_id = Net of Block_hash.t
|
||||||
|
|
||||||
@ -20,39 +20,71 @@ type block = [
|
|||||||
]
|
]
|
||||||
|
|
||||||
module Constants : sig
|
module Constants : sig
|
||||||
val errors: block -> Json_schema.schema Lwt.t
|
val errors:
|
||||||
val bootstrap: block -> Bootstrap.account list Lwt.t
|
Client_commands.context ->
|
||||||
val cycle_length: block -> int32 tzresult Lwt.t
|
block -> Json_schema.schema Lwt.t
|
||||||
val voting_period_length: block -> int32 tzresult Lwt.t
|
val bootstrap:
|
||||||
val time_before_reward: block -> Period.t tzresult Lwt.t
|
Client_commands.context ->
|
||||||
val time_between_slots: block -> Period.t tzresult Lwt.t
|
block -> Bootstrap.account list Lwt.t
|
||||||
val first_free_mining_slot: block -> int32 tzresult Lwt.t
|
val cycle_length:
|
||||||
val max_signing_slot: block -> int tzresult Lwt.t
|
Client_commands.context ->
|
||||||
val instructions_per_transaction: block -> int tzresult Lwt.t
|
block -> int32 tzresult Lwt.t
|
||||||
val stamp_threshold: block -> int64 tzresult Lwt.t
|
val voting_period_length:
|
||||||
|
Client_commands.context ->
|
||||||
|
block -> int32 tzresult Lwt.t
|
||||||
|
val time_before_reward:
|
||||||
|
Client_commands.context ->
|
||||||
|
block -> Period.t tzresult Lwt.t
|
||||||
|
val time_between_slots:
|
||||||
|
Client_commands.context ->
|
||||||
|
block -> Period.t tzresult Lwt.t
|
||||||
|
val first_free_mining_slot:
|
||||||
|
Client_commands.context ->
|
||||||
|
block -> int32 tzresult Lwt.t
|
||||||
|
val max_signing_slot:
|
||||||
|
Client_commands.context ->
|
||||||
|
block -> int tzresult Lwt.t
|
||||||
|
val instructions_per_transaction:
|
||||||
|
Client_commands.context ->
|
||||||
|
block -> int tzresult Lwt.t
|
||||||
|
val stamp_threshold:
|
||||||
|
Client_commands.context ->
|
||||||
|
block -> int64 tzresult Lwt.t
|
||||||
end
|
end
|
||||||
|
|
||||||
module Context : sig
|
module Context : sig
|
||||||
val level: block -> Level.t tzresult Lwt.t
|
val level:
|
||||||
val next_level: block -> Level.t tzresult Lwt.t
|
Client_commands.context ->
|
||||||
|
block -> Level.t tzresult Lwt.t
|
||||||
|
val next_level:
|
||||||
|
Client_commands.context ->
|
||||||
|
block -> Level.t tzresult Lwt.t
|
||||||
module Nonce : sig
|
module Nonce : sig
|
||||||
val hash: block -> Nonce_hash.t tzresult Lwt.t
|
val hash:
|
||||||
|
Client_commands.context ->
|
||||||
|
block -> Nonce_hash.t tzresult Lwt.t
|
||||||
type nonce_info =
|
type nonce_info =
|
||||||
| Revealed of Nonce.t
|
| Revealed of Nonce.t
|
||||||
| Missing of Nonce_hash.t
|
| Missing of Nonce_hash.t
|
||||||
| Forgotten
|
| Forgotten
|
||||||
val get: block -> Raw_level.t -> nonce_info tzresult Lwt.t
|
val get:
|
||||||
|
Client_commands.context ->
|
||||||
|
block -> Raw_level.t -> nonce_info tzresult Lwt.t
|
||||||
end
|
end
|
||||||
module Key : sig
|
module Key : sig
|
||||||
val get :
|
val get :
|
||||||
|
Client_commands.context ->
|
||||||
block ->
|
block ->
|
||||||
public_key_hash -> (public_key_hash * public_key) tzresult Lwt.t
|
public_key_hash -> (public_key_hash * public_key) tzresult Lwt.t
|
||||||
val list :
|
val list :
|
||||||
|
Client_commands.context ->
|
||||||
block ->
|
block ->
|
||||||
((public_key_hash * public_key) list) tzresult Lwt.t
|
((public_key_hash * public_key) list) tzresult Lwt.t
|
||||||
end
|
end
|
||||||
module Contract : sig
|
module Contract : sig
|
||||||
val list: block -> Contract.t list tzresult Lwt.t
|
val list:
|
||||||
|
Client_commands.context ->
|
||||||
|
block -> Contract.t list tzresult Lwt.t
|
||||||
type info = {
|
type info = {
|
||||||
manager: public_key_hash ;
|
manager: public_key_hash ;
|
||||||
balance: Tez.t ;
|
balance: Tez.t ;
|
||||||
@ -62,28 +94,38 @@ module Context : sig
|
|||||||
assets: Asset.Map.t ;
|
assets: Asset.Map.t ;
|
||||||
counter: int32 ;
|
counter: int32 ;
|
||||||
}
|
}
|
||||||
val get: block -> Contract.t -> info tzresult Lwt.t
|
val get:
|
||||||
|
Client_commands.context ->
|
||||||
|
block -> Contract.t -> info tzresult Lwt.t
|
||||||
val balance:
|
val balance:
|
||||||
|
Client_commands.context ->
|
||||||
block -> Contract.t ->
|
block -> Contract.t ->
|
||||||
Tez.t tzresult Lwt.t
|
Tez.t tzresult Lwt.t
|
||||||
val manager:
|
val manager:
|
||||||
|
Client_commands.context ->
|
||||||
block -> Contract.t ->
|
block -> Contract.t ->
|
||||||
public_key_hash tzresult Lwt.t
|
public_key_hash tzresult Lwt.t
|
||||||
val delegate:
|
val delegate:
|
||||||
|
Client_commands.context ->
|
||||||
block -> Contract.t ->
|
block -> Contract.t ->
|
||||||
public_key_hash option tzresult Lwt.t
|
public_key_hash option tzresult Lwt.t
|
||||||
val counter:
|
val counter:
|
||||||
|
Client_commands.context ->
|
||||||
block -> Contract.t ->
|
block -> Contract.t ->
|
||||||
int32 tzresult Lwt.t
|
int32 tzresult Lwt.t
|
||||||
val spendable:
|
val spendable:
|
||||||
|
Client_commands.context ->
|
||||||
block -> Contract.t ->
|
block -> Contract.t ->
|
||||||
bool tzresult Lwt.t
|
bool tzresult Lwt.t
|
||||||
val delegatable:
|
val delegatable:
|
||||||
|
Client_commands.context ->
|
||||||
block -> Contract.t ->
|
block -> Contract.t ->
|
||||||
bool tzresult Lwt.t
|
bool tzresult Lwt.t
|
||||||
val script:
|
val script:
|
||||||
|
Client_commands.context ->
|
||||||
block -> Contract.t -> Script.t tzresult Lwt.t
|
block -> Contract.t -> Script.t tzresult Lwt.t
|
||||||
val assets:
|
val assets:
|
||||||
|
Client_commands.context ->
|
||||||
block -> Contract.t ->
|
block -> Contract.t ->
|
||||||
Asset.Map.t tzresult Lwt.t
|
Asset.Map.t tzresult Lwt.t
|
||||||
end
|
end
|
||||||
@ -91,29 +133,48 @@ end
|
|||||||
|
|
||||||
module Helpers : sig
|
module Helpers : sig
|
||||||
val minimal_time:
|
val minimal_time:
|
||||||
|
Client_commands.context ->
|
||||||
block -> ?prio:int -> unit -> Time.t tzresult Lwt.t
|
block -> ?prio:int -> unit -> Time.t tzresult Lwt.t
|
||||||
val run_code: block -> Script.code ->
|
val run_code:
|
||||||
|
Client_commands.context ->
|
||||||
|
block -> Script.code ->
|
||||||
(Script.expr * Script.expr) ->
|
(Script.expr * Script.expr) ->
|
||||||
(Script.expr * Script.expr) tzresult Lwt.t
|
(Script.expr * Script.expr) tzresult Lwt.t
|
||||||
val trace_code: block -> Script.code ->
|
val trace_code:
|
||||||
|
Client_commands.context ->
|
||||||
|
block -> Script.code ->
|
||||||
(Script.expr * Script.expr) ->
|
(Script.expr * Script.expr) ->
|
||||||
(Script.expr * Script.expr *
|
(Script.expr * Script.expr *
|
||||||
(Script.location * int * Script.expr list) list) tzresult Lwt.t
|
(Script.location * int * Script.expr list) list) tzresult Lwt.t
|
||||||
val typecheck_code: block -> Script.code -> Script_ir_translator.type_map tzresult Lwt.t
|
val typecheck_code:
|
||||||
val typecheck_tagged_data: block -> Script.expr -> unit tzresult Lwt.t
|
Client_commands.context ->
|
||||||
val typecheck_untagged_data: block -> Script.expr * Script.expr -> unit tzresult Lwt.t
|
block -> Script.code -> Script_ir_translator.type_map tzresult Lwt.t
|
||||||
val hash_data: block -> Script.expr -> string tzresult Lwt.t
|
val typecheck_tagged_data:
|
||||||
val level: block -> ?offset:int32 -> Raw_level.t -> Level.t tzresult Lwt.t
|
Client_commands.context ->
|
||||||
val levels: block -> Cycle.t -> Level.t list tzresult Lwt.t
|
block -> Script.expr -> unit tzresult Lwt.t
|
||||||
|
val typecheck_untagged_data:
|
||||||
|
Client_commands.context ->
|
||||||
|
block -> Script.expr * Script.expr -> unit tzresult Lwt.t
|
||||||
|
val hash_data:
|
||||||
|
Client_commands.context ->
|
||||||
|
block -> Script.expr -> string tzresult Lwt.t
|
||||||
|
val level:
|
||||||
|
Client_commands.context ->
|
||||||
|
block -> ?offset:int32 -> Raw_level.t -> Level.t tzresult Lwt.t
|
||||||
|
val levels:
|
||||||
|
Client_commands.context ->
|
||||||
|
block -> Cycle.t -> Level.t list tzresult Lwt.t
|
||||||
|
|
||||||
module Rights : sig
|
module Rights : sig
|
||||||
type slot = Raw_level.t * int * Time.t option
|
type slot = Raw_level.t * int * Time.t option
|
||||||
val mining_rights_for_delegate:
|
val mining_rights_for_delegate:
|
||||||
|
Client_commands.context ->
|
||||||
block -> public_key_hash ->
|
block -> public_key_hash ->
|
||||||
?max_priority:int -> ?first_level:Raw_level.t ->
|
?max_priority:int -> ?first_level:Raw_level.t ->
|
||||||
?last_level:Raw_level.t -> unit ->
|
?last_level:Raw_level.t -> unit ->
|
||||||
(slot list) tzresult Lwt.t
|
(slot list) tzresult Lwt.t
|
||||||
val endorsement_rights_for_delegate:
|
val endorsement_rights_for_delegate:
|
||||||
|
Client_commands.context ->
|
||||||
block -> public_key_hash ->
|
block -> public_key_hash ->
|
||||||
?max_priority:int -> ?first_level:Raw_level.t -> ?last_level:Raw_level.t -> unit ->
|
?max_priority:int -> ?first_level:Raw_level.t -> ?last_level:Raw_level.t -> unit ->
|
||||||
(slot list) tzresult Lwt.t
|
(slot list) tzresult Lwt.t
|
||||||
@ -122,6 +183,7 @@ module Helpers : sig
|
|||||||
module Forge : sig
|
module Forge : sig
|
||||||
module Manager : sig
|
module Manager : sig
|
||||||
val operations:
|
val operations:
|
||||||
|
Client_commands.context ->
|
||||||
block ->
|
block ->
|
||||||
net:net ->
|
net:net ->
|
||||||
source:Contract.t ->
|
source:Contract.t ->
|
||||||
@ -131,6 +193,7 @@ module Helpers : sig
|
|||||||
manager_operation list ->
|
manager_operation list ->
|
||||||
(MBytes.t * Contract.t list) tzresult Lwt.t
|
(MBytes.t * Contract.t list) tzresult Lwt.t
|
||||||
val transaction:
|
val transaction:
|
||||||
|
Client_commands.context ->
|
||||||
block ->
|
block ->
|
||||||
net:net ->
|
net:net ->
|
||||||
source:Contract.t ->
|
source:Contract.t ->
|
||||||
@ -142,6 +205,7 @@ module Helpers : sig
|
|||||||
fee:Tez.t ->
|
fee:Tez.t ->
|
||||||
unit -> MBytes.t tzresult Lwt.t
|
unit -> MBytes.t tzresult Lwt.t
|
||||||
val origination:
|
val origination:
|
||||||
|
Client_commands.context ->
|
||||||
block ->
|
block ->
|
||||||
net:net ->
|
net:net ->
|
||||||
source:Contract.t ->
|
source:Contract.t ->
|
||||||
@ -157,6 +221,7 @@ module Helpers : sig
|
|||||||
unit ->
|
unit ->
|
||||||
(Contract.t * MBytes.t) tzresult Lwt.t
|
(Contract.t * MBytes.t) tzresult Lwt.t
|
||||||
val issuance:
|
val issuance:
|
||||||
|
Client_commands.context ->
|
||||||
block ->
|
block ->
|
||||||
net:net ->
|
net:net ->
|
||||||
source:Contract.t ->
|
source:Contract.t ->
|
||||||
@ -167,6 +232,7 @@ module Helpers : sig
|
|||||||
fee:Tez.t ->
|
fee:Tez.t ->
|
||||||
unit -> MBytes.t tzresult Lwt.t
|
unit -> MBytes.t tzresult Lwt.t
|
||||||
val delegation:
|
val delegation:
|
||||||
|
Client_commands.context ->
|
||||||
block ->
|
block ->
|
||||||
net:net ->
|
net:net ->
|
||||||
source:Contract.t ->
|
source:Contract.t ->
|
||||||
@ -178,12 +244,14 @@ module Helpers : sig
|
|||||||
end
|
end
|
||||||
module Delegate : sig
|
module Delegate : sig
|
||||||
val operations:
|
val operations:
|
||||||
|
Client_commands.context ->
|
||||||
block ->
|
block ->
|
||||||
net:net ->
|
net:net ->
|
||||||
source:public_key ->
|
source:public_key ->
|
||||||
delegate_operation list ->
|
delegate_operation list ->
|
||||||
MBytes.t tzresult Lwt.t
|
MBytes.t tzresult Lwt.t
|
||||||
val endorsement:
|
val endorsement:
|
||||||
|
Client_commands.context ->
|
||||||
block ->
|
block ->
|
||||||
net:net ->
|
net:net ->
|
||||||
source:public_key ->
|
source:public_key ->
|
||||||
@ -193,11 +261,13 @@ module Helpers : sig
|
|||||||
end
|
end
|
||||||
module Anonymous : sig
|
module Anonymous : sig
|
||||||
val operations:
|
val operations:
|
||||||
|
Client_commands.context ->
|
||||||
block ->
|
block ->
|
||||||
net:net ->
|
net:net ->
|
||||||
anonymous_operation list ->
|
anonymous_operation list ->
|
||||||
MBytes.t tzresult Lwt.t
|
MBytes.t tzresult Lwt.t
|
||||||
val seed_nonce_revelation:
|
val seed_nonce_revelation:
|
||||||
|
Client_commands.context ->
|
||||||
block ->
|
block ->
|
||||||
net:net ->
|
net:net ->
|
||||||
level:Raw_level.t ->
|
level:Raw_level.t ->
|
||||||
@ -205,6 +275,7 @@ module Helpers : sig
|
|||||||
unit -> MBytes.t tzresult Lwt.t
|
unit -> MBytes.t tzresult Lwt.t
|
||||||
end
|
end
|
||||||
val block:
|
val block:
|
||||||
|
Client_commands.context ->
|
||||||
block ->
|
block ->
|
||||||
net:net ->
|
net:net ->
|
||||||
predecessor:Block_hash.t ->
|
predecessor:Block_hash.t ->
|
||||||
@ -220,6 +291,7 @@ module Helpers : sig
|
|||||||
|
|
||||||
module Parse : sig
|
module Parse : sig
|
||||||
val operations:
|
val operations:
|
||||||
|
Client_commands.context ->
|
||||||
block -> ?check:bool -> Updater.shell_operation -> MBytes.t ->
|
block -> ?check:bool -> Updater.shell_operation -> MBytes.t ->
|
||||||
proto_operation tzresult Lwt.t
|
proto_operation tzresult Lwt.t
|
||||||
end
|
end
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
|
|
||||||
SOURCE_DIRECTORIES += mining
|
SOURCE_DIRECTORIES += mining
|
||||||
|
|
||||||
INTFS += \
|
CLIENT_INTFS += \
|
||||||
mining/client_mining_blocks.mli \
|
mining/client_mining_blocks.mli \
|
||||||
mining/client_mining_operations.mli \
|
mining/client_mining_operations.mli \
|
||||||
mining/client_mining_endorsement.mli \
|
mining/client_mining_endorsement.mli \
|
||||||
@ -11,7 +11,7 @@ INTFS += \
|
|||||||
mining/client_mining_daemon.mli \
|
mining/client_mining_daemon.mli \
|
||||||
mining/client_mining_main.mli \
|
mining/client_mining_main.mli \
|
||||||
|
|
||||||
IMPLS += \
|
CLIENT_IMPLS += \
|
||||||
mining/client_mining_blocks.ml \
|
mining/client_mining_blocks.ml \
|
||||||
mining/client_mining_operations.ml \
|
mining/client_mining_operations.ml \
|
||||||
mining/client_mining_endorsement.ml \
|
mining/client_mining_endorsement.ml \
|
||||||
|
@ -16,25 +16,25 @@ type block_info = {
|
|||||||
level: Level.t ;
|
level: Level.t ;
|
||||||
}
|
}
|
||||||
|
|
||||||
let convert_block_info
|
let convert_block_info cctxt
|
||||||
( { hash ; predecessor ; fitness ; timestamp ; protocol }
|
( { hash ; predecessor ; fitness ; timestamp ; protocol }
|
||||||
: Client_node_rpcs.Blocks.block_info ) =
|
: Client_node_rpcs.Blocks.block_info ) =
|
||||||
Client_proto_rpcs.Context.level (`Hash hash) >>= function
|
Client_proto_rpcs.Context.level cctxt (`Hash hash) >>= function
|
||||||
| Ok level ->
|
| Ok level ->
|
||||||
Lwt.return (Some { hash ; predecessor ; fitness ; timestamp ; protocol ; level })
|
Lwt.return (Some { hash ; predecessor ; fitness ; timestamp ; protocol ; level })
|
||||||
| Error _ ->
|
| Error _ ->
|
||||||
(* TODO log error *)
|
(* TODO log error *)
|
||||||
Lwt.return_none
|
Lwt.return_none
|
||||||
|
|
||||||
let convert_block_info_err
|
let convert_block_info_err cctxt
|
||||||
( { hash ; predecessor ; fitness ; timestamp ; protocol }
|
( { hash ; predecessor ; fitness ; timestamp ; protocol }
|
||||||
: Client_node_rpcs.Blocks.block_info ) =
|
: Client_node_rpcs.Blocks.block_info ) =
|
||||||
Client_proto_rpcs.Context.level (`Hash hash) >>=? fun level ->
|
Client_proto_rpcs.Context.level cctxt (`Hash hash) >>=? fun level ->
|
||||||
return { hash ; predecessor ; fitness ; timestamp ; protocol ; level }
|
return { hash ; predecessor ; fitness ; timestamp ; protocol ; level }
|
||||||
|
|
||||||
let info ?operations block =
|
let info cctxt ?operations block =
|
||||||
Client_node_rpcs.Blocks.info ?operations block >>= fun block ->
|
Client_node_rpcs.Blocks.info cctxt ?operations block >>= fun block ->
|
||||||
convert_block_info_err block
|
convert_block_info_err cctxt block
|
||||||
|
|
||||||
let compare (bi1 : block_info) (bi2 : block_info) =
|
let compare (bi1 : block_info) (bi2 : block_info) =
|
||||||
match Fitness.compare bi1.fitness bi2.fitness with
|
match Fitness.compare bi1.fitness bi2.fitness with
|
||||||
@ -49,29 +49,29 @@ let compare (bi1 : block_info) (bi2 : block_info) =
|
|||||||
end
|
end
|
||||||
| x -> x
|
| x -> x
|
||||||
|
|
||||||
let sort_blocks ?(compare = compare) blocks =
|
let sort_blocks cctxt ?(compare = compare) blocks =
|
||||||
Lwt_list.map_p convert_block_info blocks >|= fun blocks ->
|
Lwt_list.map_p (convert_block_info cctxt) blocks >|= fun blocks ->
|
||||||
let blocks = Utils.unopt_list blocks in
|
let blocks = Utils.unopt_list blocks in
|
||||||
List.sort compare blocks
|
List.sort compare blocks
|
||||||
|
|
||||||
let monitor
|
let monitor cctxt
|
||||||
?operations ?length ?heads ?delay
|
?operations ?length ?heads ?delay
|
||||||
?min_date ?min_heads ?compare () =
|
?min_date ?min_heads ?compare () =
|
||||||
Client_node_rpcs.Blocks.monitor
|
Client_node_rpcs.Blocks.monitor cctxt
|
||||||
?operations ?length ?heads ?delay ?min_date ?min_heads
|
?operations ?length ?heads ?delay ?min_date ?min_heads
|
||||||
() >>= fun block_stream ->
|
() >>= fun block_stream ->
|
||||||
let convert blocks = sort_blocks ?compare (List.flatten blocks) in
|
let convert blocks = sort_blocks cctxt ?compare (List.flatten blocks) in
|
||||||
Lwt.return (Lwt_stream.map_s convert block_stream)
|
Lwt.return (Lwt_stream.map_s convert block_stream)
|
||||||
|
|
||||||
let blocks_from_cycle block cycle =
|
let blocks_from_cycle cctxt block cycle =
|
||||||
let block =
|
let block =
|
||||||
match block with
|
match block with
|
||||||
| `Prevalidation -> `Head 0
|
| `Prevalidation -> `Head 0
|
||||||
| `Test_prevalidation -> `Test_head 0
|
| `Test_prevalidation -> `Test_head 0
|
||||||
| _ -> block in
|
| _ -> block in
|
||||||
Client_node_rpcs.Blocks.hash block >>= fun block_hash ->
|
Client_node_rpcs.Blocks.hash cctxt block >>= fun block_hash ->
|
||||||
Client_proto_rpcs.Context.level block >>=? fun level ->
|
Client_proto_rpcs.Context.level cctxt block >>=? fun level ->
|
||||||
Client_proto_rpcs.Helpers.levels block cycle >>=? fun block_levels ->
|
Client_proto_rpcs.Helpers.levels cctxt block cycle >>=? fun block_levels ->
|
||||||
begin
|
begin
|
||||||
match List.sort Level.compare block_levels with
|
match List.sort Level.compare block_levels with
|
||||||
| [] -> failwith "Internal error"
|
| [] -> failwith "Internal error"
|
||||||
@ -79,11 +79,11 @@ let blocks_from_cycle block cycle =
|
|||||||
end >>=? fun min_level ->
|
end >>=? fun min_level ->
|
||||||
let length = 1 + Int32.to_int (Level.diff level min_level) in
|
let length = 1 + Int32.to_int (Level.diff level min_level) in
|
||||||
begin
|
begin
|
||||||
Client_node_rpcs.Blocks.list ~length ~heads:[block_hash] () >>= function
|
Client_node_rpcs.Blocks.list cctxt ~length ~heads:[block_hash] () >>= function
|
||||||
| [] | _::_::_ -> failwith "Unexpected RPC result"
|
| [] | _::_::_ -> failwith "Unexpected RPC result"
|
||||||
| [blocks] -> return blocks
|
| [blocks] -> return blocks
|
||||||
end >>=? fun block_infos ->
|
end >>=? fun block_infos ->
|
||||||
let block_infos =
|
let block_infos =
|
||||||
Utils.remove_elem_from_list (length - List.length block_levels) block_infos in
|
Utils.remove_elem_from_list (length - List.length block_levels) block_infos in
|
||||||
map_s convert_block_info_err block_infos >>=? fun block_res ->
|
map_s (convert_block_info_err cctxt) block_infos >>=? fun block_res ->
|
||||||
return block_res
|
return block_res
|
||||||
|
@ -17,17 +17,21 @@ type block_info = {
|
|||||||
}
|
}
|
||||||
|
|
||||||
val info:
|
val info:
|
||||||
|
Client_commands.context ->
|
||||||
?operations:bool -> Client_node_rpcs.Blocks.block -> block_info tzresult Lwt.t
|
?operations:bool -> Client_node_rpcs.Blocks.block -> block_info tzresult Lwt.t
|
||||||
|
|
||||||
val compare: block_info -> block_info -> int
|
val compare:
|
||||||
|
block_info -> block_info -> int
|
||||||
|
|
||||||
val monitor:
|
val monitor:
|
||||||
|
Client_commands.context ->
|
||||||
?operations:bool -> ?length:int -> ?heads:Block_hash.t list ->
|
?operations:bool -> ?length:int -> ?heads:Block_hash.t list ->
|
||||||
?delay:int -> ?min_date:Time.t -> ?min_heads:int ->
|
?delay:int -> ?min_date:Time.t -> ?min_heads:int ->
|
||||||
?compare:(block_info -> block_info -> int) ->
|
?compare:(block_info -> block_info -> int) ->
|
||||||
unit -> block_info list Lwt_stream.t Lwt.t
|
unit -> block_info list Lwt_stream.t Lwt.t
|
||||||
|
|
||||||
val blocks_from_cycle:
|
val blocks_from_cycle:
|
||||||
|
Client_commands.context ->
|
||||||
Client_node_rpcs.Blocks.block ->
|
Client_node_rpcs.Blocks.block ->
|
||||||
Cycle.t ->
|
Cycle.t ->
|
||||||
block_info list tzresult Lwt.t
|
block_info list tzresult Lwt.t
|
||||||
|
@ -9,27 +9,27 @@
|
|||||||
|
|
||||||
open Logging.Client.Mining
|
open Logging.Client.Mining
|
||||||
|
|
||||||
let run ?max_priority ~delay ?min_date delegates =
|
let run cctxt ?max_priority ~delay ?min_date delegates =
|
||||||
(* TODO really detach... *)
|
(* TODO really detach... *)
|
||||||
let endorsement =
|
let endorsement =
|
||||||
if Client_proto_args.Daemon.(!all || !endorsement) then
|
if Client_proto_args.Daemon.(!all || !endorsement) then
|
||||||
Client_mining_blocks.monitor ?min_date () >>= fun block_stream ->
|
Client_mining_blocks.monitor cctxt ?min_date () >>= fun block_stream ->
|
||||||
Client_mining_endorsement.create ~delay delegates block_stream
|
Client_mining_endorsement.create cctxt ~delay delegates block_stream
|
||||||
else
|
else
|
||||||
Lwt.return_unit
|
Lwt.return_unit
|
||||||
in
|
in
|
||||||
let denunciation =
|
let denunciation =
|
||||||
if Client_proto_args.Daemon.(!all || !denunciation) then
|
if Client_proto_args.Daemon.(!all || !denunciation) then
|
||||||
Client_mining_operations.monitor_endorsement () >>= fun endorsement_stream ->
|
Client_mining_operations.monitor_endorsement cctxt >>= fun endorsement_stream ->
|
||||||
Client_mining_denunciation.create endorsement_stream
|
Client_mining_denunciation.create cctxt endorsement_stream
|
||||||
else
|
else
|
||||||
Lwt.return_unit
|
Lwt.return_unit
|
||||||
in
|
in
|
||||||
let forge =
|
let forge =
|
||||||
Client_mining_blocks.monitor ?min_date () >>= fun block_stream ->
|
Client_mining_blocks.monitor cctxt ?min_date () >>= fun block_stream ->
|
||||||
Client_mining_operations.monitor_endorsement () >>= fun endorsement_stream ->
|
Client_mining_operations.monitor_endorsement cctxt >>= fun endorsement_stream ->
|
||||||
if Client_proto_args.Daemon.(!all || !mining) then
|
if Client_proto_args.Daemon.(!all || !mining) then
|
||||||
Client_mining_forge.create
|
Client_mining_forge.create cctxt
|
||||||
?max_priority delegates block_stream endorsement_stream
|
?max_priority delegates block_stream endorsement_stream
|
||||||
else
|
else
|
||||||
Lwt.return_unit
|
Lwt.return_unit
|
||||||
|
@ -8,6 +8,7 @@
|
|||||||
(**************************************************************************)
|
(**************************************************************************)
|
||||||
|
|
||||||
val run:
|
val run:
|
||||||
|
Client_commands.context ->
|
||||||
?max_priority: int ->
|
?max_priority: int ->
|
||||||
delay: int ->
|
delay: int ->
|
||||||
?min_date: Time.t ->
|
?min_date: Time.t ->
|
||||||
|
@ -9,7 +9,7 @@
|
|||||||
|
|
||||||
open Logging.Client.Denunciation
|
open Logging.Client.Denunciation
|
||||||
|
|
||||||
let create endorsement_stream =
|
let create cctxt endorsement_stream =
|
||||||
let last_get_endorsement = ref None in
|
let last_get_endorsement = ref None in
|
||||||
let get_endorsement () =
|
let get_endorsement () =
|
||||||
match !last_get_endorsement with
|
match !last_get_endorsement with
|
||||||
@ -28,7 +28,7 @@ let create endorsement_stream =
|
|||||||
Lwt.return_unit
|
Lwt.return_unit
|
||||||
| `Endorsement (Some e) ->
|
| `Endorsement (Some e) ->
|
||||||
last_get_endorsement := None ;
|
last_get_endorsement := None ;
|
||||||
Client_keys.Public_key_hash.name
|
Client_keys.Public_key_hash.name cctxt
|
||||||
e.Client_mining_operations.source >>= fun source ->
|
e.Client_mining_operations.source >>= fun source ->
|
||||||
lwt_debug
|
lwt_debug
|
||||||
"Discovered endorsement for block %a by %s (slot @[<h>%a@])"
|
"Discovered endorsement for block %a by %s (slot @[<h>%a@])"
|
||||||
|
@ -8,5 +8,6 @@
|
|||||||
(**************************************************************************)
|
(**************************************************************************)
|
||||||
|
|
||||||
val create:
|
val create:
|
||||||
|
Client_commands.context ->
|
||||||
Client_mining_operations.valid_endorsement Lwt_stream.t ->
|
Client_mining_operations.valid_endorsement Lwt_stream.t ->
|
||||||
unit Lwt.t
|
unit Lwt.t
|
||||||
|
@ -15,11 +15,13 @@ module Ed25519 = Environment.Ed25519
|
|||||||
module State : sig
|
module State : sig
|
||||||
|
|
||||||
val get_endorsement:
|
val get_endorsement:
|
||||||
|
Client_commands.context ->
|
||||||
Raw_level.t ->
|
Raw_level.t ->
|
||||||
int ->
|
int ->
|
||||||
(Block_hash.t * Operation_hash.t) option tzresult Lwt.t
|
(Block_hash.t * Operation_hash.t) option tzresult Lwt.t
|
||||||
|
|
||||||
val record_endorsement:
|
val record_endorsement:
|
||||||
|
Client_commands.context ->
|
||||||
Raw_level.t ->
|
Raw_level.t ->
|
||||||
Block_hash.t ->
|
Block_hash.t ->
|
||||||
int -> Operation_hash.t -> unit tzresult Lwt.t
|
int -> Operation_hash.t -> unit tzresult Lwt.t
|
||||||
@ -45,20 +47,20 @@ end = struct
|
|||||||
let filename () =
|
let filename () =
|
||||||
Client_config.(base_dir#get // "endorsements")
|
Client_config.(base_dir#get // "endorsements")
|
||||||
|
|
||||||
let load () =
|
let load cctxt =
|
||||||
let filename = filename () in
|
let filename = filename () in
|
||||||
if not (Sys.file_exists filename) then return LevelMap.empty else
|
if not (Sys.file_exists filename) then return LevelMap.empty else
|
||||||
Data_encoding_ezjsonm.read_file filename >>= function
|
Data_encoding_ezjsonm.read_file filename >>= function
|
||||||
| None ->
|
| None ->
|
||||||
error "couldn't to read the endorsement file"
|
cctxt.Client_commands.error "couldn't to read the endorsement file"
|
||||||
| Some json ->
|
| Some json ->
|
||||||
match Data_encoding.Json.destruct encoding json with
|
match Data_encoding.Json.destruct encoding json with
|
||||||
| exception _ -> (* TODO print_error *)
|
| exception _ -> (* TODO print_error *)
|
||||||
error "didn't understand the endorsement file"
|
cctxt.Client_commands.error "didn't understand the endorsement file"
|
||||||
| map ->
|
| map ->
|
||||||
return map
|
return map
|
||||||
|
|
||||||
let save map =
|
let save cctxt map =
|
||||||
Lwt.catch
|
Lwt.catch
|
||||||
(fun () ->
|
(fun () ->
|
||||||
let dirname = Client_config.base_dir#get in
|
let dirname = Client_config.base_dir#get in
|
||||||
@ -70,15 +72,15 @@ end = struct
|
|||||||
| false -> failwith "Json.write_file"
|
| false -> failwith "Json.write_file"
|
||||||
| true -> return ())
|
| true -> return ())
|
||||||
(fun exn ->
|
(fun exn ->
|
||||||
error "could not write the endorsement file: %s."
|
cctxt.Client_commands.error "could not write the endorsement file: %s."
|
||||||
(Printexc.to_string exn))
|
(Printexc.to_string exn))
|
||||||
|
|
||||||
let lock = Lwt_mutex.create ()
|
let lock = Lwt_mutex.create ()
|
||||||
|
|
||||||
let get_endorsement level slot =
|
let get_endorsement cctxt level slot =
|
||||||
Lwt_mutex.with_lock lock
|
Lwt_mutex.with_lock lock
|
||||||
(fun () ->
|
(fun () ->
|
||||||
load () >>=? fun map ->
|
load cctxt >>=? fun map ->
|
||||||
try
|
try
|
||||||
let _, block, op =
|
let _, block, op =
|
||||||
LevelMap.find level map
|
LevelMap.find level map
|
||||||
@ -86,27 +88,27 @@ end = struct
|
|||||||
return (Some (block, op))
|
return (Some (block, op))
|
||||||
with Not_found -> return None)
|
with Not_found -> return None)
|
||||||
|
|
||||||
let record_endorsement level hash slot oph =
|
let record_endorsement cctxt level hash slot oph =
|
||||||
Lwt_mutex.with_lock lock
|
Lwt_mutex.with_lock lock
|
||||||
(fun () ->
|
(fun () ->
|
||||||
load () >>=? fun map ->
|
load cctxt >>=? fun map ->
|
||||||
let previous =
|
let previous =
|
||||||
try LevelMap.find level map
|
try LevelMap.find level map
|
||||||
with Not_found -> [] in
|
with Not_found -> [] in
|
||||||
save
|
save cctxt
|
||||||
(LevelMap.add level ((slot, hash, oph) :: previous) map))
|
(LevelMap.add level ((slot, hash, oph) :: previous) map))
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
let get_block_hash = function
|
let get_block_hash cctxt = function
|
||||||
| `Hash hash -> Lwt.return hash
|
| `Hash hash -> Lwt.return hash
|
||||||
| `Genesis | `Head _ | `Test_head _ as block ->
|
| `Genesis | `Head _ | `Test_head _ as block ->
|
||||||
Client_node_rpcs.Blocks.hash block
|
Client_node_rpcs.Blocks.hash cctxt block
|
||||||
| `Prevalidation -> Client_node_rpcs.Blocks.hash (`Head 0)
|
| `Prevalidation -> Client_node_rpcs.Blocks.hash cctxt (`Head 0)
|
||||||
| `Test_prevalidation -> Client_node_rpcs.Blocks.hash (`Test_head 0)
|
| `Test_prevalidation -> Client_node_rpcs.Blocks.hash cctxt (`Test_head 0)
|
||||||
|
|
||||||
let get_signing_slots ?max_priority block delegate level =
|
let get_signing_slots cctxt ?max_priority block delegate level =
|
||||||
Client_proto_rpcs.Helpers.Rights.endorsement_rights_for_delegate
|
Client_proto_rpcs.Helpers.Rights.endorsement_rights_for_delegate cctxt
|
||||||
?max_priority ~first_level:level ~last_level:level
|
?max_priority ~first_level:level ~last_level:level
|
||||||
block delegate () >>=? fun possibilities ->
|
block delegate () >>=? fun possibilities ->
|
||||||
let slots =
|
let slots =
|
||||||
@ -114,12 +116,12 @@ let get_signing_slots ?max_priority block delegate level =
|
|||||||
@@ List.filter (fun (l, _, _) -> l = level) possibilities in
|
@@ List.filter (fun (l, _, _) -> l = level) possibilities in
|
||||||
return slots
|
return slots
|
||||||
|
|
||||||
let inject_endorsement
|
let inject_endorsement cctxt
|
||||||
block level ?wait ?force
|
block level ?wait ?force
|
||||||
src_sk source slot =
|
src_sk source slot =
|
||||||
get_block_hash block >>= fun block_hash ->
|
get_block_hash cctxt block >>= fun block_hash ->
|
||||||
Client_node_rpcs.Blocks.net block >>= fun net ->
|
Client_node_rpcs.Blocks.net cctxt block >>= fun net ->
|
||||||
Client_proto_rpcs.Helpers.Forge.Delegate.endorsement
|
Client_proto_rpcs.Helpers.Forge.Delegate.endorsement cctxt
|
||||||
block
|
block
|
||||||
~net
|
~net
|
||||||
~source
|
~source
|
||||||
@ -127,41 +129,41 @@ let inject_endorsement
|
|||||||
~slot:slot
|
~slot:slot
|
||||||
() >>=? fun bytes ->
|
() >>=? fun bytes ->
|
||||||
let signed_bytes = Ed25519.append_signature src_sk bytes in
|
let signed_bytes = Ed25519.append_signature src_sk bytes in
|
||||||
Client_node_rpcs.inject_operation ?force ?wait signed_bytes >>=? fun oph ->
|
Client_node_rpcs.inject_operation cctxt ?force ?wait signed_bytes >>=? fun oph ->
|
||||||
State.record_endorsement level block_hash slot oph >>=? fun () ->
|
State.record_endorsement cctxt level block_hash slot oph >>=? fun () ->
|
||||||
return oph
|
return oph
|
||||||
|
|
||||||
|
|
||||||
let previously_endorsed_slot level slot =
|
let previously_endorsed_slot cctxt level slot =
|
||||||
State.get_endorsement level slot >>=? function
|
State.get_endorsement cctxt level slot >>=? function
|
||||||
| None -> return false
|
| None -> return false
|
||||||
| Some _ -> return true
|
| Some _ -> return true
|
||||||
|
|
||||||
let check_endorsement level slot =
|
let check_endorsement cctxt level slot =
|
||||||
State.get_endorsement level slot >>=? function
|
State.get_endorsement cctxt level slot >>=? function
|
||||||
| None -> return ()
|
| None -> return ()
|
||||||
| Some (block, _) ->
|
| Some (block, _) ->
|
||||||
failwith
|
Error_monad.failwith
|
||||||
"Already signed block %a at level %a, slot %d"
|
"Already signed block %a at level %a, slot %d"
|
||||||
Block_hash.pp_short block Raw_level.pp level slot
|
Block_hash.pp_short block Raw_level.pp level slot
|
||||||
|
|
||||||
|
|
||||||
let forge_endorsement
|
let forge_endorsement cctxt
|
||||||
block ?(force = false)
|
block ?(force = false)
|
||||||
~src_sk ?slot ?max_priority src_pk =
|
~src_sk ?slot ?max_priority src_pk =
|
||||||
let src_pkh = Ed25519.hash src_pk in
|
let src_pkh = Ed25519.hash src_pk in
|
||||||
Client_proto_rpcs.Context.next_level block >>=? fun level ->
|
Client_proto_rpcs.Context.next_level cctxt block >>=? fun level ->
|
||||||
let level = Raw_level.succ @@ level.level in
|
let level = Raw_level.succ @@ level.level in
|
||||||
begin
|
begin
|
||||||
match slot with
|
match slot with
|
||||||
| Some slot -> return slot
|
| Some slot -> return slot
|
||||||
| None ->
|
| None ->
|
||||||
get_signing_slots ?max_priority block src_pkh level >>=? function
|
get_signing_slots cctxt ?max_priority block src_pkh level >>=? function
|
||||||
| slot::_ -> return slot
|
| slot::_ -> return slot
|
||||||
| [] -> error "No slot found at level %a" Raw_level.pp level
|
| [] -> cctxt.error "No slot found at level %a" Raw_level.pp level
|
||||||
end >>=? fun slot ->
|
end >>=? fun slot ->
|
||||||
(if force then return () else check_endorsement level slot) >>=? fun () ->
|
(if force then return () else check_endorsement cctxt level slot) >>=? fun () ->
|
||||||
inject_endorsement
|
inject_endorsement cctxt
|
||||||
block level ~wait:true ~force
|
block level ~wait:true ~force
|
||||||
src_sk src_pk slot
|
src_sk src_pk slot
|
||||||
|
|
||||||
@ -194,19 +196,19 @@ let rec insert ({time} as e) = function
|
|||||||
e :: l
|
e :: l
|
||||||
| e' :: l -> e' :: insert e l
|
| e' :: l -> e' :: insert e l
|
||||||
|
|
||||||
let schedule_endorsements state bis =
|
let schedule_endorsements cctxt state bis =
|
||||||
let may_endorse (block: Client_mining_blocks.block_info) delegate time =
|
let may_endorse (block: Client_mining_blocks.block_info) delegate time =
|
||||||
Client_keys.Public_key_hash.name delegate >>= fun name ->
|
Client_keys.Public_key_hash.name cctxt delegate >>= fun name ->
|
||||||
lwt_log_info "May endorse block %a for %s"
|
lwt_log_info "May endorse block %a for %s"
|
||||||
Block_hash.pp_short block.hash name >>= fun () ->
|
Block_hash.pp_short block.hash name >>= fun () ->
|
||||||
let b = `Hash block.hash in
|
let b = `Hash block.hash in
|
||||||
let level = Raw_level.succ block.level.level in
|
let level = Raw_level.succ block.level.level in
|
||||||
get_signing_slots b delegate level >>=? fun slots ->
|
get_signing_slots cctxt b delegate level >>=? fun slots ->
|
||||||
lwt_debug "Found slots for %a/%s (%d)"
|
lwt_debug "Found slots for %a/%s (%d)"
|
||||||
Block_hash.pp_short block.hash name (List.length slots) >>= fun () ->
|
Block_hash.pp_short block.hash name (List.length slots) >>= fun () ->
|
||||||
iter_p
|
iter_p
|
||||||
(fun slot ->
|
(fun slot ->
|
||||||
previously_endorsed_slot level slot >>=? function
|
previously_endorsed_slot cctxt level slot >>=? function
|
||||||
| true ->
|
| true ->
|
||||||
lwt_debug "slot %d: previously endorsed." slot >>= fun () ->
|
lwt_debug "slot %d: previously endorsed." slot >>= fun () ->
|
||||||
return ()
|
return ()
|
||||||
@ -270,23 +272,23 @@ let pop_endorsements state =
|
|||||||
state.to_endorse <- future_endorsement ;
|
state.to_endorse <- future_endorsement ;
|
||||||
to_endorse
|
to_endorse
|
||||||
|
|
||||||
let endorse state =
|
let endorse cctxt state =
|
||||||
let to_endorse = pop_endorsements state in
|
let to_endorse = pop_endorsements state in
|
||||||
iter_p
|
iter_p
|
||||||
(fun {delegate;block;slot} ->
|
(fun {delegate;block;slot} ->
|
||||||
let hash = block.hash in
|
let hash = block.hash in
|
||||||
let b = `Hash hash in
|
let b = `Hash hash in
|
||||||
let level = Raw_level.succ block.level.level in
|
let level = Raw_level.succ block.level.level in
|
||||||
previously_endorsed_slot level slot >>=? function
|
previously_endorsed_slot cctxt level slot >>=? function
|
||||||
| true -> return ()
|
| true -> return ()
|
||||||
| false ->
|
| false ->
|
||||||
Client_keys.get_key delegate >>=? fun (name, pk, sk) ->
|
Client_keys.get_key cctxt delegate >>=? fun (name, pk, sk) ->
|
||||||
lwt_debug "Endorsing %a for %s (slot %d)!"
|
lwt_debug "Endorsing %a for %s (slot %d)!"
|
||||||
Block_hash.pp_short hash name slot >>= fun () ->
|
Block_hash.pp_short hash name slot >>= fun () ->
|
||||||
inject_endorsement
|
inject_endorsement cctxt
|
||||||
b level ~wait:false ~force:true
|
b level ~wait:false ~force:true
|
||||||
sk pk slot >>=? fun oph ->
|
sk pk slot >>=? fun oph ->
|
||||||
message
|
cctxt.message
|
||||||
"Injected endorsement for block '%a' \
|
"Injected endorsement for block '%a' \
|
||||||
\ (level %a, slot %d, contract %s) '%a'"
|
\ (level %a, slot %d, contract %s) '%a'"
|
||||||
Block_hash.pp_short hash
|
Block_hash.pp_short hash
|
||||||
@ -306,11 +308,11 @@ let compute_timeout state =
|
|||||||
else
|
else
|
||||||
Lwt_unix.sleep (Int64.to_float delay)
|
Lwt_unix.sleep (Int64.to_float delay)
|
||||||
|
|
||||||
let create ~delay contracts block_stream =
|
let create cctxt ~delay contracts block_stream =
|
||||||
lwt_log_info "Starting endorsement daemon" >>= fun () ->
|
lwt_log_info "Starting endorsement daemon" >>= fun () ->
|
||||||
Lwt_stream.get block_stream >>= function
|
Lwt_stream.get block_stream >>= function
|
||||||
| None | Some [] ->
|
| None | Some [] ->
|
||||||
error "Can't fetch the current block head."
|
cctxt.Client_commands.error "Can't fetch the current block head."
|
||||||
| Some ({ Client_mining_blocks.fitness } :: _ as initial_heads) ->
|
| Some ({ Client_mining_blocks.fitness } :: _ as initial_heads) ->
|
||||||
let last_get_block = ref None in
|
let last_get_block = ref None in
|
||||||
let get_block () =
|
let get_block () =
|
||||||
@ -330,11 +332,11 @@ let create ~delay contracts block_stream =
|
|||||||
| `Hash (Some bis) ->
|
| `Hash (Some bis) ->
|
||||||
Lwt.cancel timeout ;
|
Lwt.cancel timeout ;
|
||||||
last_get_block := None ;
|
last_get_block := None ;
|
||||||
schedule_endorsements state bis >>= fun () ->
|
schedule_endorsements cctxt state bis >>= fun () ->
|
||||||
worker_loop ()
|
worker_loop ()
|
||||||
| `Timeout ->
|
| `Timeout ->
|
||||||
begin
|
begin
|
||||||
endorse state >>= function
|
endorse cctxt state >>= function
|
||||||
| Ok () -> Lwt.return_unit
|
| Ok () -> Lwt.return_unit
|
||||||
| Error errs ->
|
| Error errs ->
|
||||||
lwt_log_error "Error while endorsing:\n%a"
|
lwt_log_error "Error while endorsing:\n%a"
|
||||||
@ -343,5 +345,5 @@ let create ~delay contracts block_stream =
|
|||||||
Lwt.return_unit
|
Lwt.return_unit
|
||||||
end >>= fun () ->
|
end >>= fun () ->
|
||||||
worker_loop () in
|
worker_loop () in
|
||||||
schedule_endorsements state initial_heads >>= fun () ->
|
schedule_endorsements cctxt state initial_heads >>= fun () ->
|
||||||
worker_loop ()
|
worker_loop ()
|
||||||
|
@ -8,6 +8,7 @@
|
|||||||
(**************************************************************************)
|
(**************************************************************************)
|
||||||
|
|
||||||
val forge_endorsement:
|
val forge_endorsement:
|
||||||
|
Client_commands.context ->
|
||||||
Client_proto_rpcs.block ->
|
Client_proto_rpcs.block ->
|
||||||
?force:bool ->
|
?force:bool ->
|
||||||
src_sk:secret_key ->
|
src_sk:secret_key ->
|
||||||
@ -17,6 +18,7 @@ val forge_endorsement:
|
|||||||
Operation_hash.t tzresult Lwt.t
|
Operation_hash.t tzresult Lwt.t
|
||||||
|
|
||||||
val create:
|
val create:
|
||||||
|
Client_commands.context ->
|
||||||
delay: int ->
|
delay: int ->
|
||||||
public_key_hash list ->
|
public_key_hash list ->
|
||||||
Client_mining_blocks.block_info list Lwt_stream.t ->
|
Client_mining_blocks.block_info list Lwt_stream.t ->
|
||||||
|
@ -19,8 +19,8 @@ let generate_seed_nonce () =
|
|||||||
| Error _ -> assert false
|
| Error _ -> assert false
|
||||||
| Ok nonce -> nonce
|
| Ok nonce -> nonce
|
||||||
|
|
||||||
let rec compute_stamp block delegate_sk shell mining_slot seed_nonce_hash =
|
let rec compute_stamp cctxt block delegate_sk shell mining_slot seed_nonce_hash =
|
||||||
Client_proto_rpcs.Constants.stamp_threshold block >>=? fun stamp_threshold ->
|
Client_proto_rpcs.Constants.stamp_threshold cctxt block >>=? fun stamp_threshold ->
|
||||||
let rec loop () =
|
let rec loop () =
|
||||||
let proof_of_work_nonce = generate_proof_of_work_nonce () in
|
let proof_of_work_nonce = generate_proof_of_work_nonce () in
|
||||||
let unsigned_header =
|
let unsigned_header =
|
||||||
@ -35,21 +35,21 @@ let rec compute_stamp block delegate_sk shell mining_slot seed_nonce_hash =
|
|||||||
loop () in
|
loop () in
|
||||||
return (loop ())
|
return (loop ())
|
||||||
|
|
||||||
let inject_block block
|
let inject_block cctxt block
|
||||||
?force
|
?force
|
||||||
~priority ~timestamp ~fitness ~seed_nonce
|
~priority ~timestamp ~fitness ~seed_nonce
|
||||||
~src_sk operations =
|
~src_sk operations =
|
||||||
let block = match block with `Prevalidation -> `Head 0 | block -> block in
|
let block = match block with `Prevalidation -> `Head 0 | block -> block in
|
||||||
Client_node_rpcs.Blocks.info block >>= fun bi ->
|
Client_node_rpcs.Blocks.info cctxt block >>= fun bi ->
|
||||||
let seed_nonce_hash = Nonce.hash seed_nonce in
|
let seed_nonce_hash = Nonce.hash seed_nonce in
|
||||||
Client_proto_rpcs.Context.next_level block >>=? fun level ->
|
Client_proto_rpcs.Context.next_level cctxt block >>=? fun level ->
|
||||||
let shell =
|
let shell =
|
||||||
{ Store.net_id = bi.net ; predecessor = bi.hash ;
|
{ Store.net_id = bi.net ; predecessor = bi.hash ;
|
||||||
timestamp ; fitness ; operations } in
|
timestamp ; fitness ; operations } in
|
||||||
let slot = level.level, Int32.of_int priority in
|
let slot = level.level, Int32.of_int priority in
|
||||||
compute_stamp block
|
compute_stamp cctxt block
|
||||||
src_sk shell slot seed_nonce_hash >>=? fun proof_of_work_nonce ->
|
src_sk shell slot seed_nonce_hash >>=? fun proof_of_work_nonce ->
|
||||||
Client_proto_rpcs.Helpers.Forge.block
|
Client_proto_rpcs.Helpers.Forge.block cctxt
|
||||||
block
|
block
|
||||||
~net:bi.net
|
~net:bi.net
|
||||||
~predecessor:bi.hash
|
~predecessor:bi.hash
|
||||||
@ -62,11 +62,11 @@ let inject_block block
|
|||||||
~proof_of_work_nonce
|
~proof_of_work_nonce
|
||||||
() >>=? fun unsigned_header ->
|
() >>=? fun unsigned_header ->
|
||||||
let signed_header = Ed25519.append_signature src_sk unsigned_header in
|
let signed_header = Ed25519.append_signature src_sk unsigned_header in
|
||||||
Client_node_rpcs.inject_block
|
Client_node_rpcs.inject_block cctxt
|
||||||
~wait:true ?force signed_header >>=? fun block_hash ->
|
~wait:true ?force signed_header >>=? fun block_hash ->
|
||||||
return block_hash
|
return block_hash
|
||||||
|
|
||||||
let forge_block block
|
let forge_block cctxt block
|
||||||
?force
|
?force
|
||||||
?operations ?(best_effort = operations = None) ?(sort = best_effort)
|
?operations ?(best_effort = operations = None) ?(sort = best_effort)
|
||||||
?timestamp ?max_priority ?priority
|
?timestamp ?max_priority ?priority
|
||||||
@ -76,12 +76,12 @@ let forge_block block
|
|||||||
| `Prevalidation -> `Head 0
|
| `Prevalidation -> `Head 0
|
||||||
| `Test_prevalidation -> `Test_head 0
|
| `Test_prevalidation -> `Test_head 0
|
||||||
| block -> block in
|
| block -> block in
|
||||||
Client_proto_rpcs.Context.level block >>=? fun level ->
|
Client_proto_rpcs.Context.level cctxt block >>=? fun level ->
|
||||||
let level = Raw_level.succ level.level in
|
let level = Raw_level.succ level.level in
|
||||||
begin
|
begin
|
||||||
match operations with
|
match operations with
|
||||||
| None ->
|
| None ->
|
||||||
Client_node_rpcs.Blocks.pending_operations block >|= fun (ops, pendings) ->
|
Client_node_rpcs.Blocks.pending_operations cctxt block >|= fun (ops, pendings) ->
|
||||||
Operation_hash_set.elements @@
|
Operation_hash_set.elements @@
|
||||||
Operation_hash_set.union (Updater.operations ops) pendings
|
Operation_hash_set.union (Updater.operations ops) pendings
|
||||||
| Some operations -> Lwt.return operations
|
| Some operations -> Lwt.return operations
|
||||||
@ -89,11 +89,11 @@ let forge_block block
|
|||||||
begin
|
begin
|
||||||
match priority with
|
match priority with
|
||||||
| Some prio -> begin
|
| Some prio -> begin
|
||||||
Client_proto_rpcs.Helpers.minimal_time block ~prio () >>=? fun time ->
|
Client_proto_rpcs.Helpers.minimal_time cctxt block ~prio () >>=? fun time ->
|
||||||
return (prio, Some time)
|
return (prio, Some time)
|
||||||
end
|
end
|
||||||
| None ->
|
| None ->
|
||||||
Client_proto_rpcs.Helpers.Rights.mining_rights_for_delegate
|
Client_proto_rpcs.Helpers.Rights.mining_rights_for_delegate cctxt
|
||||||
?max_priority
|
?max_priority
|
||||||
~first_level:level
|
~first_level:level
|
||||||
~last_level:level
|
~last_level:level
|
||||||
@ -103,7 +103,7 @@ let forge_block block
|
|||||||
List.find (fun (l,_,_) -> l = level) possibilities in
|
List.find (fun (l,_,_) -> l = level) possibilities in
|
||||||
return (prio, time)
|
return (prio, time)
|
||||||
with Not_found ->
|
with Not_found ->
|
||||||
failwith "No slot found at level %a" Raw_level.pp level
|
Error_monad.failwith "No slot found at level %a" Raw_level.pp level
|
||||||
end >>=? fun (priority, minimal_timestamp) ->
|
end >>=? fun (priority, minimal_timestamp) ->
|
||||||
lwt_log_info "Mining block at level %a prio %d"
|
lwt_log_info "Mining block at level %a prio %d"
|
||||||
Raw_level.pp level priority >>= fun () ->
|
Raw_level.pp level priority >>= fun () ->
|
||||||
@ -113,7 +113,7 @@ let forge_block block
|
|||||||
| None, timestamp | timestamp, None -> return timestamp
|
| None, timestamp | timestamp, None -> return timestamp
|
||||||
| Some timestamp, Some minimal_timestamp ->
|
| Some timestamp, Some minimal_timestamp ->
|
||||||
if timestamp < minimal_timestamp then
|
if timestamp < minimal_timestamp then
|
||||||
failwith
|
Error_monad.failwith
|
||||||
"Proposed timestamp %a is earlier than minimal timestamp %a"
|
"Proposed timestamp %a is earlier than minimal timestamp %a"
|
||||||
Time.pp_hum timestamp
|
Time.pp_hum timestamp
|
||||||
Time.pp_hum minimal_timestamp
|
Time.pp_hum minimal_timestamp
|
||||||
@ -121,7 +121,7 @@ let forge_block block
|
|||||||
return (Some timestamp)
|
return (Some timestamp)
|
||||||
end >>=? fun timestamp ->
|
end >>=? fun timestamp ->
|
||||||
let request = List.length operations in
|
let request = List.length operations in
|
||||||
Client_node_rpcs.Blocks.preapply block ?timestamp ~sort operations >>=?
|
Client_node_rpcs.Blocks.preapply cctxt block ?timestamp ~sort operations >>=?
|
||||||
fun { operations ; fitness ; timestamp } ->
|
fun { operations ; fitness ; timestamp } ->
|
||||||
let valid = List.length operations.applied in
|
let valid = List.length operations.applied in
|
||||||
lwt_log_info "Found %d valid operations (%d refused) for timestamp %a"
|
lwt_log_info "Found %d valid operations (%d refused) for timestamp %a"
|
||||||
@ -132,7 +132,7 @@ let forge_block block
|
|||||||
|| ( Operation_hash_map.is_empty operations.refused
|
|| ( Operation_hash_map.is_empty operations.refused
|
||||||
&& Operation_hash_map.is_empty operations.branch_refused
|
&& Operation_hash_map.is_empty operations.branch_refused
|
||||||
&& Operation_hash_map.is_empty operations.branch_delayed ) then
|
&& Operation_hash_map.is_empty operations.branch_delayed ) then
|
||||||
inject_block ?force ~src_sk
|
inject_block cctxt ?force ~src_sk
|
||||||
~priority ~timestamp ~fitness ~seed_nonce block operations.applied
|
~priority ~timestamp ~fitness ~seed_nonce block operations.applied
|
||||||
else
|
else
|
||||||
failwith "Cannot (fully) validate the given operations."
|
failwith "Cannot (fully) validate the given operations."
|
||||||
@ -143,9 +143,11 @@ let forge_block block
|
|||||||
module State : sig
|
module State : sig
|
||||||
|
|
||||||
val get_block:
|
val get_block:
|
||||||
|
Client_commands.context ->
|
||||||
Raw_level.t -> Block_hash.t list tzresult Lwt.t
|
Raw_level.t -> Block_hash.t list tzresult Lwt.t
|
||||||
|
|
||||||
val record_block:
|
val record_block:
|
||||||
|
Client_commands.context ->
|
||||||
Raw_level.t -> Block_hash.t -> Nonce.t -> unit tzresult Lwt.t
|
Raw_level.t -> Block_hash.t -> Nonce.t -> unit tzresult Lwt.t
|
||||||
|
|
||||||
end = struct
|
end = struct
|
||||||
@ -190,13 +192,13 @@ end = struct
|
|||||||
| false -> failwith "Json.write_file"
|
| false -> failwith "Json.write_file"
|
||||||
| true -> return ())
|
| true -> return ())
|
||||||
(fun exn ->
|
(fun exn ->
|
||||||
failwith
|
Error_monad.failwith
|
||||||
"could not write the block file: %s."
|
"could not write the block file: %s."
|
||||||
(Printexc.to_string exn))
|
(Printexc.to_string exn))
|
||||||
|
|
||||||
let lock = Lwt_mutex.create ()
|
let lock = Lwt_mutex.create ()
|
||||||
|
|
||||||
let get_block level =
|
let get_block cctxt level =
|
||||||
Lwt_mutex.with_lock lock
|
Lwt_mutex.with_lock lock
|
||||||
(fun () ->
|
(fun () ->
|
||||||
load () >>=? fun map ->
|
load () >>=? fun map ->
|
||||||
@ -205,7 +207,7 @@ end = struct
|
|||||||
return blocks
|
return blocks
|
||||||
with Not_found -> return [])
|
with Not_found -> return [])
|
||||||
|
|
||||||
let record_block level hash nonce =
|
let record_block cctxt level hash nonce =
|
||||||
Lwt_mutex.with_lock lock
|
Lwt_mutex.with_lock lock
|
||||||
(fun () ->
|
(fun () ->
|
||||||
load () >>=? fun map ->
|
load () >>=? fun map ->
|
||||||
@ -214,17 +216,17 @@ end = struct
|
|||||||
with Not_found -> [] in
|
with Not_found -> [] in
|
||||||
save
|
save
|
||||||
(LevelMap.add level (hash :: previous) map)) >>=? fun () ->
|
(LevelMap.add level (hash :: previous) map)) >>=? fun () ->
|
||||||
Client_proto_nonces.add hash nonce
|
Client_proto_nonces.add cctxt hash nonce
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
let get_mining_slot
|
let get_mining_slot cctxt
|
||||||
?max_priority (bi: Client_mining_blocks.block_info) delegates =
|
?max_priority (bi: Client_mining_blocks.block_info) delegates =
|
||||||
let block = `Hash bi.hash in
|
let block = `Hash bi.hash in
|
||||||
let level = Raw_level.succ bi.level.level in
|
let level = Raw_level.succ bi.level.level in
|
||||||
Lwt_list.filter_map_p
|
Lwt_list.filter_map_p
|
||||||
(fun delegate ->
|
(fun delegate ->
|
||||||
Client_proto_rpcs.Helpers.Rights.mining_rights_for_delegate
|
Client_proto_rpcs.Helpers.Rights.mining_rights_for_delegate cctxt
|
||||||
?max_priority
|
?max_priority
|
||||||
~first_level:level
|
~first_level:level
|
||||||
~last_level:level
|
~last_level:level
|
||||||
@ -278,16 +280,16 @@ let compute_timeout { future_slots } =
|
|||||||
else
|
else
|
||||||
Lwt_unix.sleep (Int64.to_float delay)
|
Lwt_unix.sleep (Int64.to_float delay)
|
||||||
|
|
||||||
let insert_block ?max_priority state (bi: Client_mining_blocks.block_info) =
|
let insert_block cctxt ?max_priority state (bi: Client_mining_blocks.block_info) =
|
||||||
if Fitness.compare state.best_fitness bi.fitness < 0 then
|
if Fitness.compare state.best_fitness bi.fitness < 0 then
|
||||||
state.best_fitness <- bi.fitness ;
|
state.best_fitness <- bi.fitness ;
|
||||||
get_mining_slot ?max_priority bi state.delegates >>= function
|
get_mining_slot cctxt ?max_priority bi state.delegates >>= function
|
||||||
| None ->
|
| None ->
|
||||||
lwt_debug
|
lwt_debug
|
||||||
"Can't compute slot for %a" Block_hash.pp_short bi.hash >>= fun () ->
|
"Can't compute slot for %a" Block_hash.pp_short bi.hash >>= fun () ->
|
||||||
Lwt.return_unit
|
Lwt.return_unit
|
||||||
| Some ((timestamp, (_,_,delegate)) as slot) ->
|
| Some ((timestamp, (_,_,delegate)) as slot) ->
|
||||||
Client_keys.Public_key_hash.name delegate >>= fun name ->
|
Client_keys.Public_key_hash.name cctxt delegate >>= fun name ->
|
||||||
lwt_log_info "New mining slot at %a for %s after %a"
|
lwt_log_info "New mining slot at %a for %s after %a"
|
||||||
Time.pp_hum timestamp
|
Time.pp_hum timestamp
|
||||||
name
|
name
|
||||||
@ -306,10 +308,10 @@ let pop_mining_slots state =
|
|||||||
state.future_slots <- future_slots ;
|
state.future_slots <- future_slots ;
|
||||||
slots
|
slots
|
||||||
|
|
||||||
let insert_blocks ?max_priority state bis =
|
let insert_blocks cctxt ?max_priority state bis =
|
||||||
Lwt_list.iter_s (insert_block ?max_priority state) bis
|
Lwt_list.iter_s (insert_block cctxt ?max_priority state) bis
|
||||||
|
|
||||||
let mine state =
|
let mine cctxt state =
|
||||||
let slots = pop_mining_slots state in
|
let slots = pop_mining_slots state in
|
||||||
Lwt_list.map_p
|
Lwt_list.map_p
|
||||||
(fun (timestamp, (bi, prio, delegate)) ->
|
(fun (timestamp, (bi, prio, delegate)) ->
|
||||||
@ -319,17 +321,17 @@ let mine state =
|
|||||||
Time.now ()
|
Time.now ()
|
||||||
else
|
else
|
||||||
timestamp in
|
timestamp in
|
||||||
Client_keys.Public_key_hash.name delegate >>= fun name ->
|
Client_keys.Public_key_hash.name cctxt delegate >>= fun name ->
|
||||||
lwt_debug "Try mining after %a (slot %d) for %s (%a)"
|
lwt_debug "Try mining after %a (slot %d) for %s (%a)"
|
||||||
Block_hash.pp_short bi.hash
|
Block_hash.pp_short bi.hash
|
||||||
prio name Time.pp_hum timestamp >>= fun () ->
|
prio name Time.pp_hum timestamp >>= fun () ->
|
||||||
Client_node_rpcs.Blocks.pending_operations
|
Client_node_rpcs.Blocks.pending_operations cctxt
|
||||||
block >>= fun (res, ops) ->
|
block >>= fun (res, ops) ->
|
||||||
let operations =
|
let operations =
|
||||||
let open Operation_hash_set in
|
let open Operation_hash_set in
|
||||||
elements (union ops (Updater.operations res)) in
|
elements (union ops (Updater.operations res)) in
|
||||||
let request = List.length operations in
|
let request = List.length operations in
|
||||||
Client_node_rpcs.Blocks.preapply block
|
Client_node_rpcs.Blocks.preapply cctxt block
|
||||||
~timestamp ~sort:true operations >>= function
|
~timestamp ~sort:true operations >>= function
|
||||||
| Error errs ->
|
| Error errs ->
|
||||||
lwt_log_error "Error while prevalidating operations:\n%a"
|
lwt_log_error "Error while prevalidating operations:\n%a"
|
||||||
@ -359,14 +361,14 @@ let mine state =
|
|||||||
Block_hash.pp_short bi.hash priority
|
Block_hash.pp_short bi.hash priority
|
||||||
Fitness.pp fitness >>= fun () ->
|
Fitness.pp fitness >>= fun () ->
|
||||||
let seed_nonce = generate_seed_nonce () in
|
let seed_nonce = generate_seed_nonce () in
|
||||||
Client_keys.get_key delegate >>=? fun (_,_,src_sk) ->
|
Client_keys.get_key cctxt delegate >>=? fun (_,_,src_sk) ->
|
||||||
inject_block ~force:true ~src_sk ~priority ~timestamp ~fitness ~seed_nonce
|
inject_block cctxt ~force:true ~src_sk ~priority ~timestamp ~fitness ~seed_nonce
|
||||||
(`Hash bi.hash) operations.applied
|
(`Hash bi.hash) operations.applied
|
||||||
|> trace_exn (Failure "Error while injecting block") >>=? fun block_hash ->
|
|> trace_exn (Failure "Error while injecting block") >>=? fun block_hash ->
|
||||||
State.record_block level block_hash seed_nonce
|
State.record_block cctxt level block_hash seed_nonce
|
||||||
|> trace_exn (Failure "Error while recording block") >>=? fun () ->
|
|> trace_exn (Failure "Error while recording block") >>=? fun () ->
|
||||||
Client_keys.Public_key_hash.name delegate >>= fun name ->
|
Client_keys.Public_key_hash.name cctxt delegate >>= fun name ->
|
||||||
Cli_entries.message
|
cctxt.message
|
||||||
"Injected block %a for %s after %a \
|
"Injected block %a for %s after %a \
|
||||||
\ (level %a, slot %d, fitness %a, operations %d)"
|
\ (level %a, slot %d, fitness %a, operations %d)"
|
||||||
Block_hash.pp_short block_hash
|
Block_hash.pp_short block_hash
|
||||||
@ -381,14 +383,14 @@ let mine state =
|
|||||||
lwt_debug "No valid candidates." >>= fun () ->
|
lwt_debug "No valid candidates." >>= fun () ->
|
||||||
return ()
|
return ()
|
||||||
|
|
||||||
let create ?max_priority delegates
|
let create cctxt ?max_priority delegates
|
||||||
(block_stream: Client_mining_blocks.block_info list Lwt_stream.t)
|
(block_stream: Client_mining_blocks.block_info list Lwt_stream.t)
|
||||||
(endorsement_stream: Client_mining_operations.valid_endorsement Lwt_stream.t) =
|
(endorsement_stream: Client_mining_operations.valid_endorsement Lwt_stream.t) =
|
||||||
Lwt_stream.get block_stream >>= function
|
Lwt_stream.get block_stream >>= function
|
||||||
| None | Some [] ->
|
| None | Some [] ->
|
||||||
Cli_entries.error "Can't fetch the current block head."
|
cctxt.Client_commands.error "Can't fetch the current block head."
|
||||||
| Some ({ Client_mining_blocks.fitness } :: _ as initial_heads) ->
|
| Some ({ Client_mining_blocks.fitness } :: _ as initial_heads) ->
|
||||||
Client_node_rpcs.Blocks.hash `Genesis >>= fun genesis_hash ->
|
Client_node_rpcs.Blocks.hash cctxt `Genesis >>= fun genesis_hash ->
|
||||||
let last_get_block = ref None in
|
let last_get_block = ref None in
|
||||||
let get_block () =
|
let get_block () =
|
||||||
match !last_get_block with
|
match !last_get_block with
|
||||||
@ -406,7 +408,7 @@ let create ?max_priority delegates
|
|||||||
t
|
t
|
||||||
| Some t -> t in
|
| Some t -> t in
|
||||||
let state = create_state genesis_hash delegates fitness in
|
let state = create_state genesis_hash delegates fitness in
|
||||||
insert_blocks ?max_priority state initial_heads >>= fun () ->
|
insert_blocks cctxt ?max_priority state initial_heads >>= fun () ->
|
||||||
let rec worker_loop () =
|
let rec worker_loop () =
|
||||||
let timeout = compute_timeout state in
|
let timeout = compute_timeout state in
|
||||||
Lwt.choose [ (timeout >|= fun () -> `Timeout) ;
|
Lwt.choose [ (timeout >|= fun () -> `Timeout) ;
|
||||||
@ -426,20 +428,20 @@ let create ?max_priority delegates
|
|||||||
Block_hash.pp_short ppf bi.Client_mining_blocks.hash))
|
Block_hash.pp_short ppf bi.Client_mining_blocks.hash))
|
||||||
bis
|
bis
|
||||||
>>= fun () ->
|
>>= fun () ->
|
||||||
insert_blocks ?max_priority state bis >>= fun () ->
|
insert_blocks cctxt ?max_priority state bis >>= fun () ->
|
||||||
worker_loop ()
|
worker_loop ()
|
||||||
end
|
end
|
||||||
| `Endorsement (Some e) ->
|
| `Endorsement (Some e) ->
|
||||||
Lwt.cancel timeout ;
|
Lwt.cancel timeout ;
|
||||||
last_get_endorsement := None ;
|
last_get_endorsement := None ;
|
||||||
Client_keys.Public_key_hash.name
|
Client_keys.Public_key_hash.name cctxt
|
||||||
e.Client_mining_operations.source >>= fun _source ->
|
e.Client_mining_operations.source >>= fun _source ->
|
||||||
(* TODO *)
|
(* TODO *)
|
||||||
worker_loop ()
|
worker_loop ()
|
||||||
| `Timeout ->
|
| `Timeout ->
|
||||||
lwt_debug "Waking up for mining..." >>= fun () ->
|
lwt_debug "Waking up for mining..." >>= fun () ->
|
||||||
begin
|
begin
|
||||||
mine state >>= function
|
mine cctxt state >>= function
|
||||||
| Ok () -> Lwt.return_unit
|
| Ok () -> Lwt.return_unit
|
||||||
| Error errs ->
|
| Error errs ->
|
||||||
lwt_log_error "Error while mining:\n%a"
|
lwt_log_error "Error while mining:\n%a"
|
||||||
|
@ -10,6 +10,7 @@
|
|||||||
val generate_seed_nonce: unit -> Nonce.t
|
val generate_seed_nonce: unit -> Nonce.t
|
||||||
|
|
||||||
val inject_block:
|
val inject_block:
|
||||||
|
Client_commands.context ->
|
||||||
Client_proto_rpcs.block ->
|
Client_proto_rpcs.block ->
|
||||||
?force:bool ->
|
?force:bool ->
|
||||||
priority:int ->
|
priority:int ->
|
||||||
@ -21,6 +22,7 @@ val inject_block:
|
|||||||
Block_hash.t tzresult Lwt.t
|
Block_hash.t tzresult Lwt.t
|
||||||
|
|
||||||
val forge_block:
|
val forge_block:
|
||||||
|
Client_commands.context ->
|
||||||
Client_proto_rpcs.block ->
|
Client_proto_rpcs.block ->
|
||||||
?force:bool ->
|
?force:bool ->
|
||||||
?operations:Operation_hash.t list ->
|
?operations:Operation_hash.t list ->
|
||||||
@ -35,11 +37,16 @@ val forge_block:
|
|||||||
Block_hash.t tzresult Lwt.t
|
Block_hash.t tzresult Lwt.t
|
||||||
|
|
||||||
module State : sig
|
module State : sig
|
||||||
val get_block: Raw_level.t -> Block_hash.t list tzresult Lwt.t
|
val get_block:
|
||||||
val record_block: Raw_level.t -> Block_hash.t -> Nonce.t -> unit tzresult Lwt.t
|
Client_commands.context ->
|
||||||
|
Raw_level.t -> Block_hash.t list tzresult Lwt.t
|
||||||
|
val record_block:
|
||||||
|
Client_commands.context ->
|
||||||
|
Raw_level.t -> Block_hash.t -> Nonce.t -> unit tzresult Lwt.t
|
||||||
end
|
end
|
||||||
|
|
||||||
val create:
|
val create:
|
||||||
|
Client_commands.context ->
|
||||||
?max_priority: int ->
|
?max_priority: int ->
|
||||||
public_key_hash list ->
|
public_key_hash list ->
|
||||||
Client_mining_blocks.block_info list Lwt_stream.t ->
|
Client_mining_blocks.block_info list Lwt_stream.t ->
|
||||||
|
@ -10,159 +10,156 @@
|
|||||||
open Cli_entries
|
open Cli_entries
|
||||||
open Client_proto_contracts
|
open Client_proto_contracts
|
||||||
|
|
||||||
let mine_block block ?force ?max_priority ?src_sk delegate =
|
let mine_block cctxt block ?force ?max_priority ?src_sk delegate =
|
||||||
begin
|
begin
|
||||||
match src_sk with
|
match src_sk with
|
||||||
| None ->
|
| None ->
|
||||||
Client_keys.get_key delegate >>=? fun (_, _, src_sk) ->
|
Client_keys.get_key cctxt delegate >>=? fun (_, _, src_sk) ->
|
||||||
return src_sk
|
return src_sk
|
||||||
| Some sk -> return sk
|
| Some sk -> return sk
|
||||||
end >>=? fun src_sk ->
|
end >>=? fun src_sk ->
|
||||||
Client_proto_rpcs.Context.level block >>=? fun level ->
|
Client_proto_rpcs.Context.level cctxt block >>=? fun level ->
|
||||||
let level = Raw_level.succ level.level in
|
let level = Raw_level.succ level.level in
|
||||||
let seed_nonce = Client_mining_forge.generate_seed_nonce () in
|
let seed_nonce = Client_mining_forge.generate_seed_nonce () in
|
||||||
Client_mining_forge.forge_block
|
Client_mining_forge.forge_block cctxt
|
||||||
~timestamp:(Time.now ())
|
~timestamp:(Time.now ())
|
||||||
?force ?max_priority
|
?force ?max_priority
|
||||||
~seed_nonce ~src_sk block delegate >>=? fun block_hash ->
|
~seed_nonce ~src_sk block delegate >>=? fun block_hash ->
|
||||||
Client_mining_forge.State.record_block level block_hash seed_nonce
|
Client_mining_forge.State.record_block cctxt level block_hash seed_nonce
|
||||||
|> trace_exn (Failure "Error while recording block") >>=? fun () ->
|
|> trace_exn (Failure "Error while recording block") >>=? fun () ->
|
||||||
message "Injected block %a" Block_hash.pp_short block_hash >>= fun () ->
|
cctxt.message "Injected block %a" Block_hash.pp_short block_hash >>= fun () ->
|
||||||
return ()
|
return ()
|
||||||
|
|
||||||
let endorse_block ?force ?max_priority delegate =
|
let endorse_block cctxt ?force ?max_priority delegate =
|
||||||
let block = Client_proto_args.block () in
|
let block = Client_proto_args.block () in
|
||||||
Client_keys.get_key delegate >>=? fun (_src_name, src_pk, src_sk) ->
|
Client_keys.get_key cctxt delegate >>=? fun (_src_name, src_pk, src_sk) ->
|
||||||
Client_mining_endorsement.forge_endorsement
|
Client_mining_endorsement.forge_endorsement cctxt
|
||||||
block ?force ?max_priority ~src_sk src_pk >>=? fun oph ->
|
block ?force ?max_priority ~src_sk src_pk >>=? fun oph ->
|
||||||
answer "Operation successfully injected in the node." >>= fun () ->
|
cctxt.answer "Operation successfully injected in the node." >>= fun () ->
|
||||||
answer "Operation hash is '%a'." Operation_hash.pp oph >>= fun () ->
|
cctxt.answer "Operation hash is '%a'." Operation_hash.pp oph >>= fun () ->
|
||||||
return ()
|
return ()
|
||||||
|
|
||||||
let get_predecessor_cycle cycle =
|
let get_predecessor_cycle cctxt cycle =
|
||||||
match Cycle.pred cycle with
|
match Cycle.pred cycle with
|
||||||
| None ->
|
| None ->
|
||||||
if Cycle.(cycle = root) then
|
if Cycle.(cycle = root) then
|
||||||
error "No predecessor for the first cycle"
|
cctxt.Client_commands.error "No predecessor for the first cycle"
|
||||||
else
|
else
|
||||||
error
|
cctxt.error
|
||||||
"Cannot compute the predecessor of cycle %a"
|
"Cannot compute the predecessor of cycle %a"
|
||||||
Cycle.pp cycle
|
Cycle.pp cycle
|
||||||
| Some cycle -> Lwt.return cycle
|
| Some cycle -> Lwt.return cycle
|
||||||
|
|
||||||
let do_reveal ?force block blocks =
|
let do_reveal cctxt ?force block blocks =
|
||||||
let nonces = List.map snd blocks in
|
let nonces = List.map snd blocks in
|
||||||
Client_mining_revelation.forge_seed_nonce_revelation
|
Client_mining_revelation.forge_seed_nonce_revelation cctxt
|
||||||
block ?force nonces >>=? fun () ->
|
block ?force nonces >>=? fun () ->
|
||||||
Client_proto_nonces.dels (List.map fst blocks) >>=? fun () ->
|
Client_proto_nonces.dels cctxt (List.map fst blocks) >>=? fun () ->
|
||||||
return ()
|
return ()
|
||||||
|
|
||||||
let reveal_block_nonces ?force block_hashes =
|
let reveal_block_nonces cctxt ?force block_hashes =
|
||||||
let block = Client_proto_args.block () in
|
let block = Client_proto_args.block () in
|
||||||
Lwt_list.filter_map_p
|
Lwt_list.filter_map_p
|
||||||
(fun hash ->
|
(fun hash ->
|
||||||
Lwt.catch
|
Lwt.catch
|
||||||
(fun () ->
|
(fun () ->
|
||||||
Client_mining_blocks.info (`Hash hash) >>= function
|
Client_mining_blocks.info cctxt (`Hash hash) >>= function
|
||||||
| Ok bi -> Lwt.return (Some bi)
|
| Ok bi -> Lwt.return (Some bi)
|
||||||
| Error _ ->
|
| Error _ ->
|
||||||
Lwt.fail Not_found)
|
Lwt.fail Not_found)
|
||||||
(fun _ ->
|
(fun _ ->
|
||||||
Cli_entries.warning
|
cctxt.warning
|
||||||
"Cannot find block %a in the chain. (ignoring)@."
|
"Cannot find block %a in the chain. (ignoring)@."
|
||||||
Block_hash.pp_short hash >>= fun () ->
|
Block_hash.pp_short hash >>= fun () ->
|
||||||
Lwt.return_none))
|
Lwt.return_none))
|
||||||
block_hashes >>= fun block_infos ->
|
block_hashes >>= fun block_infos ->
|
||||||
map_filter_s (fun (bi : Client_mining_blocks.block_info) ->
|
map_filter_s (fun (bi : Client_mining_blocks.block_info) ->
|
||||||
Client_proto_nonces.find bi.hash >>= function
|
Client_proto_nonces.find cctxt bi.hash >>= function
|
||||||
| None ->
|
| None ->
|
||||||
Cli_entries.warning "Cannot find nonces for block %a (ignoring)@."
|
cctxt.warning "Cannot find nonces for block %a (ignoring)@."
|
||||||
Block_hash.pp_short bi.hash >>= fun () ->
|
Block_hash.pp_short bi.hash >>= fun () ->
|
||||||
return None
|
return None
|
||||||
| Some nonce ->
|
| Some nonce ->
|
||||||
return (Some (bi.hash, (bi.level.level, nonce))))
|
return (Some (bi.hash, (bi.level.level, nonce))))
|
||||||
block_infos >>=? fun blocks ->
|
block_infos >>=? fun blocks ->
|
||||||
do_reveal ?force block blocks
|
do_reveal cctxt ?force block blocks
|
||||||
|
|
||||||
let reveal_nonces ?force () =
|
let reveal_nonces cctxt ?force () =
|
||||||
let block = Client_proto_args.block () in
|
let block = Client_proto_args.block () in
|
||||||
Client_proto_rpcs.Context.next_level block >>=? fun level ->
|
Client_proto_rpcs.Context.next_level cctxt block >>=? fun level ->
|
||||||
let cur_cycle = level.cycle in
|
let cur_cycle = level.cycle in
|
||||||
get_predecessor_cycle cur_cycle >>= fun cycle ->
|
get_predecessor_cycle cctxt cur_cycle >>= fun cycle ->
|
||||||
Client_mining_blocks.blocks_from_cycle block cycle >>=? fun block_infos ->
|
Client_mining_blocks.blocks_from_cycle cctxt block cycle >>=? fun block_infos ->
|
||||||
map_filter_s (fun (bi : Client_mining_blocks.block_info) ->
|
map_filter_s (fun (bi : Client_mining_blocks.block_info) ->
|
||||||
Client_proto_nonces.find bi.hash >>= function
|
Client_proto_nonces.find cctxt bi.hash >>= function
|
||||||
| None -> return None
|
| None -> return None
|
||||||
| Some nonce ->
|
| Some nonce ->
|
||||||
Cli_entries.warning "Found nonce for %a (level: %a)@."
|
cctxt.warning "Found nonce for %a (level: %a)@."
|
||||||
Block_hash.pp_short bi.hash Level.pp bi.level >>= fun () ->
|
Block_hash.pp_short bi.hash Level.pp bi.level >>= fun () ->
|
||||||
return (Some (bi.hash, (bi.level.level, nonce))))
|
return (Some (bi.hash, (bi.level.level, nonce))))
|
||||||
block_infos >>=? fun blocks ->
|
block_infos >>=? fun blocks ->
|
||||||
do_reveal ?force block blocks
|
do_reveal cctxt ?force block blocks
|
||||||
|
|
||||||
open Client_proto_args
|
open Client_proto_args
|
||||||
|
|
||||||
let run_daemon delegates () =
|
let run_daemon cctxt delegates =
|
||||||
Client_mining_daemon.run
|
Client_mining_daemon.run cctxt
|
||||||
?max_priority:!max_priority
|
?max_priority:!max_priority
|
||||||
~delay:!endorsement_delay
|
~delay:!endorsement_delay
|
||||||
~min_date:((Time.add (Time.now ()) (Int64.neg 1800L)))
|
~min_date:((Time.add (Time.now ()) (Int64.neg 1800L)))
|
||||||
(List.map snd delegates)
|
(List.map snd delegates)
|
||||||
|
|
||||||
|
let group =
|
||||||
|
{ Cli_entries.name = "delegate" ;
|
||||||
|
title = "Commands related to delegate operations." }
|
||||||
|
|
||||||
let commands () =
|
let commands () =
|
||||||
let open Cli_entries in
|
let open Cli_entries in
|
||||||
register_group "delegate" "Commands related to delegate operations." ;
|
|
||||||
[
|
[
|
||||||
command
|
command ~group ~desc: "Launch a daemon that handles delegate operations."
|
||||||
~group: "delegate"
|
|
||||||
~desc: "Launch a daemon that handles delegate operations."
|
|
||||||
~args: [endorsement_delay_arg; max_priority_arg;
|
~args: [endorsement_delay_arg; max_priority_arg;
|
||||||
Daemon.mining_arg ; Daemon.endorsement_arg ; Daemon.denunciation_arg]
|
Daemon.mining_arg ; Daemon.endorsement_arg ; Daemon.denunciation_arg]
|
||||||
(prefixes [ "launch" ; "daemon" ]
|
(prefixes [ "launch" ; "daemon" ]
|
||||||
@@ seq_of_param Client_keys.Public_key_hash.alias_param )
|
@@ seq_of_param Client_keys.Public_key_hash.alias_param )
|
||||||
run_daemon ;
|
(fun delegates cctxt ->
|
||||||
command
|
run_daemon cctxt delegates) ;
|
||||||
~group: "delegate"
|
command ~group ~desc: "Forge and inject an endorsement operation"
|
||||||
~desc: "Forge and inject an endorsement operation"
|
|
||||||
~args: [ force_arg ]
|
~args: [ force_arg ]
|
||||||
(prefixes [ "endorse"; "for" ]
|
(prefixes [ "endorse"; "for" ]
|
||||||
@@ Client_keys.Public_key_hash.alias_param
|
@@ Client_keys.Public_key_hash.alias_param
|
||||||
~name:"miner" ~desc: "name of the delegate owning the endorsement right"
|
~name:"miner" ~desc: "name of the delegate owning the endorsement right"
|
||||||
@@ stop)
|
@@ stop)
|
||||||
(fun (_, delegate) () ->
|
(fun (_, delegate) cctxt ->
|
||||||
endorse_block
|
endorse_block cctxt
|
||||||
~force:!force ?max_priority:!max_priority delegate >>=
|
~force:!force ?max_priority:!max_priority delegate >>=
|
||||||
Client_proto_rpcs.handle_error) ;
|
Client_proto_rpcs.handle_error cctxt) ;
|
||||||
command
|
command ~group ~desc: "Forge and inject block using the delegate rights"
|
||||||
~group: "delegate"
|
|
||||||
~desc: "Forge and inject block using the delegate rights"
|
|
||||||
~args: [ max_priority_arg ; force_arg ]
|
~args: [ max_priority_arg ; force_arg ]
|
||||||
(prefixes [ "mine"; "for" ]
|
(prefixes [ "mine"; "for" ]
|
||||||
@@ Client_keys.Public_key_hash.alias_param
|
@@ Client_keys.Public_key_hash.alias_param
|
||||||
~name:"miner" ~desc: "name of the delegate owning the mining right"
|
~name:"miner" ~desc: "name of the delegate owning the mining right"
|
||||||
@@ stop)
|
@@ stop)
|
||||||
(fun (_, delegate) () ->
|
(fun (_, delegate) cctxt ->
|
||||||
mine_block (block ())
|
mine_block cctxt (block ())
|
||||||
~force:!force ?max_priority:!max_priority delegate >>=
|
~force:!force ?max_priority:!max_priority delegate >>=
|
||||||
Client_proto_rpcs.handle_error) ;
|
Client_proto_rpcs.handle_error cctxt) ;
|
||||||
command
|
command ~group ~desc: "Forge and inject a seed-nonce revelation operation"
|
||||||
~group: "delegate"
|
|
||||||
~desc: "Forge and inject a seed-nonce revelation operation"
|
|
||||||
~args: [ force_arg ]
|
~args: [ force_arg ]
|
||||||
(prefixes [ "reveal"; "nonce"; "for" ]
|
(prefixes [ "reveal"; "nonce"; "for" ]
|
||||||
@@ Cli_entries.seq_of_param Block_hash.param)
|
@@ Cli_entries.seq_of_param Block_hash.param)
|
||||||
(fun block_hashes () ->
|
(fun block_hashes cctxt ->
|
||||||
reveal_block_nonces ~force:!force block_hashes >>= Client_proto_rpcs.handle_error) ;
|
reveal_block_nonces cctxt
|
||||||
command
|
~force:!force block_hashes >>=
|
||||||
~group: "delegate"
|
Client_proto_rpcs.handle_error cctxt) ;
|
||||||
~desc: "Forge and inject redemption operations"
|
command ~group ~desc: "Forge and inject redemption operations"
|
||||||
~args: [ force_arg ]
|
~args: [ force_arg ]
|
||||||
(prefixes [ "reveal"; "nonces" ]
|
(prefixes [ "reveal"; "nonces" ]
|
||||||
@@ stop)
|
@@ stop)
|
||||||
(fun () ->
|
(fun cctxt ->
|
||||||
reveal_nonces ~force:!force () >>= Client_proto_rpcs.handle_error) ;
|
reveal_nonces cctxt ~force:!force () >>=
|
||||||
|
Client_proto_rpcs.handle_error cctxt) ;
|
||||||
]
|
]
|
||||||
|
|
||||||
let () =
|
let () =
|
||||||
Client_version.register Client_proto_main.protocol @@
|
Client_commands.register Client_proto_main.protocol @@
|
||||||
commands ()
|
commands ()
|
||||||
|
@ -8,6 +8,7 @@
|
|||||||
(**************************************************************************)
|
(**************************************************************************)
|
||||||
|
|
||||||
val mine_block:
|
val mine_block:
|
||||||
|
Client_commands.context ->
|
||||||
Client_proto_rpcs.block ->
|
Client_proto_rpcs.block ->
|
||||||
?force:bool ->
|
?force:bool ->
|
||||||
?max_priority: int ->
|
?max_priority: int ->
|
||||||
@ -15,4 +16,4 @@ val mine_block:
|
|||||||
public_key_hash ->
|
public_key_hash ->
|
||||||
unit tzresult Lwt.t
|
unit tzresult Lwt.t
|
||||||
|
|
||||||
val commands: unit -> Cli_entries.command list
|
val commands: unit -> Client_commands.command list
|
||||||
|
@ -18,15 +18,15 @@ type operation = {
|
|||||||
content: (Updater.shell_operation * proto_operation) option
|
content: (Updater.shell_operation * proto_operation) option
|
||||||
}
|
}
|
||||||
|
|
||||||
let monitor ?contents ?check () =
|
let monitor cctxt ?contents ?check () =
|
||||||
Client_node_rpcs.Operations.monitor ?contents () >>= fun ops_stream ->
|
Client_node_rpcs.Operations.monitor cctxt ?contents () >>= fun ops_stream ->
|
||||||
let convert ops =
|
let convert ops =
|
||||||
Lwt_list.filter_map_p
|
Lwt_list.filter_map_p
|
||||||
(fun (hash, bytes) ->
|
(fun (hash, bytes) ->
|
||||||
match bytes with
|
match bytes with
|
||||||
| None -> Lwt.return (Some { hash; content = None })
|
| None -> Lwt.return (Some { hash; content = None })
|
||||||
| Some ({ Store.shell ; proto } : Updater.raw_operation) ->
|
| Some ({ Store.shell ; proto } : Updater.raw_operation) ->
|
||||||
Client_proto_rpcs.Helpers.Parse.operations
|
Client_proto_rpcs.Helpers.Parse.operations cctxt
|
||||||
`Prevalidation ?check shell proto >>= function
|
`Prevalidation ?check shell proto >>= function
|
||||||
| Ok proto -> Lwt.return (Some { hash ; content = Some (shell, proto) })
|
| Ok proto -> Lwt.return (Some { hash ; content = Some (shell, proto) })
|
||||||
| Error err ->
|
| Error err ->
|
||||||
@ -46,7 +46,7 @@ type valid_endorsement = {
|
|||||||
slots: int list ;
|
slots: int list ;
|
||||||
}
|
}
|
||||||
|
|
||||||
let filter_valid_endorsement { hash; content } =
|
let filter_valid_endorsement cctxt { hash; content } =
|
||||||
let open Tezos_context in
|
let open Tezos_context in
|
||||||
match content with
|
match content with
|
||||||
| None
|
| None
|
||||||
@ -73,14 +73,14 @@ let filter_valid_endorsement { hash; content } =
|
|||||||
slots in
|
slots in
|
||||||
(* Ensure thath the block has been previously validated by
|
(* Ensure thath the block has been previously validated by
|
||||||
the node. This might took some times... *)
|
the node. This might took some times... *)
|
||||||
Client_node_rpcs.validate_block net_id block >>= function
|
Client_node_rpcs.validate_block cctxt net_id block >>= function
|
||||||
| Error error ->
|
| Error error ->
|
||||||
lwt_log_info
|
lwt_log_info
|
||||||
"@[<v 2>Found endorsement for an invalid block@,%a@["
|
"@[<v 2>Found endorsement for an invalid block@,%a@["
|
||||||
pp_print_error error >>= fun () ->
|
pp_print_error error >>= fun () ->
|
||||||
Lwt.return_none
|
Lwt.return_none
|
||||||
| Ok () ->
|
| Ok () ->
|
||||||
Client_node_rpcs.Blocks.preapply (`Hash block) [hash] >>= function
|
Client_node_rpcs.Blocks.preapply cctxt (`Hash block) [hash] >>= function
|
||||||
| Ok _ ->
|
| Ok _ ->
|
||||||
Lwt.return (Some { hash ; source ; block ; slots })
|
Lwt.return (Some { hash ; source ; block ; slots })
|
||||||
| Error error ->
|
| Error error ->
|
||||||
@ -90,14 +90,14 @@ let filter_valid_endorsement { hash; content } =
|
|||||||
Lwt.return_none
|
Lwt.return_none
|
||||||
with Not_found -> Lwt.return_none
|
with Not_found -> Lwt.return_none
|
||||||
|
|
||||||
let monitor_endorsement () =
|
let monitor_endorsement cctxt =
|
||||||
monitor ~contents:true ~check:true () >>= fun ops_stream ->
|
monitor cctxt ~contents:true ~check:true () >>= fun ops_stream ->
|
||||||
let endorsement_stream, push = Lwt_stream.create () in
|
let endorsement_stream, push = Lwt_stream.create () in
|
||||||
Lwt_stream.on_termination ops_stream (fun () -> push None) ;
|
Lwt_stream.on_termination ops_stream (fun () -> push None) ;
|
||||||
Lwt.async (fun () ->
|
Lwt.async (fun () ->
|
||||||
Lwt_stream.iter_p
|
Lwt_stream.iter_p
|
||||||
(Lwt_list.iter_p (fun e ->
|
(Lwt_list.iter_p (fun e ->
|
||||||
filter_valid_endorsement e >>= function
|
filter_valid_endorsement cctxt e >>= function
|
||||||
| None -> Lwt.return_unit
|
| None -> Lwt.return_unit
|
||||||
| Some e -> push (Some e) ; Lwt.return_unit))
|
| Some e -> push (Some e) ; Lwt.return_unit))
|
||||||
ops_stream) ;
|
ops_stream) ;
|
||||||
|
@ -13,6 +13,7 @@ type operation = {
|
|||||||
}
|
}
|
||||||
|
|
||||||
val monitor:
|
val monitor:
|
||||||
|
Client_commands.context ->
|
||||||
?contents:bool -> ?check:bool -> unit ->
|
?contents:bool -> ?check:bool -> unit ->
|
||||||
operation list Lwt_stream.t Lwt.t
|
operation list Lwt_stream.t Lwt.t
|
||||||
|
|
||||||
@ -24,7 +25,9 @@ type valid_endorsement = {
|
|||||||
}
|
}
|
||||||
|
|
||||||
val filter_valid_endorsement:
|
val filter_valid_endorsement:
|
||||||
|
Client_commands.context ->
|
||||||
operation -> valid_endorsement option Lwt.t
|
operation -> valid_endorsement option Lwt.t
|
||||||
|
|
||||||
val monitor_endorsement:
|
val monitor_endorsement:
|
||||||
unit -> valid_endorsement Lwt_stream.t Lwt.t
|
Client_commands.context ->
|
||||||
|
valid_endorsement Lwt_stream.t Lwt.t
|
||||||
|
@ -11,30 +11,31 @@ open Cli_entries
|
|||||||
open Tezos_context
|
open Tezos_context
|
||||||
open Logging.Client.Revelation
|
open Logging.Client.Revelation
|
||||||
|
|
||||||
let inject_seed_nonce_revelation block ?force ?wait nonces =
|
let inject_seed_nonce_revelation cctxt block ?force ?wait nonces =
|
||||||
let operations =
|
let operations =
|
||||||
List.map
|
List.map
|
||||||
(fun (level, nonce) ->
|
(fun (level, nonce) ->
|
||||||
Seed_nonce_revelation { level ; nonce }) nonces in
|
Seed_nonce_revelation { level ; nonce }) nonces in
|
||||||
Client_node_rpcs.Blocks.net block >>= fun net ->
|
Client_node_rpcs.Blocks.net cctxt block >>= fun net ->
|
||||||
Client_proto_rpcs.Helpers.Forge.Anonymous.operations
|
Client_proto_rpcs.Helpers.Forge.Anonymous.operations cctxt
|
||||||
block ~net operations >>=? fun bytes ->
|
block ~net operations >>=? fun bytes ->
|
||||||
Client_node_rpcs.inject_operation ?force ?wait bytes >>=? fun oph ->
|
Client_node_rpcs.inject_operation cctxt ?force ?wait bytes >>=? fun oph ->
|
||||||
return oph
|
return oph
|
||||||
|
|
||||||
type Error_monad.error += Bad_revelation
|
type Error_monad.error += Bad_revelation
|
||||||
|
|
||||||
let forge_seed_nonce_revelation block ?(force = false) redempted_nonces =
|
let forge_seed_nonce_revelation cctxt
|
||||||
|
block ?(force = false) redempted_nonces =
|
||||||
begin
|
begin
|
||||||
if force then return redempted_nonces else
|
if force then return redempted_nonces else
|
||||||
map_filter_s (fun (level, nonce) ->
|
map_filter_s (fun (level, nonce) ->
|
||||||
Client_proto_rpcs.Context.Nonce.get block level >>=? function
|
Client_proto_rpcs.Context.Nonce.get cctxt block level >>=? function
|
||||||
| Forgotten ->
|
| Forgotten ->
|
||||||
message "Too late revelation for level %a"
|
cctxt.message "Too late revelation for level %a"
|
||||||
Raw_level.pp level >>= fun () ->
|
Raw_level.pp level >>= fun () ->
|
||||||
return None
|
return None
|
||||||
| Revealed _ ->
|
| Revealed _ ->
|
||||||
message "Ignoring previously-revealed nonce for level %a"
|
cctxt.message "Ignoring previously-revealed nonce for level %a"
|
||||||
Raw_level.pp level >>= fun () ->
|
Raw_level.pp level >>= fun () ->
|
||||||
return None
|
return None
|
||||||
| Missing nonce_hash ->
|
| Missing nonce_hash ->
|
||||||
@ -48,11 +49,11 @@ let forge_seed_nonce_revelation block ?(force = false) redempted_nonces =
|
|||||||
end >>=? fun nonces ->
|
end >>=? fun nonces ->
|
||||||
match nonces with
|
match nonces with
|
||||||
| [] ->
|
| [] ->
|
||||||
message "No nonce to reveal";
|
cctxt.message "No nonce to reveal" >>= fun () ->
|
||||||
return ()
|
return ()
|
||||||
| _ ->
|
| _ ->
|
||||||
inject_seed_nonce_revelation
|
inject_seed_nonce_revelation cctxt
|
||||||
block ~force ~wait:true nonces >>=? fun oph ->
|
block ~force ~wait:true nonces >>=? fun oph ->
|
||||||
answer "Operation successfully injected in the node." >>= fun () ->
|
cctxt.answer "Operation successfully injected in the node." >>= fun () ->
|
||||||
answer "Operation hash is '%a'." Operation_hash.pp_short oph >>= fun () ->
|
cctxt.answer "Operation hash is '%a'." Operation_hash.pp_short oph >>= fun () ->
|
||||||
return ()
|
return ()
|
||||||
|
@ -8,6 +8,7 @@
|
|||||||
(**************************************************************************)
|
(**************************************************************************)
|
||||||
|
|
||||||
val inject_seed_nonce_revelation:
|
val inject_seed_nonce_revelation:
|
||||||
|
Client_commands.context ->
|
||||||
Client_proto_rpcs.block ->
|
Client_proto_rpcs.block ->
|
||||||
?force:bool ->
|
?force:bool ->
|
||||||
?wait:bool ->
|
?wait:bool ->
|
||||||
@ -15,6 +16,7 @@ val inject_seed_nonce_revelation:
|
|||||||
Operation_hash.t tzresult Lwt.t
|
Operation_hash.t tzresult Lwt.t
|
||||||
|
|
||||||
val forge_seed_nonce_revelation:
|
val forge_seed_nonce_revelation:
|
||||||
|
Client_commands.context ->
|
||||||
Client_proto_rpcs.block ->
|
Client_proto_rpcs.block ->
|
||||||
?force:bool ->
|
?force:bool ->
|
||||||
(Raw_level.t * Nonce.t) list ->
|
(Raw_level.t * Nonce.t) list ->
|
||||||
|
5
src/client/embedded/bootstrap/webclient/.merlin
Normal file
5
src/client/embedded/bootstrap/webclient/.merlin
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
REC
|
||||||
|
B browser/
|
||||||
|
S browser/
|
||||||
|
B shared/
|
||||||
|
S shared/
|
9
src/client/embedded/bootstrap/webclient/browser/.merlin
Normal file
9
src/client/embedded/bootstrap/webclient/browser/.merlin
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
B ../../../../../minutils
|
||||||
|
S ../../../../../minutils
|
||||||
|
B ../shared
|
||||||
|
S ../shared
|
||||||
|
PKG lwt
|
||||||
|
PKG ocplib-json-typed.bson
|
||||||
|
PKG ocplib-resto.directory \
|
||||||
|
PKG js_of_ocaml.ppx
|
||||||
|
PKG js_of_ocaml.tyxml
|
@ -0,0 +1,53 @@
|
|||||||
|
(**************************************************************************)
|
||||||
|
(* *)
|
||||||
|
(* Copyright (c) 2014 - 2016. *)
|
||||||
|
(* Dynamic Ledger Solutions, Inc. <contact@tezos.com> *)
|
||||||
|
(* *)
|
||||||
|
(* All rights reserved. No warranty, explicit or implicit, provided. *)
|
||||||
|
(* *)
|
||||||
|
(**************************************************************************)
|
||||||
|
|
||||||
|
open Lwt.Infix
|
||||||
|
|
||||||
|
module Services = Webclient_proto_services.Make (struct
|
||||||
|
type root = unit
|
||||||
|
end)
|
||||||
|
|
||||||
|
let call_service service params input =
|
||||||
|
let write_json_body json =
|
||||||
|
let jsobj =
|
||||||
|
Json_repr.convert
|
||||||
|
(module Json_repr.Ezjsonm)
|
||||||
|
(module Json_repr_browser.Repr)
|
||||||
|
json in
|
||||||
|
Js._JSON##stringify jsobj in
|
||||||
|
let read_json_body body =
|
||||||
|
Json_repr.convert
|
||||||
|
(module Json_repr_browser.Repr)
|
||||||
|
(module Json_repr.Ezjsonm)
|
||||||
|
(Js._JSON##parse body) in
|
||||||
|
let path, json = RPC.forge_request service params input in
|
||||||
|
let url = String.concat "/" path in
|
||||||
|
let xhr = XmlHttpRequest.create () in
|
||||||
|
let t, u = Lwt.wait () in
|
||||||
|
xhr##.onreadystatechange := Js.wrap_callback (fun _ ->
|
||||||
|
if xhr##.readyState = XmlHttpRequest.DONE then
|
||||||
|
let response = read_json_body xhr##.responseText in
|
||||||
|
Lwt.wakeup u response) ;
|
||||||
|
xhr##_open (Js.string "POST") (Js.string url) Js._true ;
|
||||||
|
xhr##send (Js.Opt.return (write_json_body json)) ;
|
||||||
|
t >>= fun json ->
|
||||||
|
match RPC.read_answer service json with
|
||||||
|
| Ok res -> Lwt.return res
|
||||||
|
| Error msg -> Lwt.fail_with msg
|
||||||
|
|
||||||
|
let () = Lwt.async @@ fun () ->
|
||||||
|
call_service Services.contracts () () >>= fun names ->
|
||||||
|
call_service Services.hash () () >>= fun hash ->
|
||||||
|
let list = Tyxml_js.Html.(ul (List.map (fun n -> (li [ pcdata n ])) names)) in
|
||||||
|
Tyxml_js.Register.id "receptacle"
|
||||||
|
Tyxml_js.Html.
|
||||||
|
[ h2 [ pcdata "Block: " ; pcdata hash ] ;
|
||||||
|
h2 [ pcdata "Contract aliases:" ] ;
|
||||||
|
list ] ;
|
||||||
|
Lwt.return ()
|
5
src/client/embedded/bootstrap/webclient/shared/.merlin
Normal file
5
src/client/embedded/bootstrap/webclient/shared/.merlin
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
B ../../../../../minutils
|
||||||
|
S ../../../../../minutils
|
||||||
|
PKG lwt
|
||||||
|
PKG ocplib-json-typed.bson
|
||||||
|
PKG ocplib-resto.directory
|
@ -0,0 +1,30 @@
|
|||||||
|
(**************************************************************************)
|
||||||
|
(* *)
|
||||||
|
(* Copyright (c) 2014 - 2016. *)
|
||||||
|
(* Dynamic Ledger Solutions, Inc. <contact@tezos.com> *)
|
||||||
|
(* *)
|
||||||
|
(* All rights reserved. No warranty, explicit or implicit, provided. *)
|
||||||
|
(* *)
|
||||||
|
(**************************************************************************)
|
||||||
|
|
||||||
|
module type RPC_CONTEXT = sig
|
||||||
|
type root
|
||||||
|
end
|
||||||
|
|
||||||
|
module Make (RPC_context : RPC_CONTEXT) = struct
|
||||||
|
|
||||||
|
let box_result field enc =
|
||||||
|
let open Data_encoding in
|
||||||
|
obj1 (req field enc)
|
||||||
|
|
||||||
|
let contracts =
|
||||||
|
let input = Data_encoding.empty in
|
||||||
|
let output = box_result "contracts" Data_encoding.(list string) in
|
||||||
|
RPC.service ~input ~output RPC.Path.(root / "contracts")
|
||||||
|
|
||||||
|
let hash =
|
||||||
|
let input = Data_encoding.empty in
|
||||||
|
let output = box_result "hash" Data_encoding.string in
|
||||||
|
RPC.service ~input ~output RPC.Path.(root / "hash")
|
||||||
|
|
||||||
|
end
|
@ -0,0 +1,19 @@
|
|||||||
|
(**************************************************************************)
|
||||||
|
(* *)
|
||||||
|
(* Copyright (c) 2014 - 2016. *)
|
||||||
|
(* Dynamic Ledger Solutions, Inc. <contact@tezos.com> *)
|
||||||
|
(* *)
|
||||||
|
(* All rights reserved. No warranty, explicit or implicit, provided. *)
|
||||||
|
(* *)
|
||||||
|
(**************************************************************************)
|
||||||
|
|
||||||
|
module type RPC_CONTEXT = sig
|
||||||
|
type root
|
||||||
|
end
|
||||||
|
|
||||||
|
module Make (RPC_context : RPC_CONTEXT) : sig
|
||||||
|
val contracts :
|
||||||
|
(RPC_context.root, RPC_context.root, unit, string list) RPC.service
|
||||||
|
val hash :
|
||||||
|
(RPC_context.root, RPC_context.root, unit, string) RPC.service
|
||||||
|
end
|
12
src/client/embedded/bootstrap/webclient/static/index.html
Normal file
12
src/client/embedded/bootstrap/webclient/static/index.html
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
<!doctype html>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<title>Tezos Web Client :: Bootstrap Version</title>
|
||||||
|
<meta charset="utf-8" />
|
||||||
|
<script src="main.js" defer></script>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<h1>Tezos Web client :: Bootstrap Version</h1>
|
||||||
|
<div id="receptacle"></div>
|
||||||
|
</body>
|
||||||
|
</html>
|
@ -0,0 +1,10 @@
|
|||||||
|
<!doctype html>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<title>Tezos Web Client :: Bootstrap Version</title>
|
||||||
|
<meta charset="utf-8" />
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<h1>Not Found</h1>
|
||||||
|
</body>
|
||||||
|
</html>
|
@ -7,10 +7,9 @@
|
|||||||
(* *)
|
(* *)
|
||||||
(**************************************************************************)
|
(**************************************************************************)
|
||||||
|
|
||||||
open Cli_entries
|
|
||||||
|
|
||||||
exception Version_not_found
|
let () =
|
||||||
|
Webclient_version.register_services
|
||||||
val register: Protocol_hash.t -> command list -> unit
|
Client_proto_main.protocol Webclient_proto_service_directory.root ;
|
||||||
val commands_for_version: Protocol_hash.t -> command list
|
Webclient_version.register_static_files
|
||||||
val get_versions: unit -> (Protocol_hash.t * (command list)) list
|
Client_proto_main.protocol Webclient_proto_static.root
|
@ -0,0 +1,26 @@
|
|||||||
|
(**************************************************************************)
|
||||||
|
(* *)
|
||||||
|
(* Copyright (c) 2014 - 2016. *)
|
||||||
|
(* Dynamic Ledger Solutions, Inc. <contact@tezos.com> *)
|
||||||
|
(* *)
|
||||||
|
(* All rights reserved. No warranty, explicit or implicit, provided. *)
|
||||||
|
(* *)
|
||||||
|
(**************************************************************************)
|
||||||
|
|
||||||
|
module Services = Webclient_proto_services.Make (struct
|
||||||
|
type root = Node_rpc_services.Blocks.block
|
||||||
|
end)
|
||||||
|
|
||||||
|
let cctxt = Client_commands.ignore_context
|
||||||
|
|
||||||
|
let root =
|
||||||
|
let root =
|
||||||
|
RPC.register RPC.empty Services.contracts @@ fun block () ->
|
||||||
|
Client_proto_contracts.RawContractAlias.load cctxt >>= fun list ->
|
||||||
|
let (names, _) = List.split list in
|
||||||
|
RPC.Answer.return names in
|
||||||
|
let root =
|
||||||
|
RPC.register root Services.hash @@ fun block () ->
|
||||||
|
Client_node_rpcs.(call_service1 cctxt Node_rpc_services.Blocks.hash block ()) >>= fun res ->
|
||||||
|
RPC.Answer.return (Hash.Block_hash.to_b48check res) in
|
||||||
|
root
|
@ -1,11 +1,11 @@
|
|||||||
|
|
||||||
PROTO_VERSION = demo
|
PROTO_VERSION = demo
|
||||||
|
|
||||||
IMPLS = \
|
CLIENT_IMPLS = \
|
||||||
client_proto_rpcs.ml \
|
client_proto_rpcs.ml \
|
||||||
client_proto_main.ml
|
client_proto_main.ml
|
||||||
|
|
||||||
INTFS = \
|
CLIENT_INTFS = \
|
||||||
client_proto_rpcs.mli \
|
client_proto_rpcs.mli \
|
||||||
client_proto_main.mli
|
client_proto_main.mli
|
||||||
|
|
||||||
|
@ -11,35 +11,35 @@ let protocol =
|
|||||||
Protocol_hash.of_b48check
|
Protocol_hash.of_b48check
|
||||||
"2gagsSEvTKAHRjxAamgSdBNkv39VtNCqpaDXrrH4K8R4KQAAHrhe3"
|
"2gagsSEvTKAHRjxAamgSdBNkv39VtNCqpaDXrrH4K8R4KQAAHrhe3"
|
||||||
|
|
||||||
let demo () =
|
let demo cctxt =
|
||||||
let block = Client_config.block () in
|
let block = Client_config.block () in
|
||||||
Cli_entries.message "Calling the 'echo' RPC." >>= fun () ->
|
cctxt.Client_commands.message "Calling the 'echo' RPC." >>= fun () ->
|
||||||
let msg = "test" in
|
let msg = "test" in
|
||||||
Client_proto_rpcs.echo block msg >>= fun reply ->
|
Client_proto_rpcs.echo cctxt block msg >>= fun reply ->
|
||||||
fail_unless (reply = msg) (Unclassified "...") >>=? fun () ->
|
fail_unless (reply = msg) (Unclassified "...") >>=? fun () ->
|
||||||
begin
|
begin
|
||||||
Cli_entries.message "Calling the 'failing' RPC." >>= fun () ->
|
cctxt.message "Calling the 'failing' RPC." >>= fun () ->
|
||||||
Client_proto_rpcs.failing block 3 >>= function
|
Client_proto_rpcs.failing cctxt block 3 >>= function
|
||||||
| Error [Ecoproto_error [Error.Demo_error 3]] ->
|
| Error [Ecoproto_error [Error.Demo_error 3]] ->
|
||||||
return ()
|
return ()
|
||||||
| _ -> failwith "..."
|
| _ -> failwith "..."
|
||||||
end >>=? fun () ->
|
end >>=? fun () ->
|
||||||
Cli_entries.message "Direct call to `demo_error`." >>= fun () ->
|
cctxt.message "Direct call to `demo_error`." >>= fun () ->
|
||||||
begin Error.demo_error 101010 >|= wrap_error >>= function
|
begin Error.demo_error 101010 >|= wrap_error >>= function
|
||||||
| Error [Ecoproto_error [Error.Demo_error 101010]] ->
|
| Error [Ecoproto_error [Error.Demo_error 101010]] ->
|
||||||
return ()
|
return ()
|
||||||
| _ -> failwith "...."
|
| _ -> failwith "...."
|
||||||
end >>=? fun () ->
|
end >>=? fun () ->
|
||||||
Cli_entries.answer "All good!" >>= fun () ->
|
cctxt.answer "All good!" >>= fun () ->
|
||||||
return ()
|
return ()
|
||||||
|
|
||||||
let mine () =
|
let mine cctxt =
|
||||||
let block =
|
let block =
|
||||||
match Client_config.block () with
|
match Client_config.block () with
|
||||||
| `Prevalidation -> `Head 0
|
| `Prevalidation -> `Head 0
|
||||||
| `Test_prevalidation -> `Test_head 0
|
| `Test_prevalidation -> `Test_head 0
|
||||||
| b -> b in
|
| b -> b in
|
||||||
Client_node_rpcs.Blocks.info block >>= fun bi ->
|
Client_node_rpcs.Blocks.info cctxt block >>= fun bi ->
|
||||||
let fitness =
|
let fitness =
|
||||||
match bi.fitness with
|
match bi.fitness with
|
||||||
| [ v ; b ] ->
|
| [ v ; b ] ->
|
||||||
@ -48,46 +48,40 @@ let mine () =
|
|||||||
[ v ; b ]
|
[ v ; b ]
|
||||||
| _ ->
|
| _ ->
|
||||||
Lwt.ignore_result
|
Lwt.ignore_result
|
||||||
(Cli_entries.message "Cannot parse fitness: %a" Fitness.pp bi.fitness);
|
(cctxt.message "Cannot parse fitness: %a" Fitness.pp bi.fitness);
|
||||||
exit 2 in
|
exit 2 in
|
||||||
Client_node_rpcs.forge_block
|
Client_node_rpcs.forge_block cctxt
|
||||||
~net:bi.net ~predecessor:bi.hash
|
~net:bi.net ~predecessor:bi.hash
|
||||||
fitness [] (MBytes.create 0) >>= fun bytes ->
|
fitness [] (MBytes.create 0) >>= fun bytes ->
|
||||||
Client_node_rpcs.inject_block ~wait:true bytes >>=? fun hash ->
|
Client_node_rpcs.inject_block cctxt ~wait:true bytes >>=? fun hash ->
|
||||||
Cli_entries.answer "Injected %a" Block_hash.pp_short hash >>= fun () ->
|
cctxt.answer "Injected %a" Block_hash.pp_short hash >>= fun () ->
|
||||||
return ()
|
return ()
|
||||||
|
|
||||||
let handle_error = function
|
let handle_error cctxt = function
|
||||||
| Ok res ->
|
| Ok res ->
|
||||||
Lwt.return res
|
Lwt.return res
|
||||||
| Error exns ->
|
| Error exns ->
|
||||||
pp_print_error Format.err_formatter exns ;
|
pp_print_error Format.err_formatter exns ;
|
||||||
Cli_entries.error "cannot continue"
|
cctxt.Client_commands.error "%s" "cannot continue"
|
||||||
|
|
||||||
let commands () =
|
let commands () =
|
||||||
let open Cli_entries in
|
let open Cli_entries in
|
||||||
register_group "demo" "Some demo command" ;
|
let group = {name = "demo" ; title = "Some demo command" } in
|
||||||
[
|
[
|
||||||
command
|
command ~group ~desc: "A demo command"
|
||||||
~group: "demo"
|
|
||||||
~desc: "A demo command"
|
|
||||||
(fixed [ "demo" ])
|
(fixed [ "demo" ])
|
||||||
(fun () -> demo () >>= handle_error) ;
|
(fun cctxt -> demo cctxt >>= handle_error cctxt) ;
|
||||||
command
|
command ~group ~desc: "A failing command"
|
||||||
~group: "demo"
|
|
||||||
~desc: "An failing command"
|
|
||||||
(fixed [ "fail" ])
|
(fixed [ "fail" ])
|
||||||
(fun () ->
|
(fun cctxt ->
|
||||||
Error.demo_error 101010
|
Error.demo_error 101010
|
||||||
>|= wrap_error
|
>|= wrap_error
|
||||||
>>= handle_error ) ;
|
>>= handle_error cctxt) ;
|
||||||
command
|
command ~group ~desc: "Mine an empty block"
|
||||||
~group: "demo"
|
|
||||||
~desc: "Mine an empty block"
|
|
||||||
(fixed [ "mine" ])
|
(fixed [ "mine" ])
|
||||||
(fun () -> mine () >>= handle_error) ;
|
(fun cctxt -> mine cctxt >>= handle_error cctxt) ;
|
||||||
]
|
]
|
||||||
|
|
||||||
let () =
|
let () =
|
||||||
Client_version.register protocol @@
|
Client_commands.register protocol @@
|
||||||
commands ()
|
commands ()
|
||||||
|
@ -7,11 +7,11 @@
|
|||||||
(* *)
|
(* *)
|
||||||
(**************************************************************************)
|
(**************************************************************************)
|
||||||
|
|
||||||
let call_service1 s block a1 =
|
let call_service1 cctxt s block a1 =
|
||||||
Client_node_rpcs.call_service1
|
Client_node_rpcs.call_service1 cctxt
|
||||||
(s Node_rpc_services.Blocks.proto_path) block a1
|
(s Node_rpc_services.Blocks.proto_path) block a1
|
||||||
let call_error_service1 s block a1 =
|
let call_error_service1 cctxt s block a1 =
|
||||||
call_service1 s block a1 >|= wrap_error
|
call_service1 cctxt s block a1 >|= wrap_error
|
||||||
|
|
||||||
let echo = call_service1 Services.echo_service
|
let echo cctxt = call_service1 cctxt Services.echo_service
|
||||||
let failing = call_error_service1 Services.failing_service
|
let failing cctxt = call_error_service1 cctxt Services.failing_service
|
||||||
|
@ -9,5 +9,9 @@
|
|||||||
|
|
||||||
open Node_rpc_services
|
open Node_rpc_services
|
||||||
|
|
||||||
val echo: Blocks.block -> string -> string Lwt.t
|
val echo:
|
||||||
val failing: Blocks.block -> int -> unit tzresult Lwt.t
|
Client_commands.context ->
|
||||||
|
Blocks.block -> string -> string Lwt.t
|
||||||
|
val failing:
|
||||||
|
Client_commands.context ->
|
||||||
|
Blocks.block -> int -> unit tzresult Lwt.t
|
||||||
|
28
src/client/webclient_version.ml
Normal file
28
src/client/webclient_version.ml
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
(**************************************************************************)
|
||||||
|
(* *)
|
||||||
|
(* Copyright (c) 2014 - 2016. *)
|
||||||
|
(* Dynamic Ledger Solutions, Inc. <contact@tezos.com> *)
|
||||||
|
(* *)
|
||||||
|
(* All rights reserved. No warranty, explicit or implicit, provided. *)
|
||||||
|
(* *)
|
||||||
|
(**************************************************************************)
|
||||||
|
|
||||||
|
(* Tezos Web Interface - version dependent services *)
|
||||||
|
|
||||||
|
let contextual_static_files : string OCamlRes.Res.root Protocol_hash_table.t =
|
||||||
|
Protocol_hash_table.create 7
|
||||||
|
|
||||||
|
let register_static_files version root =
|
||||||
|
Protocol_hash_table.add contextual_static_files version root
|
||||||
|
|
||||||
|
let find_contextual_static_files version =
|
||||||
|
Protocol_hash_table.find contextual_static_files version
|
||||||
|
|
||||||
|
let contextual_services : Node_rpc_services.Blocks.block RPC.directory Protocol_hash_table.t =
|
||||||
|
Protocol_hash_table.create 7
|
||||||
|
|
||||||
|
let register_services version root =
|
||||||
|
Protocol_hash_table.add contextual_services version root
|
||||||
|
|
||||||
|
let find_contextual_services version =
|
||||||
|
Protocol_hash_table.find contextual_services version
|
@ -11,7 +11,7 @@
|
|||||||
|
|
||||||
open Lwt
|
open Lwt
|
||||||
|
|
||||||
let () =
|
let cctxt =
|
||||||
let startup =
|
let startup =
|
||||||
CalendarLib.Printer.Precise_Calendar.sprint
|
CalendarLib.Printer.Precise_Calendar.sprint
|
||||||
"%Y-%m-%dT%H:%M:%SZ"
|
"%Y-%m-%dT%H:%M:%SZ"
|
||||||
@ -30,7 +30,7 @@ let () =
|
|||||||
~mode: Lwt_io.Output
|
~mode: Lwt_io.Output
|
||||||
Client_config.(base_dir#get // "logs" // log // startup)
|
Client_config.(base_dir#get // "logs" // log // startup)
|
||||||
(fun chan -> Lwt_io.write chan msg) in
|
(fun chan -> Lwt_io.write chan msg) in
|
||||||
Cli_entries.log_hook := Some log
|
Client_commands.make_context log
|
||||||
|
|
||||||
(* Main (lwt) entry *)
|
(* Main (lwt) entry *)
|
||||||
let main () =
|
let main () =
|
||||||
@ -38,12 +38,13 @@ let main () =
|
|||||||
Sodium.Random.stir () ;
|
Sodium.Random.stir () ;
|
||||||
catch
|
catch
|
||||||
(fun () ->
|
(fun () ->
|
||||||
Client_config.preparse_args () >>= fun block ->
|
Client_config.preparse_args Sys.argv cctxt >>= fun block ->
|
||||||
Lwt.catch
|
Lwt.catch
|
||||||
(fun () ->
|
(fun () ->
|
||||||
Client_node_rpcs.Blocks.protocol block)
|
Client_node_rpcs.Blocks.protocol cctxt block)
|
||||||
(fun _ ->
|
(fun _ ->
|
||||||
Cli_entries.message "\n\
|
cctxt.message
|
||||||
|
"\n\
|
||||||
The connection to the RPC server failed, \
|
The connection to the RPC server failed, \
|
||||||
using the default protocol version.\n" >>= fun () ->
|
using the default protocol version.\n" >>= fun () ->
|
||||||
Lwt.return Client_bootstrap.Client_proto_main.protocol)
|
Lwt.return Client_bootstrap.Client_proto_main.protocol)
|
||||||
@ -53,36 +54,39 @@ let main () =
|
|||||||
Client_keys.commands () @
|
Client_keys.commands () @
|
||||||
Client_protocols.commands () @
|
Client_protocols.commands () @
|
||||||
Client_helpers.commands () @
|
Client_helpers.commands () @
|
||||||
Client_version.commands_for_version version in
|
Client_commands.commands_for_version version in
|
||||||
Client_config.parse_args ~version
|
Client_config.parse_args ~version
|
||||||
(Cli_entries.usage commands)
|
(Cli_entries.usage ~commands)
|
||||||
(Cli_entries.inline_dispatch commands))
|
(Cli_entries.inline_dispatch commands)
|
||||||
|
Sys.argv cctxt >>= fun command ->
|
||||||
|
command cctxt >>= fun () ->
|
||||||
|
Lwt.return 0)
|
||||||
(function
|
(function
|
||||||
| Arg.Help help ->
|
| Arg.Help help ->
|
||||||
Format.printf "%s%!" help ;
|
Format.printf "%s%!" help ;
|
||||||
Pervasives.exit 0
|
Lwt.return 0
|
||||||
| Arg.Bad help ->
|
| Arg.Bad help ->
|
||||||
Format.eprintf "%s%!" help ;
|
Format.eprintf "%s%!" help ;
|
||||||
Pervasives.exit 1
|
Lwt.return 1
|
||||||
| Cli_entries.Command_not_found ->
|
| Cli_entries.Command_not_found ->
|
||||||
Format.eprintf "Unkonwn command, try `-help`.\n%!" ;
|
Format.eprintf "Unkonwn command, try `-help`.\n%!" ;
|
||||||
Pervasives.exit 1
|
Lwt.return 1
|
||||||
| Client_version.Version_not_found ->
|
| Client_commands.Version_not_found ->
|
||||||
Format.eprintf "Unkonwn protocol version, try `list versions`.\n%!" ;
|
Format.eprintf "Unkonwn protocol version, try `list versions`.\n%!" ;
|
||||||
Pervasives.exit 1
|
Lwt.return 1
|
||||||
| Cli_entries.Bad_argument (idx, _n, v) ->
|
| Cli_entries.Bad_argument (idx, _n, v) ->
|
||||||
Format.eprintf "There's a problem with argument %d, %s.\n%!" idx v ;
|
Format.eprintf "There's a problem with argument %d, %s.\n%!" idx v ;
|
||||||
Pervasives.exit 1
|
Lwt.return 1
|
||||||
| Cli_entries.Command_failed message ->
|
| Cli_entries.Command_failed message ->
|
||||||
Format.eprintf "Command failed, %s.\n%!" message ;
|
Format.eprintf "Command failed, %s.\n%!" message ;
|
||||||
Pervasives.exit 1
|
Lwt.return 1
|
||||||
| Failure message ->
|
| Failure message ->
|
||||||
Format.eprintf "%s%!" message ;
|
Format.eprintf "%s\n%!" message ;
|
||||||
Pervasives.exit 1
|
Lwt.return 1
|
||||||
| exn ->
|
| exn ->
|
||||||
Format.printf "Fatal internal error: %s\n%!"
|
Format.printf "Fatal internal error: %s\n%!"
|
||||||
(Printexc.to_string exn) ;
|
(Printexc.to_string exn) ;
|
||||||
Pervasives.exit 1)
|
Lwt.return 1)
|
||||||
|
|
||||||
(* Where all the user friendliness starts *)
|
(* Where all the user friendliness starts *)
|
||||||
let () = Lwt_main.run (main ())
|
let () = Pervasives.exit (Lwt_main.run (main ()))
|
||||||
|
@ -27,6 +27,9 @@ depends: [
|
|||||||
"ocplib-endian"
|
"ocplib-endian"
|
||||||
"ocplib-json-typed"
|
"ocplib-json-typed"
|
||||||
"ocplib-resto" {>= "dev"}
|
"ocplib-resto" {>= "dev"}
|
||||||
|
"reactiveData"
|
||||||
|
"tyxml"
|
||||||
|
"js_of_ocaml"
|
||||||
"sodium" {>= "0.3.0"}
|
"sodium" {>= "0.3.0"}
|
||||||
"kaputt" (* only for testing *)
|
"kaputt" (* only for testing *)
|
||||||
"bisect_ppx" (* only for testing *)
|
"bisect_ppx" (* only for testing *)
|
||||||
|
@ -18,50 +18,35 @@ exception Command_failed of string
|
|||||||
|
|
||||||
(* A simple structure for command interpreters.
|
(* A simple structure for command interpreters.
|
||||||
This is more generic than the exported one, see end of file. *)
|
This is more generic than the exported one, see end of file. *)
|
||||||
type ('a, 'arg, 'ret) tparams =
|
type ('a, 'arg, 'ret) params =
|
||||||
| Prefix : string * ('a, 'arg, 'ret) tparams ->
|
| Prefix : string * ('a, 'arg, 'ret) params ->
|
||||||
('a, 'arg, 'ret) tparams
|
('a, 'arg, 'ret) params
|
||||||
| Param : string * string *
|
| Param : string * string *
|
||||||
(string -> 'p Lwt.t) *
|
('arg -> string -> 'p Lwt.t) *
|
||||||
('a, 'arg, 'ret) tparams ->
|
('a, 'arg, 'ret) params ->
|
||||||
('p -> 'a, 'arg, 'ret) tparams
|
('p -> 'a, 'arg, 'ret) params
|
||||||
| Stop :
|
| Stop :
|
||||||
('arg -> 'ret Lwt.t, 'arg, 'ret) tparams
|
('arg -> 'ret Lwt.t, 'arg, 'ret) params
|
||||||
| More :
|
| More :
|
||||||
(string list -> 'arg -> 'ret Lwt.t, 'arg, 'ret) tparams
|
(string list -> 'arg -> 'ret Lwt.t, 'arg, 'ret) params
|
||||||
| Seq : string * string *
|
| Seq : string * string *
|
||||||
(string -> 'p Lwt.t) ->
|
('arg -> string -> 'p Lwt.t) ->
|
||||||
('p list -> 'arg -> 'ret Lwt.t, 'arg, 'ret) tparams
|
('p list -> 'arg -> 'ret Lwt.t, 'arg, 'ret) params
|
||||||
|
|
||||||
|
(* A command group *)
|
||||||
|
type group =
|
||||||
|
{ name : string ;
|
||||||
|
title : string }
|
||||||
|
|
||||||
(* A command wraps a callback with its type and info *)
|
(* A command wraps a callback with its type and info *)
|
||||||
and ('arg, 'ret) tcommand =
|
type ('arg, 'ret) command =
|
||||||
| Command
|
| Command
|
||||||
: ('a, 'arg, 'ret) tparams * 'a *
|
: { params: ('a, 'arg, 'ret) params ;
|
||||||
desc option * tag list * group option *
|
handler : 'a ;
|
||||||
(Arg.key * Arg.spec * Arg.doc) list
|
desc : string ;
|
||||||
-> ('arg, 'ret) tcommand
|
group : group option ;
|
||||||
|
args : (Arg.key * Arg.spec * Arg.doc) list }
|
||||||
and desc = string
|
-> ('arg, 'ret) command
|
||||||
and group = string
|
|
||||||
and tag = string
|
|
||||||
|
|
||||||
(* Associates group names with group titles *)
|
|
||||||
let groups : (group * string) list ref = ref []
|
|
||||||
let register_group group title =
|
|
||||||
try ignore @@ List.assoc group !groups with
|
|
||||||
| Not_found -> groups := (group, title) :: !groups
|
|
||||||
let group_title group =
|
|
||||||
try List.assoc group !groups with
|
|
||||||
| Not_found -> group
|
|
||||||
|
|
||||||
(* Associates tag names with tag descriptions *)
|
|
||||||
let tags : (tag * string) list ref = ref []
|
|
||||||
let register_tag tag title =
|
|
||||||
try ignore @@ List.assoc tag !tags with
|
|
||||||
| Not_found -> tags := (tag, title) :: !tags
|
|
||||||
let tag_description tag =
|
|
||||||
try List.assoc tag !tags with
|
|
||||||
| Not_found -> "undocumented tag"
|
|
||||||
|
|
||||||
(* Some combinators for writing commands concisely. *)
|
(* Some combinators for writing commands concisely. *)
|
||||||
let param ~name ~desc kind next = Param (name, desc, kind, next)
|
let param ~name ~desc kind next = Param (name, desc, kind, next)
|
||||||
@ -80,18 +65,19 @@ let stop = Stop
|
|||||||
let more = More
|
let more = More
|
||||||
let void = Stop
|
let void = Stop
|
||||||
let any = More
|
let any = More
|
||||||
let command ?desc ?(tags = []) ?group ?(args = []) params cb =
|
let command ?group ?(args = []) ~desc params handler =
|
||||||
Command (params, cb, desc,tags, group, args)
|
Command { params ; handler ; desc ; group ; args }
|
||||||
|
|
||||||
(* Param combinators *)
|
(* Param combinators *)
|
||||||
let string n desc next = param n desc (fun s -> return s) next
|
let string ~name ~desc next =
|
||||||
|
param name desc (fun _ s -> return s) next
|
||||||
|
|
||||||
(* Command execution *)
|
(* Command execution *)
|
||||||
let exec
|
let exec
|
||||||
(type arg) (type ret)
|
(type arg) (type ret)
|
||||||
(Command (params, cb, _, _, _, _)) (last : arg) args =
|
(Command { params ; handler }) (last : arg) args =
|
||||||
let rec exec
|
let rec exec
|
||||||
: type a. int -> (a, arg, ret) tparams -> a -> string list -> ret Lwt.t
|
: type a. int -> (a, arg, ret) params -> a -> string list -> ret Lwt.t
|
||||||
= fun i params cb args ->
|
= fun i params cb args ->
|
||||||
match params, args with
|
match params, args with
|
||||||
| Stop, [] -> cb last
|
| Stop, [] -> cb last
|
||||||
@ -101,7 +87,7 @@ let exec
|
|||||||
| [] -> Lwt.return (List.rev acc)
|
| [] -> Lwt.return (List.rev acc)
|
||||||
| p :: rest ->
|
| p :: rest ->
|
||||||
catch
|
catch
|
||||||
(fun () -> f p)
|
(fun () -> f last p)
|
||||||
(function
|
(function
|
||||||
| Failure msg -> Lwt.fail (Bad_argument (i, p, msg))
|
| Failure msg -> Lwt.fail (Bad_argument (i, p, msg))
|
||||||
| exn -> Lwt.fail exn) >>= fun v ->
|
| exn -> Lwt.fail exn) >>= fun v ->
|
||||||
@ -113,33 +99,33 @@ let exec
|
|||||||
exec (succ i) next cb rest
|
exec (succ i) next cb rest
|
||||||
| Param (_, _, f, next), p :: rest ->
|
| Param (_, _, f, next), p :: rest ->
|
||||||
catch
|
catch
|
||||||
(fun () -> f p)
|
(fun () -> f last p)
|
||||||
(function
|
(function
|
||||||
| Failure msg -> Lwt.fail (Bad_argument (i, p, msg))
|
| Failure msg -> Lwt.fail (Bad_argument (i, p, msg))
|
||||||
| exn -> Lwt.fail exn) >>= fun v ->
|
| exn -> Lwt.fail exn) >>= fun v ->
|
||||||
exec (succ i) next (cb v) rest
|
exec (succ i) next (cb v) rest
|
||||||
| _ -> Lwt.fail Command_not_found
|
| _ -> Lwt.fail Command_not_found
|
||||||
in exec 1 params cb args
|
in exec 1 params handler args
|
||||||
|
|
||||||
(* Command dispatch tree *)
|
(* Command dispatch tree *)
|
||||||
type ('arg, 'ret) level =
|
type ('arg, 'ret) level =
|
||||||
{ stop : ('arg, 'ret) tcommand option ;
|
{ stop : ('arg, 'ret) command option ;
|
||||||
prefix : (string * ('arg, 'ret) tree) list }
|
prefix : (string * ('arg, 'ret) tree) list }
|
||||||
and ('arg, 'ret) param_level =
|
and ('arg, 'ret) param_level =
|
||||||
{ stop : ('arg, 'ret) tcommand option ;
|
{ stop : ('arg, 'ret) command option ;
|
||||||
tree : ('arg, 'ret) tree }
|
tree : ('arg, 'ret) tree }
|
||||||
and ('arg, 'ret) tree =
|
and ('arg, 'ret) tree =
|
||||||
| TPrefix of ('arg, 'ret) level
|
| TPrefix of ('arg, 'ret) level
|
||||||
| TParam of ('arg, 'ret) param_level
|
| TParam of ('arg, 'ret) param_level
|
||||||
| TStop of ('arg, 'ret) tcommand
|
| TStop of ('arg, 'ret) command
|
||||||
| TMore of ('arg, 'ret) tcommand
|
| TMore of ('arg, 'ret) command
|
||||||
| TEmpty
|
| TEmpty
|
||||||
|
|
||||||
let insert_in_dispatch_tree
|
let insert_in_dispatch_tree
|
||||||
(type arg) (type ret)
|
(type arg) (type ret)
|
||||||
root (Command (params, _, _, _, _, _) as command) =
|
root (Command { params } as command) =
|
||||||
let rec insert_tree
|
let rec insert_tree
|
||||||
: type a. (arg, ret) tree -> (a, arg, ret) tparams -> (arg, ret) tree
|
: type a. (arg, ret) tree -> (a, arg, ret) params -> (arg, ret) tree
|
||||||
= fun t c -> match t, c with
|
= fun t c -> match t, c with
|
||||||
| TEmpty, Stop -> TStop command
|
| TEmpty, Stop -> TStop command
|
||||||
| TEmpty, More -> TMore command
|
| TEmpty, More -> TMore command
|
||||||
@ -189,7 +175,7 @@ let tree_dispatch tree last args =
|
|||||||
in
|
in
|
||||||
loop (tree, args)
|
loop (tree, args)
|
||||||
|
|
||||||
let inline_tree_dispatch tree last =
|
let inline_tree_dispatch tree () =
|
||||||
let state = ref (tree, []) in
|
let state = ref (tree, []) in
|
||||||
fun arg -> match !state, arg with
|
fun arg -> match !state, arg with
|
||||||
| (( TStop c |
|
| (( TStop c |
|
||||||
@ -198,7 +184,7 @@ let inline_tree_dispatch tree last =
|
|||||||
TParam { stop = Some c}), acc),
|
TParam { stop = Some c}), acc),
|
||||||
`End ->
|
`End ->
|
||||||
state := (TEmpty, []) ;
|
state := (TEmpty, []) ;
|
||||||
`Res (exec c last (List.rev acc))
|
`Res (fun last -> exec c last (List.rev acc))
|
||||||
| (TMore c, acc), `Arg n ->
|
| (TMore c, acc), `Arg n ->
|
||||||
state := (TMore c, n :: acc) ;
|
state := (TMore c, n :: acc) ;
|
||||||
`Nop
|
`Nop
|
||||||
@ -207,15 +193,15 @@ let inline_tree_dispatch tree last =
|
|||||||
let t = List.assoc n prefix in
|
let t = List.assoc n prefix in
|
||||||
state := (t, n :: acc) ;
|
state := (t, n :: acc) ;
|
||||||
begin match t with
|
begin match t with
|
||||||
| TStop (Command (_, _, _, _, _, args))
|
| TStop (Command { args })
|
||||||
| TMore (Command (_, _, _, _, _, args)) -> `Args args
|
| TMore (Command { args }) -> `Args args
|
||||||
| _ -> `Nop end
|
| _ -> `Nop end
|
||||||
with Not_found -> `Fail Command_not_found end
|
with Not_found -> `Fail Command_not_found end
|
||||||
| (TParam { tree }, acc), `Arg n ->
|
| (TParam { tree }, acc), `Arg n ->
|
||||||
state := (tree, n :: acc) ;
|
state := (tree, n :: acc) ;
|
||||||
begin match tree with
|
begin match tree with
|
||||||
| TStop (Command (_, _, _, _, _, args))
|
| TStop (Command { args })
|
||||||
| TMore (Command (_, _, _, _, _, args)) -> `Args args
|
| TMore (Command { args }) -> `Args args
|
||||||
| _ -> `Nop end
|
| _ -> `Nop end
|
||||||
| _, _ -> `Fail Command_not_found
|
| _, _ -> `Fail Command_not_found
|
||||||
|
|
||||||
@ -232,13 +218,13 @@ let inline_dispatch commands =
|
|||||||
(* Command line help for a set of commands *)
|
(* Command line help for a set of commands *)
|
||||||
let usage
|
let usage
|
||||||
(type arg) (type ret)
|
(type arg) (type ret)
|
||||||
commands options =
|
~commands options =
|
||||||
let trim s = (* config-file wokaround *)
|
let trim s = (* config-file wokaround *)
|
||||||
Utils.split '\n' s |>
|
Utils.split '\n' s |>
|
||||||
List.map String.trim |>
|
List.map String.trim |>
|
||||||
String.concat "\n" in
|
String.concat "\n" in
|
||||||
let rec help
|
let rec help
|
||||||
: type a. Format.formatter -> (a, arg, ret) tparams -> unit
|
: type a. Format.formatter -> (a, arg, ret) params -> unit
|
||||||
= fun ppf -> function
|
= fun ppf -> function
|
||||||
| Stop -> ()
|
| Stop -> ()
|
||||||
| More -> Format.fprintf ppf "..."
|
| More -> Format.fprintf ppf "..."
|
||||||
@ -251,7 +237,7 @@ let usage
|
|||||||
| Param (n, "", _, next) -> Format.fprintf ppf "(%s) %a" n help next
|
| Param (n, "", _, next) -> Format.fprintf ppf "(%s) %a" n help next
|
||||||
| Param (_, desc, _, next) -> Format.fprintf ppf "(%s) %a" desc help next in
|
| Param (_, desc, _, next) -> Format.fprintf ppf "(%s) %a" desc help next in
|
||||||
let rec help_sum
|
let rec help_sum
|
||||||
: type a. Format.formatter -> (a, arg, ret) tparams -> unit
|
: type a. Format.formatter -> (a, arg, ret) params -> unit
|
||||||
= fun ppf -> function
|
= fun ppf -> function
|
||||||
| Stop -> ()
|
| Stop -> ()
|
||||||
| More -> Format.fprintf ppf "..."
|
| More -> Format.fprintf ppf "..."
|
||||||
@ -261,7 +247,7 @@ let usage
|
|||||||
| Prefix (n, next) -> Format.fprintf ppf "%s %a" n help_sum next
|
| Prefix (n, next) -> Format.fprintf ppf "%s %a" n help_sum next
|
||||||
| Param (n, _, _, next) -> Format.fprintf ppf "(%s) %a" n help_sum next in
|
| Param (n, _, _, next) -> Format.fprintf ppf "(%s) %a" n help_sum next in
|
||||||
let rec help_args
|
let rec help_args
|
||||||
: type a. Format.formatter -> (a, arg, ret) tparams -> unit
|
: type a. Format.formatter -> (a, arg, ret) params -> unit
|
||||||
= fun ppf -> function
|
= fun ppf -> function
|
||||||
| Stop -> ()
|
| Stop -> ()
|
||||||
| More -> Format.fprintf ppf "..."
|
| More -> Format.fprintf ppf "..."
|
||||||
@ -293,35 +279,28 @@ let usage
|
|||||||
| Rest _ -> "" in example opt) ;
|
| Rest _ -> "" in example opt) ;
|
||||||
if desc <> "" then
|
if desc <> "" then
|
||||||
Format.fprintf ppf "@, @[<hov>%a@]" Format.pp_print_text (trim desc) in
|
Format.fprintf ppf "@, @[<hov>%a@]" Format.pp_print_text (trim desc) in
|
||||||
let command_help ppf (Command (p, _, desc, _, _, options)) =
|
let command_help ppf (Command { params ; desc ; args }) =
|
||||||
let small = Format.asprintf "@[<h>%a@]" help p in
|
let small = Format.asprintf "@[<h>%a@]" help params in
|
||||||
let desc =
|
let desc = trim desc in
|
||||||
match desc with
|
|
||||||
| None -> "undocumented command"
|
|
||||||
| Some desc -> trim desc in
|
|
||||||
if String.length small < 50 then begin
|
if String.length small < 50 then begin
|
||||||
Format.fprintf ppf "@[<v 2>%s@,@[<hov>%a@]"
|
Format.fprintf ppf "@[<v 2>%s@,@[<hov>%a@]"
|
||||||
small Format.pp_print_text desc
|
small Format.pp_print_text desc
|
||||||
end else begin
|
end else begin
|
||||||
Format.fprintf ppf "@[<v 2>%a@,@[<hov 0>%a@]@,%a"
|
Format.fprintf ppf "@[<v 2>%a@,@[<hov 0>%a@]@,%a"
|
||||||
help_sum p
|
help_sum params
|
||||||
Format.pp_print_text desc
|
Format.pp_print_text desc
|
||||||
help_args p ;
|
help_args params ;
|
||||||
end ;
|
end ;
|
||||||
if options = [] then
|
if args = [] then
|
||||||
Format.fprintf ppf "@]"
|
Format.fprintf ppf "@]"
|
||||||
else
|
else
|
||||||
Format.fprintf ppf "@,%a@]"
|
Format.fprintf ppf "@,%a@]"
|
||||||
(Format.pp_print_list option_help)
|
(Format.pp_print_list option_help)
|
||||||
options in
|
args in
|
||||||
let rec group_help ppf (n, commands) =
|
let rec group_help ppf ({ title }, commands) =
|
||||||
let title =
|
|
||||||
match n with
|
|
||||||
| None -> "Miscellaneous commands"
|
|
||||||
| Some n -> group_title n in
|
|
||||||
Format.fprintf ppf "@[<v 2>%s:@,%a@]"
|
Format.fprintf ppf "@[<v 2>%s:@,%a@]"
|
||||||
title
|
title
|
||||||
(Format.pp_print_list command_help) !commands in
|
(Format.pp_print_list command_help) commands in
|
||||||
let usage ppf (by_group, options) =
|
let usage ppf (by_group, options) =
|
||||||
Format.fprintf ppf
|
Format.fprintf ppf
|
||||||
"@[<v>@[<v 2>Usage:@,%s [ options ] command [ command options ]@]@,\
|
"@[<v>@[<v 2>Usage:@,%s [ options ] command [ command options ]@]@,\
|
||||||
@ -331,49 +310,26 @@ let usage
|
|||||||
(Format.pp_print_list option_help) options
|
(Format.pp_print_list option_help) options
|
||||||
(Format.pp_print_list group_help) by_group in
|
(Format.pp_print_list group_help) by_group in
|
||||||
let by_group =
|
let by_group =
|
||||||
|
let ungrouped = ref [] in
|
||||||
|
let grouped =
|
||||||
List.fold_left
|
List.fold_left
|
||||||
(fun acc (Command (_, _, _, _, g, _) as c) ->
|
(fun acc (Command { group } as command) ->
|
||||||
|
match group with
|
||||||
|
| None ->
|
||||||
|
ungrouped := command :: !ungrouped ;
|
||||||
|
acc
|
||||||
|
| Some group ->
|
||||||
try
|
try
|
||||||
let r = List.assoc g acc in
|
let ({ title }, r) =
|
||||||
r := c :: !r ;
|
List.find (fun ({ name }, _) -> group.name = name) acc in
|
||||||
|
if title <> group.title then
|
||||||
|
invalid_arg "Cli_entries.usage: duplicate group name" ;
|
||||||
|
r := command :: !r ;
|
||||||
acc
|
acc
|
||||||
with Not_found ->
|
with Not_found ->
|
||||||
(g, ref [ c ]) :: acc)
|
(group, ref [ command ]) :: acc)
|
||||||
[] commands |> List.sort compare in
|
[] commands in
|
||||||
|
List.map (fun (g, c) -> (g, List.rev !c)) grouped @
|
||||||
|
[ { name = "untitled" ; title = "Miscellaneous commands" },
|
||||||
|
List.rev !ungrouped ] in
|
||||||
Format.asprintf "%a" usage (by_group, options)
|
Format.asprintf "%a" usage (by_group, options)
|
||||||
|
|
||||||
(* Pre-instanciated types *)
|
|
||||||
type 'a params = ('a, unit, unit) tparams
|
|
||||||
type command = (unit, unit) tcommand
|
|
||||||
|
|
||||||
let log_hook
|
|
||||||
: (string -> string -> unit Lwt.t) option ref
|
|
||||||
= ref None
|
|
||||||
|
|
||||||
let log channel msg =
|
|
||||||
match !log_hook with
|
|
||||||
| None -> Lwt.fail (Invalid_argument "Cli_entries.log: uninitialized hook")
|
|
||||||
| Some hook -> hook channel msg
|
|
||||||
|
|
||||||
let error fmt=
|
|
||||||
Format.kasprintf
|
|
||||||
(fun msg ->
|
|
||||||
Lwt.fail (Failure msg))
|
|
||||||
fmt
|
|
||||||
|
|
||||||
let warning fmt =
|
|
||||||
Format.kasprintf
|
|
||||||
(fun msg -> log "stderr" msg)
|
|
||||||
fmt
|
|
||||||
|
|
||||||
let message fmt =
|
|
||||||
Format.kasprintf
|
|
||||||
(fun msg -> log "stdout" msg)
|
|
||||||
fmt
|
|
||||||
|
|
||||||
let answer = message
|
|
||||||
|
|
||||||
let log name fmt =
|
|
||||||
Format.kasprintf
|
|
||||||
(fun msg -> log name msg)
|
|
||||||
fmt
|
|
||||||
|
@ -14,61 +14,66 @@ exception Command_not_found
|
|||||||
exception Bad_argument of int * string * string
|
exception Bad_argument of int * string * string
|
||||||
exception Command_failed of string
|
exception Command_failed of string
|
||||||
|
|
||||||
type 'a params
|
type ('a, 'arg, 'ret) params
|
||||||
type command
|
type ('arg, 'ret) command
|
||||||
|
|
||||||
and desc = string
|
|
||||||
and group = string
|
|
||||||
and tag = string
|
|
||||||
|
|
||||||
val param:
|
val param:
|
||||||
name: string ->
|
name: string ->
|
||||||
desc: string ->
|
desc: string ->
|
||||||
(string -> 'a Lwt.t) -> 'b params -> ('a -> 'b) params
|
('arg -> string -> 'a Lwt.t) ->
|
||||||
val prefix: string -> 'a params -> 'a params
|
('b, 'arg, 'ret) params ->
|
||||||
val prefixes: string list -> 'a params -> 'a params
|
('a -> 'b, 'arg, 'ret) params
|
||||||
val string: string -> string -> 'a params -> (string -> 'a) params
|
val prefix:
|
||||||
val fixed: string list -> (unit -> unit Lwt.t) params
|
string ->
|
||||||
val stop: (unit -> unit Lwt.t) params
|
('a, 'arg, 'ret) params ->
|
||||||
|
('a, 'arg, 'ret) params
|
||||||
|
val prefixes:
|
||||||
|
string list ->
|
||||||
|
('a, 'arg, 'ret) params ->
|
||||||
|
('a, 'arg, 'ret) params
|
||||||
|
val fixed:
|
||||||
|
string list ->
|
||||||
|
('arg -> 'ret Lwt.t, 'arg, 'ret) params
|
||||||
|
val stop:
|
||||||
|
('arg -> 'ret Lwt.t, 'arg, 'ret) params
|
||||||
val seq:
|
val seq:
|
||||||
name: string ->
|
name: string ->
|
||||||
desc: string ->
|
desc: string ->
|
||||||
(string -> 'p Lwt.t) ->
|
('arg -> string -> 'p Lwt.t) ->
|
||||||
('p list -> unit -> unit Lwt.t) params
|
('p list -> 'arg -> 'ret Lwt.t, 'arg, 'ret) params
|
||||||
|
|
||||||
|
val string:
|
||||||
|
name: string ->
|
||||||
|
desc: string ->
|
||||||
|
('a, 'arg, 'ret) params ->
|
||||||
|
(string -> 'a, 'arg, 'ret) params
|
||||||
|
|
||||||
val seq_of_param:
|
val seq_of_param:
|
||||||
((unit -> unit Lwt.t) params ->
|
(('arg -> 'ret Lwt.t, 'arg, 'ret) params ->
|
||||||
('a -> unit -> unit Lwt.t) params) ->
|
('a -> 'arg -> 'ret Lwt.t, 'arg, 'ret) params) ->
|
||||||
('a list -> unit -> unit Lwt.t) params
|
('a list -> 'arg -> 'ret Lwt.t, 'arg, 'ret) params
|
||||||
|
|
||||||
|
type group =
|
||||||
|
{ name : string ;
|
||||||
|
title : string }
|
||||||
|
|
||||||
val command:
|
val command:
|
||||||
?desc:desc ->
|
|
||||||
?tags:tag list ->
|
|
||||||
?group: group ->
|
?group: group ->
|
||||||
?args: (Arg.key * Arg.spec * Arg.doc) list ->
|
?args: (Arg.key * Arg.spec * Arg.doc) list ->
|
||||||
'a params -> 'a -> command
|
desc: string ->
|
||||||
|
('a, 'arg, 'ret) params -> 'a -> ('arg, 'ret) command
|
||||||
val register_group: group -> group -> unit
|
|
||||||
val register_tag: tag -> string -> unit
|
|
||||||
|
|
||||||
val usage:
|
val usage:
|
||||||
command list -> (string * Arg.spec * string) list -> string
|
commands: ('arg, 'ret) command list ->
|
||||||
|
(string * Arg.spec * string) list -> string
|
||||||
|
|
||||||
val inline_dispatch:
|
val inline_dispatch:
|
||||||
command list ->
|
('arg, 'ret) command list -> unit ->
|
||||||
unit ->
|
[ `Arg of string | `End ] ->
|
||||||
[> `Arg of string | `End ] ->
|
[ `Args of (Arg.key * Arg.spec * Arg.doc) list
|
||||||
[> `Args of (Arg.key * Arg.spec * Arg.doc) list
|
|
||||||
| `Fail of exn
|
| `Fail of exn
|
||||||
| `Nop
|
| `Nop
|
||||||
| `Res of unit Lwt.t ]
|
| `Res of 'arg -> 'ret Lwt.t ]
|
||||||
|
|
||||||
val dispatch:
|
val dispatch:
|
||||||
command list -> unit -> string list -> unit Lwt.t
|
('arg, 'ret) command list -> 'arg -> string list -> 'ret Lwt.t
|
||||||
|
|
||||||
val log_hook : (string -> string -> unit Lwt.t) option ref
|
|
||||||
|
|
||||||
val error : ('a, Format.formatter, unit, 'b Lwt.t) format4 -> 'a
|
|
||||||
val warning : ('a, Format.formatter, unit, unit Lwt.t) format4 -> 'a
|
|
||||||
val message : ('a, Format.formatter, unit, unit Lwt.t) format4 -> 'a
|
|
||||||
val answer : ('a, Format.formatter, unit, unit Lwt.t) format4 -> 'a
|
|
||||||
val log : string -> ('a, Format.formatter, unit, unit Lwt.t) format4 -> 'a
|
|
||||||
|
@ -224,7 +224,7 @@ module Make_Blake2B (R : sig
|
|||||||
conv to_b48check (Data_encoding.Json.wrap_error of_b48check) string)
|
conv to_b48check (Data_encoding.Json.wrap_error of_b48check) string)
|
||||||
|
|
||||||
let param ?(name=K.name) ?(desc=K.title) t =
|
let param ?(name=K.name) ?(desc=K.title) t =
|
||||||
Cli_entries.param ~name ~desc (fun str -> Lwt.return (of_b48check str)) t
|
Cli_entries.param ~name ~desc (fun _ str -> Lwt.return (of_b48check str)) t
|
||||||
|
|
||||||
let pp ppf t =
|
let pp ppf t =
|
||||||
Format.pp_print_string ppf (to_b48check t)
|
Format.pp_print_string ppf (to_b48check t)
|
||||||
|
@ -113,8 +113,8 @@ module Block_hash : sig
|
|||||||
val param :
|
val param :
|
||||||
?name:string ->
|
?name:string ->
|
||||||
?desc:string ->
|
?desc:string ->
|
||||||
'a Cli_entries.params ->
|
('a, 'arg, 'ret) Cli_entries.params ->
|
||||||
(t -> 'a) Cli_entries.params
|
(t -> 'a, 'arg, 'ret) Cli_entries.params
|
||||||
end
|
end
|
||||||
|
|
||||||
module Block_hash_set : module type of Hash_set (Block_hash)
|
module Block_hash_set : module type of Hash_set (Block_hash)
|
||||||
|
@ -85,6 +85,7 @@ module Client = struct
|
|||||||
module Revelation = Make(struct let name = "client.revealation" end)
|
module Revelation = Make(struct let name = "client.revealation" end)
|
||||||
module Denunciation = Make(struct let name = "client.denunciation" end)
|
module Denunciation = Make(struct let name = "client.denunciation" end)
|
||||||
end
|
end
|
||||||
|
module Webclient = Make(struct let name = "webclient" end)
|
||||||
|
|
||||||
let default_logger () =
|
let default_logger () =
|
||||||
Lwt_log.channel ~close_mode:`Keep ~channel:Lwt_io.stderr ()
|
Lwt_log.channel ~close_mode:`Keep ~channel:Lwt_io.stderr ()
|
||||||
|
@ -44,6 +44,7 @@ module Client : sig
|
|||||||
module Revelation : LOG
|
module Revelation : LOG
|
||||||
module Denunciation : LOG
|
module Denunciation : LOG
|
||||||
end
|
end
|
||||||
|
module Webclient : LOG
|
||||||
|
|
||||||
module Make(S: sig val name: string end) : LOG
|
module Make(S: sig val name: string end) : LOG
|
||||||
|
|
||||||
|
199
src/webclient_main.ml
Normal file
199
src/webclient_main.ml
Normal file
@ -0,0 +1,199 @@
|
|||||||
|
(**************************************************************************)
|
||||||
|
(* *)
|
||||||
|
(* Copyright (c) 2014 - 2016. *)
|
||||||
|
(* Dynamic Ledger Solutions, Inc. <contact@tezos.com> *)
|
||||||
|
(* *)
|
||||||
|
(* All rights reserved. No warranty, explicit or implicit, provided. *)
|
||||||
|
(* *)
|
||||||
|
(**************************************************************************)
|
||||||
|
|
||||||
|
(* Tezos Command line interface - Main Program *)
|
||||||
|
|
||||||
|
open Lwt.Infix
|
||||||
|
open Logging.Webclient
|
||||||
|
|
||||||
|
let make_context () =
|
||||||
|
let buffers = Hashtbl.create 50 in
|
||||||
|
Hashtbl.add buffers "stdout" (Buffer.create 1000) ;
|
||||||
|
Hashtbl.add buffers "stderr" (Buffer.create 1000) ;
|
||||||
|
let log channel msg =
|
||||||
|
let buffer =
|
||||||
|
try Hashtbl.find buffers channel with
|
||||||
|
Not_found ->
|
||||||
|
let buffer = Buffer.create 1000 in
|
||||||
|
Hashtbl.add buffers channel buffer ;
|
||||||
|
buffer in
|
||||||
|
Buffer.add_string buffer msg ;
|
||||||
|
Buffer.add_char buffer '\n' ;
|
||||||
|
Lwt.return () in
|
||||||
|
Client_commands.make_context log,
|
||||||
|
(fun () ->
|
||||||
|
Hashtbl.fold
|
||||||
|
(fun channel buffer acc ->
|
||||||
|
(channel, Buffer.contents buffer) :: acc)
|
||||||
|
buffers [])
|
||||||
|
|
||||||
|
let block_protocol cctxt block =
|
||||||
|
Lwt.catch
|
||||||
|
(fun () ->
|
||||||
|
Client_node_rpcs.Blocks.protocol cctxt block)
|
||||||
|
(fun _ ->
|
||||||
|
cctxt.Client_commands.message
|
||||||
|
"\n\
|
||||||
|
The connection to the RPC server failed, \
|
||||||
|
using the default protocol version.\n" >>= fun () ->
|
||||||
|
Lwt.return Client_bootstrap.Client_proto_main.protocol)
|
||||||
|
|
||||||
|
let eval_command argv =
|
||||||
|
let cctxt, result = make_context () in
|
||||||
|
Lwt.catch
|
||||||
|
(fun () ->
|
||||||
|
Client_config.preparse_args argv cctxt >>= fun block ->
|
||||||
|
block_protocol cctxt block >>= fun version ->
|
||||||
|
let commands =
|
||||||
|
Client_generic_rpcs.commands @
|
||||||
|
Client_keys.commands () @
|
||||||
|
Client_protocols.commands () @
|
||||||
|
Client_helpers.commands () @
|
||||||
|
Client_commands.commands_for_version version in
|
||||||
|
Client_config.parse_args ~version
|
||||||
|
(Cli_entries.usage ~commands)
|
||||||
|
(Cli_entries.inline_dispatch commands)
|
||||||
|
argv cctxt >>= fun command ->
|
||||||
|
command cctxt >>= fun () ->
|
||||||
|
Lwt.return (Ok (result ())))
|
||||||
|
(fun exn ->
|
||||||
|
let msg = match exn with
|
||||||
|
| Arg.Help help ->
|
||||||
|
Format.asprintf "%s%!" help
|
||||||
|
| Arg.Bad help ->
|
||||||
|
Format.asprintf "%s%!" help
|
||||||
|
| Cli_entries.Command_not_found ->
|
||||||
|
Format.asprintf "Unkonwn command, try `-help`.\n%!"
|
||||||
|
| Client_commands.Version_not_found ->
|
||||||
|
Format.asprintf "Unkonwn protocol version, try `list versions`.\n%!"
|
||||||
|
| Cli_entries.Bad_argument (idx, _n, v) ->
|
||||||
|
Format.asprintf "There's a problem with argument %d, %s.\n%!" idx v
|
||||||
|
| Cli_entries.Command_failed message ->
|
||||||
|
Format.asprintf "Command failed, %s.\n%!" message
|
||||||
|
| Failure msg ->
|
||||||
|
Format.asprintf "Fatal error: %s\n%!" msg
|
||||||
|
| exn ->
|
||||||
|
Format.asprintf "Fatal internal error: %s\n%!" (Printexc.to_string exn) in
|
||||||
|
let result =
|
||||||
|
result () in
|
||||||
|
let stderr =
|
||||||
|
List.assoc "stderr" result in
|
||||||
|
let stderr =
|
||||||
|
if stderr = ""
|
||||||
|
|| String.get stderr (String.length stderr - 1) = '\n' then
|
||||||
|
msg
|
||||||
|
else
|
||||||
|
stderr ^ "\n" ^ msg in
|
||||||
|
let result =
|
||||||
|
("stderr", stderr)::
|
||||||
|
List.filter (fun (n, _) -> n <> "stderr") result in
|
||||||
|
Lwt.return (Error result))
|
||||||
|
|
||||||
|
module ConnectionMap = Map.Make(Cohttp.Connection)
|
||||||
|
|
||||||
|
exception Invalid_method
|
||||||
|
exception Cannot_parse_body of string
|
||||||
|
|
||||||
|
let root =
|
||||||
|
let input, output =
|
||||||
|
let open Data_encoding in
|
||||||
|
(obj1 (req "command" string)),
|
||||||
|
(obj1 (req "outputs" (assoc string))) in
|
||||||
|
let root =
|
||||||
|
RPC.empty in
|
||||||
|
let root =
|
||||||
|
RPC.register0 root
|
||||||
|
(RPC.service ~input ~output RPC.Path.(root / "command"))
|
||||||
|
(fun command ->
|
||||||
|
let argv = Array.of_list (Utils.split ' ' command) in
|
||||||
|
eval_command argv >>= function
|
||||||
|
| Ok output | Error output ->
|
||||||
|
RPC.Answer.return output) in
|
||||||
|
let root =
|
||||||
|
RPC.register_dynamic_directory1 root
|
||||||
|
RPC.Path.(root / "block" /: Node_rpc_services.Blocks.blocks_arg)
|
||||||
|
(fun block ->
|
||||||
|
Client_node_rpcs.Blocks.protocol Client_commands.ignore_context block >>= fun version ->
|
||||||
|
let directory = Webclient_version.find_contextual_services version in
|
||||||
|
let directory = RPC.map (fun ((), block) -> block) directory in
|
||||||
|
Lwt.return directory) in
|
||||||
|
root
|
||||||
|
|
||||||
|
let find_static_file path =
|
||||||
|
let path = OCamlRes.Path.of_string path in
|
||||||
|
let index path = match path with
|
||||||
|
| ([], None) -> ([], Some ("index", Some "html"))
|
||||||
|
| oth -> oth in
|
||||||
|
match path with
|
||||||
|
| ("block" :: block :: path, file) ->
|
||||||
|
let path = index (path, file) in
|
||||||
|
(match Node_rpc_services.Blocks.parse_block block with
|
||||||
|
| Ok block ->
|
||||||
|
block_protocol Client_commands.ignore_context block >>= fun version ->
|
||||||
|
Lwt.return
|
||||||
|
(try
|
||||||
|
let root =
|
||||||
|
Webclient_version.find_contextual_static_files version in
|
||||||
|
Some (OCamlRes.Res.find path root)
|
||||||
|
with Not_found -> None)
|
||||||
|
| Error _ -> Lwt.return None)
|
||||||
|
| _ ->
|
||||||
|
Lwt.return
|
||||||
|
(try
|
||||||
|
Some (OCamlRes.Res.find (index path) Webclient_static.root)
|
||||||
|
with Not_found -> None)
|
||||||
|
|
||||||
|
let http_proxy port =
|
||||||
|
let pre_hook path =
|
||||||
|
find_static_file path >>= function
|
||||||
|
| Some body ->
|
||||||
|
Lwt.return { RPC.Answer.code = 200 ; body = RPC.Answer.Single body }
|
||||||
|
| None ->
|
||||||
|
Lwt.return { RPC.Answer.code = 404 ; body = RPC.Answer.Empty } in
|
||||||
|
let post_hook _ =
|
||||||
|
(find_static_file "not_found.html" >>= function
|
||||||
|
| Some body ->
|
||||||
|
Lwt.return (RPC.Answer.Single body)
|
||||||
|
| None ->
|
||||||
|
Lwt.return (RPC.Answer.Empty)) >>= fun body ->
|
||||||
|
Lwt.return { RPC.Answer.code = 404 ; body } in
|
||||||
|
RPC_server.launch ~pre_hook ~post_hook port root
|
||||||
|
|
||||||
|
let web_port = Client_config.in_both_groups @@
|
||||||
|
new Config_file.int_cp [ "web" ; "port" ] 8080
|
||||||
|
"The TCP port to point the web browser to."
|
||||||
|
|
||||||
|
(* Where all the user friendliness starts *)
|
||||||
|
let () =
|
||||||
|
Pervasives.exit @@ Lwt_main.run
|
||||||
|
(Lwt.catch
|
||||||
|
(fun () ->
|
||||||
|
Client_config.parse_args
|
||||||
|
(Cli_entries.usage ~commands: [])
|
||||||
|
(fun () -> function
|
||||||
|
| `Arg arg -> raise (Arg.Bad ("unexpected argument " ^ arg))
|
||||||
|
| `End -> `Res (fun () -> Lwt.return ()))
|
||||||
|
Sys.argv Client_commands.ignore_context>>= fun _no_command ->
|
||||||
|
Random.self_init () ;
|
||||||
|
Sodium.Random.stir () ;
|
||||||
|
http_proxy web_port#get >>= fun _server ->
|
||||||
|
fst (Lwt.wait ()))
|
||||||
|
(function
|
||||||
|
| Arg.Help help ->
|
||||||
|
Format.eprintf "%s%!" help ;
|
||||||
|
Lwt.return 0
|
||||||
|
| Arg.Bad help ->
|
||||||
|
Format.eprintf "%s%!" help ;
|
||||||
|
Lwt.return 1
|
||||||
|
| Failure msg ->
|
||||||
|
Format.eprintf "Fatal error: %s\n%!" msg ;
|
||||||
|
Lwt.return 1
|
||||||
|
| exn ->
|
||||||
|
Format.eprintf "Fatal internal error: %s\n%!" (Printexc.to_string exn) ;
|
||||||
|
Lwt.return 1))
|
38
src/webclient_static/index.html
Normal file
38
src/webclient_static/index.html
Normal file
@ -0,0 +1,38 @@
|
|||||||
|
<!doctype html>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<title>Tezos Web Client</title>
|
||||||
|
<meta charset="utf-8" />
|
||||||
|
<script src="//code.jquery.com/jquery-2.1.0.min.js"></script>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<h1>Tezos Web client</h1>
|
||||||
|
<pre id="console"></pre>
|
||||||
|
<br/>
|
||||||
|
<form id="form">
|
||||||
|
./tezos-client <input type="text" name="command" id="command">
|
||||||
|
<input type="submit" value="RUN">
|
||||||
|
</form>
|
||||||
|
<script>
|
||||||
|
$('#form').on('submit', function(e) {
|
||||||
|
e.preventDefault();
|
||||||
|
$.ajax ({
|
||||||
|
url: '/command',
|
||||||
|
method: 'POST',
|
||||||
|
contentType: 'application/json',
|
||||||
|
dataType: 'json',
|
||||||
|
data: JSON.stringify({ command : './tezos-client ' + $('#command')[0].value }),
|
||||||
|
processData: false
|
||||||
|
}).done (function ({ outputs }) {
|
||||||
|
let stdout = document.createElement ("span");
|
||||||
|
stdout.appendChild (document.createTextNode (outputs.stdout));
|
||||||
|
let stderr = document.createElement ("span");
|
||||||
|
stderr.appendChild (document.createTextNode (outputs.stderr));
|
||||||
|
stderr.style.color = "darkred";
|
||||||
|
$('#console')[0].appendChild (stdout);
|
||||||
|
$('#console')[0].appendChild (stderr);
|
||||||
|
})
|
||||||
|
})
|
||||||
|
</script>
|
||||||
|
</body>
|
||||||
|
</html>
|
10
src/webclient_static/not_found.html
Normal file
10
src/webclient_static/not_found.html
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
<!doctype html>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<title>Tezos Web Client</title>
|
||||||
|
<meta charset="utf-8" />
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<h1>Not Found</h1>
|
||||||
|
</body>
|
||||||
|
</html>
|
@ -214,7 +214,6 @@ COVERAGESRCDIR= \
|
|||||||
-I ../src/client/embedded \
|
-I ../src/client/embedded \
|
||||||
-I ../src/client/embedded/bootstrap \
|
-I ../src/client/embedded/bootstrap \
|
||||||
-I ../src/client/embedded/bootstrap/mining \
|
-I ../src/client/embedded/bootstrap/mining \
|
||||||
-I ../src/client/embedded/bootstrap/demo \
|
|
||||||
-I ../src/compiler \
|
-I ../src/compiler \
|
||||||
-I ../src/node \
|
-I ../src/node \
|
||||||
-I ../src/node/db \
|
-I ../src/node/db \
|
||||||
|
@ -14,7 +14,9 @@ open Error_monad
|
|||||||
open Hash
|
open Hash
|
||||||
|
|
||||||
let () =
|
let () =
|
||||||
Random.self_init () ;
|
Random.self_init ()
|
||||||
|
|
||||||
|
let cctxt =
|
||||||
let log channel msg = match channel with
|
let log channel msg = match channel with
|
||||||
| "stdout" ->
|
| "stdout" ->
|
||||||
print_endline msg ;
|
print_endline msg ;
|
||||||
@ -23,7 +25,7 @@ let () =
|
|||||||
prerr_endline msg ;
|
prerr_endline msg ;
|
||||||
Lwt.return ()
|
Lwt.return ()
|
||||||
| _ -> Lwt.return () in
|
| _ -> Lwt.return () in
|
||||||
Cli_entries.log_hook := Some log
|
Client_commands.make_context log
|
||||||
|
|
||||||
let should_fail f t =
|
let should_fail f t =
|
||||||
t >>= function
|
t >>= function
|
||||||
@ -74,7 +76,7 @@ type account = {
|
|||||||
}
|
}
|
||||||
|
|
||||||
let bootstrap_accounts () =
|
let bootstrap_accounts () =
|
||||||
Client_proto_rpcs.Constants.bootstrap `Genesis
|
Client_proto_rpcs.Constants.bootstrap cctxt `Genesis
|
||||||
>>= fun accounts ->
|
>>= fun accounts ->
|
||||||
let cpt = ref 0 in
|
let cpt = ref 0 in
|
||||||
Lwt.return
|
Lwt.return
|
||||||
@ -105,7 +107,7 @@ let transfer ?(block = `Prevalidation) ?(fee = 5L) ~src ~target amount =
|
|||||||
match amount with
|
match amount with
|
||||||
| Some x -> x
|
| Some x -> x
|
||||||
| None -> assert false in (* will be captured by the previous assert *)
|
| None -> assert false in (* will be captured by the previous assert *)
|
||||||
Client_proto_context.transfer
|
Client_proto_context.transfer cctxt
|
||||||
block
|
block
|
||||||
~source:src.contract
|
~source:src.contract
|
||||||
~src_pk:src.public_key
|
~src_pk:src.public_key
|
||||||
@ -114,7 +116,7 @@ let transfer ?(block = `Prevalidation) ?(fee = 5L) ~src ~target amount =
|
|||||||
~amount ~fee ()
|
~amount ~fee ()
|
||||||
|
|
||||||
let check_balance ?(block = `Prevalidation) account expected =
|
let check_balance ?(block = `Prevalidation) account expected =
|
||||||
Client_proto_rpcs.Context.Contract.balance
|
Client_proto_rpcs.Context.Contract.balance cctxt
|
||||||
block account.contract >>=? fun balance ->
|
block account.contract >>=? fun balance ->
|
||||||
let balance = Tez.to_cents balance in
|
let balance = Tez.to_cents balance in
|
||||||
Assert.equal_int64 ~msg:__LOC__ expected balance ;
|
Assert.equal_int64 ~msg:__LOC__ expected balance ;
|
||||||
@ -122,9 +124,9 @@ let check_balance ?(block = `Prevalidation) account expected =
|
|||||||
|
|
||||||
let mine contract =
|
let mine contract =
|
||||||
let block = `Head 0 in
|
let block = `Head 0 in
|
||||||
Client_proto_rpcs.Context.level block >>=? fun level ->
|
Client_proto_rpcs.Context.level cctxt block >>=? fun level ->
|
||||||
let seed_nonce = Client_mining_forge.generate_seed_nonce () in
|
let seed_nonce = Client_mining_forge.generate_seed_nonce () in
|
||||||
Client_mining_forge.forge_block
|
Client_mining_forge.forge_block cctxt
|
||||||
~timestamp:(Time.now ()) ~seed_nonce ~src_sk:contract.secret_key
|
~timestamp:(Time.now ()) ~seed_nonce ~src_sk:contract.secret_key
|
||||||
block contract.public_key_hash >>=? fun block_hash ->
|
block contract.public_key_hash >>=? fun block_hash ->
|
||||||
return ()
|
return ()
|
||||||
|
Loading…
Reference in New Issue
Block a user