diff --git a/multisig/.gitignore b/multisig/.gitignore new file mode 100644 index 000000000..e108c569c --- /dev/null +++ b/multisig/.gitignore @@ -0,0 +1,3 @@ +kompile_tool/k +kompile_tool/k.old +bazel-* diff --git a/multisig/BUILD b/multisig/BUILD new file mode 100644 index 000000000..e69de29bb diff --git a/multisig/WORKSPACE.bazel b/multisig/WORKSPACE.bazel new file mode 100644 index 000000000..e69de29bb diff --git a/multisig/kompile_tool/BUILD b/multisig/kompile_tool/BUILD new file mode 100644 index 000000000..eda341114 --- /dev/null +++ b/multisig/kompile_tool/BUILD @@ -0,0 +1,63 @@ +sh_binary( + name = "kompile_tool", + srcs = ["kompile.sh"], + deps = [":k_release"], + data = [":k_release"], + visibility = ["//visibility:public"], +) + +sh_binary( + name = "kompile_e_tool", + srcs = ["kompile-e.sh"], + deps = [":k_release"], + data = [":k_release"], + visibility = ["//visibility:public"], +) + +sh_binary( + name = "kprove_tool", + srcs = ["kprove.sh"], + deps = [":k_release"], + data = [":k_release"], + visibility = ["//visibility:public"], +) + +sh_binary( + name = "kprove_kompile_tool", + srcs = ["kprove-kompile.sh"], + deps = [":k_release"], + data = [":k_release"], + visibility = ["//visibility:public"], +) + +sh_binary( + name = "kore_tool", + srcs = ["kore.sh"], + deps = [":k_release"], + data = [":k_release"], + visibility = ["//visibility:public"], +) + +sh_binary( + name = "ktrusted_tool", + srcs = ["make-trusted.py"], + visibility = ["//visibility:public"], +) + +sh_binary( + name = "kmerge_tool", + srcs = ["kmerge.sh"], + visibility = ["//visibility:public"], +) + +sh_library( + name = "k_release", + data = glob(["k/**"]), + visibility = ["//visibility:public"], +) + +sh_library( + name = "kast_script", + srcs = ["kast.kscript"], + visibility = ["//visibility:public"], +) diff --git a/multisig/kompile_tool/kast.kscript b/multisig/kompile_tool/kast.kscript new file mode 100644 index 000000000..e337c2470 --- /dev/null +++ b/multisig/kompile_tool/kast.kscript @@ -0,0 +1,18 @@ +alias kclaim = claim | kast -i kore -o pretty -d . /dev/stdin +alias kclaim-d x = claim | kast -i kore -o pretty -d x /dev/stdin +alias kclaim-n x = claim x | kast -i kore -o pretty -d . /dev/stdin +alias kclaim-nd x y = claim x | kast -i kore -o pretty -d y /dev/stdin +alias kaxiom x = axiom x | kast -i kore -o pretty -d . /dev/stdin +alias kaxiom-d x y = axiom x | kast -i kore -o pretty -d y /dev/stdin +alias konfig = config | kast -i kore -o pretty -d . /dev/stdin +alias konfig-d x = config | kast -i kore -o pretty -d x /dev/stdin +alias konfig-n x = config x | kast -i kore -o pretty -d . /dev/stdin +alias konfig-nd x y = config x | kast -i kore -o pretty -d y /dev/stdin +alias ktry x = try x | kast -i kore -o pretty -d . /dev/stdin +alias ktry-d x y = try x | kast -i kore -o pretty -d y /dev/stdin +alias ktryf x = tryf x | kast -i kore -o pretty -d . /dev/stdin +alias ktryf-d x y = tryf x | kast -i kore -o pretty -d y /dev/stdin +alias krule = rule | kast -i kore -o pretty -d . /dev/stdin +alias krule-d x = rule | kast -i kore -o pretty -d x /dev/stdin +alias krule-n x = rule x | kast -i kore -o pretty -d . /dev/stdin +alias krule-nd x y = rule x | kast -i kore -o pretty -d y /dev/stdin diff --git a/multisig/kompile_tool/kmerge.sh b/multisig/kompile_tool/kmerge.sh new file mode 100755 index 000000000..bb6785021 --- /dev/null +++ b/multisig/kompile_tool/kmerge.sh @@ -0,0 +1,18 @@ +#!/usr/bin/env bash + +set -e + +OUTPUT=$1 +shift + +FIRST=$1 +shift + +cat $FIRST | sed 's/^.*\/\/@ Bazel remove\s*$/\/\/ Removed by Bazel + kmerge./' > $OUTPUT +echo >> $OUTPUT + +for f in "$@" +do + cat "$f" | sed 's/^.*\/\/@ Bazel remove\s*$/\/\/ Removed by Bazel + kmerge./' >> $OUTPUT + echo >> $OUTPUT +done diff --git a/multisig/kompile_tool/kompile-e.sh b/multisig/kompile_tool/kompile-e.sh new file mode 100755 index 000000000..8988ce6f6 --- /dev/null +++ b/multisig/kompile_tool/kompile-e.sh @@ -0,0 +1,8 @@ +#!/usr/bin/env bash + +set -e + +PARENT_DIR=`dirname $0` + +KOMPILE=$PARENT_DIR/kompile_e_tool.runfiles/__main__/kompile_tool/k/bin/kompile +$KOMPILE --backend haskell -I `pwd` -E "$@" > /dev/null diff --git a/multisig/kompile_tool/kompile.sh b/multisig/kompile_tool/kompile.sh new file mode 100755 index 000000000..cce0ea7f3 --- /dev/null +++ b/multisig/kompile_tool/kompile.sh @@ -0,0 +1,12 @@ +#!/usr/bin/env bash + +set -e + +PARENT_DIR=`dirname $0` + +OUTPUT_DIR=`dirname $1` +OUTPUT_DIR=`dirname $OUTPUT_DIR` +shift + +KOMPILE=$PARENT_DIR/kompile_tool.runfiles/__main__/kompile_tool/k/bin/kompile +$KOMPILE --backend haskell -I `pwd` --directory $OUTPUT_DIR "$@" diff --git a/multisig/kompile_tool/kore.sh b/multisig/kompile_tool/kore.sh new file mode 100755 index 000000000..eab912a83 --- /dev/null +++ b/multisig/kompile_tool/kore.sh @@ -0,0 +1,59 @@ +#!/usr/bin/env bash + +set -e + +SPEC_MODULE_NAME=$1 +shift + +KOMPILE_DIR=`dirname $1` +shift + +DEFINITION=$(realpath $1) +shift + +SPEC=$(realpath $1) +shift + +COMMAND=$1 +shift + +OUTPUT=$(realpath $1) +shift + +BREADTH=$1 +shift + +MODULE_NAME=$(cat $COMMAND | sed 's/^.*--module \([^ ]*\) .*$/\1/') + +# SPEC_MODULE_NAME=$(cat $COMMAND | sed 's/^.*--spec-module \([^ ]*\) .*$/\1/') + +KOMPILE_TOOL_DIR=kompile_tool + +REPL_SCRIPT=$(realpath $KOMPILE_TOOL_DIR/kast.kscript) + +KORE_EXEC="$(realpath $KOMPILE_TOOL_DIR/k/bin/kore-exec) --breadth $BREADTH" +KORE_REPL="$(realpath $KOMPILE_TOOL_DIR/k/bin/kore-repl) --repl-script $REPL_SCRIPT" + +BACKEND_COMMAND=$KORE_EXEC +if [ $# -eq 0 ]; then + BACKEND_COMMAND=$KORE_EXEC +else + if [ "$1" == "--debug" ]; then + BACKEND_COMMAND=$KORE_REPL + else + echo "Unknown argument: '$1'" + exit 1 + fi +fi + +PATH=$(realpath $KOMPILE_TOOL_DIR/k/bin):$PATH + +cd $(dirname $KOMPILE_DIR) + +$BACKEND_COMMAND \ + --smt-timeout 4000 \ + $DEFINITION \ + --prove $SPEC \ + --module $MODULE_NAME \ + --spec-module $SPEC_MODULE_NAME \ + --output $OUTPUT diff --git a/multisig/kompile_tool/kprove-kompile.sh b/multisig/kompile_tool/kprove-kompile.sh new file mode 100755 index 000000000..36764022e --- /dev/null +++ b/multisig/kompile_tool/kprove-kompile.sh @@ -0,0 +1,61 @@ +#!/usr/bin/env bash + +set -e + +KOMPILE_DIR=`dirname $1` +shift + +ORIGINAL_FILE=$1 +shift + +PROOF_FILE=$(realpath $1) +shift + +SPEC_OUTPUT=$1 +shift + +DEFINITION_OUTPUT=$1 +shift + +COMMAND_OUTPUT=$1 +shift + +KOMPILE_OUTPUT=$(dirname $1) +shift + +MODULE_NAME=$(basename "$ORIGINAL_FILE" | sed 's/\.[^\.]*$//' | tr [:lower:] [:upper:]) + +KOMPILE_TOOL_DIR=kompile_tool + +KPROVE=$(realpath $KOMPILE_TOOL_DIR/k/bin/kprove) + +TMP_DIR=$(mktemp -d) +trap 'rm -rf -- "$TMP_DIR"' EXIT + +cp -rL $KOMPILE_DIR $TMP_DIR +chmod -R a+w $TMP_DIR/* + +pushd $TMP_DIR > /dev/null + +nice -n 10 \ +$KPROVE \ + --spec-module "$MODULE_NAME" \ + --dry-run \ + "$PROOF_FILE" > output + +SPEC_FILE=$(cat output | grep kore-exec | sed 's/^.*--prove \([^ ]*\) .*$/\1/') +COMMAND=$(cat output | grep kore-exec) + +popd > /dev/null + +cp $SPEC_FILE $SPEC_OUTPUT + +DEFINITION_FILE=$(dirname $SPEC_FILE)/vdefinition.kore + +cp $DEFINITION_FILE $DEFINITION_OUTPUT + +echo $COMMAND > $COMMAND_OUTPUT + +mkdir -p $KOMPILE_OUTPUT + +cp $TMP_DIR/$(basename $KOMPILE_DIR)/* $KOMPILE_OUTPUT diff --git a/multisig/kompile_tool/kprove.sh b/multisig/kompile_tool/kprove.sh new file mode 100755 index 000000000..63a9ed0d4 --- /dev/null +++ b/multisig/kompile_tool/kprove.sh @@ -0,0 +1,60 @@ +#!/usr/bin/env bash + +set -e + +PARENT_DIR=$(dirname $0) + +KOMPILE_DIR=$(dirname $1) +shift + +TMP_DIR=$(mktemp -d) +trap 'rm -rf -- "$TMP_DIR"' EXIT + +ORIGINAL_FILE=$1 +shift + +PROOF_FILE=$(realpath $1) +shift + +BREADTH=$1 +shift + +#KOMPILE_PARENT = $(dirname $KOMPILE_DIR) +# +MODULE_NAME=$(basename "$ORIGINAL_FILE" | sed 's/\.[^\.]*$//' | tr [:lower:] [:upper:]) + +cp -rL $KOMPILE_DIR $TMP_DIR +chmod -R a+w $TMP_DIR/* + +KOMPILE_TOOL_DIR=kompile_tool + +KPROVE=$(realpath $KOMPILE_TOOL_DIR/k/bin/kprove) +REPL_SCRIPT=$(realpath $KOMPILE_TOOL_DIR/kast.kscript) + +#PROOF_FILE_PATH=$(realpath $PROOF_FILE) +#REPL_SCRIPT_PATH=$(realpath $REPL_SCRIPT) +# +KORE_EXEC="kore-exec --breadth $BREADTH" +KORE_REPL="kore-repl --repl-script $REPL_SCRIPT" + +BACKEND_COMMAND=$KORE_EXEC +if [ $# -eq 0 ]; then + BACKEND_COMMAND=$KORE_EXEC +else + if [ "$1" == "--debug" ]; then + BACKEND_COMMAND=$KORE_REPL + else + echo "Unknown argument: '$1'" + exit 1 + fi +fi + +cd $TMP_DIR +echo $TMP_DIR + +$KPROVE \ + --haskell-backend-command "$BACKEND_COMMAND --smt-timeout 4000" \ + --spec-module "$MODULE_NAME" \ + "$PROOF_FILE" + +# --directory "$TMP_DIR" \ diff --git a/multisig/kompile_tool/make-trusted.py b/multisig/kompile_tool/make-trusted.py new file mode 100755 index 000000000..e2f125d0e --- /dev/null +++ b/multisig/kompile_tool/make-trusted.py @@ -0,0 +1,65 @@ +#!/usr/bin/env python3 +import sys + +def naturalNumbers(): + i = 1 + while True: + yield i + i += 1 + +DEFAULT = 0 +PROOF = 1 +TRUSTED = 2 + +def makeTrusted(file_name, lines): + state = DEFAULT + for (line_number, line) in lines: + normalized = line.strip() + if normalized.startswith('//@'): + if state == DEFAULT: + if normalized == '//@ proof': + state = PROOF + else: + raise Exception( + "Unexpected trusted directive, only '//@ proof' allowed here.\n%s:%d" + % (file_name, line_number)) + elif state == PROOF: + if normalized == '//@ trusted': + state = TRUSTED + else: + raise Exception( + "Unexpected trusted directive, only '//@ trusted' allowed here.\n%s:%d" + % (file_name, line_number)) + elif state == TRUSTED: + if normalized == '//@ end': + state = DEFAULT + else: + raise Exception( + "Unexpected trusted directive, only '//@ end' allowed here.\n%s:%d" + % (file_name, line_number)) + else: + if state == DEFAULT: + pass + else: + unindented = line.lstrip() + indentation = ' ' * (len(line) - len(unindented)) + if state == PROOF: + line = indentation + '// ' + unindented + elif state == TRUSTED: + if unindented.startswith('// '): + line = indentation + unindented[3:] + else: + raise Exception( + "Expected trusted lines to be commented.\n%s:%d" + % (file_name, line_number)) + yield line + +def main(argv): + if len(argv) != 2: + raise Exception('Wrong number of arguments, expected an input and an output file name.') + with open(argv[0], 'r') as f: + with open(argv[1], 'w') as g: + g.writelines(makeTrusted(argv[0], zip(naturalNumbers(), f))) + +if __name__ == '__main__': + main(sys.argv[1:]) diff --git a/multisig/kompile_tool/prepare-k.sh b/multisig/kompile_tool/prepare-k.sh new file mode 100755 index 000000000..851ea4ec0 --- /dev/null +++ b/multisig/kompile_tool/prepare-k.sh @@ -0,0 +1,9 @@ +#!/usr/bin/env bash + +KOMPILE=`which kompile` +BIN=`dirname $KOMPILE` +RELEASE=`dirname $BIN` + +mkdir k + +cp -r $RELEASE/* k diff --git a/multisig/proof.bzl b/multisig/proof.bzl new file mode 100644 index 000000000..0784abedf --- /dev/null +++ b/multisig/proof.bzl @@ -0,0 +1,385 @@ +KompileInfo = provider(fields=["files"]) +KtrustedInfo = provider(fields=["trusted"]) +KproveInfo = provider(fields=["spec", "definition", "command"]) + +def _kompile_impl(ctx): + output_files = [ + ctx.actions.declare_file(ctx.label.name + '-kompiled/' + name) + for name in [ + 'allRules.txt', 'cache.bin', 'compiled.bin', 'compiled.txt', + 'configVars.sh', 'definition.kore', 'macros.kore', 'mainModule.txt', + 'parsed.txt', 'syntaxDefinition.kore', 'timestamp'] + ] + if len(ctx.files.srcs) != 1: + fail + input_names = [output_files[0].path] + [s.path for s in ctx.files.srcs] + # TODO: Make this work if the file name is not based on the target name. + ctx.actions.run( + inputs=depset(ctx.files.srcs, transitive = [dep[DefaultInfo].files for dep in ctx.attr.deps]), + outputs=output_files, + arguments=input_names, + progress_message="Kompiling %s" % ctx.files.srcs[0].path, + executable=ctx.executable.kompile_tool) + + return [ + DefaultInfo( + files = depset( + output_files, + transitive = [dep[DefaultInfo].files for dep in ctx.attr.deps] + ), + ), + KompileInfo(files=output_files), + ] + +kompile = rule( + implementation = _kompile_impl, + attrs = { + "deps": attr.label_list(), + "srcs": attr.label_list(allow_files = [".k"]), + "kompile_tool": attr.label( + executable = True, + cfg = "exec", + allow_files = True, + default = Label("//kompile_tool"), + ), + }, + executable = False, +) + +def _klibrary_impl(ctx): + if len(ctx.files.srcs) != 1: + fail + input_names = [s.path for s in ctx.files.srcs] + output_dir = ctx.actions.declare_directory(ctx.label.name + '-kompiled') + # TODO: Make this work if the file name is not based on the target name. + ctx.actions.run( + inputs=depset(ctx.files.srcs, transitive = [dep[DefaultInfo].files for dep in ctx.attr.deps]), + outputs=[output_dir], + arguments=input_names, + progress_message="Checking %s" % ctx.files.srcs[0].path, + executable=ctx.executable.kompile_tool) + return [ + DefaultInfo( + files = depset(ctx.files.srcs + [ output_dir ], transitive = [dep[DefaultInfo].files for dep in ctx.attr.deps]), + ) + ] + +klibrary = rule( + implementation = _klibrary_impl, + attrs = { + "deps": attr.label_list(), + "srcs": attr.label_list(allow_files = [".k"]), + "kompile_tool": attr.label( + executable = True, + cfg = "exec", + allow_files = True, + default = Label("//kompile_tool:kompile_e_tool"), + ), + }, +) + +def _ktrusted_impl(ctx): + if len(ctx.files.srcs) != 1: + fail + + tmp_file = ctx.actions.declare_file(ctx.label.name + ".tmp.k") + ctx.actions.run( + inputs=depset(ctx.files.srcs), + outputs=[tmp_file], + arguments=[ctx.files.srcs[0].path, tmp_file.path], + progress_message="Trusting %s" % ctx.files.srcs[0].path, + executable=ctx.executable.ktrusted_tool) + + output_file = ctx.actions.declare_file(ctx.label.name + ".k") + all_trusted = [] + for dep in ctx.attr.trusted: + all_trusted += dep[KtrustedInfo].trusted + ctx.actions.run( + inputs=depset([tmp_file] + all_trusted), + outputs=[output_file], + arguments=[output_file.path, tmp_file.path] + [s.path for s in all_trusted], + progress_message="Merging %s" % ctx.files.srcs[0].path, + executable=ctx.executable.kmerge_tool) + return [ + KtrustedInfo( + trusted = output_file, + ) + ] + +ktrusted = rule( + implementation = _ktrusted_impl, + attrs = { + "srcs": attr.label_list(allow_files = [".k"]), + "trusted": attr.label_list(providers=[DefaultInfo, KtrustedInfo]), + "ktrusted_tool": attr.label( + executable = True, + cfg = "exec", + allow_files = True, + default = Label("//kompile_tool:ktrusted_tool"), + ), + "kmerge_tool": attr.label( + executable = True, + cfg = "exec", + allow_files = True, + default = Label("//kompile_tool:kmerge_tool"), + ), + }, +) + +def _merge_trusted(input_file, trusted_attr, kmerge, actions, merged_file): + all_trusted = [] + for dep in trusted_attr: + all_trusted += [dep[KtrustedInfo].trusted] + actions.run( + inputs=depset([input_file] + all_trusted), + outputs=[merged_file], + arguments=[merged_file.path, input_file.path] + [s.path for s in all_trusted], + progress_message="Preparing %s" % input_file.path, + executable=kmerge) + +# def _kprove_test_impl(ctx): +# if len(ctx.files.srcs) != 1: +# fail +# merged_file = ctx.actions.declare_file(ctx.label.name + '.k') + +# _merge_trusted( +# ctx.files.srcs[0], +# ctx.attr.trusted, +# ctx.executable.kmerge_tool, +# ctx.actions, +# merged_file) + +# output_file = ctx.actions.declare_file(ctx.label.name + '-runner.sh') +# command_parts = [ +# "pushd $(pwd)", +# "kompile_tool/kprove_tool %s %s %s --debug" % ( +# ctx.attr.semantics[KompileInfo].files[0].short_path, +# ctx.files.srcs[0].path, +# merged_file.short_path), +# "popd", +# ] +# script_lines = [ +# "#!/usr/bin/env bash", +# "", +# # "read line", +# # 'echo "aaa: $line"', +# # "", +# "echo 'To debug:'", +# 'echo "%s"' % ("; ".join(command_parts)), +# "kompile_tool/kprove_tool %s %s %s %s" % (ctx.attr.semantics[KompileInfo].files[0].short_path, ctx.files.srcs[0].path, merged_file.short_path, '"$@"'), +# ] +# ctx.actions.write(output_file, "\n".join(script_lines), is_executable = True) +# runfiles = ctx.runfiles( +# [merged_file, ctx.executable.kprove_tool] +# + ctx.attr.semantics[KompileInfo].files +# + ctx.attr.k_distribution[DefaultInfo].files.to_list() +# + ctx.attr.debug_script[DefaultInfo].files.to_list() +# ) +# return [ +# DefaultInfo( +# runfiles = runfiles, +# executable = output_file, +# ) +# ] + +# kprove_test = rule( +# implementation = _kprove_test_impl, +# attrs = { +# "srcs": attr.label_list(allow_files = [".k"]), +# "trusted": attr.label_list(providers=[DefaultInfo, KtrustedInfo]), +# "semantics": attr.label(mandatory=True, providers=[DefaultInfo, KompileInfo]), +# "kprove_tool": attr.label( +# executable = True, +# cfg = "exec", +# allow_files = True, +# default = Label("//kompile_tool:kprove_tool"), +# ), +# "kmerge_tool": attr.label( +# executable = True, +# cfg = "exec", +# allow_files = True, +# default = Label("//kompile_tool:kmerge_tool"), +# ), +# "k_distribution": attr.label( +# executable = False, +# cfg = "exec", +# allow_files = True, +# default = Label("//kompile_tool:k_release"), +# ), +# "debug_script": attr.label( +# executable = False, +# cfg = "exec", +# allow_files = True, +# default = Label("//kompile_tool:kast_script"), +# ), +# }, +# test = True, +# ) + +def _kprove_kompile_impl(ctx): + if len(ctx.files.srcs) != 1: + fail + merged_file = ctx.actions.declare_file(ctx.label.name + '.k') + + _merge_trusted( + ctx.files.srcs[0], + ctx.attr.trusted, + ctx.executable.kmerge_tool, + ctx.actions, + merged_file) + + output_spec = ctx.actions.declare_file(ctx.label.name + '.spec.kore') + output_definition = ctx.actions.declare_file(ctx.label.name + '.definition.kore') + output_command = ctx.actions.declare_file(ctx.label.name + '.command') + + output_kompile_files = [ + ctx.actions.declare_file(ctx.label.name + '-kompiled/' + name) + for name in [ + 'allRules.txt', 'cache.bin', 'compiled.bin', 'compiled.txt', + 'configVars.sh', 'definition.kore', 'macros.kore', 'mainModule.txt', + 'parsed.txt', 'syntaxDefinition.kore', 'timestamp'] + ] + + runfiles = depset( + [merged_file, ctx.executable.kprove_kompile_tool] + + ctx.attr.semantics[KompileInfo].files + + ctx.attr.k_distribution[DefaultInfo].files.to_list() + ) + ctx.actions.run( + inputs=runfiles.to_list(), + outputs=[output_spec, output_definition, output_command] + output_kompile_files, + arguments=[ + ctx.attr.semantics[KompileInfo].files[0].path, + ctx.files.srcs[0].path, + merged_file.path, + output_spec.path, + output_definition.path, + output_command.path, + output_kompile_files[0].path + ], + progress_message="Generating kore for %s" % ctx.files.srcs[0].path, + executable=ctx.executable.kprove_kompile_tool) + return [ + KompileInfo(files=output_kompile_files), + KproveInfo( + spec = output_spec, + definition = output_definition, + command = output_command + ) + ] + +kprove_kompile = rule( + implementation = _kprove_kompile_impl, + attrs = { + "srcs": attr.label_list(allow_files = [".k"]), + "trusted": attr.label_list(providers=[DefaultInfo, KtrustedInfo]), + "semantics": attr.label(mandatory=True, providers=[DefaultInfo, KompileInfo]), + "kprove_kompile_tool": attr.label( + executable = True, + cfg = "exec", + allow_files = True, + default = Label("//kompile_tool:kprove_kompile_tool"), + ), + "kmerge_tool": attr.label( + executable = True, + cfg = "exec", + allow_files = True, + default = Label("//kompile_tool:kmerge_tool"), + ), + "k_distribution": attr.label( + executable = False, + cfg = "exec", + allow_files = True, + default = Label("//kompile_tool:k_release"), + ), + }, +) + +def _kore_test_impl(ctx): + + script_file = ctx.actions.declare_file(ctx.label.name + '-runner.sh') + + tool_call = "kompile_tool/kore_tool %s %s %s %s %s %s %s" % ( + ctx.attr.module, + ctx.attr.kompiled[KompileInfo].files[0].short_path, + ctx.attr.kompiled[KproveInfo].definition.short_path, + ctx.attr.kompiled[KproveInfo].spec.short_path, + ctx.attr.kompiled[KproveInfo].command.short_path, + ctx.label.name + '.output.k', + ctx.attr.breadth) + + command_parts = [ + "pushd $(pwd) > /dev/null", + "%s --debug" % tool_call, + "popd > /dev/null", + ] + script_lines = [ + "#!/usr/bin/env bash", + "", + "echo 'To debug:'", + 'echo "%s"' % ("; ".join(command_parts)), + "%s %s" % (tool_call, '"$@"'), + ] + ctx.actions.write(script_file, "\n".join(script_lines), is_executable = True) + runfiles = ctx.runfiles( + [ + ctx.attr.kompiled[KproveInfo].definition, + ctx.attr.kompiled[KproveInfo].spec, + ctx.attr.kompiled[KproveInfo].command, + ctx.executable.kore_tool, + ] + + ctx.attr.kompiled[KompileInfo].files + + ctx.attr.k_distribution[DefaultInfo].files.to_list() + + ctx.attr.debug_script[DefaultInfo].files.to_list() + ) + return [ + DefaultInfo( + runfiles = runfiles, + executable = script_file, + ) + ] + +kore_test = rule( + implementation = _kore_test_impl, + attrs = { + "kompiled": attr.label(providers=[KproveInfo], mandatory=True), + "module": attr.string(mandatory=True), + "breadth": attr.string(mandatory=True), + "kore_tool": attr.label( + executable = True, + cfg = "exec", + allow_files = True, + default = Label("//kompile_tool:kore_tool"), + ), + "k_distribution": attr.label( + executable = False, + cfg = "exec", + allow_files = True, + default = Label("//kompile_tool:k_release"), + ), + "debug_script": attr.label( + executable = False, + cfg = "exec", + allow_files = True, + default = Label("//kompile_tool:kast_script"), + ), + }, + test = True, +) + +def kprove_test(*, name, srcs, trusted=[], semantics, breadth="1", timeout="short"): + kprove_kompile( + name = "%s-kompile" % name, + srcs = srcs, + trusted = trusted, + semantics = semantics, + ) + + kore_test( + name = name, + module = name.upper(), + breadth = breadth, + kompiled = ":%s-kompile" % name, + timeout = timeout, + ) + diff --git a/multisig/protocol-correctness/.gitignore b/multisig/protocol-correctness/.gitignore new file mode 100644 index 000000000..87f27b29b --- /dev/null +++ b/multisig/protocol-correctness/.gitignore @@ -0,0 +1,6 @@ +*.timestamp +*-kompiled +*.cmp +.krun-* +kore-*.tar.gz +*.tar.gz diff --git a/multisig/protocol-correctness/BUILD b/multisig/protocol-correctness/BUILD new file mode 100644 index 000000000..14747ce7c --- /dev/null +++ b/multisig/protocol-correctness/BUILD @@ -0,0 +1,7 @@ +load("//:proof.bzl", "klibrary") + +klibrary( + name = "pseudocode-files", + srcs = ["pseudocode.k"], + visibility = ["//visibility:public"], +) \ No newline at end of file diff --git a/multisig/protocol-correctness/Makefile b/multisig/protocol-correctness/Makefile new file mode 100644 index 000000000..531df4789 --- /dev/null +++ b/multisig/protocol-correctness/Makefile @@ -0,0 +1,33 @@ +TESTS = $(wildcard tests/*.golden) +TEST_COMPARISON = ${TESTS:.golden=.cmp} +TEST_GOLDEN = ${TESTS:=.make} + +CHECK_RESULT_RUN = if [ $$? -eq 0 ] ; then echo "passed $<"; mv $@.tmp $@; else echo "failed $<"; cat $@.tmp; exit 1; fi + +.PRECIOUS: tests/*.out + +execution.timestamp: execution.k *.k + @echo "Compiling $<" + @kompile $(KOMPILE_FLAGS) $< --backend haskell + @touch execution.timestamp + +test: ${TEST_COMPARISON} + +tests/%.cmp: tests/%.out tests/%.golden + @echo "Comparing $^... " + @diff --strip-trailing-cr $^ > $@.tmp 2>&1; ${CHECK_RESULT_RUN} + +tests/%.out: tests/%.msig execution.timestamp + @echo "Running $<" + @krun $< > $@ 2>&1 + +golden: ${TEST_GOLDEN} + +tests/%.golden.make: tests/%.msig execution.timestamp + @echo "Running $<" + @krun $< > tests/$*.golden 2>&1 + +clean: + -rm *.timestamp tests/*.out tests/*.cmp + -rm -r execution-kompiled + -rm -r .krun* diff --git a/multisig/protocol-correctness/execution.k b/multisig/protocol-correctness/execution.k new file mode 100644 index 000000000..d4013327d --- /dev/null +++ b/multisig/protocol-correctness/execution.k @@ -0,0 +1,10 @@ +require "pseudocode.k" + +module EXECUTION-SYNTAX + imports PSEUDOCODE-SYNTAX +endmodule + +module EXECUTION + imports EXECUTION-SYNTAX + imports PSEUDOCODE +endmodule \ No newline at end of file diff --git a/multisig/protocol-correctness/proof/.gitignore b/multisig/protocol-correctness/proof/.gitignore new file mode 100644 index 000000000..88cc470a3 --- /dev/null +++ b/multisig/protocol-correctness/proof/.gitignore @@ -0,0 +1,10 @@ +.kprove-* +kore-repl* +*.log +*.svg +*.json +*.eventlog +out +.out +.deps +trusted-*.k diff --git a/multisig/protocol-correctness/proof/BUILD b/multisig/protocol-correctness/proof/BUILD new file mode 100644 index 000000000..205c37410 --- /dev/null +++ b/multisig/protocol-correctness/proof/BUILD @@ -0,0 +1,31 @@ +load("//:proof.bzl", "klibrary") + +klibrary( + name = "execution-proof-files", + srcs = ["execution-proof.k"], + deps = [ + ":invariant-files", + ":execution-proof-helpers-files", + ], + visibility = ["//visibility:public"], +) + +klibrary( + name = "execution-proof-helpers-files", + srcs = ["execution-proof-helpers.k"], + deps = [ + "//protocol-correctness:pseudocode-files", + "//protocol-correctness/proof/map:map-files", + ], + visibility = ["//visibility:public"], +) + +klibrary( + name = "invariant-files", + srcs = ["invariant.k"], + deps = [ + ":execution-proof-helpers-files", + "//protocol-correctness:pseudocode-files" + ], + visibility = ["//visibility:public"], +) diff --git a/multisig/protocol-correctness/proof/Makefile b/multisig/protocol-correctness/proof/Makefile new file mode 100644 index 000000000..305a191af --- /dev/null +++ b/multisig/protocol-correctness/proof/Makefile @@ -0,0 +1,37 @@ +include settings.mak + +.PHONY: default +default: all ; + +SCRIPT_DIR=. + +PROOF_DIR := . +include proof-dependency.mak + +MAP_DIR := map +include map/map.mak + +FUNCTIONS_DIR := functions +include functions/functions.mak + +INVARIANT_DIR := invariant +include invariant/invariant.mak + +PROPERTIES_DIR := properties +include properties/properties.mak + +.PHONY: all functions invariant map properties clean + +all: functions invariant map properties + +functions: $(FUNCTIONS_OUT_PREFIX)proof.timestamp + +invariant: $(INVARIANT_OUT_PREFIX)proof.timestamp + +map: $(MAP_OUT_PREFIX)proof.timestamp + +properties: $(PROPERTIES_OUT_PREFIX)proof.timestamp + +clean: functions.clean invariant.clean map.clean properties.clean + rm -r *-kompiled + rm -r out diff --git a/multisig/protocol-correctness/proof/compute-duration.py b/multisig/protocol-correctness/proof/compute-duration.py new file mode 100755 index 000000000..960120459 --- /dev/null +++ b/multisig/protocol-correctness/proof/compute-duration.py @@ -0,0 +1,26 @@ +#!/usr/bin/env python3 +import sys + +def main(argv): + with open(argv[0], 'rt') as f: + contents = f.read() + lines = contents.strip('\r\n').split('\n') + assert len(lines) == 2, lines + start = float(lines[0]) + end = float(lines[1]) + seconds = end - start + minutes = seconds / 60 + hours = minutes / 60 + minutes = minutes % 60 + seconds = seconds % 60 + if hours > 0: + message = '%dh %dm %ds' % (hours, minutes, seconds) + elif minutes > 0: + message = '%dm %ds' % (minutes, seconds) + else: + message = '%ds' % seconds + print(message) + + +if __name__ == '__main__': + main(sys.argv[1:]) \ No newline at end of file diff --git a/multisig/protocol-correctness/proof/execution-proof-helpers.k b/multisig/protocol-correctness/proof/execution-proof-helpers.k new file mode 100644 index 000000000..ea995c31a --- /dev/null +++ b/multisig/protocol-correctness/proof/execution-proof-helpers.k @@ -0,0 +1,500 @@ +require "protocol-correctness/pseudocode.k" +require "protocol-correctness/proof/map/map-execute.k" + +module EXECUTION-PROOF-HELPERS + imports MAP-SYMBOLIC + imports SET + + imports PSEUDOCODE + imports MAP-EXECUTE + imports EXPLICIT-KITEM-INJECTION + + // Expand and PropertyHandling form a stupid trick used to control symbolic + // function application. + // Any function that receives them as an argument should not depend on them, + // i.e it should have the same value for all possible PropertyHandling values. + syntax Expand ::= "expanded" | expand(Expand) + syntax PropertyHandling ::= "usesExpanded" | Expand + // TODO: Delete above or below. + syntax Int ::= expand(Int) [function, functional, no-evaluators] + syntax Int ::= "usesExpanded" [function, functional, no-evaluators] + + rule isKResult(last(Es)) => true + requires isKResult(Es) + // TODO: Define a function called `lastCeilCondition`... + ensures pListLen([Es]) >Int 0 + [simplification] + + rule isUsize(last(Es)) => true + requires listElementsAreUsize([Es]) + [simplification] + + rule isKResult(lastToStart(Es)) => isKResult(Es) + [simplification] + + rule listElementsAreUsize([lastToStart(Es)]) => listElementsAreUsize([Es]) + [simplification] + + rule isKResult(removeLast(Es)) => true + requires isKResult(Es) + ensures pListLen([Es]) >Int 0 + [simplification] + + rule listElementsAreUsize([removeLast(Es:ExpressionCSV)]) => true + requires listElementsAreUsize([Es]) + [simplification] + + rule pListLen(_) >=Int 0 => true [simplification, smt-lemma] + + rule addOneIfNotNegative(X:Int) >=Int 0 => X >=Int 0 [simplification] + + // Override the default behaviour. + rule isDefaultValue(E:ExpressionList, rExpressionList) + => notBool (pListLen(E) >Int 0) + rule pListLen([#pushList(_, _)]) >Int 0 => true + [simplification] + + syntax Bool ::= noCommonItem(Usize, Map, ExpressionList) [function, functional] + rule noCommonItem(_:Usize, _:Map, [.]) => true + rule noCommonItem(U:Usize, M:Map, [E:Expression , Es:ExpressionCSV]) + => notBool (E in_keys(M)) + andBool noCommonItem(add(U, u(1)), (E |-> U) M, [Es]) + + syntax Bool ::= noReusedIndexAddress(Usize, Map, ExpressionList) [function, functional] + rule noReusedIndexAddress(U:Usize, M:Map, [.]) => forall-v-greater-or-equal-than-u-v-not-in-m(U, M, [.]) + rule noReusedIndexAddress(U:Usize, M:Map, [E:Expression , Es:ExpressionCSV] #as L) + => forall-v-greater-or-equal-than-u-v-not-in-m(U, M, L) + andBool noReusedIndexAddress(add(U, u(1)), (U |-> E) M, [Es]) + + syntax Bool ::= noReusedIndexRole(Usize, Map, ExpressionList) [function, functional] + rule noReusedIndexRole(U:Usize, M:Map, [.]) => forall-v-greater-or-equal-than-u-v-not-in-m(U, M, [.]) + rule noReusedIndexRole(U:Usize, M:Map, [_:Expression , Es:ExpressionCSV] #as L) + => forall-v-greater-or-equal-than-u-v-not-in-m(U, M, L) + andBool noReusedIndexRole(add(U, u(1)), (U |-> BoardMember) M, [Es]) + + syntax Bool ::= "forall-v-greater-or-equal-than-u-v-not-in-m" "(" Usize "," Map "," ExpressionList ")" [function, functional] + rule forall-v-greater-or-equal-than-u-v-not-in-m(U, M, [.]) + => notBool U in_keys(M) + rule forall-v-greater-or-equal-than-u-v-not-in-m(U, M, [_:Expression , Es:ExpressionCSV]) + => notBool U in_keys(M) + andBool forall-v-greater-or-equal-than-u-v-not-in-m(add(U, u(1)), M, [Es]) + + syntax Usize ::= usizeWithDefault(KItem, Usize) [function, functional] + rule usizeWithDefault(uninitialized, Default:Usize) => Default + rule usizeWithDefault(V:Usize, _:Usize) => V + + syntax Int ::= usizeToInt(Usize) [function, functional] + rule usizeToInt(u(V:Int)) => V + + syntax Bool ::= listElementsAreAddresses(ExpressionList) [function, functional] + rule listElementsAreAddresses([.]) => true + rule listElementsAreAddresses([E:Expression , Es:ExpressionCSV]) + => isAddress(E) andBool listElementsAreAddresses([Es]) + + syntax Bool ::= listElementsAreUsize(KItem) [function, functional] + rule listElementsAreUsize([.]) => true + rule listElementsAreUsize([E:Expression, Es:ExpressionCSV]) + => isUsize(E) andBool listElementsAreUsize([Es]) + rule listElementsAreUsize(_:KItem) => false + [owise] + rule listElementsAreUsize([E:Expression, Es:ExpressionCSV]) + => isUsize(E) andBool listElementsAreUsize([Es]) + [simplification] + + syntax Bool ::= listElementsAreDistinct(KItem) [function, functional] + rule listElementsAreDistinct([.]) => true + rule listElementsAreDistinct([E:Expression, Es:ExpressionCSV]) + => true + andBool notBool #listContains([Es], E) + andBool listElementsAreDistinct([Es]) + rule listElementsAreDistinct(_:KItem) => false + [owise] + + syntax Bool ::= valuesAreExpressionListOfUsize(Map) [function, functional] + rule valuesAreExpressionListOfUsize(.Map) => true + rule valuesAreExpressionListOfUsize((_ |-> V M:Map) #as _:Map) + => isExpressionList(V) + andBool listElementsAreUsize(V) + andBool valuesAreExpressionListOfUsize(M) + rule valuesAreExpressionListOfUsize((_ |-> V M:Map) #as _:Map) + => isExpressionList(V) + andBool listElementsAreUsize(V) + andBool valuesAreExpressionListOfUsize(M) + [simplification] + + syntax Bool ::= valuesAreKResult(Map) [function, functional] + rule valuesAreKResult(.Map) => true + rule valuesAreKResult((_ |-> V M:Map) #as _:Map) + => isKResult(V) andBool valuesAreKResult(M) + rule valuesAreKResult((_ |-> V M:Map) #as _:Map) + => isKResult(V) andBool valuesAreKResult(M) + [simplification] + + syntax Bool ::= valuesAreOfType(Map, ReflectionType) [function, functional] + rule valuesAreOfType(.Map, _:ReflectionType) => true + rule valuesAreOfType((_ |-> V M:Map) #as _:Map, T:ReflectionType) + => valueOfType(V, T) andBool valuesAreOfType(M, T) + rule valuesAreOfType((_ |-> V M:Map) #as _:Map, T:ReflectionType) + => valueOfType(V, T) andBool valuesAreOfType(M, T) + [simplification] + + syntax Bool ::= keysAreKResult(Map) [function, functional] + rule keysAreKResult(.Map) => true + rule keysAreKResult((K:KItem |-> _:KItem M:Map) #as _:Map) + => isKResult(K) andBool keysAreKResult(M) + rule keysAreKResult((K:KItem |-> _:KItem M:Map) #as _:Map) + => isKResult(K) andBool keysAreKResult(M) + [simplification] + + syntax Bool ::= keysAreOfType(Map, ReflectionType) [function, functional] + rule keysAreOfType(.Map, _:ReflectionType) => true + rule keysAreOfType((K:KItem |-> _:KItem M:Map) #as _:Map, T:ReflectionType) + => valueOfType(K, T) andBool keysAreOfType(M, T) + rule keysAreOfType((K:KItem |-> _:KItem M:Map) #as _:Map, T:ReflectionType) + => valueOfType(K, T) andBool keysAreOfType(M, T) + [simplification] + + syntax Bool ::= valueIsNotEmpty(KItem, ReflectionType) [function, functional] + rule valueIsNotEmpty(V:KItem, T:ReflectionType) + => notBool (V ==K defaultValue(T)) + + syntax Bool ::= valuesAreNotEmpty(Map, ReflectionType) [function, functional] + rule valuesAreNotEmpty(.Map, _:ReflectionType) => true + rule valuesAreNotEmpty((_ |-> V M:Map) #as _:Map, T:ReflectionType) + => valuesAreNotEmpty(M, T) andBool valueIsNotEmpty(V, T) + rule valuesAreNotEmpty((_ |-> V M:Map) #as _:Map, T:ReflectionType) + => valuesAreNotEmpty(M, T) andBool valueIsNotEmpty(V, T) + [simplification] + + syntax Bool ::= valuesAreDistinct(Map) [function, functional] + rule valuesAreDistinct(.Map) => true + rule valuesAreDistinct((_:KItem |-> V:KItem M:Map) #as _:Map) + => valuesAreDistinct(M) andBool valueNotInMapValues(V, M) + [simplification] + + syntax Bool ::= valueNotInMapValues(KItem, Map) [function, functional] + rule valueNotInMapValues(_:KItem, .Map) => true + rule valueNotInMapValues(V1:KItem, (_:KItem |-> V2:KItem M:Map) #as _:Map) + => (notBool (V1 ==K V2)) andBool valueNotInMapValues(V1, M) + [simplification] + rule valueNotInMapValues(u(X:Int +Int 4), M:Map) => true + requires #noReusedIndexValue(X +Int 3, M, expanded) + [simplification] + + syntax Bool ::= noReusedIndexValue(Int, Map, PropertyHandling) [function, functional] + syntax Bool ::= #noReusedIndexValue(Int, Map, PropertyHandling) [function, functional] + + rule noReusedIndexValue(_Index:Int, .Map, _:PropertyHandling) => true + + rule noReusedIndexValue(Index:Int, (_:KItem |-> V:Usize M:Map) #as _:Map, Expand:PropertyHandling) + => Index >Int usizeToInt(V) andBool noReusedIndexValue(Index, M, Expand) + [simplification(20)] + rule noReusedIndexValue(Index:Int, M:Map, Handling:PropertyHandling) + => true + andBool valueNotInMapValues(u(Index), M) + andBool #noReusedIndexValue(Index, M, Handling) + [simplification(50)] + + rule #noReusedIndexValue(_Index:Int, .Map, expanded) => true + rule #noReusedIndexValue(Index:Int, (_:KItem |-> V:Usize M:Map) #as _:Map, Expand:PropertyHandling) + => Index >Int usizeToInt(V) andBool #noReusedIndexValue(Index, M, Expand) + [simplification(20)] + rule #noReusedIndexValue(Index:Int, M:Map, expand(Expand:Expand)) + => noReusedIndexValue(Index +Int 1, M, Expand) + [simplification(50)] + + rule #noReusedIndexValue(X:Int, M:Map, usesExpanded) + => true + requires false + orBool #noReusedIndexValue(X, M, expanded) + orBool (true + andBool valueNotInMapValues(u(X), M) + andBool #noReusedIndexValue(X +Int 1, M, expanded) + ) + orBool (true + andBool valueNotInMapValues(u(X), M) + andBool valueNotInMapValues(u(X +Int 1), M) + andBool #noReusedIndexValue(X +Int 2, M, expanded) + ) + [simplification] + + rule #noReusedIndexValue(X:Int +Int 4, M:Map, expanded) + => true + requires #noReusedIndexValue(X +Int 3, M, expanded) + [simplification] + rule #noReusedIndexValue(X:Int +Int 2, M:Map, expanded) + => true + requires true + andBool #noReusedIndexValue(X +Int 3, M, expanded) + andBool valueNotInMapValues(u(X +Int 2), M) + [simplification] + + syntax Bool ::= allValuesBecomeKeys(Map, Map) [function, functional] + syntax Bool ::= #allValuesBecomeKeys(Map, Map) [function, functional] + + rule allValuesBecomeKeys(M:Map, N:Map) => #allValuesBecomeKeys(M, keysMap(N)) + + rule #allValuesBecomeKeys(.Map, _:Map) => true + // TODO: This does not work if the key is in the map. Fix it and everything else. + rule #allValuesBecomeKeys((_ |-> V M:Map) #as _:Map, N:Map) + => V in_keys(N) andBool #allValuesBecomeKeys(M, N) + [simplification] + rule #allValuesBecomeKeys(M:Map, (_ |-> _ N:Map) #as _:Map) => true + requires #allValuesBecomeKeys(M, N) + [simplification] + + syntax Bool ::= mapsAreReverse(Map, Map) [function, functional] + syntax Bool ::= mapsAreReverseHalf(Map, Map) [function, functional] + + rule mapsAreReverse(M:Map, N:Map) + => mapsAreReverseHalf(M, N) andBool mapsAreReverseHalf(N, M) + + rule mapsAreReverseHalf(.Map, _:Map) => true + rule mapsAreReverseHalf((K:KItem |-> V:KItem M:Map) #as _:Map, N:Map) + => V in_keys(N) andBool N[V] ==K K andBool mapsAreReverseHalf(M, N) + [simplification] + + syntax Bool ::= mapIncluded(Map, Map) [function, functional] + + rule mapIncluded(.Map, _:Map) => true + rule mapIncluded((K:KItem |-> V:KItem M:Map) #as _:Map, N:Map) + => K in_keys(N) andBool N[K] ==K V andBool mapIncluded(M, N) + [simplification] + rule mapIncluded(M:Map, M:Map) => true + [simplification] + rule mapIncluded(M1:Map, _:KItem |-> _:KItem M2:Map) => true + requires M1 ==K M2 + [simplification] + // Not sure why this does not work instead of the above: + rule mapIncluded(M:Map, _:KItem |-> _:KItem M:Map) => true + [simplification] + + rule X:Int -Int X:Int => 0 [simplification] + // Int addition normalization + rule X:Int +Int (Y:Int +Int Z:Int) => (X +Int Y) +Int Z [simplification] + // rule (X:Int +Int Y:Int) => (Y +Int X) [simplification, concrete(X), symbolic(Y)] + rule (A:Int +Int I:Int) +Int B:Int => (A +Int B) +Int I [simplification, concrete(I), symbolic(A,B)] + //rule (X:Int +Int Y:Int) +Int Z:Int => X +Int (Y +Int Z) [simplification, concrete(Y), concrete(Z)] + + syntax Bool ::= unusedIdsInMapKeys(lastIndex:Int, Map, expand:PropertyHandling) [function, functional] + + rule unusedIdsInMapKeys(_:Int, .Map, _:PropertyHandling) => true + rule unusedIdsInMapKeys(LastIndex:Int, (U:Usize |-> _:KItem M:Map) #as _:Map, Handling:PropertyHandling) + => unusedIdsInMapKeys(LastIndex, M, Handling) + andBool LastIndex >Int usizeToInt(U) + [simplification(30)] + rule unusedIdsInMapKeys(LastIndex:Int, M:Map, expand(Expand:Expand)) + => notBool u(LastIndex) in_keys(M) // TODO: Maybe check before wrapping + andBool unusedIdsInMapKeys(LastIndex +Int 1, M, Expand) + [simplification] + + rule unusedIdsInMapKeys(LastIndex:Int +Int 4, M:Map, expanded) + => true + requires unusedIdsInMapKeys(LastIndex +Int 3, M, expanded) + [simplification] + rule unusedIdsInMapKeys(LastIndex:Int +Int 2, M:Map, expanded) + => true + requires true + andBool notBool u(LastIndex +Int 2) in_keys(M) + andBool unusedIdsInMapKeys(LastIndex +Int 3, M, expanded) + [simplification] + + rule unusedIdsInMapKeys(LastIndex:Int, M:Map, usesExpanded) + => true + requires false + orBool unusedIdsInMapKeys(LastIndex, M, expanded) + orBool (true + andBool notBool u(LastIndex) in_keys(M) + andBool unusedIdsInMapKeys(LastIndex +Int 1, M, expanded) + ) + orBool (true + andBool notBool u(LastIndex) in_keys(M) + andBool notBool u(LastIndex +Int 1) in_keys(M) + andBool unusedIdsInMapKeys(LastIndex +Int 2, M, expanded) + ) + [simplification] + + rule unusedIdsInMapKeys(LastIndex:Int +Int 1, keysMap(M):Map, usesExpanded) + => true + requires true + andBool notBool u(LastIndex +Int 1) in_keys(M) + andBool unusedIdsInMapKeys(LastIndex +Int 2, keysMap(M), expanded) + [simplification] + + /* + rule unusedIdsInMapKeys(LastIndex:Int +Int 1, M:Map, usesExpanded) + => true + requires notBool u(LastIndex +Int 1) in_keys(M) + andBool unusedIdsInMapKeys(LastIndex +Int 2, M, expanded) + [simplification] + */ + + syntax Bool ::= unusedIdsInMapValues(lastIndex:Int, Map, handling:PropertyHandling) [function, functional] + rule unusedIdsInMapValues(_:Int, .Map, _:PropertyHandling) => true + rule unusedIdsInMapValues( + LastIndex:Int, + (_:KItem |-> Value:Usize M:Map) #as _:Map, + Handling:PropertyHandling + ) + => unusedIdsInMapValues(LastIndex, M, Handling) + andBool LastIndex >Int usizeToInt(Value) + [simplification(10)] + rule unusedIdsInMapValues(LastIndex:Int, M:Map, expand(_:Expand)) + => unusedIdsInMapValues(LastIndex, M, expanded) + + rule unusedIdsInMapValues(LastIndex:Int +Int 3, M:Map, _:PropertyHandling) + => true + requires unusedIdsInMapValues(LastIndex +Int 2, M, expanded) + [simplification] + + rule unusedIdsInMapValues(LastIndex:Int, M:Map, usesExpanded) + => true + requires false + orBool unusedIdsInMapValues(LastIndex -Int 1, M, expanded) + orBool unusedIdsInMapValues(LastIndex, M, expanded) + [simplification] + + syntax Bool ::= noMapKeyInList(Map, ExpressionList) [function, functional] + rule noMapKeyInList(.Map, _:ExpressionList) => true + // TODO: Do I need this? + rule noMapKeyInList(.Map, [.]) => true + [simplification] + rule noMapKeyInList(M:Map, [E:Expression, .]) => true + requires notBool E in_keys(M) + [simplification] + rule noMapKeyInList((K:KItem |-> _:KItem M:Map) #as _:Map, L:ExpressionList) + => true + andBool notBool #listContains(L, K) + andBool noMapKeyInList(M, L) + [simplification] + rule noMapKeyInList(M:Map, [#pushList(L:ExpressionCSV, E:Expression)]) + => true + requires noMapKeyInList(M, [L]) + andBool notBool E in_keys(M) + [simplification] + + syntax Map ::= keysMap(Map) [function, functional] + rule keysMap(.Map) => .Map + rule keysMap(K:KItem |-> _:KItem M:Map) => K |-> 0 keysMap(M) + [simplification] + rule X:KItem in_keys(keysMap(M:Map)) => X in_keys(M) + [simplification] + + rule #Ceil(@M:Map (@K:KItem |-> @V:KItem)) + => {(@K in_keys(@M)) #Equals false} + #And #Ceil(@M) + #And #Ceil(@K) + #And #Ceil(@V) + [anywhere, simplification(20)] + + syntax Int ::= countMapValues(Map, ExplicitKItem) [function, functional, smtlib(countMapValues)] + rule countMapValues(.Map, _) => 0 + rule countMapValues(((_ |-> U) M:Map) #as _:Map, V:ExplicitKItem) => countMapValues(M, V) +Int countValue(wrap(U), V) + [simplification] + + syntax Int ::= countValue(ExplicitKItem, ExplicitKItem) [function, functional, smtlib(countMapValue)] + rule countValue(V:ExplicitKItem, V:ExplicitKItem) => 1 + rule countValue(_:ExplicitKItem, _:ExplicitKItem) => 0 [owise] + // requires notBool (V1 ==K V2) + + rule 0 <=Int countValue(_:ExplicitKItem, _:ExplicitKItem) => true [simplification, smt-lemma] + // rule countValue(_:KItem, _:KItem) >=Int 0 => true [simplification] + rule countValue(_:ExplicitKItem, _:ExplicitKItem) <=Int 1 => true [simplification, smt-lemma] + + rule 0 <=Int countMapValues(_:Map, _:ExplicitKItem) => true [simplification, smt-lemma] + // rule countMapValues(_, _) >=Int 0 => true [simplification] + + // rule countMapValues(X, Y) >Int 0 => true requires notBool countMapValues(X, Y) ==Int 0 [simplification] + + // rule countMapValues(_, _) +Int X:Int <=Int 0 => false + // requires X >Int 0 + // [simplification] + // // TODO: Replace these with generic int rules. + // rule 0 <=Int countMapValues(A, B) +Int X:Int => countMapValues(A, B) +Int X >=Int 0 + // [simplification] + // rule countMapValues(_, _) +Int X:Int >=Int 0 => true + // requires X >=Int 0 + // [simplification] + // rule countMapValues(_, _) +Int X:Int >Int 0 => true + // requires X >Int 0 + // [simplification] + // rule countValue(_, _) +Int X:Int >=Int 0 => true + // requires X >=Int 0 + // [simplification] + // rule countValue(_, _) +Int X:Int >Int 0 => true + // requires X >Int 0 + // [simplification] + + // rule Q:Int <=Int (countMapValues(_, _) #as Cmv:Int) +Int X:Int +Int Y:Int => true + // requires Q:Int <=Int Cmv +Int X:Int andBool Y >=Int 0 + // [simplification] + // // TODO: Do I really need the rule below? + // rule countMapValues(_, _) +Int X:Int +Int Y:Int >=Int 0 => true + // requires X >=Int 0 andBool Y >=Int 0 + // [simplification] + + // TODO: Proof for this. + syntax Bool ::= canSignFunction(UserRole) [function, functional] + rule canSignFunction(Role:UserRole) => Role ==K BoardMember + + syntax Int ::= countCanSignFunction(signerIDs:ExpressionList, userIdToRole:Map) [function, functional, smtlib(countCanSignFunction)] + syntax Int ::= #countCanSignFunction(userID:Usize, signerIDs:ExpressionList, userIdToRole:Map, value:KItem) [function, functional] + rule countCanSignFunction([.], _:Map) => 0 + rule countCanSignFunction([UserId:Usize, Es:ExpressionCSV], UserId |-> Role:UserRole M:Map) + => 1 +Int countCanSignFunction([Es], M) // Remove UserId from the map since each user is counted at most once. + requires canSignFunction(Role) + rule countCanSignFunction([UserId:Usize, Es:ExpressionCSV], M:Map) + => countCanSignFunction([Es], M) // Remove UserId from the map since each user is counted at most once. + requires notBool UserId in_keys(M) + rule countCanSignFunction([_:Expression, Es:ExpressionCSV], M) + => countCanSignFunction([Es], M) + [owise] + rule countCanSignFunction([#pushList(Es:ExpressionCSV, UserId:Usize)], UserId |-> Role:UserRole M:Map) + => 1 +Int countCanSignFunction([Es], M) // Remove UserId from the map since each user is counted at most once. + requires canSignFunction(Role) + [simplification] + rule countCanSignFunction([#pushList(Es:ExpressionCSV, UserId:Usize)], UserId |-> Role:UserRole M:Map) + => countCanSignFunction([Es], M) // Remove UserId from the map since each user is counted at most once. + requires notBool canSignFunction(Role) + [simplification] + rule countCanSignFunction(Es:ExpressionList, UserId |-> _:UserRole M:Map) + => countCanSignFunction(Es, M) + requires notBool #listContains(Es, UserId) + [simplification] + rule countCanSignFunction(Es:ExpressionList, concat(UserId, _:UserRole, M:Map)) + => countCanSignFunction(Es, M) + requires notBool #listContains(Es, UserId) + [simplification] + + rule countCanSignFunction(Es:ExpressionList, concat(UserId:KItem, _Role:UserRole, M:Map)) + => countCanSignFunction(Es, M) + requires notBool #listContains(Es, UserId) + [simplification] + rule countCanSignFunction([UserId:Usize, Es:ExpressionCSV], concat(UserId1:KItem, Role:UserRole, M:Map)) + => #countCanSignFunction(UserId, [Es], concat(UserId1, Role, M), concat(UserId1, Role, M)[UserId] orDefault None) + [simplification] + rule countCanSignFunction([#pushList(Es:ExpressionCSV, UserId:Usize)], concat(UserId1:KItem, Role:UserRole, M:Map)) + => #countCanSignFunction(UserId, [Es], concat(UserId1, Role, M), concat(UserId1, Role, M)[UserId] orDefault None) + [simplification] + rule #countCanSignFunction(UserId:Usize, Es:ExpressionList, M:Map, Value:UserRole) + => 1 +Int countCanSignFunction(Es, M[UserId <- undef]) + requires canSignFunction(Value) + [simplification] + rule #countCanSignFunction(_:Usize, Es:ExpressionList, M:Map, Value:UserRole) + => countCanSignFunction(Es, M) + requires notBool canSignFunction(Value) + [simplification] + + rule 0 <=Int countCanSignFunction(_, _) => true [simplification, smt-lemma] + +endmodule + +module EXPLICIT-KITEM-INJECTION + imports PSEUDOCODE + + // The Haskell backend does not send sort injections to the SMT solver. + // However, sometimes, in predicates one needs to use KItems that should be + // sent to the SMT solver. ExplicitKItem allows us to do that. + syntax ExplicitKItem ::= wrap(KItem) + +endmodule diff --git a/multisig/protocol-correctness/proof/execution-proof.k b/multisig/protocol-correctness/proof/execution-proof.k new file mode 100644 index 000000000..e40d4639f --- /dev/null +++ b/multisig/protocol-correctness/proof/execution-proof.k @@ -0,0 +1,163 @@ +require "protocol-correctness/pseudocode.k" +require "protocol-correctness/proof/invariant.k" +require "protocol-correctness/proof/execution-proof-helpers.k" + +module EXECUTION-PROOF-SYNTAX + imports PSEUDOCODE-SYNTAX +endmodule + +module CONCRETIZE-INSTRUMENTATION + imports MAP + + imports PSEUDOCODE + + syntax KItem ::= concretizeValue(KItem) + + rule concretizeValue([CSV:ExpressionCSV]) => concretizeValue(CSV) [label(concretizeValueCsv)] + + rule concretizeValue(u(V:Int)) => concretizeValue(V) [label(concretizeValueUsize)] + + rule concretizeValue(address(V:Int)) => concretizeValue(V) [label(concretizeValueAddress)] + + rule concretizeValue(big(V:Int)) => concretizeValue(V) [label(concretizeValueBig)] + + rule concretizeValue(meta(V:Int)) => concretizeValue(V) [label(concretizeValueMeta)] + + rule concretizeValue(bytes(V:String)) => concretizeValue(V) [label(concretizeValueBytes)] + + rule concretizeValue(BoardMember) => .K [label(concretizeValueBoardMember)] + rule concretizeValue(Proposer) => .K [label(concretizeValueProposer)] + rule concretizeValue(None) => .K [label(concretizeValueNone)] + + rule concretizeValue(_) => .K [priority(200)] + + syntax KItem ::= concretizeExpressionList(ExpressionList, Int) + rule concretizeExpressionList([.:ExpressionCSV], X:Int) => .K + requires X >Int 0 + rule concretizeExpressionList([_:Expression , L:ExpressionCSV], X:Int) + => concretizeExpressionList([L], X -Int 1) + requires X >Int 0 + rule concretizeExpressionList([_:ExpressionCSV], X:Int) + => .K + requires X <=Int 0 + + syntax Expression ::= expressionListGetOrDefault(ExpressionList, Int, Expression) [function] + rule expressionListGetOrDefault([.], _:Int, Default:Expression) => Default + rule expressionListGetOrDefault([_:ExpressionCSV], X:Int, Default:Expression) => Default + requires X E + rule expressionListGetOrDefault([_:Expression, Es:ExpressionCSV], X:Int, Default:Expression) + => expressionListGetOrDefault([Es:ExpressionCSV], X -Int 1, Default) + requires X >Int 0 + + syntax Singleton ::= "singleton" + + syntax IntVarList ::= vars(Int, IntVarList) + | ".IntVarList" + + syntax Bool ::= isLazyConcretize(KItem) [function, functional] + rule isLazyConcretize(lazyConcretizeKeysFreezer) => true + rule isLazyConcretize(lazyConcretizeKeys(_:Map)) => true + rule isLazyConcretize(lazyConcretizeValues(_:Map)) => true + rule isLazyConcretize(_:KItem) => false [owise] + + syntax Singleton ::= concretizeKeys(Map, IntVarList) [function, functional] + rule concretizeKeys((K:Usize |-> _:KItem M:Map) #as _:Map, vars(U:Int, Vars:IntVarList)) + => concretizeKeys(M, Vars) + ensures K ==K u(U:Int) + // => concretizeKeys(M, Vars) #And #Ceil(K #And u(U:Int)) + [simplification(40)] + rule concretizeKeys(_:Map, _:IntVarList) => singleton + [simplification(50)] + + syntax Singleton ::= concretizeValues(Map, IntVarList) [function, functional] + rule concretizeValues((_:KItem |-> V:Usize M:Map) #as _:Map, vars(U:Int, Vars:IntVarList)) + => concretizeValues(M, Vars) + ensures V ==K u(U:Int) + // => concretizeKeys(M, Vars) #And #Ceil(K #And u(U:Int)) + [simplification(40)] + rule concretizeValues(_:Map, _:IntVarList) => singleton + [simplification(50)] + + syntax KItem ::= concretized(Singleton) + rule concretized(singleton) => .K + + syntax KItem ::= "lazyConcretizeKeysFreezer" + + syntax KItem ::= lazyConcretizeKeys(Map) + rule lazyConcretizeKeys(M:Map) => concretized(concretizeKeys(M, vars(?_, vars(?_, .IntVarList)))) + + syntax KItem ::= lazyConcretizeValues(Map) + rule lazyConcretizeValues(M:Map) => concretized(concretizeValues(M, vars(?_, vars(?_, .IntVarList)))) + + // TODO: Rename this. + // TODO: If I know the number of concretized elements alreadyin the map, and I usually do, + // I can do this instead of splitMap: + // syntax KItem ::= makeConcreteValue2(key:KItem, key2:KItem, Map) + // rule makeConcreteValue2(Key:KItem, Key2:KItem, Key2 |-> _:KItem M:Map) + // => .K + // requires Key in_keys(M) andBool notBool (Key ==K Key2) + // ensures M ==K Key |-> ?_Value:KItem ?Remainder:Map andBool notBool Key in_keys(?Remainder) + syntax KItem ::= makeConcreteValue(key:KItem, valueType:ReflectionType, Map) + rule makeConcreteValue(Key:KItem, ValueType:ReflectionType, M:Map) + => splitMap(Key, M, ?_Value:KItem, ?_Remainder:Map) + ~> cast(M[Key], ValueType) + ~> removeValue + ~> concretizeValue(M[Key]) + requires Key in_keys(M) + + syntax KItem ::= concretizeCastInKeys(key:KItem, valueType:ReflectionType, Map) + rule concretizeCastInKeys(Key:KItem, ValueType:ReflectionType, M:Map) + => splitMap(Key, M, ?_Value:KItem, ?_Remainder:Map) + ~> cast(M[Key], ValueType) + ~> removeValue + requires Key in_keys(M) + + syntax KItem ::= makeConcrete(value:KItem, valueType:ReflectionType) + rule makeConcrete(Value:KItem, ValueType:ReflectionType) + => cast(Value, ValueType) + ~> removeValue + ~> concretizeValue(Value) +endmodule + +module PROOF-INSTRUMENTATION + imports MAP + + imports PSEUDOCODE + + imports CONCRETIZE-INSTRUMENTATION + + syntax KItem ::= splitBoolean(Bool) + rule splitBoolean(true) => .K [label(splitBooleanTrue)] + rule splitBoolean(false) => .K [label(splitBooleanFalse)] + + syntax KItem ::= branchK(Bool, K, K) + rule branchK(true, K:K, _:K) => K [label(branchKTrue)] + rule branchK(false, _:K, K:K) => K [label(branchKFalse)] + +endmodule + +module EXECUTION-PROOF-BOOL + imports BOOL + + rule B1:Bool orBool _:Bool => true + requires B1 + [simplification] + rule _:Bool orBool B2:Bool => true + requires B2 + [simplification] + rule B1:Bool orBool B2:Bool => B2 + requires notBool B1 + [simplification] + rule B1:Bool orBool B2:Bool => B1 + requires notBool B2 + [simplification] +endmodule + +module EXECUTION-PROOF + imports EXECUTION-PROOF-BOOL + imports EXECUTION-PROOF-HELPERS + imports PROOF-INSTRUMENTATION + + imports INVARIANT +endmodule \ No newline at end of file diff --git a/multisig/protocol-correctness/proof/functions/BUILD b/multisig/protocol-correctness/proof/functions/BUILD new file mode 100644 index 000000000..3f09e4d24 --- /dev/null +++ b/multisig/protocol-correctness/proof/functions/BUILD @@ -0,0 +1,1554 @@ +load("//:proof.bzl", "kompile", "kprove_test", "ktrusted", "klibrary") + +kompile( + name = "functions-execute", + srcs = ["functions-execute.k"], + deps = [ + "//protocol-correctness/proof:execution-proof-files", + "//protocol-correctness:pseudocode-files", + ], +) + +klibrary( + name = "functions-execute-files", + srcs = ["functions-execute.k"], + deps = [ + "//protocol-correctness/proof:execution-proof-files", + "//protocol-correctness:pseudocode-files", + ], + visibility = ["//visibility:public"], +) + +kprove_test( + name = "proof-perform-action-endpoint-New", + srcs = ["proof-perform-action-endpoint-New.k"], + trusted = [":trusted-perform-action-endpoint-fragment-New"], + semantics = ":functions-execute", +) + +kprove_test( + name = "proof-perform-action-endpoint-None", + srcs = ["proof-perform-action-endpoint-None.k"], + trusted = [":trusted-perform-action-endpoint-fragment-None"], + semantics = ":functions-execute", +) + +kprove_test( + name = "proof-perform-action-endpoint-no-quorum", + srcs = ["proof-perform-action-endpoint-no-quorum.k"], + trusted = [":trusted-perform-action-endpoint-fragment-no-quorum"], + semantics = ":functions-execute", +) + +kprove_test( + name = "proof-perform-action-endpoint-nothing", + srcs = ["proof-perform-action-endpoint-nothing.k"], + trusted = [ + ":trusted-perform-action-endpoint-fragment-performs", + ":trusted-perform-action-id-nothing", + ], + semantics = ":functions-execute", + timeout = "moderate", +) + +kprove_test( + name = "proof-perform-action-endpoint-remove-user-BoardMember", + srcs = ["proof-perform-action-endpoint-remove-user-BoardMember.k"], + trusted = [ + ":trusted-perform-action-endpoint-fragment-performs", + ":trusted-perform-action-id-remove-user-BoardMember", + ], + semantics = ":functions-execute", + timeout = "moderate", +) + +kprove_test( + name = "proof-perform-action-endpoint-remove-user-BoardMember-eq", + srcs = ["proof-perform-action-endpoint-remove-user-BoardMember-eq.k"], + trusted = [ + ":trusted-perform-action-endpoint-fragment-performs", + ":trusted-perform-action-id-remove-user-BoardMember", + ], + semantics = ":functions-execute", + timeout = "moderate", +) + +kprove_test( + name = "proof-perform-action-endpoint-remove-user-BoardMember-too-few", + srcs = ["proof-perform-action-endpoint-remove-user-BoardMember-too-few.k"], + trusted = [ + ":trusted-perform-action-endpoint-fragment-performs", + ":trusted-perform-action-id-remove-user-BoardMember-too-few", + ], + semantics = ":functions-execute", + timeout = "moderate", +) + +kprove_test( + name = "proof-perform-action-endpoint-remove-user-BoardMember-too-few-eq", + srcs = ["proof-perform-action-endpoint-remove-user-BoardMember-too-few-eq.k"], + trusted = [ + ":trusted-perform-action-endpoint-fragment-performs", + ":trusted-perform-action-id-remove-user-BoardMember-too-few", + ], + semantics = ":functions-execute", + timeout = "moderate", +) + +kprove_test( + name = "proof-perform-action-endpoint-remove-user-Proposer-nobody-left", + srcs = ["proof-perform-action-endpoint-remove-user-Proposer-nobody-left.k"], + trusted = [ + ":trusted-perform-action-endpoint-fragment-performs", + ":trusted-perform-action-id-remove-user-Proposer-nobody-left", + ], + semantics = ":functions-execute", + timeout = "moderate", +) + +kprove_test( + name = "proof-perform-action-endpoint-remove-user-Proposer-nobody-left-eq", + srcs = ["proof-perform-action-endpoint-remove-user-Proposer-nobody-left-eq.k"], + trusted = [ + ":trusted-perform-action-endpoint-fragment-performs", + ":trusted-perform-action-id-remove-user-Proposer-nobody-left", + ], + semantics = ":functions-execute", + timeout = "moderate", +) + +kprove_test( + name = "proof-perform-action-endpoint-remove-user-Proposer", + srcs = ["proof-perform-action-endpoint-remove-user-Proposer.k"], + trusted = [ + ":trusted-perform-action-endpoint-fragment-performs", + ":trusted-perform-action-id-remove-user-Proposer", + ], + semantics = ":functions-execute", + timeout = "moderate", +) + +kprove_test( + name = "proof-perform-action-endpoint-remove-user-Proposer-eq", + srcs = ["proof-perform-action-endpoint-remove-user-Proposer-eq.k"], + trusted = [ + ":trusted-perform-action-endpoint-fragment-performs", + ":trusted-perform-action-id-remove-user-Proposer", + ], + semantics = ":functions-execute", + timeout = "moderate", +) + +kprove_test( + name = "proof-perform-action-endpoint-remove-user-None", + srcs = ["proof-perform-action-endpoint-remove-user-None.k"], + trusted = [ + ":trusted-perform-action-endpoint-fragment-performs", + ":trusted-perform-action-id-remove-user-None", + ], + semantics = ":functions-execute", + timeout = "moderate", +) + +kprove_test( + name = "proof-perform-action-endpoint-remove-user-New", + srcs = ["proof-perform-action-endpoint-remove-user-New.k"], + trusted = [ + ":trusted-perform-action-endpoint-fragment-performs", + ":trusted-perform-action-id-remove-user-New", + ], + semantics = ":functions-execute", + timeout = "moderate", +) + +kprove_test( + name = "proof-perform-action-endpoint-change-quorum", + srcs = ["proof-perform-action-endpoint-change-quorum.k"], + trusted = [ + ":trusted-perform-action-endpoint-fragment-performs", + ":trusted-perform-action-id-change-quorum", + ], + semantics = ":functions-execute", + timeout = "moderate", +) + +kprove_test( + name = "proof-perform-action-endpoint-change-quorum-no-quorum", + srcs = ["proof-perform-action-endpoint-change-quorum-no-quorum.k"], + trusted = [ + ":trusted-perform-action-endpoint-fragment-performs", + ":trusted-perform-action-id-change-quorum-no-quorum", + ], + semantics = ":functions-execute", + timeout = "moderate", +) + +kprove_test( + name = "proof-perform-action-endpoint-add-proposer-BoardMember-no-quorum", + srcs = ["proof-perform-action-endpoint-add-proposer-BoardMember-no-quorum.k"], + trusted = [ + ":trusted-perform-action-endpoint-fragment-performs", + ":trusted-perform-action-id-add-proposer-BoardMember-no-quorum", + ], + semantics = ":functions-execute", + timeout = "moderate", +) + +kprove_test( + name = "proof-perform-action-endpoint-add-proposer-BoardMember-no-quorum-eq", + srcs = ["proof-perform-action-endpoint-add-proposer-BoardMember-no-quorum-eq.k"], + trusted = [ + ":trusted-perform-action-endpoint-fragment-performs", + ":trusted-perform-action-id-add-proposer-BoardMember-no-quorum", + ], + semantics = ":functions-execute", + timeout = "moderate", +) + +kprove_test( + name = "proof-perform-action-endpoint-add-proposer-BoardMember", + srcs = ["proof-perform-action-endpoint-add-proposer-BoardMember.k"], + trusted = [ + ":trusted-perform-action-endpoint-fragment-performs", + ":trusted-perform-action-id-add-proposer-BoardMember", + ], + semantics = ":functions-execute", + timeout = "moderate", +) + +kprove_test( + name = "proof-perform-action-endpoint-add-proposer-BoardMember-eq", + srcs = ["proof-perform-action-endpoint-add-proposer-BoardMember-eq.k"], + trusted = [ + ":trusted-perform-action-endpoint-fragment-performs", + ":trusted-perform-action-id-add-proposer-BoardMember", + ], + semantics = ":functions-execute", + timeout = "moderate", +) + +kprove_test( + name = "proof-perform-action-endpoint-add-proposer-Proposer", + srcs = ["proof-perform-action-endpoint-add-proposer-Proposer.k"], + trusted = [ + ":trusted-perform-action-endpoint-fragment-performs", + ":trusted-perform-action-id-add-proposer-Proposer", + ], + semantics = ":functions-execute", + timeout = "moderate", +) + +kprove_test( + name = "proof-perform-action-endpoint-add-proposer-Proposer-eq", + srcs = ["proof-perform-action-endpoint-add-proposer-Proposer-eq.k"], + trusted = [ + ":trusted-perform-action-endpoint-fragment-performs", + ":trusted-perform-action-id-add-proposer-Proposer", + ], + semantics = ":functions-execute", + timeout = "moderate", +) + +kprove_test( + name = "proof-perform-action-endpoint-add-proposer-New", + srcs = ["proof-perform-action-endpoint-add-proposer-New.k"], + trusted = [ + ":trusted-perform-action-endpoint-fragment-performs", + ":trusted-perform-action-id-add-proposer-New", + ], + semantics = ":functions-execute", + timeout = "moderate", +) + +kprove_test( + name = "proof-perform-action-endpoint-add-proposer-None", + srcs = ["proof-perform-action-endpoint-add-proposer-None.k"], + trusted = [ + ":trusted-perform-action-endpoint-fragment-performs", + ":trusted-perform-action-id-add-proposer-None", + ], + semantics = ":functions-execute", + timeout = "moderate", +) + +kprove_test( + name = "proof-perform-action-endpoint-add-board-member-New", + srcs = ["proof-perform-action-endpoint-add-board-member-New.k"], + trusted = [ + ":trusted-perform-action-endpoint-fragment-performs", + ":trusted-perform-action-id-add-board-member-New", + ], + semantics = ":functions-execute", + timeout = "moderate", +) + +kprove_test( + name = "proof-perform-action-endpoint-add-board-member-BoardMember-eq", + srcs = ["proof-perform-action-endpoint-add-board-member-BoardMember-eq.k"], + trusted = [ + ":trusted-perform-action-endpoint-fragment-performs", + ":trusted-perform-action-id-add-board-member-BoardMember", + ], + semantics = ":functions-execute", + timeout = "moderate", +) + +kprove_test( + name = "proof-perform-action-endpoint-add-board-member-BoardMember", + srcs = ["proof-perform-action-endpoint-add-board-member-BoardMember.k"], + trusted = [ + ":trusted-perform-action-endpoint-fragment-performs", + ":trusted-perform-action-id-add-board-member-BoardMember", + ], + semantics = ":functions-execute", + timeout = "moderate", +) + +kprove_test( + name = "proof-perform-action-endpoint-add-board-member-Proposer", + srcs = ["proof-perform-action-endpoint-add-board-member-Proposer.k"], + trusted = [ + ":trusted-perform-action-endpoint-fragment-performs", + ":trusted-perform-action-id-add-board-member-Proposer", + ], + semantics = ":functions-execute", + timeout = "moderate", +) + +kprove_test( + name = "proof-perform-action-endpoint-add-board-member-Proposer-eq", + srcs = ["proof-perform-action-endpoint-add-board-member-Proposer-eq.k"], + trusted = [ + ":trusted-perform-action-endpoint-fragment-performs", + ":trusted-perform-action-id-add-board-member-Proposer", + ], + semantics = ":functions-execute", + timeout = "moderate", +) + +kprove_test( + name = "proof-perform-action-endpoint-add-board-member-None", + srcs = ["proof-perform-action-endpoint-add-board-member-None.k"], + trusted = [ + ":trusted-perform-action-endpoint-fragment-performs", + ":trusted-perform-action-id-add-board-member-None", + ], + semantics = ":functions-execute", + timeout = "moderate", +) + +kprove_test( + name = "proof-perform-action-endpoint-send-egld", + srcs = ["proof-perform-action-endpoint-send-egld.k"], + trusted = [ + ":trusted-perform-action-endpoint-fragment-performs", + ":trusted-perform-action-id-send-egld", + ], + semantics = ":functions-execute", + timeout = "moderate", +) + +kprove_test( + name = "proof-perform-action-endpoint-sc-call", + srcs = ["proof-perform-action-endpoint-sc-call.k"], + trusted = [ + ":trusted-perform-action-endpoint-fragment-performs", + ":trusted-perform-action-id-sc-call", + ], + semantics = ":functions-execute", + timeout = "moderate", +) + +kprove_test( + name = "proof-perform-action-endpoint-sc-deploy", + srcs = ["proof-perform-action-endpoint-sc-deploy.k"], + trusted = [ + ":trusted-perform-action-endpoint-fragment-performs", + ":trusted-perform-action-id-sc-deploy", + ], + semantics = ":functions-execute", + timeout = "moderate", +) + +kprove_test( + name = "proof-perform-action-endpoint-fragment-New", + srcs = ["proof-perform-action-endpoint-fragment-New.k"], + semantics = ":functions-execute", + breadth = "2", +) + +kprove_test( + name = "proof-perform-action-endpoint-fragment-None", + srcs = ["proof-perform-action-endpoint-fragment-None.k"], + semantics = ":functions-execute", +) + +kprove_test( + name = "proof-perform-action-endpoint-fragment-no-quorum", + srcs = ["proof-perform-action-endpoint-fragment-no-quorum.k"], + trusted = ["trusted-count-can-sign"], + semantics = ":functions-execute", + timeout = "eternal", + breadth = "6", +) + +kprove_test( + name = "proof-perform-action-endpoint-fragment-performs", + srcs = ["proof-perform-action-endpoint-fragment-performs.k"], + trusted = ["trusted-count-can-sign"], + semantics = ":functions-execute", + timeout = "eternal", + breadth = "6", +) + +kprove_test( + name = "proof-perform-action-id-nothing", + srcs = ["proof-perform-action-id-nothing.k"], + trusted = [":trusted-perform-action-nothing"], + semantics = ":functions-execute", + timeout = "moderate", + breadth = "3", +) + +kprove_test( + name = "proof-perform-action-id-remove-user-BoardMember", + srcs = ["proof-perform-action-id-remove-user-BoardMember.k"], + trusted = [":trusted-perform-action-remove-user-BoardMember"], + semantics = ":functions-execute", + timeout = "moderate", + breadth = "3", +) + +kprove_test( + name = "proof-perform-action-id-remove-user-BoardMember-too-few", + srcs = ["proof-perform-action-id-remove-user-BoardMember-too-few.k"], + trusted = [":trusted-perform-action-remove-user-BoardMember-too-few"], + semantics = ":functions-execute", + timeout = "moderate", + breadth = "3", +) + +kprove_test( + name = "proof-perform-action-id-remove-user-Proposer-nobody-left", + srcs = ["proof-perform-action-id-remove-user-Proposer-nobody-left.k"], + trusted = [":trusted-perform-action-remove-user-Proposer-nobody-left"], + semantics = ":functions-execute", + timeout = "moderate", + breadth = "3", +) + +kprove_test( + name = "proof-perform-action-id-remove-user-Proposer", + srcs = ["proof-perform-action-id-remove-user-Proposer.k"], + trusted = [":trusted-perform-action-remove-user-Proposer"], + semantics = ":functions-execute", + timeout = "moderate", + breadth = "3", +) + +kprove_test( + name = "proof-perform-action-id-remove-user-None", + srcs = ["proof-perform-action-id-remove-user-None.k"], + trusted = [":trusted-perform-action-remove-user-None"], + semantics = ":functions-execute", + timeout = "moderate", + breadth = "3", +) + +kprove_test( + name = "proof-perform-action-id-remove-user-New", + srcs = ["proof-perform-action-id-remove-user-New.k"], + trusted = [":trusted-perform-action-remove-user-New"], + semantics = ":functions-execute", + timeout = "long", # "moderate", + breadth = "3", +) + +kprove_test( + name = "proof-perform-action-id-change-quorum", + srcs = ["proof-perform-action-id-change-quorum.k"], + trusted = [":trusted-perform-action-change-quorum"], + semantics = ":functions-execute", + breadth = "3", +) + +kprove_test( + name = "proof-perform-action-id-change-quorum-no-quorum", + srcs = ["proof-perform-action-id-change-quorum-no-quorum.k"], + trusted = [":trusted-perform-action-change-quorum-no-quorum"], + semantics = ":functions-execute", + breadth = "3", +) + +kprove_test( + name = "proof-perform-action-id-add-proposer-BoardMember-no-quorum", + srcs = ["proof-perform-action-id-add-proposer-BoardMember-no-quorum.k"], + trusted = [":trusted-perform-action-add-proposer-BoardMember-no-quorum"], + semantics = ":functions-execute", + timeout = "moderate", + breadth = "3", +) + +kprove_test( + name = "proof-perform-action-id-add-proposer-BoardMember", + srcs = ["proof-perform-action-id-add-proposer-BoardMember.k"], + trusted = [":trusted-perform-action-add-proposer-BoardMember"], + semantics = ":functions-execute", + timeout = "moderate", + breadth = "3", +) + +kprove_test( + name = "proof-perform-action-id-add-proposer-Proposer", + srcs = ["proof-perform-action-id-add-proposer-Proposer.k"], + trusted = [":trusted-perform-action-add-proposer-Proposer"], + semantics = ":functions-execute", + timeout = "moderate", + breadth = "3", +) + +kprove_test( + name = "proof-perform-action-id-add-proposer-New", + srcs = ["proof-perform-action-id-add-proposer-New.k"], + trusted = [":trusted-perform-action-add-proposer-New"], + semantics = ":functions-execute", + timeout = "moderate", + breadth = "5", +) + +kprove_test( + name = "proof-perform-action-id-add-proposer-None", + srcs = ["proof-perform-action-id-add-proposer-None.k"], + trusted = [":trusted-perform-action-add-proposer-None"], + semantics = ":functions-execute", + timeout = "moderate", + breadth = "5", +) + +kprove_test( + name = "proof-perform-action-id-add-board-member-New", + srcs = ["proof-perform-action-id-add-board-member-New.k"], + trusted = [":trusted-perform-action-add-board-member-New"], + semantics = ":functions-execute", + timeout = "moderate", + breadth = "3", +) + +kprove_test( + name = "proof-perform-action-id-add-board-member-BoardMember", + srcs = ["proof-perform-action-id-add-board-member-BoardMember.k"], + trusted = [":trusted-perform-action-add-board-member-BoardMember"], + semantics = ":functions-execute", + timeout = "moderate", + breadth = "3", +) + +kprove_test( + name = "proof-perform-action-id-add-board-member-Proposer", + srcs = ["proof-perform-action-id-add-board-member-Proposer.k"], + trusted = [":trusted-perform-action-add-board-member-Proposer"], + semantics = ":functions-execute", + timeout = "moderate", + breadth = "3", +) + +kprove_test( + name = "proof-perform-action-id-add-board-member-None", + srcs = ["proof-perform-action-id-add-board-member-None.k"], + trusted = [":trusted-perform-action-add-board-member-None"], + semantics = ":functions-execute", + timeout = "moderate", + breadth = "3", +) + +kprove_test( + name = "proof-perform-action-id-send-egld", + srcs = ["proof-perform-action-id-send-egld.k"], + trusted = [":trusted-perform-action-send-egld"], + semantics = ":functions-execute", + breadth = "3", +) + +kprove_test( + name = "proof-perform-action-id-sc-call", + srcs = ["proof-perform-action-id-sc-call.k"], + trusted = [":trusted-perform-action-sc-call"], + semantics = ":functions-execute", + timeout = "moderate", + breadth = "3", +) + +kprove_test( + name = "proof-perform-action-id-sc-deploy", + srcs = ["proof-perform-action-id-sc-deploy.k"], + trusted = [":trusted-perform-action-sc-deploy"], + semantics = ":functions-execute", + timeout = "moderate", + breadth = "3", +) + +kprove_test( + name = "proof-perform-action-remove-user-BoardMember", + srcs = ["proof-perform-action-remove-user-BoardMember.k"], + trusted = [":trusted-change-user-role-BoardMember"], + semantics = ":functions-execute", +) + +kprove_test( + name = "proof-perform-action-remove-user-BoardMember-too-few", + srcs = ["proof-perform-action-remove-user-BoardMember-too-few.k"], + trusted = [":trusted-change-user-role-BoardMember"], + semantics = ":functions-execute", + timeout = "moderate", + breadth = "2", +) + +kprove_test( + name = "proof-perform-action-remove-user-Proposer-nobody-left", + srcs = ["proof-perform-action-remove-user-Proposer-nobody-left.k"], + trusted = [":trusted-change-user-role-Proposer"], + semantics = ":functions-execute", +) + +kprove_test( + name = "proof-perform-action-remove-user-Proposer", + srcs = ["proof-perform-action-remove-user-Proposer.k"], + trusted = [":trusted-change-user-role-Proposer"], + semantics = ":functions-execute", + breadth = "2", +) + +kprove_test( + name = "proof-perform-action-remove-user-None", + srcs = ["proof-perform-action-remove-user-None.k"], + trusted = [":trusted-change-user-role-None"], + semantics = ":functions-execute", + timeout = "moderate", # "short", +) + +kprove_test( + name = "proof-perform-action-remove-user-New", + srcs = ["proof-perform-action-remove-user-New.k"], + trusted = [":trusted-change-user-role-New"], + semantics = ":functions-execute", + timeout = "moderate", +) + +kprove_test( + name = "proof-perform-action-change-quorum", + srcs = ["proof-perform-action-change-quorum.k"], + semantics = ":functions-execute", +) + +kprove_test( + name = "proof-perform-action-change-quorum-no-quorum", + srcs = ["proof-perform-action-change-quorum-no-quorum.k"], + semantics = ":functions-execute", +) + +kprove_test( + name = "proof-perform-action-add-proposer-BoardMember-no-quorum", + srcs = ["proof-perform-action-add-proposer-BoardMember-no-quorum.k"], + trusted = [":trusted-change-user-role-BoardMember"], + semantics = ":functions-execute", +) + +kprove_test( + name = "proof-perform-action-add-proposer-BoardMember", + srcs = ["proof-perform-action-add-proposer-BoardMember.k"], + trusted = [":trusted-change-user-role-BoardMember"], + semantics = ":functions-execute", +) + +kprove_test( + name = "proof-perform-action-add-proposer-Proposer", + srcs = ["proof-perform-action-add-proposer-Proposer.k"], + trusted = [":trusted-change-user-role-Proposer"], + semantics = ":functions-execute", +) + +kprove_test( + name = "proof-perform-action-add-proposer-New", + srcs = ["proof-perform-action-add-proposer-New.k"], + trusted = [":trusted-change-user-role-New"], + semantics = ":functions-execute", + timeout = "moderate", +) + +kprove_test( + name = "proof-perform-action-add-proposer-None", + srcs = ["proof-perform-action-add-proposer-None.k"], + trusted = [":trusted-change-user-role-None"], + semantics = ":functions-execute", +) + +kprove_test( + name = "proof-perform-action-add-board-member-New", + srcs = ["proof-perform-action-add-board-member-New.k"], + trusted = [":trusted-change-user-role-New"], + semantics = ":functions-execute", +) + +kprove_test( + name = "proof-perform-action-add-board-member-BoardMember", + srcs = ["proof-perform-action-add-board-member-BoardMember.k"], + trusted = [":trusted-change-user-role-BoardMember"], + semantics = ":functions-execute", +) + +kprove_test( + name = "proof-perform-action-add-board-member-Proposer", + srcs = ["proof-perform-action-add-board-member-Proposer.k"], + trusted = [":trusted-change-user-role-Proposer"], + semantics = ":functions-execute", +) + +kprove_test( + name = "proof-perform-action-add-board-member-None", + srcs = ["proof-perform-action-add-board-member-None.k"], + trusted = [":trusted-change-user-role-None"], + semantics = ":functions-execute", +) + +kprove_test( + name = "proof-perform-action-send-egld", + srcs = ["proof-perform-action-send-egld.k"], + semantics = ":functions-execute", +) + +kprove_test( + name = "proof-perform-action-sc-call", + srcs = ["proof-perform-action-sc-call.k"], + semantics = ":functions-execute", +) + +kprove_test( + name = "proof-perform-action-sc-deploy", + srcs = ["proof-perform-action-sc-deploy.k"], + semantics = ":functions-execute", +) + +kprove_test( + name = "proof-perform-action-nothing", + srcs = ["proof-perform-action-nothing.k"], + semantics = ":functions-execute", +) + +kprove_test( + name = "proof-change-user-role-BoardMember", + srcs = ["proof-change-user-role-BoardMember.k"], + semantics = ":functions-execute", + timeout = "moderate", + breadth = "3", +) + +kprove_test( + name = "proof-change-user-role-New", + srcs = ["proof-change-user-role-New.k"], + semantics = ":functions-execute", + timeout = "long", + breadth = "3", +) + +kprove_test( + name = "proof-change-user-role-None", + srcs = ["proof-change-user-role-None.k"], + semantics = ":functions-execute", + timeout = "moderate", + breadth = "3", +) + +kprove_test( + name = "proof-change-user-role-Proposer", + srcs = ["proof-change-user-role-Proposer.k"], + semantics = ":functions-execute", + timeout = "moderate", + breadth = "3", +) + +kprove_test( + name = "proof-count-can-sign", + srcs = ["proof-count-can-sign.k"], + semantics = ":functions-execute", + timeout = "moderate", + breadth = "6", + # depth ~= 61 +) + +kprove_test( + name = "proof-discard-action-has-signers", + srcs = ["proof-discard-action-has-signers.k"], + trusted = [":trusted-count-can-sign"], + semantics = ":functions-execute", + timeout = "long", + breadth = "2", +) + +kprove_test( + name = "proof-discard-action-no-role", + srcs = ["proof-discard-action-no-role.k"], + semantics = ":functions-execute", +) + +kprove_test( + name = "proof-discard-action-no-signers-no-action", + srcs = ["proof-discard-action-no-signers-no-action.k"], + trusted = [":trusted-count-can-sign"], + semantics = ":functions-execute", + timeout = "long", # "moderate", + breadth = "2", +) + +kprove_test( + name = "proof-discard-action-no-signers", + srcs = ["proof-discard-action-no-signers.k"], + trusted = [":trusted-count-can-sign"], + semantics = ":functions-execute", + timeout = "long", # "moderate", + breadth = "2", +) + +kprove_test( + name = "proof-discard-action-no-user", + srcs = ["proof-discard-action-no-user.k"], + semantics = ":functions-execute", +) + +kprove_test( + name = "proof-discard-action-no-valid-signers-no-action", + srcs = ["proof-discard-action-no-valid-signers-no-action.k"], + trusted = [":trusted-count-can-sign"], + semantics = ":functions-execute", + timeout = "eternal", # "long", + breadth = "2", +) + +kprove_test( + name = "proof-discard-action-no-valid-signers", + srcs = ["proof-discard-action-no-valid-signers.k"], + trusted = [":trusted-count-can-sign"], + semantics = ":functions-execute", + timeout = "eternal", # "long", + breadth = "2", +) + +kprove_test( + name = "proof-propose-action-BoardMember", + srcs = ["proof-propose-action-BoardMember.k"], + semantics = ":functions-execute", + timeout = "eternal", # "long", + breadth = "2", +) + +kprove_test( + name = "proof-propose-action-error-no-role", + srcs = ["proof-propose-action-error-no-role.k"], + semantics = ":functions-execute", +) + +kprove_test( + name = "proof-propose-action-error-no-user", + srcs = ["proof-propose-action-error-no-user.k"], + semantics = ":functions-execute", +) + +kprove_test( + name = "proof-propose-action-Proposer", + srcs = ["proof-propose-action-Proposer.k"], + semantics = ":functions-execute", + timeout = "long", + breadth = "2", +) + +kprove_test( + name = "proof-propose-sc-deploy-BoardMember", + srcs = ["proof-propose-sc-deploy-BoardMember.k"], + trusted = [ + ":trusted-propose-action-BoardMember", + ":trusted-propose-sc-deploy-fragment", + ], + semantics = ":functions-execute", + timeout = "moderate", + breadth = "2", +) + +kprove_test( + name = "proof-propose-sc-deploy-error-no-role", + srcs = ["proof-propose-sc-deploy-error-no-role.k"], + trusted = [ + ":trusted-propose-action-error-no-role", + ":trusted-propose-sc-deploy-fragment", + ], + semantics = ":functions-execute", + timeout = "moderate", # "short", +) + +kprove_test( + name = "proof-propose-sc-deploy-error-no-user", + srcs = ["proof-propose-sc-deploy-error-no-user.k"], + trusted = [ + ":trusted-propose-action-error-no-user", + ":trusted-propose-sc-deploy-fragment", + ], + semantics = ":functions-execute", +) + +kprove_test( + name = "proof-propose-sc-deploy-fragment", + srcs = ["proof-propose-sc-deploy-fragment.k"], + semantics = ":functions-execute", + breadth = "6", +) + +kprove_test( + name = "proof-propose-sc-deploy-Proposer", + srcs = ["proof-propose-sc-deploy-Proposer.k"], + trusted = [ + ":trusted-propose-action-Proposer", + ":trusted-propose-sc-deploy-fragment", + ], + semantics = ":functions-execute", + timeout = "moderate", + breadth = "2", +) + +kprove_test( + name = "proof-sign-caller-none", + srcs = ["proof-sign-caller-none.k"], + semantics = ":functions-execute", + timeout = "moderate", + breadth = "2", +) + +kprove_test( + name = "proof-sign-caller-not-user", + srcs = ["proof-sign-caller-not-user.k"], + semantics = ":functions-execute", + breadth = "2", +) + +kprove_test( + name = "proof-sign-caller-proposer", + srcs = ["proof-sign-caller-proposer.k"], + semantics = ":functions-execute", + timeout = "moderate", + breadth = "2", +) + +kprove_test( + name = "proof-sign-empty-action", + srcs = ["proof-sign-empty-action.k"], + semantics = ":functions-execute", +) + +kprove_test( + name = "proof-sign-existing-signers-in-list", + srcs = ["proof-sign-existing-signers-in-list.k"], + semantics = ":functions-execute", + timeout = "moderate", + breadth = "2", +) + +kprove_test( + name = "proof-sign-existing-signers-not-in-list", + srcs = ["proof-sign-existing-signers-not-in-list.k"], + semantics = ":functions-execute", + timeout = "moderate", + breadth = "2", +) + +kprove_test( + name = "proof-sign-no-signers", + srcs = ["proof-sign-no-signers.k"], + semantics = ":functions-execute", + timeout = "moderate", + breadth = "2", +) + +kprove_test( + name = "proof-unsign-no-action", + srcs = ["proof-unsign-no-action.k"], + semantics = ":functions-execute", + timeout = "moderate", +) + +kprove_test( + name = "proof-unsign-no-role", + srcs = ["proof-unsign-no-role.k"], + semantics = ":functions-execute", + timeout = "moderate", +) + +kprove_test( + name = "proof-unsign-no-signers", + srcs = ["proof-unsign-no-signers.k"], + semantics = ":functions-execute", + timeout = "moderate", +) + +kprove_test( + name = "proof-unsign-no-user", + srcs = ["proof-unsign-no-user.k"], + semantics = ":functions-execute", + timeout = "moderate", +) + +kprove_test( + name = "proof-unsign-not-signed", + srcs = ["proof-unsign-not-signed.k"], + semantics = ":functions-execute", + timeout = "moderate", +) + +kprove_test( + name = "proof-unsign-only-signer", + srcs = ["proof-unsign-only-signer.k"], + semantics = ":functions-execute", + timeout = "moderate", +) + +kprove_test( + name = "proof-unsign-other-signers-first", + srcs = ["proof-unsign-other-signers-first.k"], + semantics = ":functions-execute", + timeout = "long", +) + +kprove_test( + name = "proof-unsign-other-signers-not-first", + srcs = ["proof-unsign-other-signers-not-first.k"], + semantics = ":functions-execute", + timeout = "long", +) + +kprove_test( + name = "proof-unsign-Proposer", + srcs = ["proof-unsign-Proposer.k"], + semantics = ":functions-execute", + timeout = "moderate", +) + +ktrusted( + name = "trusted-count-can-sign", + srcs = ["proof-count-can-sign.k"], +) + +ktrusted( + name = "trusted-propose-action-BoardMember", + srcs = ["proof-propose-action-BoardMember.k"], + visibility = ["//visibility:public"], +) + +ktrusted( + name = "trusted-propose-action-Proposer", + srcs = ["proof-propose-action-Proposer.k"], + visibility = ["//visibility:public"], +) + +ktrusted( + name = "trusted-propose-action-error-no-role", + srcs = ["proof-propose-action-error-no-role.k"], + visibility = ["//visibility:public"], +) + +ktrusted( + name = "trusted-propose-action-error-no-user", + srcs = ["proof-propose-action-error-no-user.k"], + visibility = ["//visibility:public"], +) + +ktrusted( + name = "trusted-propose-sc-deploy-fragment", + srcs = ["proof-propose-sc-deploy-fragment.k"], +) + +ktrusted( + name = "trusted-change-user-role-BoardMember", + srcs = ["proof-change-user-role-BoardMember.k"], +) + +ktrusted( + name = "trusted-change-user-role-New", + srcs = ["proof-change-user-role-New.k"], +) + +ktrusted( + name = "trusted-change-user-role-None", + srcs = ["proof-change-user-role-None.k"], +) + +ktrusted( + name = "trusted-change-user-role-Proposer", + srcs = ["proof-change-user-role-Proposer.k"], +) + +ktrusted( + name = "trusted-perform-action-remove-user-BoardMember", + srcs = ["proof-perform-action-remove-user-BoardMember.k"], +) + +ktrusted( + name = "trusted-perform-action-remove-user-BoardMember-too-few", + srcs = ["proof-perform-action-remove-user-BoardMember-too-few.k"], +) + +ktrusted( + name = "trusted-perform-action-remove-user-Proposer-nobody-left", + srcs = ["proof-perform-action-remove-user-Proposer-nobody-left.k"], +) + +ktrusted( + name = "trusted-perform-action-remove-user-Proposer", + srcs = ["proof-perform-action-remove-user-Proposer.k"], +) + +ktrusted( + name = "trusted-perform-action-remove-user-None", + srcs = ["proof-perform-action-remove-user-None.k"], +) + +ktrusted( + name = "trusted-perform-action-remove-user-New", + srcs = ["proof-perform-action-remove-user-New.k"], +) + +ktrusted( + name = "trusted-perform-action-change-quorum", + srcs = ["proof-perform-action-change-quorum.k"], +) + +ktrusted( + name = "trusted-perform-action-change-quorum-no-quorum", + srcs = ["proof-perform-action-change-quorum-no-quorum.k"], +) + +ktrusted( + name = "trusted-perform-action-add-proposer-BoardMember-no-quorum", + srcs = ["proof-perform-action-add-proposer-BoardMember-no-quorum.k"], +) + +ktrusted( + name = "trusted-perform-action-add-proposer-BoardMember", + srcs = ["proof-perform-action-add-proposer-BoardMember.k"], +) + +ktrusted( + name = "trusted-perform-action-add-proposer-Proposer", + srcs = ["proof-perform-action-add-proposer-Proposer.k"], +) + +ktrusted( + name = "trusted-perform-action-add-proposer-New", + srcs = ["proof-perform-action-add-proposer-New.k"], +) + +ktrusted( + name = "trusted-perform-action-add-proposer-None", + srcs = ["proof-perform-action-add-proposer-None.k"], +) + +ktrusted( + name = "trusted-perform-action-add-board-member-New", + srcs = ["proof-perform-action-add-board-member-New.k"], +) + +ktrusted( + name = "trusted-perform-action-add-board-member-BoardMember", + srcs = ["proof-perform-action-add-board-member-BoardMember.k"], +) + +ktrusted( + name = "trusted-perform-action-add-board-member-Proposer", + srcs = ["proof-perform-action-add-board-member-Proposer.k"], +) + +ktrusted( + name = "trusted-perform-action-add-board-member-None", + srcs = ["proof-perform-action-add-board-member-None.k"], +) + +ktrusted( + name = "trusted-perform-action-send-egld", + srcs = ["proof-perform-action-send-egld.k"], +) + +ktrusted( + name = "trusted-perform-action-sc-call", + srcs = ["proof-perform-action-sc-call.k"], +) + +ktrusted( + name = "trusted-perform-action-sc-deploy", + srcs = ["proof-perform-action-sc-deploy.k"], +) + +ktrusted( + name = "trusted-perform-action-nothing", + srcs = ["proof-perform-action-nothing.k"], +) + +ktrusted( + name = "trusted-perform-action-endpoint-fragment-New", + srcs = ["proof-perform-action-endpoint-fragment-New.k"], +) + +ktrusted( + name = "trusted-perform-action-endpoint-fragment-None", + srcs = ["proof-perform-action-endpoint-fragment-None.k"], +) + +ktrusted( + name = "trusted-perform-action-endpoint-fragment-no-quorum", + srcs = ["proof-perform-action-endpoint-fragment-no-quorum.k"], +) + +ktrusted( + name = "trusted-perform-action-endpoint-fragment-performs", + srcs = ["proof-perform-action-endpoint-fragment-performs.k"], +) + +ktrusted( + name = "trusted-perform-action-id-remove-user-BoardMember", + srcs = ["proof-perform-action-id-remove-user-BoardMember.k"], +) + +ktrusted( + name = "trusted-perform-action-id-remove-user-BoardMember-too-few", + srcs = ["proof-perform-action-id-remove-user-BoardMember-too-few.k"], +) + +ktrusted( + name = "trusted-perform-action-id-remove-user-Proposer-nobody-left", + srcs = ["proof-perform-action-id-remove-user-Proposer-nobody-left.k"], +) + +ktrusted( + name = "trusted-perform-action-id-remove-user-Proposer", + srcs = ["proof-perform-action-id-remove-user-Proposer.k"], +) + +ktrusted( + name = "trusted-perform-action-id-remove-user-None", + srcs = ["proof-perform-action-id-remove-user-None.k"], +) + +ktrusted( + name = "trusted-perform-action-id-remove-user-New", + srcs = ["proof-perform-action-id-remove-user-New.k"], +) + +ktrusted( + name = "trusted-perform-action-id-change-quorum", + srcs = ["proof-perform-action-id-change-quorum.k"], +) + +ktrusted( + name = "trusted-perform-action-id-change-quorum-no-quorum", + srcs = ["proof-perform-action-id-change-quorum-no-quorum.k"], +) + +ktrusted( + name = "trusted-perform-action-id-add-proposer-BoardMember-no-quorum", + srcs = ["proof-perform-action-id-add-proposer-BoardMember-no-quorum.k"], +) + +ktrusted( + name = "trusted-perform-action-id-add-proposer-BoardMember", + srcs = ["proof-perform-action-id-add-proposer-BoardMember.k"], +) + +ktrusted( + name = "trusted-perform-action-id-add-proposer-Proposer", + srcs = ["proof-perform-action-id-add-proposer-Proposer.k"], +) + +ktrusted( + name = "trusted-perform-action-id-add-proposer-New", + srcs = ["proof-perform-action-id-add-proposer-New.k"], +) + +ktrusted( + name = "trusted-perform-action-id-add-proposer-None", + srcs = ["proof-perform-action-id-add-proposer-None.k"], +) + +ktrusted( + name = "trusted-perform-action-id-add-board-member-New", + srcs = ["proof-perform-action-id-add-board-member-New.k"], +) + +ktrusted( + name = "trusted-perform-action-id-add-board-member-BoardMember", + srcs = ["proof-perform-action-id-add-board-member-BoardMember.k"], +) + +ktrusted( + name = "trusted-perform-action-id-add-board-member-Proposer", + srcs = ["proof-perform-action-id-add-board-member-Proposer.k"], +) + +ktrusted( + name = "trusted-perform-action-id-add-board-member-None", + srcs = ["proof-perform-action-id-add-board-member-None.k"], +) + +ktrusted( + name = "trusted-perform-action-id-send-egld", + srcs = ["proof-perform-action-id-send-egld.k"], +) + +ktrusted( + name = "trusted-perform-action-id-sc-call", + srcs = ["proof-perform-action-id-sc-call.k"], +) + +ktrusted( + name = "trusted-perform-action-id-sc-deploy", + srcs = ["proof-perform-action-id-sc-deploy.k"], +) + +ktrusted( + name = "trusted-perform-action-id-nothing", + srcs = ["proof-perform-action-id-nothing.k"], +) + +ktrusted( + name = "trusted-discard-action-has-signers", + srcs = ["proof-discard-action-has-signers.k"], + visibility = ["//visibility:public"], +) + +ktrusted( + name = "trusted-discard-action-no-role", + srcs = ["proof-discard-action-no-role.k"], + visibility = ["//visibility:public"], +) + +ktrusted( + name = "trusted-discard-action-no-signers-no-action", + srcs = ["proof-discard-action-no-signers-no-action.k"], + visibility = ["//visibility:public"], +) + +ktrusted( + name = "trusted-discard-action-no-signers", + srcs = ["proof-discard-action-no-signers.k"], + visibility = ["//visibility:public"], +) + +ktrusted( + name = "trusted-discard-action-no-user", + srcs = ["proof-discard-action-no-user.k"], + visibility = ["//visibility:public"], +) + +ktrusted( + name = "trusted-discard-action-no-valid-signers-no-action", + srcs = ["proof-discard-action-no-valid-signers-no-action.k"], + visibility = ["//visibility:public"], +) + +ktrusted( + name = "trusted-discard-action-no-valid-signers", + srcs = ["proof-discard-action-no-valid-signers.k"], + visibility = ["//visibility:public"], +) + +ktrusted( + name = "trusted-perform-action-endpoint-add-board-member-BoardMember-eq", + srcs = ["proof-perform-action-endpoint-add-board-member-BoardMember-eq.k"], + visibility = ["//visibility:public"], +) + +ktrusted( + name = "trusted-perform-action-endpoint-add-board-member-BoardMember", + srcs = ["proof-perform-action-endpoint-add-board-member-BoardMember.k"], + visibility = ["//visibility:public"], +) + +ktrusted( + name = "trusted-perform-action-endpoint-add-board-member-New", + srcs = ["proof-perform-action-endpoint-add-board-member-New.k"], + visibility = ["//visibility:public"], +) + +ktrusted( + name = "trusted-perform-action-endpoint-add-board-member-None", + srcs = ["proof-perform-action-endpoint-add-board-member-None.k"], + visibility = ["//visibility:public"], +) + +ktrusted( + name = "trusted-perform-action-endpoint-add-board-member-Proposer-eq", + srcs = ["proof-perform-action-endpoint-add-board-member-Proposer-eq.k"], + visibility = ["//visibility:public"], +) + +ktrusted( + name = "trusted-perform-action-endpoint-add-board-member-Proposer", + srcs = ["proof-perform-action-endpoint-add-board-member-Proposer.k"], + visibility = ["//visibility:public"], +) + +ktrusted( + name = "trusted-perform-action-endpoint-add-proposer-BoardMember-eq", + srcs = ["proof-perform-action-endpoint-add-proposer-BoardMember-eq.k"], + visibility = ["//visibility:public"], +) + +ktrusted( + name = "trusted-perform-action-endpoint-add-proposer-BoardMember", + srcs = ["proof-perform-action-endpoint-add-proposer-BoardMember.k"], + visibility = ["//visibility:public"], +) + +ktrusted( + name = "trusted-perform-action-endpoint-add-proposer-BoardMember-no-quorum-eq", + srcs = ["proof-perform-action-endpoint-add-proposer-BoardMember-no-quorum-eq.k"], + visibility = ["//visibility:public"], +) + +ktrusted( + name = "trusted-perform-action-endpoint-add-proposer-BoardMember-no-quorum", + srcs = ["proof-perform-action-endpoint-add-proposer-BoardMember-no-quorum.k"], + visibility = ["//visibility:public"], +) + +ktrusted( + name = "trusted-perform-action-endpoint-add-proposer-New", + srcs = ["proof-perform-action-endpoint-add-proposer-New.k"], + visibility = ["//visibility:public"], +) + +ktrusted( + name = "trusted-perform-action-endpoint-add-proposer-None", + srcs = ["proof-perform-action-endpoint-add-proposer-None.k"], + visibility = ["//visibility:public"], +) + +ktrusted( + name = "trusted-perform-action-endpoint-add-proposer-Proposer-eq", + srcs = ["proof-perform-action-endpoint-add-proposer-Proposer-eq.k"], + visibility = ["//visibility:public"], +) + +ktrusted( + name = "trusted-perform-action-endpoint-add-proposer-Proposer", + srcs = ["proof-perform-action-endpoint-add-proposer-Proposer.k"], + visibility = ["//visibility:public"], +) + +ktrusted( + name = "trusted-perform-action-endpoint-change-quorum", + srcs = ["proof-perform-action-endpoint-change-quorum.k"], + visibility = ["//visibility:public"], +) + +ktrusted( + name = "trusted-perform-action-endpoint-change-quorum-no-quorum", + srcs = ["proof-perform-action-endpoint-change-quorum-no-quorum.k"], + visibility = ["//visibility:public"], +) + +ktrusted( + name = "trusted-perform-action-endpoint-New", + srcs = ["proof-perform-action-endpoint-New.k"], + visibility = ["//visibility:public"], +) + +ktrusted( + name = "trusted-perform-action-endpoint-None", + srcs = ["proof-perform-action-endpoint-None.k"], + visibility = ["//visibility:public"], +) + +ktrusted( + name = "trusted-perform-action-endpoint-no-quorum", + srcs = ["proof-perform-action-endpoint-no-quorum.k"], + visibility = ["//visibility:public"], +) + +ktrusted( + name = "trusted-perform-action-endpoint-nothing", + srcs = ["proof-perform-action-endpoint-nothing.k"], + visibility = ["//visibility:public"], +) + +ktrusted( + name = "trusted-perform-action-endpoint-remove-user-BoardMember-eq", + srcs = ["proof-perform-action-endpoint-remove-user-BoardMember-eq.k"], + visibility = ["//visibility:public"], +) + +ktrusted( + name = "trusted-perform-action-endpoint-remove-user-BoardMember", + srcs = ["proof-perform-action-endpoint-remove-user-BoardMember.k"], + visibility = ["//visibility:public"], +) + +ktrusted( + name = "trusted-perform-action-endpoint-remove-user-BoardMember-too-few-eq", + srcs = ["proof-perform-action-endpoint-remove-user-BoardMember-too-few-eq.k"], + visibility = ["//visibility:public"], +) + +ktrusted( + name = "trusted-perform-action-endpoint-remove-user-BoardMember-too-few", + srcs = ["proof-perform-action-endpoint-remove-user-BoardMember-too-few.k"], + visibility = ["//visibility:public"], +) + +ktrusted( + name = "trusted-perform-action-endpoint-remove-user-New", + srcs = ["proof-perform-action-endpoint-remove-user-New.k"], + visibility = ["//visibility:public"], +) + +ktrusted( + name = "trusted-perform-action-endpoint-remove-user-None", + srcs = ["proof-perform-action-endpoint-remove-user-None.k"], + visibility = ["//visibility:public"], +) + +ktrusted( + name = "trusted-perform-action-endpoint-remove-user-Proposer-eq", + srcs = ["proof-perform-action-endpoint-remove-user-Proposer-eq.k"], + visibility = ["//visibility:public"], +) + +ktrusted( + name = "trusted-perform-action-endpoint-remove-user-Proposer", + srcs = ["proof-perform-action-endpoint-remove-user-Proposer.k"], + visibility = ["//visibility:public"], +) + +ktrusted( + name = "trusted-perform-action-endpoint-remove-user-Proposer-nobody-left-eq", + srcs = ["proof-perform-action-endpoint-remove-user-Proposer-nobody-left-eq.k"], + visibility = ["//visibility:public"], +) + +ktrusted( + name = "trusted-perform-action-endpoint-remove-user-Proposer-nobody-left", + srcs = ["proof-perform-action-endpoint-remove-user-Proposer-nobody-left.k"], + visibility = ["//visibility:public"], +) + +ktrusted( + name = "trusted-perform-action-endpoint-sc-call", + srcs = ["proof-perform-action-endpoint-sc-call.k"], + visibility = ["//visibility:public"], +) + +ktrusted( + name = "trusted-perform-action-endpoint-sc-deploy", + srcs = ["proof-perform-action-endpoint-sc-deploy.k"], + visibility = ["//visibility:public"], +) + +ktrusted( + name = "trusted-perform-action-endpoint-send-egld", + srcs = ["proof-perform-action-endpoint-send-egld.k"], + visibility = ["//visibility:public"], +) + diff --git a/multisig/protocol-correctness/proof/functions/Makefile b/multisig/protocol-correctness/proof/functions/Makefile new file mode 100644 index 000000000..fd8cddb9a --- /dev/null +++ b/multisig/protocol-correctness/proof/functions/Makefile @@ -0,0 +1,20 @@ +include ../settings.mak + +.PHONY: default +default: all ; + +SCRIPT_DIR = .. + +PROOF_DIR = .. +include $(PROOF_DIR)/proof-dependency.mak + +FUNCTIONS_DIR = . +include functions.mak + +.PHONY: all clean execution + +all: $(FUNCTIONS_OUT_PREFIX)proof.timestamp + +execution: $(FUNCTIONS_OUT_PREFIX)execution.timestamp $(FUNCTIONS_OUT_PREFIX)trusted.timestamp + +clean: functions.clean diff --git a/multisig/protocol-correctness/proof/functions/functions-dependency.mak b/multisig/protocol-correctness/proof/functions/functions-dependency.mak new file mode 100644 index 000000000..7b9623076 --- /dev/null +++ b/multisig/protocol-correctness/proof/functions/functions-dependency.mak @@ -0,0 +1,4 @@ +FUNCTIONS_ALL := $(wildcard $(FUNCTIONS_DIR)/*.k) +FUNCTIONS_PROOFS := $(wildcard $(FUNCTIONS_DIR)/proof-*.k) +FUNCTIONS_TRUSTED := $(wildcard $(FUNCTIONS_DIR)/trusted-*.k) +FUNCTIONS_EXECUTION := $(filter-out $(FUNCTIONS_TRUSTED), $(filter-out $(FUNCTIONS_PROOFS), $(FUNCTIONS_ALL))) $(PROOF_EXECUTION) diff --git a/multisig/protocol-correctness/proof/functions/functions-execute.k b/multisig/protocol-correctness/proof/functions/functions-execute.k new file mode 100644 index 000000000..abe0eb1a4 --- /dev/null +++ b/multisig/protocol-correctness/proof/functions/functions-execute.k @@ -0,0 +1,74 @@ +require "protocol-correctness/proof/execution-proof.k" + +module FUNCTIONS-EXECUTE-SYNTAX + imports EXECUTION-PROOF-SYNTAX +endmodule + +module PROPOSE-ACTION-INSTRUMENTATION + imports PROOF-INSTRUMENTATION + imports PSEUDOCODE + + syntax KItem ::= "split-propose-action" + syntax KItem ::= "split-propose-action1" + + rule preCall ~> (.K => split-propose-action) ~> call(proposeAction(_Action:Action)) + [priority(20)] + + rule split-propose-action + => branchK( + Caller in_keys(AddressToUserId), + makeConcreteValue(Caller, rUsize, AddressToUserId) + ~> split-propose-action1, + .K + ) + ... + AddressToUserId:Map + Caller:KItem + + rule split-propose-action1 + => branchK( + AddressToUserId[Caller] in_keys(UserIdToRole), + makeConcreteValue(AddressToUserId[Caller], rUserRole, UserIdToRole), + .K + ) + ... + AddressToUserId:Map + UserIdToRole:Map + Caller:KItem +endmodule + +module FUNCTIONS-INSTRUMENTATION + imports PROOF-INSTRUMENTATION + + rule preCall + ~> (.K => concretizeValue(Role)) + ~> call(canSign(Role:UserRole)) + [priority(20)] +endmodule + +module FUNCTIONS-HELPERS + imports PSEUDOCODE + + // TODO: Move to pseudocode.k + syntax Int ::= metadataToInt(CodeMetadata) [function, functional] + rule metadataToInt(meta(Value:Int)) => Value + + syntax CodeMetadata ::= codeMetadataFunction(upgradeable:Bool, payable:Bool, readable:Bool) + [function, functional] + rule codeMetadataFunction(Upgradeable:Bool, Payable:Bool, Readable:Bool) + => meta( + metadataToInt(CodeMetadata::DEFAULT) + |Int #if Upgradeable #then metadataToInt(CodeMetadata::UPGRADEABLE) #else 0 #fi + |Int #if Payable #then metadataToInt(CodeMetadata::PAYABLE) #else 0 #fi + |Int #if Readable #then metadataToInt(CodeMetadata::READABLE) #else 0 #fi + ) +endmodule + +module FUNCTIONS-EXECUTE + imports EXECUTION-PROOF + + imports FUNCTIONS-INSTRUMENTATION + imports PROPOSE-ACTION-INSTRUMENTATION + + imports FUNCTIONS-HELPERS +endmodule diff --git a/multisig/protocol-correctness/proof/functions/functions.mak b/multisig/protocol-correctness/proof/functions/functions.mak new file mode 100644 index 000000000..02a33e0c6 --- /dev/null +++ b/multisig/protocol-correctness/proof/functions/functions.mak @@ -0,0 +1,68 @@ +FUNCTIONS_OUT_PREFIX=.out/functions. + +FUNCTIONS_TRUSTED_DIR=$(FUNCTIONS_DIR) + +FUNCTIONS_DEPS_DIR=$(FUNCTIONS_DIR)/.deps + +include ${FUNCTIONS_DIR}/functions-dependency.mak + +FUNCTIONS_PROOF_TIMESTAMPS := $(addprefix $(FUNCTIONS_OUT_PREFIX),$(notdir ${FUNCTIONS_PROOFS:.k=.timestamp})) +FUNCTIONS_PROOF_DEBUGGERS := $(addprefix $(FUNCTIONS_OUT_PREFIX),$(notdir ${FUNCTIONS_PROOFS:.k=.debugger})) + +FUNCTIONS_DEPFILES := $(addprefix $(FUNCTIONS_DEPS_DIR)/,$(notdir ${FUNCTIONS_PROOFS:.k=.deps})) +FUNCTIONS_TRUSTED_FILES := $(addprefix $(FUNCTIONS_TRUSTED_DIR)/,$(patsubst proof-%.k,trusted-%.k,$(notdir ${FUNCTIONS_PROOFS}))) + +.PHONY: functions.clean ${FUNCTIONS_PROOF_DEBUGGERS} +.SECONDARY: + +# TODO: This is broken, I should add individual dependencies for each proof on their trusted imports. +$(FUNCTIONS_OUT_PREFIX)proof.timestamp: $(FUNCTIONS_OUT_PREFIX)trusted.timestamp ${FUNCTIONS_PROOF_TIMESTAMPS} + $(DIR_GUARD) + @touch $(FUNCTIONS_OUT_PREFIX)proof.timestamp + +$(FUNCTIONS_OUT_PREFIX)trusted.timestamp: ${FUNCTIONS_TRUSTED_FILES} + +$(FUNCTIONS_OUT_PREFIX)proof-%.timestamp: \ + ${FUNCTIONS_DIR}/proof-%.k \ + ${FUNCTIONS_DEPS_DIR}/proof-%.deps \ + $(FUNCTIONS_OUT_PREFIX)execution.timestamp + $(DIR_GUARD) + @echo "Proving $*..." + @cat /proc/uptime | sed 's/\s.*//' > $(FUNCTIONS_OUT_PREFIX)proof-$*.duration.temp + @((kprove $< --directory $(FUNCTIONS_DIR) --haskell-backend-command $(BACKEND_COMMAND) > $(FUNCTIONS_OUT_PREFIX)proof-$*.out 2>&1) && echo "$* done") || (cat $(FUNCTIONS_OUT_PREFIX)proof-$*.out; echo "$* failed"; echo "$*" >> $(FUNCTIONS_OUT_PREFIX)failures; false) + @cat /proc/uptime | sed 's/\s.*//' >> $(FUNCTIONS_OUT_PREFIX)proof-$*.duration.temp + @$(SCRIPT_DIR)/compute-duration.py $(FUNCTIONS_OUT_PREFIX)proof-$*.duration.temp > $(FUNCTIONS_OUT_PREFIX)proof-$*.duration + @rm $(FUNCTIONS_OUT_PREFIX)proof-$*.duration.temp + @touch $(FUNCTIONS_OUT_PREFIX)proof-$*.timestamp + +${FUNCTIONS_DEPS_DIR}/proof-%.deps: ${FUNCTIONS_DIR}/proof-%.k + $(DIR_GUARD) + @echo "Generating dependencies for $*..." + @kdep $< | sed 's#^.* : \\$$#$(FUNCTIONS_OUT_PREFIX)proof-$*.timestamp : \\#' > $@ + @kdep $< | sed 's#^.* : \\$$#$@ : \\#' >> $@ + +$(FUNCTIONS_TRUSTED_DIR)/trusted-%.k: ${FUNCTIONS_DIR}/proof-%.k $(SCRIPT_DIR)/make-trusted.py + $(DIR_GUARD) + @$(SCRIPT_DIR)/make-trusted.py $< $@ + +$(FUNCTIONS_OUT_PREFIX)proof-%.debugger: ${FUNCTIONS_DIR}/proof-%.k $(FUNCTIONS_OUT_PREFIX)execution.timestamp + $(DIR_GUARD) + @echo "Debugging $*..." + @kprove $< --directory $(FUNCTIONS_DIR) --haskell-backend-command $(DEBUG_COMMAND) + +$(FUNCTIONS_OUT_PREFIX)execution.timestamp: $(FUNCTIONS_DIR)/functions-execute.k $(FUNCTIONS_EXECUTION) + $(DIR_GUARD) + @echo "Compiling execution..." + @kompile $(KOMPILE_FLAGS) $< --backend haskell --directory $(FUNCTIONS_DIR) + @touch $(FUNCTIONS_OUT_PREFIX)kompile.timestamp + +functions.clean: + -rm -r $(FUNCTIONS_DIR)/*-kompiled + -rm -r .kprove-* + -rm kore-*.tar.gz + -rm $(FUNCTIONS_OUT_PREFIX)* + # TODO: Delete only function dependencies + -rm -r ${FUNCTIONS_DEPS_DIR} + +-include $(FUNCTIONS_DEPFILES) +-include $(FUNCTIONS_TRUSTED_DEPFILES) diff --git a/multisig/protocol-correctness/proof/functions/proof-change-user-role-BoardMember.k b/multisig/protocol-correctness/proof/functions/proof-change-user-role-BoardMember.k new file mode 100644 index 000000000..ebd7bb842 --- /dev/null +++ b/multisig/protocol-correctness/proof/functions/proof-change-user-role-BoardMember.k @@ -0,0 +1,55 @@ +//@ proof +module PROOF-CHANGE-USER-ROLE-BOARDMEMBER +//@ trusted +// module TRUSTED-CHANGE-USER-ROLE-BOARDMEMBER +//@ end + imports FUNCTIONS-EXECUTE + + claim + call(changeUserRole(UserAddress:Address, NewRole:UserRole)) ~> K:K + + invariantStateFull( + u(NumUsers:Int), + UserIdToAddress:Map, + (UserAddress |-> UserId:Usize _AddressToUserId:Map) #as AddressToUserId:Map, + u(NumBoardMembers:Int), + u(NumProposers:Int), + UserId |-> BoardMember UserIdToRole:Map, + Quorum:Usize, + u(ActionLastIndex:Int), + ActionData:Map, + ActionSigners:Map, + CallerAddress:Address, + Stack:Stack, + .Map, + PerformedActions:List + ) + + => + + evaluate(void) ~> K + invariantStateFull( + u(NumUsers), + UserIdToAddress, + AddressToUserId, + u(NumBoardMembers -Int 1 +Int #if NewRole ==K BoardMember #then 1 #else 0 #fi), + u(NumProposers +Int #if NewRole ==K Proposer #then 1 #else 0 #fi), + #if NewRole ==K None #then UserIdToRole #else UserId |-> NewRole UserIdToRole #fi, + Quorum, + u(ActionLastIndex), + ActionData, + ActionSigners, + CallerAddress, + Stack:Stack, + ?_Variables, + PerformedActions:List + ):StateCell + + requires true + andBool addressToUserIdInvariant(AddressToUserId) + ensures true + //@ proof + //@ trusted + // [trusted] + //@ end +endmodule diff --git a/multisig/protocol-correctness/proof/functions/proof-change-user-role-New.k b/multisig/protocol-correctness/proof/functions/proof-change-user-role-New.k new file mode 100644 index 000000000..dd581d0cb --- /dev/null +++ b/multisig/protocol-correctness/proof/functions/proof-change-user-role-New.k @@ -0,0 +1,61 @@ +//@ proof +module PROOF-CHANGE-USER-ROLE-NEW +//@ trusted +// module TRUSTED-CHANGE-USER-ROLE-NEW +//@ end + imports FUNCTIONS-EXECUTE + + claim + call(changeUserRole(UserAddress:Address, NewRole:UserRole)) ~> K:K + + invariantStateFull( + u(NumUsers:Int), + UserIdToAddress:Map, + AddressToUserId:Map, + u(NumBoardMembers:Int), + u(NumProposers:Int), + UserIdToRole:Map, + Quorum:Usize, + u(ActionLastIndex:Int), + ActionData:Map, + ActionSigners:Map, + CallerAddress:Address, + Stack:Stack, + .Map, + PerformedActions:List + ) + + => + + evaluate(void) ~> K + invariantStateFull( + u(NumUsers +Int 1), + u(NumUsers +Int 1) |-> UserAddress UserIdToAddress, + UserAddress |-> u(NumUsers +Int 1) AddressToUserId, + u(NumBoardMembers +Int #if NewRole ==K BoardMember #then 1 #else 0 #fi), + u(NumProposers +Int #if NewRole ==K Proposer #then 1 #else 0 #fi), + #if NewRole ==K None #then UserIdToRole #else u(NumUsers +Int 1) |-> NewRole UserIdToRole #fi, + Quorum, + u(ActionLastIndex), + ActionData, + ActionSigners, + CallerAddress, + Stack:Stack, + ?_Variables, + PerformedActions:List + ):StateCell + + requires true + andBool NumUsers >=Int 0 + // TODO: Perhaps replace with unusedIdsInMapValues(AddressToUserId) + + // something to map values to keys. + andBool unusedIdsInMapKeys(NumUsers +Int 1, keysMap(UserIdToAddress), expand(expanded)) + andBool unusedIdsInMapKeys(NumUsers +Int 1, keysMap(UserIdToRole), expand(expanded)) + + andBool notBool UserAddress in_keys(AddressToUserId) + ensures true + //@ proof + //@ trusted + // [trusted] + //@ end +endmodule diff --git a/multisig/protocol-correctness/proof/functions/proof-change-user-role-None.k b/multisig/protocol-correctness/proof/functions/proof-change-user-role-None.k new file mode 100644 index 000000000..6ab62ab09 --- /dev/null +++ b/multisig/protocol-correctness/proof/functions/proof-change-user-role-None.k @@ -0,0 +1,57 @@ +//@ proof +module PROOF-CHANGE-USER-ROLE-NONE +//@ trusted +// module TRUSTED-CHANGE-USER-ROLE-NONE +//@ end + imports FUNCTIONS-EXECUTE + + claim + call(changeUserRole(UserAddress:Address, NewRole:UserRole)) ~> K:K + + invariantStateFull( + u(NumUsers:Int), + UserIdToAddress:Map, + (UserAddress |-> UserId:Usize _AddressToUserId:Map) #as AddressToUserId:Map, + u(NumBoardMembers:Int), + u(NumProposers:Int), + UserIdToRole:Map, + Quorum:Usize, + u(ActionLastIndex:Int), + ActionData:Map, + ActionSigners:Map, + CallerAddress:Address, + Stack:Stack, + .Map, + PerformedActions:List + ) + + => + + evaluate(void) ~> K + invariantStateFull( + u(NumUsers), + UserIdToAddress, + AddressToUserId, + u(NumBoardMembers +Int #if NewRole ==K BoardMember #then 1 #else 0 #fi), + u(NumProposers +Int #if NewRole ==K Proposer #then 1 #else 0 #fi), + #if NewRole ==K None #then UserIdToRole #else UserId |-> NewRole UserIdToRole #fi, + Quorum, + u(ActionLastIndex), + ActionData, + ActionSigners, + CallerAddress, + Stack:Stack, + ?_Variables, + PerformedActions:List + ):StateCell + + requires true + andBool addressToUserIdInvariant(AddressToUserId) + + andBool notBool UserId in_keys(UserIdToRole) + ensures true + //@ proof + //@ trusted + // [trusted] + //@ end +endmodule diff --git a/multisig/protocol-correctness/proof/functions/proof-change-user-role-Proposer.k b/multisig/protocol-correctness/proof/functions/proof-change-user-role-Proposer.k new file mode 100644 index 000000000..42f8febd6 --- /dev/null +++ b/multisig/protocol-correctness/proof/functions/proof-change-user-role-Proposer.k @@ -0,0 +1,55 @@ +//@ proof +module PROOF-CHANGE-USER-ROLE-PROPOSER +//@ trusted +// module TRUSTED-CHANGE-USER-ROLE-PROPOSER +//@ end + imports FUNCTIONS-EXECUTE + + claim + call(changeUserRole(UserAddress:Address, NewRole:UserRole)) ~> K:K + + invariantStateFull( + u(NumUsers:Int), + UserIdToAddress:Map, + (UserAddress |-> UserId:Usize _AddressToUserId:Map) #as AddressToUserId:Map, + u(NumBoardMembers:Int), + u(NumProposers:Int), + UserId |-> Proposer UserIdToRole:Map, + Quorum:Usize, + u(ActionLastIndex:Int), + ActionData:Map, + ActionSigners:Map, + CallerAddress:Address, + Stack:Stack, + .Map, + PerformedActions:List + ) + + => + + evaluate(void) ~> K + invariantStateFull( + u(NumUsers), + UserIdToAddress, + AddressToUserId, + u(NumBoardMembers +Int #if NewRole ==K BoardMember #then 1 #else 0 #fi), + u(NumProposers -Int 1 +Int #if NewRole ==K Proposer #then 1 #else 0 #fi), + #if NewRole ==K None #then UserIdToRole #else UserId |-> NewRole UserIdToRole #fi, + Quorum, + u(ActionLastIndex), + ActionData, + ActionSigners, + CallerAddress, + Stack:Stack, + ?_Variables, + PerformedActions:List + ):StateCell + + requires true + andBool addressToUserIdInvariant(AddressToUserId) + ensures true + //@ proof + //@ trusted + // [trusted] + //@ end +endmodule diff --git a/multisig/protocol-correctness/proof/functions/proof-count-can-sign.k b/multisig/protocol-correctness/proof/functions/proof-count-can-sign.k new file mode 100644 index 000000000..ac401906c --- /dev/null +++ b/multisig/protocol-correctness/proof/functions/proof-count-can-sign.k @@ -0,0 +1,60 @@ +//@ proof +module PROOF-COUNT-CAN-SIGN + imports FUNCTIONS-EXECUTE +//@ trusted +// module TRUSTED-COUNT-CAN-SIGN + // imports EXECUTION-PROOF +//@ end + + claim + + call(countCanSign(SignerIds:ExpressionList)) ~> K:K + + invariantStateFull( + NumUsers:Usize, + UserIdToAddress:Map, + AddressToUserId:Map, + NumBoardMembers:Usize, + NumProposers:Usize, + UserIdToRole:Map, + Quorum:Usize, + ActionLastIndex:Usize, + ActionData:Map, + ActionSigners:Map, + CallerAddress:Address, + Stack:Stack, + .Map, + PerformedActions:List + ) + + => + + evaluate(u(countCanSignFunction(SignerIds, opaque(UserIdToRole)))) ~> K + + invariantStateFull( + NumUsers, + UserIdToAddress, + AddressToUserId, + NumBoardMembers, + NumProposers, + UserIdToRole, + Quorum, + ActionLastIndex, + ActionData, + ActionSigners, + CallerAddress, + Stack, + ?_Variables, + PerformedActions:List) + + requires true + andBool isKResult(SignerIds) + andBool listElementsAreUsize(SignerIds) + andBool userIdToRoleInvariant(UserIdToRole) + andBool listElementsAreDistinct(SignerIds) + ensures true + //@ proof + //@ trusted + // [trusted] + //@ end +endmodule diff --git a/multisig/protocol-correctness/proof/functions/proof-discard-action-has-signers.k b/multisig/protocol-correctness/proof/functions/proof-discard-action-has-signers.k new file mode 100644 index 000000000..23cf9d832 --- /dev/null +++ b/multisig/protocol-correctness/proof/functions/proof-discard-action-has-signers.k @@ -0,0 +1,71 @@ +//@ proof +require "trusted-count-can-sign.k" //@ Bazel remove +//@ trusted +//@ end + +//@ proof +module PROOF-DISCARD-ACTION-HAS-SIGNERS + imports FUNCTIONS-EXECUTE + imports TRUSTED-COUNT-CAN-SIGN +//@ trusted +// module TRUSTED-DISCARD-ACTION-HAS-SIGNERS + // imports EXECUTION-PROOF +//@ end + + claim + call(discardAction(ActionId:Usize)) ~> K:K + + invariantStateFull( + NumUsers:Usize, + UserIdToAddress:Map, + (CallerAddress |-> UserId:Usize _AddressToUserId:Map) #as AddressToUserId:Map, + NumBoardMembers:Usize, + NumProposers:Usize, + (UserId |-> Role:UserRole _UserIdToRole:Map) #as UserIdToRole:Map, + Quorum:Usize, + ActionLastIndex:Usize, + ActionData:Map, + (ActionId |-> SignerIds _ActionSigners:Map) #as ActionSigners:Map, + CallerAddress:Address, + Stack:Stack, + .Map, + PerformedActions:List + ) + + => + + error ~> K + invariantStateFull( + NumUsers, + UserIdToAddress, + AddressToUserId, + NumBoardMembers, + NumProposers, + UserIdToRole, + Quorum, + ActionLastIndex:Usize, + ActionData, + ActionSigners, + CallerAddress, + Stack:Stack, + ?_Variables, + PerformedActions:List + ):StateCell + + requires true + andBool notBool u(0) in_keys(UserIdToRole) + + andBool isKResult(SignerIds) + andBool listElementsAreUsize(SignerIds) + andBool userIdToRoleInvariant(UserIdToRole) + andBool listElementsAreDistinct(SignerIds) + + + andBool (Role ==K BoardMember orBool Role ==K Proposer) + andBool countCanSignFunction(SignerIds, opaque(UserIdToRole)) >Int 0 + ensures true + //@ proof + //@ trusted + // [trusted] + //@ end +endmodule diff --git a/multisig/protocol-correctness/proof/functions/proof-discard-action-no-role.k b/multisig/protocol-correctness/proof/functions/proof-discard-action-no-role.k new file mode 100644 index 000000000..f19cdeee8 --- /dev/null +++ b/multisig/protocol-correctness/proof/functions/proof-discard-action-no-role.k @@ -0,0 +1,57 @@ +//@ proof +module PROOF-DISCARD-ACTION-NO-ROLE +//@ trusted +// module TRUSTED-DISCARD-ACTION-NO-ROLE +//@ end + imports FUNCTIONS-EXECUTE + + claim + call(discardAction(_ActionId:Usize)) ~> K:K + + invariantStateFull( + NumUsers:Usize, + UserIdToAddress:Map, + (CallerAddress |-> UserId:Usize _AddressToUserId:Map) #as AddressToUserId:Map, + NumBoardMembers:Usize, + NumProposers:Usize, + UserIdToRole:Map, + Quorum:Usize, + ActionLastIndex:Usize, + ActionData:Map, + ActionSigners:Map, + CallerAddress:Address, + Stack:Stack, + .Map, + PerformedActions:List + ) + + => + + error ~> K + invariantStateFull( + NumUsers, + UserIdToAddress, + AddressToUserId, + NumBoardMembers, + NumProposers, + UserIdToRole, + Quorum, + ActionLastIndex:Usize, + ActionData, + ActionSigners, + CallerAddress, + Stack:Stack, + ?_Variables, + PerformedActions:List + ):StateCell + + requires true + andBool notBool u(0) in_keys(UserIdToRole) + + andBool notBool UserId in_keys(UserIdToRole) + ensures true + //@ proof + //@ trusted + // [trusted] + //@ end +endmodule diff --git a/multisig/protocol-correctness/proof/functions/proof-discard-action-no-signers-no-action.k b/multisig/protocol-correctness/proof/functions/proof-discard-action-no-signers-no-action.k new file mode 100644 index 000000000..5ecac37ee --- /dev/null +++ b/multisig/protocol-correctness/proof/functions/proof-discard-action-no-signers-no-action.k @@ -0,0 +1,69 @@ +//@ proof +require "trusted-count-can-sign.k" //@ Bazel remove +//@ trusted +//@ end + +//@ proof +module PROOF-DISCARD-ACTION-NO-SIGNERS-NO-ACTION + imports FUNCTIONS-EXECUTE + imports TRUSTED-COUNT-CAN-SIGN +//@ trusted +// module TRUSTED-DISCARD-ACTION-NO-SIGNERS-NO-ACTION + // imports EXECUTION-PROOF +//@ end + + claim + call(discardAction(ActionId:Usize)) ~> K:K + + invariantStateFull( + NumUsers:Usize, + UserIdToAddress:Map, + (CallerAddress |-> UserId:Usize _AddressToUserId:Map) #as AddressToUserId:Map, + NumBoardMembers:Usize, + NumProposers:Usize, + (UserId |-> Role:UserRole _UserIdToRole:Map) #as UserIdToRole:Map, + Quorum:Usize, + ActionLastIndex:Usize, + ActionData:Map, + ActionSigners:Map, + CallerAddress:Address, + Stack:Stack, + .Map, + PerformedActions:List + ) + + => + + void ~> K + invariantStateFull( + NumUsers, + UserIdToAddress, + AddressToUserId, + NumBoardMembers, + NumProposers, + UserIdToRole, + Quorum, + ActionLastIndex:Usize, + ActionData, + ActionSigners, + CallerAddress, + Stack:Stack, + ?_Variables, + PerformedActions:List + ):StateCell + + requires true + andBool notBool u(0) in_keys(UserIdToRole) + + andBool userIdToRoleInvariant(UserIdToRole) + + + andBool (Role ==K BoardMember orBool Role ==K Proposer) + andBool notBool ActionId in_keys(ActionSigners) + andBool notBool ActionId in_keys(ActionData) + ensures true + //@ proof + //@ trusted + // [trusted] + //@ end +endmodule diff --git a/multisig/protocol-correctness/proof/functions/proof-discard-action-no-signers.k b/multisig/protocol-correctness/proof/functions/proof-discard-action-no-signers.k new file mode 100644 index 000000000..f5fb2147d --- /dev/null +++ b/multisig/protocol-correctness/proof/functions/proof-discard-action-no-signers.k @@ -0,0 +1,68 @@ +//@ proof +require "trusted-count-can-sign.k" //@ Bazel remove +//@ trusted +//@ end + +//@ proof +module PROOF-DISCARD-ACTION-NO-SIGNERS + imports FUNCTIONS-EXECUTE + imports TRUSTED-COUNT-CAN-SIGN +//@ trusted +// module TRUSTED-DISCARD-ACTION-NO-SIGNERS + // imports EXECUTION-PROOF +//@ end + + claim + call(discardAction(ActionId:Usize)) ~> K:K + + invariantStateFull( + NumUsers:Usize, + UserIdToAddress:Map, + (CallerAddress |-> UserId:Usize _AddressToUserId:Map) #as AddressToUserId:Map, + NumBoardMembers:Usize, + NumProposers:Usize, + (UserId |-> Role:UserRole _UserIdToRole:Map) #as UserIdToRole:Map, + Quorum:Usize, + ActionLastIndex:Usize, + ActionId |-> _:Action ActionData:Map, + ActionSigners:Map, + CallerAddress:Address, + Stack:Stack, + .Map, + PerformedActions:List + ) + + => + + void ~> K + invariantStateFull( + NumUsers, + UserIdToAddress, + AddressToUserId, + NumBoardMembers, + NumProposers, + UserIdToRole, + Quorum, + ActionLastIndex:Usize, + ActionData, + ActionSigners, + CallerAddress, + Stack:Stack, + ?_Variables, + PerformedActions:List + ):StateCell + + requires true + andBool notBool u(0) in_keys(UserIdToRole) + + andBool userIdToRoleInvariant(UserIdToRole) + + + andBool (Role ==K BoardMember orBool Role ==K Proposer) + andBool notBool ActionId in_keys(ActionSigners) + ensures true + //@ proof + //@ trusted + // [trusted] + //@ end +endmodule diff --git a/multisig/protocol-correctness/proof/functions/proof-discard-action-no-user.k b/multisig/protocol-correctness/proof/functions/proof-discard-action-no-user.k new file mode 100644 index 000000000..6261376ab --- /dev/null +++ b/multisig/protocol-correctness/proof/functions/proof-discard-action-no-user.k @@ -0,0 +1,57 @@ +//@ proof +module PROOF-DISCARD-ACTION-NO-USER +//@ trusted +// module TRUSTED-DISCARD-ACTION-NO-USER +//@ end + imports FUNCTIONS-EXECUTE + + claim + call(discardAction(_ActionId:Usize)) ~> K:K + + invariantStateFull( + NumUsers:Usize, + UserIdToAddress:Map, + AddressToUserId:Map, + NumBoardMembers:Usize, + NumProposers:Usize, + UserIdToRole:Map, + Quorum:Usize, + ActionLastIndex:Usize, + ActionData:Map, + ActionSigners:Map, + CallerAddress:Address, + Stack:Stack, + .Map, + PerformedActions:List + ) + + => + + error ~> K + invariantStateFull( + NumUsers, + UserIdToAddress, + AddressToUserId, + NumBoardMembers, + NumProposers, + UserIdToRole, + Quorum, + ActionLastIndex:Usize, + ActionData, + ActionSigners, + CallerAddress, + Stack:Stack, + ?_Variables, + PerformedActions:List + ):StateCell + + requires true + andBool notBool u(0) in_keys(UserIdToRole) + + andBool notBool CallerAddress in_keys(AddressToUserId) + ensures true + //@ proof + //@ trusted + // [trusted] + //@ end +endmodule diff --git a/multisig/protocol-correctness/proof/functions/proof-discard-action-no-valid-signers-no-action.k b/multisig/protocol-correctness/proof/functions/proof-discard-action-no-valid-signers-no-action.k new file mode 100644 index 000000000..e5dfe0a83 --- /dev/null +++ b/multisig/protocol-correctness/proof/functions/proof-discard-action-no-valid-signers-no-action.k @@ -0,0 +1,74 @@ +//@ proof +require "trusted-count-can-sign.k" //@ Bazel remove +//@ trusted +//@ end + +//@ proof +module PROOF-DISCARD-ACTION-NO-VALID-SIGNERS-NO-ACTION + imports FUNCTIONS-EXECUTE + imports TRUSTED-COUNT-CAN-SIGN +//@ trusted +// module TRUSTED-DISCARD-ACTION-NO-VALID-SIGNERS-NO-ACTION + // imports EXECUTION-PROOF +//@ end + + // TODO: I think that this is an invalid case that should be discarded + // by the main invariant. + claim + call(discardAction(ActionId:Usize)) ~> K:K + + invariantStateFull( + NumUsers:Usize, + UserIdToAddress:Map, + (CallerAddress |-> UserId:Usize _AddressToUserId:Map) #as AddressToUserId:Map, + NumBoardMembers:Usize, + NumProposers:Usize, + (UserId |-> Role:UserRole _UserIdToRole:Map) #as UserIdToRole:Map, + Quorum:Usize, + ActionLastIndex:Usize, + ActionData:Map, + ActionId |-> SignerIds ActionSigners:Map, + CallerAddress:Address, + Stack:Stack, + .Map, + PerformedActions:List + ) + + => + + void ~> K + invariantStateFull( + NumUsers, + UserIdToAddress, + AddressToUserId, + NumBoardMembers, + NumProposers, + UserIdToRole, + Quorum, + ActionLastIndex:Usize, + ActionData, + ActionSigners, + CallerAddress, + Stack:Stack, + ?_Variables, + PerformedActions:List + ):StateCell + + requires true + andBool notBool u(0) in_keys(UserIdToRole) + + andBool isKResult(SignerIds) + andBool listElementsAreUsize(SignerIds) + andBool listElementsAreDistinct(SignerIds) + andBool userIdToRoleInvariant(UserIdToRole) + + + andBool (Role ==K BoardMember orBool Role ==K Proposer) + andBool countCanSignFunction(SignerIds, opaque(UserIdToRole)) ==Int 0 + andBool notBool ActionId in_keys(ActionData) + ensures true + //@ proof + //@ trusted + // [trusted] + //@ end +endmodule diff --git a/multisig/protocol-correctness/proof/functions/proof-discard-action-no-valid-signers.k b/multisig/protocol-correctness/proof/functions/proof-discard-action-no-valid-signers.k new file mode 100644 index 000000000..a65345a59 --- /dev/null +++ b/multisig/protocol-correctness/proof/functions/proof-discard-action-no-valid-signers.k @@ -0,0 +1,71 @@ +//@ proof +require "trusted-count-can-sign.k" //@ Bazel remove +//@ trusted +//@ end + +//@ proof +module PROOF-DISCARD-ACTION-NO-VALID-SIGNERS + imports FUNCTIONS-EXECUTE + imports TRUSTED-COUNT-CAN-SIGN +//@ trusted +// module TRUSTED-DISCARD-ACTION-NO-VALID-SIGNERS + // imports EXECUTION-PROOF +//@ end + + claim + call(discardAction(ActionId:Usize)) ~> K:K + + invariantStateFull( + NumUsers:Usize, + UserIdToAddress:Map, + (CallerAddress |-> UserId:Usize _AddressToUserId:Map) #as AddressToUserId:Map, + NumBoardMembers:Usize, + NumProposers:Usize, + (UserId |-> Role:UserRole _UserIdToRole:Map) #as UserIdToRole:Map, + Quorum:Usize, + ActionLastIndex:Usize, + ActionId |-> _:Action ActionData:Map, + ActionId |-> SignerIds ActionSigners:Map, + CallerAddress:Address, + Stack:Stack, + .Map, + PerformedActions:List + ) + + => + + void ~> K + invariantStateFull( + NumUsers, + UserIdToAddress, + AddressToUserId, + NumBoardMembers, + NumProposers, + UserIdToRole, + Quorum, + ActionLastIndex:Usize, + ActionData, + ActionSigners, + CallerAddress, + Stack:Stack, + ?_Variables, + PerformedActions:List + ):StateCell + + requires true + andBool notBool u(0) in_keys(UserIdToRole) + + andBool isKResult(SignerIds) + andBool listElementsAreUsize(SignerIds) + andBool listElementsAreDistinct(SignerIds) + andBool userIdToRoleInvariant(UserIdToRole) + + + andBool (Role ==K BoardMember orBool Role ==K Proposer) + andBool countCanSignFunction(SignerIds, opaque(UserIdToRole)) ==Int 0 + ensures true + //@ proof + //@ trusted + // [trusted] + //@ end +endmodule diff --git a/multisig/protocol-correctness/proof/functions/proof-perform-action-add-board-member-BoardMember.k b/multisig/protocol-correctness/proof/functions/proof-perform-action-add-board-member-BoardMember.k new file mode 100644 index 000000000..6cfaaf94d --- /dev/null +++ b/multisig/protocol-correctness/proof/functions/proof-perform-action-add-board-member-BoardMember.k @@ -0,0 +1,85 @@ +//@ proof +require "trusted-change-user-role-BoardMember.k" //@ Bazel remove + +module PROOF-PERFORM-ACTION-ADD-BOARD-MEMBER-BOARDMEMBER + imports TRUSTED-CHANGE-USER-ROLE-BOARDMEMBER +//@ trusted +// module TRUSTED-PERFORM-ACTION-ADD-BOARD-MEMBER-BOARDMEMBER +//@ end + + imports INVARIANT-HELPERS + imports PSEUDOCODE + + claim + + call(performAction( + AddBoardMember(UserAddress:Address) #as Action:Action + )) ~> K:K + + + + + NumUsers:Usize + UserIdToAddress:Map + (UserAddress |-> UserId:Usize _AddressToUserId:Map) #as AddressToUserId:Map + + + NumBoardMembers:Usize + NumProposers:Usize + (UserId |-> BoardMember _UserIdToRole:Map) #as UserIdToRole:Map + Quorum:Usize + + ActionState:ActionStateCell + + + .Map + Stack:Stack + + + CallerAddress:Address + + + PerformedActions:List + + + + => + + evaluate(void) ~> K + + + + NumUsers + UserIdToAddress + AddressToUserId + + + NumBoardMembers + NumProposers + UserIdToRole + Quorum + + ActionState + + + ?_Variables:Map + Stack + + + CallerAddress + + + ListItem(Action) PerformedActions + + + + requires true + andBool isKResult(Action) + andBool addressToUserIdInvariant(AddressToUserId) + ensures true + //@ proof + //@ trusted + // [trusted] + //@ end + +endmodule diff --git a/multisig/protocol-correctness/proof/functions/proof-perform-action-add-board-member-New.k b/multisig/protocol-correctness/proof/functions/proof-perform-action-add-board-member-New.k new file mode 100644 index 000000000..b2ee711a8 --- /dev/null +++ b/multisig/protocol-correctness/proof/functions/proof-perform-action-add-board-member-New.k @@ -0,0 +1,92 @@ +//@ proof +require "trusted-change-user-role-New.k" //@ Bazel remove + +module PROOF-PERFORM-ACTION-ADD-BOARD-MEMBER-NEW + imports TRUSTED-CHANGE-USER-ROLE-NEW +//@ trusted +// module TRUSTED-PERFORM-ACTION-ADD-BOARD-MEMBER-NEW +//@ end + + imports EXECUTION-PROOF-HELPERS + imports PSEUDOCODE + + claim + + call(performAction( + AddBoardMember(UserAddress:Address) #as Action:Action + )) ~> K:K + + + + + u(NumUsers:Int) + UserIdToAddress:Map + AddressToUserId:Map + + + u(NumBoardMembers:Int) + NumProposers:Usize + UserIdToRole:Map + Quorum:Usize + + ActionState:ActionStateCell + + + .Map + Stack:Stack + + + CallerAddress:Address + + + PerformedActions:List + + + + => + + evaluate(void) ~> K + + + + u(NumUsers +Int 1) + u(NumUsers +Int 1) |-> UserAddress UserIdToAddress + UserAddress |-> u(NumUsers +Int 1) AddressToUserId + + + u(NumBoardMembers +Int 1) + NumProposers + u(NumUsers +Int 1) |-> BoardMember UserIdToRole + Quorum + + ActionState + + + ?_Variables:Map + Stack + + + CallerAddress + + + ListItem(Action) PerformedActions + + + + requires true + andBool isKResult(Action) + + andBool NumUsers >=Int 0 + // TODO: Perhaps replace with unusedIdsInMapValues(AddressToUserId) + + // someting to map values to keys. + andBool unusedIdsInMapKeys(NumUsers +Int 1, keysMap(UserIdToAddress), expand(expanded)) + andBool unusedIdsInMapKeys(NumUsers +Int 1, keysMap(UserIdToRole), expand(expanded)) + + andBool notBool UserAddress in_keys(AddressToUserId) + ensures true + //@ proof + //@ trusted + // [trusted] + //@ end + +endmodule diff --git a/multisig/protocol-correctness/proof/functions/proof-perform-action-add-board-member-None.k b/multisig/protocol-correctness/proof/functions/proof-perform-action-add-board-member-None.k new file mode 100644 index 000000000..983d3399f --- /dev/null +++ b/multisig/protocol-correctness/proof/functions/proof-perform-action-add-board-member-None.k @@ -0,0 +1,87 @@ +//@ proof +require "trusted-change-user-role-None.k" //@ Bazel remove + +module PROOF-PERFORM-ACTION-ADD-BOARD-MEMBER-NONE + imports TRUSTED-CHANGE-USER-ROLE-NONE +//@ trusted +// module TRUSTED-PERFORM-ACTION-ADD-BOARD-MEMBER-NONE +//@ end + + imports INVARIANT-HELPERS + imports PSEUDOCODE + + claim + + call(performAction( + AddBoardMember(UserAddress:Address) #as Action:Action + )) ~> K:K + + + + + NumUsers:Usize + UserIdToAddress:Map + (UserAddress |-> UserId:Usize _AddressToUserId:Map) #as AddressToUserId:Map + + + u(NumBoardMembers:Int) + NumProposers:Usize + UserIdToRole:Map + Quorum:Usize + + ActionState:ActionStateCell + + + .Map + Stack:Stack + + + CallerAddress:Address + + + PerformedActions:List + + + + => + + evaluate(void) ~> K + + + + NumUsers + UserIdToAddress + AddressToUserId + + + u(NumBoardMembers +Int 1) + NumProposers + UserId |-> BoardMember UserIdToRole + Quorum + + ActionState + + + ?_Variables:Map + Stack + + + CallerAddress + + + ListItem(Action) PerformedActions + + + + requires true + andBool isKResult(Action) + andBool addressToUserIdInvariant(AddressToUserId) + + andBool notBool UserId in_keys(UserIdToRole) + ensures true + //@ proof + //@ trusted + // [trusted] + //@ end + +endmodule diff --git a/multisig/protocol-correctness/proof/functions/proof-perform-action-add-board-member-Proposer.k b/multisig/protocol-correctness/proof/functions/proof-perform-action-add-board-member-Proposer.k new file mode 100644 index 000000000..460ff47f8 --- /dev/null +++ b/multisig/protocol-correctness/proof/functions/proof-perform-action-add-board-member-Proposer.k @@ -0,0 +1,85 @@ +//@ proof +require "trusted-change-user-role-Proposer.k" //@ Bazel remove + +module PROOF-PERFORM-ACTION-ADD-BOARD-MEMBER-PROPOSER + imports TRUSTED-CHANGE-USER-ROLE-PROPOSER +//@ trusted +// module TRUSTED-PERFORM-ACTION-ADD-BOARD-MEMBER-PROPOSER +//@ end + + imports INVARIANT-HELPERS + imports PSEUDOCODE + + claim + + call(performAction( + AddBoardMember(UserAddress:Address) #as Action:Action + )) ~> K:K + + + + + NumUsers:Usize + UserIdToAddress:Map + (UserAddress |-> UserId:Usize _AddressToUserId:Map) #as AddressToUserId:Map + + + u(NumBoardMembers:Int) + u(NumProposers:Int) + UserId |-> Proposer UserIdToRole:Map + Quorum:Usize + + ActionState:ActionStateCell + + + .Map + Stack:Stack + + + CallerAddress:Address + + + PerformedActions:List + + + + => + + evaluate(void) ~> K + + + + NumUsers + UserIdToAddress + AddressToUserId + + + u(NumBoardMembers +Int 1) + u(NumProposers -Int 1) + UserId |-> BoardMember UserIdToRole:Map + Quorum + + ActionState + + + ?_Variables:Map + Stack + + + CallerAddress + + + ListItem(Action) PerformedActions + + + + requires true + andBool isKResult(Action) + andBool addressToUserIdInvariant(AddressToUserId) + ensures true + //@ proof + //@ trusted + // [trusted] + //@ end + +endmodule diff --git a/multisig/protocol-correctness/proof/functions/proof-perform-action-add-proposer-BoardMember-no-quorum.k b/multisig/protocol-correctness/proof/functions/proof-perform-action-add-proposer-BoardMember-no-quorum.k new file mode 100644 index 000000000..16619666b --- /dev/null +++ b/multisig/protocol-correctness/proof/functions/proof-perform-action-add-proposer-BoardMember-no-quorum.k @@ -0,0 +1,87 @@ +//@ proof +require "trusted-change-user-role-BoardMember.k" //@ Bazel remove + +module PROOF-PERFORM-ACTION-ADD-PROPOSER-BOARDMEMBER-NO-QUORUM + imports TRUSTED-CHANGE-USER-ROLE-BOARDMEMBER +//@ trusted +// module TRUSTED-PERFORM-ACTION-ADD-PROPOSER-BOARDMEMBER-NO-QUORUM +//@ end + + imports INVARIANT-HELPERS + imports PSEUDOCODE + + claim + + call(performAction( + AddProposer(UserAddress:Address) #as Action:Action + )) ~> K:K + + + + + NumUsers:Usize + UserIdToAddress:Map + (UserAddress |-> UserId:Usize _AddressToUserId:Map) #as AddressToUserId:Map + + + u(NumBoardMembers:Int) + u(NumProposers:Int) + UserId |-> BoardMember UserIdToRole:Map + u(Quorum:Int) + + ActionState:ActionStateCell + + + .Map + Stack:Stack + + + CallerAddress:Address + + + PerformedActions:List + + + + => + + error ~> K + + + + NumUsers + UserIdToAddress + AddressToUserId + + + u(NumBoardMembers -Int 1) + u(NumProposers +Int 1) + UserId |-> Proposer UserIdToRole:Map + u(Quorum) + + ActionState + + + ?_Variables:Map + Stack + + + CallerAddress + + + ListItem(Action) PerformedActions + + + + requires true + andBool isKResult(Action) + andBool addressToUserIdInvariant(AddressToUserId) + + andBool Quorum ==Int NumBoardMembers + ensures true + //@ proof + //@ trusted + // [trusted] + //@ end + +endmodule diff --git a/multisig/protocol-correctness/proof/functions/proof-perform-action-add-proposer-BoardMember.k b/multisig/protocol-correctness/proof/functions/proof-perform-action-add-proposer-BoardMember.k new file mode 100644 index 000000000..ca20a3a23 --- /dev/null +++ b/multisig/protocol-correctness/proof/functions/proof-perform-action-add-proposer-BoardMember.k @@ -0,0 +1,87 @@ +//@ proof +require "trusted-change-user-role-BoardMember.k" //@ Bazel remove + +module PROOF-PERFORM-ACTION-ADD-PROPOSER-BOARDMEMBER + imports TRUSTED-CHANGE-USER-ROLE-BOARDMEMBER +//@ trusted +// module TRUSTED-PERFORM-ACTION-ADD-PROPOSER-BOARDMEMBER +//@ end + + imports INVARIANT-HELPERS + imports PSEUDOCODE + + claim + + call(performAction( + AddProposer(UserAddress:Address) #as Action:Action + )) ~> K:K + + + + + NumUsers:Usize + UserIdToAddress:Map + (UserAddress |-> UserId:Usize _AddressToUserId:Map) #as AddressToUserId:Map + + + u(NumBoardMembers:Int) + u(NumProposers:Int) + UserId |-> BoardMember UserIdToRole:Map + u(Quorum:Int) + + ActionState:ActionStateCell + + + .Map + Stack:Stack + + + CallerAddress:Address + + + PerformedActions:List + + + + => + + evaluate(void) ~> K + + + + NumUsers + UserIdToAddress + AddressToUserId + + + u(NumBoardMembers -Int 1) + u(NumProposers +Int 1) + UserId |-> Proposer UserIdToRole:Map + u(Quorum) + + ActionState + + + ?_Variables:Map + Stack + + + CallerAddress + + + ListItem(Action) PerformedActions + + + + requires true + andBool isKResult(Action) + andBool addressToUserIdInvariant(AddressToUserId) + + andBool Quorum <=Int NumBoardMembers -Int 1 + ensures true + //@ proof + //@ trusted + // [trusted] + //@ end + +endmodule diff --git a/multisig/protocol-correctness/proof/functions/proof-perform-action-add-proposer-New.k b/multisig/protocol-correctness/proof/functions/proof-perform-action-add-proposer-New.k new file mode 100644 index 000000000..4eb8a389c --- /dev/null +++ b/multisig/protocol-correctness/proof/functions/proof-perform-action-add-proposer-New.k @@ -0,0 +1,93 @@ +//@ proof +require "trusted-change-user-role-New.k" //@ Bazel remove + +module PROOF-PERFORM-ACTION-ADD-PROPOSER-NEW + imports TRUSTED-CHANGE-USER-ROLE-NEW +//@ trusted +// module TRUSTED-PERFORM-ACTION-ADD-PROPOSER-NEW +//@ end + + imports EXECUTION-PROOF-HELPERS + imports PSEUDOCODE + + claim + + call(performAction( + AddProposer(UserAddress:Address) #as Action:Action + )) ~> K:K + + + + + u(NumUsers:Int) + UserIdToAddress:Map + AddressToUserId:Map + + + u(NumBoardMembers:Int) + u(NumProposers:Int) + UserIdToRole:Map + u(Quorum:Int) + + ActionState:ActionStateCell + + + .Map + Stack:Stack + + + CallerAddress:Address + + + PerformedActions:List + + + + => + + evaluate(void) ~> K + + + + u(NumUsers +Int 1) + u(NumUsers +Int 1) |-> UserAddress UserIdToAddress + UserAddress |-> u(NumUsers +Int 1) AddressToUserId + + + u(NumBoardMembers) + u(NumProposers +Int 1) + u(NumUsers +Int 1) |-> Proposer UserIdToRole + u(Quorum) + + ActionState + + + ?_Variables:Map + Stack + + + CallerAddress + + + ListItem(Action) PerformedActions + + + + requires true + andBool isKResult(Action) + + andBool NumUsers >=Int 0 + // TODO: Perhaps replace with unusedIdsInMapValues(AddressToUserId) + + // someting to map values to keys. + andBool unusedIdsInMapKeys(NumUsers +Int 1, keysMap(UserIdToAddress), expand(expanded)) + andBool unusedIdsInMapKeys(NumUsers +Int 1, keysMap(UserIdToRole), expand(expanded)) + andBool Quorum <=Int NumBoardMembers + + andBool notBool UserAddress in_keys(AddressToUserId) + ensures true + //@ proof + //@ trusted + // [trusted] + //@ end + +endmodule diff --git a/multisig/protocol-correctness/proof/functions/proof-perform-action-add-proposer-None.k b/multisig/protocol-correctness/proof/functions/proof-perform-action-add-proposer-None.k new file mode 100644 index 000000000..7f264ff6d --- /dev/null +++ b/multisig/protocol-correctness/proof/functions/proof-perform-action-add-proposer-None.k @@ -0,0 +1,88 @@ +//@ proof +require "trusted-change-user-role-None.k" //@ Bazel remove + +module PROOF-PERFORM-ACTION-ADD-PROPOSER-NONE + imports TRUSTED-CHANGE-USER-ROLE-NONE +//@ trusted +// module TRUSTED-PERFORM-ACTION-ADD-PROPOSER-NONE +//@ end + + imports INVARIANT-HELPERS + imports PSEUDOCODE + + claim + + call(performAction( + AddProposer(UserAddress:Address) #as Action:Action + )) ~> K:K + + + + + NumUsers:Usize + UserIdToAddress:Map + (UserAddress |-> UserId:Usize _AddressToUserId:Map) #as AddressToUserId:Map + + + u(NumBoardMembers:Int) + u(NumProposers:Int) + UserIdToRole:Map + u(Quorum:Int) + + ActionState:ActionStateCell + + + .Map + Stack:Stack + + + CallerAddress:Address + + + PerformedActions:List + + + + => + + evaluate(void) ~> K + + + + NumUsers + UserIdToAddress + AddressToUserId + + + u(NumBoardMembers) + u(NumProposers +Int 1) + UserId |-> Proposer UserIdToRole + u(Quorum) + + ActionState + + + ?_Variables:Map + Stack + + + CallerAddress + + + ListItem(Action) PerformedActions + + + + requires true + andBool isKResult(Action) + andBool addressToUserIdInvariant(AddressToUserId) + andBool Quorum <=Int NumBoardMembers + + andBool notBool UserId in_keys(UserIdToRole) + ensures true + //@ proof + //@ trusted + // [trusted] + //@ end + +endmodule diff --git a/multisig/protocol-correctness/proof/functions/proof-perform-action-add-proposer-Proposer.k b/multisig/protocol-correctness/proof/functions/proof-perform-action-add-proposer-Proposer.k new file mode 100644 index 000000000..764a83197 --- /dev/null +++ b/multisig/protocol-correctness/proof/functions/proof-perform-action-add-proposer-Proposer.k @@ -0,0 +1,86 @@ +//@ proof +require "trusted-change-user-role-Proposer.k" //@ Bazel remove + +module PROOF-PERFORM-ACTION-ADD-PROPOSER-PROPOSER + imports TRUSTED-CHANGE-USER-ROLE-PROPOSER +//@ trusted +// module TRUSTED-PERFORM-ACTION-ADD-PROPOSER-PROPOSER +//@ end + + imports INVARIANT-HELPERS + imports PSEUDOCODE + + claim + + call(performAction( + AddProposer(UserAddress:Address) #as Action:Action + )) ~> K:K + + + + + NumUsers:Usize + UserIdToAddress:Map + (UserAddress |-> UserId:Usize _AddressToUserId:Map) #as AddressToUserId:Map + + + u(NumBoardMembers:Int) + NumProposers:Usize + (UserId |-> Proposer _UserIdToRole:Map) #as UserIdToRole:Map + u(Quorum:Int) + + ActionState:ActionStateCell + + + .Map + Stack:Stack + + + CallerAddress:Address + + + PerformedActions:List + + + + => + + evaluate(void) ~> K + + + + NumUsers + UserIdToAddress + AddressToUserId + + + u(NumBoardMembers) + NumProposers + UserIdToRole + u(Quorum) + + ActionState + + + ?_Variables:Map + Stack + + + CallerAddress + + + ListItem(Action) PerformedActions + + + + requires true + andBool isKResult(Action) + andBool addressToUserIdInvariant(AddressToUserId) + andBool Quorum <=Int NumBoardMembers + ensures true + //@ proof + //@ trusted + // [trusted] + //@ end + +endmodule diff --git a/multisig/protocol-correctness/proof/functions/proof-perform-action-change-quorum-no-quorum.k b/multisig/protocol-correctness/proof/functions/proof-perform-action-change-quorum-no-quorum.k new file mode 100644 index 000000000..f8de0b559 --- /dev/null +++ b/multisig/protocol-correctness/proof/functions/proof-perform-action-change-quorum-no-quorum.k @@ -0,0 +1,81 @@ +//@ proof +module PROOF-PERFORM-ACTION-CHANGE-QUORUM-NO-QUORUM +//@ trusted +// module TRUSTED-PERFORM-ACTION-CHANGE-QUORUM-NO-QUORUM +//@ end + + imports PSEUDOCODE + + claim + + call(performAction( + ChangeQuorum(u(NewQuorum:Int)) #as Action:Action + )) ~> K:K + + + + + NumUsers:Usize + UserIdToAddress:Map + AddressToUserId:Map + + + u(NumBoardMembers:Int) + NumProposers:Usize + UserIdToRole:Map + OldQuorum:Usize + + ActionState:ActionStateCell + + + .Map + Stack:Stack + + + CallerAddress:Address + + + PerformedActions:List + + + + => + + error ~> K + + + + NumUsers + UserIdToAddress + AddressToUserId + + + u(NumBoardMembers) + NumProposers + UserIdToRole + OldQuorum + + ActionState + + + ?_Variables:Map + Stack + + + CallerAddress + + + ListItem(Action) PerformedActions + + + + requires true + andBool isKResult(Action) + andBool NewQuorum >Int NumBoardMembers + ensures true + //@ proof + //@ trusted + // [trusted] + //@ end + +endmodule diff --git a/multisig/protocol-correctness/proof/functions/proof-perform-action-change-quorum.k b/multisig/protocol-correctness/proof/functions/proof-perform-action-change-quorum.k new file mode 100644 index 000000000..f8bc3be33 --- /dev/null +++ b/multisig/protocol-correctness/proof/functions/proof-perform-action-change-quorum.k @@ -0,0 +1,81 @@ +//@ proof +module PROOF-PERFORM-ACTION-CHANGE-QUORUM +//@ trusted +// module TRUSTED-PERFORM-ACTION-CHANGE-QUORUM +//@ end + + imports PSEUDOCODE + + claim + + call(performAction( + ChangeQuorum(u(NewQuorum:Int)) #as Action:Action + )) ~> K:K + + + + + NumUsers:Usize + UserIdToAddress:Map + AddressToUserId:Map + + + u(NumBoardMembers:Int) + NumProposers:Usize + UserIdToRole:Map + _OldQuorum:Usize + + ActionState:ActionStateCell + + + .Map + Stack:Stack + + + CallerAddress:Address + + + PerformedActions:List + + + + => + + evaluate(void) ~> K + + + + NumUsers + UserIdToAddress + AddressToUserId + + + u(NumBoardMembers) + NumProposers + UserIdToRole + u(NewQuorum) + + ActionState + + + ?_Variables:Map + Stack + + + CallerAddress + + + ListItem(Action) PerformedActions + + + + requires true + andBool isKResult(Action) + andBool NewQuorum <=Int NumBoardMembers + ensures true + //@ proof + //@ trusted + // [trusted] + //@ end + +endmodule diff --git a/multisig/protocol-correctness/proof/functions/proof-perform-action-endpoint-New.k b/multisig/protocol-correctness/proof/functions/proof-perform-action-endpoint-New.k new file mode 100644 index 000000000..d5bcdbf2c --- /dev/null +++ b/multisig/protocol-correctness/proof/functions/proof-perform-action-endpoint-New.k @@ -0,0 +1,60 @@ +//@ proof +require "trusted-perform-action-endpoint-fragment-new.k" //@ Bazel remove + +module PROOF-PERFORM-ACTION-ENDPOINT-NEW + imports TRUSTED-PERFORM-ACTION-ENDPOINT-FRAGMENT-NEW +//@ trusted +// module TRUSTED-PERFORM-ACTION-ENDPOINT-NEW +//@ end + imports FUNCTIONS-EXECUTE + + claim + call(performActionEndpoint(_ActionId:Usize)) ~> K:K + invariantStateFull( + NumUsers:Usize, + UserIdToAddress:Map, + AddressToUserId:Map, + NumBoardMembers:Usize, + NumProposers:Usize, + UserIdToRole:Map, + Quorum:Usize, + ActionLastIndex:Usize, + ActionData:Map, + ActionSigners:Map, + CallerAddress:Address, + Stack:Stack, + .Map, + PerformedActions:List + ) + + => + + error ~> K:K + invariantStateFull( + NumUsers, + UserIdToAddress, + AddressToUserId, + NumBoardMembers, + NumProposers, + UserIdToRole, + Quorum, + ActionLastIndex, + ActionData, + ActionSigners, + CallerAddress, + Stack, + caller_address |-> CallerAddress + caller_id |-> u(0) + caller_role |-> None, + PerformedActions + ) + + requires true + andBool notBool CallerAddress in_keys(AddressToUserId) + andBool notBool u(0) in_keys(UserIdToRole) + ensures true + //@ proof + //@ trusted + // [trusted] + //@ end +endmodule diff --git a/multisig/protocol-correctness/proof/functions/proof-perform-action-endpoint-None.k b/multisig/protocol-correctness/proof/functions/proof-perform-action-endpoint-None.k new file mode 100644 index 000000000..049b6f179 --- /dev/null +++ b/multisig/protocol-correctness/proof/functions/proof-perform-action-endpoint-None.k @@ -0,0 +1,59 @@ +//@ proof +require "trusted-perform-action-endpoint-fragment-none.k" //@ Bazel remove + +module PROOF-PERFORM-ACTION-ENDPOINT-NONE + imports TRUSTED-PERFORM-ACTION-ENDPOINT-FRAGMENT-NONE +//@ trusted +// module TRUSTED-PERFORM-ACTION-ENDPOINT-NONE +//@ end + imports FUNCTIONS-EXECUTE + + claim + call(performActionEndpoint(_ActionId:Usize)) ~> K:K + invariantStateFull( + NumUsers:Usize, + UserIdToAddress:Map, + (CallerAddress |-> UserId:Usize _AddressToUserId:Map) #as AddressToUserId:Map, + NumBoardMembers:Usize, + NumProposers:Usize, + UserIdToRole:Map, + Quorum:Usize, + ActionLastIndex:Usize, + ActionData:Map, + ActionSigners:Map, + CallerAddress:Address, + Stack:Stack, + .Map, + PerformedActions:List + ) + + => + + error ~> K:K + invariantStateFull( + NumUsers, + UserIdToAddress, + AddressToUserId, + NumBoardMembers, + NumProposers, + UserIdToRole, + Quorum, + ActionLastIndex, + ActionData, + ActionSigners, + CallerAddress, + Stack, + caller_address |-> CallerAddress + caller_id |-> UserId + caller_role |-> None, + PerformedActions + ) + + requires true + andBool notBool UserId in_keys(UserIdToRole) + ensures true + //@ proof + //@ trusted + // [trusted] + //@ end +endmodule diff --git a/multisig/protocol-correctness/proof/functions/proof-perform-action-endpoint-add-board-member-BoardMember-eq.k b/multisig/protocol-correctness/proof/functions/proof-perform-action-endpoint-add-board-member-BoardMember-eq.k new file mode 100644 index 000000000..b5e964409 --- /dev/null +++ b/multisig/protocol-correctness/proof/functions/proof-perform-action-endpoint-add-board-member-BoardMember-eq.k @@ -0,0 +1,71 @@ +//@ proof +require "trusted-perform-action-endpoint-fragment-performs.k" //@ Bazel remove +require "trusted-perform-action-endpoint-id-add-board-member-boardmember.k" //@ Bazel remove + +module PROOF-PERFORM-ACTION-ENDPOINT-ADD-BOARD-MEMBER-BOARDMEMBER-EQ + imports TRUSTED-PERFORM-ACTION-ENDPOINT-FRAGMENT-PERFORMS + imports TRUSTED-PERFORM-ACTION-ID-ADD-BOARD-MEMBER-BOARDMEMBER +//@ trusted +// module TRUSTED-PERFORM-ACTION-ENDPOINT-ADD-BOARD-MEMBER-BOARDMEMBER-EQ +//@ end + imports FUNCTIONS-EXECUTE + + claim + call(performActionEndpoint(ActionId:Usize)) ~> K:K + invariantStateFull( + NumUsers:Usize, + UserIdToAddress:Map, + (CallerAddress |-> CallerId:Usize + _AddressToUserId:Map + ) #as AddressToUserId:Map, + NumBoardMembers:Usize, + NumProposers:Usize, + (CallerId |-> BoardMember + _UserIdToRole:Map + ) #as UserIdToRole:Map, + u(Quorum:Int), + ActionLastIndex:Usize, + ActionId |-> AddBoardMember(CallerAddress:Address) #as Action:Action + ActionData:Map, + ActionSigners:Map, + CallerAddress:Address, + Stack:Stack, + .Map, + PerformedActions:List + ) + + => + + evaluate(void) ~> K:K + invariantStateFull( + NumUsers, + UserIdToAddress, + AddressToUserId, + NumBoardMembers, + NumProposers, + UserIdToRole, + u(Quorum), + ActionLastIndex, + ActionData, + ActionSigners[ActionId <- undef], + CallerAddress, + Stack, + ?_Variables:Map, + ListItem(Action) PerformedActions + ) + + requires true + // perform-from-id + andBool isKResult(Action) + andBool addressToUserIdInvariant(AddressToUserId) + + // perform-fragment + andBool actionSignersInvariant(ActionSigners) + andBool userIdToRoleInvariant(UserIdToRole) + andBool Quorum <=Int countCanSignFunction({ActionSigners[ActionId] orDefault [.]}:>ExpressionList, opaque(UserIdToRole)) + ensures true + //@ proof + //@ trusted + // [trusted] + //@ end +endmodule diff --git a/multisig/protocol-correctness/proof/functions/proof-perform-action-endpoint-add-board-member-BoardMember.k b/multisig/protocol-correctness/proof/functions/proof-perform-action-endpoint-add-board-member-BoardMember.k new file mode 100644 index 000000000..a25a78256 --- /dev/null +++ b/multisig/protocol-correctness/proof/functions/proof-perform-action-endpoint-add-board-member-BoardMember.k @@ -0,0 +1,74 @@ +//@ proof +require "trusted-perform-action-endpoint-fragment-performs.k" //@ Bazel remove +require "trusted-perform-action-endpoint-id-add-board-member-BoardMember.k" //@ Bazel remove + +module PROOF-PERFORM-ACTION-ENDPOINT-ADD-BOARD-MEMBER-BOARDMEMBER + imports TRUSTED-PERFORM-ACTION-ENDPOINT-FRAGMENT-PERFORMS + imports TRUSTED-PERFORM-ACTION-ID-ADD-BOARD-MEMBER-BOARDMEMBER +//@ trusted +// module TRUSTED-PERFORM-ACTION-ENDPOINT-ADD-BOARD-MEMBER-BOARDMEMBER +//@ end + imports FUNCTIONS-EXECUTE + + claim + call(performActionEndpoint(ActionId:Usize)) ~> K:K + invariantStateFull( + NumUsers:Usize, + UserIdToAddress:Map, + (CallerAddress |-> CallerId:Usize + UserAddress |-> UserId:Usize + _AddressToUserId:Map + ) #as AddressToUserId:Map, + NumBoardMembers:Usize, + NumProposers:Usize, + (CallerId |-> Role:UserRole + UserId |-> BoardMember + _UserIdToRole:Map + ) #as UserIdToRole:Map, + u(Quorum:Int), + ActionLastIndex:Usize, + ActionId |-> AddBoardMember(UserAddress:Address) #as Action:Action + ActionData:Map, + ActionSigners:Map, + CallerAddress:Address, + Stack:Stack, + .Map, + PerformedActions:List + ) + + => + + evaluate(void) ~> K:K + invariantStateFull( + NumUsers, + UserIdToAddress, + AddressToUserId, + NumBoardMembers, + NumProposers, + UserIdToRole, + u(Quorum), + ActionLastIndex, + ActionData, + ActionSigners[ActionId <- undef], + CallerAddress, + Stack, + ?_Variables:Map, + ListItem(Action) PerformedActions + ) + + requires true + // perform-from-id + andBool isKResult(Action) + andBool addressToUserIdInvariant(AddressToUserId) + + // perform-fragment + andBool actionSignersInvariant(ActionSigners) + andBool userIdToRoleInvariant(UserIdToRole) + andBool (Role ==K BoardMember orBool Role ==K Proposer) + andBool Quorum <=Int countCanSignFunction({ActionSigners[ActionId] orDefault [.]}:>ExpressionList, opaque(UserIdToRole)) + ensures true + //@ proof + //@ trusted + // [trusted] + //@ end +endmodule diff --git a/multisig/protocol-correctness/proof/functions/proof-perform-action-endpoint-add-board-member-New.k b/multisig/protocol-correctness/proof/functions/proof-perform-action-endpoint-add-board-member-New.k new file mode 100644 index 000000000..802756713 --- /dev/null +++ b/multisig/protocol-correctness/proof/functions/proof-perform-action-endpoint-add-board-member-New.k @@ -0,0 +1,79 @@ +//@ proof +require "trusted-perform-action-endpoint-fragment-performs.k" //@ Bazel remove +require "trusted-perform-action-endpoint-id-add-board-member-New.k" //@ Bazel remove + +module PROOF-PERFORM-ACTION-ENDPOINT-ADD-BOARD-MEMBER-NEW + imports TRUSTED-PERFORM-ACTION-ENDPOINT-FRAGMENT-PERFORMS + imports TRUSTED-PERFORM-ACTION-ID-ADD-BOARD-MEMBER-NEW +//@ trusted +// module TRUSTED-PERFORM-ACTION-ENDPOINT-ADD-BOARD-MEMBER-NEW +//@ end + imports FUNCTIONS-EXECUTE + + claim + call(performActionEndpoint(ActionId:Usize)) ~> K:K + invariantStateFull( + u(NumUsers:Int), + UserIdToAddress:Map, + (CallerAddress |-> CallerId:Usize + _AddressToUserId:Map + ) #as AddressToUserId:Map, + u(NumBoardMembers:Int), + NumProposers:Usize, + (CallerId |-> Role:UserRole + _UserIdToRole:Map + ) #as UserIdToRole:Map, + u(Quorum:Int), + ActionLastIndex:Usize, + ActionId |-> AddBoardMember(UserAddress:Address) #as Action:Action + ActionData:Map, + ActionSigners:Map, + CallerAddress:Address, + Stack:Stack, + .Map, + PerformedActions:List + ) + + => + + evaluate(void) ~> K:K + invariantStateFull( + u(NumUsers +Int 1), + u(NumUsers +Int 1) |-> UserAddress UserIdToAddress, + UserAddress |-> u(NumUsers +Int 1) AddressToUserId, + u(NumBoardMembers +Int 1), + NumProposers, + u(NumUsers +Int 1) |-> BoardMember UserIdToRole, + u(Quorum), + ActionLastIndex, + ActionData, + ActionSigners[ActionId <- undef], + CallerAddress, + Stack, + ?_Variables:Map, + ListItem(Action) PerformedActions + ) + + requires true + // perform-from-id + andBool isKResult(Action) + + andBool NumUsers >=Int 0 + // TODO: Perhaps replace with unusedIdsInMapValues(AddressToUserId) + + // someting to map values to keys. + andBool unusedIdsInMapKeys(NumUsers +Int 1, keysMap(UserIdToAddress), expand(expanded)) + andBool unusedIdsInMapKeys(NumUsers +Int 1, keysMap(UserIdToRole), expand(expanded)) + + andBool notBool UserAddress in_keys(AddressToUserId) + + // perform-fragment + andBool actionSignersInvariant(ActionSigners) + andBool userIdToRoleInvariant(UserIdToRole) + andBool (Role ==K BoardMember orBool Role ==K Proposer) + andBool Quorum <=Int countCanSignFunction({ActionSigners[ActionId] orDefault [.]}:>ExpressionList, opaque(UserIdToRole)) + ensures true + //@ proof + //@ trusted + // [trusted] + //@ end +endmodule diff --git a/multisig/protocol-correctness/proof/functions/proof-perform-action-endpoint-add-board-member-None.k b/multisig/protocol-correctness/proof/functions/proof-perform-action-endpoint-add-board-member-None.k new file mode 100644 index 000000000..f01d21cee --- /dev/null +++ b/multisig/protocol-correctness/proof/functions/proof-perform-action-endpoint-add-board-member-None.k @@ -0,0 +1,74 @@ +//@ proof +require "trusted-perform-action-endpoint-fragment-performs.k" //@ Bazel remove +require "trusted-perform-action-endpoint-id-add-board-member-None.k" //@ Bazel remove + +module PROOF-PERFORM-ACTION-ENDPOINT-ADD-BOARD-MEMBER-NONE + imports TRUSTED-PERFORM-ACTION-ENDPOINT-FRAGMENT-PERFORMS + imports TRUSTED-PERFORM-ACTION-ID-ADD-BOARD-MEMBER-NONE +//@ trusted +// module TRUSTED-PERFORM-ACTION-ENDPOINT-ADD-BOARD-MEMBER-NONE +//@ end + imports FUNCTIONS-EXECUTE + + claim + call(performActionEndpoint(ActionId:Usize)) ~> K:K + invariantStateFull( + NumUsers:Usize, + UserIdToAddress:Map, + (CallerAddress |-> CallerId:Usize + UserAddress |-> UserId:Usize + _AddressToUserId:Map + ) #as AddressToUserId:Map, + u(NumBoardMembers:Int), + NumProposers:Usize, + (CallerId |-> Role:UserRole + _UserIdToRole:Map + ) #as UserIdToRole:Map, + u(Quorum:Int), + ActionLastIndex:Usize, + ActionId |-> AddBoardMember(UserAddress:Address) #as Action:Action + ActionData:Map, + ActionSigners:Map, + CallerAddress:Address, + Stack:Stack, + .Map, + PerformedActions:List + ) + + => + + evaluate(void) ~> K:K + invariantStateFull( + NumUsers, + UserIdToAddress, + AddressToUserId, + u(NumBoardMembers +Int 1), + NumProposers, + UserId |-> BoardMember UserIdToRole, + u(Quorum), + ActionLastIndex, + ActionData, + ActionSigners[ActionId <- undef], + CallerAddress, + Stack, + ?_Variables:Map, + ListItem(Action) PerformedActions + ) + + requires true + // perform-from-id + andBool isKResult(Action) + andBool addressToUserIdInvariant(AddressToUserId) + andBool notBool UserId in_keys(UserIdToRole) + + // perform-fragment + andBool actionSignersInvariant(ActionSigners) + andBool userIdToRoleInvariant(UserIdToRole) + andBool (Role ==K BoardMember orBool Role ==K Proposer) + andBool Quorum <=Int countCanSignFunction({ActionSigners[ActionId] orDefault [.]}:>ExpressionList, opaque(UserIdToRole)) + ensures true + //@ proof + //@ trusted + // [trusted] + //@ end +endmodule diff --git a/multisig/protocol-correctness/proof/functions/proof-perform-action-endpoint-add-board-member-Proposer-eq.k b/multisig/protocol-correctness/proof/functions/proof-perform-action-endpoint-add-board-member-Proposer-eq.k new file mode 100644 index 000000000..2824081da --- /dev/null +++ b/multisig/protocol-correctness/proof/functions/proof-perform-action-endpoint-add-board-member-Proposer-eq.k @@ -0,0 +1,72 @@ +//@ proof +require "trusted-perform-action-endpoint-fragment-performs.k" //@ Bazel remove +require "trusted-perform-action-endpoint-id-add-board-member-Proposer.k" //@ Bazel remove + +module PROOF-PERFORM-ACTION-ENDPOINT-ADD-BOARD-MEMBER-PROPOSER-EQ + imports TRUSTED-PERFORM-ACTION-ENDPOINT-FRAGMENT-PERFORMS + imports TRUSTED-PERFORM-ACTION-ID-ADD-BOARD-MEMBER-PROPOSER +//@ trusted +// module TRUSTED-PERFORM-ACTION-ENDPOINT-ADD-BOARD-MEMBER-PROPOSER-EQ +//@ end + imports FUNCTIONS-EXECUTE + + claim + call(performActionEndpoint(ActionId:Usize)) ~> K:K + invariantStateFull( + NumUsers:Usize, + UserIdToAddress:Map, + (CallerAddress |-> CallerId:Usize + _AddressToUserId:Map + ) #as AddressToUserId:Map, + u(NumBoardMembers:Int), + u(NumProposers:Int), + (CallerId |-> Proposer + UserIdToRoleInner:Map + ) #as UserIdToRole:Map, + u(Quorum:Int), + ActionLastIndex:Usize, + ActionId |-> AddBoardMember(CallerAddress:Address) #as Action:Action + ActionData:Map, + ActionSigners:Map, + CallerAddress:Address, + Stack:Stack, + .Map, + PerformedActions:List + ) + + => + + evaluate(void) ~> K:K + invariantStateFull( + NumUsers, + UserIdToAddress, + AddressToUserId, + u(NumBoardMembers +Int 1), + u(NumProposers -Int 1), + CallerId |-> BoardMember + UserIdToRoleInner:Map, + u(Quorum), + ActionLastIndex, + ActionData, + ActionSigners[ActionId <- undef], + CallerAddress, + Stack, + ?_Variables:Map, + ListItem(Action) PerformedActions + ) + + requires true + // perform-from-id + andBool isKResult(Action) + andBool addressToUserIdInvariant(AddressToUserId) + + // perform-fragment + andBool actionSignersInvariant(ActionSigners) + andBool userIdToRoleInvariant(UserIdToRole) + andBool Quorum <=Int countCanSignFunction({ActionSigners[ActionId] orDefault [.]}:>ExpressionList, opaque(UserIdToRole)) + ensures true + //@ proof + //@ trusted + // [trusted] + //@ end +endmodule diff --git a/multisig/protocol-correctness/proof/functions/proof-perform-action-endpoint-add-board-member-Proposer.k b/multisig/protocol-correctness/proof/functions/proof-perform-action-endpoint-add-board-member-Proposer.k new file mode 100644 index 000000000..0a768a030 --- /dev/null +++ b/multisig/protocol-correctness/proof/functions/proof-perform-action-endpoint-add-board-member-Proposer.k @@ -0,0 +1,76 @@ +//@ proof +require "trusted-perform-action-endpoint-fragment-performs.k" //@ Bazel remove +require "trusted-perform-action-endpoint-id-add-board-member-Proposer.k" //@ Bazel remove + +module PROOF-PERFORM-ACTION-ENDPOINT-ADD-BOARD-MEMBER-PROPOSER + imports TRUSTED-PERFORM-ACTION-ENDPOINT-FRAGMENT-PERFORMS + imports TRUSTED-PERFORM-ACTION-ID-ADD-BOARD-MEMBER-PROPOSER +//@ trusted +// module TRUSTED-PERFORM-ACTION-ENDPOINT-ADD-BOARD-MEMBER-PROPOSER +//@ end + imports FUNCTIONS-EXECUTE + + claim + call(performActionEndpoint(ActionId:Usize)) ~> K:K + invariantStateFull( + NumUsers:Usize, + UserIdToAddress:Map, + (CallerAddress |-> CallerId:Usize + UserAddress |-> UserId:Usize + _AddressToUserId:Map + ) #as AddressToUserId:Map, + u(NumBoardMembers:Int), + u(NumProposers:Int), + (UserId |-> Proposer + CallerId |-> Role:UserRole + UserIdToRoleInner:Map + ) #as UserIdToRole:Map, + u(Quorum:Int), + ActionLastIndex:Usize, + ActionId |-> AddBoardMember(UserAddress:Address) #as Action:Action + ActionData:Map, + ActionSigners:Map, + CallerAddress:Address, + Stack:Stack, + .Map, + PerformedActions:List + ) + + => + + evaluate(void) ~> K:K + invariantStateFull( + NumUsers, + UserIdToAddress, + AddressToUserId, + u(NumBoardMembers +Int 1), + u(NumProposers -Int 1), + UserId |-> BoardMember + CallerId |-> Role:UserRole + UserIdToRoleInner:Map, + u(Quorum), + ActionLastIndex, + ActionData, + ActionSigners[ActionId <- undef], + CallerAddress, + Stack, + ?_Variables:Map, + ListItem(Action) PerformedActions + ) + + requires true + // perform-from-id + andBool isKResult(Action) + andBool addressToUserIdInvariant(AddressToUserId) + + // perform-fragment + andBool actionSignersInvariant(ActionSigners) + andBool userIdToRoleInvariant(UserIdToRole) + andBool (Role ==K BoardMember orBool Role ==K Proposer) + andBool Quorum <=Int countCanSignFunction({ActionSigners[ActionId] orDefault [.]}:>ExpressionList, opaque(UserIdToRole)) + ensures true + //@ proof + //@ trusted + // [trusted] + //@ end +endmodule diff --git a/multisig/protocol-correctness/proof/functions/proof-perform-action-endpoint-add-proposer-BoardMember-eq.k b/multisig/protocol-correctness/proof/functions/proof-perform-action-endpoint-add-proposer-BoardMember-eq.k new file mode 100644 index 000000000..c99d79028 --- /dev/null +++ b/multisig/protocol-correctness/proof/functions/proof-perform-action-endpoint-add-proposer-BoardMember-eq.k @@ -0,0 +1,73 @@ +//@ proof +require "trusted-perform-action-endpoint-fragment-performs.k" //@ Bazel remove +require "trusted-perform-action-endpoint-id-add-proposer-BoardMember.k" //@ Bazel remove + +module PROOF-PERFORM-ACTION-ENDPOINT-ADD-PROPOSER-BOARDMEMBER-EQ + imports TRUSTED-PERFORM-ACTION-ENDPOINT-FRAGMENT-PERFORMS + imports TRUSTED-PERFORM-ACTION-ID-ADD-PROPOSER-BOARDMEMBER +//@ trusted +// module TRUSTED-PERFORM-ACTION-ENDPOINT-ADD-PROPOSER-BOARDMEMBER-EQ +//@ end + imports FUNCTIONS-EXECUTE + + claim + call(performActionEndpoint(ActionId:Usize)) ~> K:K + invariantStateFull( + NumUsers:Usize, + UserIdToAddress:Map, + (CallerAddress |-> CallerId:Usize + _AddressToUserId:Map + ) #as AddressToUserId:Map, + u(NumBoardMembers:Int), + u(NumProposers:Int), + (CallerId |-> BoardMember + UserIdToRoleInner:Map + ) #as UserIdToRole:Map, + u(Quorum:Int), + ActionLastIndex:Usize, + ActionId |-> AddProposer(CallerAddress:Address) #as Action:Action + ActionData:Map, + ActionSigners:Map, + CallerAddress:Address, + Stack:Stack, + .Map, + PerformedActions:List + ) + + => + + evaluate(void) ~> K:K + invariantStateFull( + NumUsers, + UserIdToAddress, + AddressToUserId, + u(NumBoardMembers -Int 1), + u(NumProposers +Int 1), + (CallerId |-> Proposer + UserIdToRoleInner), + u(Quorum), + ActionLastIndex, + ActionData, + ActionSigners[ActionId <- undef], + CallerAddress, + Stack, + ?_Variables:Map, + ListItem(Action) PerformedActions + ) + + requires true + // perform-from-id + andBool isKResult(Action) + andBool addressToUserIdInvariant(AddressToUserId) + andBool Quorum <=Int NumBoardMembers -Int 1 + + // perform-fragment + andBool actionSignersInvariant(ActionSigners) + andBool userIdToRoleInvariant(UserIdToRole) + andBool Quorum <=Int countCanSignFunction({ActionSigners[ActionId] orDefault [.]}:>ExpressionList, opaque(UserIdToRole)) + ensures true + //@ proof + //@ trusted + // [trusted] + //@ end +endmodule diff --git a/multisig/protocol-correctness/proof/functions/proof-perform-action-endpoint-add-proposer-BoardMember-no-quorum-eq.k b/multisig/protocol-correctness/proof/functions/proof-perform-action-endpoint-add-proposer-BoardMember-no-quorum-eq.k new file mode 100644 index 000000000..923c8ef9b --- /dev/null +++ b/multisig/protocol-correctness/proof/functions/proof-perform-action-endpoint-add-proposer-BoardMember-no-quorum-eq.k @@ -0,0 +1,72 @@ +//@ proof +require "trusted-perform-action-endpoint-fragment-performs.k" //@ Bazel remove +require "trusted-perform-action-endpoint-id-add-proposer-BoardMember-no-quorum.k" //@ Bazel remove + +module PROOF-PERFORM-ACTION-ENDPOINT-ADD-PROPOSER-BOARDMEMBER-NO-QUORUM-EQ + imports TRUSTED-PERFORM-ACTION-ENDPOINT-FRAGMENT-PERFORMS + imports TRUSTED-PERFORM-ACTION-ID-ADD-PROPOSER-BOARDMEMBER-NO-QUORUM +//@ trusted +// module TRUSTED-PERFORM-ACTION-ENDPOINT-ADD-PROPOSER-BOARDMEMBER-NO-QUORUM-EQ +//@ end + imports FUNCTIONS-EXECUTE + + claim + call(performActionEndpoint(ActionId:Usize)) ~> K:K + invariantStateFull( + NumUsers:Usize, + UserIdToAddress:Map, + (CallerAddress |-> CallerId:Usize + _AddressToUserId:Map + ) #as AddressToUserId:Map, + u(NumBoardMembers:Int), + u(NumProposers:Int), + (CallerId |-> BoardMember + _UserIdToRole:Map + ) #as UserIdToRole:Map, + u(Quorum:Int), + ActionLastIndex:Usize, + ActionId |-> AddProposer(CallerAddress:Address) #as Action:Action + ActionData:Map, + ActionSigners:Map, + CallerAddress:Address, + Stack:Stack, + .Map, + PerformedActions:List + ) + + => + + error ~> K:K + invariantStateFull( + NumUsers, + UserIdToAddress, + AddressToUserId, + u(NumBoardMembers), + u(NumProposers), + UserIdToRole, + u(Quorum), + ActionLastIndex, + ActionId |-> Action ActionData, + ActionSigners, + CallerAddress, + Stack, + ?_Variables:Map, + PerformedActions + ) + + requires true + // perform-from-id + andBool isKResult(Action) + andBool addressToUserIdInvariant(AddressToUserId) + andBool Quorum ==Int NumBoardMembers + + // perform-fragment + andBool actionSignersInvariant(ActionSigners) + andBool userIdToRoleInvariant(UserIdToRole) + andBool Quorum <=Int countCanSignFunction({ActionSigners[ActionId] orDefault [.]}:>ExpressionList, opaque(UserIdToRole)) + ensures true + //@ proof + //@ trusted + // [trusted] + //@ end +endmodule diff --git a/multisig/protocol-correctness/proof/functions/proof-perform-action-endpoint-add-proposer-BoardMember-no-quorum.k b/multisig/protocol-correctness/proof/functions/proof-perform-action-endpoint-add-proposer-BoardMember-no-quorum.k new file mode 100644 index 000000000..25e0a1daa --- /dev/null +++ b/multisig/protocol-correctness/proof/functions/proof-perform-action-endpoint-add-proposer-BoardMember-no-quorum.k @@ -0,0 +1,75 @@ +//@ proof +require "trusted-perform-action-endpoint-fragment-performs.k" //@ Bazel remove +require "trusted-perform-action-endpoint-id-add-proposer-BoardMember-no-quorum.k" //@ Bazel remove + +module PROOF-PERFORM-ACTION-ENDPOINT-ADD-PROPOSER-BOARDMEMBER-NO-QUORUM + imports TRUSTED-PERFORM-ACTION-ENDPOINT-FRAGMENT-PERFORMS + imports TRUSTED-PERFORM-ACTION-ID-ADD-PROPOSER-BOARDMEMBER-NO-QUORUM +//@ trusted +// module TRUSTED-PERFORM-ACTION-ENDPOINT-ADD-PROPOSER-BOARDMEMBER-NO-QUORUM +//@ end + imports FUNCTIONS-EXECUTE + + claim + call(performActionEndpoint(ActionId:Usize)) ~> K:K + invariantStateFull( + NumUsers:Usize, + UserIdToAddress:Map, + (CallerAddress |-> CallerId:Usize + UserAddress |-> UserId:Usize + _AddressToUserId:Map + ) #as AddressToUserId:Map, + u(NumBoardMembers:Int), + u(NumProposers:Int), + (CallerId |-> Role:UserRole + UserId |-> BoardMember + _UserIdToRole:Map + ) #as UserIdToRole:Map, + u(Quorum:Int), + ActionLastIndex:Usize, + ActionId |-> AddProposer(UserAddress:Address) #as Action:Action + ActionData:Map, + ActionSigners:Map, + CallerAddress:Address, + Stack:Stack, + .Map, + PerformedActions:List + ) + + => + + error ~> K:K + invariantStateFull( + NumUsers, + UserIdToAddress, + AddressToUserId, + u(NumBoardMembers), + u(NumProposers), + UserIdToRole, + u(Quorum), + ActionLastIndex, + ActionId |-> Action ActionData, + ActionSigners, + CallerAddress, + Stack, + ?_Variables:Map, + PerformedActions + ) + + requires true + // perform-from-id + andBool isKResult(Action) + andBool addressToUserIdInvariant(AddressToUserId) + andBool Quorum ==Int NumBoardMembers + + // perform-fragment + andBool actionSignersInvariant(ActionSigners) + andBool userIdToRoleInvariant(UserIdToRole) + andBool (Role ==K BoardMember orBool Role ==K Proposer) + andBool Quorum <=Int countCanSignFunction({ActionSigners[ActionId] orDefault [.]}:>ExpressionList, opaque(UserIdToRole)) + ensures true + //@ proof + //@ trusted + // [trusted] + //@ end +endmodule diff --git a/multisig/protocol-correctness/proof/functions/proof-perform-action-endpoint-add-proposer-BoardMember.k b/multisig/protocol-correctness/proof/functions/proof-perform-action-endpoint-add-proposer-BoardMember.k new file mode 100644 index 000000000..10e604bda --- /dev/null +++ b/multisig/protocol-correctness/proof/functions/proof-perform-action-endpoint-add-proposer-BoardMember.k @@ -0,0 +1,77 @@ +//@ proof +require "trusted-perform-action-endpoint-fragment-performs.k" //@ Bazel remove +require "trusted-perform-action-endpoint-id-add-proposer-BoardMember.k" //@ Bazel remove + +module PROOF-PERFORM-ACTION-ENDPOINT-ADD-PROPOSER-BOARDMEMBER + imports TRUSTED-PERFORM-ACTION-ENDPOINT-FRAGMENT-PERFORMS + imports TRUSTED-PERFORM-ACTION-ID-ADD-PROPOSER-BOARDMEMBER +//@ trusted +// module TRUSTED-PERFORM-ACTION-ENDPOINT-ADD-PROPOSER-BOARDMEMBER +//@ end + imports FUNCTIONS-EXECUTE + + claim + call(performActionEndpoint(ActionId:Usize)) ~> K:K + invariantStateFull( + NumUsers:Usize, + UserIdToAddress:Map, + (CallerAddress |-> CallerId:Usize + UserAddress |-> UserId:Usize + _AddressToUserId:Map + ) #as AddressToUserId:Map, + u(NumBoardMembers:Int), + u(NumProposers:Int), + (CallerId |-> Role:UserRole + UserId |-> BoardMember + UserIdToRoleInner:Map + ) #as UserIdToRole:Map, + u(Quorum:Int), + ActionLastIndex:Usize, + ActionId |-> AddProposer(UserAddress:Address) #as Action:Action + ActionData:Map, + ActionSigners:Map, + CallerAddress:Address, + Stack:Stack, + .Map, + PerformedActions:List + ) + + => + + evaluate(void) ~> K:K + invariantStateFull( + NumUsers, + UserIdToAddress, + AddressToUserId, + u(NumBoardMembers -Int 1), + u(NumProposers +Int 1), + (CallerId |-> Role:UserRole + UserId |-> Proposer + UserIdToRoleInner), + u(Quorum), + ActionLastIndex, + ActionData, + ActionSigners[ActionId <- undef], + CallerAddress, + Stack, + ?_Variables:Map, + ListItem(Action) PerformedActions + ) + + requires true + // perform-from-id + andBool isKResult(Action) + andBool addressToUserIdInvariant(AddressToUserId) + andBool Quorum <=Int NumBoardMembers -Int 1 + + // perform-fragment + andBool actionSignersInvariant(ActionSigners) + andBool userIdToRoleInvariant(UserIdToRole) + andBool (Role ==K BoardMember orBool Role ==K Proposer) + andBool Quorum <=Int countCanSignFunction({ActionSigners[ActionId] orDefault [.]}:>ExpressionList, opaque(UserIdToRole)) + ensures true + //@ proof + //@ trusted + // [trusted] + //@ end +endmodule diff --git a/multisig/protocol-correctness/proof/functions/proof-perform-action-endpoint-add-proposer-New.k b/multisig/protocol-correctness/proof/functions/proof-perform-action-endpoint-add-proposer-New.k new file mode 100644 index 000000000..4b663377d --- /dev/null +++ b/multisig/protocol-correctness/proof/functions/proof-perform-action-endpoint-add-proposer-New.k @@ -0,0 +1,80 @@ +//@ proof +require "trusted-perform-action-endpoint-fragment-performs.k" //@ Bazel remove +require "trusted-perform-action-endpoint-id-add-proposer-New.k" //@ Bazel remove + +module PROOF-PERFORM-ACTION-ENDPOINT-ADD-PROPOSER-NEW + imports TRUSTED-PERFORM-ACTION-ENDPOINT-FRAGMENT-PERFORMS + imports TRUSTED-PERFORM-ACTION-ID-ADD-PROPOSER-NEW +//@ trusted +// module TRUSTED-PERFORM-ACTION-ENDPOINT-ADD-PROPOSER-NEW +//@ end + imports FUNCTIONS-EXECUTE + + claim + call(performActionEndpoint(ActionId:Usize)) ~> K:K + invariantStateFull( + u(NumUsers:Int), + UserIdToAddress:Map, + (CallerAddress |-> CallerId:Usize + _AddressToUserId:Map + ) #as AddressToUserId:Map, + u(NumBoardMembers:Int), + u(NumProposers:Int), + (CallerId |-> Role:UserRole + _UserIdToRole:Map + ) #as UserIdToRole:Map, + u(Quorum:Int), + ActionLastIndex:Usize, + ActionId |-> AddProposer(UserAddress:Address) #as Action:Action + ActionData:Map, + ActionSigners:Map, + CallerAddress:Address, + Stack:Stack, + .Map, + PerformedActions:List + ) + + => + + evaluate(void) ~> K:K + invariantStateFull( + u(NumUsers +Int 1), + u(NumUsers +Int 1) |-> UserAddress UserIdToAddress, + UserAddress |-> u(NumUsers +Int 1) AddressToUserId, + u(NumBoardMembers), + u(NumProposers +Int 1), + u(NumUsers +Int 1) |-> Proposer UserIdToRole, + u(Quorum), + ActionLastIndex, + ActionData, + ActionSigners[ActionId <- undef], + CallerAddress, + Stack, + ?_Variables:Map, + ListItem(Action) PerformedActions + ) + + requires true + // perform-from-id + andBool isKResult(Action) + + andBool NumUsers >=Int 0 + // TODO: Perhaps replace with unusedIdsInMapValues(AddressToUserId) + + // someting to map values to keys. + andBool unusedIdsInMapKeys(NumUsers +Int 1, keysMap(UserIdToAddress), expand(expanded)) + andBool unusedIdsInMapKeys(NumUsers +Int 1, keysMap(UserIdToRole), expand(expanded)) + andBool Quorum <=Int NumBoardMembers + + andBool notBool UserAddress in_keys(AddressToUserId) + + // perform-fragment + andBool actionSignersInvariant(ActionSigners) + andBool userIdToRoleInvariant(UserIdToRole) + andBool (Role ==K BoardMember orBool Role ==K Proposer) + andBool Quorum <=Int countCanSignFunction({ActionSigners[ActionId] orDefault [.]}:>ExpressionList, opaque(UserIdToRole)) + ensures true + //@ proof + //@ trusted + // [trusted] + //@ end +endmodule diff --git a/multisig/protocol-correctness/proof/functions/proof-perform-action-endpoint-add-proposer-None.k b/multisig/protocol-correctness/proof/functions/proof-perform-action-endpoint-add-proposer-None.k new file mode 100644 index 000000000..db11f380f --- /dev/null +++ b/multisig/protocol-correctness/proof/functions/proof-perform-action-endpoint-add-proposer-None.k @@ -0,0 +1,75 @@ +//@ proof +require "trusted-perform-action-endpoint-fragment-performs.k" //@ Bazel remove +require "trusted-perform-action-endpoint-id-add-proposer-None.k" //@ Bazel remove + +module PROOF-PERFORM-ACTION-ENDPOINT-ADD-PROPOSER-NONE + imports TRUSTED-PERFORM-ACTION-ENDPOINT-FRAGMENT-PERFORMS + imports TRUSTED-PERFORM-ACTION-ID-ADD-PROPOSER-NONE +//@ trusted +// module TRUSTED-PERFORM-ACTION-ENDPOINT-ADD-PROPOSER-NONE +//@ end + imports FUNCTIONS-EXECUTE + + claim + call(performActionEndpoint(ActionId:Usize)) ~> K:K + invariantStateFull( + NumUsers:Usize, + UserIdToAddress:Map, + (CallerAddress |-> CallerId:Usize + UserAddress |-> UserId:Usize + _AddressToUserId:Map + ) #as AddressToUserId:Map, + u(NumBoardMembers:Int), + u(NumProposers:Int), + (CallerId |-> Role:UserRole + _UserIdToRole:Map + ) #as UserIdToRole:Map, + u(Quorum:Int), + ActionLastIndex:Usize, + ActionId |-> AddProposer(UserAddress:Address) #as Action:Action + ActionData:Map, + ActionSigners:Map, + CallerAddress:Address, + Stack:Stack, + .Map, + PerformedActions:List + ) + + => + + evaluate(void) ~> K:K + invariantStateFull( + NumUsers, + UserIdToAddress, + AddressToUserId, + u(NumBoardMembers), + u(NumProposers +Int 1), + UserId |-> Proposer UserIdToRole, + u(Quorum), + ActionLastIndex, + ActionData, + ActionSigners[ActionId <- undef], + CallerAddress, + Stack, + ?_Variables:Map, + ListItem(Action) PerformedActions + ) + + requires true + // perform-from-id + andBool isKResult(Action) + andBool addressToUserIdInvariant(AddressToUserId) + andBool Quorum <=Int NumBoardMembers + andBool notBool UserId in_keys(UserIdToRole) + + // perform-fragment + andBool actionSignersInvariant(ActionSigners) + andBool userIdToRoleInvariant(UserIdToRole) + andBool (Role ==K BoardMember orBool Role ==K Proposer) + andBool Quorum <=Int countCanSignFunction({ActionSigners[ActionId] orDefault [.]}:>ExpressionList, opaque(UserIdToRole)) + ensures true + //@ proof + //@ trusted + // [trusted] + //@ end +endmodule diff --git a/multisig/protocol-correctness/proof/functions/proof-perform-action-endpoint-add-proposer-Proposer-eq.k b/multisig/protocol-correctness/proof/functions/proof-perform-action-endpoint-add-proposer-Proposer-eq.k new file mode 100644 index 000000000..de4988742 --- /dev/null +++ b/multisig/protocol-correctness/proof/functions/proof-perform-action-endpoint-add-proposer-Proposer-eq.k @@ -0,0 +1,72 @@ +//@ proof +require "trusted-perform-action-endpoint-fragment-performs.k" //@ Bazel remove +require "trusted-perform-action-endpoint-id-add-proposer-Proposer.k" //@ Bazel remove + +module PROOF-PERFORM-ACTION-ENDPOINT-ADD-PROPOSER-PROPOSER-EQ + imports TRUSTED-PERFORM-ACTION-ENDPOINT-FRAGMENT-PERFORMS + imports TRUSTED-PERFORM-ACTION-ID-ADD-PROPOSER-PROPOSER +//@ trusted +// module TRUSTED-PERFORM-ACTION-ENDPOINT-ADD-PROPOSER-PROPOSER-EQ +//@ end + imports FUNCTIONS-EXECUTE + + claim + call(performActionEndpoint(ActionId:Usize)) ~> K:K + invariantStateFull( + NumUsers:Usize, + UserIdToAddress:Map, + (CallerAddress |-> CallerId:Usize + _AddressToUserId:Map + ) #as AddressToUserId:Map, + u(NumBoardMembers:Int), + NumProposers:Usize, + (CallerId |-> Proposer + _UserIdToRole:Map + ) #as UserIdToRole:Map, + u(Quorum:Int), + ActionLastIndex:Usize, + ActionId |-> AddProposer(CallerAddress:Address) #as Action:Action + ActionData:Map, + ActionSigners:Map, + CallerAddress:Address, + Stack:Stack, + .Map, + PerformedActions:List + ) + + => + + evaluate(void) ~> K:K + invariantStateFull( + NumUsers, + UserIdToAddress, + AddressToUserId, + u(NumBoardMembers), + NumProposers, + UserIdToRole, + u(Quorum), + ActionLastIndex, + ActionData, + ActionSigners[ActionId <- undef], + CallerAddress, + Stack, + ?_Variables:Map, + ListItem(Action) PerformedActions + ) + + requires true + // perform-from-id + andBool isKResult(Action) + andBool addressToUserIdInvariant(AddressToUserId) + andBool Quorum <=Int NumBoardMembers + + // perform-fragment + andBool actionSignersInvariant(ActionSigners) + andBool userIdToRoleInvariant(UserIdToRole) + andBool Quorum <=Int countCanSignFunction({ActionSigners[ActionId] orDefault [.]}:>ExpressionList, opaque(UserIdToRole)) + ensures true + //@ proof + //@ trusted + // [trusted] + //@ end +endmodule diff --git a/multisig/protocol-correctness/proof/functions/proof-perform-action-endpoint-add-proposer-Proposer.k b/multisig/protocol-correctness/proof/functions/proof-perform-action-endpoint-add-proposer-Proposer.k new file mode 100644 index 000000000..60246d409 --- /dev/null +++ b/multisig/protocol-correctness/proof/functions/proof-perform-action-endpoint-add-proposer-Proposer.k @@ -0,0 +1,75 @@ +//@ proof +require "trusted-perform-action-endpoint-fragment-performs.k" //@ Bazel remove +require "trusted-perform-action-endpoint-id-add-proposer-Proposer.k" //@ Bazel remove + +module PROOF-PERFORM-ACTION-ENDPOINT-ADD-PROPOSER-PROPOSER + imports TRUSTED-PERFORM-ACTION-ENDPOINT-FRAGMENT-PERFORMS + imports TRUSTED-PERFORM-ACTION-ID-ADD-PROPOSER-PROPOSER +//@ trusted +// module TRUSTED-PERFORM-ACTION-ENDPOINT-ADD-PROPOSER-PROPOSER +//@ end + imports FUNCTIONS-EXECUTE + + claim + call(performActionEndpoint(ActionId:Usize)) ~> K:K + invariantStateFull( + NumUsers:Usize, + UserIdToAddress:Map, + (CallerAddress |-> CallerId:Usize + UserAddress |-> UserId:Usize + _AddressToUserId:Map + ) #as AddressToUserId:Map, + u(NumBoardMembers:Int), + NumProposers:Usize, + (CallerId |-> Role:UserRole + UserId |-> Proposer + _UserIdToRole:Map + ) #as UserIdToRole:Map, + u(Quorum:Int), + ActionLastIndex:Usize, + ActionId |-> AddProposer(UserAddress:Address) #as Action:Action + ActionData:Map, + ActionSigners:Map, + CallerAddress:Address, + Stack:Stack, + .Map, + PerformedActions:List + ) + + => + + evaluate(void) ~> K:K + invariantStateFull( + NumUsers, + UserIdToAddress, + AddressToUserId, + u(NumBoardMembers), + NumProposers, + UserIdToRole, + u(Quorum), + ActionLastIndex, + ActionData, + ActionSigners[ActionId <- undef], + CallerAddress, + Stack, + ?_Variables:Map, + ListItem(Action) PerformedActions + ) + + requires true + // perform-from-id + andBool isKResult(Action) + andBool addressToUserIdInvariant(AddressToUserId) + andBool Quorum <=Int NumBoardMembers + + // perform-fragment + andBool actionSignersInvariant(ActionSigners) + andBool userIdToRoleInvariant(UserIdToRole) + andBool (Role ==K BoardMember orBool Role ==K Proposer) + andBool Quorum <=Int countCanSignFunction({ActionSigners[ActionId] orDefault [.]}:>ExpressionList, opaque(UserIdToRole)) + ensures true + //@ proof + //@ trusted + // [trusted] + //@ end +endmodule diff --git a/multisig/protocol-correctness/proof/functions/proof-perform-action-endpoint-change-quorum-no-quorum.k b/multisig/protocol-correctness/proof/functions/proof-perform-action-endpoint-change-quorum-no-quorum.k new file mode 100644 index 000000000..78aa6b147 --- /dev/null +++ b/multisig/protocol-correctness/proof/functions/proof-perform-action-endpoint-change-quorum-no-quorum.k @@ -0,0 +1,72 @@ +//@ proof +require "trusted-perform-action-endpoint-fragment-performs.k" //@ Bazel remove +require "trusted-perform-action-id-change-quorum-no-quorum.k" //@ Bazel remove + +module PROOF-PERFORM-ACTION-ENDPOINT-CHANGE-QUORUM-NO-QUORUM + imports TRUSTED-PERFORM-ACTION-ENDPOINT-FRAGMENT-PERFORMS + imports TRUSTED-PERFORM-ACTION-ID-CHANGE-QUORUM-NO-QUORUM +//@ trusted +// module TRUSTED-PERFORM-ACTION-ENDPOINT-CHANGE-QUORUM-NO-QUORUM +//@ end + imports FUNCTIONS-EXECUTE + + claim + call(performActionEndpoint(ActionId:Usize)) ~> K:K + invariantStateFull( + NumUsers:Usize, + UserIdToAddress:Map, + (CallerAddress |-> CallerId:Usize + _AddressToUserId:Map + ) #as AddressToUserId:Map, + u(NumBoardMembers:Int), + NumProposers:Usize, + (CallerId |-> Role:UserRole + _UserIdToRole:Map + ) #as UserIdToRole:Map, + u(OldQuorum:Int), + ActionLastIndex:Usize, + ActionId |-> ChangeQuorum(u(NewQuorum:Int)) #as Action:Action + ActionData:Map, + ActionSigners:Map, + CallerAddress:Address, + Stack:Stack, + .Map, + PerformedActions:List + ) + + => + + error ~> K:K + invariantStateFull( + NumUsers, + UserIdToAddress, + AddressToUserId, + u(NumBoardMembers), + NumProposers, + UserIdToRole, + u(OldQuorum), + ActionLastIndex, + ActionId |-> Action ActionData, + ActionSigners, + CallerAddress, + Stack, + ?_Variables:Map, + PerformedActions + ) + + requires true + // perform-from-id + andBool isKResult(Action) + andBool NewQuorum >Int NumBoardMembers + + // perform-fragment + andBool actionSignersInvariant(ActionSigners) + andBool userIdToRoleInvariant(UserIdToRole) + andBool (Role ==K BoardMember orBool Role ==K Proposer) + andBool OldQuorum <=Int countCanSignFunction({ActionSigners[ActionId] orDefault [.]}:>ExpressionList, opaque(UserIdToRole)) + ensures true + //@ proof + //@ trusted + // [trusted] + //@ end +endmodule diff --git a/multisig/protocol-correctness/proof/functions/proof-perform-action-endpoint-change-quorum.k b/multisig/protocol-correctness/proof/functions/proof-perform-action-endpoint-change-quorum.k new file mode 100644 index 000000000..910bd13e7 --- /dev/null +++ b/multisig/protocol-correctness/proof/functions/proof-perform-action-endpoint-change-quorum.k @@ -0,0 +1,72 @@ +//@ proof +require "trusted-perform-action-endpoint-fragment-performs.k" //@ Bazel remove +require "trusted-perform-action-id-change-quorum.k" //@ Bazel remove + +module PROOF-PERFORM-ACTION-ENDPOINT-CHANGE-QUORUM + imports TRUSTED-PERFORM-ACTION-ENDPOINT-FRAGMENT-PERFORMS + imports TRUSTED-PERFORM-ACTION-ID-CHANGE-QUORUM +//@ trusted +// module TRUSTED-PERFORM-ACTION-ENDPOINT-CHANGE-QUORUM +//@ end + imports FUNCTIONS-EXECUTE + + claim + call(performActionEndpoint(ActionId:Usize)) ~> K:K + invariantStateFull( + NumUsers:Usize, + UserIdToAddress:Map, + (CallerAddress |-> CallerId:Usize + _AddressToUserId:Map + ) #as AddressToUserId:Map, + u(NumBoardMembers:Int), + NumProposers:Usize, + (CallerId |-> Role:UserRole + _UserIdToRole:Map + ) #as UserIdToRole:Map, + u(OldQuorum:Int), + ActionLastIndex:Usize, + ActionId |-> ChangeQuorum(u(NewQuorum:Int)) #as Action:Action + ActionData:Map, + ActionSigners:Map, + CallerAddress:Address, + Stack:Stack, + .Map, + PerformedActions:List + ) + + => + + evaluate(void) ~> K:K + invariantStateFull( + NumUsers, + UserIdToAddress, + AddressToUserId, + u(NumBoardMembers), + NumProposers, + UserIdToRole, + u(NewQuorum), + ActionLastIndex, + ActionData, + ActionSigners[ActionId <- undef], + CallerAddress, + Stack, + ?_Variables:Map, + ListItem(Action) PerformedActions + ) + + requires true + // perform-from-id + andBool isKResult(Action) + andBool NewQuorum <=Int NumBoardMembers + + // perform-fragment + andBool actionSignersInvariant(ActionSigners) + andBool userIdToRoleInvariant(UserIdToRole) + andBool (Role ==K BoardMember orBool Role ==K Proposer) + andBool OldQuorum <=Int countCanSignFunction({ActionSigners[ActionId] orDefault [.]}:>ExpressionList, opaque(UserIdToRole)) + ensures true + //@ proof + //@ trusted + // [trusted] + //@ end +endmodule diff --git a/multisig/protocol-correctness/proof/functions/proof-perform-action-endpoint-fragment-New.k b/multisig/protocol-correctness/proof/functions/proof-perform-action-endpoint-fragment-New.k new file mode 100644 index 000000000..99bcbbb1e --- /dev/null +++ b/multisig/protocol-correctness/proof/functions/proof-perform-action-endpoint-fragment-New.k @@ -0,0 +1,66 @@ +//@ proof +module PROOF-PERFORM-ACTION-ENDPOINT-FRAGMENT-NEW +//@ trusted +// module TRUSTED-PERFORM-ACTION-ENDPOINT-FRAGMENT-NEW +//@ end + imports FUNCTIONS-EXECUTE + + claim + runPseudoCode( + caller_address = getCaller(); + caller_id = getUserId(caller_address); + caller_role = getUserIdToRole(caller_id); + require(userRoleCanPerformAction(caller_role)); + require(quorumReached(ActionId:Usize)); + performActionFromId(ActionId); + ) + ~> K:K + + invariantStateFull( + NumUsers:Usize, + UserIdToAddress:Map, + AddressToUserId:Map, + NumBoardMembers:Usize, + NumProposers:Usize, + UserIdToRole:Map, + Quorum:Usize, + ActionLastIndex:Usize, + ActionData:Map, + ActionSigners:Map, + CallerAddress:Address, + Stack:Stack, + .Map, + PerformedActions:List + ) + + => + + error ~> K:K + invariantStateFull( + NumUsers:Usize, + UserIdToAddress:Map, + AddressToUserId:Map, + NumBoardMembers:Usize, + NumProposers:Usize, + UserIdToRole:Map, + Quorum:Usize, + ActionLastIndex:Usize, + ActionData:Map, + ActionSigners:Map, + CallerAddress:Address, + Stack:Stack, + caller_address |-> CallerAddress + caller_id |-> u(0) + caller_role |-> None, + PerformedActions:List + ) + + requires true + andBool notBool CallerAddress in_keys(AddressToUserId) + andBool notBool u(0) in_keys(UserIdToRole) + ensures true + //@ proof + //@ trusted + // [trusted] + //@ end +endmodule diff --git a/multisig/protocol-correctness/proof/functions/proof-perform-action-endpoint-fragment-None.k b/multisig/protocol-correctness/proof/functions/proof-perform-action-endpoint-fragment-None.k new file mode 100644 index 000000000..6e3755d84 --- /dev/null +++ b/multisig/protocol-correctness/proof/functions/proof-perform-action-endpoint-fragment-None.k @@ -0,0 +1,65 @@ +//@ proof +module PROOF-PERFORM-ACTION-ENDPOINT-FRAGMENT-NONE +//@ trusted +// module TRUSTED-PERFORM-ACTION-ENDPOINT-FRAGMENT-NONE +//@ end + imports FUNCTIONS-EXECUTE + + claim + runPseudoCode( + caller_address = getCaller(); + caller_id = getUserId(caller_address); + caller_role = getUserIdToRole(caller_id); + require(userRoleCanPerformAction(caller_role)); + require(quorumReached(ActionId:Usize)); + performActionFromId(ActionId); + ) + ~> K:K + + invariantStateFull( + NumUsers:Usize, + UserIdToAddress:Map, + (CallerAddress |-> UserId:Usize _AddressToUserId:Map) #as AddressToUserId:Map, + NumBoardMembers:Usize, + NumProposers:Usize, + UserIdToRole:Map, + Quorum:Usize, + ActionLastIndex:Usize, + ActionData:Map, + ActionSigners:Map, + CallerAddress:Address, + Stack:Stack, + .Map, + PerformedActions:List + ) + + => + + error ~> K:K + invariantStateFull( + NumUsers:Usize, + UserIdToAddress:Map, + AddressToUserId:Map, + NumBoardMembers:Usize, + NumProposers:Usize, + UserIdToRole:Map, + Quorum:Usize, + ActionLastIndex:Usize, + ActionData:Map, + ActionSigners:Map, + CallerAddress:Address, + Stack:Stack, + caller_address |-> CallerAddress + caller_id |-> UserId + caller_role |-> None, + PerformedActions:List + ) + + requires true + andBool notBool UserId in_keys(UserIdToRole) + ensures true + //@ proof + //@ trusted + // [trusted] + //@ end +endmodule diff --git a/multisig/protocol-correctness/proof/functions/proof-perform-action-endpoint-fragment-no-quorum.k b/multisig/protocol-correctness/proof/functions/proof-perform-action-endpoint-fragment-no-quorum.k new file mode 100644 index 000000000..92569abe0 --- /dev/null +++ b/multisig/protocol-correctness/proof/functions/proof-perform-action-endpoint-fragment-no-quorum.k @@ -0,0 +1,72 @@ +//@ proof +require "trusted-count-can-sign.k" //@ Bazel remove + +module PROOF-PERFORM-ACTION-ENDPOINT-FRAGMENT-NO-QUORUM + imports TRUSTED-COUNT-CAN-SIGN +//@ trusted +// module TRUSTED-PERFORM-ACTION-ENDPOINT-FRAGMENT-NO-QUORUM +//@ end + imports FUNCTIONS-EXECUTE + + claim + runPseudoCode( + caller_address = getCaller(); + caller_id = getUserId(caller_address); + caller_role = getUserIdToRole(caller_id); + require(userRoleCanPerformAction(caller_role)); + require(quorumReached(ActionId:Usize)); + performActionFromId(ActionId); + ) + ~> K:K + + invariantStateFull( + NumUsers:Usize, + UserIdToAddress:Map, + (CallerAddress |-> UserId:Usize _AddressToUserId:Map) #as AddressToUserId:Map, + NumBoardMembers:Usize, + NumProposers:Usize, + (UserId |-> Role:UserRole _UserIdToRole:Map) #as UserIdToRole:Map, + u(Quorum:Int), + ActionLastIndex:Usize, + ActionData:Map, + ActionSigners:Map, + CallerAddress:Address, + Stack:Stack, + .Map, + PerformedActions:List + ) + + => + + error ~> K:K + invariantStateFull( + NumUsers, + UserIdToAddress, + AddressToUserId, + NumBoardMembers, + NumProposers, + UserIdToRole, + u(Quorum), + ActionLastIndex, + ActionData, + ActionSigners, + CallerAddress, + Stack, + caller_address |-> CallerAddress + caller_id |-> UserId + caller_role |-> Role, + PerformedActions + ) + + requires true + andBool userIdToRoleInvariant(UserIdToRole) + andBool actionSignersInvariant(ActionSigners) + + andBool (Role ==K BoardMember orBool Role ==K Proposer) + andBool Quorum >Int countCanSignFunction({ActionSigners[ActionId] orDefault [.]}:>ExpressionList, opaque(UserIdToRole)) + ensures true + //@ proof + //@ trusted + // [trusted] + //@ end +endmodule diff --git a/multisig/protocol-correctness/proof/functions/proof-perform-action-endpoint-fragment-performs.k b/multisig/protocol-correctness/proof/functions/proof-perform-action-endpoint-fragment-performs.k new file mode 100644 index 000000000..e224b59ec --- /dev/null +++ b/multisig/protocol-correctness/proof/functions/proof-perform-action-endpoint-fragment-performs.k @@ -0,0 +1,77 @@ +//@ proof +require "trusted-count-can-sign.k" //@ Bazel remove + +module PROOF-PERFORM-ACTION-ENDPOINT-FRAGMENT-PERFORMS + imports TRUSTED-COUNT-CAN-SIGN +//@ trusted +// module TRUSTED-PERFORM-ACTION-ENDPOINT-FRAGMENT-PERFORMS +//@ end + + imports INVARIANT + + claim + runPseudoCode( + caller_address = getCaller(); + caller_id = getUserId(caller_address); + caller_role = getUserIdToRole(caller_id); + require(userRoleCanPerformAction(caller_role)); + require(quorumReached(ActionId:Usize)); + performActionFromId(ActionId); + ) + ~> K:K + + invariantStateFull( + NumUsers:Usize, + UserIdToAddress:Map, + (CallerAddress |-> UserId:Usize _AddressToUserId:Map) #as AddressToUserId:Map, + NumBoardMembers:Usize, + NumProposers:Usize, + (UserId |-> Role:UserRole _UserIdToRole:Map) #as UserIdToRole:Map, + u(Quorum:Int), + ActionLastIndex:Usize, + ActionData:Map, + ActionSigners:Map, + CallerAddress:Address, + Stack:Stack, + .Map, + PerformedActions:List + ) + + => + + runPseudoCode( + performActionFromId(ActionId); + ) + ~> K:K + + invariantStateFull( + NumUsers, + UserIdToAddress, + AddressToUserId, + NumBoardMembers, + NumProposers, + UserIdToRole, + u(Quorum), + ActionLastIndex, + ActionData, + ActionSigners, + CallerAddress, + Stack, + caller_address |-> CallerAddress + caller_id |-> UserId + caller_role |-> Role, + PerformedActions + ) + + requires true + andBool userIdToRoleInvariant(UserIdToRole) + andBool actionSignersInvariant(ActionSigners) + + andBool (Role ==K BoardMember orBool Role ==K Proposer) + andBool Quorum <=Int countCanSignFunction({ActionSigners[ActionId] orDefault [.]}:>ExpressionList, opaque(UserIdToRole)) + ensures true + //@ proof + //@ trusted + // [trusted] + //@ end +endmodule diff --git a/multisig/protocol-correctness/proof/functions/proof-perform-action-endpoint-no-quorum.k b/multisig/protocol-correctness/proof/functions/proof-perform-action-endpoint-no-quorum.k new file mode 100644 index 000000000..3005141df --- /dev/null +++ b/multisig/protocol-correctness/proof/functions/proof-perform-action-endpoint-no-quorum.k @@ -0,0 +1,62 @@ +//@ proof +require "trusted-perform-action-endpoint-fragment-no-quorum-has-signers.k" //@ Bazel remove + +module PROOF-PERFORM-ACTION-ENDPOINT-NO-QUORUM + imports TRUSTED-PERFORM-ACTION-ENDPOINT-FRAGMENT-NO-QUORUM +//@ trusted +// module TRUSTED-PERFORM-ACTION-ENDPOINT-NO-QUORUM +//@ end + imports FUNCTIONS-EXECUTE + + claim + call(performActionEndpoint(ActionId:Usize)) ~> K:K + invariantStateFull( + NumUsers:Usize, + UserIdToAddress:Map, + (CallerAddress |-> UserId:Usize _AddressToUserId:Map) #as AddressToUserId:Map, + NumBoardMembers:Usize, + NumProposers:Usize, + (UserId |-> Role:UserRole _UserIdToRole:Map) #as UserIdToRole:Map, + u(Quorum:Int), + ActionLastIndex:Usize, + ActionData:Map, + ActionSigners:Map, + CallerAddress:Address, + Stack:Stack, + .Map, + PerformedActions:List + ) + + => + + error ~> K:K + invariantStateFull( + NumUsers, + UserIdToAddress, + AddressToUserId, + NumBoardMembers, + NumProposers, + UserIdToRole, + u(Quorum), + ActionLastIndex, + ActionData, + ActionSigners, + CallerAddress, + Stack, + caller_address |-> CallerAddress + caller_id |-> UserId + caller_role |-> Role, + PerformedActions + ) + + requires true + andBool userIdToRoleInvariant(UserIdToRole) + andBool actionSignersInvariant(ActionSigners) + andBool (Role ==K BoardMember orBool Role ==K Proposer) + andBool Quorum >Int countCanSignFunction({ActionSigners[ActionId] orDefault [.]}:>ExpressionList, opaque(UserIdToRole)) + ensures true + //@ proof + //@ trusted + // [trusted] + //@ end +endmodule diff --git a/multisig/protocol-correctness/proof/functions/proof-perform-action-endpoint-nothing.k b/multisig/protocol-correctness/proof/functions/proof-perform-action-endpoint-nothing.k new file mode 100644 index 000000000..076d9f027 --- /dev/null +++ b/multisig/protocol-correctness/proof/functions/proof-perform-action-endpoint-nothing.k @@ -0,0 +1,70 @@ +//@ proof +require "trusted-perform-action-endpoint-fragment-performs.k" //@ Bazel remove +require "trusted-perform-action-id-nothing.k" //@ Bazel remove + +module PROOF-PERFORM-ACTION-ENDPOINT-NOTHING + imports TRUSTED-PERFORM-ACTION-ENDPOINT-FRAGMENT-PERFORMS + imports TRUSTED-PERFORM-ACTION-ID-NOTHING +//@ trusted +// module TRUSTED-PERFORM-ACTION-ENDPOINT-NOTHING +//@ end + imports FUNCTIONS-EXECUTE + + claim + call(performActionEndpoint(ActionId:Usize)) ~> K:K + invariantStateFull( + NumUsers:Usize, + UserIdToAddress:Map, + (CallerAddress |-> CallerId:Usize + _AddressToUserId:Map + ) #as AddressToUserId:Map, + NumBoardMembers:Usize, + NumProposers:Usize, + (CallerId |-> Role:UserRole + _UserIdToRole:Map + ) #as UserIdToRole:Map, + u(Quorum:Int), + ActionLastIndex:Usize, + ActionData:Map, + ActionSigners:Map, + CallerAddress:Address, + Stack:Stack, + .Map, + PerformedActions:List + ) + + => + + evaluate(void) ~> K:K + invariantStateFull( + NumUsers, + UserIdToAddress, + AddressToUserId, + NumBoardMembers, + NumProposers, + UserIdToRole, + u(Quorum), + ActionLastIndex, + ActionData, + ActionSigners[ActionId <- undef], + CallerAddress, + Stack, + ?_Variables:Map, + ListItem(Nothing) PerformedActions + ) + + requires true + // perform-from-id + andBool notBool ActionId in_keys(ActionData) + + // perform-fragment + andBool actionSignersInvariant(ActionSigners) + andBool userIdToRoleInvariant(UserIdToRole) + andBool (Role ==K BoardMember orBool Role ==K Proposer) + andBool Quorum <=Int countCanSignFunction({ActionSigners[ActionId] orDefault [.]}:>ExpressionList, opaque(UserIdToRole)) + ensures true + //@ proof + //@ trusted + // [trusted] + //@ end +endmodule diff --git a/multisig/protocol-correctness/proof/functions/proof-perform-action-endpoint-remove-user-BoardMember-eq.k b/multisig/protocol-correctness/proof/functions/proof-perform-action-endpoint-remove-user-BoardMember-eq.k new file mode 100644 index 000000000..9379609df --- /dev/null +++ b/multisig/protocol-correctness/proof/functions/proof-perform-action-endpoint-remove-user-BoardMember-eq.k @@ -0,0 +1,73 @@ +//@ proof +require "trusted-perform-action-endpoint-fragment-performs.k" //@ Bazel remove +require "trusted-perform-action-endpoint-id-remove-user-BoardMember.k" //@ Bazel remove + +module PROOF-PERFORM-ACTION-ENDPOINT-REMOVE-USER-BOARDMEMBER-EQ + imports TRUSTED-PERFORM-ACTION-ENDPOINT-FRAGMENT-PERFORMS + imports TRUSTED-PERFORM-ACTION-ID-REMOVE-USER-BOARDMEMBER +//@ trusted +// module TRUSTED-PERFORM-ACTION-ENDPOINT-REMOVE-USER-BOARDMEMBER-EQ +//@ end + imports FUNCTIONS-EXECUTE + + claim + call(performActionEndpoint(ActionId:Usize)) ~> K:K + invariantStateFull( + NumUsers:Usize, + UserIdToAddress:Map, + (CallerAddress |-> CallerId:Usize + _AddressToUserId:Map + ) #as AddressToUserId:Map, + u(NumBoardMembers:Int), + u(NumProposers:Int), + (CallerId |-> BoardMember + UserIdToRoleInner:Map + ) #as UserIdToRole:Map, + u(Quorum:Int), + ActionLastIndex:Usize, + ActionId |-> RemoveUser(CallerAddress:Address) #as Action:Action + ActionData:Map, + ActionSigners:Map, + CallerAddress:Address, + Stack:Stack, + .Map, + PerformedActions:List + ) + + => + + evaluate(void) ~> K:K + invariantStateFull( + NumUsers, + UserIdToAddress, + AddressToUserId, + u(NumBoardMembers -Int 1), + u(NumProposers), + UserIdToRoleInner, + u(Quorum), + ActionLastIndex, + ActionData, + ActionSigners[ActionId <- undef], + CallerAddress, + Stack, + ?_Variables:Map, + ListItem(Action) PerformedActions + ) + + requires true + // perform-from-id + andBool isKResult(Action) + andBool addressToUserIdInvariant(AddressToUserId) + andBool NumBoardMembers +Int NumProposers -Int 1 >Int 0 + andBool Quorum <=Int NumBoardMembers -Int 1 + + // perform-fragment + andBool actionSignersInvariant(ActionSigners) + andBool userIdToRoleInvariant(UserIdToRole) + andBool Quorum <=Int countCanSignFunction({ActionSigners[ActionId] orDefault [.]}:>ExpressionList, opaque(UserIdToRole)) + ensures true + //@ proof + //@ trusted + // [trusted] + //@ end +endmodule diff --git a/multisig/protocol-correctness/proof/functions/proof-perform-action-endpoint-remove-user-BoardMember-too-few-eq.k b/multisig/protocol-correctness/proof/functions/proof-perform-action-endpoint-remove-user-BoardMember-too-few-eq.k new file mode 100644 index 000000000..5230ffc27 --- /dev/null +++ b/multisig/protocol-correctness/proof/functions/proof-perform-action-endpoint-remove-user-BoardMember-too-few-eq.k @@ -0,0 +1,75 @@ +//@ proof +require "trusted-perform-action-endpoint-fragment-performs.k" //@ Bazel remove +require "trusted-perform-action-endpoint-id-remove-user-BoardMember-too-few.k" //@ Bazel remove + +module PROOF-PERFORM-ACTION-ENDPOINT-REMOVE-USER-BOARDMEMBER-TOO-FEW-EQ + imports TRUSTED-PERFORM-ACTION-ENDPOINT-FRAGMENT-PERFORMS + imports TRUSTED-PERFORM-ACTION-ID-REMOVE-USER-BOARDMEMBER-TOO-FEW +//@ trusted +// module TRUSTED-PERFORM-ACTION-ENDPOINT-REMOVE-USER-BOARDMEMBER-TOO-FEW-EQ +//@ end + imports FUNCTIONS-EXECUTE + + claim + call(performActionEndpoint(ActionId:Usize)) ~> K:K + invariantStateFull( + NumUsers:Usize, + UserIdToAddress:Map, + (CallerAddress |-> CallerId:Usize + _AddressToUserId:Map + ) #as AddressToUserId:Map, + u(NumBoardMembers:Int), + u(NumProposers:Int), + (CallerId |-> BoardMember + _UserIdToRole:Map + ) #as UserIdToRole:Map, + u(Quorum:Int), + ActionLastIndex:Usize, + ActionId |-> RemoveUser(CallerAddress:Address) #as Action:Action + ActionData:Map, + ActionSigners:Map, + CallerAddress:Address, + Stack:Stack, + .Map, + PerformedActions:List + ) + + => + + error ~> K:K + invariantStateFull( + NumUsers, + UserIdToAddress, + AddressToUserId, + u(NumBoardMembers), + u(NumProposers), + UserIdToRole, + u(Quorum), + ActionLastIndex, + ActionId |-> Action ActionData, + ActionSigners, + CallerAddress, + Stack, + ?_Variables:Map, + PerformedActions + ) + + requires true + // perform-from-id + andBool isKResult(Action) + andBool addressToUserIdInvariant(AddressToUserId) + andBool (false + orBool NumBoardMembers +Int NumProposers ==Int 1 + orBool Quorum ==Int NumBoardMembers + ) + + // perform-fragment + andBool actionSignersInvariant(ActionSigners) + andBool userIdToRoleInvariant(UserIdToRole) + andBool Quorum <=Int countCanSignFunction({ActionSigners[ActionId] orDefault [.]}:>ExpressionList, opaque(UserIdToRole)) + ensures true + //@ proof + //@ trusted + // [trusted] + //@ end +endmodule diff --git a/multisig/protocol-correctness/proof/functions/proof-perform-action-endpoint-remove-user-BoardMember-too-few.k b/multisig/protocol-correctness/proof/functions/proof-perform-action-endpoint-remove-user-BoardMember-too-few.k new file mode 100644 index 000000000..9621da959 --- /dev/null +++ b/multisig/protocol-correctness/proof/functions/proof-perform-action-endpoint-remove-user-BoardMember-too-few.k @@ -0,0 +1,78 @@ +//@ proof +require "trusted-perform-action-endpoint-fragment-performs.k" //@ Bazel remove +require "trusted-perform-action-endpoint-id-remove-user-BoardMember-too-few.k" //@ Bazel remove + +module PROOF-PERFORM-ACTION-ENDPOINT-REMOVE-USER-BOARDMEMBER-TOO-FEW + imports TRUSTED-PERFORM-ACTION-ENDPOINT-FRAGMENT-PERFORMS + imports TRUSTED-PERFORM-ACTION-ID-REMOVE-USER-BOARDMEMBER-TOO-FEW +//@ trusted +// module TRUSTED-PERFORM-ACTION-ENDPOINT-REMOVE-USER-BOARDMEMBER-TOO-FEW +//@ end + imports FUNCTIONS-EXECUTE + + claim + call(performActionEndpoint(ActionId:Usize)) ~> K:K + invariantStateFull( + NumUsers:Usize, + UserIdToAddress:Map, + (CallerAddress |-> CallerId:Usize + UserAddress |-> UserId:Usize + _AddressToUserId:Map + ) #as AddressToUserId:Map, + u(NumBoardMembers:Int), + u(NumProposers:Int), + (CallerId |-> Role:UserRole + UserId |-> BoardMember + _UserIdToRole:Map + ) #as UserIdToRole:Map, + u(Quorum:Int), + ActionLastIndex:Usize, + ActionId |-> RemoveUser(UserAddress:Address) #as Action:Action + ActionData:Map, + ActionSigners:Map, + CallerAddress:Address, + Stack:Stack, + .Map, + PerformedActions:List + ) + + => + + error ~> K:K + invariantStateFull( + NumUsers, + UserIdToAddress, + AddressToUserId, + u(NumBoardMembers), + u(NumProposers), + UserIdToRole, + u(Quorum), + ActionLastIndex, + ActionId |-> Action ActionData, + ActionSigners, + CallerAddress, + Stack, + ?_Variables:Map, + PerformedActions + ) + + requires true + // perform-from-id + andBool isKResult(Action) + andBool addressToUserIdInvariant(AddressToUserId) + andBool (false + orBool NumBoardMembers +Int NumProposers ==Int 1 + orBool Quorum ==Int NumBoardMembers + ) + + // perform-fragment + andBool actionSignersInvariant(ActionSigners) + andBool userIdToRoleInvariant(UserIdToRole) + andBool (Role ==K BoardMember orBool Role ==K Proposer) + andBool Quorum <=Int countCanSignFunction({ActionSigners[ActionId] orDefault [.]}:>ExpressionList, opaque(UserIdToRole)) + ensures true + //@ proof + //@ trusted + // [trusted] + //@ end +endmodule diff --git a/multisig/protocol-correctness/proof/functions/proof-perform-action-endpoint-remove-user-BoardMember.k b/multisig/protocol-correctness/proof/functions/proof-perform-action-endpoint-remove-user-BoardMember.k new file mode 100644 index 000000000..a0501be64 --- /dev/null +++ b/multisig/protocol-correctness/proof/functions/proof-perform-action-endpoint-remove-user-BoardMember.k @@ -0,0 +1,76 @@ +//@ proof +require "trusted-perform-action-endpoint-fragment-performs.k" //@ Bazel remove +require "trusted-perform-action-endpoint-id-remove-user-BoardMember.k" //@ Bazel remove + +module PROOF-PERFORM-ACTION-ENDPOINT-REMOVE-USER-BOARDMEMBER + imports TRUSTED-PERFORM-ACTION-ENDPOINT-FRAGMENT-PERFORMS + imports TRUSTED-PERFORM-ACTION-ID-REMOVE-USER-BOARDMEMBER +//@ trusted +// module TRUSTED-PERFORM-ACTION-ENDPOINT-REMOVE-USER-BOARDMEMBER +//@ end + imports FUNCTIONS-EXECUTE + + claim + call(performActionEndpoint(ActionId:Usize)) ~> K:K + invariantStateFull( + NumUsers:Usize, + UserIdToAddress:Map, + (CallerAddress |-> CallerId:Usize + UserAddress |-> UserId:Usize + _AddressToUserId:Map + ) #as AddressToUserId:Map, + u(NumBoardMembers:Int), + u(NumProposers:Int), + (CallerId |-> Role:UserRole + UserId |-> BoardMember + UserIdToRoleInner:Map + ) #as UserIdToRole:Map, + u(Quorum:Int), + ActionLastIndex:Usize, + ActionId |-> RemoveUser(UserAddress:Address) #as Action:Action + ActionData:Map, + ActionSigners:Map, + CallerAddress:Address, + Stack:Stack, + .Map, + PerformedActions:List + ) + + => + + evaluate(void) ~> K:K + invariantStateFull( + NumUsers, + UserIdToAddress, + AddressToUserId, + u(NumBoardMembers -Int 1), + u(NumProposers), + (CallerId |-> Role UserIdToRoleInner), + u(Quorum), + ActionLastIndex, + ActionData, + ActionSigners[ActionId <- undef], + CallerAddress, + Stack, + ?_Variables:Map, + ListItem(Action) PerformedActions + ) + + requires true + // perform-from-id + andBool isKResult(Action) + andBool addressToUserIdInvariant(AddressToUserId) + andBool NumBoardMembers +Int NumProposers -Int 1 >Int 0 + andBool Quorum <=Int NumBoardMembers -Int 1 + + // perform-fragment + andBool actionSignersInvariant(ActionSigners) + andBool userIdToRoleInvariant(UserIdToRole) + andBool (Role ==K BoardMember orBool Role ==K Proposer) + andBool Quorum <=Int countCanSignFunction({ActionSigners[ActionId] orDefault [.]}:>ExpressionList, opaque(UserIdToRole)) + ensures true + //@ proof + //@ trusted + // [trusted] + //@ end +endmodule diff --git a/multisig/protocol-correctness/proof/functions/proof-perform-action-endpoint-remove-user-New.k b/multisig/protocol-correctness/proof/functions/proof-perform-action-endpoint-remove-user-New.k new file mode 100644 index 000000000..24c1db79e --- /dev/null +++ b/multisig/protocol-correctness/proof/functions/proof-perform-action-endpoint-remove-user-New.k @@ -0,0 +1,79 @@ +//@ proof +require "trusted-perform-action-endpoint-fragment-performs.k" //@ Bazel remove +require "trusted-perform-action-endpoint-id-remove-user-New.k" //@ Bazel remove + +module PROOF-PERFORM-ACTION-ENDPOINT-REMOVE-USER-NEW + imports TRUSTED-PERFORM-ACTION-ENDPOINT-FRAGMENT-PERFORMS + imports TRUSTED-PERFORM-ACTION-ID-REMOVE-USER-NEW +//@ trusted +// module TRUSTED-PERFORM-ACTION-ENDPOINT-REMOVE-USER-NEW +//@ end + imports FUNCTIONS-EXECUTE + + claim + call(performActionEndpoint(ActionId:Usize)) ~> K:K + invariantStateFull( + u(NumUsers:Int), + UserIdToAddress:Map, + (CallerAddress |-> CallerId:Usize + _AddressToUserId:Map + ) #as AddressToUserId:Map, + u(NumBoardMembers:Int), + u(NumProposers:Int), + (CallerId |-> Role:UserRole + _UserIdToRole:Map + ) #as UserIdToRole:Map, + u(Quorum:Int), + ActionLastIndex:Usize, + ActionId |-> RemoveUser(UserAddress:Address) #as Action:Action + ActionData:Map, + ActionSigners:Map, + CallerAddress:Address, + Stack:Stack, + .Map, + PerformedActions:List + ) + + => + + evaluate(void) ~> K:K + invariantStateFull( + u(NumUsers +Int 1), + u(NumUsers +Int 1) |-> UserAddress UserIdToAddress, + UserAddress |-> u(NumUsers +Int 1) AddressToUserId, + u(NumBoardMembers), + u(NumProposers), + UserIdToRole, + u(Quorum), + ActionLastIndex, + ActionData, + ActionSigners[ActionId <- undef], + CallerAddress, + Stack, + ?_Variables:Map, + ListItem(Action) PerformedActions + ) + + requires true + // perform-from-id + andBool isKResult(Action) + andBool NumUsers >=Int 0 + // TODO: Perhaps replace with unusedIdsInMapValues(AddressToUserId) + + // something to map values to keys. + andBool unusedIdsInMapKeys(NumUsers +Int 1, keysMap(UserIdToAddress), expand(expanded)) + andBool unusedIdsInMapKeys(NumUsers +Int 1, keysMap(UserIdToRole), expand(expanded)) + andBool NumBoardMembers +Int NumProposers >Int 0 + andBool Quorum <=Int NumBoardMembers + andBool notBool (UserAddress in_keys(AddressToUserId)) + + // perform-fragment + andBool actionSignersInvariant(ActionSigners) + andBool userIdToRoleInvariant(UserIdToRole) + andBool (Role ==K BoardMember orBool Role ==K Proposer) + andBool Quorum <=Int countCanSignFunction({ActionSigners[ActionId] orDefault [.]}:>ExpressionList, opaque(UserIdToRole)) + ensures true + //@ proof + //@ trusted + // [trusted] + //@ end +endmodule diff --git a/multisig/protocol-correctness/proof/functions/proof-perform-action-endpoint-remove-user-None.k b/multisig/protocol-correctness/proof/functions/proof-perform-action-endpoint-remove-user-None.k new file mode 100644 index 000000000..f0559a9b1 --- /dev/null +++ b/multisig/protocol-correctness/proof/functions/proof-perform-action-endpoint-remove-user-None.k @@ -0,0 +1,76 @@ +//@ proof +require "trusted-perform-action-endpoint-fragment-performs.k" //@ Bazel remove +require "trusted-perform-action-endpoint-id-remove-user-None.k" //@ Bazel remove + +module PROOF-PERFORM-ACTION-ENDPOINT-REMOVE-USER-NONE + imports TRUSTED-PERFORM-ACTION-ENDPOINT-FRAGMENT-PERFORMS + imports TRUSTED-PERFORM-ACTION-ID-REMOVE-USER-NONE +//@ trusted +// module TRUSTED-PERFORM-ACTION-ENDPOINT-REMOVE-USER-NONE +//@ end + imports FUNCTIONS-EXECUTE + + claim + call(performActionEndpoint(ActionId:Usize)) ~> K:K + invariantStateFull( + NumUsers:Usize, + UserIdToAddress:Map, + (CallerAddress |-> CallerId:Usize + UserAddress |-> UserId:Usize + _AddressToUserId:Map + ) #as AddressToUserId:Map, + u(NumBoardMembers:Int), + u(NumProposers:Int), + (CallerId |-> Role:UserRole + _UserIdToRole:Map + ) #as UserIdToRole:Map, + u(Quorum:Int), + ActionLastIndex:Usize, + ActionId |-> RemoveUser(UserAddress:Address) #as Action:Action + ActionData:Map, + ActionSigners:Map, + CallerAddress:Address, + Stack:Stack, + .Map, + PerformedActions:List + ) + + => + + evaluate(void) ~> K:K + invariantStateFull( + NumUsers, + UserIdToAddress, + AddressToUserId, + u(NumBoardMembers), + u(NumProposers), + UserIdToRole, + u(Quorum), + ActionLastIndex, + ActionData, + ActionSigners[ActionId <- undef], + CallerAddress, + Stack, + ?_Variables:Map, + ListItem(Action) PerformedActions + ) + + requires true + // perform-from-id + andBool isKResult(Action) + andBool addressToUserIdInvariant(AddressToUserId) + andBool Quorum <=Int NumBoardMembers + andBool NumBoardMembers +Int NumProposers >Int 0 + andBool notBool (UserId in_keys(UserIdToRole)) + + // perform-fragment + andBool actionSignersInvariant(ActionSigners) + andBool userIdToRoleInvariant(UserIdToRole) + andBool (Role ==K BoardMember orBool Role ==K Proposer) + andBool Quorum <=Int countCanSignFunction({ActionSigners[ActionId] orDefault [.]}:>ExpressionList, opaque(UserIdToRole)) + ensures true + //@ proof + //@ trusted + // [trusted] + //@ end +endmodule diff --git a/multisig/protocol-correctness/proof/functions/proof-perform-action-endpoint-remove-user-Proposer-eq.k b/multisig/protocol-correctness/proof/functions/proof-perform-action-endpoint-remove-user-Proposer-eq.k new file mode 100644 index 000000000..9e125b78e --- /dev/null +++ b/multisig/protocol-correctness/proof/functions/proof-perform-action-endpoint-remove-user-Proposer-eq.k @@ -0,0 +1,73 @@ +//@ proof +require "trusted-perform-action-endpoint-fragment-performs.k" //@ Bazel remove +require "trusted-perform-action-endpoint-id-remove-user-Proposer.k" //@ Bazel remove + +module PROOF-PERFORM-ACTION-ENDPOINT-REMOVE-USER-PROPOSER-EQ + imports TRUSTED-PERFORM-ACTION-ENDPOINT-FRAGMENT-PERFORMS + imports TRUSTED-PERFORM-ACTION-ID-REMOVE-USER-PROPOSER +//@ trusted +// module TRUSTED-PERFORM-ACTION-ENDPOINT-REMOVE-USER-PROPOSER-EQ +//@ end + imports FUNCTIONS-EXECUTE + + claim + call(performActionEndpoint(ActionId:Usize)) ~> K:K + invariantStateFull( + NumUsers:Usize, + UserIdToAddress:Map, + (CallerAddress |-> CallerId:Usize + _AddressToUserId:Map + ) #as AddressToUserId:Map, + u(NumBoardMembers:Int), + u(NumProposers:Int), + (CallerId |-> Proposer + UserIdToRoleInner:Map + ) #as UserIdToRole:Map, + u(Quorum:Int), + ActionLastIndex:Usize, + ActionId |-> RemoveUser(CallerAddress:Address) #as Action:Action + ActionData:Map, + ActionSigners:Map, + CallerAddress:Address, + Stack:Stack, + .Map, + PerformedActions:List + ) + + => + + evaluate(void) ~> K:K + invariantStateFull( + NumUsers, + UserIdToAddress, + AddressToUserId, + u(NumBoardMembers), + u(NumProposers -Int 1), + UserIdToRoleInner, + u(Quorum), + ActionLastIndex, + ActionData, + ActionSigners[ActionId <- undef], + CallerAddress, + Stack, + ?_Variables:Map, + ListItem(Action) PerformedActions + ) + + requires true + // perform-from-id + andBool isKResult(Action) + andBool addressToUserIdInvariant(AddressToUserId) + andBool Quorum <=Int NumBoardMembers + andBool NumBoardMembers +Int NumProposers -Int 1 >Int 0 + + // perform-fragment + andBool actionSignersInvariant(ActionSigners) + andBool userIdToRoleInvariant(UserIdToRole) + andBool Quorum <=Int countCanSignFunction({ActionSigners[ActionId] orDefault [.]}:>ExpressionList, opaque(UserIdToRole)) + ensures true + //@ proof + //@ trusted + // [trusted] + //@ end +endmodule diff --git a/multisig/protocol-correctness/proof/functions/proof-perform-action-endpoint-remove-user-Proposer-nobody-left-eq.k b/multisig/protocol-correctness/proof/functions/proof-perform-action-endpoint-remove-user-Proposer-nobody-left-eq.k new file mode 100644 index 000000000..ebdb5f4a6 --- /dev/null +++ b/multisig/protocol-correctness/proof/functions/proof-perform-action-endpoint-remove-user-Proposer-nobody-left-eq.k @@ -0,0 +1,73 @@ +//@ proof +require "trusted-perform-action-endpoint-fragment-performs.k" //@ Bazel remove +require "trusted-perform-action-endpoint-id-remove-user-Proposer-nobody-left.k" //@ Bazel remove + +module PROOF-PERFORM-ACTION-ENDPOINT-REMOVE-USER-PROPOSER-NOBODY-LEFT-EQ + imports TRUSTED-PERFORM-ACTION-ENDPOINT-FRAGMENT-PERFORMS + imports TRUSTED-PERFORM-ACTION-ID-REMOVE-USER-PROPOSER-NOBODY-LEFT +//@ trusted +// module TRUSTED-PERFORM-ACTION-ENDPOINT-REMOVE-USER-PROPOSER-NOBODY-LEFT-EQ +//@ end + imports FUNCTIONS-EXECUTE + + claim + call(performActionEndpoint(ActionId:Usize)) ~> K:K + invariantStateFull( + NumUsers:Usize, + UserIdToAddress:Map, + (CallerAddress |-> CallerId:Usize + _AddressToUserId:Map + ) #as AddressToUserId:Map, + u(NumBoardMembers:Int), + u(NumProposers:Int), + (CallerId |-> Proposer + _UserIdToRole:Map + ) #as UserIdToRole:Map, + u(Quorum:Int), + ActionLastIndex:Usize, + ActionId |-> RemoveUser(CallerAddress:Address) #as Action:Action + ActionData:Map, + ActionSigners:Map, + CallerAddress:Address, + Stack:Stack, + .Map, + PerformedActions:List + ) + + => + + error ~> K:K + invariantStateFull( + NumUsers, + UserIdToAddress, + AddressToUserId, + u(NumBoardMembers), + u(NumProposers), + UserIdToRole, + u(Quorum), + ActionLastIndex, + ActionId |-> Action ActionData, + ActionSigners, + CallerAddress, + Stack, + ?_Variables:Map, + PerformedActions + ) + + requires true + // perform-from-id + andBool isKResult(Action) + andBool addressToUserIdInvariant(AddressToUserId) + andBool Quorum <=Int NumBoardMembers + andBool NumBoardMembers +Int NumProposers ==Int 1 + + // perform-fragment + andBool actionSignersInvariant(ActionSigners) + andBool userIdToRoleInvariant(UserIdToRole) + andBool Quorum <=Int countCanSignFunction({ActionSigners[ActionId] orDefault [.]}:>ExpressionList, opaque(UserIdToRole)) + ensures true + //@ proof + //@ trusted + // [trusted] + //@ end +endmodule diff --git a/multisig/protocol-correctness/proof/functions/proof-perform-action-endpoint-remove-user-Proposer-nobody-left.k b/multisig/protocol-correctness/proof/functions/proof-perform-action-endpoint-remove-user-Proposer-nobody-left.k new file mode 100644 index 000000000..439e02bfd --- /dev/null +++ b/multisig/protocol-correctness/proof/functions/proof-perform-action-endpoint-remove-user-Proposer-nobody-left.k @@ -0,0 +1,76 @@ +//@ proof +require "trusted-perform-action-endpoint-fragment-performs.k" //@ Bazel remove +require "trusted-perform-action-endpoint-id-remove-user-Proposer-nobody-left.k" //@ Bazel remove + +module PROOF-PERFORM-ACTION-ENDPOINT-REMOVE-USER-PROPOSER-NOBODY-LEFT + imports TRUSTED-PERFORM-ACTION-ENDPOINT-FRAGMENT-PERFORMS + imports TRUSTED-PERFORM-ACTION-ID-REMOVE-USER-PROPOSER-NOBODY-LEFT +//@ trusted +// module TRUSTED-PERFORM-ACTION-ENDPOINT-REMOVE-USER-PROPOSER-NOBODY-LEFT +//@ end + imports FUNCTIONS-EXECUTE + + claim + call(performActionEndpoint(ActionId:Usize)) ~> K:K + invariantStateFull( + NumUsers:Usize, + UserIdToAddress:Map, + (CallerAddress |-> CallerId:Usize + UserAddress |-> UserId:Usize + _AddressToUserId:Map + ) #as AddressToUserId:Map, + u(NumBoardMembers:Int), + u(NumProposers:Int), + (CallerId |-> Role:UserRole + UserId |-> Proposer + _UserIdToRole:Map + ) #as UserIdToRole:Map, + u(Quorum:Int), + ActionLastIndex:Usize, + ActionId |-> RemoveUser(UserAddress:Address) #as Action:Action + ActionData:Map, + ActionSigners:Map, + CallerAddress:Address, + Stack:Stack, + .Map, + PerformedActions:List + ) + + => + + error ~> K:K + invariantStateFull( + NumUsers, + UserIdToAddress, + AddressToUserId, + u(NumBoardMembers), + u(NumProposers), + UserIdToRole, + u(Quorum), + ActionLastIndex, + ActionId |-> Action ActionData, + ActionSigners, + CallerAddress, + Stack, + ?_Variables:Map, + PerformedActions + ) + + requires true + // perform-from-id + andBool isKResult(Action) + andBool addressToUserIdInvariant(AddressToUserId) + andBool Quorum <=Int NumBoardMembers + andBool NumBoardMembers +Int NumProposers ==Int 1 + + // perform-fragment + andBool actionSignersInvariant(ActionSigners) + andBool userIdToRoleInvariant(UserIdToRole) + andBool (Role ==K BoardMember orBool Role ==K Proposer) + andBool Quorum <=Int countCanSignFunction({ActionSigners[ActionId] orDefault [.]}:>ExpressionList, opaque(UserIdToRole)) + ensures true + //@ proof + //@ trusted + // [trusted] + //@ end +endmodule diff --git a/multisig/protocol-correctness/proof/functions/proof-perform-action-endpoint-remove-user-Proposer.k b/multisig/protocol-correctness/proof/functions/proof-perform-action-endpoint-remove-user-Proposer.k new file mode 100644 index 000000000..396d182cc --- /dev/null +++ b/multisig/protocol-correctness/proof/functions/proof-perform-action-endpoint-remove-user-Proposer.k @@ -0,0 +1,76 @@ +//@ proof +require "trusted-perform-action-endpoint-fragment-performs.k" //@ Bazel remove +require "trusted-perform-action-endpoint-id-remove-user-Proposer.k" //@ Bazel remove + +module PROOF-PERFORM-ACTION-ENDPOINT-REMOVE-USER-PROPOSER + imports TRUSTED-PERFORM-ACTION-ENDPOINT-FRAGMENT-PERFORMS + imports TRUSTED-PERFORM-ACTION-ID-REMOVE-USER-PROPOSER +//@ trusted +// module TRUSTED-PERFORM-ACTION-ENDPOINT-REMOVE-USER-PROPOSER +//@ end + imports FUNCTIONS-EXECUTE + + claim + call(performActionEndpoint(ActionId:Usize)) ~> K:K + invariantStateFull( + NumUsers:Usize, + UserIdToAddress:Map, + (CallerAddress |-> CallerId:Usize + UserAddress |-> UserId:Usize + _AddressToUserId:Map + ) #as AddressToUserId:Map, + u(NumBoardMembers:Int), + u(NumProposers:Int), + (CallerId |-> Role:UserRole + UserId |-> Proposer + UserIdToRoleInner:Map + ) #as UserIdToRole:Map, + u(Quorum:Int), + ActionLastIndex:Usize, + ActionId |-> RemoveUser(UserAddress:Address) #as Action:Action + ActionData:Map, + ActionSigners:Map, + CallerAddress:Address, + Stack:Stack, + .Map, + PerformedActions:List + ) + + => + + evaluate(void) ~> K:K + invariantStateFull( + NumUsers, + UserIdToAddress, + AddressToUserId, + u(NumBoardMembers), + u(NumProposers -Int 1), + (CallerId |-> Role UserIdToRoleInner), + u(Quorum), + ActionLastIndex, + ActionData, + ActionSigners[ActionId <- undef], + CallerAddress, + Stack, + ?_Variables:Map, + ListItem(Action) PerformedActions + ) + + requires true + // perform-from-id + andBool isKResult(Action) + andBool addressToUserIdInvariant(AddressToUserId) + andBool Quorum <=Int NumBoardMembers + andBool NumBoardMembers +Int NumProposers -Int 1 >Int 0 + + // perform-fragment + andBool actionSignersInvariant(ActionSigners) + andBool userIdToRoleInvariant(UserIdToRole) + andBool (Role ==K BoardMember orBool Role ==K Proposer) + andBool Quorum <=Int countCanSignFunction({ActionSigners[ActionId] orDefault [.]}:>ExpressionList, opaque(UserIdToRole)) + ensures true + //@ proof + //@ trusted + // [trusted] + //@ end +endmodule diff --git a/multisig/protocol-correctness/proof/functions/proof-perform-action-endpoint-sc-call.k b/multisig/protocol-correctness/proof/functions/proof-perform-action-endpoint-sc-call.k new file mode 100644 index 000000000..4d02b210e --- /dev/null +++ b/multisig/protocol-correctness/proof/functions/proof-perform-action-endpoint-sc-call.k @@ -0,0 +1,75 @@ +//@ proof +require "trusted-perform-action-endpoint-fragment-performs.k" //@ Bazel remove +require "trusted-perform-action-id-sc-call.k" //@ Bazel remove + +module PROOF-PERFORM-ACTION-ENDPOINT-SC-CALL + imports TRUSTED-PERFORM-ACTION-ENDPOINT-FRAGMENT-PERFORMS + imports TRUSTED-PERFORM-ACTION-ID-SC-CALL +//@ trusted +// module TRUSTED-PERFORM-ACTION-ENDPOINT-SC-CALL +//@ end + imports FUNCTIONS-EXECUTE + + claim + call(performActionEndpoint(ActionId:Usize)) ~> K:K + invariantStateFull( + NumUsers:Usize, + UserIdToAddress:Map, + (CallerAddress |-> CallerId:Usize + _AddressToUserId:Map + ) #as AddressToUserId:Map, + NumBoardMembers:Usize, + NumProposers:Usize, + (CallerId |-> Role:UserRole + _UserIdToRole:Map + ) #as UserIdToRole:Map, + u(Quorum:Int), + ActionLastIndex:Usize, + ActionId |-> SCCall( + _To:Address, + _Amount:BigUint, + _Function:BoxedBytes, + _Arguments:ExpressionList) #as Action:Action + ActionData:Map, + ActionSigners:Map, + CallerAddress:Address, + Stack:Stack, + .Map, + PerformedActions:List + ) + + => + + evaluate(void) ~> K:K + invariantStateFull( + NumUsers, + UserIdToAddress, + AddressToUserId, + NumBoardMembers, + NumProposers, + UserIdToRole, + u(Quorum), + ActionLastIndex, + ActionData, + ActionSigners[ActionId <- undef], + CallerAddress, + Stack, + ?_Variables:Map, + ListItem(Action) PerformedActions + ) + + requires true + // perform-from-id + andBool isKResult(Action) + + // perform-fragment + andBool actionSignersInvariant(ActionSigners) + andBool userIdToRoleInvariant(UserIdToRole) + andBool (Role ==K BoardMember orBool Role ==K Proposer) + andBool Quorum <=Int countCanSignFunction({ActionSigners[ActionId] orDefault [.]}:>ExpressionList, opaque(UserIdToRole)) + ensures true + //@ proof + //@ trusted + // [trusted] + //@ end +endmodule diff --git a/multisig/protocol-correctness/proof/functions/proof-perform-action-endpoint-sc-deploy.k b/multisig/protocol-correctness/proof/functions/proof-perform-action-endpoint-sc-deploy.k new file mode 100644 index 000000000..65dbd23ac --- /dev/null +++ b/multisig/protocol-correctness/proof/functions/proof-perform-action-endpoint-sc-deploy.k @@ -0,0 +1,75 @@ +//@ proof +require "trusted-perform-action-endpoint-fragment-performs.k" //@ Bazel remove +require "trusted-perform-action-id-sc-deploy.k" //@ Bazel remove + +module PROOF-PERFORM-ACTION-ENDPOINT-SC-DEPLOY + imports TRUSTED-PERFORM-ACTION-ENDPOINT-FRAGMENT-PERFORMS + imports TRUSTED-PERFORM-ACTION-ID-SC-DEPLOY +//@ trusted +// module TRUSTED-PERFORM-ACTION-ENDPOINT-SC-DEPLOY +//@ end + imports FUNCTIONS-EXECUTE + + claim + call(performActionEndpoint(ActionId:Usize)) ~> K:K + invariantStateFull( + NumUsers:Usize, + UserIdToAddress:Map, + (CallerAddress |-> CallerId:Usize + _AddressToUserId:Map + ) #as AddressToUserId:Map, + NumBoardMembers:Usize, + NumProposers:Usize, + (CallerId |-> Role:UserRole + _UserIdToRole:Map + ) #as UserIdToRole:Map, + u(Quorum:Int), + ActionLastIndex:Usize, + ActionId |-> SCDeploy( + _Amount:BigUint, + _Code:BoxedBytes, + _CodeMetadata:CodeMetadata, + _Arguments:ExpressionList) #as Action:Action + ActionData:Map, + ActionSigners:Map, + CallerAddress:Address, + Stack:Stack, + .Map, + PerformedActions:List + ) + + => + + evaluate(void) ~> K:K + invariantStateFull( + NumUsers, + UserIdToAddress, + AddressToUserId, + NumBoardMembers, + NumProposers, + UserIdToRole, + u(Quorum), + ActionLastIndex, + ActionData, + ActionSigners[ActionId <- undef], + CallerAddress, + Stack, + ?_Variables:Map, + ListItem(Action) PerformedActions + ) + + requires true + // perform-from-id + andBool isKResult(Action) + + // perform-fragment + andBool actionSignersInvariant(ActionSigners) + andBool userIdToRoleInvariant(UserIdToRole) + andBool (Role ==K BoardMember orBool Role ==K Proposer) + andBool Quorum <=Int countCanSignFunction({ActionSigners[ActionId] orDefault [.]}:>ExpressionList, opaque(UserIdToRole)) + ensures true + //@ proof + //@ trusted + // [trusted] + //@ end +endmodule diff --git a/multisig/protocol-correctness/proof/functions/proof-perform-action-endpoint-send-egld.k b/multisig/protocol-correctness/proof/functions/proof-perform-action-endpoint-send-egld.k new file mode 100644 index 000000000..740c5a62d --- /dev/null +++ b/multisig/protocol-correctness/proof/functions/proof-perform-action-endpoint-send-egld.k @@ -0,0 +1,74 @@ +//@ proof +require "trusted-perform-action-endpoint-fragment-performs.k" //@ Bazel remove +require "trusted-perform-action-id-send-egld.k" //@ Bazel remove + +module PROOF-PERFORM-ACTION-ENDPOINT-SEND-EGLD + imports TRUSTED-PERFORM-ACTION-ENDPOINT-FRAGMENT-PERFORMS + imports TRUSTED-PERFORM-ACTION-ID-SEND-EGLD +//@ trusted +// module TRUSTED-PERFORM-ACTION-ENDPOINT-SEND-EGLD +//@ end + imports FUNCTIONS-EXECUTE + + claim + call(performActionEndpoint(ActionId:Usize)) ~> K:K + invariantStateFull( + NumUsers:Usize, + UserIdToAddress:Map, + (CallerAddress |-> CallerId:Usize + _AddressToUserId:Map + ) #as AddressToUserId:Map, + NumBoardMembers:Usize, + NumProposers:Usize, + (CallerId |-> Role:UserRole + _UserIdToRole:Map + ) #as UserIdToRole:Map, + u(Quorum:Int), + ActionLastIndex:Usize, + ActionId |-> SendEgld( + _To:Address, + _Amount:BigUint, + _Data:BoxedBytes) #as Action:Action + ActionData:Map, + ActionSigners:Map, + CallerAddress:Address, + Stack:Stack, + .Map, + PerformedActions:List + ) + + => + + evaluate(void) ~> K:K + invariantStateFull( + NumUsers, + UserIdToAddress, + AddressToUserId, + NumBoardMembers, + NumProposers, + UserIdToRole, + u(Quorum), + ActionLastIndex, + ActionData, + ActionSigners[ActionId <- undef], + CallerAddress, + Stack, + ?_Variables:Map, + ListItem(Action) PerformedActions + ) + + requires true + // perform-from-id + andBool isKResult(Action) + + // perform-fragment + andBool actionSignersInvariant(ActionSigners) + andBool userIdToRoleInvariant(UserIdToRole) + andBool (Role ==K BoardMember orBool Role ==K Proposer) + andBool Quorum <=Int countCanSignFunction({ActionSigners[ActionId] orDefault [.]}:>ExpressionList, opaque(UserIdToRole)) + ensures true + //@ proof + //@ trusted + // [trusted] + //@ end +endmodule diff --git a/multisig/protocol-correctness/proof/functions/proof-perform-action-id-add-board-member-BoardMember.k b/multisig/protocol-correctness/proof/functions/proof-perform-action-id-add-board-member-BoardMember.k new file mode 100644 index 000000000..25065335b --- /dev/null +++ b/multisig/protocol-correctness/proof/functions/proof-perform-action-id-add-board-member-BoardMember.k @@ -0,0 +1,97 @@ +//@ proof +require "trusted-perform-action-add-board-member-boardmember.k" //@ Bazel remove + +module PROOF-PERFORM-ACTION-ID-ADD-BOARD-MEMBER-BOARDMEMBER + imports TRUSTED-PERFORM-ACTION-ADD-BOARD-MEMBER-BOARDMEMBER +//@ trusted +// module TRUSTED-PERFORM-ACTION-ID-ADD-BOARD-MEMBER-BOARDMEMBER +//@ end + + imports INVARIANT-HELPERS + imports PSEUDOCODE + + claim + + call(performActionFromId(ActionId:Usize)) ~> K:K + + + + NumUsers:Usize + UserIdToAddress:Map + (UserAddress |-> UserId:Usize _AddressToUserId:Map) #as AddressToUserId:Map + + + NumBoardMembers:Usize + NumProposers:Usize + (UserId |-> BoardMember _UserIdToRole:Map) #as UserIdToRole:Map + Quorum:Usize + + + ActionLastIndex:Usize + + + ActionId |-> AddBoardMember(UserAddress:Address) #as Action:Action + ActionData:Map + + ActionSigners:Map + + + + + .Map + Stack:Stack + + + CallerAddress:Address + + + PerformedActions:List + + + + => + + evaluate(void) ~> K + + + + NumUsers + UserIdToAddress + AddressToUserId + + + NumBoardMembers + NumProposers + UserIdToRole + Quorum + + + ActionLastIndex + + ActionData + ActionSigners[ActionId <- undef] + + + + + ?_Variables:Map + Stack + + + CallerAddress + + + ListItem(Action) PerformedActions + + + + requires true + andBool isKResult(Action) + andBool addressToUserIdInvariant(AddressToUserId) + ensures true + //@ proof + //@ trusted + // [trusted] + //@ end + +endmodule diff --git a/multisig/protocol-correctness/proof/functions/proof-perform-action-id-add-board-member-New.k b/multisig/protocol-correctness/proof/functions/proof-perform-action-id-add-board-member-New.k new file mode 100644 index 000000000..ada782534 --- /dev/null +++ b/multisig/protocol-correctness/proof/functions/proof-perform-action-id-add-board-member-New.k @@ -0,0 +1,104 @@ +//@ proof +require "trusted-perform-action-add-board-member-new.k" //@ Bazel remove + +module PROOF-PERFORM-ACTION-ID-ADD-BOARD-MEMBER-NEW + imports TRUSTED-PERFORM-ACTION-ADD-BOARD-MEMBER-NEW +//@ trusted +// module TRUSTED-PERFORM-ACTION-ID-ADD-BOARD-MEMBER-NEW +//@ end + + imports INVARIANT-HELPERS + imports PSEUDOCODE + + claim + + call(performActionFromId(ActionId:Usize)) ~> K:K + + + + u(NumUsers:Int) + UserIdToAddress:Map + AddressToUserId:Map + + + u(NumBoardMembers:Int) + NumProposers:Usize + UserIdToRole:Map + Quorum:Usize + + + ActionLastIndex:Usize + + + ActionId |-> AddBoardMember(UserAddress:Address) #as Action:Action + ActionData:Map + + ActionSigners:Map + + + + + .Map + Stack:Stack + + + CallerAddress:Address + + + PerformedActions:List + + + + => + + evaluate(void) ~> K + + + + u(NumUsers +Int 1) + u(NumUsers +Int 1) |-> UserAddress UserIdToAddress + UserAddress |-> u(NumUsers +Int 1) AddressToUserId + + + u(NumBoardMembers +Int 1) + NumProposers + u(NumUsers +Int 1) |-> BoardMember UserIdToRole + Quorum + + + ActionLastIndex + + ActionData + ActionSigners[ActionId <- undef] + + + + + ?_Variables:Map + Stack + + + CallerAddress + + + ListItem(Action) PerformedActions + + + + requires true + andBool isKResult(Action) + + andBool NumUsers >=Int 0 + // TODO: Perhaps replace with unusedIdsInMapValues(AddressToUserId) + + // someting to map values to keys. + andBool unusedIdsInMapKeys(NumUsers +Int 1, keysMap(UserIdToAddress), expand(expanded)) + andBool unusedIdsInMapKeys(NumUsers +Int 1, keysMap(UserIdToRole), expand(expanded)) + + andBool notBool UserAddress in_keys(AddressToUserId) + ensures true + //@ proof + //@ trusted + // [trusted] + //@ end + +endmodule diff --git a/multisig/protocol-correctness/proof/functions/proof-perform-action-id-add-board-member-None.k b/multisig/protocol-correctness/proof/functions/proof-perform-action-id-add-board-member-None.k new file mode 100644 index 000000000..77a3a0dff --- /dev/null +++ b/multisig/protocol-correctness/proof/functions/proof-perform-action-id-add-board-member-None.k @@ -0,0 +1,99 @@ +//@ proof +require "trusted-perform-action-add-board-member-none.k" //@ Bazel remove + +module PROOF-PERFORM-ACTION-ID-ADD-BOARD-MEMBER-NONE + imports TRUSTED-PERFORM-ACTION-ADD-BOARD-MEMBER-NONE +//@ trusted +// module TRUSTED-PERFORM-ACTION-ID-ADD-BOARD-MEMBER-NONE +//@ end + + imports INVARIANT-HELPERS + imports PSEUDOCODE + + claim + + call(performActionFromId(ActionId:Usize)) ~> K:K + + + + NumUsers:Usize + UserIdToAddress:Map + (UserAddress |-> UserId:Usize _AddressToUserId:Map) #as AddressToUserId:Map + + + u(NumBoardMembers:Int) + NumProposers:Usize + UserIdToRole:Map + Quorum:Usize + + + ActionLastIndex:Usize + + + ActionId |-> AddBoardMember(UserAddress:Address) #as Action:Action + ActionData:Map + + ActionSigners:Map + + + + + .Map + Stack:Stack + + + CallerAddress:Address + + + PerformedActions:List + + + + => + + evaluate(void) ~> K + + + + NumUsers + UserIdToAddress + AddressToUserId + + + u(NumBoardMembers +Int 1) + NumProposers + UserId |-> BoardMember UserIdToRole + Quorum + + + ActionLastIndex + + ActionData + ActionSigners[ActionId <- undef] + + + + + ?_Variables:Map + Stack + + + CallerAddress + + + ListItem(Action) PerformedActions + + + + requires true + andBool isKResult(Action) + andBool addressToUserIdInvariant(AddressToUserId) + + andBool notBool UserId in_keys(UserIdToRole) + ensures true + //@ proof + //@ trusted + // [trusted] + //@ end + +endmodule diff --git a/multisig/protocol-correctness/proof/functions/proof-perform-action-id-add-board-member-Proposer.k b/multisig/protocol-correctness/proof/functions/proof-perform-action-id-add-board-member-Proposer.k new file mode 100644 index 000000000..7e21661e0 --- /dev/null +++ b/multisig/protocol-correctness/proof/functions/proof-perform-action-id-add-board-member-Proposer.k @@ -0,0 +1,97 @@ +//@ proof +require "trusted-perform-action-add-board-member-proposer.k" //@ Bazel remove + +module PROOF-PERFORM-ACTION-ID-ADD-BOARD-MEMBER-PROPOSER + imports TRUSTED-PERFORM-ACTION-ADD-BOARD-MEMBER-PROPOSER +//@ trusted +// module TRUSTED-PERFORM-ACTION-ID-ADD-BOARD-MEMBER-PROPOSER +//@ end + + imports INVARIANT-HELPERS + imports PSEUDOCODE + + claim + + call(performActionFromId(ActionId:Usize)) ~> K:K + + + + NumUsers:Usize + UserIdToAddress:Map + (UserAddress |-> UserId:Usize _AddressToUserId:Map) #as AddressToUserId:Map + + + u(NumBoardMembers:Int) + u(NumProposers:Int) + UserId |-> Proposer UserIdToRole:Map + Quorum:Usize + + + ActionLastIndex:Usize + + + ActionId |-> AddBoardMember(UserAddress:Address) #as Action:Action + ActionData:Map + + ActionSigners:Map + + + + + .Map + Stack:Stack + + + CallerAddress:Address + + + PerformedActions:List + + + + => + + evaluate(void) ~> K + + + + NumUsers + UserIdToAddress + AddressToUserId + + + u(NumBoardMembers +Int 1) + u(NumProposers -Int 1) + UserId |-> BoardMember UserIdToRole:Map + Quorum + + + ActionLastIndex + + ActionData + ActionSigners[ActionId <- undef] + + + + + ?_Variables:Map + Stack + + + CallerAddress + + + ListItem(Action) PerformedActions + + + + requires true + andBool isKResult(Action) + andBool addressToUserIdInvariant(AddressToUserId) + ensures true + //@ proof + //@ trusted + // [trusted] + //@ end + +endmodule diff --git a/multisig/protocol-correctness/proof/functions/proof-perform-action-id-add-proposer-BoardMember-no-quorum.k b/multisig/protocol-correctness/proof/functions/proof-perform-action-id-add-proposer-BoardMember-no-quorum.k new file mode 100644 index 000000000..ff114239b --- /dev/null +++ b/multisig/protocol-correctness/proof/functions/proof-perform-action-id-add-proposer-BoardMember-no-quorum.k @@ -0,0 +1,99 @@ +//@ proof +require "trusted-perform-action-add-proposer-boardmember-no-quorum.k" //@ Bazel remove + +module PROOF-PERFORM-ACTION-ID-ADD-PROPOSER-BOARDMEMBER-NO-QUORUM + imports TRUSTED-PERFORM-ACTION-ADD-PROPOSER-BOARDMEMBER-NO-QUORUM +//@ trusted +// module TRUSTED-PERFORM-ACTION-ID-ADD-PROPOSER-BOARDMEMBER-NO-QUORUM +//@ end + + imports INVARIANT-HELPERS + imports PSEUDOCODE + + claim + + call(performActionFromId(ActionId:Usize)) ~> K:K + + + + NumUsers:Usize + UserIdToAddress:Map + (UserAddress |-> UserId:Usize _AddressToUserId:Map) #as AddressToUserId:Map + + + u(NumBoardMembers:Int) + u(NumProposers:Int) + (UserId |-> BoardMember _UserIdToRole:Map) #as UserIdToRole:Map + u(Quorum:Int) + + + ActionLastIndex:Usize + + + ActionId |-> AddProposer(UserAddress:Address) #as Action:Action + ActionData:Map + + ActionSigners:Map + + + + + .Map + Stack:Stack + + + CallerAddress:Address + + + PerformedActions:List + + + + => + + error ~> K + + + + NumUsers + UserIdToAddress + AddressToUserId + + + u(NumBoardMembers) + u(NumProposers) + UserIdToRole:Map + u(Quorum) + + + ActionLastIndex + + ActionData + ActionSigners[ActionId <- undef] + + + + + ?_Variables:Map + Stack + + + CallerAddress + + + PerformedActions + + + + requires true + andBool isKResult(Action) + andBool addressToUserIdInvariant(AddressToUserId) + + andBool Quorum ==Int NumBoardMembers + ensures true + //@ proof + //@ trusted + // [trusted] + //@ end + +endmodule diff --git a/multisig/protocol-correctness/proof/functions/proof-perform-action-id-add-proposer-BoardMember.k b/multisig/protocol-correctness/proof/functions/proof-perform-action-id-add-proposer-BoardMember.k new file mode 100644 index 000000000..e7eb8b39f --- /dev/null +++ b/multisig/protocol-correctness/proof/functions/proof-perform-action-id-add-proposer-BoardMember.k @@ -0,0 +1,99 @@ +//@ proof +require "trusted-perform-action-add-proposer-boardmember.k" //@ Bazel remove + +module PROOF-PERFORM-ACTION-ID-ADD-PROPOSER-BOARDMEMBER + imports TRUSTED-PERFORM-ACTION-ADD-PROPOSER-BOARDMEMBER +//@ trusted +// module TRUSTED-PERFORM-ACTION-ID-ADD-PROPOSER-BOARDMEMBER +//@ end + + imports INVARIANT-HELPERS + imports PSEUDOCODE + + claim + + call(performActionFromId(ActionId:Usize)) ~> K:K + + + + NumUsers:Usize + UserIdToAddress:Map + (UserAddress |-> UserId:Usize _AddressToUserId:Map) #as AddressToUserId:Map + + + u(NumBoardMembers:Int) + u(NumProposers:Int) + UserId |-> BoardMember UserIdToRole:Map + u(Quorum:Int) + + + ActionLastIndex:Usize + + + ActionId |-> AddProposer(UserAddress:Address) #as Action:Action + ActionData:Map + + ActionSigners:Map + + + + + .Map + Stack:Stack + + + CallerAddress:Address + + + PerformedActions:List + + + + => + + evaluate(void) ~> K + + + + NumUsers + UserIdToAddress + AddressToUserId + + + u(NumBoardMembers -Int 1) + u(NumProposers +Int 1) + UserId |-> Proposer UserIdToRole:Map + u(Quorum) + + + ActionLastIndex + + ActionData + ActionSigners[ActionId <- undef] + + + + + ?_Variables:Map + Stack + + + CallerAddress + + + ListItem(Action) PerformedActions + + + + requires true + andBool isKResult(Action) + andBool addressToUserIdInvariant(AddressToUserId) + + andBool Quorum <=Int NumBoardMembers -Int 1 + ensures true + //@ proof + //@ trusted + // [trusted] + //@ end + +endmodule diff --git a/multisig/protocol-correctness/proof/functions/proof-perform-action-id-add-proposer-New.k b/multisig/protocol-correctness/proof/functions/proof-perform-action-id-add-proposer-New.k new file mode 100644 index 000000000..a3f696807 --- /dev/null +++ b/multisig/protocol-correctness/proof/functions/proof-perform-action-id-add-proposer-New.k @@ -0,0 +1,105 @@ +//@ proof +require "trusted-perform-action-add-proposer-new.k" //@ Bazel remove + +module PROOF-PERFORM-ACTION-ID-ADD-PROPOSER-NEW + imports TRUSTED-PERFORM-ACTION-ADD-PROPOSER-NEW +//@ trusted +// module TRUSTED-PERFORM-ACTION-ID-ADD-PROPOSER-NEW +//@ end + + imports EXECUTION-PROOF-HELPERS + imports PSEUDOCODE + + claim + + call(performActionFromId(ActionId:Usize)) ~> K:K + + + + u(NumUsers:Int) + UserIdToAddress:Map + AddressToUserId:Map + + + u(NumBoardMembers:Int) + u(NumProposers:Int) + UserIdToRole:Map + u(Quorum:Int) + + + ActionLastIndex:Usize + + + ActionId |-> AddProposer(UserAddress:Address) #as Action:Action + ActionData:Map + + ActionSigners:Map + + + + + .Map + Stack:Stack + + + CallerAddress:Address + + + PerformedActions:List + + + + => + + evaluate(void) ~> K + + + + u(NumUsers +Int 1) + u(NumUsers +Int 1) |-> UserAddress UserIdToAddress + UserAddress |-> u(NumUsers +Int 1) AddressToUserId + + + u(NumBoardMembers) + u(NumProposers +Int 1) + u(NumUsers +Int 1) |-> Proposer UserIdToRole + u(Quorum) + + + ActionLastIndex + + ActionData + ActionSigners[ActionId <- undef] + + + + + ?_Variables:Map + Stack + + + CallerAddress + + + ListItem(Action) PerformedActions + + + + requires true + andBool isKResult(Action) + + andBool NumUsers >=Int 0 + // TODO: Perhaps replace with unusedIdsInMapValues(AddressToUserId) + + // someting to map values to keys. + andBool unusedIdsInMapKeys(NumUsers +Int 1, keysMap(UserIdToAddress), expand(expanded)) + andBool unusedIdsInMapKeys(NumUsers +Int 1, keysMap(UserIdToRole), expand(expanded)) + andBool Quorum <=Int NumBoardMembers + + andBool notBool UserAddress in_keys(AddressToUserId) + ensures true + //@ proof + //@ trusted + // [trusted] + //@ end + +endmodule diff --git a/multisig/protocol-correctness/proof/functions/proof-perform-action-id-add-proposer-None.k b/multisig/protocol-correctness/proof/functions/proof-perform-action-id-add-proposer-None.k new file mode 100644 index 000000000..f675407e1 --- /dev/null +++ b/multisig/protocol-correctness/proof/functions/proof-perform-action-id-add-proposer-None.k @@ -0,0 +1,100 @@ +//@ proof +require "trusted-perform-action-add-proposer-none.k" //@ Bazel remove + +module PROOF-PERFORM-ACTION-ID-ADD-PROPOSER-NONE + imports TRUSTED-PERFORM-ACTION-ADD-PROPOSER-NONE +//@ trusted +// module TRUSTED-PERFORM-ACTION-ID-ADD-PROPOSER-NONE +//@ end + + imports INVARIANT-HELPERS + imports PSEUDOCODE + + claim + + call(performActionFromId(ActionId:Usize)) ~> K:K + + + + NumUsers:Usize + UserIdToAddress:Map + (UserAddress |-> UserId:Usize _AddressToUserId:Map) #as AddressToUserId:Map + + + u(NumBoardMembers:Int) + u(NumProposers:Int) + UserIdToRole:Map + u(Quorum:Int) + + + ActionLastIndex:Usize + + + ActionId |-> AddProposer(UserAddress:Address) #as Action:Action + ActionData:Map + + ActionSigners:Map + + + + + .Map + Stack:Stack + + + CallerAddress:Address + + + PerformedActions:List + + + + => + + evaluate(void) ~> K + + + + NumUsers + UserIdToAddress + AddressToUserId + + + u(NumBoardMembers) + u(NumProposers +Int 1) + UserId |-> Proposer UserIdToRole + u(Quorum) + + + ActionLastIndex + + ActionData + ActionSigners[ActionId <- undef] + + + + + ?_Variables:Map + Stack + + + CallerAddress + + + ListItem(Action) PerformedActions + + + + requires true + andBool isKResult(Action) + andBool addressToUserIdInvariant(AddressToUserId) + andBool Quorum <=Int NumBoardMembers + + andBool notBool UserId in_keys(UserIdToRole) + ensures true + //@ proof + //@ trusted + // [trusted] + //@ end + +endmodule diff --git a/multisig/protocol-correctness/proof/functions/proof-perform-action-id-add-proposer-Proposer.k b/multisig/protocol-correctness/proof/functions/proof-perform-action-id-add-proposer-Proposer.k new file mode 100644 index 000000000..d801676b8 --- /dev/null +++ b/multisig/protocol-correctness/proof/functions/proof-perform-action-id-add-proposer-Proposer.k @@ -0,0 +1,98 @@ +//@ proof +require "trusted-perform-action-add-proposer-proposer.k" //@ Bazel remove + +module PROOF-PERFORM-ACTION-ID-ADD-PROPOSER-PROPOSER + imports TRUSTED-PERFORM-ACTION-ADD-PROPOSER-PROPOSER +//@ trusted +// module TRUSTED-PERFORM-ACTION-ID-ADD-PROPOSER-PROPOSER +//@ end + + imports INVARIANT-HELPERS + imports PSEUDOCODE + + claim + + call(performActionFromId(ActionId:Usize)) ~> K:K + + + + NumUsers:Usize + UserIdToAddress:Map + (UserAddress |-> UserId:Usize _AddressToUserId:Map) #as AddressToUserId:Map + + + u(NumBoardMembers:Int) + NumProposers:Usize + (UserId |-> Proposer _UserIdToRole:Map) #as UserIdToRole:Map + u(Quorum:Int) + + + ActionLastIndex:Usize + + + ActionId |-> AddProposer(UserAddress:Address) #as Action:Action + ActionData:Map + + ActionSigners:Map + + + + + .Map + Stack:Stack + + + CallerAddress:Address + + + PerformedActions:List + + + + => + + evaluate(void) ~> K + + + + NumUsers + UserIdToAddress + AddressToUserId + + + u(NumBoardMembers) + NumProposers + UserIdToRole + u(Quorum) + + + ActionLastIndex + + ActionData + ActionSigners[ActionId <- undef] + + + + + ?_Variables:Map + Stack + + + CallerAddress + + + ListItem(Action) PerformedActions + + + + requires true + andBool isKResult(Action) + andBool addressToUserIdInvariant(AddressToUserId) + andBool Quorum <=Int NumBoardMembers + ensures true + //@ proof + //@ trusted + // [trusted] + //@ end + +endmodule diff --git a/multisig/protocol-correctness/proof/functions/proof-perform-action-id-change-quorum-no-quorum.k b/multisig/protocol-correctness/proof/functions/proof-perform-action-id-change-quorum-no-quorum.k new file mode 100644 index 000000000..06387b767 --- /dev/null +++ b/multisig/protocol-correctness/proof/functions/proof-perform-action-id-change-quorum-no-quorum.k @@ -0,0 +1,96 @@ +//@ proof +require "trusted-perform-action-change-quorum-no-quorum.k" //@ Bazel remove + +module PROOF-PERFORM-ACTION-ID-CHANGE-QUORUM-NO-QUORUM + imports TRUSTED-PERFORM-ACTION-CHANGE-QUORUM-NO-QUORUM +//@ trusted +// module TRUSTED-PERFORM-ACTION-ID-CHANGE-QUORUM-NO-QUORUM +//@ end + + imports PSEUDOCODE + + claim + + call(performActionFromId(ActionId:Usize)) ~> K:K + + + + NumUsers:Usize + UserIdToAddress:Map + AddressToUserId:Map + + + u(NumBoardMembers:Int) + NumProposers:Usize + UserIdToRole:Map + OldQuorum:Usize + + + ActionLastIndex:Usize + + + ActionId |-> ChangeQuorum(u(NewQuorum:Int)) #as Action:Action + ActionData:Map + + ActionSigners:Map + + + + + .Map + Stack:Stack + + + CallerAddress:Address + + + PerformedActions:List + + + + => + + error ~> K + + + + NumUsers + UserIdToAddress + AddressToUserId + + + u(NumBoardMembers) + NumProposers + UserIdToRole + OldQuorum + + + ActionLastIndex + + ActionData + ActionSigners[ActionId <- undef] + + + + + ?_Variables:Map + Stack + + + CallerAddress + + + PerformedActions + + + + requires true + andBool isKResult(Action) + andBool NewQuorum >Int NumBoardMembers + ensures true + //@ proof + //@ trusted + // [trusted] + //@ end + +endmodule diff --git a/multisig/protocol-correctness/proof/functions/proof-perform-action-id-change-quorum.k b/multisig/protocol-correctness/proof/functions/proof-perform-action-id-change-quorum.k new file mode 100644 index 000000000..00a2ebb57 --- /dev/null +++ b/multisig/protocol-correctness/proof/functions/proof-perform-action-id-change-quorum.k @@ -0,0 +1,96 @@ +//@ proof +require "trusted-perform-action-change-quorum.k" //@ Bazel remove + +module PROOF-PERFORM-ACTION-ID-CHANGE-QUORUM + imports TRUSTED-PERFORM-ACTION-CHANGE-QUORUM +//@ trusted +// module TRUSTED-PERFORM-ACTION-ID-CHANGE-QUORUM +//@ end + + imports PSEUDOCODE + + claim + + call(performActionFromId(ActionId:Usize)) ~> K:K + + + + NumUsers:Usize + UserIdToAddress:Map + AddressToUserId:Map + + + u(NumBoardMembers:Int) + NumProposers:Usize + UserIdToRole:Map + _OldQuorum:Usize + + + ActionLastIndex:Usize + + + ActionId |-> ChangeQuorum(u(NewQuorum:Int)) #as Action:Action + ActionData:Map + + ActionSigners:Map + + + + + .Map + Stack:Stack + + + CallerAddress:Address + + + PerformedActions:List + + + + => + + evaluate(void) ~> K + + + + NumUsers + UserIdToAddress + AddressToUserId + + + u(NumBoardMembers) + NumProposers + UserIdToRole + u(NewQuorum) + + + ActionLastIndex + + ActionData + ActionSigners[ActionId <- undef] + + + + + ?_Variables:Map + Stack + + + CallerAddress + + + ListItem(Action) PerformedActions + + + + requires true + andBool isKResult(Action) + andBool NewQuorum <=Int NumBoardMembers + ensures true + //@ proof + //@ trusted + // [trusted] + //@ end + +endmodule diff --git a/multisig/protocol-correctness/proof/functions/proof-perform-action-id-nothing.k b/multisig/protocol-correctness/proof/functions/proof-perform-action-id-nothing.k new file mode 100644 index 000000000..e7abbd524 --- /dev/null +++ b/multisig/protocol-correctness/proof/functions/proof-perform-action-id-nothing.k @@ -0,0 +1,93 @@ +//@ proof +require "trusted-perform-action-sc-call.k" //@ Bazel remove + +module PROOF-PERFORM-ACTION-ID-NOTHING + imports TRUSTED-PERFORM-ACTION-NOTHING +//@ trusted +// module TRUSTED-PERFORM-ACTION-ID-NOTHING +//@ end + + imports PSEUDOCODE + + claim + + call(performActionFromId(ActionId:Usize)) ~> K:K + + + + + NumUsers:Usize + UserIdToAddress:Map + AddressToUserId:Map + + + NumBoardMembers:Usize + NumProposers:Usize + UserIdToRole:Map + Quorum:Usize + + + ActionLastIndex:Usize + + ActionData:Map + ActionSigners:Map + + + + + .Map + Stack:Stack + + + CallerAddress:Address + + + PerformedActions:List + + + + => + + evaluate(void) ~> K + + + + NumUsers + UserIdToAddress + AddressToUserId + + + NumBoardMembers + NumProposers + UserIdToRole + Quorum + + + ActionLastIndex + + ActionData + ActionSigners[ActionId <- undef] + + + + + ?_Variables + Stack + + + CallerAddress + + + ListItem(Nothing) PerformedActions + + + + requires true + andBool notBool ActionId in_keys(ActionData) + ensures true + //@ proof + //@ trusted + // [trusted] + //@ end + +endmodule \ No newline at end of file diff --git a/multisig/protocol-correctness/proof/functions/proof-perform-action-id-remove-user-BoardMember-too-few.k b/multisig/protocol-correctness/proof/functions/proof-perform-action-id-remove-user-BoardMember-too-few.k new file mode 100644 index 000000000..e298275da --- /dev/null +++ b/multisig/protocol-correctness/proof/functions/proof-perform-action-id-remove-user-BoardMember-too-few.k @@ -0,0 +1,102 @@ +//@ proof +require "trusted-perform-action-remove-user-boardmember-too-few.k" //@ Bazel remove + +module PROOF-PERFORM-ACTION-ID-REMOVE-USER-BOARDMEMBER-TOO-FEW + imports TRUSTED-PERFORM-ACTION-REMOVE-USER-BOARDMEMBER-TOO-FEW +//@ trusted +// module TRUSTED-PERFORM-ACTION-ID-REMOVE-USER-BOARDMEMBER-TOO-FEW +//@ end + + imports INVARIANT-HELPERS + imports PSEUDOCODE + + claim + + call(performActionFromId(ActionId:Usize)) ~> K:K + + + + u(NumUsers:Int) + UserIdToAddress:Map + (UserAddress |-> u(UserId:Int) _AddressToUserId:Map) #as AddressToUserId:Map + + + u(NumBoardMembers:Int) + u(NumProposers:Int) + (u(UserId:Int) |-> BoardMember _UserIdToRole:Map) #as UserIdToRole:Map + u(Quorum:Int) + + + ActionLastIndex:Usize + + + ActionId |-> RemoveUser(UserAddress:Address) #as Action:Action + ActionData:Map + + ActionSigners:Map + + + + + .Map + Stack:Stack + + + CallerAddress:Address + + + PerformedActions:List + + + + => + + error ~> K + + + + u(NumUsers) + UserIdToAddress + AddressToUserId + + + u(NumBoardMembers) + u(NumProposers) + UserIdToRole + u(Quorum) + + + ActionLastIndex + + ActionData + ActionSigners[ActionId <- undef] + + + + + ?_Variables:Map + Stack + + + CallerAddress + + + PerformedActions + + + + requires true + andBool isKResult(Action) + andBool addressToUserIdInvariant(AddressToUserId) + + andBool (false + orBool NumBoardMembers +Int NumProposers ==Int 1 + orBool Quorum ==Int NumBoardMembers + ) + ensures true + //@ proof + //@ trusted + // [trusted] + //@ end + +endmodule diff --git a/multisig/protocol-correctness/proof/functions/proof-perform-action-id-remove-user-BoardMember.k b/multisig/protocol-correctness/proof/functions/proof-perform-action-id-remove-user-BoardMember.k new file mode 100644 index 000000000..72332bbe7 --- /dev/null +++ b/multisig/protocol-correctness/proof/functions/proof-perform-action-id-remove-user-BoardMember.k @@ -0,0 +1,100 @@ +//@ proof +require "trusted-perform-action-remove-user-boardmember.k" //@ Bazel remove + +module PROOF-PERFORM-ACTION-ID-REMOVE-USER-BOARDMEMBER + imports TRUSTED-PERFORM-ACTION-REMOVE-USER-BOARDMEMBER +//@ trusted +// module TRUSTED-PERFORM-ACTION-ID-REMOVE-USER-BOARDMEMBER +//@ end + + imports INVARIANT-HELPERS + imports PSEUDOCODE + + claim + + call(performActionFromId(ActionId:Usize)) ~> K:K + + + + u(NumUsers:Int) + UserIdToAddress:Map + (UserAddress |-> u(UserId:Int) _AddressToUserId:Map) #as AddressToUserId:Map + + + u(NumBoardMembers:Int) + u(NumProposers:Int) + u(UserId:Int) |-> BoardMember UserIdToRole:Map + u(Quorum:Int) + + + ActionLastIndex:Usize + + + ActionId |-> RemoveUser(UserAddress:Address) #as Action:Action + ActionData:Map + + ActionSigners:Map + + + + + .Map + Stack:Stack + + + CallerAddress:Address + + + PerformedActions:List + + + + => + + evaluate(void) ~> K + + + + u(NumUsers) + UserIdToAddress + AddressToUserId + + + u(NumBoardMembers -Int 1) + u(NumProposers) + UserIdToRole + u(Quorum) + + + ActionLastIndex + + ActionData + ActionSigners[ActionId <- undef] + + + + + ?_Variables:Map + Stack + + + CallerAddress + + + ListItem(Action) PerformedActions + + + + requires true + andBool isKResult(Action) + andBool addressToUserIdInvariant(AddressToUserId) + + andBool NumBoardMembers +Int NumProposers -Int 1 >Int 0 + andBool Quorum <=Int NumBoardMembers -Int 1 + ensures true + //@ proof + //@ trusted + // [trusted] + //@ end + +endmodule diff --git a/multisig/protocol-correctness/proof/functions/proof-perform-action-id-remove-user-New.k b/multisig/protocol-correctness/proof/functions/proof-perform-action-id-remove-user-New.k new file mode 100644 index 000000000..556160c59 --- /dev/null +++ b/multisig/protocol-correctness/proof/functions/proof-perform-action-id-remove-user-New.k @@ -0,0 +1,105 @@ +//@ proof +require "trusted-perform-action-remove-user-new.k" //@ Bazel remove + +module PROOF-PERFORM-ACTION-ID-REMOVE-USER-NEW + imports TRUSTED-PERFORM-ACTION-REMOVE-USER-NEW +//@ trusted +// module TRUSTED-PERFORM-ACTION-ID-REMOVE-USER-NEW +//@ end + + imports EXECUTION-PROOF-HELPERS + imports PSEUDOCODE + + claim + + call(performActionFromId(ActionId:Usize)) ~> K:K + + + + u(NumUsers:Int) + UserIdToAddress:Map + AddressToUserId:Map + + + u(NumBoardMembers:Int) + u(NumProposers:Int) + UserIdToRole:Map + u(Quorum:Int) + + + ActionLastIndex:Usize + + + ActionId |-> RemoveUser(UserAddress:Address) #as Action:Action + ActionData:Map + + ActionSigners:Map + + + + + .Map + Stack:Stack + + + CallerAddress:Address + + + PerformedActions:List + + + + => + + evaluate(void) ~> K + + + + u(NumUsers +Int 1) + u(NumUsers +Int 1) |-> UserAddress UserIdToAddress + UserAddress |-> u(NumUsers +Int 1) AddressToUserId + + + u(NumBoardMembers) + u(NumProposers) + UserIdToRole + u(Quorum) + + + ActionLastIndex + + ActionData + ActionSigners[ActionId <- undef] + + + + + ?_Variables:Map + Stack + + + CallerAddress + + + ListItem(Action) PerformedActions + + + + requires true + andBool isKResult(Action) + andBool NumUsers >=Int 0 + // TODO: Perhaps replace with unusedIdsInMapValues(AddressToUserId) + + // something to map values to keys. + andBool unusedIdsInMapKeys(NumUsers +Int 1, keysMap(UserIdToAddress), expand(expanded)) + andBool unusedIdsInMapKeys(NumUsers +Int 1, keysMap(UserIdToRole), expand(expanded)) + andBool NumBoardMembers +Int NumProposers >Int 0 + andBool Quorum <=Int NumBoardMembers + + andBool notBool (UserAddress in_keys(AddressToUserId)) + ensures true + //@ proof + //@ trusted + // [trusted] + //@ end + +endmodule diff --git a/multisig/protocol-correctness/proof/functions/proof-perform-action-id-remove-user-None.k b/multisig/protocol-correctness/proof/functions/proof-perform-action-id-remove-user-None.k new file mode 100644 index 000000000..15049022c --- /dev/null +++ b/multisig/protocol-correctness/proof/functions/proof-perform-action-id-remove-user-None.k @@ -0,0 +1,101 @@ +//@ proof +require "trusted-perform-action-remove-user-none.k" //@ Bazel remove + +module PROOF-PERFORM-ACTION-ID-REMOVE-USER-NONE + imports TRUSTED-PERFORM-ACTION-REMOVE-USER-NONE +//@ trusted +// module TRUSTED-PERFORM-ACTION-ID-REMOVE-USER-NONE +//@ end + + imports INVARIANT-HELPERS + imports PSEUDOCODE + + claim + + call(performActionFromId(ActionId:Usize)) ~> K:K + + + + u(NumUsers:Int) + UserIdToAddress:Map + (UserAddress |-> u(UserId:Int) _AddressToUserId:Map) #as AddressToUserId:Map + + + u(NumBoardMembers:Int) + u(NumProposers:Int) + UserIdToRole:Map + u(Quorum:Int) + + + ActionLastIndex:Usize + + + ActionId |-> RemoveUser(UserAddress:Address) #as Action:Action + ActionData:Map + + ActionSigners:Map + + + + + .Map + Stack:Stack + + + CallerAddress:Address + + + PerformedActions:List + + + + => + + evaluate(void) ~> K + + + + u(NumUsers) + UserIdToAddress + AddressToUserId + + + u(NumBoardMembers) + u(NumProposers) + UserIdToRole + u(Quorum) + + + ActionLastIndex + + ActionData + ActionSigners[ActionId <- undef] + + + + + ?_Variables:Map + Stack + + + CallerAddress + + + ListItem(Action) PerformedActions + + + + requires true + andBool isKResult(Action) + andBool addressToUserIdInvariant(AddressToUserId) + andBool NumBoardMembers +Int NumProposers >Int 0 + andBool Quorum <=Int NumBoardMembers + + andBool notBool (u(UserId) in_keys(UserIdToRole)) + ensures true + //@ proof + //@ trusted + // [trusted] + //@ end + +endmodule diff --git a/multisig/protocol-correctness/proof/functions/proof-perform-action-id-remove-user-Proposer-nobody-left.k b/multisig/protocol-correctness/proof/functions/proof-perform-action-id-remove-user-Proposer-nobody-left.k new file mode 100644 index 000000000..116774624 --- /dev/null +++ b/multisig/protocol-correctness/proof/functions/proof-perform-action-id-remove-user-Proposer-nobody-left.k @@ -0,0 +1,100 @@ +//@ proof +require "trusted-perform-action-remove-user-Proposer-nobody-left.k" //@ Bazel remove + +module PROOF-PERFORM-ACTION-ID-REMOVE-USER-PROPOSER-NOBODY-LEFT + imports TRUSTED-PERFORM-ACTION-REMOVE-USER-PROPOSER-NOBODY-LEFT +//@ trusted +// module TRUSTED-PERFORM-ACTION-ID-REMOVE-USER-PROPOSER-NOBODY-LEFT +//@ end + + imports INVARIANT-HELPERS + imports PSEUDOCODE + + claim + + call(performActionFromId(ActionId:Usize)) ~> K:K + + + + u(NumUsers:Int) + UserIdToAddress:Map + (UserAddress |-> u(UserId:Int) _AddressToUserId:Map) #as AddressToUserId:Map + + + u(NumBoardMembers:Int) + u(NumProposers:Int) + (u(UserId:Int) |-> Proposer _UserIdToRole:Map) #as UserIdToRole:Map + u(Quorum:Int) + + + ActionLastIndex:Usize + + + ActionId |-> RemoveUser(UserAddress:Address) #as Action:Action + ActionData:Map + + ActionSigners:Map + + + + + .Map + Stack:Stack + + + CallerAddress:Address + + + PerformedActions:List + + + + => + + error ~> K + + + + u(NumUsers) + UserIdToAddress + AddressToUserId + + + u(NumBoardMembers) + u(NumProposers) + UserIdToRole + u(Quorum) + + + ActionLastIndex + + ActionData + ActionSigners[ActionId <- undef] + + + + + ?_Variables:Map + Stack + + + CallerAddress + + + PerformedActions + + + + requires true + andBool isKResult(Action) + andBool addressToUserIdInvariant(AddressToUserId) + andBool Quorum <=Int NumBoardMembers + + andBool NumBoardMembers +Int NumProposers ==Int 1 + ensures true + //@ proof + //@ trusted + // [trusted] + //@ end + +endmodule diff --git a/multisig/protocol-correctness/proof/functions/proof-perform-action-id-remove-user-Proposer.k b/multisig/protocol-correctness/proof/functions/proof-perform-action-id-remove-user-Proposer.k new file mode 100644 index 000000000..54135915e --- /dev/null +++ b/multisig/protocol-correctness/proof/functions/proof-perform-action-id-remove-user-Proposer.k @@ -0,0 +1,100 @@ +//@ proof +require "trusted-perform-action-remove-user-Proposer.k" //@ Bazel remove + +module PROOF-PERFORM-ACTION-ID-REMOVE-USER-PROPOSER + imports TRUSTED-PERFORM-ACTION-REMOVE-USER-PROPOSER +//@ trusted +// module TRUSTED-PERFORM-ACTION-ID-REMOVE-USER-PROPOSER +//@ end + + imports INVARIANT-HELPERS + imports PSEUDOCODE + + claim + + call(performActionFromId(ActionId:Usize)) ~> K:K + + + + u(NumUsers:Int) + UserIdToAddress:Map + (UserAddress |-> u(UserId:Int) _AddressToUserId:Map) #as AddressToUserId:Map + + + u(NumBoardMembers:Int) + u(NumProposers:Int) + u(UserId:Int) |-> Proposer UserIdToRole:Map + u(Quorum:Int) + + + ActionLastIndex:Usize + + + ActionId |-> RemoveUser(UserAddress:Address) #as Action:Action + ActionData:Map + + ActionSigners:Map + + + + + .Map + Stack:Stack + + + CallerAddress:Address + + + PerformedActions:List + + + + => + + evaluate(void) ~> K + + + + u(NumUsers) + UserIdToAddress + AddressToUserId + + + u(NumBoardMembers) + u(NumProposers -Int 1) + UserIdToRole + u(Quorum) + + + ActionLastIndex + + ActionData + ActionSigners[ActionId <- undef] + + + + + ?_Variables:Map + Stack + + + CallerAddress + + + ListItem(Action) PerformedActions + + + + requires true + andBool isKResult(Action) + andBool addressToUserIdInvariant(AddressToUserId) + andBool Quorum <=Int NumBoardMembers + + andBool NumBoardMembers +Int NumProposers -Int 1 >Int 0 + ensures true + //@ proof + //@ trusted + // [trusted] + //@ end + +endmodule diff --git a/multisig/protocol-correctness/proof/functions/proof-perform-action-id-sc-call.k b/multisig/protocol-correctness/proof/functions/proof-perform-action-id-sc-call.k new file mode 100644 index 000000000..9d3a51e6f --- /dev/null +++ b/multisig/protocol-correctness/proof/functions/proof-perform-action-id-sc-call.k @@ -0,0 +1,100 @@ +//@ proof +require "trusted-perform-action-sc-call.k" //@ Bazel remove + +module PROOF-PERFORM-ACTION-ID-SC-CALL + imports TRUSTED-PERFORM-ACTION-SC-CALL +//@ trusted +// module TRUSTED-PERFORM-ACTION-ID-SC-CALL +//@ end + + imports PSEUDOCODE + + claim + + call(performActionFromId(ActionId:Usize)) ~> K:K + + + + + NumUsers:Usize + UserIdToAddress:Map + AddressToUserId:Map + + + NumBoardMembers:Usize + NumProposers:Usize + UserIdToRole:Map + Quorum:Usize + + + ActionLastIndex:Usize + + + ActionId |-> SCCall( + _To:Address, + _Amount:BigUint, + _Function:BoxedBytes, + _Arguments:ExpressionList) #as Action:Action + ActionData:Map + + ActionSigners:Map + + + + + .Map + Stack:Stack + + + CallerAddress:Address + + + PerformedActions:List + + + + => + + evaluate(void) ~> K + + + + NumUsers + UserIdToAddress + AddressToUserId + + + NumBoardMembers + NumProposers + UserIdToRole + Quorum + + + ActionLastIndex + + ActionData + ActionSigners[ActionId <- undef] + + + + + ?_Variables + Stack + + + CallerAddress + + + ListItem(Action) PerformedActions + + + + requires true + andBool isKResult(Action) + ensures true + //@ proof + //@ trusted + // [trusted] + //@ end + +endmodule \ No newline at end of file diff --git a/multisig/protocol-correctness/proof/functions/proof-perform-action-id-sc-deploy.k b/multisig/protocol-correctness/proof/functions/proof-perform-action-id-sc-deploy.k new file mode 100644 index 000000000..0434b04df --- /dev/null +++ b/multisig/protocol-correctness/proof/functions/proof-perform-action-id-sc-deploy.k @@ -0,0 +1,99 @@ +//@ proof +require "trusted-perform-action-sc-deploy.k" //@ Bazel remove + +module PROOF-PERFORM-ACTION-ID-SC-DEPLOY + imports TRUSTED-PERFORM-ACTION-SC-DEPLOY +//@ trusted +// module TRUSTED-PERFORM-ACTION-ID-SC-DEPLOY +//@ end + + imports PSEUDOCODE + + claim + + call(performActionFromId(ActionId:Usize)) ~> K:K + + + + NumUsers:Usize + UserIdToAddress:Map + AddressToUserId:Map + + + NumBoardMembers:Usize + NumProposers:Usize + UserIdToRole:Map + Quorum:Usize + + + ActionLastIndex:Usize + + + ActionId |-> SCDeploy( + _Amount:BigUint, + _Code:BoxedBytes, + _CodeMetadata:CodeMetadata, + _Arguments:ExpressionList) #as Action:Action + ActionData:Map + + ActionSigners:Map + + + + + .Map + Stack:Stack + + + CallerAddress:Address + + + PerformedActions:List + + + + => + + evaluate(void) ~> K + + + + NumUsers + UserIdToAddress + AddressToUserId + + + NumBoardMembers + NumProposers + UserIdToRole + Quorum + + + ActionLastIndex + + ActionData + ActionSigners[ActionId <- undef] + + + + + ?_Variables:Map + Stack + + + CallerAddress + + + ListItem(Action) PerformedActions + + + + requires true + andBool isKResult(Action) + ensures true + //@ proof + //@ trusted + // [trusted] + //@ end + +endmodule \ No newline at end of file diff --git a/multisig/protocol-correctness/proof/functions/proof-perform-action-id-send-egld.k b/multisig/protocol-correctness/proof/functions/proof-perform-action-id-send-egld.k new file mode 100644 index 000000000..5f452cdfb --- /dev/null +++ b/multisig/protocol-correctness/proof/functions/proof-perform-action-id-send-egld.k @@ -0,0 +1,98 @@ +//@ proof +require "trusted-perform-action-send-egld.k" //@ Bazel remove + +module PROOF-PERFORM-ACTION-ID-SEND-EGLD + imports TRUSTED-PERFORM-ACTION-SEND-EGLD +//@ trusted +// module TRUSTED-PERFORM-ACTION-ID-SEND-EGLD +//@ end + + imports PSEUDOCODE + + claim + + call(performActionFromId(ActionId:Usize)) ~> K:K + + + + NumUsers:Usize + UserIdToAddress:Map + AddressToUserId:Map + + + NumBoardMembers:Usize + NumProposers:Usize + UserIdToRole:Map + Quorum:Usize + + + ActionLastIndex:Usize + + + ActionId |-> SendEgld( + _To:Address, + _Amount:BigUint, + _Data:BoxedBytes) #as Action:Action + ActionData:Map + + ActionSigners:Map + + + + + .Map + Stack:Stack + + + CallerAddress:Address + + + PerformedActions:List + + + + => + + evaluate(void) ~> K + + + + NumUsers + UserIdToAddress + AddressToUserId + + + NumBoardMembers + NumProposers + UserIdToRole + Quorum + + + ActionLastIndex + + ActionData + ActionSigners[ActionId <- undef] + + + + + ?_Variables:Map + Stack + + + CallerAddress + + + ListItem(Action) PerformedActions + + + + requires true + andBool isKResult(Action) + ensures true + //@ proof + //@ trusted + // [trusted] + //@ end + +endmodule \ No newline at end of file diff --git a/multisig/protocol-correctness/proof/functions/proof-perform-action-nothing.k b/multisig/protocol-correctness/proof/functions/proof-perform-action-nothing.k new file mode 100644 index 000000000..8034d5cf0 --- /dev/null +++ b/multisig/protocol-correctness/proof/functions/proof-perform-action-nothing.k @@ -0,0 +1,76 @@ +//@ proof +module PROOF-PERFORM-ACTION-NOTHING +//@ trusted +// module TRUSTED-PERFORM-ACTION-NOTHING +//@ end + + imports PSEUDOCODE + + claim + + call(performAction(Nothing #as Action:Action)) ~> K:K + + + + NumUsers:Usize + UserIdToAddress:Map + AddressToUserId:Map + + + NumBoardMembers:Usize + NumProposers:Usize + UserIdToRole:Map + Quorum:Usize + + ActionState:ActionStateCell + + + .Map + Stack:Stack + + + CallerAddress:Address + + + PerformedActions:List + + + + => + + evaluate(void) ~> K + + + + NumUsers + UserIdToAddress + AddressToUserId + + + NumBoardMembers + NumProposers + UserIdToRole + Quorum + + ActionState + + + ?_Variables:Map + Stack + + + CallerAddress + + + ListItem(Action) PerformedActions + + + + requires true + ensures true + //@ proof + //@ trusted + // [trusted] + //@ end + +endmodule \ No newline at end of file diff --git a/multisig/protocol-correctness/proof/functions/proof-perform-action-remove-user-BoardMember-too-few.k b/multisig/protocol-correctness/proof/functions/proof-perform-action-remove-user-BoardMember-too-few.k new file mode 100644 index 000000000..0ae0fa4a0 --- /dev/null +++ b/multisig/protocol-correctness/proof/functions/proof-perform-action-remove-user-BoardMember-too-few.k @@ -0,0 +1,90 @@ +//@ proof +require "trusted-change-user-role-BoardMember.k" //@ Bazel remove + +module PROOF-PERFORM-ACTION-REMOVE-USER-BOARDMEMBER-TOO-FEW + imports TRUSTED-CHANGE-USER-ROLE-BOARDMEMBER +//@ trusted +// module TRUSTED-PERFORM-ACTION-REMOVE-USER-BOARDMEMBER-TOO-FEW +//@ end + + imports INVARIANT-HELPERS + imports PSEUDOCODE + + claim + + call(performAction( + RemoveUser(UserAddress:Address) #as Action:Action + )) ~> K:K + + + + + u(NumUsers:Int) + UserIdToAddress:Map + (UserAddress |-> u(UserId:Int) _AddressToUserId:Map) #as AddressToUserId:Map + + + u(NumBoardMembers:Int) + u(NumProposers:Int) + u(UserId:Int) |-> BoardMember UserIdToRole:Map + u(Quorum:Int) + + ActionState:ActionStateCell + + + .Map + Stack:Stack + + + CallerAddress:Address + + + PerformedActions:List + + + + => + + error ~> K + + + + u(NumUsers) + UserIdToAddress + AddressToUserId + + + u(NumBoardMembers -Int 1) + u(NumProposers) + UserIdToRole + u(Quorum) + + ActionState + + + ?_Variables:Map + Stack + + + CallerAddress + + + ListItem(Action) PerformedActions + + + + requires true + andBool isKResult(Action) + andBool addressToUserIdInvariant(AddressToUserId) + + andBool (false + orBool NumBoardMembers +Int NumProposers ==Int 1 + orBool Quorum ==Int NumBoardMembers + ) + ensures true + //@ proof + //@ trusted + // [trusted] + //@ end + +endmodule diff --git a/multisig/protocol-correctness/proof/functions/proof-perform-action-remove-user-BoardMember.k b/multisig/protocol-correctness/proof/functions/proof-perform-action-remove-user-BoardMember.k new file mode 100644 index 000000000..694a17d96 --- /dev/null +++ b/multisig/protocol-correctness/proof/functions/proof-perform-action-remove-user-BoardMember.k @@ -0,0 +1,88 @@ +//@ proof +require "trusted-change-user-role-BoardMember.k" //@ Bazel remove + +module PROOF-PERFORM-ACTION-REMOVE-USER-BOARDMEMBER + imports TRUSTED-CHANGE-USER-ROLE-BOARDMEMBER +//@ trusted +// module TRUSTED-PERFORM-ACTION-REMOVE-USER-BOARDMEMBER +//@ end + + imports INVARIANT-HELPERS + imports PSEUDOCODE + + claim + + call(performAction( + RemoveUser(UserAddress:Address) #as Action:Action + )) ~> K:K + + + + + u(NumUsers:Int) + UserIdToAddress:Map + (UserAddress |-> u(UserId:Int) _AddressToUserId:Map) #as AddressToUserId:Map + + + u(NumBoardMembers:Int) + u(NumProposers:Int) + u(UserId:Int) |-> BoardMember UserIdToRole:Map + u(Quorum:Int) + + ActionState:ActionStateCell + + + .Map + Stack:Stack + + + CallerAddress:Address + + + PerformedActions:List + + + + => + + evaluate(void) ~> K + + + + u(NumUsers) + UserIdToAddress + AddressToUserId + + + u(NumBoardMembers -Int 1) + u(NumProposers) + UserIdToRole + u(Quorum) + + ActionState + + + ?_Variables:Map + Stack + + + CallerAddress + + + ListItem(Action) PerformedActions + + + + requires true + andBool isKResult(Action) + andBool addressToUserIdInvariant(AddressToUserId) + + andBool NumBoardMembers +Int NumProposers -Int 1 >Int 0 + andBool Quorum <=Int NumBoardMembers -Int 1 + ensures true + //@ proof + //@ trusted + // [trusted] + //@ end + +endmodule diff --git a/multisig/protocol-correctness/proof/functions/proof-perform-action-remove-user-New.k b/multisig/protocol-correctness/proof/functions/proof-perform-action-remove-user-New.k new file mode 100644 index 000000000..990ff6a71 --- /dev/null +++ b/multisig/protocol-correctness/proof/functions/proof-perform-action-remove-user-New.k @@ -0,0 +1,93 @@ +//@ proof +require "trusted-change-user-role-New.k" //@ Bazel remove + +module PROOF-PERFORM-ACTION-REMOVE-USER-NEW + imports TRUSTED-CHANGE-USER-ROLE-NEW +//@ trusted +// module TRUSTED-PERFORM-ACTION-REMOVE-USER-NEW +//@ end + + imports EXECUTION-PROOF-HELPERS + imports PSEUDOCODE + + claim + + call(performAction( + RemoveUser(UserAddress:Address) #as Action:Action + )) ~> K:K + + + + + u(NumUsers:Int) + UserIdToAddress:Map + AddressToUserId:Map + + + u(NumBoardMembers:Int) + u(NumProposers:Int) + UserIdToRole:Map + u(Quorum:Int) + + ActionState:ActionStateCell + + + .Map + Stack:Stack + + + CallerAddress:Address + + + PerformedActions:List + + + + => + + evaluate(void) ~> K + + + + u(NumUsers +Int 1) + u(NumUsers +Int 1) |-> UserAddress UserIdToAddress + UserAddress |-> u(NumUsers +Int 1) AddressToUserId + + + u(NumBoardMembers) + u(NumProposers) + UserIdToRole + u(Quorum) + + ActionState + + + ?_Variables:Map + Stack + + + CallerAddress + + + ListItem(Action) PerformedActions + + + + requires true + andBool isKResult(Action) + andBool NumUsers >=Int 0 + // TODO: Perhaps replace with unusedIdsInMapValues(AddressToUserId) + + // something to map values to keys. + andBool unusedIdsInMapKeys(NumUsers +Int 1, keysMap(UserIdToAddress), expand(expanded)) + andBool unusedIdsInMapKeys(NumUsers +Int 1, keysMap(UserIdToRole), expand(expanded)) + andBool NumBoardMembers +Int NumProposers >Int 0 + andBool Quorum <=Int NumBoardMembers + + andBool notBool (UserAddress in_keys(AddressToUserId)) + ensures true + //@ proof + //@ trusted + // [trusted] + //@ end + +endmodule diff --git a/multisig/protocol-correctness/proof/functions/proof-perform-action-remove-user-None.k b/multisig/protocol-correctness/proof/functions/proof-perform-action-remove-user-None.k new file mode 100644 index 000000000..9986d8402 --- /dev/null +++ b/multisig/protocol-correctness/proof/functions/proof-perform-action-remove-user-None.k @@ -0,0 +1,89 @@ +//@ proof +require "trusted-change-user-role-None.k" //@ Bazel remove + +module PROOF-PERFORM-ACTION-REMOVE-USER-NONE + imports TRUSTED-CHANGE-USER-ROLE-NONE +//@ trusted +// module TRUSTED-PERFORM-ACTION-REMOVE-USER-NONE +//@ end + + imports INVARIANT-HELPERS + imports PSEUDOCODE + + claim + + call(performAction( + RemoveUser(UserAddress:Address) #as Action:Action + )) ~> K:K + + + + + u(NumUsers:Int) + UserIdToAddress:Map + (UserAddress |-> u(UserId:Int) _AddressToUserId:Map) #as AddressToUserId:Map + + + u(NumBoardMembers:Int) + u(NumProposers:Int) + UserIdToRole:Map + u(Quorum:Int) + + ActionState:ActionStateCell + + + .Map + Stack:Stack + + + CallerAddress:Address + + + PerformedActions:List + + + + => + + evaluate(void) ~> K + + + + u(NumUsers) + UserIdToAddress + AddressToUserId + + + u(NumBoardMembers) + u(NumProposers) + UserIdToRole + u(Quorum) + + ActionState + + + ?_Variables:Map + Stack + + + CallerAddress + + + ListItem(Action) PerformedActions + + + + requires true + andBool isKResult(Action) + andBool addressToUserIdInvariant(AddressToUserId) + andBool NumBoardMembers +Int NumProposers >Int 0 + andBool Quorum <=Int NumBoardMembers + + andBool notBool (u(UserId) in_keys(UserIdToRole)) + ensures true + //@ proof + //@ trusted + // [trusted] + //@ end + +endmodule diff --git a/multisig/protocol-correctness/proof/functions/proof-perform-action-remove-user-Proposer-nobody-left.k b/multisig/protocol-correctness/proof/functions/proof-perform-action-remove-user-Proposer-nobody-left.k new file mode 100644 index 000000000..54798d18d --- /dev/null +++ b/multisig/protocol-correctness/proof/functions/proof-perform-action-remove-user-Proposer-nobody-left.k @@ -0,0 +1,88 @@ +//@ proof +require "trusted-change-user-role-Proposer.k" //@ Bazel remove + +module PROOF-PERFORM-ACTION-REMOVE-USER-PROPOSER-NOBODY-LEFT + imports TRUSTED-CHANGE-USER-ROLE-PROPOSER +//@ trusted +// module TRUSTED-PERFORM-ACTION-REMOVE-USER-PROPOSER-NOBODY-LEFT +//@ end + + imports INVARIANT-HELPERS + imports PSEUDOCODE + + claim + + call(performAction( + RemoveUser(UserAddress:Address) #as Action:Action + )) ~> K:K + + + + + u(NumUsers:Int) + UserIdToAddress:Map + (UserAddress |-> u(UserId:Int) _AddressToUserId:Map) #as AddressToUserId:Map + + + u(NumBoardMembers:Int) + u(NumProposers:Int) + u(UserId:Int) |-> Proposer UserIdToRole:Map + u(Quorum:Int) + + ActionState:ActionStateCell + + + .Map + Stack:Stack + + + CallerAddress:Address + + + PerformedActions:List + + + + => + + error ~> K + + + + u(NumUsers) + UserIdToAddress + AddressToUserId + + + u(NumBoardMembers) + u(NumProposers -Int 1) + UserIdToRole + u(Quorum) + + ActionState + + + ?_Variables:Map + Stack + + + CallerAddress + + + ListItem(Action) PerformedActions + + + + requires true + andBool isKResult(Action) + andBool addressToUserIdInvariant(AddressToUserId) + andBool Quorum <=Int NumBoardMembers + + andBool NumBoardMembers +Int NumProposers ==Int 1 + ensures true + //@ proof + //@ trusted + // [trusted] + //@ end + +endmodule diff --git a/multisig/protocol-correctness/proof/functions/proof-perform-action-remove-user-Proposer.k b/multisig/protocol-correctness/proof/functions/proof-perform-action-remove-user-Proposer.k new file mode 100644 index 000000000..2122c2038 --- /dev/null +++ b/multisig/protocol-correctness/proof/functions/proof-perform-action-remove-user-Proposer.k @@ -0,0 +1,88 @@ +//@ proof +require "trusted-change-user-role-Proposer.k" //@ Bazel remove + +module PROOF-PERFORM-ACTION-REMOVE-USER-PROPOSER + imports TRUSTED-CHANGE-USER-ROLE-PROPOSER +//@ trusted +// module TRUSTED-PERFORM-ACTION-REMOVE-USER-PROPOSER +//@ end + + imports INVARIANT-HELPERS + imports PSEUDOCODE + + claim + + call(performAction( + RemoveUser(UserAddress:Address) #as Action:Action + )) ~> K:K + + + + + u(NumUsers:Int) + UserIdToAddress:Map + (UserAddress |-> u(UserId:Int) _AddressToUserId:Map) #as AddressToUserId:Map + + + u(NumBoardMembers:Int) + u(NumProposers:Int) + u(UserId:Int) |-> Proposer UserIdToRole:Map + u(Quorum:Int) + + ActionState:ActionStateCell + + + .Map + Stack:Stack + + + CallerAddress:Address + + + PerformedActions:List + + + + => + + evaluate(void) ~> K + + + + u(NumUsers) + UserIdToAddress + AddressToUserId + + + u(NumBoardMembers) + u(NumProposers -Int 1) + UserIdToRole + u(Quorum) + + ActionState + + + ?_Variables:Map + Stack + + + CallerAddress + + + ListItem(Action) PerformedActions + + + + requires true + andBool isKResult(Action) + andBool addressToUserIdInvariant(AddressToUserId) + andBool Quorum <=Int NumBoardMembers + + andBool NumBoardMembers +Int NumProposers -Int 1 >Int 0 + ensures true + //@ proof + //@ trusted + // [trusted] + //@ end + +endmodule diff --git a/multisig/protocol-correctness/proof/functions/proof-perform-action-sc-call.k b/multisig/protocol-correctness/proof/functions/proof-perform-action-sc-call.k new file mode 100644 index 000000000..1e8d2d025 --- /dev/null +++ b/multisig/protocol-correctness/proof/functions/proof-perform-action-sc-call.k @@ -0,0 +1,83 @@ +//@ proof +module PROOF-PERFORM-ACTION-SC-CALL +//@ trusted +// module TRUSTED-PERFORM-ACTION-SC-CALL +//@ end + + imports PSEUDOCODE + + claim + + call(performAction(SCCall( + _To:Address, + _Amount:BigUint, + _Function:BoxedBytes, + _Arguments:ExpressionList) #as Action:Action + )) ~> K:K + + + + + NumUsers:Usize + UserIdToAddress:Map + AddressToUserId:Map + + + NumBoardMembers:Usize + NumProposers:Usize + UserIdToRole:Map + Quorum:Usize + + ActionState:ActionStateCell + + + .Map + Stack:Stack + + + CallerAddress:Address + + + PerformedActions:List + + + + => + + evaluate(void) ~> K + + + + NumUsers + UserIdToAddress + AddressToUserId + + + NumBoardMembers + NumProposers + UserIdToRole + Quorum + + ActionState + + + ?_Variables:Map + Stack + + + CallerAddress + + + ListItem(Action) PerformedActions + + + + requires true + andBool isKResult(Action) + ensures true + //@ proof + //@ trusted + // [trusted] + //@ end + +endmodule \ No newline at end of file diff --git a/multisig/protocol-correctness/proof/functions/proof-perform-action-sc-deploy.k b/multisig/protocol-correctness/proof/functions/proof-perform-action-sc-deploy.k new file mode 100644 index 000000000..7d83935e6 --- /dev/null +++ b/multisig/protocol-correctness/proof/functions/proof-perform-action-sc-deploy.k @@ -0,0 +1,83 @@ +//@ proof +module PROOF-PERFORM-ACTION-SC-DEPLOY +//@ trusted +// module TRUSTED-PERFORM-ACTION-SC-DEPLOY +//@ end + + imports PSEUDOCODE + + claim + + call(performAction(SCDeploy( + _Amount:BigUint, + _Code:BoxedBytes, + _CodeMetadata:CodeMetadata, + _Arguments:ExpressionList) #as Action:Action + )) ~> K:K + + + + + NumUsers:Usize + UserIdToAddress:Map + AddressToUserId:Map + + + NumBoardMembers:Usize + NumProposers:Usize + UserIdToRole:Map + Quorum:Usize + + ActionState:ActionStateCell + + + .Map + Stack:Stack + + + CallerAddress:Address + + + PerformedActions:List + + + + => + + evaluate(void) ~> K + + + + NumUsers + UserIdToAddress + AddressToUserId + + + NumBoardMembers + NumProposers + UserIdToRole + Quorum + + ActionState + + + ?_Variables:Map + Stack + + + CallerAddress + + + ListItem(Action) PerformedActions + + + + requires true + andBool isKResult(Action) + ensures true + //@ proof + //@ trusted + // [trusted] + //@ end + +endmodule \ No newline at end of file diff --git a/multisig/protocol-correctness/proof/functions/proof-perform-action-send-egld.k b/multisig/protocol-correctness/proof/functions/proof-perform-action-send-egld.k new file mode 100644 index 000000000..aaa815d38 --- /dev/null +++ b/multisig/protocol-correctness/proof/functions/proof-perform-action-send-egld.k @@ -0,0 +1,82 @@ +//@ proof +module PROOF-PERFORM-ACTION-SEND-EGLD +//@ trusted +// module TRUSTED-PERFORM-ACTION-SEND-EGLD +//@ end + + imports PSEUDOCODE + + claim + + call(performAction(SendEgld( + _To:Address, + _Amount:BigUint, + _Data:BoxedBytes) #as Action:Action + )) ~> K:K + + + + + NumUsers:Usize + UserIdToAddress:Map + AddressToUserId:Map + + + NumBoardMembers:Usize + NumProposers:Usize + UserIdToRole:Map + Quorum:Usize + + ActionState:ActionStateCell + + + .Map + Stack:Stack + + + CallerAddress:Address + + + PerformedActions:List + + + + => + + evaluate(void) ~> K + + + + NumUsers + UserIdToAddress + AddressToUserId + + + NumBoardMembers + NumProposers + UserIdToRole + Quorum + + ActionState + + + ?_Variables:Map + Stack + + + CallerAddress + + + ListItem(Action) PerformedActions + + + + requires true + andBool isKResult(Action) + ensures true + //@ proof + //@ trusted + // [trusted] + //@ end + +endmodule \ No newline at end of file diff --git a/multisig/protocol-correctness/proof/functions/proof-propose-action-BoardMember.k b/multisig/protocol-correctness/proof/functions/proof-propose-action-BoardMember.k new file mode 100644 index 000000000..a0c426f35 --- /dev/null +++ b/multisig/protocol-correctness/proof/functions/proof-propose-action-BoardMember.k @@ -0,0 +1,72 @@ +//@ proof +module PROOF-PROPOSE-ACTION-BOARDMEMBER +//@ trusted +// module TRUSTED-PROPOSE-ACTION-BOARDMEMBER +//@ end + + imports EXECUTION-PROOF-HELPERS + imports FUNCTIONS-EXECUTE + + claim + call(proposeAction(Action:Action)) ~> K:K + + invariantStateFull( + NumUsers:Usize, + UserIdToAddress:Map, + AddressToUserId:Map, + NumBoardMembers:Usize, + NumProposers:Usize, + UserIdToRole:Map, + Quorum:Usize, + u(ActionLastIndex:Int), + ActionData:Map, + ActionSigners:Map, + CallerAddress:Address, + Stack:Stack, + .Map, + PerformedActions:List + ) + + => + + u(ActionLastIndex +Int 1) ~> K + invariantStateFull( + NumUsers, + UserIdToAddress, + AddressToUserId, + NumBoardMembers, + NumProposers, + UserIdToRole, + Quorum, + u(ActionLastIndex +Int 1), + u(ActionLastIndex +Int 1) |-> Action ActionData, + (u(ActionLastIndex +Int 1) |-> [{AddressToUserId[CallerAddress]}:>Usize, .]) ActionSigners, + CallerAddress, + Stack:Stack, + ?_Variables, + PerformedActions:List + ):StateCell + + requires true + andBool isKResult(Action) + andBool valueIsNotEmpty(Action, rAction) + + andBool valuesAreKResult(AddressToUserId) + andBool valuesAreOfType(AddressToUserId, rUsize) + andBool valuesAreNotEmpty(AddressToUserId, rUsize) + + andBool valuesAreOfType(UserIdToRole, rUserRole) + andBool valuesAreKResult(UserIdToRole) + + andBool unusedIdsInMapKeys(ActionLastIndex +Int 1, keysMap(ActionData), expand(expanded)) + andBool unusedIdsInMapKeys(ActionLastIndex +Int 1, keysMap(ActionSigners), expand(expanded)) + + andBool CallerAddress in_keys(AddressToUserId) + andBool AddressToUserId[CallerAddress] in_keys(UserIdToRole) + andBool UserIdToRole[AddressToUserId[CallerAddress]] ==K BoardMember + ensures true + //@ proof + //@ trusted + // [trusted] + //@ end +endmodule diff --git a/multisig/protocol-correctness/proof/functions/proof-propose-action-Proposer.k b/multisig/protocol-correctness/proof/functions/proof-propose-action-Proposer.k new file mode 100644 index 000000000..d20c7e554 --- /dev/null +++ b/multisig/protocol-correctness/proof/functions/proof-propose-action-Proposer.k @@ -0,0 +1,72 @@ +//@ proof +module PROOF-PROPOSE-ACTION-PROPOSER +//@ trusted +// module TRUSTED-PROPOSE-ACTION-PROPOSER +//@ end + + imports EXECUTION-PROOF-HELPERS + imports FUNCTIONS-EXECUTE + + claim + call(proposeAction(Action:Action)) ~> K:K + + invariantStateFull( + NumUsers:Usize, + UserIdToAddress:Map, + AddressToUserId:Map, + NumBoardMembers:Usize, + NumProposers:Usize, + UserIdToRole:Map, + Quorum:Usize, + u(ActionLastIndex:Int), + ActionData:Map, + ActionSigners:Map, + CallerAddress:Address, + Stack:Stack, + .Map, + PerformedActions:List + ) + + => + + u(ActionLastIndex +Int 1) ~> K + invariantStateFull( + NumUsers, + UserIdToAddress, + AddressToUserId, + NumBoardMembers, + NumProposers, + UserIdToRole, + Quorum, + u(ActionLastIndex +Int 1), + u(ActionLastIndex +Int 1) |-> Action ActionData, + ActionSigners, + CallerAddress, + Stack:Stack, + ?_Variables, + PerformedActions:List + ):StateCell + + requires true + andBool isKResult(Action) + andBool valueIsNotEmpty(Action, rAction) + + andBool valuesAreKResult(AddressToUserId) + andBool valuesAreOfType(AddressToUserId, rUsize) + andBool valuesAreNotEmpty(AddressToUserId, rUsize) + + andBool valuesAreOfType(UserIdToRole, rUserRole) + andBool valuesAreKResult(UserIdToRole) + + andBool unusedIdsInMapKeys(ActionLastIndex +Int 1, keysMap(ActionData), expand(expanded)) + andBool unusedIdsInMapKeys(ActionLastIndex +Int 1, keysMap(ActionSigners), expand(expanded)) + + andBool CallerAddress in_keys(AddressToUserId) + andBool AddressToUserId[CallerAddress] in_keys(UserIdToRole) + andBool UserIdToRole[AddressToUserId[CallerAddress]] ==K Proposer + ensures true + //@ proof + //@ trusted + // [trusted] + //@ end +endmodule diff --git a/multisig/protocol-correctness/proof/functions/proof-propose-action-error-no-role.k b/multisig/protocol-correctness/proof/functions/proof-propose-action-error-no-role.k new file mode 100644 index 000000000..a2f27d56b --- /dev/null +++ b/multisig/protocol-correctness/proof/functions/proof-propose-action-error-no-role.k @@ -0,0 +1,64 @@ +//@ proof +module PROOF-PROPOSE-ACTION-ERROR-NO-ROLE +//@ trusted +// module TRUSTED-PROPOSE-ACTION-ERROR-NO-ROLE +//@ end + imports FUNCTIONS-EXECUTE + + claim + call(proposeAction(_Action:Action)) ~> K:K + + invariantStateFull( + NumUsers:Usize, + UserIdToAddress:Map, + (CallerAddress |-> UserId:Usize _AddressToUserId:Map) #as AddressToUserId:Map, + NumBoardMembers:Usize, + NumProposers:Usize, + UserIdToRole:Map, + Quorum:Usize, + ActionLastIndex:Usize, + ActionData:Map, + ActionSigners:Map, + CallerAddress:Address, + Stack:Stack, + .Map, + PerformedActions:List + ) + + => + + error ~> K + invariantStateFull( + NumUsers, + UserIdToAddress, + AddressToUserId, + NumBoardMembers, + NumProposers, + UserIdToRole, + Quorum, + ActionLastIndex, + ActionData, + ActionSigners, + CallerAddress, + Stack:Stack, + ?_Variables:Map, + PerformedActions:List + ):StateCell + + requires true + andBool notBool u(0) in_keys(UserIdToRole) + + andBool valuesAreKResult(AddressToUserId) + andBool valuesAreOfType(AddressToUserId, rUsize) + andBool valuesAreNotEmpty(AddressToUserId, rUsize) + + andBool valuesAreOfType(UserIdToRole, rUserRole) + andBool valuesAreKResult(UserIdToRole) + + andBool notBool UserId in_keys(UserIdToRole) + ensures true + //@ proof + //@ trusted + // [trusted] + //@ end +endmodule diff --git a/multisig/protocol-correctness/proof/functions/proof-propose-action-error-no-user.k b/multisig/protocol-correctness/proof/functions/proof-propose-action-error-no-user.k new file mode 100644 index 000000000..5b03fd0dc --- /dev/null +++ b/multisig/protocol-correctness/proof/functions/proof-propose-action-error-no-user.k @@ -0,0 +1,64 @@ +//@ proof +module PROOF-PROPOSE-ACTION-ERROR-NO-USER +//@ trusted +// module TRUSTED-PROPOSE-ACTION-ERROR-NO-USER +//@ end + imports FUNCTIONS-EXECUTE + + claim + call(proposeAction(_Action:Action)) ~> K:K + + invariantStateFull( + NumUsers:Usize, + UserIdToAddress:Map, + AddressToUserId:Map, + NumBoardMembers:Usize, + NumProposers:Usize, + UserIdToRole:Map, + Quorum:Usize, + ActionLastIndex:Usize, + ActionData:Map, + ActionSigners:Map, + CallerAddress:Address, + Stack:Stack, + .Map, + PerformedActions:List + ) + + => + + error ~> K + invariantStateFull( + NumUsers, + UserIdToAddress, + AddressToUserId, + NumBoardMembers, + NumProposers, + UserIdToRole, + Quorum, + ActionLastIndex, + ActionData, + ActionSigners, + CallerAddress, + Stack:Stack, + ?_Variables:Map, + PerformedActions:List + ):StateCell + + requires true + andBool notBool u(0) in_keys(UserIdToRole) + + andBool valuesAreKResult(AddressToUserId) + andBool valuesAreOfType(AddressToUserId, rUsize) + andBool valuesAreNotEmpty(AddressToUserId, rUsize) + + andBool valuesAreOfType(UserIdToRole, rUserRole) + andBool valuesAreKResult(UserIdToRole) + + andBool notBool CallerAddress in_keys(AddressToUserId) + ensures true + //@ proof + //@ trusted + // [trusted] + //@ end +endmodule diff --git a/multisig/protocol-correctness/proof/functions/proof-propose-sc-deploy-BoardMember.k b/multisig/protocol-correctness/proof/functions/proof-propose-sc-deploy-BoardMember.k new file mode 100644 index 000000000..d854d9946 --- /dev/null +++ b/multisig/protocol-correctness/proof/functions/proof-propose-sc-deploy-BoardMember.k @@ -0,0 +1,96 @@ +//@ proof +require "trusted-propose-action-BoardMember.k" //@ Bazel remove +require "trusted-propose-sc-deploy-fragment.k" //@ Bazel remove +//@ trusted +//@ end + +//@ proof +module PROOF-PROPOSE-SC-DEPLOY-BOARDMEMBER +//@ trusted +// module TRUSTED-PROPOSE-SC-DEPLOY-BOARDMEMBER +//@ end + imports FUNCTIONS-EXECUTE + + //@ proof + imports TRUSTED-PROPOSE-ACTION-BOARDMEMBER + imports TRUSTED-PROPOSE-SC-DEPLOY-FRAGMENT + //@ trusted + //@ end + + claim + call(proposeSCDeploy( + Amount:BigUint, + Code:BoxedBytes, + Upgradeable:Bool, + Payable:Bool, + Readable:Bool, + Args:ExpressionList)) + ~> K:K + + invariantStateFull( + NumUsers:Usize, + UserIdToAddress:Map, + AddressToUserId:Map, + NumBoardMembers:Usize, + NumProposers:Usize, + UserIdToRole:Map, + Quorum:Usize, + u(ActionLastIndex:Int), + ActionData:Map, + ActionSigners:Map, + CallerAddress:Address, + Stack:Stack, + .Map, + PerformedActions:List + ) + + => + + evaluate(u(ActionLastIndex +Int 1)) ~> K + invariantStateFull( + NumUsers, + UserIdToAddress, + AddressToUserId, + NumBoardMembers, + NumProposers, + UserIdToRole, + Quorum, + u(ActionLastIndex +Int 1), + u(ActionLastIndex +Int 1) + |-> SCDeploy( + Amount, + Code, + codeMetadataFunction(Upgradeable, Payable, Readable), + Args) + ActionData, + (u(ActionLastIndex +Int 1) |-> [{AddressToUserId[CallerAddress]}:>Usize, .]) ActionSigners, + CallerAddress, + Stack:Stack, + ?_Variables, + PerformedActions:List + ):StateCell + + requires true + andBool isKResult(Args) + + andBool valuesAreKResult(AddressToUserId) + andBool valuesAreOfType(AddressToUserId, rUsize) + andBool valuesAreNotEmpty(AddressToUserId, rUsize) + + andBool valuesAreOfType(UserIdToRole, rUserRole) + andBool valuesAreKResult(UserIdToRole) + + andBool unusedIdsInMapKeys(ActionLastIndex +Int 1, keysMap(ActionData), expand(expanded)) + andBool unusedIdsInMapKeys(ActionLastIndex +Int 1, keysMap(ActionSigners), expand(expanded)) + + andBool CallerAddress in_keys(AddressToUserId) + andBool AddressToUserId[CallerAddress] in_keys(UserIdToRole) + andBool UserIdToRole[AddressToUserId[CallerAddress]] ==K BoardMember + ensures true + //@ proof + //@ trusted + // [trusted] + //@ end +endmodule + + diff --git a/multisig/protocol-correctness/proof/functions/proof-propose-sc-deploy-Proposer.k b/multisig/protocol-correctness/proof/functions/proof-propose-sc-deploy-Proposer.k new file mode 100644 index 000000000..dfb91fa31 --- /dev/null +++ b/multisig/protocol-correctness/proof/functions/proof-propose-sc-deploy-Proposer.k @@ -0,0 +1,90 @@ +//@ proof +require "trusted-propose-action-Proposer.k" //@ Bazel remove +require "trusted-propose-sc-deploy-fragment.k" //@ Bazel remove +//@ trusted +//@ end + +//@ proof +module PROOF-PROPOSE-SC-DEPLOY-PROPOSER +//@ trusted +// module TRUSTED-PROPOSE-SC-DEPLOY-PROPOSER +//@ end + imports FUNCTIONS-EXECUTE + + //@ proof + imports TRUSTED-PROPOSE-ACTION-PROPOSER + imports TRUSTED-PROPOSE-SC-DEPLOY-FRAGMENT + //@ trusted + //@ end + + claim + call(proposeSCDeploy( + Amount:BigUint, + Code:BoxedBytes, + Upgradeable:Bool, + Payable:Bool, + Readable:Bool, + Args:ExpressionList)) + ~> K:K + + invariantStateFull( + NumUsers:Usize, + UserIdToAddress:Map, + AddressToUserId:Map, + NumBoardMembers:Usize, + NumProposers:Usize, + UserIdToRole:Map, + Quorum:Usize, + u(ActionLastIndex:Int), + ActionData:Map, + ActionSigners:Map, + CallerAddress:Address, + Stack:Stack, + .Map, + PerformedActions:List + ) + + => + + evaluate(u(ActionLastIndex +Int 1)) ~> K + invariantStateFull( + NumUsers, + UserIdToAddress, + AddressToUserId, + NumBoardMembers, + NumProposers, + UserIdToRole, + Quorum, + u(ActionLastIndex +Int 1), + u(ActionLastIndex +Int 1) + |-> SCDeploy( + Amount, + Code, + codeMetadataFunction(Upgradeable, Payable, Readable), + Args) + ActionData, + ActionSigners, + CallerAddress, + Stack:Stack, + ?_Variables, + PerformedActions:List + ):StateCell + + requires true + andBool isKResult(Args) + + andBool valuesAreKResult(AddressToUserId) + andBool valuesAreOfType(AddressToUserId, rUsize) + andBool valuesAreNotEmpty(AddressToUserId, rUsize) + + andBool valuesAreOfType(UserIdToRole, rUserRole) + andBool valuesAreKResult(UserIdToRole) + + andBool unusedIdsInMapKeys(ActionLastIndex +Int 1, keysMap(ActionData), expand(expanded)) + andBool unusedIdsInMapKeys(ActionLastIndex +Int 1, keysMap(ActionSigners), expand(expanded)) + + andBool CallerAddress in_keys(AddressToUserId) + andBool AddressToUserId[CallerAddress] in_keys(UserIdToRole) + andBool UserIdToRole[AddressToUserId[CallerAddress]] ==K Proposer + ensures true +endmodule diff --git a/multisig/protocol-correctness/proof/functions/proof-propose-sc-deploy-error-no-role.k b/multisig/protocol-correctness/proof/functions/proof-propose-sc-deploy-error-no-role.k new file mode 100644 index 000000000..5af1d3745 --- /dev/null +++ b/multisig/protocol-correctness/proof/functions/proof-propose-sc-deploy-error-no-role.k @@ -0,0 +1,84 @@ +//@ proof +require "trusted-propose-action-error-no-role.k" //@ Bazel remove +require "trusted-propose-sc-deploy-fragment.k" //@ Bazel remove +//@ trusted +//@ end + +//@ proof +module PROOF-PROPOSE-SC-DEPLOY-ERROR-NO-ROLE +//@ trusted +// module TRUSTED-PROPOSE-SC-DEPLOY-ERROR-NO-ROLE +//@ end + imports FUNCTIONS-EXECUTE + + //@ proof + imports TRUSTED-PROPOSE-ACTION-ERROR-NO-ROLE + imports TRUSTED-PROPOSE-SC-DEPLOY-FRAGMENT + //@ trusted + //@ end + + claim + call(proposeSCDeploy( + _Amount:BigUint, + _Code:BoxedBytes, + _Upgradeable:Bool, + _Payable:Bool, + _Readable:Bool, + Args:ExpressionList)) + ~> K:K + + invariantStateFull( + NumUsers:Usize, + UserIdToAddress:Map, + (CallerAddress |-> UserId:Usize _AddressToUserId:Map) #as AddressToUserId:Map, + NumBoardMembers:Usize, + NumProposers:Usize, + UserIdToRole:Map, + Quorum:Usize, + ActionLastIndex:Usize, + ActionData:Map, + ActionSigners:Map, + CallerAddress:Address, + Stack:Stack, + .Map, + PerformedActions:List + ) + + => + + error ~> K + invariantStateFull( + NumUsers, + UserIdToAddress, + AddressToUserId, + NumBoardMembers, + NumProposers, + UserIdToRole, + Quorum, + ActionLastIndex, + ActionData, + ActionSigners, + CallerAddress, + Stack:Stack, + ?_Variables:Map, + PerformedActions:List + ):StateCell + + requires true + andBool isKResult(Args) + andBool notBool u(0) in_keys(UserIdToRole) + + andBool valuesAreKResult(AddressToUserId) + andBool valuesAreOfType(AddressToUserId, rUsize) + andBool valuesAreNotEmpty(AddressToUserId, rUsize) + + andBool valuesAreOfType(UserIdToRole, rUserRole) + andBool valuesAreKResult(UserIdToRole) + + andBool notBool UserId in_keys(UserIdToRole) + ensures true + //@ proof + //@ trusted + // [trusted] + //@ end +endmodule diff --git a/multisig/protocol-correctness/proof/functions/proof-propose-sc-deploy-error-no-user.k b/multisig/protocol-correctness/proof/functions/proof-propose-sc-deploy-error-no-user.k new file mode 100644 index 000000000..b1ac48787 --- /dev/null +++ b/multisig/protocol-correctness/proof/functions/proof-propose-sc-deploy-error-no-user.k @@ -0,0 +1,84 @@ +//@ proof +require "trusted-propose-action-error-no-user.k" //@ Bazel remove +require "trusted-propose-sc-deploy-fragment.k" //@ Bazel remove +//@ trusted +//@ end + +//@ proof +module PROOF-PROPOSE-SC-DEPLOY-ERROR-NO-USER +//@ trusted +// module TRUSTED-PROPOSE-SC-DEPLOY-ERROR-NO-USER +//@ end + imports FUNCTIONS-EXECUTE + + //@ proof + imports TRUSTED-PROPOSE-ACTION-ERROR-NO-USER + imports TRUSTED-PROPOSE-SC-DEPLOY-FRAGMENT + //@ trusted + //@ end + + claim + call(proposeSCDeploy( + _Amount:BigUint, + _Code:BoxedBytes, + _Upgradeable:Bool, + _Payable:Bool, + _Readable:Bool, + Args:ExpressionList)) + ~> K:K + + invariantStateFull( + NumUsers:Usize, + UserIdToAddress:Map, + AddressToUserId:Map, + NumBoardMembers:Usize, + NumProposers:Usize, + UserIdToRole:Map, + Quorum:Usize, + ActionLastIndex:Usize, + ActionData:Map, + ActionSigners:Map, + CallerAddress:Address, + Stack:Stack, + .Map, + PerformedActions:List + ) + + => + + error ~> K + invariantStateFull( + NumUsers, + UserIdToAddress, + AddressToUserId, + NumBoardMembers, + NumProposers, + UserIdToRole, + Quorum, + ActionLastIndex, + ActionData, + ActionSigners, + CallerAddress, + Stack:Stack, + ?_Variables:Map, + PerformedActions:List + ):StateCell + + requires true + andBool isKResult(Args) + andBool notBool u(0) in_keys(UserIdToRole) + + andBool valuesAreKResult(AddressToUserId) + andBool valuesAreOfType(AddressToUserId, rUsize) + andBool valuesAreNotEmpty(AddressToUserId, rUsize) + + andBool valuesAreOfType(UserIdToRole, rUserRole) + andBool valuesAreKResult(UserIdToRole) + + andBool notBool CallerAddress in_keys(AddressToUserId) + ensures true + //@ proof + //@ trusted + // [trusted] + //@ end +endmodule diff --git a/multisig/protocol-correctness/proof/functions/proof-propose-sc-deploy-fragment.k b/multisig/protocol-correctness/proof/functions/proof-propose-sc-deploy-fragment.k new file mode 100644 index 000000000..0505c01c4 --- /dev/null +++ b/multisig/protocol-correctness/proof/functions/proof-propose-sc-deploy-fragment.k @@ -0,0 +1,71 @@ +//@ proof +module PROOF-PROPOSE-SC-DEPLOY-FRAGMENT +//@ trusted +// module TRUSTED-PROPOSE-SC-DEPLOY-FRAGMENT +//@ end + imports FUNCTIONS-EXECUTE + + claim + runPseudoCode( + code_metadata = CodeMetadata::DEFAULT; + if (Upgradeable) { + code_metadata = code_metadata | CodeMetadata::UPGRADEABLE; + } + if (Payable) { + code_metadata = code_metadata | CodeMetadata::PAYABLE; + } + if (Readable) { + code_metadata = code_metadata | CodeMetadata::READABLE; + } + proposeActionSCDeploy(Amount, Code, code_metadata, Args); + ) + ~> K:K + + invariantStateFull( + NumUsers:Usize, + UserIdToAddress:Map, + AddressToUserId:Map, + NumBoardMembers:Usize, + NumProposers:Usize, + UserIdToRole:Map, + Quorum:Usize, + u(ActionLastIndex:Int), + ActionData:Map, + ActionSigners:Map, + CallerAddress:Address, + Stack:Stack, + .Map, + PerformedActions:List + ) + + => + + runPseudoCode( + proposeActionSCDeploy(Amount, Code, code_metadata, Args); + ) + ~> K:K + + invariantStateFull( + NumUsers:Usize, + UserIdToAddress:Map, + AddressToUserId:Map, + NumBoardMembers:Usize, + NumProposers:Usize, + UserIdToRole:Map, + Quorum:Usize, + u(ActionLastIndex:Int), + ActionData:Map, + ActionSigners:Map, + CallerAddress:Address, + Stack:Stack, + code_metadata |-> codeMetadataFunction(Upgradeable, Payable, Readable), + PerformedActions:List + ) + + requires true + ensures true + //@ proof + //@ trusted + // [trusted] + //@ end +endmodule diff --git a/multisig/protocol-correctness/proof/functions/proof-sign-caller-none.k b/multisig/protocol-correctness/proof/functions/proof-sign-caller-none.k new file mode 100644 index 000000000..e66477951 --- /dev/null +++ b/multisig/protocol-correctness/proof/functions/proof-sign-caller-none.k @@ -0,0 +1,59 @@ +//@ proof +module PROOF-SIGN-CALLER-NONE +//@ trusted +// module TRUSTED-SIGN-CALLER-NONE +//@ end + imports FUNCTIONS-EXECUTE + + claim + call(sign(ActionId:Usize)) ~> K:K + + invariantStateFull( + NumUsers:Usize, + UserIdToAddress:Map, + (CallerAddress |-> UserId:Usize _AddressToUserId:Map) #as AddressToUserId:Map, + NumBoardMembers:Usize, + NumProposers:Usize, + UserIdToRole:Map, + Quorum:Usize, + ActionLastIndex:Usize, + ActionData:Map, + ActionSigners:Map, + CallerAddress:Address, + Stack:Stack, + .Map, + PerformedActions:List + ) + + => + + error ~> K + invariantStateFull( + NumUsers, + UserIdToAddress, + AddressToUserId, + NumBoardMembers, + NumProposers, + UserIdToRole, + Quorum, + ActionLastIndex, + ActionData, + ActionSigners, + CallerAddress, + Stack:Stack, + ?_Variables, + PerformedActions:List + ):StateCell + + requires true + andBool notBool u(0) in_keys(UserIdToRole) + andBool actionDataInvariant(ActionData) + + andBool ActionId in_keys(ActionData) + andBool notBool UserId in_keys(UserIdToRole) + ensures true + //@ proof + //@ trusted + // [trusted] + //@ end +endmodule diff --git a/multisig/protocol-correctness/proof/functions/proof-sign-caller-not-user.k b/multisig/protocol-correctness/proof/functions/proof-sign-caller-not-user.k new file mode 100644 index 000000000..a560812cd --- /dev/null +++ b/multisig/protocol-correctness/proof/functions/proof-sign-caller-not-user.k @@ -0,0 +1,59 @@ +//@ proof +module PROOF-SIGN-CALLER-NOT-USER +//@ trusted +// module TRUSTED-SIGN-CALLER-NOT-USER +//@ end + imports FUNCTIONS-EXECUTE + + claim + call(sign(ActionId:Usize)) ~> K:K + + invariantStateFull( + NumUsers:Usize, + UserIdToAddress:Map, + AddressToUserId:Map, + NumBoardMembers:Usize, + NumProposers:Usize, + UserIdToRole:Map, + Quorum:Usize, + ActionLastIndex:Usize, + ActionData:Map, + ActionSigners:Map, + CallerAddress:Address, + Stack:Stack, + .Map, + PerformedActions:List + ) + + => + + error ~> K + invariantStateFull( + NumUsers, + UserIdToAddress, + AddressToUserId, + NumBoardMembers, + NumProposers, + UserIdToRole, + Quorum, + ActionLastIndex, + ActionData, + ActionSigners, + CallerAddress, + Stack:Stack, + ?_Variables, + PerformedActions:List + ):StateCell + + requires true + andBool notBool u(0) in_keys(UserIdToRole) + andBool actionDataInvariant(ActionData) + + andBool ActionId in_keys(ActionData) + andBool notBool CallerAddress in_keys(AddressToUserId) + ensures true + //@ proof + //@ trusted + // [trusted] + //@ end +endmodule diff --git a/multisig/protocol-correctness/proof/functions/proof-sign-caller-proposer.k b/multisig/protocol-correctness/proof/functions/proof-sign-caller-proposer.k new file mode 100644 index 000000000..381966298 --- /dev/null +++ b/multisig/protocol-correctness/proof/functions/proof-sign-caller-proposer.k @@ -0,0 +1,60 @@ +//@ proof +module PROOF-SIGN-CALLER-PROPOSER +//@ trusted +// module TRUSTED-SIGN-CALLER-PROPOSER +//@ end + imports FUNCTIONS-EXECUTE + + claim + call(sign(ActionId:Usize)) ~> K:K + + invariantStateFull( + NumUsers:Usize, + UserIdToAddress:Map, + (CallerAddress |-> UserId:Usize _AddressToUserId:Map) #as AddressToUserId:Map, + NumBoardMembers:Usize, + NumProposers:Usize, + (UserId |-> Proposer _UserIdToRole:Map) #as UserIdToRole:Map, + Quorum:Usize, + ActionLastIndex:Usize, + ActionData:Map, + ActionSigners:Map, + CallerAddress:Address, + Stack:Stack, + .Map, + PerformedActions:List + ) + + => + + error ~> K + invariantStateFull( + NumUsers, + UserIdToAddress, + AddressToUserId, + NumBoardMembers, + NumProposers, + UserIdToRole, + Quorum, + ActionLastIndex, + ActionData, + ActionSigners, + CallerAddress, + Stack:Stack, + ?_Variables, + PerformedActions:List + ):StateCell + + requires true + andBool notBool u(0) in_keys(UserIdToRole) + andBool actionDataInvariant(ActionData) + andBool userIdToRoleInvariant(UserIdToRole) + + andBool ActionId in_keys(ActionData) + // andBool notBool ActionId in_keys(ActionSigners) + ensures true + //@ proof + //@ trusted + // [trusted] + //@ end +endmodule diff --git a/multisig/protocol-correctness/proof/functions/proof-sign-empty-action.k b/multisig/protocol-correctness/proof/functions/proof-sign-empty-action.k new file mode 100644 index 000000000..a5e662a23 --- /dev/null +++ b/multisig/protocol-correctness/proof/functions/proof-sign-empty-action.k @@ -0,0 +1,55 @@ +//@ proof +module PROOF-SIGN-EMPTY-ACTION +//@ trusted +// module TRUSTED-SIGN-EMPTY-ACTION +//@ end + imports FUNCTIONS-EXECUTE + + claim + call(sign(ActionId:Usize)) ~> K:K + + invariantStateFull( + NumUsers:Usize, + UserIdToAddress:Map, + AddressToUserId:Map, + NumBoardMembers:Usize, + NumProposers:Usize, + UserIdToRole:Map, + Quorum:Usize, + ActionLastIndex:Usize, + ActionData:Map, + ActionSigners:Map, + CallerAddress:Address, + Stack:Stack, + .Map, + PerformedActions:List + ) + + => + + error ~> K + invariantStateFull( + NumUsers, + UserIdToAddress, + AddressToUserId, + NumBoardMembers, + NumProposers, + UserIdToRole, + Quorum, + ActionLastIndex, + ActionData, + ActionSigners, + CallerAddress, + Stack:Stack, + ?_Variables, + PerformedActions:List + ):StateCell + + requires true + andBool notBool ActionId in_keys(ActionData) + ensures true + //@ proof + //@ trusted + // [trusted] + //@ end +endmodule diff --git a/multisig/protocol-correctness/proof/functions/proof-sign-existing-signers-in-list.k b/multisig/protocol-correctness/proof/functions/proof-sign-existing-signers-in-list.k new file mode 100644 index 000000000..19fd16098 --- /dev/null +++ b/multisig/protocol-correctness/proof/functions/proof-sign-existing-signers-in-list.k @@ -0,0 +1,61 @@ +//@ proof +module PROOF-SIGN-EXISTING-SIGNERS-IN-LIST +//@ trusted +// module TRUSTED-SIGN-EXISTING-SIGNERS-IN-LIST +//@ end + imports FUNCTIONS-EXECUTE + + claim + call(sign(ActionId:Usize)) ~> K:K + + invariantStateFull( + NumUsers:Usize, + UserIdToAddress:Map, + (CallerAddress |-> UserId:Usize _AddressToUserId:Map) #as AddressToUserId:Map, + NumBoardMembers:Usize, + NumProposers:Usize, + (UserId |-> BoardMember _UserIdToRole:Map) #as UserIdToRole:Map, + Quorum:Usize, + ActionLastIndex:Usize, + ActionData:Map, + ((ActionId |-> Signers:ExpressionList) _ActionSigners:Map) #as ActionSigners:Map, + CallerAddress:Address, + Stack:Stack, + .Map, + PerformedActions:List + ) + + => + + void ~> K + invariantStateFull( + NumUsers, + UserIdToAddress, + AddressToUserId, + NumBoardMembers, + NumProposers, + UserIdToRole, + Quorum, + ActionLastIndex, + ActionData, + ActionSigners, + CallerAddress, + Stack:Stack, + ?_Variables, + PerformedActions:List + ):StateCell + + requires true + andBool notBool u(0) in_keys(UserIdToRole) + andBool actionDataInvariant(ActionData) + andBool userIdToRoleInvariant(UserIdToRole) + + andBool ActionId in_keys(ActionData) + andBool isKResult(Signers) + andBool #listContains(Signers, UserId) + ensures true + //@ proof + //@ trusted + // [trusted] + //@ end +endmodule diff --git a/multisig/protocol-correctness/proof/functions/proof-sign-existing-signers-not-in-list.k b/multisig/protocol-correctness/proof/functions/proof-sign-existing-signers-not-in-list.k new file mode 100644 index 000000000..eb51451df --- /dev/null +++ b/multisig/protocol-correctness/proof/functions/proof-sign-existing-signers-not-in-list.k @@ -0,0 +1,61 @@ +//@ proof +module PROOF-SIGN-EXISTING-SIGNERS-NOT-IN-LIST +//@ trusted +// module TRUSTED-SIGN-EXISTING-SIGNERS-NOT-IN-LIST +//@ end + imports FUNCTIONS-EXECUTE + + claim + call(sign(ActionId:Usize)) ~> K:K + + invariantStateFull( + NumUsers:Usize, + UserIdToAddress:Map, + (CallerAddress |-> UserId:Usize _AddressToUserId:Map) #as AddressToUserId:Map, + NumBoardMembers:Usize, + NumProposers:Usize, + (UserId |-> BoardMember _UserIdToRole:Map) #as UserIdToRole:Map, + Quorum:Usize, + ActionLastIndex:Usize, + ActionData:Map, + (ActionId |-> [Signers:ExpressionCSV]) ActionSigners:Map, + CallerAddress:Address, + Stack:Stack, + .Map, + PerformedActions:List + ) + + => + + void ~> K + invariantStateFull( + NumUsers, + UserIdToAddress, + AddressToUserId, + NumBoardMembers, + NumProposers, + UserIdToRole, + Quorum, + ActionLastIndex, + ActionData, + (ActionId |-> [#pushList(Signers, UserId)]) ActionSigners, + CallerAddress, + Stack:Stack, + ?_Variables, + PerformedActions:List + ):StateCell + + requires true + andBool notBool u(0) in_keys(UserIdToRole) + andBool actionDataInvariant(ActionData) + andBool userIdToRoleInvariant(UserIdToRole) + + andBool ActionId in_keys(ActionData) + andBool isKResult(Signers) + andBool notBool #listContains([Signers], UserId) + ensures true + //@ proof + //@ trusted + // [trusted] + //@ end +endmodule diff --git a/multisig/protocol-correctness/proof/functions/proof-sign-no-signers.k b/multisig/protocol-correctness/proof/functions/proof-sign-no-signers.k new file mode 100644 index 000000000..e02229da4 --- /dev/null +++ b/multisig/protocol-correctness/proof/functions/proof-sign-no-signers.k @@ -0,0 +1,62 @@ +//@ proof +module PROOF-SIGN-NO-SIGNERS +//@ trusted +// module TRUSTED-SIGN-NO-SIGNERS +//@ end + imports FUNCTIONS-EXECUTE + + claim + call(sign(ActionId:Usize)) ~> K:K + + invariantStateFull( + NumUsers:Usize, + UserIdToAddress:Map, + (CallerAddress |-> UserId:Usize _AddressToUserId:Map) #as AddressToUserId:Map, + NumBoardMembers:Usize, + NumProposers:Usize, + (UserId |-> BoardMember _UserIdToRole:Map) #as UserIdToRole:Map, + Quorum:Usize, + u(ActionLastIndex:Int), + ActionData:Map, + ActionSigners:Map, + CallerAddress:Address, + Stack:Stack, + .Map, + PerformedActions:List + ) + + => + + void ~> K + invariantStateFull( + NumUsers, + UserIdToAddress, + AddressToUserId, + NumBoardMembers, + NumProposers, + UserIdToRole, + Quorum, + u(ActionLastIndex), + ActionData, + ActionId |-> [UserId, .] ActionSigners, + CallerAddress, + Stack:Stack, + ?_Variables, + PerformedActions:List + ):StateCell + + requires true + andBool notBool u(0) in_keys(UserIdToRole) + andBool actionDataInvariant(ActionData) + andBool userIdToRoleInvariant(UserIdToRole) + andBool unusedIdsInMapKeys(ActionLastIndex +Int 1, keysMap(ActionData), Handling) + + andBool ActionId in_keys(ActionData) + andBool notBool ActionId in_keys(ActionSigners) + ensures true + andBool usizeToInt(ActionId) + call(unsign(ActionId:Usize)) ~> K:K + + invariantStateFull( + NumUsers:Usize, + UserIdToAddress:Map, + (CallerAddress |-> UserId:Usize _AddressToUserId:Map) #as AddressToUserId:Map, + NumBoardMembers:Usize, + NumProposers:Usize, + (UserId |-> Proposer _UserIdToRole:Map) #as UserIdToRole:Map, + Quorum:Usize, + u(ActionLastIndex:Int), + (ActionId |-> Action:Action _ActionData:Map) #as ActionData:Map, + ActionSigners:Map, + CallerAddress:Address, + Stack:Stack, + .Map, + PerformedActions:List + ) + + => + + error ~> K + invariantStateFull( + NumUsers, + UserIdToAddress, + AddressToUserId, + NumBoardMembers, + NumProposers, + UserIdToRole, + Quorum, + u(ActionLastIndex), + ActionData, + ActionSigners, + CallerAddress, + Stack:Stack, + ?_Variables, + PerformedActions:List + ):StateCell + + requires true + andBool isKResult(Action) + andBool valueIsNotEmpty(Action, rAction) + ensures true + //@ proof + //@ trusted + // [trusted] + //@ end +endmodule diff --git a/multisig/protocol-correctness/proof/functions/proof-unsign-no-action.k b/multisig/protocol-correctness/proof/functions/proof-unsign-no-action.k new file mode 100644 index 000000000..ff192cc8b --- /dev/null +++ b/multisig/protocol-correctness/proof/functions/proof-unsign-no-action.k @@ -0,0 +1,56 @@ +//@ proof +module PROOF-UNSIGN-NO-ACTION + imports FUNCTIONS-EXECUTE +//@ trusted +// module TRUSTED-UNSIGN-NO-ACTION + // imports EXECUTION-PROOF +//@ end + + claim + call(unsign(ActionId:Usize)) ~> K:K + + invariantStateFull( + NumUsers:Usize, + UserIdToAddress:Map, + AddressToUserId:Map, + NumBoardMembers:Usize, + NumProposers:Usize, + UserIdToRole:Map, + Quorum:Usize, + u(ActionLastIndex:Int), + ActionData:Map, + ActionSigners:Map, + CallerAddress:Address, + Stack:Stack, + .Map, + PerformedActions:List + ) + + => + + error ~> K + invariantStateFull( + NumUsers, + UserIdToAddress, + AddressToUserId, + NumBoardMembers, + NumProposers, + UserIdToRole, + Quorum, + u(ActionLastIndex), + ActionData, + ActionSigners, + CallerAddress, + Stack:Stack, + ?_Variables, + PerformedActions:List + ):StateCell + + requires true + andBool notBool ActionId in_keys(ActionData) + ensures true + //@ proof + //@ trusted + // [trusted] + //@ end +endmodule diff --git a/multisig/protocol-correctness/proof/functions/proof-unsign-no-role.k b/multisig/protocol-correctness/proof/functions/proof-unsign-no-role.k new file mode 100644 index 000000000..5f8a86d5d --- /dev/null +++ b/multisig/protocol-correctness/proof/functions/proof-unsign-no-role.k @@ -0,0 +1,59 @@ +//@ proof +module PROOF-UNSIGN-NO-ROLE + imports FUNCTIONS-EXECUTE +//@ trusted +// module TRUSTED-UNSIGN-NO-ROLE + // imports EXECUTION-PROOF +//@ end + + claim + call(unsign(ActionId:Usize)) ~> K:K + + invariantStateFull( + NumUsers:Usize, + UserIdToAddress:Map, + (CallerAddress |-> UserId:Usize _AddressToUserId:Map) #as AddressToUserId:Map, + NumBoardMembers:Usize, + NumProposers:Usize, + UserIdToRole:Map, + Quorum:Usize, + u(ActionLastIndex:Int), + (ActionId |-> Action:Action _ActionData:Map) #as ActionData:Map, + ActionSigners:Map, + CallerAddress:Address, + Stack:Stack, + .Map, + PerformedActions:List + ) + + => + + error ~> K + invariantStateFull( + NumUsers, + UserIdToAddress, + AddressToUserId, + NumBoardMembers, + NumProposers, + UserIdToRole, + Quorum, + u(ActionLastIndex), + ActionData, + ActionSigners, + CallerAddress, + Stack:Stack, + ?_Variables, + PerformedActions:List + ):StateCell + + requires true + andBool isKResult(Action) + andBool valueIsNotEmpty(Action, rAction) + + andBool notBool UserId in_keys(UserIdToRole) + ensures true + //@ proof + //@ trusted + // [trusted] + //@ end +endmodule diff --git a/multisig/protocol-correctness/proof/functions/proof-unsign-no-signers.k b/multisig/protocol-correctness/proof/functions/proof-unsign-no-signers.k new file mode 100644 index 000000000..9bf605b96 --- /dev/null +++ b/multisig/protocol-correctness/proof/functions/proof-unsign-no-signers.k @@ -0,0 +1,59 @@ +//@ proof +module PROOF-UNSIGN-NO-SIGNERS + imports FUNCTIONS-EXECUTE +//@ trusted +// module TRUSTED-UNSIGN-NO-SIGNERS + // imports EXECUTION-PROOF +//@ end + + claim + call(unsign(ActionId:Usize)) ~> K:K + + invariantStateFull( + NumUsers:Usize, + UserIdToAddress:Map, + (CallerAddress |-> UserId:Usize _AddressToUserId:Map) #as AddressToUserId:Map, + NumBoardMembers:Usize, + NumProposers:Usize, + (UserId |-> BoardMember _UserIdToRole:Map) #as UserIdToRole:Map, + Quorum:Usize, + u(ActionLastIndex:Int), + (ActionId |-> Action:Action _ActionData:Map) #as ActionData:Map, + ActionSigners:Map, + CallerAddress:Address, + Stack:Stack, + .Map, + PerformedActions:List + ) + + => + + void ~> K + invariantStateFull( + NumUsers, + UserIdToAddress, + AddressToUserId, + NumBoardMembers, + NumProposers, + UserIdToRole, + Quorum, + u(ActionLastIndex), + ActionData, + ActionSigners, + CallerAddress, + Stack:Stack, + ?_Variables, + PerformedActions:List + ):StateCell + + requires true + andBool isKResult(Action) + andBool valueIsNotEmpty(Action, rAction) + + andBool notBool ActionId in_keys(ActionSigners) + ensures true + //@ proof + //@ trusted + // [trusted] + //@ end +endmodule diff --git a/multisig/protocol-correctness/proof/functions/proof-unsign-no-user.k b/multisig/protocol-correctness/proof/functions/proof-unsign-no-user.k new file mode 100644 index 000000000..dbf246381 --- /dev/null +++ b/multisig/protocol-correctness/proof/functions/proof-unsign-no-user.k @@ -0,0 +1,60 @@ +//@ proof +module PROOF-UNSIGN-NO-USER + imports FUNCTIONS-EXECUTE +//@ trusted +// module TRUSTED-UNSIGN-NO-USER + // imports EXECUTION-PROOF +//@ end + + claim + call(unsign(ActionId:Usize)) ~> K:K + + invariantStateFull( + NumUsers:Usize, + UserIdToAddress:Map, + AddressToUserId:Map, + NumBoardMembers:Usize, + NumProposers:Usize, + UserIdToRole:Map, + Quorum:Usize, + u(ActionLastIndex:Int), + (ActionId |-> Action:Action _ActionData:Map) #as ActionData:Map, + ActionSigners:Map, + CallerAddress:Address, + Stack:Stack, + .Map, + PerformedActions:List + ) + + => + + error ~> K + invariantStateFull( + NumUsers, + UserIdToAddress, + AddressToUserId, + NumBoardMembers, + NumProposers, + UserIdToRole, + Quorum, + u(ActionLastIndex), + ActionData, + ActionSigners, + CallerAddress, + Stack:Stack, + ?_Variables, + PerformedActions:List + ):StateCell + + requires true + andBool isKResult(Action) + andBool valueIsNotEmpty(Action, rAction) + andBool notBool u(0) in_keys(UserIdToRole) + + andBool notBool CallerAddress in_keys(AddressToUserId) + ensures true + //@ proof + //@ trusted + // [trusted] + //@ end +endmodule diff --git a/multisig/protocol-correctness/proof/functions/proof-unsign-not-signed.k b/multisig/protocol-correctness/proof/functions/proof-unsign-not-signed.k new file mode 100644 index 000000000..fe0601cb0 --- /dev/null +++ b/multisig/protocol-correctness/proof/functions/proof-unsign-not-signed.k @@ -0,0 +1,60 @@ +//@ proof +module PROOF-UNSIGN-NOT-SIGNED + imports FUNCTIONS-EXECUTE +//@ trusted +// module TRUSTED-UNSIGN-NOT-SIGNED + // imports EXECUTION-PROOF +//@ end + + claim + call(unsign(ActionId:Usize)) ~> K:K + + invariantStateFull( + NumUsers:Usize, + UserIdToAddress:Map, + (CallerAddress |-> UserId:Usize _AddressToUserId:Map) #as AddressToUserId:Map, + NumBoardMembers:Usize, + NumProposers:Usize, + (UserId |-> BoardMember _UserIdToRole:Map) #as UserIdToRole:Map, + Quorum:Usize, + u(ActionLastIndex:Int), + (ActionId |-> Action:Action _ActionData:Map) #as ActionData:Map, + (ActionId |-> Signers:ExpressionList _ActionSigners:Map) #as ActionSigners:Map, + CallerAddress:Address, + Stack:Stack, + .Map, + PerformedActions:List + ) + + => + + void ~> K + invariantStateFull( + NumUsers, + UserIdToAddress, + AddressToUserId, + NumBoardMembers, + NumProposers, + UserIdToRole, + Quorum, + u(ActionLastIndex), + ActionData, + ActionSigners, + CallerAddress, + Stack:Stack, + ?_Variables, + PerformedActions:List + ):StateCell + + requires true + andBool isKResult(Action) + andBool valueIsNotEmpty(Action, rAction) + andBool isKResult(Signers) + + andBool #listFind(Signers, UserId) + call(unsign(ActionId:Usize)) ~> K:K + + invariantStateFull( + NumUsers:Usize, + UserIdToAddress:Map, + (CallerAddress |-> UserId:Usize _AddressToUserId:Map) #as AddressToUserId:Map, + NumBoardMembers:Usize, + NumProposers:Usize, + (UserId |-> BoardMember _UserIdToRole:Map) #as UserIdToRole:Map, + Quorum:Usize, + u(ActionLastIndex:Int), + (ActionId |-> Action:Action _ActionData:Map) #as ActionData:Map, + ActionId |-> [UserId, .] ActionSigners:Map, + CallerAddress:Address, + Stack:Stack, + .Map, + PerformedActions:List + ) + + => + + void ~> K + invariantStateFull( + NumUsers, + UserIdToAddress, + AddressToUserId, + NumBoardMembers, + NumProposers, + UserIdToRole, + Quorum, + u(ActionLastIndex), + ActionData, + ActionSigners, + CallerAddress, + Stack:Stack, + ?_Variables, + PerformedActions:List + ):StateCell + + requires true + andBool isKResult(Action) + andBool valueIsNotEmpty(Action, rAction) + ensures true + //@ proof + //@ trusted + // [trusted] + //@ end +endmodule diff --git a/multisig/protocol-correctness/proof/functions/proof-unsign-other-signers-first.k b/multisig/protocol-correctness/proof/functions/proof-unsign-other-signers-first.k new file mode 100644 index 000000000..0385e338c --- /dev/null +++ b/multisig/protocol-correctness/proof/functions/proof-unsign-other-signers-first.k @@ -0,0 +1,61 @@ +//@ proof +module PROOF-UNSIGN-OTHER-SIGNERS-FIRST + imports FUNCTIONS-EXECUTE +//@ trusted +// module TRUSTED-UNSIGN-OTHER-SIGNERS-FIRST + // imports EXECUTION-PROOF +//@ end + + claim + call(unsign(ActionId:Usize)) ~> K:K + + invariantStateFull( + NumUsers:Usize, + UserIdToAddress:Map, + (CallerAddress |-> UserId:Usize _AddressToUserId:Map) #as AddressToUserId:Map, + NumBoardMembers:Usize, + NumProposers:Usize, + (UserId |-> BoardMember _UserIdToRole:Map) #as UserIdToRole:Map, + Quorum:Usize, + u(ActionLastIndex:Int), + (ActionId |-> Action:Action _ActionData:Map) #as ActionData:Map, + ActionId |-> [(UserId, _:Usize, _Signers:ExpressionCSV) #as Signers:ExpressionCSV] ActionSigners:Map, + CallerAddress:Address, + Stack:Stack, + .Map, + PerformedActions:List + ) + + => + + void ~> K + invariantStateFull( + NumUsers, + UserIdToAddress, + AddressToUserId, + NumBoardMembers, + NumProposers, + UserIdToRole, + Quorum, + u(ActionLastIndex), + ActionData, + ActionId |-> [#listSwapRemove(Signers, #listFind([Signers], UserId))] ActionSigners, + CallerAddress, + Stack:Stack, + ?_Variables, + PerformedActions:List + ):StateCell + + requires true + andBool isKResult(Action) + andBool valueIsNotEmpty(Action, rAction) + andBool isKResult(Signers) + + andBool #listFind([Signers], UserId) >=Int 0 + // andBool pListLen([Signers]) >=Int 2 + ensures true + //@ proof + //@ trusted + // [trusted] + //@ end +endmodule diff --git a/multisig/protocol-correctness/proof/functions/proof-unsign-other-signers-not-first.k b/multisig/protocol-correctness/proof/functions/proof-unsign-other-signers-not-first.k new file mode 100644 index 000000000..adba9d5ce --- /dev/null +++ b/multisig/protocol-correctness/proof/functions/proof-unsign-other-signers-not-first.k @@ -0,0 +1,62 @@ +//@ proof +module PROOF-UNSIGN-OTHER-SIGNERS-NOT-FIRST + imports FUNCTIONS-EXECUTE +//@ trusted +// module TRUSTED-UNSIGN-OTHER-SIGNERS-NOT-FIRST + // imports EXECUTION-PROOF +//@ end + + claim + call(unsign(ActionId:Usize)) ~> K:K + + invariantStateFull( + NumUsers:Usize, + UserIdToAddress:Map, + (CallerAddress |-> UserId:Usize _AddressToUserId:Map) #as AddressToUserId:Map, + NumBoardMembers:Usize, + NumProposers:Usize, + (UserId |-> BoardMember _UserIdToRole:Map) #as UserIdToRole:Map, + Quorum:Usize, + u(ActionLastIndex:Int), + (ActionId |-> Action:Action _ActionData:Map) #as ActionData:Map, + ActionId |-> [(First:Usize, _Signers:ExpressionCSV) #as Signers:ExpressionCSV] ActionSigners:Map, + CallerAddress:Address, + Stack:Stack, + .Map, + PerformedActions:List + ) + + => + + void ~> K + invariantStateFull( + NumUsers, + UserIdToAddress, + AddressToUserId, + NumBoardMembers, + NumProposers, + UserIdToRole, + Quorum, + u(ActionLastIndex), + ActionData, + ActionId |-> [#listSwapRemove(Signers, #listFind([Signers], UserId))] ActionSigners, + CallerAddress, + Stack:Stack, + ?_Variables, + PerformedActions:List + ):StateCell + + requires true + andBool isKResult(Action) + andBool valueIsNotEmpty(Action, rAction) + andBool isKResult(Signers) + + andBool #listFind([Signers], UserId) >=Int 0 + andBool notBool First ==K UserId // TODO: Combine with the above. + // andBool pListLen([Signers]) >=Int 2 + ensures true + //@ proof + //@ trusted + // [trusted] + //@ end +endmodule diff --git a/multisig/protocol-correctness/proof/invariant.k b/multisig/protocol-correctness/proof/invariant.k new file mode 100644 index 000000000..13dbac42a --- /dev/null +++ b/multisig/protocol-correctness/proof/invariant.k @@ -0,0 +1,397 @@ +require "protocol-correctness/proof/execution-proof-helpers.k" + +module INVARIANT-HELPERS + imports EXECUTION-PROOF-HELPERS + + syntax Bool ::= addressToUserIdInvariant(addressToUserId:Map) + [function, functional] + + rule addressToUserIdInvariant(.Map) => true + + rule addressToUserIdInvariant(_:KItem |-> V:KItem AddressToUserId:Map) + => true + andBool valueOfType(V, rUsize) // valuesAreOfType(AddressToUserId, rUsize) + andBool isKResult(V) // valuesAreKResult(AddressToUserId) + andBool valueIsNotEmpty(V, rUsize) // valuesAreNotEmpty(AddressToUserId, rUsize) + andBool valueNotInMapValues(V, AddressToUserId) // valuesAreDistinct(AddressToUserId) + + andBool addressToUserIdInvariant(AddressToUserId) + [simplification] + + + syntax Bool ::= userIdToRoleInvariant(userIdToRole:Map) + [function, functional] + + rule userIdToRoleInvariant(.Map) => true + + rule userIdToRoleInvariant(_:KItem |-> V:KItem UserIdToRole:Map) + => true + andBool valueOfType(V, rUserRole) // valuesAreOfType(UserIdToRole, rUserRole) + andBool isKResult(V) // valuesAreKResult(UserIdToRole) + andBool valueIsNotEmpty(V, rUserRole) // valuesAreNotEmpty(UserIdToRole, rUserRole) + + andBool userIdToRoleInvariant(UserIdToRole:Map) + [simplification] + + + syntax Bool ::= actionDataInvariant(actionData:Map) + [function, functional] + rule actionDataInvariant(.Map) => true + rule actionDataInvariant(_:KItem |-> V:KItem ActionData:Map) + => true + andBool valueOfType(V, rAction) // valuesAreOfType(ActionData, rAction) + andBool isKResult(V) // valuesAreKResult(ActionData) + andBool valueIsNotEmpty(V, rAction) // valuesAreNotEmpty(ActionData, rAction) + + andBool actionDataInvariant(ActionData) + [simplification] + + + syntax Bool ::= actionSignersInvariant(actionSigners:Map) + [function, functional] + rule actionSignersInvariant(.Map) => true + rule actionSignersInvariant(_:KItem |-> V:KItem ActionSigners:Map) + => true + andBool isExpressionList(V) andBool listElementsAreUsize(V) // valuesAreExpressionListOfUsize(ActionSigners) + andBool isKResult(V) // valuesAreKResult(ActionSigners) + andBool valueIsNotEmpty(V, rExpressionList) // valuesAreNotEmpty(ActionSigners, rExpressionList) + andBool listElementsAreDistinct(V) + + andBool actionSignersInvariant(ActionSigners) + [simplification] +endmodule + +module INVARIANT + imports EXECUTION-PROOF-HELPERS + imports PSEUDOCODE + imports INVARIANT-HELPERS + + syntax StateCell ::= invariantState( + /*numUsers:*/Usize, + /*userIdToAddress:*/Map, + /*addressToUserId:*/Map, + /*numBoardMembers:*/Usize, + /*numProposers:*/Usize, + /*userIdToRole:*/Map, + /*quorum:*/Usize, + /*actionLastIndex:*/Usize, + /*actionData:*/Map, + /*actionSigners:*/Map, + /*performedActions:*/List) [function, functional] + + syntax MultisigStateCell ::= invariantMultisigState( + /*numUsers:*/Usize, + /*userIdToAddress:*/Map, + /*addressToUserId:*/Map, + /*numBoardMembers:*/Usize, + /*numProposers:*/Usize, + /*userIdToRole:*/Map, + /*quorum:*/Usize, + /*actionLastIndex:*/Usize, + /*actionData:*/Map, + /*actionSigners:*/Map) [function, functional] + + syntax StateCell ::= invariantStateStack( + /*numUsers:*/Usize, + /*userIdToAddress:*/Map, + /*addressToUserId:*/Map, + /*numBoardMembers:*/Usize, + /*numProposers:*/Usize, + /*userIdToRole:*/Map, + /*quorum:*/Usize, + /*actionLastIndex:*/Usize, + /*actionData:*/Map, + /*actionSigners:*/Map, + /*callerAddress:*/KItem, + /*stack:*/Stack, + /*performedActions:*/List) [function, functional] + + syntax StateCell ::= invariantStateFull( + /*numUsers:*/Usize, + /*userIdToAddress:*/Map, + /*addressToUserId:*/Map, + /*numBoardMembers:*/Usize, + /*numProposers:*/Usize, + /*userIdToRole:*/Map, + /*quorum:*/Usize, + /*actionLastIndex:*/Usize, + /*actionData:*/Map, + /*actionSigners:*/Map, + /*callerAddress:*/KItem, + /*stack:*/Stack, + /*variables:*/Map, + /*performedActions:*/List) [function, functional] + + rule invariantState( + NumUsers:Usize, + UserIdToAddress:Map, + AddressToUserId:Map, + NumBoardMembers:Usize, + NumProposers:Usize, + UserIdToRole:Map, + Quorum:Usize, + ActionLastIndex:Usize, + ActionData:Map, + ActionSigners:Map, + PerformedActions:List) + => + invariantStateStack( + NumUsers, + UserIdToAddress, + AddressToUserId, + NumBoardMembers, + NumProposers, + UserIdToRole, + Quorum, + ActionLastIndex, + ActionData, + ActionSigners, + uninitialized, + .stack, + PerformedActions) + + rule invariantStateStack( + NumUsers:Usize, + UserIdToAddress:Map, + AddressToUserId:Map, + NumBoardMembers:Usize, + NumProposers:Usize, + UserIdToRole:Map, + Quorum:Usize, + ActionLastIndex:Usize, + ActionData:Map, + ActionSigners:Map, + CallerAddress:KItem, + Stack:Stack, + PerformedActions:List) + => invariantStateFull( + NumUsers, + UserIdToAddress, + AddressToUserId, + NumBoardMembers, + NumProposers, + UserIdToRole, + Quorum, + ActionLastIndex, + ActionData, + ActionSigners, + CallerAddress, + Stack, + .Map, + PerformedActions) + + rule invariantStateFull( + NumUsers:Usize, + UserIdToAddress:Map, + AddressToUserId:Map, + NumBoardMembers:Usize, + NumProposers:Usize, + UserIdToRole:Map, + Quorum:Usize, + ActionLastIndex:Usize, + ActionData:Map, + ActionSigners:Map, + CallerAddress:KItem, + Stack:Stack, + Variables:Map, + PerformedActions:List) + => + + invariantMultisigState( + NumUsers, + UserIdToAddress, + AddressToUserId, + NumBoardMembers, + NumProposers, + UserIdToRole, + Quorum, + ActionLastIndex, + ActionData, + ActionSigners):MultisigStateCell + + Variables + Stack + + + CallerAddress + + + PerformedActions + + + + rule invariantMultisigState( + NumUsers:Usize, + UserIdToAddress:Map, + AddressToUserId:Map, + NumBoardMembers:Usize, + NumProposers:Usize, + UserIdToRole:Map, + Quorum:Usize, + ActionLastIndex:Usize, + ActionData:Map, + ActionSigners:Map) + => + + + NumUsers + UserIdToAddress + AddressToUserId + + + NumBoardMembers + NumProposers + UserIdToRole + Quorum + + + ActionLastIndex + + ActionData + ActionSigners + + + + + syntax Bool ::= invariant( + numUsers:Usize, + userIdToAddress:Map, + addressToUserId:Map, + numBoardMembers:Usize, + numProposers:Usize, + userIdToRole:Map, + quorum:Usize, + actionLastIndex:Usize, + actionData:Map, + actionSigners:Map, + handling:PropertyHandling) [function, functional] + + rule invariant( + u(NumUsers:Int), + UserIdToAddress:Map, + AddressToUserId:Map, + u(NumBoardMembers:Int), + u(NumProposers:Int), + UserIdToRole:Map, + u(Quorum:Int), + u(ActionLastIndex:Int), + ActionData:Map, + ActionSigners:Map, + Handling:PropertyHandling) + => true + andBool notBool u(0) in_keys(UserIdToAddress) + andBool notBool u(0) in_keys(UserIdToRole) + + andBool allValuesBecomeKeys(AddressToUserId, UserIdToAddress) + andBool allValuesBecomeKeys(UserIdToAddress, AddressToUserId) + + andBool addressToUserIdInvariant(AddressToUserId) + // andBool valuesAreOfType(AddressToUserId, rUsize) + // andBool valuesAreKResult(AddressToUserId) + // andBool valuesAreNotEmpty(AddressToUserId, rUsize) + // andBool valuesAreDistinct(AddressToUserId) + // TODO: Is unusedIdsInMapValues the same as noReusedIndexValue? + andBool unusedIdsInMapValues(NumUsers +Int 1, AddressToUserId, Handling) + andBool noReusedIndexValue(NumUsers +Int 1, AddressToUserId, Handling) + + andBool unusedIdsInMapKeys(NumUsers +Int 1, keysMap(UserIdToAddress), Handling) + + andBool userIdToRoleInvariant(UserIdToRole) + // andBool valuesAreOfType(UserIdToRole, rUserRole) + // andBool valuesAreKResult(UserIdToRole) + // andBool valuesAreNotEmpty(UserIdToRole, rUserRole) + andBool unusedIdsInMapKeys(NumUsers +Int 1, keysMap(UserIdToRole), Handling) + + andBool unusedIdsInMapKeys(ActionLastIndex +Int 1, keysMap(ActionData), Handling) + andBool unusedIdsInMapKeys(ActionLastIndex +Int 1, keysMap(ActionSigners), Handling) + andBool maxMapKey(u(ActionLastIndex), keysMap(ActionData)) + andBool maxMapKey(u(ActionLastIndex), keysMap(ActionSigners)) + + andBool actionSignersInvariant(ActionSigners) + // andBool valuesAreExpressionListOfUsize(ActionSigners) + // andBool valuesAreKResult(ActionSigners) + // andBool valuesAreExpressionListOfDistinctElements(ActionSigners) + + andBool actionDataInvariant(ActionData) + // andBool valuesAreOfType(ActionData, rAction) + // andBool valuesAreKResult(ActionData) + + andBool NumUsers >=Int 0 // TODO: Strict >? + andBool NumBoardMembers >=Int 0 + andBool NumProposers >=Int 0 + + andBool Quorum <=Int NumBoardMembers + andBool (NumBoardMembers +Int NumProposers >Int 0) + + andBool NumBoardMembers ==Int countMapValues(UserIdToRole, wrap(BoardMember)) + andBool NumProposers ==Int countMapValues(UserIdToRole, wrap(Proposer)) + + // TODO: Maybe move somewhere else. + rule valuesAreOfType(M:Map, rUsize) => true + requires addressToUserIdInvariant(M) + rule valuesAreOfType(M:Map, rUserRole) => true + requires userIdToRoleInvariant(M) + rule valuesAreOfType(M:Map, rAction) => true + requires actionDataInvariant(M) + rule valuesAreKResult(M:Map) => true + requires false + orBool addressToUserIdInvariant(M) + orBool userIdToRoleInvariant(M) + orBool actionSignersInvariant(M) + orBool actionDataInvariant(M) + rule valuesAreNotEmpty(M:Map, rUsize) => true + requires false + orBool addressToUserIdInvariant(M) + rule valuesAreNotEmpty(M:Map, rUserRole) => true + requires false + orBool userIdToRoleInvariant(M) + rule valuesAreExpressionListOfUsize(M:Map) => true + requires false + orBool actionSignersInvariant(M) + rule valuesAreDistinct(M:Map) => true + requires false + orBool addressToUserIdInvariant(M) + + syntax Bool ::= subset(Map, Map) [function, functional] + rule subset(K:KItem |-> _:KItem M:Map, N:Map) + => K in_keys(N) andBool subset(M, N) + [simplification] + rule subset(M:Map, _:KItem |-> _:KItem N:Map) + => true + requires subset(M, N) + [simplification] + + syntax Bool ::= maxMapKey(lastIndex:Usize, Map) [function, functional] + rule maxMapKey(_:Usize, .Map) => true + rule maxMapKey(u(V:Int), u(K:Int) |-> _:KItem M:Map) + => (K <=Int V) andBool maxMapKey(u(V), M) + rule maxMapKey(u(V:Int), u(K:Int) |-> _:KItem M:Map) + => (K <=Int V) andBool maxMapKey(u(V), M) + [simplification] + rule maxMapKey(u(V:Int +Int 1), M:Map) + => true + requires maxMapKey(u(V:Int), M:Map) + [simplification] + + rule isKResult(#pushList(Es:ExpressionCSV, E:Expression)) + => isKResult(Es) andBool isKResult(E) + [simplification] + + rule listElementsAreUsize([#pushList(Es:ExpressionCSV, E:Expression)]) + => listElementsAreUsize([Es]) andBool isUsize(E) + [simplification] + + rule isKResult(#listSwapRemove(Es:ExpressionCSV, _:Int)) + => isKResult(Es) + [simplification] + + // TODO: This is wrong, although it works in practice. + rule listElementsAreUsize([#listSwapRemove(Es:ExpressionCSV, _:Int)]) + => listElementsAreUsize([Es]) + [simplification] + + rule A:Int +Int K:Int >Int B:Int => true + requires K >Int 0 andBool A >=Int B + [simplification] + +endmodule diff --git a/multisig/protocol-correctness/proof/invariant/BUILD b/multisig/protocol-correctness/proof/invariant/BUILD new file mode 100644 index 000000000..2d646a330 --- /dev/null +++ b/multisig/protocol-correctness/proof/invariant/BUILD @@ -0,0 +1,894 @@ +load("//:proof.bzl", "kompile", "kprove_test", "ktrusted", "klibrary", "kore_test", "kprove_kompile") + +kompile( + name = "invariant-execution", + srcs = ["invariant-execution.k"], + deps = [ + ":count-can-sign-parts-files", + ":init-loop-parts-files", + ":perform-parts-files", + "//protocol-correctness/proof:execution-proof-files", + "//protocol-correctness/proof/functions:functions-execute-files", + ], +) + +klibrary( + name = "invariant-execution-files", + srcs = ["invariant-execution.k"], + deps = [ + ":count-can-sign-parts-files", + ":init-loop-parts-files", + ":perform-parts-files", + "//protocol-correctness/proof:execution-proof-files", + "//protocol-correctness/proof/functions:functions-execute-files", + ], + visibility = ["//visibility:public"], +) + +# TODO: Delete. +klibrary( + name = "count-can-sign-parts-files", + srcs = ["count-can-sign-parts.k"], + deps = [ + "//protocol-correctness/proof:execution-proof-helpers-files", + "//protocol-correctness/proof:invariant-files", + "//protocol-correctness:pseudocode-files", + ], +) + +klibrary( + name = "init-loop-parts-files", + srcs = ["init-loop-parts.k"], + deps = [ + "//protocol-correctness/proof:execution-proof-helpers-files", + "//protocol-correctness/proof:invariant-files", + "//protocol-correctness:pseudocode-files", + ], +) + +# TODO: Delete. +klibrary( + name = "perform-parts-files", + srcs = ["perform-parts.k"], + deps = [ + "//protocol-correctness/proof:execution-proof-helpers-files", + "//protocol-correctness/proof:invariant-files", + "//protocol-correctness:pseudocode-files", + ], +) + +# kprove_test( +# name = "proof-discard-action", +# srcs = ["proof-discard-action.k"], +# trusted = [ +# "//protocol-correctness/proof/functions:trusted-discard-action-has-signers", +# "//protocol-correctness/proof/functions:trusted-discard-action-no-role", +# "//protocol-correctness/proof/functions:trusted-discard-action-no-signers", +# "//protocol-correctness/proof/functions:trusted-discard-action-no-signers-no-action", +# "//protocol-correctness/proof/functions:trusted-discard-action-no-user", +# "//protocol-correctness/proof/functions:trusted-discard-action-no-valid-signers", +# "//protocol-correctness/proof/functions:trusted-discard-action-no-valid-signers-no-action", +# ], +# semantics = ":invariant-execution", +# ) + +kprove_test( + name = "proof-perform-action-endpoint", + srcs = ["proof-perform-action-endpoint.k"], + trusted = [ + ":trusted-perform-parts-1", + #":trusted-perform-parts-add-board-member", + # ":trusted-perform-parts-add-proposer", + # ":trusted-perform-parts-change-quorum-with-quorum", + # ":trusted-perform-parts-change-quorum-no-quorum", + # ":trusted-perform-parts-New", + # ":trusted-perform-parts-no-quorum", + # ":trusted-perform-parts-None", + # ":trusted-perform-parts-Nothing", + # ":trusted-perform-parts-remove-user", + # ":trusted-perform-parts-sc-call", + # ":trusted-perform-parts-sc-deploy", + # ":trusted-perform-parts-send-egld", + ], + semantics = ":invariant-execution", +) + +kprove_test( + name = "proof-perform-parts-1", + srcs = ["proof-perform-parts-1.k"], + trusted = [ + ":trusted-perform-parts-add-board-member", + ":trusted-perform-parts-add-proposer-signers", + ":trusted-perform-parts-add-proposer-no-signers", + ":trusted-perform-parts-change-quorum", + ":trusted-perform-parts-New", + ":trusted-perform-parts-no-quorum", + ":trusted-perform-parts-None", + ":trusted-perform-parts-remove-user", + ":trusted-perform-parts-sc-call", + ":trusted-perform-parts-sc-deploy", + ":trusted-perform-parts-send-egld", + ], + semantics = ":invariant-execution", + timeout = "eternal", + breadth = "7", + #depth ??? +) + +kprove_test( + name = "proof-perform-parts-change-quorum", + srcs = ["proof-perform-parts-change-quorum.k"], + trusted = [ + ":trusted-perform-parts-change-quorum-with-quorum", + ":trusted-perform-parts-change-quorum-no-quorum", + ], + semantics = ":invariant-execution", + timeout = "eternal", + breadth = "6", + # depth = 21 +) + +kprove_test( + name = "proof-perform-parts-change-quorum-with-quorum", + srcs = ["proof-perform-parts-change-quorum-with-quorum.k"], + trusted = [ + "//protocol-correctness/proof/functions:trusted-perform-action-endpoint-change-quorum", + ], + semantics = ":invariant-execution", +) + +kprove_test( + name = "proof-perform-parts-change-quorum-no-quorum", + srcs = ["proof-perform-parts-change-quorum-no-quorum.k"], + trusted = [ + "//protocol-correctness/proof/functions:trusted-perform-action-endpoint-change-quorum-no-quorum", + ], + semantics = ":invariant-execution", +) + +kprove_test( + name = "proof-perform-parts-New", + srcs = ["proof-perform-parts-New.k"], + trusted = [ + "//protocol-correctness/proof/functions:trusted-perform-action-endpoint-New", + ], + semantics = ":invariant-execution", +) + +kprove_test( + name = "proof-perform-parts-None", + srcs = ["proof-perform-parts-None.k"], + trusted = [ + "//protocol-correctness/proof/functions:trusted-perform-action-endpoint-None", + ], + semantics = ":invariant-execution", +) + +kprove_test( + name = "proof-perform-parts-no-quorum", + srcs = ["proof-perform-parts-no-quorum.k"], + trusted = [ + "//protocol-correctness/proof/functions:trusted-perform-action-endpoint-no-quorum", + ], + semantics = ":invariant-execution", +) + +kprove_test( + name = "proof-perform-parts-nothing", + srcs = ["proof-perform-parts-nothing.k"], + trusted = [ + "//protocol-correctness/proof/functions:trusted-perform-action-endpoint-nothing", + ], + semantics = ":invariant-execution", +) + +kprove_test( + name = "proof-perform-parts-sc-call", + srcs = ["proof-perform-parts-sc-call.k"], + trusted = [ + "//protocol-correctness/proof/functions:trusted-perform-action-endpoint-sc-call", + ], + semantics = ":invariant-execution", +) + +kprove_test( + name = "proof-perform-parts-sc-deploy", + srcs = ["proof-perform-parts-sc-deploy.k"], + trusted = [ + "//protocol-correctness/proof/functions:trusted-perform-action-endpoint-sc-deploy", + ], + semantics = ":invariant-execution", +) + +kprove_test( + name = "proof-perform-parts-send-egld", + srcs = ["proof-perform-parts-send-egld.k"], + trusted = [ + "//protocol-correctness/proof/functions:trusted-perform-action-endpoint-send-egld", + ], + semantics = ":invariant-execution", +) + +kprove_test( + name = "proof-perform-parts-add-board-member", + srcs = ["proof-perform-parts-add-board-member.k"], + trusted = [ + "trusted-perform-parts-add-board-member-eq", + "trusted-perform-parts-add-board-member-neq", + ":trusted-perform-parts-add-board-member-new", + ":trusted-perform-parts-add-board-member-none", + ], + semantics = ":invariant-execution", + timeout = "eternal", + breadth = "9", # 0 + # 57 states +) + +kprove_test( + name = "proof-perform-parts-add-board-member-eq", + srcs = ["proof-perform-parts-add-board-member-eq.k"], + trusted = [ + ":trusted-perform-parts-add-board-member-boardmember-eq", + ":trusted-perform-parts-add-board-member-proposer-eq", + ], + semantics = ":invariant-execution", + timeout = "long", + breadth = "6", # 0 +) + +kprove_test( + name = "proof-perform-parts-add-board-member-neq", + srcs = ["proof-perform-parts-add-board-member-neq.k"], + trusted = [ + ":trusted-perform-parts-add-board-member-boardmember", + ":trusted-perform-parts-add-board-member-proposer", + ], + semantics = ":invariant-execution", + timeout = "eternal", + breadth = "7", # 0 + # depth = ~27 +) + +kprove_test( + name = "proof-perform-parts-add-proposer-signers", + srcs = ["proof-perform-parts-add-proposer-signers.k"], + trusted = [ + ":trusted-perform-parts-add-proposer-signers-eq", + ":trusted-perform-parts-add-proposer-signers-neq", + ":trusted-perform-parts-add-proposer-New", + ":trusted-perform-parts-add-proposer-None", + ], + semantics = ":invariant-execution", + timeout = "eternal", + breadth = "5", + # depth = ~25 +) + +kprove_test( + name = "proof-perform-parts-add-proposer-signers-eq", + srcs = ["proof-perform-parts-add-proposer-signers-eq.k"], + trusted = [ + ":trusted-perform-parts-add-proposer-BoardMember-eq", + ":trusted-perform-parts-add-proposer-BoardMember-no-quorum-eq", + ":trusted-perform-parts-add-proposer-Proposer-eq", + ], + semantics = ":invariant-execution", + timeout = "eternal", + breadth = "3", + # depth = ~32 +) + +kprove_test( + name = "proof-perform-parts-add-proposer-signers-neq", + srcs = ["proof-perform-parts-add-proposer-signers-neq.k"], + trusted = [ + ":trusted-perform-parts-add-proposer-BoardMember-no-quorum", + ":trusted-perform-parts-add-proposer-BoardMember", + ":trusted-perform-parts-add-proposer-Proposer", + ], + semantics = ":invariant-execution", + timeout = "eternal", + breadth = "4", + # depth = ~35 +) + +kprove_test( + name = "proof-perform-parts-add-proposer-no-signers", + srcs = ["proof-perform-parts-add-proposer-no-signers.k"], + trusted = [ + ":trusted-perform-parts-add-proposer-no-signers-eq", + ":trusted-perform-parts-add-proposer-no-signers-neq", + ":trusted-perform-parts-add-proposer-New", + ":trusted-perform-parts-add-proposer-None", + ], + timeout = "eternal", + semantics = ":invariant-execution", + breadth = "5", + # depth = ~25 +) + +kprove_test( + name = "proof-perform-parts-add-proposer-no-signers-eq", + srcs = ["proof-perform-parts-add-proposer-no-signers-eq.k"], + trusted = [ + ":trusted-perform-parts-add-proposer-BoardMember-eq", + ":trusted-perform-parts-add-proposer-BoardMember-no-quorum-eq", + ":trusted-perform-parts-add-proposer-Proposer-eq", + ], + semantics = ":invariant-execution", + timeout = "eternal", + breadth = "2", + # depth = ~22 +) + +kprove_test( + name = "proof-perform-parts-add-proposer-no-signers-neq", + srcs = ["proof-perform-parts-add-proposer-no-signers-neq.k"], + trusted = [ + ":trusted-perform-parts-add-proposer-BoardMember-no-quorum", + ":trusted-perform-parts-add-proposer-BoardMember", + ":trusted-perform-parts-add-proposer-Proposer", + ], + semantics = ":invariant-execution", + timeout = "eternal", + breadth = "3", + # depth = ~23 +) + +kprove_test( + name = "proof-perform-parts-remove-user", + srcs = ["proof-perform-parts-remove-user.k"], + trusted = [ + ":trusted-perform-parts-remove-user-eq", + ":trusted-perform-parts-remove-user-neq", + ":trusted-perform-parts-remove-user-New", + ":trusted-perform-parts-remove-user-None", + ], + semantics = ":invariant-execution", + timeout = "eternal", + breadth = "9", + # depth = 32 +) + +kprove_test( + name = "proof-perform-parts-remove-user-eq", + srcs = ["proof-perform-parts-remove-user-eq.k"], + trusted = [ + ":trusted-perform-parts-remove-user-BoardMember-eq", + ":trusted-perform-parts-remove-user-BoardMember-too-few-eq", + ":trusted-perform-parts-remove-user-Proposer-eq", + ":trusted-perform-parts-remove-user-Proposer-nobody-left-eq", + ], + semantics = ":invariant-execution", + timeout = "eternal", + breadth = "12", + # depth = ~24 +) + +kprove_test( + name = "proof-perform-parts-remove-user-neq", + srcs = ["proof-perform-parts-remove-user-neq.k"], + trusted = [ + ":trusted-perform-parts-remove-user-BoardMember", + ":trusted-perform-parts-remove-user-BoardMember-too-few", + ":trusted-perform-parts-remove-user-Proposer", + ":trusted-perform-parts-remove-user-Proposer-nobody-left", + ], + semantics = ":invariant-execution", + timeout = "eternal", + breadth = "13", + # depth = ~25 +) + +kprove_test( + name = "proof-perform-parts-add-board-member-boardmember-eq", + srcs = ["proof-perform-parts-add-board-member-boardmember-eq.k"], + trusted = [ + "//protocol-correctness/proof/functions:trusted-perform-action-endpoint-add-board-member-BoardMember-eq", + ], + semantics = ":invariant-execution", +) + +kprove_test( + name = "proof-perform-parts-add-board-member-boardmember", + srcs = ["proof-perform-parts-add-board-member-boardmember.k"], + trusted = [ + "//protocol-correctness/proof/functions:trusted-perform-action-endpoint-add-board-member-BoardMember", + ], + semantics = ":invariant-execution", +) + +kprove_test( + name = "proof-perform-parts-add-board-member-new", + srcs = ["proof-perform-parts-add-board-member-new.k"], + trusted = [ + "//protocol-correctness/proof/functions:trusted-perform-action-endpoint-add-board-member-New", + ], + semantics = ":invariant-execution", +) + +kprove_test( + name = "proof-perform-parts-add-board-member-none", + srcs = ["proof-perform-parts-add-board-member-none.k"], + trusted = [ + "//protocol-correctness/proof/functions:trusted-perform-action-endpoint-add-board-member-None", + ], + semantics = ":invariant-execution", +) + +kprove_test( + name = "proof-perform-parts-add-board-member-proposer-eq", + srcs = ["proof-perform-parts-add-board-member-proposer-eq.k"], + trusted = [ + "//protocol-correctness/proof/functions:trusted-perform-action-endpoint-add-board-member-Proposer-eq", + ], + semantics = ":invariant-execution", +) + +kprove_test( + name = "proof-perform-parts-add-board-member-proposer", + srcs = ["proof-perform-parts-add-board-member-proposer.k"], + trusted = [ + "//protocol-correctness/proof/functions:trusted-perform-action-endpoint-add-board-member-Proposer", + ], + semantics = ":invariant-execution", +) + +kprove_test( + name = "proof-perform-parts-add-proposer-BoardMember-eq", + srcs = ["proof-perform-parts-add-proposer-BoardMember-eq.k"], + trusted = [ + "//protocol-correctness/proof/functions:trusted-perform-action-endpoint-add-proposer-BoardMember-eq", + ], + semantics = ":invariant-execution", +) + +kprove_test( + name = "proof-perform-parts-add-proposer-BoardMember", + srcs = ["proof-perform-parts-add-proposer-BoardMember.k"], + trusted = [ + "//protocol-correctness/proof/functions:trusted-perform-action-endpoint-add-proposer-BoardMember", + ], + semantics = ":invariant-execution", +) + +kprove_test( + name = "proof-perform-parts-add-proposer-BoardMember-no-quorum-eq", + srcs = ["proof-perform-parts-add-proposer-BoardMember-no-quorum-eq.k"], + trusted = [ + "//protocol-correctness/proof/functions:trusted-perform-action-endpoint-add-proposer-BoardMember-no-quorum-eq", + ], + semantics = ":invariant-execution", +) + +kprove_test( + name = "proof-perform-parts-add-proposer-BoardMember-no-quorum", + srcs = ["proof-perform-parts-add-proposer-BoardMember-no-quorum.k"], + trusted = [ + "//protocol-correctness/proof/functions:trusted-perform-action-endpoint-add-proposer-BoardMember-no-quorum", + ], + semantics = ":invariant-execution", +) + +kprove_test( + name = "proof-perform-parts-add-proposer-New", + srcs = ["proof-perform-parts-add-proposer-New.k"], + trusted = [ + "//protocol-correctness/proof/functions:trusted-perform-action-endpoint-add-proposer-New", + ], + semantics = ":invariant-execution", +) + +kprove_test( + name = "proof-perform-parts-add-proposer-None", + srcs = ["proof-perform-parts-add-proposer-None.k"], + trusted = [ + "//protocol-correctness/proof/functions:trusted-perform-action-endpoint-add-proposer-None", + ], + semantics = ":invariant-execution", +) + +kprove_test( + name = "proof-perform-parts-add-proposer-Proposer-eq", + srcs = ["proof-perform-parts-add-proposer-Proposer-eq.k"], + trusted = [ + "//protocol-correctness/proof/functions:trusted-perform-action-endpoint-add-proposer-Proposer-eq", + ], + semantics = ":invariant-execution", +) + +kprove_test( + name = "proof-perform-parts-add-proposer-Proposer", + srcs = ["proof-perform-parts-add-proposer-Proposer.k"], + trusted = [ + "//protocol-correctness/proof/functions:trusted-perform-action-endpoint-add-proposer-Proposer", + ], + semantics = ":invariant-execution", +) + +kprove_test( + name = "proof-perform-parts-remove-user-BoardMember-eq", + srcs = ["proof-perform-parts-remove-user-BoardMember-eq.k"], + trusted = [ + "//protocol-correctness/proof/functions:trusted-perform-action-endpoint-remove-user-BoardMember-eq", + ], + semantics = ":invariant-execution", +) + +kprove_test( + name = "proof-perform-parts-remove-user-BoardMember", + srcs = ["proof-perform-parts-remove-user-BoardMember.k"], + trusted = [ + "//protocol-correctness/proof/functions:trusted-perform-action-endpoint-remove-user-BoardMember", + ], + semantics = ":invariant-execution", +) + +kprove_test( + name = "proof-perform-parts-remove-user-BoardMember-too-few-eq", + srcs = ["proof-perform-parts-remove-user-BoardMember-too-few-eq.k"], + trusted = [ + "//protocol-correctness/proof/functions:trusted-perform-action-endpoint-remove-user-BoardMember-too-few-eq", + ], + semantics = ":invariant-execution", +) + +kprove_test( + name = "proof-perform-parts-remove-user-BoardMember-too-few", + srcs = ["proof-perform-parts-remove-user-BoardMember-too-few.k"], + trusted = [ + "//protocol-correctness/proof/functions:trusted-perform-action-endpoint-remove-user-BoardMember-too-few", + ], + semantics = ":invariant-execution", +) + +kprove_test( + name = "proof-perform-parts-remove-user-New", + srcs = ["proof-perform-parts-remove-user-New.k"], + trusted = [ + "//protocol-correctness/proof/functions:trusted-perform-action-endpoint-remove-user-New", + ], + semantics = ":invariant-execution", +) + +kprove_test( + name = "proof-perform-parts-remove-user-None", + srcs = ["proof-perform-parts-remove-user-None.k"], + trusted = [ + "//protocol-correctness/proof/functions:trusted-perform-action-endpoint-remove-user-None", + ], + semantics = ":invariant-execution", +) + +kprove_test( + name = "proof-perform-parts-remove-user-Proposer-eq", + srcs = ["proof-perform-parts-remove-user-Proposer-eq.k"], + trusted = [ + "//protocol-correctness/proof/functions:trusted-perform-action-endpoint-remove-user-Proposer-eq", + ], + semantics = ":invariant-execution", +) + +kprove_test( + name = "proof-perform-parts-remove-user-Proposer", + srcs = ["proof-perform-parts-remove-user-Proposer.k"], + trusted = [ + "//protocol-correctness/proof/functions:trusted-perform-action-endpoint-remove-user-Proposer", + ], + semantics = ":invariant-execution", +) + +kprove_test( + name = "proof-perform-parts-remove-user-Proposer-nobody-left-eq", + srcs = ["proof-perform-parts-remove-user-Proposer-nobody-left-eq.k"], + trusted = [ + "//protocol-correctness/proof/functions:trusted-perform-action-endpoint-remove-user-Proposer-nobody-left-eq", + ], + semantics = ":invariant-execution", +) + +kprove_test( + name = "proof-perform-parts-remove-user-Proposer-nobody-left", + srcs = ["proof-perform-parts-remove-user-Proposer-nobody-left.k"], + trusted = [ + "//protocol-correctness/proof/functions:trusted-perform-action-endpoint-remove-user-Proposer-nobody-left", + ], + semantics = ":invariant-execution", +) + +kprove_test( + name = "proof-propose-add-board-member", + srcs = ["proof-propose-add-board-member.k"], + trusted = [ + "//protocol-correctness/proof/functions:trusted-propose-action-BoardMember", + "//protocol-correctness/proof/functions:trusted-propose-action-Proposer", + "//protocol-correctness/proof/functions:trusted-propose-action-error-no-user", + "//protocol-correctness/proof/functions:trusted-propose-action-error-no-role", + ], + semantics = ":invariant-execution", + timeout = "eternal", + breadth = "4" # 0 +) + +ktrusted( + name = "trusted-perform-parts-add-board-member-boardmember-eq", + srcs = ["proof-perform-parts-add-board-member-boardmember-eq.k"], + visibility = ["//visibility:public"], +) + +ktrusted( + name = "trusted-perform-parts-add-board-member-boardmember", + srcs = ["proof-perform-parts-add-board-member-boardmember.k"], + visibility = ["//visibility:public"], +) + +ktrusted( + name = "trusted-perform-parts-add-board-member-new", + srcs = ["proof-perform-parts-add-board-member-new.k"], + visibility = ["//visibility:public"], +) + +ktrusted( + name = "trusted-perform-parts-add-board-member-none", + srcs = ["proof-perform-parts-add-board-member-none.k"], + visibility = ["//visibility:public"], +) + +ktrusted( + name = "trusted-perform-parts-add-board-member-proposer-eq", + srcs = ["proof-perform-parts-add-board-member-proposer-eq.k"], + visibility = ["//visibility:public"], +) + +ktrusted( + name = "trusted-perform-parts-add-board-member-proposer", + srcs = ["proof-perform-parts-add-board-member-proposer.k"], + visibility = ["//visibility:public"], +) + +ktrusted( + name = "trusted-perform-parts-add-proposer-BoardMember-eq", + srcs = ["proof-perform-parts-add-proposer-BoardMember-eq.k"], + visibility = ["//visibility:public"], +) + +ktrusted( + name = "trusted-perform-parts-add-proposer-BoardMember-no-quorum-eq", + srcs = ["proof-perform-parts-add-proposer-BoardMember-no-quorum-eq.k"], + visibility = ["//visibility:public"], +) + +ktrusted( + name = "trusted-perform-parts-add-proposer-BoardMember-no-quorum", + srcs = ["proof-perform-parts-add-proposer-BoardMember-no-quorum.k"], + visibility = ["//visibility:public"], +) + +ktrusted( + name = "trusted-perform-parts-add-proposer-BoardMember", + srcs = ["proof-perform-parts-add-proposer-BoardMember.k"], + visibility = ["//visibility:public"], +) + +ktrusted( + name = "trusted-perform-parts-add-proposer-New", + srcs = ["proof-perform-parts-add-proposer-New.k"], + visibility = ["//visibility:public"], +) + +ktrusted( + name = "trusted-perform-parts-add-proposer-None", + srcs = ["proof-perform-parts-add-proposer-None.k"], + visibility = ["//visibility:public"], +) + +ktrusted( + name = "trusted-perform-parts-add-proposer-Proposer-eq", + srcs = ["proof-perform-parts-add-proposer-Proposer-eq.k"], + visibility = ["//visibility:public"], +) + +ktrusted( + name = "trusted-perform-parts-add-proposer-Proposer", + srcs = ["proof-perform-parts-add-proposer-Proposer.k"], + visibility = ["//visibility:public"], +) + +ktrusted( + name = "trusted-perform-parts-add-board-member-eq", + srcs = ["proof-perform-parts-add-board-member-eq.k"], + visibility = ["//visibility:public"], +) + +ktrusted( + name = "trusted-perform-parts-add-board-member-neq", + srcs = ["proof-perform-parts-add-board-member-neq.k"], + visibility = ["//visibility:public"], +) + +ktrusted( + name = "trusted-perform-parts-add-board-member", + srcs = ["proof-perform-parts-add-board-member.k"], + visibility = ["//visibility:public"], +) + +ktrusted( + name = "trusted-perform-parts-add-proposer-signers-eq", + srcs = ["proof-perform-parts-add-proposer-signers-eq.k"], + visibility = ["//visibility:public"], +) + +ktrusted( + name = "trusted-perform-parts-add-proposer-signers-neq", + srcs = ["proof-perform-parts-add-proposer-signers-neq.k"], + visibility = ["//visibility:public"], +) + +ktrusted( + name = "trusted-perform-parts-add-proposer-signers", + srcs = ["proof-perform-parts-add-proposer-signers.k"], + visibility = ["//visibility:public"], +) + +ktrusted( + name = "trusted-perform-parts-add-proposer-no-signers-eq", + srcs = ["proof-perform-parts-add-proposer-no-signers-eq.k"], + visibility = ["//visibility:public"], +) + +ktrusted( + name = "trusted-perform-parts-add-proposer-no-signers-neq", + srcs = ["proof-perform-parts-add-proposer-no-signers-neq.k"], + visibility = ["//visibility:public"], +) + +ktrusted( + name = "trusted-perform-parts-add-proposer-no-signers", + srcs = ["proof-perform-parts-add-proposer-no-signers.k"], + visibility = ["//visibility:public"], +) + +ktrusted( + name = "trusted-perform-parts-remove-user-BoardMember-eq", + srcs = ["proof-perform-parts-remove-user-BoardMember-eq.k"], + visibility = ["//visibility:public"], +) + +ktrusted( + name = "trusted-perform-parts-remove-user-BoardMember-too-few-eq", + srcs = ["proof-perform-parts-remove-user-BoardMember-too-few-eq.k"], + visibility = ["//visibility:public"], +) + +ktrusted( + name = "trusted-perform-parts-remove-user-BoardMember", + srcs = ["proof-perform-parts-remove-user-BoardMember.k"], + visibility = ["//visibility:public"], +) + +ktrusted( + name = "trusted-perform-parts-remove-user-BoardMember-too-few", + srcs = ["proof-perform-parts-remove-user-BoardMember-too-few.k"], + visibility = ["//visibility:public"], +) + +ktrusted( + name = "trusted-perform-parts-remove-user-New", + srcs = ["proof-perform-parts-remove-user-New.k"], + visibility = ["//visibility:public"], +) + +ktrusted( + name = "trusted-perform-parts-remove-user-None", + srcs = ["proof-perform-parts-remove-user-None.k"], + visibility = ["//visibility:public"], +) + +ktrusted( + name = "trusted-perform-parts-remove-user-Proposer-eq", + srcs = ["proof-perform-parts-remove-user-Proposer-eq.k"], + visibility = ["//visibility:public"], +) + +ktrusted( + name = "trusted-perform-parts-remove-user-Proposer-nobody-left-eq", + srcs = ["proof-perform-parts-remove-user-Proposer-nobody-left-eq.k"], + visibility = ["//visibility:public"], +) + +ktrusted( + name = "trusted-perform-parts-remove-user-Proposer", + srcs = ["proof-perform-parts-remove-user-Proposer.k"], + visibility = ["//visibility:public"], +) + +ktrusted( + name = "trusted-perform-parts-remove-user-Proposer-nobody-left", + srcs = ["proof-perform-parts-remove-user-Proposer-nobody-left.k"], + visibility = ["//visibility:public"], +) + +ktrusted( + name = "trusted-perform-parts-change-quorum-with-quorum", + srcs = ["proof-perform-parts-change-quorum-with-quorum.k"], + visibility = ["//visibility:public"], +) + +ktrusted( + name = "trusted-perform-parts-change-quorum-no-quorum", + srcs = ["proof-perform-parts-change-quorum-no-quorum.k"], + visibility = ["//visibility:public"], +) + +ktrusted( + name = "trusted-perform-parts-New", + srcs = ["proof-perform-parts-New.k"], + visibility = ["//visibility:public"], +) + +ktrusted( + name = "trusted-perform-parts-no-quorum", + srcs = ["proof-perform-parts-no-quorum.k"], + visibility = ["//visibility:public"], +) + +ktrusted( + name = "trusted-perform-parts-None", + srcs = ["proof-perform-parts-None.k"], + visibility = ["//visibility:public"], +) + +# ktrusted( +# name = "trusted-perform-parts-Nothing", +# srcs = ["proof-perform-parts-Nothing.k"], +# visibility = ["//visibility:public"], +# ) + +ktrusted( + name = "trusted-perform-parts-remove-user", + srcs = ["proof-perform-parts-remove-user.k"], + visibility = ["//visibility:public"], +) + +ktrusted( + name = "trusted-perform-parts-remove-user-eq", + srcs = ["proof-perform-parts-remove-user-eq.k"], + visibility = ["//visibility:public"], +) + +ktrusted( + name = "trusted-perform-parts-remove-user-neq", + srcs = ["proof-perform-parts-remove-user-neq.k"], + visibility = ["//visibility:public"], +) + +ktrusted( + name = "trusted-perform-parts-change-quorum", + srcs = ["proof-perform-parts-change-quorum.k"], + visibility = ["//visibility:public"], +) + +ktrusted( + name = "trusted-perform-parts-sc-call", + srcs = ["proof-perform-parts-sc-call.k"], + visibility = ["//visibility:public"], +) + +ktrusted( + name = "trusted-perform-parts-sc-deploy", + srcs = ["proof-perform-parts-sc-deploy.k"], + visibility = ["//visibility:public"], +) + +ktrusted( + name = "trusted-perform-parts-send-egld", + srcs = ["proof-perform-parts-send-egld.k"], + visibility = ["//visibility:public"], +) + +ktrusted( + name = "trusted-perform-parts-1", + srcs = ["proof-perform-parts-1.k"], + visibility = ["//visibility:public"], +) + diff --git a/multisig/protocol-correctness/proof/invariant/Makefile b/multisig/protocol-correctness/proof/invariant/Makefile new file mode 100644 index 000000000..2858ff861 --- /dev/null +++ b/multisig/protocol-correctness/proof/invariant/Makefile @@ -0,0 +1,48 @@ +include ../settings.mak + +.PHONY: default +default: all ; + +SCRIPT_DIR = .. + +PROOF_DIR = .. +include $(PROOF_DIR)/proof-dependency.mak + +FUNCTIONS_DIR = ../functions +include $(FUNCTIONS_DIR)/functions-dependency.mak + +INVARIANT_DIR = . +include $(INVARIANT_DIR)/invariant.mak + +INVARIANT_PERFORM = $(wildcard $(INVARIANT_DIR)/proof-perform-*.k) +FINVARIANT_PERFORM = $(filter-out $(INVARIANT_DIR)/proof-perform-action-endpoint.k, $(INVARIANT_PERFORM)) +INVARIANT_PERFORM_TIMESTAMPS = $(addprefix $(INVARIANT_OUT_PREFIX),$(notdir ${FINVARIANT_PERFORM:.k=.timestamp})) + +INVARIANT_PROPOSE = $(wildcard $(INVARIANT_DIR)/proof-propose-*.k) +INVARIANT_PROPOSE_TIMESTAMPS = $(addprefix $(INVARIANT_OUT_PREFIX),$(notdir ${INVARIANT_PROPOSE:.k=.timestamp})) + +.PHONY: all clean execution short perform + +all: $(INVARIANT_OUT_PREFIX)proof.timestamp + +execution: $(INVARIANT_OUT_PREFIX)execution.timestamp + +short: $(INVARIANT_OUT_PREFIX)short-proofs.timestamp + +perform: $(INVARIANT_OUT_PREFIX)proofperform.timestamp + +propose: $(INVARIANT_OUT_PREFIX)proofpropose.timestamp + +$(INVARIANT_OUT_PREFIX)short-proofs.timestamp: $(INVARIANT_OUT_PREFIX)proof-init-loop.timestamp $(INVARIANT_OUT_PREFIX)proof-count-can-sign.timestamp $(INVARIANT_OUT_PREFIX)proof-init.timestamp $(INVARIANT_OUT_PREFIX)proof-listlen.timestamp $(INVARIANT_OUT_PREFIX)proof-perform-add-proposer-1.timestamp $(INVARIANT_OUT_PREFIX)proof-perform-add-proposer-2.timestamp $(INVARIANT_OUT_PREFIX)proof-perform-add-proposer-3.timestamp $(INVARIANT_OUT_PREFIX)proof-perform-change-quorum.timestamp $(INVARIANT_OUT_PREFIX)proof-perform-nothing.timestamp $(INVARIANT_OUT_PREFIX)proof-perform-remove-user-1.timestamp $(INVARIANT_OUT_PREFIX)proof-perform-remove-user-2.timestamp $(INVARIANT_OUT_PREFIX)proof-perform-remove-user-5.timestamp $(INVARIANT_OUT_PREFIX)proof-perform-s-c-call.timestamp $(INVARIANT_OUT_PREFIX)proof-perform-s-c-deploy.timestamp $(INVARIANT_OUT_PREFIX)proof-perform-send-egld.timestamp $(INVARIANT_OUT_PREFIX)execution.timestamp + $(DIR_GUARD) + @touch $(INVARIANT_OUT_PREFIX)short-proof.timestamp + +$(INVARIANT_OUT_PREFIX)proofperform.timestamp: ${INVARIANT_PERFORM_TIMESTAMPS} $(INVARIANT_OUT_PREFIX)execution.timestamp + $(DIR_GUARD) + @touch $(INVARIANT_OUT_PREFIX)proofperform.timestamp + +$(INVARIANT_OUT_PREFIX)proofpropose.timestamp: ${INVARIANT_PROPOSE_TIMESTAMPS} $(INVARIANT_OUT_PREFIX)execution.timestamp + $(DIR_GUARD) + @touch $(INVARIANT_OUT_PREFIX)proofpropose.timestamp + +clean: invariant.clean diff --git a/multisig/protocol-correctness/proof/invariant/count-can-sign-parts.k b/multisig/protocol-correctness/proof/invariant/count-can-sign-parts.k new file mode 100644 index 000000000..e968baf61 --- /dev/null +++ b/multisig/protocol-correctness/proof/invariant/count-can-sign-parts.k @@ -0,0 +1,176 @@ +require "protocol-correctness/pseudocode.k" +require "protocol-correctness/proof/execution-proof-helpers.k" +require "protocol-correctness/proof/invariant.k" + +module COUNT-CAN-SIGN-PARTS + imports EXECUTION-PROOF-HELPERS + imports INVARIANT-HELPERS + imports PSEUDOCODE + + syntax TTCell ::= countCanSignLhs( + signerIds:ExpressionList, + K, + UsersCell, + numBoardMembers:Usize, + numProposers:Usize, + userIdToRole:Map, + quorum:Usize, + ActionStateCell, + variables:Map, + stack:Stack, + ExternalCallEnvCell, + performedActions:List) + [function, functional] + + rule countCanSignLhs( + SignerIds:ExpressionList, + K:K, + Users:UsersCell, + NumBoardMembers:Usize, + NumProposers:Usize, + UserIdToRole:Map, + Quorum:Usize, + ActionState:ActionStateCell, + Variables:Map, + Stack:Stack, + ExternalCallEnv:ExternalCallEnvCell, + PerformedActions:List) + => + + call(countCanSign(SignerIds)) + ~> K + + + + Users:UsersCell + + NumBoardMembers + NumProposers + UserIdToRole + Quorum + + ActionState + + + Variables + Stack + + ExternalCallEnv + + PerformedActions + + + + + syntax TTCell ::= countCanSignRhs( + count:Usize, + K, + UsersCell, + numBoardMembers:Usize, + numProposers:Usize, + userIdToRole:Map, + quorum:Usize, + ActionStateCell, + variables:Map, + stack:Stack, + ExternalCallEnvCell, + performedActions:List) + [function, functional] + + rule countCanSignRhs( + Count:Usize, + K:K, + Users:UsersCell, + NumBoardMembers:Usize, + NumProposers:Usize, + UserIdToRole:Map, + Quorum:Usize, + ActionState:ActionStateCell, + Variables:Map, + Stack:Stack, + ExternalCallEnv:ExternalCallEnvCell, + PerformedActions:List) + => + + evaluate(Count) ~> K + + + + Users + + NumBoardMembers + NumProposers + UserIdToRole + Quorum + + ActionState + + + Variables + Stack + + ExternalCallEnv + + PerformedActions + + + + + syntax Bool ::= countCanSignRequires( + signerIds:ExpressionList, + UsersCell, + numBoardMembers:KItem, + numProposers:Usize, + userIdToRole:Map, + quorum:KItem, + ActionStateCell, + variables:Map, + stack:Stack, + ExternalCallEnvCell) + [function, functional] + + rule countCanSignRequires( + SignerIds:ExpressionList, + _Users:UsersCell, + _NumBoardMembers:KItem, + _NumProposers:Usize, + UserIdToRole:Map, + _Quorum:KItem, + _ActionState:ActionStateCell, + Variables:Map, + _Stack:Stack, + _ExternalCallEnv:ExternalCallEnvCell) + => + isKResult(SignerIds) + andBool listElementsAreUsize(SignerIds) + andBool (notBool result in_keys(Variables)) + andBool (notBool user_role in_keys(Variables)) + andBool userIdToRoleInvariant(UserIdToRole) + + syntax Bool ::= countCanSignEnsures( + count:Usize, + UsersCell, + numBoardMembers:KItem, + numProposers:Usize, + userIdToRole:Map, + quorum:KItem, + ActionStateCell, + variables:Map, + stack:Stack, + ExternalCallEnvCell) + [function, functional] + + rule countCanSignEnsures( + _Count:Usize, + _Users:UsersCell, + _NumBoardMembers:KItem, + _NumProposers:Usize, + _UserIdToRole:Map, + _Quorum:KItem, + _ActionState:ActionStateCell, + _Variables:Map, + _Stack:Stack, + _ExternalCallEnv:ExternalCallEnvCell) + => true + +endmodule diff --git a/multisig/protocol-correctness/proof/invariant/init-loop-parts.k b/multisig/protocol-correctness/proof/invariant/init-loop-parts.k new file mode 100644 index 000000000..f847913f3 --- /dev/null +++ b/multisig/protocol-correctness/proof/invariant/init-loop-parts.k @@ -0,0 +1,237 @@ +require "protocol-correctness/pseudocode.k" +require "protocol-correctness/proof/execution-proof-helpers.k" +require "protocol-correctness/proof/invariant.k" + +module INIT-LOOP-PARTS + imports PSEUDOCODE + imports EXECUTION-PROOF-HELPERS + imports INVARIANT-HELPERS + + syntax TTCell ::= initLoopLhs( + prevIndex:Usize, + addresses:ExpressionList, + K, + userIdToAddress:Map, + addressToUserId:Map, + userIdToRole:Map, + quorum:Usize, + ActionStateCell, + variables:Map, + stack:Stack, + ExternalCallEnvCell, + address:Expression, + userId:Usize) + [function, functional] + rule initLoopLhs( + PrevIndex:Usize, + Addresses:ExpressionList, + K:K, + UserIdToAddress0:Map, + AddressToUserId0:Map, + UserIdToRole0:Map, + Quorum:Usize, + ActionState:ActionStateCell, + Variables:Map, + Stack:Stack, + ExternalCallEnv:ExternalCallEnvCell, + Address:Expression, + UserId:Usize) + => + + runInstruction( + for (i = add(PrevIndex, u(1)), address ) in Addresses { + user_id = i + u(1); + require(getUserId(address) == u(0)); + setUserId(address, user_id); + setUserAddress(user_id, address); + setUserIdToRole(user_id, BoardMember); + } + ) + ~> K + + + + + u(0) + UserIdToAddress0 + AddressToUserId0 + + + u(0) + u(0) + UserIdToRole0 + Quorum + + ActionState + + + + i |-> PrevIndex + address |-> Address + user_id |-> UserId + Variables + + Stack + + ExternalCallEnv + + .List + + + + + syntax TTCell ::= initLoopRhs( + KItem, + K, + userIdToAddress:Map, + addressToUserId:Map, + userIdToRole:Map, + quorum:Usize, + ActionStateCell, + variables:Map, + stack:Stack, + ExternalCallEnvCell, + index:Usize, + address:Expression, + userId:Usize) + [function, functional] + rule initLoopRhs( + Item:KItem, + K:K, + UserIdToAddress1:Map, + AddressToUserId1:Map, + UserIdToRole1:Map, + Quorum:Usize, + ActionState:ActionStateCell, + Variables:Map, + Stack:Stack, + ExternalCallEnv:ExternalCallEnvCell, + Index:Usize, + Address:Expression, + UserId:Usize) + => + + Item ~> K + + + + u(0) + UserIdToAddress1 + AddressToUserId1:Map + + + u(0) + u(0) + UserIdToRole1 + Quorum + + ActionState + + + + (i |-> Index) + (address |-> Address) + (user_id |-> UserId) + Variables + + Stack + + ExternalCallEnv + + .List + + + + + syntax Bool ::= initLoopRequires( + prevIndex:Usize, + addresses:ExpressionList, + userIdToAddress:Map, + addressToUserId:Map, + userIdToRole:Map) + [function, functional] + rule initLoopRequires( + u(PrevIndex:Int), + Addresses:ExpressionList, + UserIdToAddress0:Map, + AddressToUserId0:Map, + UserIdToRole0:Map) + => true + andBool PrevIndex >=Int 0 + andBool isKResult(Addresses) + + andBool noReusedIndexAddress(add(u(PrevIndex), u(2)), UserIdToAddress0, Addresses) + andBool noReusedIndexRole(add(u(PrevIndex), u(2)), UserIdToRole0, Addresses) + andBool listElementsAreAddresses(Addresses) + + andBool initLoopInvariant( + add(u(PrevIndex), u(1)), + UserIdToAddress0, + AddressToUserId0, + UserIdToRole0, + expand(expanded)) + + syntax Bool ::= initLoopEnsures( + numUsers:Usize, + addresses:ExpressionList, + userIdToAddress:Map, + addressToUserId:Map, + userIdToRole0:Map, + userIdToRole:Map) [function, functional] + + rule initLoopEnsures( + NumUsers:Usize, + Addresses:ExpressionList, + UserIdToAddress:Map, + AddressToUserId:Map, + UserIdToRole0:Map, + UserIdToRole:Map) + => true + andBool initLoopInvariant( + NumUsers, + UserIdToAddress, + AddressToUserId, + UserIdToRole, + usesExpanded) + andBool pListLen(Addresses) + +Int countMapValues(UserIdToRole0, wrap(BoardMember)) + ==Int countMapValues(UserIdToRole, wrap(BoardMember)) + + syntax Bool ::= initLoopInvariant( + numUsers:Usize, + userIdToAddress:Map, + addressToUserId:Map, + userIdToRole:Map, + handling:PropertyHandling) [function, functional] + + rule initLoopInvariant( + u(NumUsers:Int), + UserIdToAddress:Map, + AddressToUserId:Map, + UserIdToRole:Map, + Handling:PropertyHandling) + => true + andBool notBool u(0) in_keys(UserIdToAddress) + andBool notBool u(0) in_keys(UserIdToRole) + + andBool allValuesBecomeKeys(AddressToUserId, UserIdToAddress) + andBool allValuesBecomeKeys(UserIdToAddress, AddressToUserId) + + andBool addressToUserIdInvariant(AddressToUserId) + // andBool valuesAreOfType(AddressToUserId, rUsize) + // andBool valuesAreKResult(AddressToUserId) + // andBool valuesAreNotEmpty(AddressToUserId, rUsize) + // andBool valuesAreDistinct(AddressToUserId) + andBool noReusedIndexValue(NumUsers +Int 1, AddressToUserId, Handling) + andBool unusedIdsInMapValues(NumUsers +Int 1, AddressToUserId, Handling) + + andBool unusedIdsInMapKeys(NumUsers +Int 1, keysMap(UserIdToAddress), Handling) + + andBool userIdToRoleInvariant(UserIdToRole) + // andBool valuesAreOfType(UserIdToRole, rUserRole) + // andBool valuesAreKResult(UserIdToRole) + // andBool valuesAreNotEmpty(UserIdToRole, rUserRole) + andBool unusedIdsInMapKeys(NumUsers +Int 1, keysMap(UserIdToRole), Handling) + + andBool 0 ==Int countMapValues(UserIdToRole, wrap(Proposer)) +endmodule \ No newline at end of file diff --git a/multisig/protocol-correctness/proof/invariant/invariant-execution.k b/multisig/protocol-correctness/proof/invariant/invariant-execution.k new file mode 100644 index 000000000..5a48ef98b --- /dev/null +++ b/multisig/protocol-correctness/proof/invariant/invariant-execution.k @@ -0,0 +1,1104 @@ +require "protocol-correctness/proof/execution-proof.k" +require "protocol-correctness/proof/functions/functions-execute.k" + +require "protocol-correctness/proof/invariant/count-can-sign-parts.k" +require "protocol-correctness/proof/invariant/init-loop-parts.k" +require "protocol-correctness/proof/invariant/perform-parts.k" + +module INVARIANT-EXECUTION-SYNTAX + imports EXECUTION-PROOF-SYNTAX +endmodule + +module INVARIANT-INSTRUMENTATION + imports MAP + + imports PROOF-INSTRUMENTATION + imports PSEUDOCODE + + rule nullableMapLookup(_:KItem, M:Map, _:ReflectionType) + ~> (.K => lazyConcretizeKeys(M)) + ~> K:KItem + requires notBool isLazyConcretize(K) + [priority(20)] + rule (E:Expression => .K) ~> lazyConcretizeKeys(_) ~> (.K => E) + [priority(20)] + + rule nullableMapSet(_:KItem, _:KItem, _:Map, _:ReflectionType) // This may be needed only for addressToUserID, in init. + ~> (.K => lazyConcretizeKeysFreezer) + ~> K:KItem + requires notBool isLazyConcretize(K) + [priority(20)] + rule (M:Map ~> lazyConcretizeKeysFreezer) => (lazyConcretizeKeys(M) ~> M) + [priority(20)] + + // syntax KItem ::= lazySplitMap(k:KItem, m:Map, value:KItem, remainder:Map) + // rule lazySplitMap(K:KItem, M:Map, Value:KItem, Remainder:Map) + // => splitMap(K, M, Value, Remainder) +endmodule + +module PERFORM-SPLIT-ACTION-INSTRUMENTATION + imports PSEUDOCODE + imports CONCRETIZE-INSTRUMENTATION + + syntax KItem ::= "splitting-action" + rule pushContext ~> (.K => splitAction(A) ~> splitting-action) ~> call(performAction(A:Action)) + ... + [priority(10)] + rule (splitting-action => .K) ... + [priority(20)] + + syntax KItem ::= splitAction(Action) + rule splitAction(Nothing) => .K + rule splitAction(AddBoardMember(A:Address)) => concretizeValue(A) + rule splitAction(AddProposer(A:Address)) => concretizeValue(A) + rule splitAction(RemoveUser(A:Address)) => concretizeValue(A) + rule splitAction(ChangeQuorum(Q:Usize)) => concretizeValue(Q) + rule splitAction(SendEgld(To:Address, Amount:BigUint, Data:BoxedBytes)) => + concretizeValue(To) ~> concretizeValue(Amount) ~> concretizeValue(Data) + rule splitAction(SCDeploy( + Amount:BigUint, + Code:BoxedBytes, + CodeMetadata:CodeMetadata, + Arguments:ExpressionList)) + => concretizeValue(Amount) + ~> concretizeValue(Code) + ~> concretizeValue(CodeMetadata) + ~> concretizeValue(Arguments) + rule splitAction(SCCall( + To:Address, + Amount:BigUint, + Function:BoxedBytes, + Arguments:ExpressionList)) + => concretizeValue(To) + ~> concretizeValue(Amount) + ~> concretizeValue(Function) + ~> concretizeValue(Arguments) + +endmodule + +module PERFORM-ACTION-REMOVE-USER-INSTRUMENTATION + imports INVARIANT-INSTRUMENTATION + imports PERFORM-SPLIT-ACTION-INSTRUMENTATION + imports PSEUDOCODE + + syntax KItem ::= splittingDeleteCaller(Address) + syntax KItem ::= splittingDeleteCaller1(Address) + syntax KItem ::= splittingDeleteCaller2(Usize) + rule (splitting-action => splittingDeleteCaller(A)) + ~> call(performAction(RemoveUser(A:Address))) + [priority(10)] + + rule splittingDeleteCaller(A:Address) + => branchK( + A in_keys(AddressToUserId), + splittingDeleteCaller1(A), + .K + ) + ... + AddressToUserId:Map + rule ( + splittingDeleteCaller1(A:Address) + => makeConcreteValue(A, rUsize, AddressToUserId) + ~> branchK( + AddressToUserId[A] in_keys(UserIdToRole), + splittingDeleteCaller2({AddressToUserId[A]}:>Usize), + .K + ) + ) + ... + AddressToUserId:Map + UserIdToRole:Map + requires A in_keys(AddressToUserId) + + rule ( + splittingDeleteCaller2(UserId:Usize) + => makeConcreteValue(UserId, rUserRole, UserIdToRole) + ~> lazyConcretizeKeys(UserIdToRole) // TODO: Likely not needed. + ~> branchK( + UserIdToRole[UserId] ==K BoardMember, + splitBoolean(Quorum <=Int NumBoardMembers -Int 1), + splitBoolean(Quorum <=Int NumBoardMembers) + ) + ~> splitBoolean(NumBoardMembers -Int 1 +Int NumProposers >Int 0) + ) + ... + UserIdToRole:Map + u(NumBoardMembers:Int) + u(NumProposers:Int) + u(Quorum:Int) + requires UserId in_keys(UserIdToRole) +endmodule + +module PERFORM-ACTION-SC-DEPLOY-INSTRUMENTATION + imports PERFORM-SPLIT-ACTION-INSTRUMENTATION + imports INVARIANT-INSTRUMENTATION + + rule (splitting-action => concretizeValue(Arguments)) + ~> call(performAction(SCDeploy( + _Amount:BigUint, + _Code:BoxedBytes, + _CodeMetadata:CodeMetadata, + Arguments:ExpressionList))) + ... + [priority(10)] + +endmodule + +module PROPOSE-SC-DEPLOY-INSTRUMENTATION + imports PROOF-INSTRUMENTATION + imports PSEUDOCODE + + syntax KItem ::= "split-sc-deploy" + syntax KItem ::= "split-sc-deploy1" + + rule preCall + ~> (.K => split-sc-deploy) + ~> call(proposeSCDeploy(_:BigUint, _:BoxedBytes, _:Bool, _:Bool, _:Bool, _:ExpressionList)) + [priority(20)] + + rule split-sc-deploy + => branchK( + Caller in_keys(AddressToUserId), + makeConcreteValue(Caller, rUsize, AddressToUserId) + ~> split-sc-deploy1, + .K + ) + ... + AddressToUserId:Map + Caller:KItem + + rule split-sc-deploy1 + => branchK( + AddressToUserId[Caller] in_keys(UserIdToRole), + makeConcreteValue(AddressToUserId[Caller], rUserRole, UserIdToRole), + .K + ) + ... + AddressToUserId:Map + UserIdToRole:Map + Caller:KItem +endmodule + +module PERFORM-ACTION-ADD-PROPOSER-INSTRUMENTATION + imports INVARIANT-INSTRUMENTATION + imports PERFORM-SPLIT-ACTION-INSTRUMENTATION + imports PSEUDOCODE + + syntax KItem ::= splittingActionProposer(Address) + + rule ( + splitting-action + => branchK( + A1 in_keys(AddressToUserId), + splittingActionProposer(A1), + .K + ) + ) + ~> call(performAction(AddProposer(A1:Address))) + ... + AddressToUserId:Map + [priority(10)] + + rule splittingActionProposer(A1:Address) + => makeConcreteValue(A1, rUsize, AddressToUserId) + ~> branchK( + AddressToUserId[A1] in_keys(UserIdToRole), + makeConcreteValue(AddressToUserId[A1], rUserRole, UserIdToRole), + .K + ) + ... + AddressToUserId:Map + UserIdToRole:Map + requires A1 in_keys(AddressToUserId) + // TODO: Do I need AddressToUserId[A1] in_keys(UserIdToRole)? +endmodule + +module CHANGE-USER-ROLE-INSTRUMENTATION + imports INVARIANT-INSTRUMENTATION + imports PSEUDOCODE + + syntax KItem ::= splitChangeUserRole(Address) + syntax KItem ::= splitChangeUserRole2(Address) + syntax KItem ::= splitChangeUserRole3(Usize) + + rule preCall + ~> (.K => splitChangeUserRole(UserAddress)) + ~> call(changeUserRole(UserAddress:Address, _NewRole:UserRole)) + [priority(20)] + + rule splitChangeUserRole(Address:Address) + => branchK( + Address in_keys(AddressToUserId), + splitChangeUserRole2(Address), + .K + ) + ... + AddressToUserId:Map + + rule splitChangeUserRole2(Address:Address) + => makeConcreteValue(Address, rUsize, AddressToUserId) + ~> branchK( + AddressToUserId[Address] in_keys(UserIdToRole), + makeConcreteValue(AddressToUserId[Address], rUserRole, UserIdToRole), + .K + ) + ... + AddressToUserId:Map + UserIdToRole:Map + requires Address in_keys(AddressToUserId) +endmodule + +module SIGN-INSTRUMENTATION + imports PSEUDOCODE + imports INVARIANT-INSTRUMENTATION + + syntax KItem ::= splitSign(Usize) + syntax KItem ::= splitSign2(Usize) + syntax KItem ::= splitSign3(Usize) + + rule preCall + ~> (.K => splitSign(ActionId)) + ~> call(sign(ActionId:Usize)) + [priority(20)] + + rule splitSign(ActionId:Usize) + => branchK( + ActionId in_keys(ActionData), + branchK( + CallerAddress in_keys(AddressToUserId), + splitSign2(ActionId), + .K + ), + .K + ) + ... + AddressToUserId:Map + CallerAddress:KItem + ActionData:Map + + rule splitSign2(ActionId:Usize) + => makeConcreteValue(CallerAddress, rUsize, AddressToUserId) + ~> branchK( + AddressToUserId[CallerAddress] in_keys(UserIdToRole), + splitSign3(ActionId), + .K + ) + ... + AddressToUserId:Map + UserIdToRole:Map + CallerAddress:KItem + requires CallerAddress in_keys(AddressToUserId) + + rule splitSign3(ActionId:Usize) + => makeConcreteValue(AddressToUserId[CallerAddress], rUserRole, UserIdToRole) + ~> branchK( + UserIdToRole[AddressToUserId[CallerAddress]] ==K BoardMember, + branchK( + ActionId in_keys(ActionSigners), + makeConcreteValue(ActionId, rExpressionList, ActionSigners), + .K + ), + .K + ) + ... + AddressToUserId:Map + UserIdToRole:Map + CallerAddress:KItem + ActionSigners:Map + requires CallerAddress in_keys(AddressToUserId) + andBool AddressToUserId[CallerAddress] in_keys(UserIdToRole) +endmodule + +module UNSIGN-INSTRUMENTATION + imports INVARIANT-INSTRUMENTATION + + syntax KItem ::= splitUnsign(actionId:Usize) + syntax KItem ::= splitUnsign2(actionId:Usize) + syntax KItem ::= splitUnsign3(actionId:Usize) + syntax KItem ::= splitUnsign4(actionId:Usize) + syntax KItem ::= splitUnsign5(signers:ExpressionList, userId:Usize) + + rule preCall + ~> (.K => splitUnsign(ActionId)) + ~> call(unsign(ActionId:Usize)) + [priority(20)] + + rule splitUnsign(ActionId:Usize) + => branchK( + ActionId in_keys(ActionData), + makeConcreteValue(ActionId, rAction, ActionData) + ~> branchK( + CallerAddress in_keys(AddressToUserId), + splitUnsign2(ActionId), + .K + ), + .K + ) + ... + ActionData:Map + AddressToUserId:Map + CallerAddress:KItem + + rule splitUnsign2(ActionId:Usize) + => makeConcreteValue(CallerAddress, rUsize, AddressToUserId) + ~> branchK( + AddressToUserId[CallerAddress] in_keys(UserIdToRole), + splitUnsign3(ActionId), + .K + ) + ... + AddressToUserId:Map + UserIdToRole:Map + CallerAddress:KItem + requires CallerAddress in_keys(AddressToUserId) + + rule splitUnsign3(ActionId:Usize) + => makeConcreteValue(AddressToUserId[CallerAddress], rUserRole, UserIdToRole) + ~> branchK( + UserIdToRole[AddressToUserId[CallerAddress]] ==K BoardMember, + branchK( + ActionId in_keys(ActionSigners), + makeConcreteValue(ActionId, rExpressionList, ActionSigners) + ~> splitUnsign4(ActionId), + .K + ), + .K + ) + ... + AddressToUserId:Map + UserIdToRole:Map + CallerAddress:KItem + ActionSigners:Map + requires true + andBool CallerAddress in_keys(AddressToUserId) + andBool AddressToUserId[CallerAddress] in_keys(UserIdToRole) + + rule splitUnsign4(ActionId:Usize) + => splitUnsign5( + {ActionSigners[ActionId]}:>ExpressionList, + {AddressToUserId[CallerAddress]}:>Usize + ) + ... + ActionSigners:Map + AddressToUserId:Map + CallerAddress:KItem + requires true + andBool ActionId in_keys(ActionSigners) + andBool isExpressionList(ActionSigners[ActionId]) + andBool CallerAddress in_keys(AddressToUserId) + andBool isUsize(AddressToUserId[CallerAddress]) + + rule splitUnsign5(Signers:ExpressionList, UserId:Usize) + => branchK( + #listFind(Signers, UserId) >=Int 0, + concretizeExpressionList(Signers, 2) + ~> branchK( + pListLen(Signers) >=Int 1, + makeConcrete(expressionListGetOrDefault(Signers, 0, void), rUsize) + ~> branchK( + pListLen(Signers) ==Int 1, + branchK( + expressionListGetOrDefault(Signers, 0, void) ==K UserId, + .K, + .K + ), + branchK( + pListLen(Signers) >=Int 2, + makeConcrete(expressionListGetOrDefault(Signers, 1, void), rUsize) + ~> branchK( + expressionListGetOrDefault(Signers, 0, void) ==K UserId, + .K, + branchK( + expressionListGetOrDefault(Signers, 1, void) ==K UserId, + .K, + .K + ) + ), + stuck + ) + ), + stuck + ), + // branchK( + // ActionSigners[ActionId] ==K [?UserId1:Expression, .], + // makeConcrete(?UserId1, rUsize) + // ~> branchK( + // ?UserId1 ==K AddressToUserId[CallerAddress], + // .K, + // .K + // ), + // branchK( + // ActionSigners[ActionId] ==K [?UserId2:Expression, ?UserId3:Expression, ?_:ExpressionCSV], + // makeConcrete(?UserId2, rUsize) + // ~> makeConcrete(?UserId3, rUsize) + // ~> branchK( + // ?UserId2 ==K AddressToUserId[CallerAddress], + // .K, + // .K + // ), + // .K + // ) + // ), + .K + ) + requires true + + // rule splitUnsign6(ActionId:Usize, Signers:ExpressionList, UserId:Usize) + // => branchK( + // #listFind(Signers, UserId) >=Int 0, + // concretizeExpressionList(Signers, 2) + // ~> branchK( + // pListLen(Signers) >=Int 1, + // makeConcrete(expressionListGetOrDefault(Signers, 0, void), rUsize) + // ~> branchK( + // pListLen(Signers) ==Int 1, + // branchK( + // expressionListGetOrDefault(Signers, 0, void) ==K UserId, + // .K, + // .K + // ), + // branchK( + // pListLen(Signers) >=Int 2, + // makeConcrete(expressionListGetOrDefault(Signers, 1, void), rUsize) + // ~> branchK( + // expressionListGetOrDefault(Signers, 1, void) ==K UserId, + // .K, + // .K + // ), + // stuck + // ) + // ), + // stuck + // ), + // .K + // ) + // requires true +endmodule + +module DISCARD-ACTION-INSTRUMENTATION + imports INVARIANT-INSTRUMENTATION + imports PROOF-INSTRUMENTATION + imports EXECUTION-PROOF + imports PSEUDOCODE + + syntax KItem ::= splitDiscardAction(actionId:Usize) + syntax KItem ::= splitDiscardAction1(actionId:Usize) + syntax KItem ::= splitDiscardAction2(actionId:Usize) + syntax KItem ::= splitDiscardAction3(actionId:Usize) + syntax KItem ::= splitDiscardAction4(actionId:Usize) + + rule preCall + ~> (.K => splitDiscardAction(ActionId)) + ~> call(discardAction(ActionId:Usize)) + [priority(20)] + + rule splitDiscardAction(ActionId:Usize) + => branchK( + Caller in_keys(AddressToUserId), + splitDiscardAction1(ActionId), + .K + ) + ... + AddressToUserId:Map + Caller:KItem + + rule splitDiscardAction1(ActionId:Usize) + => makeConcreteValue(Caller, rUsize, AddressToUserId) + ~> branchK( + AddressToUserId[Caller] in_keys(UserIdToRole), + splitDiscardAction2(ActionId), + .K + ) + ... + AddressToUserId:Map + UserIdToRole:Map + Caller:KItem + requires Caller in_keys(AddressToUserId) + + rule splitDiscardAction2(ActionId:Usize) + => makeConcreteValue(AddressToUserId[Caller], rUserRole, UserIdToRole) + ~> branchK( + ActionId in_keys(ActionSigners), + splitDiscardAction3(ActionId), + branchK( + ActionId in_keys(ActionData), + makeConcreteValue(ActionId, rAction, ActionData), + .K + ) + ) + ... + AddressToUserId:Map + UserIdToRole:Map + Caller:KItem + ActionSigners:Map + ActionData + requires Caller in_keys(AddressToUserId) + + rule splitDiscardAction3(ActionId:Usize) + => makeConcreteValue(ActionId, rExpressionList, ActionSigners) + ~> branchK( + ActionId in_keys(ActionData), + makeConcreteValue(ActionId, rAction, ActionData), + splitDiscardAction4(ActionId) + ) + ... + ActionData + ActionSigners + requires ActionId in_keys(ActionSigners) + rule splitDiscardAction4(ActionId:Usize) + => branchK( + countCanSignFunction({ActionSigners[ActionId]}:>ExpressionList, opaque(UserIdToRole)) >Int 0, + .K, + .K + ) + ... + ActionSigners + UserIdToRole:Map + requires ActionId in_keys(ActionSigners) + andBool isExpressionList(ActionSigners[ActionId]) + +endmodule + +module PERFORM-ACTION-ENDPOINT-INSTRUMENTATION + // This is a diagram of the splits attempted here. The k files have only + // their suffix. The missing prefix is 'proof-perform-action-endpoint-'. + // + // Has caller user? + // No: New.k + // Yes: Has caller role? + // No: None.k + // Yes: Has quorum? + // No: TODO: merge no-quorum-has-signers.k + no-quorum-no-signers.k + // Yes: Has action? + // No: TODO: nothing.k + // Yes: split action + // action=add-board-member: Is same as caller? + // No: New user? + // Yes: add-board-member-New.k + // No: Has role? + // No: add-board-member-None.k + // Yes: split role + // role=proposer? add-board-member-Proposer.k + // role=board-member? add-board-member-BoardMember.k + // Yes: split role + // role=proposer? add-board-member-Proposer-eq.k + // role=board-member? add-board-member-BoardMember-eq.k + // action=add-proposer: Is same as caller? + // No: New user? + // Yes: add-proposer-New.k + // No: Has role? + // No: add-proposer-None.k + // Yes: split role + // role=proposer? add-proposer-Proposer.k + // role=board-member? goes-below-quorum? + // Yes: add-proposer-BoardMember-no-quorum.k + // No: add-proposer-BoardMember.k + // Yes: split role + // role=proposer? add-proposer-Proposer-eq.k + // role=board-member? goes-below-quorum? + // Yes: add-proposer-BoardMember-no-quorum-eq.k + // No: add-proposer-BoardMember-eq.k + // action=change-quorum: goes-below-quorum? + // Yes: change-quorum-no-quorum.k + // No: change-quorum.k + // action=remove-user: Is same as caller? + // No: New user? + // Yes: remove-user-New.k + // No: Has role? + // No: remove-user-None.k + // Yes: split role + // role = proposer: has-people-left? + // Yes: remove-user-Proposer.k + // No: remove-user-Proposer-nobody-left.k + // role = board-member: can-still-vote-execute? + // Yes: remove-user-BoardMember.k + // No: remove-user-BoardMember-too-few.k + // Yes: split role + // role = proposer: has-people-left? + // Yes: remove-user-Proposer-eq.k + // No: remove-user-Proposer-nobody-left-eq.k + // role = board-member: can-still-vote-execute? + // Yes: remove-user-BoardMember-eq.k + // No: remove-user-BoardMember-too-few-eq.k + // action=sc-call? sc-call.k + // action=sc-deploy? sc-deploy.k + // action=send-egld? send-egld.k + + imports PERFORM-SPLIT-ACTION-INSTRUMENTATION + imports PROOF-INSTRUMENTATION + imports EXECUTION-PROOF + imports PSEUDOCODE + + // The Haskell backend sometimes leaves traces of + // (trusted) claims that failed to apply in the predicate. + // Sometimes, these traces increase the execution time by a lot, + // so we have to work around this. + // + // The symbols below allow us to wrap those claims in another set of claims, + // which can be attemped without leaving traces. + syntax ProofBranch ::= "new.k" + syntax ProofBranch ::= "none.k" + syntax ProofBranch ::= "no-quorum.k" + syntax ProofBranch ::= "add-board-member-New.k" + syntax ProofBranch ::= "add-board-member-None.k" + syntax ProofBranch ::= "add-board-member-BoardMember.k" + syntax ProofBranch ::= "add-board-member-Proposer.k" + syntax ProofBranch ::= "add-board-member-BoardMember-eq.k" + syntax ProofBranch ::= "add-board-member-Proposer-eq.k" + syntax ProofBranch ::= "add-proposer-New.k" + syntax ProofBranch ::= "add-proposer-None.k" + syntax ProofBranch ::= "add-proposer-BoardMember.k" + syntax ProofBranch ::= "add-proposer-BoardMember-no-quorum.k" + syntax ProofBranch ::= "add-proposer-Proposer.k" + syntax ProofBranch ::= "add-proposer-BoardMember-eq.k" + syntax ProofBranch ::= "add-proposer-BoardMember-no-quorum-eq.k" + syntax ProofBranch ::= "add-proposer-Proposer-eq.k" + syntax ProofBranch ::= "change-quorum.k" + syntax ProofBranch ::= "change-quorum-no-quorum.k" + syntax ProofBranch ::= "nothing.k" + syntax ProofBranch ::= "remove-user-New.k" + syntax ProofBranch ::= "remove-user-None.k" + syntax ProofBranch ::= "remove-user-BoardMember-too-few.k" + syntax ProofBranch ::= "remove-user-BoardMember.k" + syntax ProofBranch ::= "remove-user-Proposer-nobody-left.k" + syntax ProofBranch ::= "remove-user-Proposer.k" + syntax ProofBranch ::= "remove-user-Proposer-nobody-left-eq.k" + syntax ProofBranch ::= "remove-user-Proposer-eq.k" + syntax ProofBranch ::= "remove-user-BoardMember-too-few-eq.k" + syntax ProofBranch ::= "remove-user-BoardMember-eq.k" + syntax ProofBranch ::= "sc-call.k" + syntax ProofBranch ::= "sc-deploy.k" + syntax ProofBranch ::= "send-egld.k" + + syntax KItem ::= ProofBranch + + // TODO: It might be faster to enumerate all cases separately. + rule _:ProofBranch => .K + + syntax KItem ::= splitPerformActionEndpoint(actionId:Usize) + syntax KItem ::= splitPerformActionEndpoint1(actionId:Usize) + syntax KItem ::= splitPerformActionEndpoint1a(actionId:Usize) + syntax KItem ::= splitPerformActionEndpoint2(actionId:Usize) + syntax KItem ::= splitPerformActionEndpoint3(action:Action) + syntax KItem ::= splitPerformActionEndpoint4(action:Action) + syntax KItem ::= splitActionSigners(actionId:Usize, signers:Map) + + rule preCall + ~> (.K => splitPerformActionEndpoint(ActionId)) + ~> call(performActionEndpoint(ActionId:Usize)) + ~> _:KItem + ~> _:KItem + ~> _:KItem + ~> (.K => splitActionSigners(ActionId, ActionSigners)) + ~> runExternalCalls(_:ExternalCommands) + ... + ActionSigners:Map + [priority(20)] + + rule splitActionSigners(ActionId:Usize, ActionSigners:Map) + => branchK( + ActionId in_keys(ActionSigners), + makeConcreteValue(ActionId, rExpressionList, ActionSigners), + .K + ) + + rule splitPerformActionEndpoint(ActionId:Usize) + => branchK( + CallerAddress in_keys(AddressToUserId), + splitPerformActionEndpoint1(ActionId), + new.k + ) + ... + AddressToUserId:Map + CallerAddress:Address + + rule splitPerformActionEndpoint1(ActionId:Usize) + => makeConcreteValue(CallerAddress, rUsize, AddressToUserId) + ~> branchK( + AddressToUserId[CallerAddress] in_keys(UserIdToRole), + makeConcreteValue(AddressToUserId[CallerAddress], rUserRole, UserIdToRole) + ~> branchK( + ActionId in_keys(ActionSigners), + makeConcreteValue(ActionId, rExpressionList, ActionSigners) + ~> splitPerformActionEndpoint1a(ActionId), + splitPerformActionEndpoint1a(ActionId) + ), + none.k + ) + ... + AddressToUserId:Map + UserIdToRole:Map + CallerAddress:Address + ActionSigners:Map + requires CallerAddress in_keys(AddressToUserId) + + rule splitPerformActionEndpoint1a(ActionId:Usize) + => branchK( + Quorum <=Int countCanSignFunction({ActionSigners[ActionId] orDefault [.]}:>ExpressionList, opaque(UserIdToRole)), + branchK( + ActionId in_keys(ActionData), + splitPerformActionEndpoint2(ActionId), + nothing.k + ), + no-quorum.k + ) + ... + CallerAddress |-> UserId:KItem _AddressToUserId:Map + CallerAddress:Address + u(Quorum:Int) + (UserId |-> _Role _UserIdToRole:Map) #as UserIdToRole:Map + ActionSigners:Map + ActionData:Map + + syntax Bool ::= isAddBoardMember(Action) [function, functional] + rule isAddBoardMember(AddBoardMember(_)) => true + rule isAddBoardMember(_) => false [owise] + + syntax Bool ::= isAddProposer(Action) [function, functional] + rule isAddProposer(AddProposer(_)) => true + rule isAddProposer(_) => false [owise] + + syntax Bool ::= isChangeQuorum(Action) [function, functional] + rule isChangeQuorum(ChangeQuorum(_)) => true + rule isChangeQuorum(_) => false [owise] + + syntax Bool ::= isRemoveUser(Action) [function, functional] + rule isRemoveUser(RemoveUser(_)) => true + rule isRemoveUser(_) => false [owise] + + syntax Bool ::= isScCall(Action) [function, functional] + rule isScCall(SCCall(_, _, _, _)) => true + rule isScCall(_) => false [owise] + + syntax Bool ::= isScDeploy(Action) [function, functional] + rule isScDeploy(SCDeploy(_, _, _, _)) => true + rule isScDeploy(_) => false [owise] + + syntax Bool ::= isSendEgld(Action) [function, functional] + rule isSendEgld(SendEgld(_, _, _)) => true + rule isSendEgld(_) => false [owise] + + rule splitPerformActionEndpoint2(ActionId) + => makeConcreteValue(ActionId, rAction, ActionData) + ~> splitPerformActionEndpoint3({ActionData[ActionId]}:>Action) + ... + ActionData:Map + requires ActionId in_keys(ActionData) + + syntax KItem ::= "action-splitted" + rule action-splitted => .K + + rule splitPerformActionEndpoint3(Action:Action) + => splitAction(Action) + ~> splitPerformActionEndpoint4(Action) + + rule splitPerformActionEndpoint4(Action:Action) + => branchK( + isAddBoardMember(Action), + splitAddBoardMember(Action), + branchK( + isAddProposer(Action), + splitAddProposer(Action), + branchK( + isChangeQuorum(Action), + splitChangeQuorum(Action), + branchK( + isRemoveUser(Action), + splitRemoveUser(Action), + branchK( + isScCall(Action), + sc-call.k, + branchK( + isScDeploy(Action), + sc-deploy.k, + branchK( + isSendEgld(Action), + send-egld.k, + stuck + ) + ) + ) + ) + ) + ) + ) + + syntax KItem ::= splitAddBoardMember(Action) + syntax KItem ::= splitAddBoardMember1(Address) + syntax KItem ::= splitAddBoardMember2(Address) + syntax KItem ::= splitAddBoardMember3(Address) + + rule + splitAddBoardMember(AddBoardMember(UserAddress:Address)) + => branchK( + UserAddress ==K CallerAddress, + splitAddBoardMember1(UserAddress), + branchK( + UserAddress in_keys(AddressToUserId), + splitAddBoardMember2(UserAddress), + add-board-member-New.k + ) + ) + ... + AddressToUserId:Map + CallerAddress:Address + + rule + splitAddBoardMember1(CallerAddress:Address) + => makeConcreteValue(CallerId, rUserRole, UserIdToRole) + ~> branchK( + UserIdToRole[CallerId] ==K BoardMember, + add-board-member-BoardMember-eq.k, + branchK( + UserIdToRole[CallerId] ==K Proposer, + add-board-member-Proposer-eq.k, + stuck + ) + ) + ... + UserIdToRole:Map + CallerAddress |-> CallerId:Usize _AddressToUserId:Map + CallerAddress:Address + requires CallerId in_keys(UserIdToRole) + + rule + splitAddBoardMember2(UserAddress:Address) + => makeConcreteValue(UserAddress, rUsize, AddressToUserId) + ~> branchK( + AddressToUserId[UserAddress] in_keys(UserIdToRole), + splitAddBoardMember3(UserAddress), + add-board-member-None.k + ) + ... + UserIdToRole:Map + AddressToUserId:Map + requires UserAddress in_keys(AddressToUserId) + + rule + splitAddBoardMember3(UserAddress:Address) + => makeConcreteValue(UserId, rUserRole, UserIdToRole) + ~> branchK( + UserIdToRole[UserId] ==K BoardMember, + add-board-member-BoardMember.k, + branchK( + UserIdToRole[UserId] ==K Proposer, + add-board-member-Proposer.k, + stuck + ) + ) + ... + UserIdToRole:Map + UserAddress |-> UserId _AddressToUserId:Map + requires UserId in_keys(UserIdToRole) + + syntax KItem ::= splitAddProposer(Action) + syntax KItem ::= splitAddProposer1(Address) + syntax KItem ::= splitAddProposer2(Address) + syntax KItem ::= splitAddProposer3(Address) + + rule + splitAddProposer(AddProposer(UserAddress:Address)) + => branchK( + UserAddress ==K CallerAddress, + splitAddProposer1(UserAddress), + branchK( + UserAddress in_keys(AddressToUserId), + splitAddProposer2(UserAddress), + add-proposer-New.k + ) + ) + ... + AddressToUserId:Map + CallerAddress:Address + + rule + splitAddProposer1(CallerAddress:Address) + => makeConcreteValue(CallerId, rUserRole, UserIdToRole) + ~> branchK( + UserIdToRole[CallerId] ==K BoardMember, + branchK( + Quorum ==K NumBoardMembers, + add-proposer-BoardMember-no-quorum-eq.k, + branchK( + Quorum <=Int NumBoardMembers -Int 1, + add-proposer-BoardMember-eq.k, + stuck + ) + ), + branchK( + UserIdToRole[CallerId] ==K Proposer, + add-proposer-Proposer-eq.k, + stuck + ) + ) + ... + u(NumBoardMembers) + u(Quorum) + UserIdToRole:Map + CallerAddress |-> CallerId:Usize _AddressToUserId:Map + CallerAddress:Address + requires CallerId in_keys(UserIdToRole) + + rule + splitAddProposer2(UserAddress:Address) + => makeConcreteValue(UserAddress, rUsize, AddressToUserId) + ~> branchK( + AddressToUserId[UserAddress] in_keys(UserIdToRole), + splitAddProposer3(UserAddress), + add-proposer-None.k + ) + ... + UserIdToRole:Map + AddressToUserId:Map + requires UserAddress in_keys(AddressToUserId) + + rule + splitAddProposer3(UserAddress:Address) + => makeConcreteValue(UserId, rUserRole, UserIdToRole) + ~> branchK( + UserIdToRole[UserId] ==K BoardMember, + branchK( + Quorum ==K NumBoardMembers, + add-proposer-BoardMember-no-quorum.k, + add-proposer-BoardMember.k + ), + branchK( + UserIdToRole[UserId] ==K Proposer, + add-proposer-Proposer.k, + stuck + ) + ) + ... + u(NumBoardMembers:Int) + u(Quorum:Int) + UserIdToRole:Map + UserAddress |-> UserId:Usize _AddressToUserId:Map + requires UserId in_keys(UserIdToRole) + + syntax KItem ::= splitChangeQuorum(Action) + + rule + splitChangeQuorum(ChangeQuorum(u(NewQuorum:Int))) + => branchK( + NewQuorum >Int NumBoardMembers, + change-quorum-no-quorum.k, + change-quorum.k + ) + ... + u(NumBoardMembers:Int) + + syntax KItem ::= splitRemoveUser(Action) + syntax KItem ::= splitRemoveUser1(Address) + syntax KItem ::= splitRemoveUser2(Address) + syntax KItem ::= splitRemoveUser3(Address) + + rule + splitRemoveUser(RemoveUser(UserAddress:Address)) + => branchK( + UserAddress ==K CallerAddress, + splitRemoveUser1(UserAddress), + branchK( + UserAddress in_keys(AddressToUserId), + splitRemoveUser2(UserAddress), + remove-user-New.k + ) + ) + ... + AddressToUserId:Map + CallerAddress:Address + + rule + splitRemoveUser1(CallerAddress:Address) + => makeConcreteValue(CallerId, rUserRole, UserIdToRole) + ~> branchK( + UserIdToRole[CallerId] ==K BoardMember, + branchK( + NumBoardMembers +Int NumProposers ==Int 1 + orBool Quorum ==Int NumBoardMembers, + remove-user-BoardMember-too-few-eq.k, + remove-user-BoardMember-eq.k + ), + branchK( + UserIdToRole[CallerId] ==K Proposer, + branchK( + NumBoardMembers +Int NumProposers ==Int 1, + remove-user-Proposer-nobody-left-eq.k, + remove-user-Proposer-eq.k + ), + stuck + ) + ) + ... + u(NumBoardMembers) + u(NumProposers) + u(Quorum) + UserIdToRole:Map + CallerAddress |-> CallerId:Usize _AddressToUserId:Map + CallerAddress:Address + requires CallerId in_keys(UserIdToRole) + + rule + splitRemoveUser2(UserAddress:Address) + => makeConcreteValue(UserAddress, rUsize, AddressToUserId) + ~> branchK( + AddressToUserId[UserAddress] in_keys(UserIdToRole), + splitRemoveUser3(UserAddress), + remove-user-None.k + ) + ... + UserIdToRole:Map + AddressToUserId:Map + requires UserAddress in_keys(AddressToUserId) + + rule + splitRemoveUser3(UserAddress:Address) + => makeConcreteValue(UserId, rUserRole, UserIdToRole) + ~> branchK( + UserIdToRole[UserId] ==K BoardMember, + branchK( + NumBoardMembers +Int NumProposers ==Int 1 + orBool Quorum ==Int NumBoardMembers, + remove-user-BoardMember-too-few.k, + remove-user-BoardMember.k + ), + branchK( + UserIdToRole[UserId] ==K Proposer, + branchK( + NumBoardMembers +Int NumProposers ==Int 1, + remove-user-Proposer-nobody-left.k, + remove-user-Proposer.k + ), + stuck + ) + ) + ... + u(NumBoardMembers:Int) + u(NumProposers:Int) + u(Quorum:Int) + UserIdToRole:Map + UserAddress |-> UserId:Usize _AddressToUserId:Map + requires UserId in_keys(UserIdToRole) + +endmodule + +module INVARIANT-EXECUTION + imports EXECUTION-PROOF + imports FUNCTIONS-EXECUTE + + imports INVARIANT-INSTRUMENTATION + imports SIGN-INSTRUMENTATION + imports CHANGE-USER-ROLE-INSTRUMENTATION + imports PROPOSE-ACTION-INSTRUMENTATION + imports PERFORM-ACTION-ADD-PROPOSER-INSTRUMENTATION + imports PERFORM-ACTION-SC-DEPLOY-INSTRUMENTATION + imports PERFORM-ACTION-REMOVE-USER-INSTRUMENTATION + imports PERFORM-SPLIT-ACTION-INSTRUMENTATION + imports PROPOSE-SC-DEPLOY-INSTRUMENTATION + imports DISCARD-ACTION-INSTRUMENTATION + imports UNSIGN-INSTRUMENTATION + imports PERFORM-ACTION-ENDPOINT-INSTRUMENTATION + + imports COUNT-CAN-SIGN-PARTS + imports INIT-LOOP-PARTS + imports PERFORM-PARTS +endmodule \ No newline at end of file diff --git a/multisig/protocol-correctness/proof/invariant/invariant.mak b/multisig/protocol-correctness/proof/invariant/invariant.mak new file mode 100644 index 000000000..fe5a2097f --- /dev/null +++ b/multisig/protocol-correctness/proof/invariant/invariant.mak @@ -0,0 +1,42 @@ +INVARIANT_OUT_PREFIX=.out/invariant. + +INVARIANT_ALL := $(wildcard $(INVARIANT_DIR)/*.k) +INVARIANT_PROOFS := $(wildcard $(INVARIANT_DIR)/proof-*.k) +INVARIANT_EXECUTION := $(filter-out $(INVARIANT_PROOFS), $(INVARIANT_ALL)) $(PROOF_EXECUTION) $(FUNCTIONS_EXECUTION) + +INVARIANT_PROOF_TIMESTAMPS := $(addprefix $(INVARIANT_OUT_PREFIX),$(notdir ${INVARIANT_PROOFS:.k=.timestamp})) +INVARIANT_PROOF_DEBUGGERS := $(addprefix $(INVARIANT_OUT_PREFIX),${INVARIANT_PROOFS:.k=.debugger}) + +.PHONY: invariant.clean ${INVARIANT_PROOF_DEBUGGERS} + +$(INVARIANT_OUT_PREFIX)proof.timestamp: ${INVARIANT_PROOF_TIMESTAMPS} $(INVARIANT_OUT_PREFIX)execution.timestamp + $(DIR_GUARD) + @touch $(INVARIANT_OUT_PREFIX)proof.timestamp + +$(INVARIANT_OUT_PREFIX)proof-%.timestamp: $(INVARIANT_DIR)/proof-%.k $(INVARIANT_OUT_PREFIX)execution.timestamp + $(DIR_GUARD) + @echo "Proving $*..." + @cat /proc/uptime | sed 's/\s.*//' > $(INVARIANT_OUT_PREFIX)proof-$*.duration.temp + @((kprove $< --directory $(INVARIANT_DIR) --haskell-backend-command $(BACKEND_COMMAND) > $(INVARIANT_OUT_PREFIX)proof-$*.out 2>&1) && echo "$* done") || (cat $(INVARIANT_OUT_PREFIX)proof-$*.out; echo "$* failed"; echo "$*" >> $(INVARIANT_OUT_PREFIX)failures; false) + @cat /proc/uptime | sed 's/\s.*//' >> $(INVARIANT_OUT_PREFIX)proof-$*.duration.temp + @$(SCRIPT_DIR)/compute-duration.py $(INVARIANT_OUT_PREFIX)proof-$*.duration.temp > $(INVARIANT_OUT_PREFIX)proof-$*.duration + @rm $(INVARIANT_OUT_PREFIX)proof-$*.duration.temp + @touch $(INVARIANT_OUT_PREFIX)proof-$*.timestamp + +$(INVARIANT_OUT_PREFIX)proof-%.debugger: $(INVARIANT_OUT_PREFIX)proof-%.k $(INVARIANT_OUT_PREFIX)execution.timestamp + $(DIR_GUARD) + @echo "Debugging $*..." + @kprove $< --directory $(INVARIANT_DIR) --haskell-backend-command $(DEBUG_COMMAND) + +$(INVARIANT_OUT_PREFIX)execution.timestamp: $(INVARIANT_DIR)/invariant-execution.k ${INVARIANT_EXECUTION} + $(DIR_GUARD) + @echo "Compiling execution..." + @kompile $(KOMPILE_FLAGS) $< --backend haskell --directory $(INVARIANT_DIR) + @touch $(INVARIANT_OUT_PREFIX)execution.timestamp + +invariant.clean: + -rm -r $(INVARIANT_DIR)/*-kompiled + -rm -r .kprove-* + -rm kore-*.tar.gz + -rm $(INVARIANT_OUT_PREFIX)* + -rm *.log diff --git a/multisig/protocol-correctness/proof/invariant/perform-parts.k b/multisig/protocol-correctness/proof/invariant/perform-parts.k new file mode 100644 index 000000000..e122777e8 --- /dev/null +++ b/multisig/protocol-correctness/proof/invariant/perform-parts.k @@ -0,0 +1,310 @@ +require "protocol-correctness/pseudocode.k" +require "protocol-correctness/proof/execution-proof-helpers.k" +require "protocol-correctness/proof/invariant.k" + +module PERFORM-PARTS + + imports EXECUTION-PROOF-HELPERS + imports INVARIANT-HELPERS + imports PSEUDOCODE + + syntax Bool ::= performRequires( + action:Action, + numUsers:Usize, + userIdToAddress:Map, + addressToUserId:Map, + numBoardMembers:Usize, + numProposers:Usize, + userIdToRole:Map, + quorum:Usize) + [function, functional] + syntax Bool ::= performRequiresHandling( + action:Action, + numUsers:Usize, + userIdToAddress:Map, + addressToUserId:Map, + numBoardMembers:Usize, + numProposers:Usize, + userIdToRole:Map, + quorum:Usize, + handling:PropertyHandling) + [function, functional] + syntax Bool ::= performEnsures( + numUsers:Usize, + userIdToAddress:Map, + addressToUserId:Map, + numBoardMembers:Usize, + numProposers:Usize, + userIdToRole:Map, + quorum:Usize) + [function, functional] + syntax Bool ::= performEnsuresHandling( + numUsers:Usize, + userIdToAddress:Map, + addressToUserId:Map, + numBoardMembers:Usize, + numProposers:Usize, + userIdToRole:Map, + quorum:Usize, + handling:PropertyHandling) + [function, functional] + syntax Bool ::= performInvariant( + numUsers:Usize, + userIdToAddress:Map, + addressToUserId:Map, + numBoardMembers:Usize, + numProposers:Usize, + userIdToRole:Map, + quorum:Usize, + handling:PropertyHandling) + [function, functional] + syntax TTCell ::= performLhs( + action:Action, + K, + numUsers:Usize, + userIdToAddress:Map, + addressToUserId:Map, + numBoardMembers:Usize, + numProposers:Usize, + userIdToRole:Map, + quorum:Usize, + ActionStateCell, + stack:Stack, + callerAddress:Address, + performedActions:List) + [function, functional] + syntax TTCell ::= performRhs( + result:KItem, + K, + numUsers:Usize, + userIdToAddress:Map, + addressToUserId:Map, + numBoardMembers:Usize, + numProposers:Usize, + userIdToRole:Map, + quorum:Usize, + ActionStateCell, + variables:Map, + stack:Stack, + callerAddress:Address, + performedActions:List) + [function, functional] + + rule performRequires( + Action:Action, + UNumUsers:Usize, + UserIdToAddress:Map, + AddressToUserId:Map, + u(NumBoardMembers:Int), + u(NumProposers:Int), + UserIdToRole:Map, + u(Quorum:Int)) + => performRequiresHandling( + Action, + UNumUsers, + UserIdToAddress, + AddressToUserId, + u(NumBoardMembers), + u(NumProposers), + UserIdToRole, + u(Quorum), + expand(expanded)) + + rule performRequiresHandling( + Action:Action, + UNumUsers:Usize, + UserIdToAddress:Map, + AddressToUserId:Map, + u(NumBoardMembers:Int), + u(NumProposers:Int), + UserIdToRole:Map, + u(Quorum:Int), + Handling:PropertyHandling) + => true + andBool isKResult(Action) + andBool performInvariant( + UNumUsers, + UserIdToAddress, + AddressToUserId, + u(NumBoardMembers), + u(NumProposers), + UserIdToRole, + u(Quorum), + Handling) + + rule performEnsures( + UNumUsers:Usize, + UserIdToAddress:Map, + AddressToUserId:Map, + u(NumBoardMembers:Int), + u(NumProposers:Int), + UserIdToRole:Map, + u(Quorum:Int)) + => performEnsuresHandling( + UNumUsers, + UserIdToAddress, + AddressToUserId, + u(NumBoardMembers), + u(NumProposers), + UserIdToRole, + u(Quorum), + usesExpanded) + + rule performEnsuresHandling( + UNumUsers:Usize, + UserIdToAddress:Map, + AddressToUserId:Map, + u(NumBoardMembers:Int), + u(NumProposers:Int), + UserIdToRole:Map, + u(Quorum:Int), + Handling:PropertyHandling) + => true + andBool performInvariant( + UNumUsers, + UserIdToAddress, + AddressToUserId, + u(NumBoardMembers), + u(NumProposers), + UserIdToRole, + u(Quorum), + Handling) + + // TODO: Use the main invariant. + rule performInvariant( + u(NumUsers:Int), + UserIdToAddress:Map, + AddressToUserId:Map, + u(NumBoardMembers:Int), + u(NumProposers:Int), + UserIdToRole:Map, + u(Quorum:Int), + Handling:PropertyHandling) + => true + andBool notBool u(0) in_keys(UserIdToAddress) + andBool notBool u(0) in_keys(UserIdToRole) + + andBool allValuesBecomeKeys(AddressToUserId, UserIdToAddress) + andBool allValuesBecomeKeys(UserIdToAddress, AddressToUserId) + + andBool addressToUserIdInvariant(AddressToUserId) + // andBool valuesAreOfType(AddressToUserId, rUsize) + // andBool valuesAreKResult(AddressToUserId) + // andBool valuesAreNotEmpty(AddressToUserId, rUsize) + // andBool valuesAreDistinct(AddressToUserId) + andBool unusedIdsInMapValues(NumUsers +Int 1, AddressToUserId, Handling) + andBool noReusedIndexValue(NumUsers +Int 1, AddressToUserId, Handling) + + andBool unusedIdsInMapKeys(NumUsers +Int 1, keysMap(UserIdToAddress), Handling) + + andBool userIdToRoleInvariant(UserIdToRole) + // andBool valuesAreOfType(UserIdToRole, rUserRole) + // andBool valuesAreKResult(UserIdToRole) + // andBool valuesAreNotEmpty(UserIdToRole, rUserRole) + andBool unusedIdsInMapKeys(NumUsers +Int 1, keysMap(UserIdToRole), Handling) + + andBool NumUsers >=Int 0 // TODO: Strict >? + andBool NumBoardMembers >=Int 0 + andBool NumProposers >=Int 0 + + andBool Quorum <=Int NumBoardMembers + andBool (NumBoardMembers +Int NumProposers >Int 0) + + andBool NumBoardMembers ==Int countMapValues(UserIdToRole, wrap(BoardMember)) + andBool NumProposers ==Int countMapValues(UserIdToRole, wrap(Proposer)) + rule performLhs( + Action:Action, + K:K, + NumUsers:Usize, + UserIdToAddress:Map, + AddressToUserId:Map, + NumBoardMembers:Usize, + NumProposers:Usize, + UserIdToRole:Map, + Quorum:Usize, + ActionState:ActionStateCell, + Stack:Stack, + CallerAddress:Address, + PerformedActions:List) + => + + call(performAction(Action)) ~> K + + + + NumUsers + UserIdToAddress + AddressToUserId + + + NumBoardMembers + NumProposers + UserIdToRole + Quorum + + ActionState + + + + .Map + + Stack + + + CallerAddress + + + PerformedActions + + + + + rule performRhs( + Result:KItem, + K:K, + NumUsers:Usize, + UserIdToAddress:Map, + AddressToUserId:Map, + NumBoardMembers:Usize, + NumProposers:Usize, + UserIdToRole:Map, + Quorum:Usize, + ActionState:ActionStateCell, + Variables:Map, + Stack:Stack, + CallerAddress:Address, + PerformedActions:List) + => + + Result ~> K + + + + NumUsers + UserIdToAddress + AddressToUserId + + + NumBoardMembers + NumProposers + UserIdToRole + Quorum + + ActionState + + + + Variables + + Stack + + + CallerAddress + + + PerformedActions + + + + +endmodule diff --git a/multisig/protocol-correctness/proof/invariant/proof-count-can-sign.k b/multisig/protocol-correctness/proof/invariant/proof-count-can-sign.k new file mode 100644 index 000000000..3bcb019b0 --- /dev/null +++ b/multisig/protocol-correctness/proof/invariant/proof-count-can-sign.k @@ -0,0 +1,116 @@ +// TODO: Delete and use the one in functions + +module TRUSTED-COUNT-CAN-SIGNz + imports COUNT-CAN-SIGN-PARTS + + claim countCanSignLhs( + SignerIds:ExpressionList, + K:K, + Users:UsersCell, + NumBoardMembers:Usize, + NumProposers:Usize, + UserIdToRole:Map, + Quorum:Usize, + ActionState:ActionStateCell, + Variables:Map, + Stack:Stack, + ExternalCallEnv:ExternalCallEnvCell, + PerformedActions:List) + + => countCanSignRhs( + u(countCanSignFunction(SignerIds, opaque(UserIdToRole))), + K, + Users, + NumBoardMembers, + NumProposers, + UserIdToRole, + Quorum, + ActionState, + ?Variables:Map, + Stack, + ExternalCallEnv, + PerformedActions:List) + + requires + countCanSignRequires( + SignerIds, + Users, + NumBoardMembers, + NumProposers, + UserIdToRole, + Quorum, + ActionState, + Variables, + Stack, + ExternalCallEnv) + ensures + countCanSignEnsures( + u(countCanSignFunction(SignerIds, opaque(UserIdToRole))), + Users, + NumBoardMembers, + NumProposers, + UserIdToRole, + Quorum, + ActionState, + ?Variables, + Stack, + ExternalCallEnv) + [trusted] + +endmodule + +module PROOF-COUNT-CAN-SIGNz + imports INVARIANT-EXECUTION + + claim countCanSignLhs( + SignerIds:ExpressionList, + K:K, + Users:UsersCell, + NumBoardMembers:Usize, + NumProposers:Usize, + UserIdToRole:Map, + Quorum:Usize, + ActionState:ActionStateCell, + Variables:Map, + Stack:Stack, + ExternalCallEnv:ExternalCallEnvCell) + + => countCanSignRhs( + ?Count:Usize, + K, + Users, + NumBoardMembers, + NumProposers, + UserIdToRole, + Quorum, + ActionState, + ?Variables:Map, + Stack, + ExternalCallEnv) + + requires + countCanSignRequires( + SignerIds, + Users, + NumBoardMembers, + NumProposers, + UserIdToRole, + Quorum, + ActionState, + Variables, + Stack, + ExternalCallEnv) + ensures + countCanSignEnsures( + ?Count, + Users, + NumBoardMembers, + NumProposers, + UserIdToRole, + Quorum, + ActionState, + ?Variables, + Stack, + ExternalCallEnv) + +endmodule diff --git a/multisig/protocol-correctness/proof/invariant/proof-discard-action.k b/multisig/protocol-correctness/proof/invariant/proof-discard-action.k new file mode 100644 index 000000000..acbb362a2 --- /dev/null +++ b/multisig/protocol-correctness/proof/invariant/proof-discard-action.k @@ -0,0 +1,81 @@ +require "protocol-correctness/proof/functions/trusted-discard-action-has-signers.k" //@ Bazel remove +require "protocol-correctness/proof/functions/trusted-discard-action-no-role.k" //@ Bazel remove +require "protocol-correctness/proof/functions/trusted-discard-action-no-signers.k" //@ Bazel remove +require "protocol-correctness/proof/functions/trusted-discard-action-no-signers-no-action.k" //@ Bazel remove +require "protocol-correctness/proof/functions/trusted-discard-action-no-user.k" //@ Bazel remove +require "protocol-correctness/proof/functions/trusted-discard-action-no-valid-signers.k" //@ Bazel remove +require "protocol-correctness/proof/functions/trusted-discard-action-no-valid-signers-no-action.k" //@ Bazel remove + +module PROOF-DISCARD-ACTION + imports INVARIANT-EXECUTION + imports PSEUDOCODE + + imports TRUSTED-DISCARD-ACTION-HAS-SIGNERS + imports TRUSTED-DISCARD-ACTION-NO-ROLE + imports TRUSTED-DISCARD-ACTION-NO-SIGNERS + imports TRUSTED-DISCARD-ACTION-NO-SIGNERS-NO-ACTION + imports TRUSTED-DISCARD-ACTION-NO-USER + imports TRUSTED-DISCARD-ACTION-NO-VALID-SIGNERS + imports TRUSTED-DISCARD-ACTION-NO-VALID-SIGNERS-NO-ACTION + + claim + runExternalCalls( + ( from _:Address run discardAction(ActionId:Usize); + EC:ExternalCommands + ) + ) + + invariantState( + NumUsers:Usize, + UserIdToAddress:Map, + AddressToUserId:Map, + NumBoardMembers:Usize, + NumProposers:Usize, + UserRoles:Map, + Quorum:Usize, + ActionLastIndex0:Usize, + ActionData0:Map, + ActionSigners0:Map, + PerformedActions:List) + + => + + runExternalCalls(EC) + invariantState( + NumUsers, + UserIdToAddress, + AddressToUserId, + NumBoardMembers, + NumProposers, + UserRoles, + Quorum, + ?ActionLastIndex1:Usize, + ?ActionData1:Map, + ?ActionSigners1:Map, + PerformedActions:List):StateCell + + requires invariant( + NumUsers, + UserIdToAddress, + AddressToUserId, + NumBoardMembers, + NumProposers, + UserRoles, + Quorum, + ActionLastIndex0, + ActionData0, + ActionSigners0, + expand(expanded)) + ensures invariant( + NumUsers, + UserIdToAddress, + AddressToUserId, + NumBoardMembers, + NumProposers, + UserRoles, + Quorum, + ?ActionLastIndex1:Usize, + ?ActionData1:Map, + ?ActionSigners1:Map, + usesExpanded) +endmodule diff --git a/multisig/protocol-correctness/proof/invariant/proof-init-loop.k b/multisig/protocol-correctness/proof/invariant/proof-init-loop.k new file mode 100644 index 000000000..3fb85dc17 --- /dev/null +++ b/multisig/protocol-correctness/proof/invariant/proof-init-loop.k @@ -0,0 +1,188 @@ +module TRUSTED-INIT-LOOP + imports INVARIANT-EXECUTION + imports INIT-LOOP-PARTS + imports PSEUDOCODE + + claim initLoopLhs( + PrevIndex:Usize, + Addresses:ExpressionList, + K:K, + UserIdToAddress0:Map, + AddressToUserId0:Map, + UserIdToRole0:Map, + Quorum:Usize, + ActionState:ActionStateCell, + .Map, // TODO: Variables:Map, + Stack:Stack, + ExternalCallEnv:ExternalCallEnvCell, + _Address0:Expression, + _UserId0:Usize) + + => + initLoopRhs( + evaluate(void), + K, + ?UserIdToAddress1:Map, + ?AddressToUserId1:Map, + ?UserIdToRole1, + Quorum, + ActionState, + .Map, // TODO: Variables, + Stack, + ExternalCallEnv, + add(PrevIndex, u(pListLen(Addresses))), + ?_Address1:Expression, + ?_UserId1:Usize) + + requires + initLoopRequires( + PrevIndex, + Addresses, + UserIdToAddress0, + AddressToUserId0, + UserIdToRole0) + andBool noCommonItem(add(PrevIndex, u(2)), AddressToUserId0, Addresses) + ensures + initLoopEnsures( + add(add(PrevIndex, u(pListLen(Addresses))), u(1)), + Addresses, + ?UserIdToAddress1, + ?AddressToUserId1, + UserIdToRole0, + ?UserIdToRole1) + [trusted] + + claim initLoopLhs( + PrevIndex:Usize, + Addresses:ExpressionList, + K:K, + UserIdToAddress0:Map, + AddressToUserId0:Map, + UserIdToRole0:Map, + Quorum:Usize, + ActionState:ActionStateCell, + .Map, // TODO: Variables:Map, + Stack:Stack, + ExternalCallEnv:ExternalCallEnvCell, + _Address0:Expression, + _UserId0:Usize) + + => + initLoopRhs( + error, + K, + ?_UserIdToAddress1:Map, + ?_AddressToUserId1:Map, + ?_UserIdToRole1:Map, + Quorum, + ActionState, + .Map, // TODO: Variables, + Stack, + ExternalCallEnv, + add(PrevIndex, u(pListLen(Addresses))), + ?_Address1:Expression, + ?_UserId1:Usize) + + requires + initLoopRequires( + PrevIndex, + Addresses, + UserIdToAddress0, + AddressToUserId0, + UserIdToRole0) + andBool notBool noCommonItem(add(PrevIndex, u(2)), AddressToUserId0, Addresses) + [trusted] +endmodule + +module PROOF-INIT-LOOP + imports INIT-LOOP-PARTS + + claim initLoopLhs( + PrevIndex:Usize, + Addresses:ExpressionList, + K:K, + UserIdToAddress0:Map, + AddressToUserId0:Map, + UserIdToRole0:Map, + Quorum:Usize, + ActionState:ActionStateCell, + .Map, // TODO: Variables:Map, + Stack:Stack, + ExternalCallEnv:ExternalCallEnvCell, + _Address0:Expression, + _UserId0:Usize) + + => + initLoopRhs( + evaluate(void), + K, + ?UserIdToAddress1:Map, + ?AddressToUserId1:Map, + ?UserIdToRole1, + Quorum, + ActionState, + .Map, // TODO: Variables, + Stack, + ExternalCallEnv, + add(PrevIndex, u(pListLen(Addresses))), + ?_Address1:Expression, + ?_UserId1:Usize) + + requires + initLoopRequires( + PrevIndex, + Addresses, + UserIdToAddress0, + AddressToUserId0, + UserIdToRole0) + andBool noCommonItem(add(PrevIndex, u(2)), AddressToUserId0, Addresses) + ensures + initLoopEnsures( + add(add(PrevIndex, u(pListLen(Addresses))), u(1)), + Addresses, + ?UserIdToAddress1, + ?AddressToUserId1, + UserIdToRole0, + ?UserIdToRole1) + + claim initLoopLhs( + PrevIndex:Usize, + Addresses:ExpressionList, + K:K, + UserIdToAddress0:Map, + AddressToUserId0:Map, + UserIdToRole0:Map, + Quorum:Usize, + ActionState:ActionStateCell, + .Map, // TODO: Variables:Map, + Stack:Stack, + ExternalCallEnv:ExternalCallEnvCell, + _Address0:Expression, + _UserId0:Usize) + + => + initLoopRhs( + error, + K, + ?_UserIdToAddress1:Map, + ?_AddressToUserId1:Map, + ?_UserIdToRole1, + Quorum, + ActionState, + .Map, // TODO: Variables, + Stack, + ExternalCallEnv, + add(PrevIndex, u(pListLen(Addresses))), + ?_Address1:Expression, + ?_UserId1:Usize) + + requires + initLoopRequires( + PrevIndex, + Addresses, + UserIdToAddress0, + AddressToUserId0, + UserIdToRole0) + andBool notBool noCommonItem(add(PrevIndex, u(2)), AddressToUserId0, Addresses) + +endmodule diff --git a/multisig/protocol-correctness/proof/invariant/proof-init.k b/multisig/protocol-correctness/proof/invariant/proof-init.k new file mode 100644 index 000000000..f65107d2f --- /dev/null +++ b/multisig/protocol-correctness/proof/invariant/proof-init.k @@ -0,0 +1,72 @@ +require "proof-init-loop.k" + +module PROOF-INIT + imports INVARIANT-EXECUTION + imports PSEUDOCODE + imports TRUSTED-INIT-LOOP + + rule forall-v-greater-or-equal-than-u-v-not-in-m(_:Usize, .Map, _:ExpressionList) + => true [simplification] + + claim call(listLen(L:ExpressionList)) => u(pListLen(L)) + requires isKResult(L) + [trusted] + + claim + runExternalCalls( + ( from _:Address run init(_Quorum:Usize, Addresses:ExpressionList); + EC:ExternalCommands + ) + ) + + initialState + + => + + runExternalCalls(EC) + invariantState( + ?NumUsers:Usize, + ?UserIdToAddress:Map, + ?AddressToUserId:Map, + ?NumBoardMembers:Usize, + ?NumProposers:Usize, + ?UserIdToRole:Map, + ?Quorum:Usize, + ?ActionLastIndex:Usize, + ?ActionData:Map, + ?ActionSigners:Map, + ?PerformedActions:List) + + requires listElementsAreAddresses(Addresses) + //andBool noCommonItem(u(1), .Map, Addresses) + + andBool isKResult(Addresses) + andBool noReusedIndexAddress(u(1), .Map, Addresses) + andBool noReusedIndexRole(u(1), .Map, Addresses) + + ensures invariant( + ?NumUsers, + ?UserIdToAddress, + ?AddressToUserId, + ?NumBoardMembers, + ?NumProposers, + ?UserIdToRole, + ?Quorum, + ?ActionLastIndex, + ?ActionData, + ?ActionSigners, + usesExpanded) + orBool invariantState( + ?NumUsers:Usize, + ?UserIdToAddress:Map, + ?AddressToUserId:Map, + ?NumBoardMembers:Usize, + ?NumProposers:Usize, + ?UserIdToRole:Map, + ?Quorum:Usize, + ?ActionLastIndex:Usize, + ?ActionData:Map, + ?ActionSigners:Map, + ?PerformedActions:List) + ==K initialState +endmodule diff --git a/multisig/protocol-correctness/proof/invariant/proof-listlen.k b/multisig/protocol-correctness/proof/invariant/proof-listlen.k new file mode 100644 index 000000000..710f02c45 --- /dev/null +++ b/multisig/protocol-correctness/proof/invariant/proof-listlen.k @@ -0,0 +1,14 @@ +module PROOF-LISTLEN + imports PSEUDOCODE + imports INVARIANT-EXECUTION + + // TODO: Remove the cell. + claim call(listLen([.])) => u(0) ... + + claim call(listLen([E:Expression , Es:ExpressionCSV])) => u(1 +Int pListLen([Es])) ... + requires isKResult(E) andBool isKResult(Es) + + claim call(listLen(L:ExpressionList)) => u(pListLen(L)) ... + requires isKResult(L) + +endmodule diff --git a/multisig/protocol-correctness/proof/invariant/proof-perform-action-endpoint.k b/multisig/protocol-correctness/proof/invariant/proof-perform-action-endpoint.k new file mode 100644 index 000000000..a96a53fa6 --- /dev/null +++ b/multisig/protocol-correctness/proof/invariant/proof-perform-action-endpoint.k @@ -0,0 +1,110 @@ +//@ proof +require "trusted-perform-parts-1.k" //@ Bazel remove + +module PROOF-PERFORM-ACTION-ENDPOINT + imports INVARIANT-EXECUTION + + imports TRUSTED-PERFORM-PARTS-1 +//@ trusted +// module TRUSTED-PERFORM-ACTION-ENDPOINT +//@ end + + claim + runExternalCalls( + ( from _:Address run performActionEndpoint(_ActionId:Usize); + EC:ExternalCommands + ) + ) + + invariantState( + NumUsers:Usize, + UserIdToAddress:Map, + AddressToUserId:Map, + NumBoardMembers:Usize, + NumProposers:Usize, + UserRoles:Map, + Quorum:Usize, + ActionLastIndex0:Usize, + ActionData0:Map, + ActionSigners0:Map, + _PerformedActions:List) + + => + + runExternalCalls(EC) + invariantState( + ?NumUsers1:Usize, + ?UserIdToAddress1:Map, + ?AddressToUserId1:Map, + ?NumBoardMembers1:Usize, + ?NumProposers1:Usize, + ?UserRoles1:Map, + ?Quorum1:Usize, + ?ActionLastIndex1:Usize, + ?ActionData1:Map, + ?ActionSigners1:Map, + ?_PerformedActions:List):StateCell + + requires invariant( + NumUsers:Usize, + UserIdToAddress:Map, + AddressToUserId:Map, + NumBoardMembers:Usize, + NumProposers:Usize, + UserRoles:Map, + Quorum:Usize, + ActionLastIndex0:Usize, + ActionData0:Map, + ActionSigners0:Map, + expand(expanded)) + ensures invariant( + ?NumUsers1:Usize, + ?UserIdToAddress1:Map, + ?AddressToUserId1:Map, + ?NumBoardMembers1:Usize, + ?NumProposers1:Usize, + ?UserRoles1:Map, + ?Quorum1:Usize, + ?ActionLastIndex1:Usize, + ?ActionData1:Map, + ?ActionSigners1:Map, + usesExpanded) + + claim + call(getActionSignerIds(ActionId:Usize)) ~> K:K + + invariantState( + NumUsers:Usize, + UserIdToAddress:Map, + AddressToUserId:Map, + NumBoardMembers:Usize, + NumProposers:Usize, + UserRoles:Map, + Quorum:Usize, + ActionLastIndex:Usize, + ActionData:Map, + ActionSigners:Map, + _PerformedActions:List):StateCell + + => + + ActionSigners[ActionId] orDefault [.] ~> K + invariantState( + NumUsers:Usize, + UserIdToAddress:Map, + AddressToUserId:Map, + NumBoardMembers:Usize, + NumProposers:Usize, + UserRoles:Map, + Quorum:Usize, + ActionLastIndex:Usize, + ActionData:Map, + ActionSigners:Map, + ?_PerformedActions:List):StateCell + + //@ proof + //@ trusted + // [trusted] + //@ end + +endmodule diff --git a/multisig/protocol-correctness/proof/invariant/proof-perform-action.k b/multisig/protocol-correctness/proof/invariant/proof-perform-action.k new file mode 100644 index 000000000..9be5ee9ab --- /dev/null +++ b/multisig/protocol-correctness/proof/invariant/proof-perform-action.k @@ -0,0 +1,253 @@ +require "proof-perform-add-board-member.k" +require "proof-perform-add-proposer-1.k" +require "proof-perform-add-proposer-3.k" +require "proof-perform-add-proposer-5.k" +require "proof-perform-add-proposer-7.k" +require "proof-perform-add-proposer-8.k" +require "proof-perform-add-proposer-9.k" +require "proof-perform-change-quorum.k" +require "proof-perform-nothing.k" +require "proof-perform-remove-user-1.k" +require "proof-perform-remove-user-3.k" +require "proof-perform-remove-user-5.k" +require "proof-perform-remove-user-7.k" +require "proof-perform-remove-user-9.k" +require "proof-perform-remove-user-10.k" +require "proof-perform-s-c-call.k" +require "proof-perform-s-c-deploy.k" +require "proof-perform-send-egld.k" + +module TRUSTED-PERFORM-ACTION + imports INVARIANT-EXECUTION + + claim + + + splitAction ( A:Action ) + ~> splitting-action + ~> call ( performAction ( A ) ) + ~> popContext + ~> evaluateReturnValue + ~> popContext + ~> evaluateReturnValue + ~> popContext + ~> evaluateReturnValue + ~> clearExternalCallEnv + ~> runExternalCalls ( EC ) + + invariantStateStack( + NumUsers:Usize, + UserIdToAddress:Map, + AddressToUserId:Map, + NumBoardMembers:Usize, + NumProposers:Usize, + UserRoles:Map, + Quorum:Usize, + ActionLastIndex0:Usize, + ActionData0:Map, + ActionSigners0:Map, + CallerAddress:Address, + ListItem(stackEntry(_:MultisigStateCell, _:Map)) + ListItem(stackEntry(_:MultisigStateCell, _:Map)) + ListItem(stackEntry( + invariantMultisigState( + NumUsersS:Usize, + UserIdToAddressS:Map, + AddressToUserIdS:Map, + NumBoardMembersS:Usize, + NumProposersS:Usize, + UserRolesS:Map, + QuorumS:Usize, + ActionLastIndexS:Usize, + ActionDataS:Map, + ActionSignersS:Map):MultisigStateCell, + .Map)), + _PerformedActions:List) + + => + + clearExternalCallEnv + ~> runExternalCalls(EC) + invariantStateStack( + u(?NumUsers1:Int), + ?UserIdToAddress1:Map, + ?AddressToUserId1:Map, + u(?NumBoardMembers1:Int), + u(?NumProposers1:Int), + ?UserRoles1:Map, + u(?Quorum1:Int), + u(?ActionLastIndex1:Int), + ?ActionData1:Map, + ?ActionSigners1:Map, + CallerAddress:Address, + .List, + ?_PerformedActions:List):StateCell + + requires true + andBool invariant( + NumUsers:Usize, + UserIdToAddress:Map, + AddressToUserId:Map, + NumBoardMembers:Usize, + NumProposers:Usize, + UserRoles:Map, + Quorum:Usize, + ActionLastIndex0:Usize, + ActionData0:Map, + ActionSigners0:Map, + usesExpanded) + andBool invariant( + NumUsersS:Usize, + UserIdToAddressS:Map, + AddressToUserIdS:Map, + NumBoardMembersS:Usize, + NumProposersS:Usize, + UserRolesS:Map, + QuorumS:Usize, + ActionLastIndexS:Usize, + ActionDataS:Map, + ActionSignersS:Map, + usesExpanded) + andBool isKResult(A) + ensures true + andBool invariant( + u(?NumUsers1), + ?UserIdToAddress1, + ?AddressToUserId1, + u(?NumBoardMembers1), + u(?NumProposers1), + ?UserRoles1, + u(?Quorum1), + u(?ActionLastIndex1), + ?ActionData1, + ?ActionSigners1, + expanded) + [trusted] +endmodule + +module PROOF-PERFORM-ACTION + imports INVARIANT-EXECUTION + + imports TRUSTED-PERFORM-ADD-BOARD-MEMBER + imports TRUSTED-PERFORM-ADD-PROPOSER-1 + imports TRUSTED-PERFORM-ADD-PROPOSER-3 + imports TRUSTED-PERFORM-ADD-PROPOSER-5 + imports TRUSTED-PERFORM-ADD-PROPOSER-7 + imports TRUSTED-PERFORM-ADD-PROPOSER-8 + imports TRUSTED-PERFORM-ADD-PROPOSER-9 + imports TRUSTED-PERFORM-CHANGE-QUORUM + imports TRUSTED-PERFORM-NOTHING + imports TRUSTED-PERFORM-REMOVE-USER-1 + imports TRUSTED-PERFORM-REMOVE-USER-3 + imports TRUSTED-PERFORM-REMOVE-USER-5 + imports TRUSTED-PERFORM-REMOVE-USER-7 + imports TRUSTED-PERFORM-REMOVE-USER-9 + imports TRUSTED-PERFORM-REMOVE-USER-10 + imports TRUSTED-PERFORM-S-C-CALL + imports TRUSTED-PERFORM-S-C-DEPLOY + imports TRUSTED-PERFORM-SEND-EGLD + + claim + + + splitAction ( A:Action ) + ~> splitting-action + ~> call ( performAction ( A ) ) + ~> popContext + ~> evaluateReturnValue + ~> popContext + ~> evaluateReturnValue + ~> popContext + ~> evaluateReturnValue + ~> clearExternalCallEnv + ~> runExternalCalls ( EC ) + + invariantStateStack( + NumUsers:Usize, + UserIdToAddress:Map, + AddressToUserId:Map, + NumBoardMembers:Usize, + NumProposers:Usize, + UserRoles:Map, + Quorum:Usize, + ActionLastIndex0:Usize, + ActionData0:Map, + ActionSigners0:Map, + CallerAddress:Address, + ListItem(stackEntry(_:MultisigStateCell, _:Map, _:List)) + ListItem(stackEntry(_:MultisigStateCell, _:Map, _:List)) + ListItem(stackEntry( + invariantMultisigState( + NumUsersS:Usize, + UserIdToAddressS:Map, + AddressToUserIdS:Map, + NumBoardMembersS:Usize, + NumProposersS:Usize, + UserRolesS:Map, + QuorumS:Usize, + ActionLastIndexS:Usize, + ActionDataS:Map, + ActionSignersS:Map):MultisigStateCell, + .Map, + _PerformedActionsS:List)), + _PerformedActions:List) + + => + + clearExternalCallEnv + ~> runExternalCalls(EC) + invariantStateStack( + u(?NumUsers1:Int), + ?UserIdToAddress1:Map, + ?AddressToUserId1:Map, + u(?NumBoardMembers1:Int), + u(?NumProposers1:Int), + ?UserRoles1:Map, + u(?Quorum1:Int), + u(?ActionLastIndex1:Int), + ?ActionData1:Map, + ?ActionSigners1:Map, + CallerAddress:Address, + .List, + ?_PerformedActions:List):StateCell + + requires true + andBool invariant( + NumUsers:Usize, + UserIdToAddress:Map, + AddressToUserId:Map, + NumBoardMembers:Usize, + NumProposers:Usize, + UserRoles:Map, + Quorum:Usize, + ActionLastIndex0:Usize, + ActionData0:Map, + ActionSigners0:Map, + expand(expanded)) + andBool invariant( + NumUsersS:Usize, + UserIdToAddressS:Map, + AddressToUserIdS:Map, + NumBoardMembersS:Usize, + NumProposersS:Usize, + UserRolesS:Map, + QuorumS:Usize, + ActionLastIndexS:Usize, + ActionDataS:Map, + ActionSignersS:Map, + expanded) + andBool isKResult(A) + ensures true + andBool invariant( + u(?NumUsers1), + ?UserIdToAddress1, + ?AddressToUserId1, + u(?NumBoardMembers1), + u(?NumProposers1), + ?UserRoles1, + u(?Quorum1), + u(?ActionLastIndex1), + ?ActionData1, + ?ActionSigners1, + usesExpanded) +endmodule diff --git a/multisig/protocol-correctness/proof/invariant/proof-perform-parts-1.k b/multisig/protocol-correctness/proof/invariant/proof-perform-parts-1.k new file mode 100644 index 000000000..cf05f2337 --- /dev/null +++ b/multisig/protocol-correctness/proof/invariant/proof-perform-parts-1.k @@ -0,0 +1,573 @@ +//@ proof +require "trusted-perform-parts-add-board-member.k" //@ Bazel remove +require "trusted-perform-parts-add-proposer-signers.k" //@ Bazel remove +require "trusted-perform-parts-add-proposer-no-signers.k" //@ Bazel remove +require "trusted-perform-parts-change-quorum.k" //@ Bazel remove +require "trusted-perform-parts-New.k" //@ Bazel remove +require "trusted-perform-parts-no-quorum.k" //@ Bazel remove +require "trusted-perform-parts-None.k" //@ Bazel remove +require "trusted-perform-parts-remove-user.k" //@ Bazel remove +require "trusted-perform-parts-sc-call.k" //@ Bazel remove +require "trusted-perform-parts-sc-deploy.k" //@ Bazel remove +require "trusted-perform-parts-send-egld.k" //@ Bazel remove + + +module PROOF-PERFORM-PARTS-1 + imports INVARIANT-EXECUTION + + imports TRUSTED-PERFORM-PARTS-ADD-BOARD-MEMBER + imports TRUSTED-PERFORM-PARTS-ADD-PROPOSER-SIGNERS + imports TRUSTED-PERFORM-PARTS-ADD-PROPOSER-NO-SIGNERS + imports TRUSTED-PERFORM-PARTS-CHANGE-QUORUM + imports TRUSTED-PERFORM-PARTS-NEW + imports TRUSTED-PERFORM-PARTS-NO-QUORUM + imports TRUSTED-PERFORM-PARTS-NONE + imports TRUSTED-PERFORM-PARTS-REMOVE-USER + imports TRUSTED-PERFORM-PARTS-SC-CALL + imports TRUSTED-PERFORM-PARTS-SC-DEPLOY + imports TRUSTED-PERFORM-PARTS-SEND-EGLD +//@ trusted +// module TRUSTED-PERFORM-PARTS-1 +//@ end + imports PERFORM-ACTION-ENDPOINT-INSTRUMENTATION + + claim + splitAction(Action:Action) + ~> splitPerformActionEndpoint4(Action) + ~> call(performActionEndpoint(ActionId:Usize)) + ~> popContext + ~> evaluateReturnValue + ~> clearExternalCallEnv + ~> splitActionSigners(ActionId:Usize, ActionSigners:Map) + ~> runExternalCalls(EC:ExternalCommands) + + invariantStateStack( + NumUsers:Usize, + UserIdToAddress:Map, + (CallerAddress |-> CallerId:Usize _AddressToUserId:Map) #as AddressToUserId:Map, + NumBoardMembers:Usize, + NumProposers:Usize, + (CallerId |-> CallerRole:UserRole _UserIdToRole:Map) #as UserIdToRole:Map, + u(Quorum:Int), + ActionLastIndex0:Usize, + (ActionId |-> Action _ActionData:Map) #as ActionData:Map, + (ActionId |-> Signers:ExpressionList _ActionSigners:Map) #as ActionSigners:Map, + CallerAddress:Address, + stack( + invariantMultisigState( + NumUsers, + UserIdToAddress, + AddressToUserId, + NumBoardMembers, + NumProposers, + UserIdToRole, + u(Quorum), + ActionLastIndex0, + ActionData, + ActionSigners), + .Map, + PerformedActions, + .stack), + PerformedActions:List) + + => + + runExternalCalls(EC) + invariantState( + ?NumUsers1:Usize, + ?UserIdToAddress1:Map, + ?AddressToUserId1:Map, + ?NumBoardMembers1:Usize, + ?NumProposers1:Usize, + ?UserIdToRole1:Map, + ?Quorum1:Usize, + ?ActionLastIndex1:Usize, + ?ActionData1:Map, + ?ActionSigners1:Map, + ?_PerformedActions:List):StateCell + + requires true + andBool invariant( + NumUsers, + UserIdToAddress, + AddressToUserId, + NumBoardMembers, + NumProposers, + UserIdToRole, + u(Quorum), + ActionLastIndex0, + ActionData, + ActionSigners, + expand(expanded)) + andBool (CallerRole ==K BoardMember orBool CallerRole ==K Proposer) + andBool Quorum <=Int countCanSignFunction({ActionSigners[ActionId] orDefault [.]}:>ExpressionList, opaque(UserIdToRole)) + ensures invariant( + ?NumUsers1, + ?UserIdToAddress1, + ?AddressToUserId1, + ?NumBoardMembers1, + ?NumProposers1, + ?UserIdToRole1, + ?Quorum1, + ?ActionLastIndex1, + ?ActionData1, + ?ActionSigners1, + usesExpanded) + //@ proof + //@ trusted + // [trusted] + //@ end +endmodule + +/* + #Not ( { + A + #Equals + Nothing + } ) +#And + #Not ( { + CSV + #Equals + . + } ) +#And + #Not ( { + V + #Equals + 0 + } ) +#And + #Not ( { + V + #Equals + NumUsers0 +Int 1 + } ) +#And + #Not ( { + V + #Equals + NumUsers0 +Int 2 + } ) +#And + #Not ( { + _ActionId0 + #Equals + ActionLastIndex1 +Int 1 + } ) +#And + + + + splitAction ( A ) ~> splitPerformActionEndpoint4 ( A ) ~> call ( performActionEndpoint ( u ( _ActionId0 ) ) ) ~> popContext ~> evaluateReturnValue ~> clearExternalCallEnv ~> splitActionSigners ( u ( _ActionId0 ) , 'QuesUnds'Remainder1 + u ( _ActionId0 ) |-> [ CSV ] ) ~> runExternalCalls ( EC ) ~> . + + + + + + u ( NumUsers0 ) + + + UserIdToAddress + + + 'QuesUnds'Remainder + address ( _1 ) |-> u ( V ) + + + + + u ( countMapValues ( 'QuesUnds'Remainder0 , wrap ( BoardMember ) ) ) + + + u ( countMapValues ( 'QuesUnds'Remainder0 , wrap ( Proposer ) ) +Int 1 ) + + + 'QuesUnds'Remainder0 + u ( V ) |-> Proposer + + + u ( Quorum0 ) + + + + + u ( ActionLastIndex1 ) + + + + 'QuesUnds'Remainder2 + u ( _ActionId0 ) |-> A:Action + + + 'QuesUnds'Remainder1 + u ( _ActionId0 ) |-> [ CSV ] + + + + + + + .Map + + + stack ( + + + u ( NumUsers0 ) + + + UserIdToAddress + + + 'QuesUnds'Remainder + address ( _1 ) |-> u ( V ) + + + + + u ( countMapValues ( 'QuesUnds'Remainder0 , wrap ( BoardMember ) ) ) + + + u ( countMapValues ( 'QuesUnds'Remainder0 , wrap ( Proposer ) ) +Int 1 ) + + + 'QuesUnds'Remainder0 + u ( V ) |-> Proposer + + + u ( Quorum0 ) + + + + + u ( ActionLastIndex1 ) + + + + 'QuesUnds'Remainder2 + u ( _ActionId0 ) |-> A:Action + + + 'QuesUnds'Remainder1 + u ( _ActionId0 ) |-> [ CSV ] + + + + , .Map , _PerformedActions , .stack ) + + + + + address ( _1 ) + + + + + _PerformedActions + + + + + +#And + { + 'QuesUnds'Value0 + #Equals + Proposer + } +#And + { + 'QuesUnds'Value1 + #Equals + [ CSV ] + } +#And + { + 'QuesUnds'Value2 + #Equals + A:Action + } +#And + { + 'QuesUnds'Value + #Equals + u ( V ) + } +#And + { + ActionData0 + #Equals + 'QuesUnds'Remainder2 + u ( _ActionId0 ) |-> A:Action + } +#And + { + ActionSigners0 + #Equals + 'QuesUnds'Remainder1 + u ( _ActionId0 ) |-> [ CSV ] + } +#And + { + AddressToUserId + #Equals + 'QuesUnds'Remainder + address ( _1 ) |-> u ( V ) + } +#And + { + U0 + #Equals + Proposer + } +#And + { + U + #Equals + u ( V ) + } +#And + { + UserRoles + #Equals + 'QuesUnds'Remainder0 + u ( V ) |-> Proposer + } +#And + { + V0 + #Equals + [ CSV ] + } +#And + { + false + #Equals + address ( _1 ) in_keys ( 'QuesUnds'Remainder ) + } +#And + { + false + #Equals + u ( 0 ) in_keys ( 'QuesUnds'Remainder0 ) + } +#And + { + false + #Equals + u ( 0 ) in_keys ( UserIdToAddress ) + } +#And + { + false + #Equals + u ( ActionLastIndex1 +Int 1 ) in_keys ( 'QuesUnds'Remainder1 ) + } +#And + { + false + #Equals + u ( ActionLastIndex1 +Int 1 ) in_keys ( 'QuesUnds'Remainder2 ) + } +#And + { + false + #Equals + u ( NumUsers0 +Int 1 ) in_keys ( 'QuesUnds'Remainder0 ) + } +#And + { + false + #Equals + u ( NumUsers0 +Int 1 ) in_keys ( UserIdToAddress ) + } +#And + { + false + #Equals + u ( V ) in_keys ( 'QuesUnds'Remainder0 ) + } +#And + { + false + #Equals + u ( _ActionId0 ) in_keys ( 'QuesUnds'Remainder1 ) + } +#And + { + false + #Equals + u ( _ActionId0 ) in_keys ( 'QuesUnds'Remainder2 ) + } +#And + { + true + #Equals + #allValuesBecomeKeys ( 'QuesUnds'Remainder , keysMap ( UserIdToAddress ) ) + } +#And + { + true + #Equals + #allValuesBecomeKeys ( UserIdToAddress , address ( _1 ) |-> 0 + keysMap ( 'QuesUnds'Remainder ) ) + } +#And + { + true + #Equals + #noReusedIndexValue ( NumUsers0 +Int 2 , 'QuesUnds'Remainder , expanded ) + } +#And + { + true + #Equals + NumUsers0 +Int 1 >Int V + } +#And + { + true + #Equals + NumUsers0 >=Int 0 + } +#And + { + true + #Equals + Quorum0 <=Int countCanSignFunction ( [ CSV ] , concat ( u ( V ) , Proposer , opaque ( 'QuesUnds'Remainder0 ) ) ) + } +#And + { + true + #Equals + Quorum0 <=Int countMapValues ( 'QuesUnds'Remainder0 , wrap ( BoardMember ) ) + } +#And + { + true + #Equals + _ActionId0 <=Int ActionLastIndex1 + } +#And + { + true + #Equals + actionDataInvariant ( 'QuesUnds'Remainder2 ) + } +#And + { + true + #Equals + actionSignersInvariant ( 'QuesUnds'Remainder1 ) + } +#And + { + true + #Equals + addressToUserIdInvariant ( 'QuesUnds'Remainder ) + } +#And + { + true + #Equals + countMapValues ( 'QuesUnds'Remainder0 , wrap ( BoardMember ) ) >=Int 0 + } +#And + { + true + #Equals + countMapValues ( 'QuesUnds'Remainder0 , wrap ( Proposer ) ) +Int 1 >=Int 0 + } +#And + { + true + #Equals + isKResult ( CSV:ExpressionCSV ~> . ) + } +#And + { + true + #Equals + isKResultAction ( A ) + } +#And + { + true + #Equals + listElementsAreUsize ( [ CSV ] ) + } +#And + { + true + #Equals + maxMapKey ( u ( ActionLastIndex1 ) , keysMap ( 'QuesUnds'Remainder1 ) ) + } +#And + { + true + #Equals + maxMapKey ( u ( ActionLastIndex1 ) , keysMap ( 'QuesUnds'Remainder2 ) ) + } +#And + { + true + #Equals + u ( V ) in_keys ( UserIdToAddress ) + } +#And + { + true + #Equals + unusedIdsInMapKeys ( ActionLastIndex1 +Int 2 , keysMap ( 'QuesUnds'Remainder1 ) , expanded ) + } +#And + { + true + #Equals + unusedIdsInMapKeys ( ActionLastIndex1 +Int 2 , keysMap ( 'QuesUnds'Remainder2 ) , expanded ) + } +#And + { + true + #Equals + unusedIdsInMapKeys ( NumUsers0 +Int 2 , keysMap ( 'QuesUnds'Remainder0 ) , expanded ) + } +#And + { + true + #Equals + unusedIdsInMapKeys ( NumUsers0 +Int 2 , keysMap ( UserIdToAddress ) , expanded ) + } +#And + { + true + #Equals + unusedIdsInMapValues ( NumUsers0 +Int 1 , 'QuesUnds'Remainder , expanded ) + } +#And + { + true + #Equals + userIdToRoleInvariant ( 'QuesUnds'Remainder0 ) + } +#And + { + true + #Equals + valueNotInMapValues ( u ( NumUsers0 +Int 1 ) , 'QuesUnds'Remainder ) + } +#And + { + true + #Equals + valueNotInMapValues ( u ( NumUsers0 +Int 2 ) , 'QuesUnds'Remainder ) + } +#And + { + true + #Equals + valueNotInMapValues ( u ( V ) , 'QuesUnds'Remainder ) + } +*/ \ No newline at end of file diff --git a/multisig/protocol-correctness/proof/invariant/proof-perform-parts-New.k b/multisig/protocol-correctness/proof/invariant/proof-perform-parts-New.k new file mode 100644 index 000000000..1e0855085 --- /dev/null +++ b/multisig/protocol-correctness/proof/invariant/proof-perform-parts-New.k @@ -0,0 +1,61 @@ +//@ proof +require "../functions/trusted-perform-action-endpoint-New.k" //@ Bazel remove + +module PROOF-PERFORM-PARTS-NEW + imports TRUSTED-PERFORM-ACTION-ENDPOINT-NEW +//@ trusted +// module TRUSTED-PERFORM-PARTS-NEW +//@ end + + imports PERFORM-ACTION-ENDPOINT-INSTRUMENTATION + + claim + new.k ~> call(performActionEndpoint(_ActionId:Usize)) ~> K:K + invariantStateFull( + NumUsers:Usize, + UserIdToAddress:Map, + AddressToUserId:Map, + NumBoardMembers:Usize, + NumProposers:Usize, + UserIdToRole:Map, + Quorum:Usize, + ActionLastIndex:Usize, + ActionData:Map, + ActionSigners:Map, + CallerAddress:Address, + Stack:Stack, + .Map, + PerformedActions:List + ) + + => + + error ~> K:K + invariantStateFull( + NumUsers, + UserIdToAddress, + AddressToUserId, + NumBoardMembers, + NumProposers, + UserIdToRole, + Quorum, + ActionLastIndex, + ActionData, + ActionSigners, + CallerAddress, + Stack, + caller_address |-> CallerAddress + caller_id |-> u(0) + caller_role |-> None, + PerformedActions + ) + + requires true + andBool notBool CallerAddress in_keys(AddressToUserId) + andBool notBool u(0) in_keys(UserIdToRole) + ensures true + //@ proof + //@ trusted + // [trusted] + //@ end +endmodule diff --git a/multisig/protocol-correctness/proof/invariant/proof-perform-parts-None.k b/multisig/protocol-correctness/proof/invariant/proof-perform-parts-None.k new file mode 100644 index 000000000..dd7a30431 --- /dev/null +++ b/multisig/protocol-correctness/proof/invariant/proof-perform-parts-None.k @@ -0,0 +1,60 @@ +//@ proof +require "../functions/trusted-perform-action-endpoint-None.k" //@ Bazel remove + +module PROOF-PERFORM-PARTS-NONE + imports TRUSTED-PERFORM-ACTION-ENDPOINT-NONE +//@ trusted +// module TRUSTED-PERFORM-PARTS-NONE +//@ end + + imports PERFORM-ACTION-ENDPOINT-INSTRUMENTATION + + claim + none.k ~> call(performActionEndpoint(_ActionId:Usize)) ~> K:K + invariantStateFull( + NumUsers:Usize, + UserIdToAddress:Map, + (CallerAddress |-> UserId:Usize _AddressToUserId:Map) #as AddressToUserId:Map, + NumBoardMembers:Usize, + NumProposers:Usize, + UserIdToRole:Map, + Quorum:Usize, + ActionLastIndex:Usize, + ActionData:Map, + ActionSigners:Map, + CallerAddress:Address, + Stack:Stack, + .Map, + PerformedActions:List + ) + + => + + error ~> K:K + invariantStateFull( + NumUsers, + UserIdToAddress, + AddressToUserId, + NumBoardMembers, + NumProposers, + UserIdToRole, + Quorum, + ActionLastIndex, + ActionData, + ActionSigners, + CallerAddress, + Stack, + caller_address |-> CallerAddress + caller_id |-> UserId + caller_role |-> None, + PerformedActions + ) + + requires true + andBool notBool UserId in_keys(UserIdToRole) + ensures true + //@ proof + //@ trusted + // [trusted] + //@ end +endmodule diff --git a/multisig/protocol-correctness/proof/invariant/proof-perform-parts-add-board-member-boardmember-eq.k b/multisig/protocol-correctness/proof/invariant/proof-perform-parts-add-board-member-boardmember-eq.k new file mode 100644 index 000000000..2e1370c3c --- /dev/null +++ b/multisig/protocol-correctness/proof/invariant/proof-perform-parts-add-board-member-boardmember-eq.k @@ -0,0 +1,70 @@ +//@ proof +require "../functions/trusted-perform-action-endpoint-add-board-member-BoardMember-eq.k" //@ Bazel remove + +module PROOF-PERFORM-PARTS-ADD-BOARD-MEMBER-BOARDMEMBER-EQ + imports TRUSTED-PERFORM-ACTION-ENDPOINT-ADD-BOARD-MEMBER-BOARDMEMBER-EQ +//@ trusted +// module TRUSTED-PERFORM-PARTS-ADD-BOARD-MEMBER-BOARDMEMBER-EQ +//@ end + + imports PERFORM-ACTION-ENDPOINT-INSTRUMENTATION + + claim + add-board-member-BoardMember-eq.k ~> call(performActionEndpoint(ActionId:Usize)) ~> K:K + invariantStateFull( + NumUsers:Usize, + UserIdToAddress:Map, + (CallerAddress |-> CallerId:Usize + _AddressToUserId:Map + ) #as AddressToUserId:Map, + NumBoardMembers:Usize, + NumProposers:Usize, + (CallerId |-> BoardMember + _UserIdToRole:Map + ) #as UserIdToRole:Map, + u(Quorum:Int), + ActionLastIndex:Usize, + ActionId |-> AddBoardMember(CallerAddress:Address) #as Action:Action + ActionData:Map, + ActionSigners:Map, + CallerAddress:Address, + Stack:Stack, + .Map, + PerformedActions:List + ) + + => + + evaluate(void) ~> K:K + invariantStateFull( + NumUsers, + UserIdToAddress, + AddressToUserId, + NumBoardMembers, + NumProposers, + UserIdToRole, + u(Quorum), + ActionLastIndex, + ActionData, + ActionSigners[ActionId <- undef], + CallerAddress, + Stack, + ?_Variables:Map, + ListItem(Action) PerformedActions + ) + + requires true + // perform-from-id + andBool isKResult(Action) + andBool addressToUserIdInvariant(AddressToUserId) + + // perform-fragment + andBool actionSignersInvariant(ActionSigners) + andBool userIdToRoleInvariant(UserIdToRole) + andBool Quorum <=Int countCanSignFunction({ActionSigners[ActionId] orDefault [.]}:>ExpressionList, opaque(UserIdToRole)) + ensures true + //@ proof + //@ trusted + // [trusted] + //@ end +endmodule diff --git a/multisig/protocol-correctness/proof/invariant/proof-perform-parts-add-board-member-boardmember.k b/multisig/protocol-correctness/proof/invariant/proof-perform-parts-add-board-member-boardmember.k new file mode 100644 index 000000000..93d24a935 --- /dev/null +++ b/multisig/protocol-correctness/proof/invariant/proof-perform-parts-add-board-member-boardmember.k @@ -0,0 +1,73 @@ +//@ proof +require "../functions/trusted-perform-action-endpoint-add-board-member-BoardMember.k" //@ Bazel remove + +module PROOF-PERFORM-PARTS-ADD-BOARD-MEMBER-BOARDMEMBER + imports TRUSTED-PERFORM-ACTION-ENDPOINT-ADD-BOARD-MEMBER-BOARDMEMBER +//@ trusted +// module TRUSTED-PERFORM-PARTS-ADD-BOARD-MEMBER-BOARDMEMBER +//@ end + + imports PERFORM-ACTION-ENDPOINT-INSTRUMENTATION + + claim + add-board-member-BoardMember.k ~> call(performActionEndpoint(ActionId:Usize)) ~> K:K + invariantStateFull( + NumUsers:Usize, + UserIdToAddress:Map, + (CallerAddress |-> CallerId:Usize + UserAddress |-> UserId:Usize + _AddressToUserId:Map + ) #as AddressToUserId:Map, + NumBoardMembers:Usize, + NumProposers:Usize, + (CallerId |-> Role:UserRole + UserId |-> BoardMember + _UserIdToRole:Map + ) #as UserIdToRole:Map, + u(Quorum:Int), + ActionLastIndex:Usize, + ActionId |-> AddBoardMember(UserAddress:Address) #as Action:Action + ActionData:Map, + ActionSigners:Map, + CallerAddress:Address, + Stack:Stack, + .Map, + PerformedActions:List + ) + + => + + evaluate(void) ~> K:K + invariantStateFull( + NumUsers, + UserIdToAddress, + AddressToUserId, + NumBoardMembers, + NumProposers, + UserIdToRole, + u(Quorum), + ActionLastIndex, + ActionData, + ActionSigners[ActionId <- undef], + CallerAddress, + Stack, + ?_Variables:Map, + ListItem(Action) PerformedActions + ) + + requires true + // perform-from-id + andBool isKResult(Action) + andBool addressToUserIdInvariant(AddressToUserId) + + // perform-fragment + andBool actionSignersInvariant(ActionSigners) + andBool userIdToRoleInvariant(UserIdToRole) + andBool (Role ==K BoardMember orBool Role ==K Proposer) + andBool Quorum <=Int countCanSignFunction({ActionSigners[ActionId] orDefault [.]}:>ExpressionList, opaque(UserIdToRole)) + ensures true + //@ proof + //@ trusted + // [trusted] + //@ end +endmodule diff --git a/multisig/protocol-correctness/proof/invariant/proof-perform-parts-add-board-member-eq.k b/multisig/protocol-correctness/proof/invariant/proof-perform-parts-add-board-member-eq.k new file mode 100644 index 000000000..4832f7295 --- /dev/null +++ b/multisig/protocol-correctness/proof/invariant/proof-perform-parts-add-board-member-eq.k @@ -0,0 +1,100 @@ +//@ proof +require "trusted-perform-parts-add-board-member-BoardMember-eq.k" //@ Bazel remove +require "trusted-perform-parts-add-board-member-Proposer-eq.k" //@ Bazel remove + +module PROOF-PERFORM-PARTS-ADD-BOARD-MEMBER-EQ + imports INVARIANT-EXECUTION + + imports TRUSTED-PERFORM-PARTS-ADD-BOARD-MEMBER-BOARDMEMBER-EQ + imports TRUSTED-PERFORM-PARTS-ADD-BOARD-MEMBER-PROPOSER-EQ +//@ trusted +// module TRUSTED-PERFORM-PARTS-ADD-BOARD-MEMBER-EQ +//@ end + imports PERFORM-ACTION-ENDPOINT-INSTRUMENTATION + + claim + splitAddBoardMember1(CallerAddress:Address) + ~> call(performActionEndpoint(ActionId:Usize)) + ~> popContext + ~> evaluateReturnValue + ~> clearExternalCallEnv + ~> splitActionSigners(ActionId:Usize, ActionSigners:Map) + ~> runExternalCalls(EC:ExternalCommands) + + invariantStateStack( + NumUsers:Usize, + UserIdToAddress:Map, + (CallerAddress |-> CallerId:Usize _AddressToUserId:Map) #as AddressToUserId:Map, + NumBoardMembers:Usize, + NumProposers:Usize, + (CallerId |-> CallerRole:UserRole _UserIdToRole:Map) #as UserIdToRole:Map, + u(Quorum:Int), + ActionLastIndex0:Usize, + (ActionId |-> AddBoardMember(CallerAddress) ActionData0:Map) #as ActionData:Map, + ActionSigners:Map, + CallerAddress:Address, + stack( + invariantMultisigState( + NumUsers, + UserIdToAddress, + AddressToUserId, + NumBoardMembers, + NumProposers, + UserIdToRole, + u(Quorum), + ActionLastIndex0, + ActionData, + ActionSigners), + .Map, + PerformedActions, + .stack), + PerformedActions:List) + + => + + runExternalCalls(EC) + invariantState( + ?NumUsers1:Usize, + ?UserIdToAddress1:Map, + ?AddressToUserId1:Map, + ?NumBoardMembers1:Usize, + ?NumProposers1:Usize, + ?UserIdToRole1:Map, + ?Quorum1:Usize, + ?ActionLastIndex1:Usize, + ?ActionData1:Map, + ?ActionSigners1:Map, + ?_PerformedActions:List):StateCell + + requires true + andBool invariant( + NumUsers, + UserIdToAddress, + AddressToUserId, + NumBoardMembers, + NumProposers, + UserIdToRole, + u(Quorum), + ActionLastIndex0, + ActionData0, + ActionSigners, + expand(expanded)) + andBool (CallerRole ==K BoardMember orBool CallerRole ==K Proposer) + andBool Quorum <=Int countCanSignFunction({ActionSigners[ActionId] orDefault [.]}:>ExpressionList, opaque(UserIdToRole)) + ensures invariant( + ?NumUsers1, + ?UserIdToAddress1, + ?AddressToUserId1, + ?NumBoardMembers1, + ?NumProposers1, + ?UserIdToRole1, + ?Quorum1, + ?ActionLastIndex1, + ?ActionData1, + ?ActionSigners1, + usesExpanded) + //@ proof + //@ trusted + // [trusted] + //@ end +endmodule diff --git a/multisig/protocol-correctness/proof/invariant/proof-perform-parts-add-board-member-neq.k b/multisig/protocol-correctness/proof/invariant/proof-perform-parts-add-board-member-neq.k new file mode 100644 index 000000000..d52ce8977 --- /dev/null +++ b/multisig/protocol-correctness/proof/invariant/proof-perform-parts-add-board-member-neq.k @@ -0,0 +1,102 @@ +//@ proof +require "trusted-perform-parts-add-board-member-BoardMember.k" //@ Bazel remove +require "trusted-perform-parts-add-board-member-Proposer.k" //@ Bazel remove + +module PROOF-PERFORM-PARTS-ADD-BOARD-MEMBER-NEQ + imports INVARIANT-EXECUTION + + imports TRUSTED-PERFORM-PARTS-ADD-BOARD-MEMBER-BOARDMEMBER + imports TRUSTED-PERFORM-PARTS-ADD-BOARD-MEMBER-PROPOSER +//@ trusted +// module TRUSTED-PERFORM-PARTS-ADD-BOARD-MEMBER-NEQ +//@ end + imports PERFORM-ACTION-ENDPOINT-INSTRUMENTATION + + claim + splitAddBoardMember3(UserAddress:Address) + ~> call(performActionEndpoint(ActionId:Usize)) + ~> popContext + ~> evaluateReturnValue + ~> clearExternalCallEnv + ~> splitActionSigners(ActionId:Usize, ActionSigners:Map) + ~> runExternalCalls(EC:ExternalCommands) + + invariantStateStack( + NumUsers:Usize, + UserIdToAddress:Map, + (CallerAddress |-> CallerId:Usize UserAddress |-> u(UserId:Int) _AddressToUserId:Map) #as AddressToUserId:Map, + NumBoardMembers:Usize, + NumProposers:Usize, + (CallerId |-> CallerRole:UserRole _UserIdToRole:Map) #as UserIdToRole:Map, + u(Quorum:Int), + ActionLastIndex0:Usize, + (ActionId |-> AddBoardMember(UserAddress) ActionData0:Map) #as ActionData:Map, + ActionSigners:Map, + CallerAddress:Address, + stack( + invariantMultisigState( + NumUsers, + UserIdToAddress, + AddressToUserId, + NumBoardMembers, + NumProposers, + UserIdToRole, + u(Quorum), + ActionLastIndex0, + ActionData, + ActionSigners), + .Map, + PerformedActions, + .stack), + PerformedActions:List) + + => + + runExternalCalls(EC) + invariantState( + ?NumUsers1:Usize, + ?UserIdToAddress1:Map, + ?AddressToUserId1:Map, + ?NumBoardMembers1:Usize, + ?NumProposers1:Usize, + ?UserIdToRole1:Map, + ?Quorum1:Usize, + ?ActionLastIndex1:Usize, + ?ActionData1:Map, + ?ActionSigners1:Map, + ?_PerformedActions:List):StateCell + + requires true + andBool invariant( + NumUsers, + UserIdToAddress, + AddressToUserId, + NumBoardMembers, + NumProposers, + UserIdToRole, + u(Quorum), + ActionLastIndex0, + ActionData0, + ActionSigners, + expand(expanded)) + andBool (CallerRole ==K BoardMember orBool CallerRole ==K Proposer) + andBool Quorum <=Int countCanSignFunction({ActionSigners[ActionId] orDefault [.]}:>ExpressionList, opaque(UserIdToRole)) + andBool notBool UserAddress ==K CallerAddress + andBool u(UserId) in_keys(UserIdToRole) + ensures invariant( + ?NumUsers1, + ?UserIdToAddress1, + ?AddressToUserId1, + ?NumBoardMembers1, + ?NumProposers1, + ?UserIdToRole1, + ?Quorum1, + ?ActionLastIndex1, + ?ActionData1, + ?ActionSigners1, + usesExpanded) + //@ proof + //@ trusted + // [trusted] + //@ end +endmodule diff --git a/multisig/protocol-correctness/proof/invariant/proof-perform-parts-add-board-member-new.k b/multisig/protocol-correctness/proof/invariant/proof-perform-parts-add-board-member-new.k new file mode 100644 index 000000000..9738d9932 --- /dev/null +++ b/multisig/protocol-correctness/proof/invariant/proof-perform-parts-add-board-member-new.k @@ -0,0 +1,78 @@ +//@ proof +require "../functions/trusted-perform-action-endpoint-add-board-member-New.k" //@ Bazel remove + +module PROOF-PERFORM-PARTS-ADD-BOARD-MEMBER-NEW + imports TRUSTED-PERFORM-ACTION-ENDPOINT-ADD-BOARD-MEMBER-NEW +//@ trusted +// module TRUSTED-PERFORM-PARTS-ADD-BOARD-MEMBER-NEW +//@ end + + imports PERFORM-ACTION-ENDPOINT-INSTRUMENTATION + + claim + add-board-member-New.k ~> call(performActionEndpoint(ActionId:Usize)) ~> K:K + invariantStateFull( + u(NumUsers:Int), + UserIdToAddress:Map, + (CallerAddress |-> CallerId:Usize + _AddressToUserId:Map + ) #as AddressToUserId:Map, + u(NumBoardMembers:Int), + NumProposers:Usize, + (CallerId |-> Role:UserRole + _UserIdToRole:Map + ) #as UserIdToRole:Map, + u(Quorum:Int), + ActionLastIndex:Usize, + ActionId |-> AddBoardMember(UserAddress:Address) #as Action:Action + ActionData:Map, + ActionSigners:Map, + CallerAddress:Address, + Stack:Stack, + .Map, + PerformedActions:List + ) + + => + + evaluate(void) ~> K:K + invariantStateFull( + u(NumUsers +Int 1), + u(NumUsers +Int 1) |-> UserAddress UserIdToAddress, + UserAddress |-> u(NumUsers +Int 1) AddressToUserId, + u(NumBoardMembers +Int 1), + NumProposers, + u(NumUsers +Int 1) |-> BoardMember UserIdToRole, + u(Quorum), + ActionLastIndex, + ActionData, + ActionSigners[ActionId <- undef], + CallerAddress, + Stack, + ?_Variables:Map, + ListItem(Action) PerformedActions + ) + + requires true + // perform-from-id + andBool isKResult(Action) + + andBool NumUsers >=Int 0 + // TODO: Perhaps replace with unusedIdsInMapValues(AddressToUserId) + + // someting to map values to keys. + andBool unusedIdsInMapKeys(NumUsers +Int 1, keysMap(UserIdToAddress), expand(expanded)) + andBool unusedIdsInMapKeys(NumUsers +Int 1, keysMap(UserIdToRole), expand(expanded)) + + andBool notBool UserAddress in_keys(AddressToUserId) + + // perform-fragment + andBool actionSignersInvariant(ActionSigners) + andBool userIdToRoleInvariant(UserIdToRole) + andBool (Role ==K BoardMember orBool Role ==K Proposer) + andBool Quorum <=Int countCanSignFunction({ActionSigners[ActionId] orDefault [.]}:>ExpressionList, opaque(UserIdToRole)) + ensures true + //@ proof + //@ trusted + // [trusted] + //@ end +endmodule diff --git a/multisig/protocol-correctness/proof/invariant/proof-perform-parts-add-board-member-none.k b/multisig/protocol-correctness/proof/invariant/proof-perform-parts-add-board-member-none.k new file mode 100644 index 000000000..5e8a0f0f7 --- /dev/null +++ b/multisig/protocol-correctness/proof/invariant/proof-perform-parts-add-board-member-none.k @@ -0,0 +1,73 @@ +//@ proof +require "../functions/trusted-perform-action-endpoint-add-board-member-None.k" //@ Bazel remove + +module PROOF-PERFORM-PARTS-ADD-BOARD-MEMBER-NONE + imports TRUSTED-PERFORM-ACTION-ENDPOINT-ADD-BOARD-MEMBER-NONE +//@ trusted +// module TRUSTED-PERFORM-PARTS-ADD-BOARD-MEMBER-NONE +//@ end + + imports PERFORM-ACTION-ENDPOINT-INSTRUMENTATION + + claim + add-board-member-None.k ~> call(performActionEndpoint(ActionId:Usize)) ~> K:K + invariantStateFull( + NumUsers:Usize, + UserIdToAddress:Map, + (CallerAddress |-> CallerId:Usize + UserAddress |-> UserId:Usize + _AddressToUserId:Map + ) #as AddressToUserId:Map, + u(NumBoardMembers:Int), + NumProposers:Usize, + (CallerId |-> Role:UserRole + _UserIdToRole:Map + ) #as UserIdToRole:Map, + u(Quorum:Int), + ActionLastIndex:Usize, + ActionId |-> AddBoardMember(UserAddress:Address) #as Action:Action + ActionData:Map, + ActionSigners:Map, + CallerAddress:Address, + Stack:Stack, + .Map, + PerformedActions:List + ) + + => + + evaluate(void) ~> K:K + invariantStateFull( + NumUsers, + UserIdToAddress, + AddressToUserId, + u(NumBoardMembers +Int 1), + NumProposers, + UserId |-> BoardMember UserIdToRole, + u(Quorum), + ActionLastIndex, + ActionData, + ActionSigners[ActionId <- undef], + CallerAddress, + Stack, + ?_Variables:Map, + ListItem(Action) PerformedActions + ) + + requires true + // perform-from-id + andBool isKResult(Action) + andBool addressToUserIdInvariant(AddressToUserId) + andBool notBool UserId in_keys(UserIdToRole) + + // perform-fragment + andBool actionSignersInvariant(ActionSigners) + andBool userIdToRoleInvariant(UserIdToRole) + andBool (Role ==K BoardMember orBool Role ==K Proposer) + andBool Quorum <=Int countCanSignFunction({ActionSigners[ActionId] orDefault [.]}:>ExpressionList, opaque(UserIdToRole)) + ensures true + //@ proof + //@ trusted + // [trusted] + //@ end +endmodule diff --git a/multisig/protocol-correctness/proof/invariant/proof-perform-parts-add-board-member-proposer-eq.k b/multisig/protocol-correctness/proof/invariant/proof-perform-parts-add-board-member-proposer-eq.k new file mode 100644 index 000000000..540941279 --- /dev/null +++ b/multisig/protocol-correctness/proof/invariant/proof-perform-parts-add-board-member-proposer-eq.k @@ -0,0 +1,71 @@ +//@ proof +require "../functions/trusted-perform-action-endpoint-add-board-member-Proposer-eq.k" //@ Bazel remove + +module PROOF-PERFORM-PARTS-ADD-BOARD-MEMBER-PROPOSER-EQ + imports TRUSTED-PERFORM-ACTION-ENDPOINT-ADD-BOARD-MEMBER-PROPOSER-EQ +//@ trusted +// module TRUSTED-PERFORM-PARTS-ADD-BOARD-MEMBER-PROPOSER-EQ +//@ end + + imports PERFORM-ACTION-ENDPOINT-INSTRUMENTATION + + claim + add-board-member-Proposer-eq.k ~> call(performActionEndpoint(ActionId:Usize)) ~> K:K + invariantStateFull( + NumUsers:Usize, + UserIdToAddress:Map, + (CallerAddress |-> CallerId:Usize + _AddressToUserId:Map + ) #as AddressToUserId:Map, + u(NumBoardMembers:Int), + u(NumProposers:Int), + (CallerId |-> Proposer + UserIdToRoleInner:Map + ) #as UserIdToRole:Map, + u(Quorum:Int), + ActionLastIndex:Usize, + ActionId |-> AddBoardMember(CallerAddress:Address) #as Action:Action + ActionData:Map, + ActionSigners:Map, + CallerAddress:Address, + Stack:Stack, + .Map, + PerformedActions:List + ) + + => + + evaluate(void) ~> K:K + invariantStateFull( + NumUsers, + UserIdToAddress, + AddressToUserId, + u(NumBoardMembers +Int 1), + u(NumProposers -Int 1), + CallerId |-> BoardMember + UserIdToRoleInner:Map, + u(Quorum), + ActionLastIndex, + ActionData, + ActionSigners[ActionId <- undef], + CallerAddress, + Stack, + ?_Variables:Map, + ListItem(Action) PerformedActions + ) + + requires true + // perform-from-id + andBool isKResult(Action) + andBool addressToUserIdInvariant(AddressToUserId) + + // perform-fragment + andBool actionSignersInvariant(ActionSigners) + andBool userIdToRoleInvariant(UserIdToRole) + andBool Quorum <=Int countCanSignFunction({ActionSigners[ActionId] orDefault [.]}:>ExpressionList, opaque(UserIdToRole)) + ensures true + //@ proof + //@ trusted + // [trusted] + //@ end +endmodule diff --git a/multisig/protocol-correctness/proof/invariant/proof-perform-parts-add-board-member-proposer.k b/multisig/protocol-correctness/proof/invariant/proof-perform-parts-add-board-member-proposer.k new file mode 100644 index 000000000..37ab3d8ff --- /dev/null +++ b/multisig/protocol-correctness/proof/invariant/proof-perform-parts-add-board-member-proposer.k @@ -0,0 +1,75 @@ +//@ proof +require "../functions/trusted-perform-action-endpoint-add-board-member-Proposer.k" //@ Bazel remove + +module PROOF-PERFORM-PARTS-ADD-BOARD-MEMBER-PROPOSER + imports TRUSTED-PERFORM-ACTION-ENDPOINT-ADD-BOARD-MEMBER-PROPOSER +//@ trusted +// module TRUSTED-PERFORM-PARTS-ADD-BOARD-MEMBER-PROPOSER +//@ end + + imports PERFORM-ACTION-ENDPOINT-INSTRUMENTATION + + claim + add-board-member-Proposer.k ~> call(performActionEndpoint(ActionId:Usize)) ~> K:K + invariantStateFull( + NumUsers:Usize, + UserIdToAddress:Map, + (CallerAddress |-> CallerId:Usize + UserAddress |-> UserId:Usize + _AddressToUserId:Map + ) #as AddressToUserId:Map, + u(NumBoardMembers:Int), + u(NumProposers:Int), + (UserId |-> Proposer + CallerId |-> Role:UserRole + UserIdToRoleInner:Map + ) #as UserIdToRole:Map, + u(Quorum:Int), + ActionLastIndex:Usize, + ActionId |-> AddBoardMember(UserAddress:Address) #as Action:Action + ActionData:Map, + ActionSigners:Map, + CallerAddress:Address, + Stack:Stack, + .Map, + PerformedActions:List + ) + + => + + evaluate(void) ~> K:K + invariantStateFull( + NumUsers, + UserIdToAddress, + AddressToUserId, + u(NumBoardMembers +Int 1), + u(NumProposers -Int 1), + UserId |-> BoardMember + CallerId |-> Role:UserRole + UserIdToRoleInner:Map, + u(Quorum), + ActionLastIndex, + ActionData, + ActionSigners[ActionId <- undef], + CallerAddress, + Stack, + ?_Variables:Map, + ListItem(Action) PerformedActions + ) + + requires true + // perform-from-id + andBool isKResult(Action) + andBool addressToUserIdInvariant(AddressToUserId) + + // perform-fragment + andBool actionSignersInvariant(ActionSigners) + andBool userIdToRoleInvariant(UserIdToRole) + andBool (Role ==K BoardMember orBool Role ==K Proposer) + andBool Quorum <=Int countCanSignFunction({ActionSigners[ActionId] orDefault [.]}:>ExpressionList, opaque(UserIdToRole)) + ensures true + //@ proof + //@ trusted + // [trusted] + //@ end +endmodule diff --git a/multisig/protocol-correctness/proof/invariant/proof-perform-parts-add-board-member.k b/multisig/protocol-correctness/proof/invariant/proof-perform-parts-add-board-member.k new file mode 100644 index 000000000..b5dbdf9df --- /dev/null +++ b/multisig/protocol-correctness/proof/invariant/proof-perform-parts-add-board-member.k @@ -0,0 +1,104 @@ +//@ proof +require "trusted-perform-parts-add-board-member-eq.k" //@ Bazel remove +require "trusted-perform-parts-add-board-member-neq.k" //@ Bazel remove +require "trusted-perform-parts-add-board-member-New.k" //@ Bazel remove +require "trusted-perform-parts-add-board-member-None.k" //@ Bazel remove + +module PROOF-PERFORM-PARTS-ADD-BOARD-MEMBER + imports INVARIANT-EXECUTION + + imports TRUSTED-PERFORM-PARTS-ADD-BOARD-MEMBER-EQ + imports TRUSTED-PERFORM-PARTS-ADD-BOARD-MEMBER-NEQ + imports TRUSTED-PERFORM-PARTS-ADD-BOARD-MEMBER-NEW + imports TRUSTED-PERFORM-PARTS-ADD-BOARD-MEMBER-NONE +//@ trusted +// module TRUSTED-PERFORM-PARTS-ADD-BOARD-MEMBER +//@ end + imports PERFORM-ACTION-ENDPOINT-INSTRUMENTATION + + claim + splitPerformActionEndpoint4(AddBoardMember(_UserAddress:Address) #as Action:Action) + ~> call(performActionEndpoint(ActionId:Usize)) + ~> popContext + ~> evaluateReturnValue + ~> clearExternalCallEnv + ~> splitActionSigners(ActionId:Usize, ActionSigners:Map) + ~> runExternalCalls(EC:ExternalCommands) + + invariantStateStack( + NumUsers:Usize, + UserIdToAddress:Map, + (CallerAddress |-> CallerId:Usize _AddressToUserId:Map) #as AddressToUserId:Map, + NumBoardMembers:Usize, + NumProposers:Usize, + (CallerId |-> CallerRole:UserRole _UserIdToRole:Map) #as UserIdToRole:Map, + u(Quorum:Int), + ActionLastIndex0:Usize, + (ActionId |-> Action ActionData0:Map) #as ActionData:Map, + ActionSigners:Map, + CallerAddress:Address, + stack( + invariantMultisigState( + NumUsers, + UserIdToAddress, + AddressToUserId, + NumBoardMembers, + NumProposers, + UserIdToRole, + u(Quorum), + ActionLastIndex0, + ActionData, + ActionSigners), + .Map, + PerformedActions, + .stack), + PerformedActions:List) + + => + + runExternalCalls(EC) + invariantState( + ?NumUsers1:Usize, + ?UserIdToAddress1:Map, + ?AddressToUserId1:Map, + ?NumBoardMembers1:Usize, + ?NumProposers1:Usize, + ?UserIdToRole1:Map, + ?Quorum1:Usize, + ?ActionLastIndex1:Usize, + ?ActionData1:Map, + ?ActionSigners1:Map, + ?_PerformedActions:List):StateCell + + requires true + andBool invariant( + NumUsers, + UserIdToAddress, + AddressToUserId, + NumBoardMembers, + NumProposers, + UserIdToRole, + u(Quorum), + ActionLastIndex0, + ActionData0, + ActionSigners, + expand(expanded)) + andBool (CallerRole ==K BoardMember orBool CallerRole ==K Proposer) + andBool Quorum <=Int countCanSignFunction({ActionSigners[ActionId] orDefault [.]}:>ExpressionList, opaque(UserIdToRole)) + ensures invariant( + ?NumUsers1, + ?UserIdToAddress1, + ?AddressToUserId1, + ?NumBoardMembers1, + ?NumProposers1, + ?UserIdToRole1, + ?Quorum1, + ?ActionLastIndex1, + ?ActionData1, + ?ActionSigners1, + usesExpanded) + //@ proof + //@ trusted + // [trusted] + //@ end +endmodule diff --git a/multisig/protocol-correctness/proof/invariant/proof-perform-parts-add-proposer-BoardMember-eq.k b/multisig/protocol-correctness/proof/invariant/proof-perform-parts-add-proposer-BoardMember-eq.k new file mode 100644 index 000000000..68dd30159 --- /dev/null +++ b/multisig/protocol-correctness/proof/invariant/proof-perform-parts-add-proposer-BoardMember-eq.k @@ -0,0 +1,72 @@ +//@ proof +require "../functions/trusted-perform-action-endpoint-add-proposer-BoardMember-eq.k" //@ Bazel remove + +module PROOF-PERFORM-PARTS-ADD-PROPOSER-BOARDMEMBER-EQ + imports TRUSTED-PERFORM-ACTION-ENDPOINT-ADD-PROPOSER-BOARDMEMBER-EQ +//@ trusted +// module TRUSTED-PERFORM-PARTS-ADD-PROPOSER-BOARDMEMBER-EQ +//@ end + + imports PERFORM-ACTION-ENDPOINT-INSTRUMENTATION + + claim + add-proposer-BoardMember-eq.k ~> call(performActionEndpoint(ActionId:Usize)) ~> K:K + invariantStateFull( + NumUsers:Usize, + UserIdToAddress:Map, + (CallerAddress |-> CallerId:Usize + _AddressToUserId:Map + ) #as AddressToUserId:Map, + u(NumBoardMembers:Int), + u(NumProposers:Int), + (CallerId |-> BoardMember + UserIdToRoleInner:Map + ) #as UserIdToRole:Map, + u(Quorum:Int), + ActionLastIndex:Usize, + ActionId |-> AddProposer(CallerAddress:Address) #as Action:Action + ActionData:Map, + ActionSigners:Map, + CallerAddress:Address, + Stack:Stack, + .Map, + PerformedActions:List + ) + + => + + evaluate(void) ~> K:K + invariantStateFull( + NumUsers, + UserIdToAddress, + AddressToUserId, + u(NumBoardMembers -Int 1), + u(NumProposers +Int 1), + (CallerId |-> Proposer + UserIdToRoleInner), + u(Quorum), + ActionLastIndex, + ActionData, + ActionSigners[ActionId <- undef], + CallerAddress, + Stack, + ?_Variables:Map, + ListItem(Action) PerformedActions + ) + + requires true + // perform-from-id + andBool isKResult(Action) + andBool addressToUserIdInvariant(AddressToUserId) + andBool Quorum <=Int NumBoardMembers -Int 1 + + // perform-fragment + andBool actionSignersInvariant(ActionSigners) + andBool userIdToRoleInvariant(UserIdToRole) + andBool Quorum <=Int countCanSignFunction({ActionSigners[ActionId] orDefault [.]}:>ExpressionList, opaque(UserIdToRole)) + ensures true + //@ proof + //@ trusted + // [trusted] + //@ end +endmodule diff --git a/multisig/protocol-correctness/proof/invariant/proof-perform-parts-add-proposer-BoardMember-no-quorum-eq.k b/multisig/protocol-correctness/proof/invariant/proof-perform-parts-add-proposer-BoardMember-no-quorum-eq.k new file mode 100644 index 000000000..29415667d --- /dev/null +++ b/multisig/protocol-correctness/proof/invariant/proof-perform-parts-add-proposer-BoardMember-no-quorum-eq.k @@ -0,0 +1,72 @@ +//@ proof +require "../functions/trusted-perform-action-endpoint-add-proposer-BoardMember-no-quorum-eq.k" //@ Bazel remove + +module PROOF-PERFORM-PARTS-ADD-PROPOSER-BOARDMEMBER-NO-QUORUM-EQ + imports TRUSTED-PERFORM-ACTION-ENDPOINT-ADD-PROPOSER-BOARDMEMBER-NO-QUORUM-EQ +//@ trusted +// module TRUSTED-PERFORM-PARTS-ADD-PROPOSER-BOARDMEMBER-NO-QUORUM-EQ +//@ end + + imports PERFORM-ACTION-ENDPOINT-INSTRUMENTATION + + claim + add-proposer-BoardMember-no-quorum-eq.k ~> call(performActionEndpoint(ActionId:Usize)) ~> K:K + invariantStateFull( + NumUsers:Usize, + UserIdToAddress:Map, + (CallerAddress |-> CallerId:Usize + _AddressToUserId:Map + ) #as AddressToUserId:Map, + u(NumBoardMembers:Int), + u(NumProposers:Int), + (CallerId |-> BoardMember + _UserIdToRole:Map + ) #as UserIdToRole:Map, + u(Quorum:Int), + ActionLastIndex:Usize, + ActionId |-> AddProposer(CallerAddress:Address) #as Action:Action + ActionData:Map, + ActionSigners:Map, + CallerAddress:Address, + Stack:Stack, + .Map, + PerformedActions:List + ) + + => + + error ~> K:K + invariantStateFull( + NumUsers, + UserIdToAddress, + AddressToUserId, + u(NumBoardMembers), + u(NumProposers), + UserIdToRole, + u(Quorum), + ActionLastIndex, + ActionId |-> Action ActionData, + ActionSigners, + CallerAddress, + Stack, + ?_Variables:Map, + PerformedActions + ) + + requires true + // perform-from-id + andBool isKResult(Action) + andBool addressToUserIdInvariant(AddressToUserId) + andBool Quorum ==Int NumBoardMembers + + // perform-fragment + andBool actionSignersInvariant(ActionSigners) + andBool userIdToRoleInvariant(UserIdToRole) + andBool Quorum <=Int countCanSignFunction({ActionSigners[ActionId] orDefault [.]}:>ExpressionList, opaque(UserIdToRole)) + ensures true + //@ proof + //@ trusted + // [trusted] + //@ end +endmodule + diff --git a/multisig/protocol-correctness/proof/invariant/proof-perform-parts-add-proposer-BoardMember-no-quorum.k b/multisig/protocol-correctness/proof/invariant/proof-perform-parts-add-proposer-BoardMember-no-quorum.k new file mode 100644 index 000000000..367f7de27 --- /dev/null +++ b/multisig/protocol-correctness/proof/invariant/proof-perform-parts-add-proposer-BoardMember-no-quorum.k @@ -0,0 +1,74 @@ +//@ proof +require "../functions/trusted-perform-action-endpoint-add-proposer-BoardMember-no-quorum.k" //@ Bazel remove + +module PROOF-PERFORM-PARTS-ADD-PROPOSER-BOARDMEMBER-NO-QUORUM + imports TRUSTED-PERFORM-ACTION-ENDPOINT-ADD-PROPOSER-BOARDMEMBER-NO-QUORUM +//@ trusted +// module TRUSTED-PERFORM-PARTS-ADD-PROPOSER-BOARDMEMBER-NO-QUORUM +//@ end + + imports PERFORM-ACTION-ENDPOINT-INSTRUMENTATION + + claim + add-proposer-BoardMember-no-quorum.k ~> call(performActionEndpoint(ActionId:Usize)) ~> K:K + invariantStateFull( + NumUsers:Usize, + UserIdToAddress:Map, + (CallerAddress |-> CallerId:Usize + UserAddress |-> UserId:Usize + _AddressToUserId:Map + ) #as AddressToUserId:Map, + u(NumBoardMembers:Int), + u(NumProposers:Int), + (CallerId |-> Role:UserRole + UserId |-> BoardMember + _UserIdToRole:Map + ) #as UserIdToRole:Map, + u(Quorum:Int), + ActionLastIndex:Usize, + ActionId |-> AddProposer(UserAddress:Address) #as Action:Action + ActionData:Map, + ActionSigners:Map, + CallerAddress:Address, + Stack:Stack, + .Map, + PerformedActions:List + ) + + => + + error ~> K:K + invariantStateFull( + NumUsers, + UserIdToAddress, + AddressToUserId, + u(NumBoardMembers), + u(NumProposers), + UserIdToRole, + u(Quorum), + ActionLastIndex, + ActionId |-> Action ActionData, + ActionSigners, + CallerAddress, + Stack, + ?_Variables:Map, + PerformedActions + ) + + requires true + // perform-from-id + andBool isKResult(Action) + andBool addressToUserIdInvariant(AddressToUserId) + andBool Quorum ==Int NumBoardMembers + + // perform-fragment + andBool actionSignersInvariant(ActionSigners) + andBool userIdToRoleInvariant(UserIdToRole) + andBool (Role ==K BoardMember orBool Role ==K Proposer) + andBool Quorum <=Int countCanSignFunction({ActionSigners[ActionId] orDefault [.]}:>ExpressionList, opaque(UserIdToRole)) + ensures true + //@ proof + //@ trusted + // [trusted] + //@ end +endmodule diff --git a/multisig/protocol-correctness/proof/invariant/proof-perform-parts-add-proposer-BoardMember.k b/multisig/protocol-correctness/proof/invariant/proof-perform-parts-add-proposer-BoardMember.k new file mode 100644 index 000000000..a6fc308c5 --- /dev/null +++ b/multisig/protocol-correctness/proof/invariant/proof-perform-parts-add-proposer-BoardMember.k @@ -0,0 +1,76 @@ +//@ proof +require "../functions/trusted-perform-action-endpoint-add-proposer-BoardMember.k" //@ Bazel remove + +module PROOF-PERFORM-PARTS-ADD-PROPOSER-BOARDMEMBER + imports TRUSTED-PERFORM-ACTION-ENDPOINT-ADD-PROPOSER-BOARDMEMBER +//@ trusted +// module TRUSTED-PERFORM-PARTS-ADD-PROPOSER-BOARDMEMBER +//@ end + + imports PERFORM-ACTION-ENDPOINT-INSTRUMENTATION + + claim + add-proposer-BoardMember.k ~> call(performActionEndpoint(ActionId:Usize)) ~> K:K + invariantStateFull( + NumUsers:Usize, + UserIdToAddress:Map, + (CallerAddress |-> CallerId:Usize + UserAddress |-> UserId:Usize + _AddressToUserId:Map + ) #as AddressToUserId:Map, + u(NumBoardMembers:Int), + u(NumProposers:Int), + (CallerId |-> Role:UserRole + UserId |-> BoardMember + UserIdToRoleInner:Map + ) #as UserIdToRole:Map, + u(Quorum:Int), + ActionLastIndex:Usize, + ActionId |-> AddProposer(UserAddress:Address) #as Action:Action + ActionData:Map, + ActionSigners:Map, + CallerAddress:Address, + Stack:Stack, + .Map, + PerformedActions:List + ) + + => + + evaluate(void) ~> K:K + invariantStateFull( + NumUsers, + UserIdToAddress, + AddressToUserId, + u(NumBoardMembers -Int 1), + u(NumProposers +Int 1), + (CallerId |-> Role:UserRole + UserId |-> Proposer + UserIdToRoleInner), + u(Quorum), + ActionLastIndex, + ActionData, + ActionSigners[ActionId <- undef], + CallerAddress, + Stack, + ?_Variables:Map, + ListItem(Action) PerformedActions + ) + + requires true + // perform-from-id + andBool isKResult(Action) + andBool addressToUserIdInvariant(AddressToUserId) + andBool Quorum <=Int NumBoardMembers -Int 1 + + // perform-fragment + andBool actionSignersInvariant(ActionSigners) + andBool userIdToRoleInvariant(UserIdToRole) + andBool (Role ==K BoardMember orBool Role ==K Proposer) + andBool Quorum <=Int countCanSignFunction({ActionSigners[ActionId] orDefault [.]}:>ExpressionList, opaque(UserIdToRole)) + ensures true + //@ proof + //@ trusted + // [trusted] + //@ end +endmodule diff --git a/multisig/protocol-correctness/proof/invariant/proof-perform-parts-add-proposer-New.k b/multisig/protocol-correctness/proof/invariant/proof-perform-parts-add-proposer-New.k new file mode 100644 index 000000000..feff47568 --- /dev/null +++ b/multisig/protocol-correctness/proof/invariant/proof-perform-parts-add-proposer-New.k @@ -0,0 +1,79 @@ +//@ proof +require "../functions/trusted-perform-action-endpoint-add-proposer-New.k" //@ Bazel remove + +module PROOF-PERFORM-PARTS-ADD-PROPOSER-NEW + imports TRUSTED-PERFORM-ACTION-ENDPOINT-ADD-PROPOSER-NEW +//@ trusted +// module TRUSTED-PERFORM-PARTS-ADD-PROPOSER-NEW +//@ end + + imports PERFORM-ACTION-ENDPOINT-INSTRUMENTATION + + claim + add-proposer-New.k ~> call(performActionEndpoint(ActionId:Usize)) ~> K:K + invariantStateFull( + u(NumUsers:Int), + UserIdToAddress:Map, + (CallerAddress |-> CallerId:Usize + _AddressToUserId:Map + ) #as AddressToUserId:Map, + u(NumBoardMembers:Int), + u(NumProposers:Int), + (CallerId |-> Role:UserRole + _UserIdToRole:Map + ) #as UserIdToRole:Map, + u(Quorum:Int), + ActionLastIndex:Usize, + ActionId |-> AddProposer(UserAddress:Address) #as Action:Action + ActionData:Map, + ActionSigners:Map, + CallerAddress:Address, + Stack:Stack, + .Map, + PerformedActions:List + ) + + => + + evaluate(void) ~> K:K + invariantStateFull( + u(NumUsers +Int 1), + u(NumUsers +Int 1) |-> UserAddress UserIdToAddress, + UserAddress |-> u(NumUsers +Int 1) AddressToUserId, + u(NumBoardMembers), + u(NumProposers +Int 1), + u(NumUsers +Int 1) |-> Proposer UserIdToRole, + u(Quorum), + ActionLastIndex, + ActionData, + ActionSigners[ActionId <- undef], + CallerAddress, + Stack, + ?_Variables:Map, + ListItem(Action) PerformedActions + ) + + requires true + // perform-from-id + andBool isKResult(Action) + + andBool NumUsers >=Int 0 + // TODO: Perhaps replace with unusedIdsInMapValues(AddressToUserId) + + // someting to map values to keys. + andBool unusedIdsInMapKeys(NumUsers +Int 1, keysMap(UserIdToAddress), expand(expanded)) + andBool unusedIdsInMapKeys(NumUsers +Int 1, keysMap(UserIdToRole), expand(expanded)) + andBool Quorum <=Int NumBoardMembers + + andBool notBool UserAddress in_keys(AddressToUserId) + + // perform-fragment + andBool actionSignersInvariant(ActionSigners) + andBool userIdToRoleInvariant(UserIdToRole) + andBool (Role ==K BoardMember orBool Role ==K Proposer) + andBool Quorum <=Int countCanSignFunction({ActionSigners[ActionId] orDefault [.]}:>ExpressionList, opaque(UserIdToRole)) + ensures true + //@ proof + //@ trusted + // [trusted] + //@ end +endmodule diff --git a/multisig/protocol-correctness/proof/invariant/proof-perform-parts-add-proposer-None.k b/multisig/protocol-correctness/proof/invariant/proof-perform-parts-add-proposer-None.k new file mode 100644 index 000000000..f5648b627 --- /dev/null +++ b/multisig/protocol-correctness/proof/invariant/proof-perform-parts-add-proposer-None.k @@ -0,0 +1,74 @@ +//@ proof +require "../functions/trusted-perform-action-endpoint-add-proposer-None.k" //@ Bazel remove + +module PROOF-PERFORM-PARTS-ADD-PROPOSER-NONE + imports TRUSTED-PERFORM-ACTION-ENDPOINT-ADD-PROPOSER-NONE +//@ trusted +// module TRUSTED-PERFORM-PARTS-ADD-PROPOSER-NONE +//@ end + + imports PERFORM-ACTION-ENDPOINT-INSTRUMENTATION + + claim + add-proposer-None.k ~> call(performActionEndpoint(ActionId:Usize)) ~> K:K + invariantStateFull( + NumUsers:Usize, + UserIdToAddress:Map, + (CallerAddress |-> CallerId:Usize + UserAddress |-> UserId:Usize + _AddressToUserId:Map + ) #as AddressToUserId:Map, + u(NumBoardMembers:Int), + u(NumProposers:Int), + (CallerId |-> Role:UserRole + _UserIdToRole:Map + ) #as UserIdToRole:Map, + u(Quorum:Int), + ActionLastIndex:Usize, + ActionId |-> AddProposer(UserAddress:Address) #as Action:Action + ActionData:Map, + ActionSigners:Map, + CallerAddress:Address, + Stack:Stack, + .Map, + PerformedActions:List + ) + + => + + evaluate(void) ~> K:K + invariantStateFull( + NumUsers, + UserIdToAddress, + AddressToUserId, + u(NumBoardMembers), + u(NumProposers +Int 1), + UserId |-> Proposer UserIdToRole, + u(Quorum), + ActionLastIndex, + ActionData, + ActionSigners[ActionId <- undef], + CallerAddress, + Stack, + ?_Variables:Map, + ListItem(Action) PerformedActions + ) + + requires true + // perform-from-id + andBool isKResult(Action) + andBool addressToUserIdInvariant(AddressToUserId) + andBool Quorum <=Int NumBoardMembers + andBool notBool UserId in_keys(UserIdToRole) + + // perform-fragment + andBool actionSignersInvariant(ActionSigners) + andBool userIdToRoleInvariant(UserIdToRole) + andBool (Role ==K BoardMember orBool Role ==K Proposer) + andBool Quorum <=Int countCanSignFunction({ActionSigners[ActionId] orDefault [.]}:>ExpressionList, opaque(UserIdToRole)) + ensures true + //@ proof + //@ trusted + // [trusted] + //@ end +endmodule diff --git a/multisig/protocol-correctness/proof/invariant/proof-perform-parts-add-proposer-Proposer-eq.k b/multisig/protocol-correctness/proof/invariant/proof-perform-parts-add-proposer-Proposer-eq.k new file mode 100644 index 000000000..f0807b109 --- /dev/null +++ b/multisig/protocol-correctness/proof/invariant/proof-perform-parts-add-proposer-Proposer-eq.k @@ -0,0 +1,71 @@ +//@ proof +require "../functions/trusted-perform-action-endpoint-add-proposer-Proposer-eq.k" //@ Bazel remove + +module PROOF-PERFORM-PARTS-ADD-PROPOSER-PROPOSER-EQ + imports TRUSTED-PERFORM-ACTION-ENDPOINT-ADD-PROPOSER-PROPOSER-EQ +//@ trusted +// module TRUSTED-PERFORM-PARTS-ADD-PROPOSER-PROPOSER-EQ +//@ end + + imports PERFORM-ACTION-ENDPOINT-INSTRUMENTATION + + claim + add-proposer-Proposer-eq.k ~> call(performActionEndpoint(ActionId:Usize)) ~> K:K + invariantStateFull( + NumUsers:Usize, + UserIdToAddress:Map, + (CallerAddress |-> CallerId:Usize + _AddressToUserId:Map + ) #as AddressToUserId:Map, + u(NumBoardMembers:Int), + NumProposers:Usize, + (CallerId |-> Proposer + _UserIdToRole:Map + ) #as UserIdToRole:Map, + u(Quorum:Int), + ActionLastIndex:Usize, + ActionId |-> AddProposer(CallerAddress:Address) #as Action:Action + ActionData:Map, + ActionSigners:Map, + CallerAddress:Address, + Stack:Stack, + .Map, + PerformedActions:List + ) + + => + + evaluate(void) ~> K:K + invariantStateFull( + NumUsers, + UserIdToAddress, + AddressToUserId, + u(NumBoardMembers), + NumProposers, + UserIdToRole, + u(Quorum), + ActionLastIndex, + ActionData, + ActionSigners[ActionId <- undef], + CallerAddress, + Stack, + ?_Variables:Map, + ListItem(Action) PerformedActions + ) + + requires true + // perform-from-id + andBool isKResult(Action) + andBool addressToUserIdInvariant(AddressToUserId) + andBool Quorum <=Int NumBoardMembers + + // perform-fragment + andBool actionSignersInvariant(ActionSigners) + andBool userIdToRoleInvariant(UserIdToRole) + andBool Quorum <=Int countCanSignFunction({ActionSigners[ActionId] orDefault [.]}:>ExpressionList, opaque(UserIdToRole)) + ensures true + //@ proof + //@ trusted + // [trusted] + //@ end +endmodule diff --git a/multisig/protocol-correctness/proof/invariant/proof-perform-parts-add-proposer-Proposer.k b/multisig/protocol-correctness/proof/invariant/proof-perform-parts-add-proposer-Proposer.k new file mode 100644 index 000000000..b5f9cd716 --- /dev/null +++ b/multisig/protocol-correctness/proof/invariant/proof-perform-parts-add-proposer-Proposer.k @@ -0,0 +1,75 @@ +//@ proof +require "../functions/trusted-perform-action-endpoint-add-proposer-Proposer.k" //@ Bazel remove + +module PROOF-PERFORM-PARTS-ADD-PROPOSER-PROPOSER + imports TRUSTED-PERFORM-ACTION-ENDPOINT-ADD-PROPOSER-PROPOSER +//@ trusted +// module TRUSTED-PERFORM-PARTS-ADD-PROPOSER-PROPOSER +//@ end + + imports PERFORM-ACTION-ENDPOINT-INSTRUMENTATION + + claim + add-proposer-Proposer.k ~> call(performActionEndpoint(ActionId:Usize)) ~> K:K + invariantStateFull( + NumUsers:Usize, + UserIdToAddress:Map, + (CallerAddress |-> CallerId:Usize + UserAddress |-> UserId:Usize + _AddressToUserId:Map + ) #as AddressToUserId:Map, + u(NumBoardMembers:Int), + NumProposers:Usize, + (CallerId |-> Role:UserRole + UserId |-> Proposer + _UserIdToRole:Map + ) #as UserIdToRole:Map, + u(Quorum:Int), + ActionLastIndex:Usize, + ActionId |-> AddProposer(UserAddress:Address) #as Action:Action + ActionData:Map, + ActionSigners:Map, + CallerAddress:Address, + Stack:Stack, + .Map, + PerformedActions:List + ) + + => + + evaluate(void) ~> K:K + invariantStateFull( + NumUsers, + UserIdToAddress, + AddressToUserId, + u(NumBoardMembers), + NumProposers, + UserIdToRole, + u(Quorum), + ActionLastIndex, + ActionData, + ActionSigners[ActionId <- undef], + CallerAddress, + Stack, + ?_Variables:Map, + ListItem(Action) PerformedActions + ) + + requires true + // perform-from-id + andBool isKResult(Action) + andBool addressToUserIdInvariant(AddressToUserId) + andBool Quorum <=Int NumBoardMembers + + // perform-fragment + andBool actionSignersInvariant(ActionSigners) + andBool userIdToRoleInvariant(UserIdToRole) + andBool (Role ==K BoardMember orBool Role ==K Proposer) + andBool Quorum <=Int countCanSignFunction({ActionSigners[ActionId] orDefault [.]}:>ExpressionList, opaque(UserIdToRole)) + ensures true + //@ proof + //@ trusted + // [trusted] + //@ end +endmodule + diff --git a/multisig/protocol-correctness/proof/invariant/proof-perform-parts-add-proposer-no-signers-eq.k b/multisig/protocol-correctness/proof/invariant/proof-perform-parts-add-proposer-no-signers-eq.k new file mode 100644 index 000000000..23c800a4a --- /dev/null +++ b/multisig/protocol-correctness/proof/invariant/proof-perform-parts-add-proposer-no-signers-eq.k @@ -0,0 +1,104 @@ +//@ proof +require "trusted-perform-parts-add-proposer-BoardMember-eq.k" //@ Bazel remove +require "trusted-perform-parts-add-proposer-BoardMember-no-quorum-eq.k" //@ Bazel remove +require "trusted-perform-parts-add-proposer-Proposer-eq.k" //@ Bazel remove + +module PROOF-PERFORM-PARTS-ADD-PROPOSER-NO-SIGNERS-EQ + imports INVARIANT-EXECUTION + + imports TRUSTED-PERFORM-PARTS-ADD-PROPOSER-BOARDMEMBER-EQ + imports TRUSTED-PERFORM-PARTS-ADD-PROPOSER-BOARDMEMBER-NO-QUORUM-EQ + imports TRUSTED-PERFORM-PARTS-ADD-PROPOSER-PROPOSER-EQ +//@ trusted +// module TRUSTED-PERFORM-PARTS-ADD-PROPOSER-NO-SIGNERS-EQ +//@ end + + imports PERFORM-ACTION-ENDPOINT-INSTRUMENTATION + + claim + splitAddProposer1(CallerAddress) + ~> call(performActionEndpoint(ActionId:Usize)) + ~> popContext + ~> evaluateReturnValue + ~> clearExternalCallEnv + ~> splitActionSigners(ActionId:Usize, ActionSigners:Map) + ~> runExternalCalls(EC:ExternalCommands) + + invariantStateStack( + NumUsers:Usize, + UserIdToAddress:Map, + (CallerAddress |-> CallerId:Usize _AddressToUserId:Map) #as AddressToUserId:Map, + NumBoardMembers:Usize, + NumProposers:Usize, + (CallerId |-> CallerRole:UserRole _UserIdToRole:Map) #as UserIdToRole:Map, + u(Quorum:Int), + ActionLastIndex0:Usize, + (ActionId |-> AddProposer(CallerAddress) ActionData0:Map) #as ActionData:Map, + ActionSigners:Map, + CallerAddress:Address, + stack( + invariantMultisigState( + NumUsers, + UserIdToAddress, + AddressToUserId, + NumBoardMembers, + NumProposers, + UserIdToRole, + u(Quorum), + ActionLastIndex0, + ActionData, + ActionSigners), + .Map, + PerformedActions, + .stack), + PerformedActions:List) + + => + + runExternalCalls(EC) + invariantState( + ?NumUsers1:Usize, + ?UserIdToAddress1:Map, + ?AddressToUserId1:Map, + ?NumBoardMembers1:Usize, + ?NumProposers1:Usize, + ?UserIdToRole1:Map, + ?Quorum1:Usize, + ?ActionLastIndex1:Usize, + ?ActionData1:Map, + ?ActionSigners1:Map, + ?_PerformedActions:List):StateCell + + requires true + andBool invariant( + NumUsers, + UserIdToAddress, + AddressToUserId, + NumBoardMembers, + NumProposers, + UserIdToRole, + u(Quorum), + ActionLastIndex0, + ActionData0, + ActionSigners, + expand(expanded)) + andBool (CallerRole ==K BoardMember orBool CallerRole ==K Proposer) + andBool Quorum <=Int countCanSignFunction({ActionSigners[ActionId] orDefault [.]}:>ExpressionList, opaque(UserIdToRole)) + andBool notBool ActionId in_keys(ActionSigners) + ensures invariant( + ?NumUsers1, + ?UserIdToAddress1, + ?AddressToUserId1, + ?NumBoardMembers1, + ?NumProposers1, + ?UserIdToRole1, + ?Quorum1, + ?ActionLastIndex1, + ?ActionData1, + ?ActionSigners1, + usesExpanded) + //@ proof + //@ trusted + // [trusted] + //@ end +endmodule diff --git a/multisig/protocol-correctness/proof/invariant/proof-perform-parts-add-proposer-no-signers-neq.k b/multisig/protocol-correctness/proof/invariant/proof-perform-parts-add-proposer-no-signers-neq.k new file mode 100644 index 000000000..1fab31c64 --- /dev/null +++ b/multisig/protocol-correctness/proof/invariant/proof-perform-parts-add-proposer-no-signers-neq.k @@ -0,0 +1,109 @@ +//@ proof +require "trusted-perform-parts-add-proposer-BoardMember.k" //@ Bazel remove +require "trusted-perform-parts-add-proposer-BoardMember-no-quorum.k" //@ Bazel remove +require "trusted-perform-parts-add-proposer-Proposer.k" //@ Bazel remove + +module PROOF-PERFORM-PARTS-ADD-PROPOSER-NO-SIGNERS-NEQ + imports INVARIANT-EXECUTION + + imports TRUSTED-PERFORM-PARTS-ADD-PROPOSER-BOARDMEMBER + imports TRUSTED-PERFORM-PARTS-ADD-PROPOSER-BOARDMEMBER-NO-QUORUM + imports TRUSTED-PERFORM-PARTS-ADD-PROPOSER-PROPOSER +//@ trusted +// module TRUSTED-PERFORM-PARTS-ADD-PROPOSER-NO-SIGNERS-NEQ +//@ end + + imports PERFORM-ACTION-ENDPOINT-INSTRUMENTATION + + claim + splitAddProposer3(UserAddress) + ~> call(performActionEndpoint(ActionId:Usize)) + ~> popContext + ~> evaluateReturnValue + ~> clearExternalCallEnv + ~> splitActionSigners(ActionId:Usize, ActionSigners:Map) + ~> runExternalCalls(EC:ExternalCommands) + + invariantStateStack( + NumUsers:Usize, + UserIdToAddress:Map, + (CallerAddress |-> CallerId:Usize + UserAddress |-> UserId:Usize + _AddressToUserId:Map + ) #as AddressToUserId:Map, + NumBoardMembers:Usize, + NumProposers:Usize, + (CallerId |-> CallerRole:UserRole _UserIdToRole:Map) #as UserIdToRole:Map, + u(Quorum:Int), + ActionLastIndex0:Usize, + (ActionId |-> AddProposer(UserAddress) ActionData0:Map) #as ActionData:Map, + ActionSigners:Map, + CallerAddress:Address, + stack( + invariantMultisigState( + NumUsers, + UserIdToAddress, + AddressToUserId, + NumBoardMembers, + NumProposers, + UserIdToRole, + u(Quorum), + ActionLastIndex0, + ActionData, + ActionSigners), + .Map, + PerformedActions, + .stack), + PerformedActions:List) + + => + + runExternalCalls(EC) + invariantState( + ?NumUsers1:Usize, + ?UserIdToAddress1:Map, + ?AddressToUserId1:Map, + ?NumBoardMembers1:Usize, + ?NumProposers1:Usize, + ?UserIdToRole1:Map, + ?Quorum1:Usize, + ?ActionLastIndex1:Usize, + ?ActionData1:Map, + ?ActionSigners1:Map, + ?_PerformedActions:List):StateCell + + requires true + andBool invariant( + NumUsers, + UserIdToAddress, + AddressToUserId, + NumBoardMembers, + NumProposers, + UserIdToRole, + u(Quorum), + ActionLastIndex0, + ActionData0, + ActionSigners, + expand(expanded)) + andBool (CallerRole ==K BoardMember orBool CallerRole ==K Proposer) + andBool Quorum <=Int countCanSignFunction({ActionSigners[ActionId] orDefault [.]}:>ExpressionList, opaque(UserIdToRole)) + andBool notBool UserAddress ==K CallerAddress + andBool UserId in_keys(UserIdToRole) + andBool notBool ActionId in_keys(ActionSigners) + ensures invariant( + ?NumUsers1, + ?UserIdToAddress1, + ?AddressToUserId1, + ?NumBoardMembers1, + ?NumProposers1, + ?UserIdToRole1, + ?Quorum1, + ?ActionLastIndex1, + ?ActionData1, + ?ActionSigners1, + usesExpanded) + //@ proof + //@ trusted + // [trusted] + //@ end +endmodule diff --git a/multisig/protocol-correctness/proof/invariant/proof-perform-parts-add-proposer-no-signers.k b/multisig/protocol-correctness/proof/invariant/proof-perform-parts-add-proposer-no-signers.k new file mode 100644 index 000000000..2f7453940 --- /dev/null +++ b/multisig/protocol-correctness/proof/invariant/proof-perform-parts-add-proposer-no-signers.k @@ -0,0 +1,106 @@ +//@ proof +require "trusted-perform-parts-add-proposer-no-signers-eq.k" //@ Bazel remove +require "trusted-perform-parts-add-proposer-no-signers-neq.k" //@ Bazel remove +require "trusted-perform-parts-add-proposer-New.k" //@ Bazel remove +require "trusted-perform-parts-add-proposer-None.k" //@ Bazel remove + +module PROOF-PERFORM-PARTS-ADD-PROPOSER-NO-SIGNERS + imports INVARIANT-EXECUTION + + imports TRUSTED-PERFORM-PARTS-ADD-PROPOSER-NO-SIGNERS-EQ + imports TRUSTED-PERFORM-PARTS-ADD-PROPOSER-NO-SIGNERS-NEQ + imports TRUSTED-PERFORM-PARTS-ADD-PROPOSER-NEW + imports TRUSTED-PERFORM-PARTS-ADD-PROPOSER-NONE +//@ trusted +// module TRUSTED-PERFORM-PARTS-ADD-PROPOSER-NO-SIGNERS +//@ end + + imports PERFORM-ACTION-ENDPOINT-INSTRUMENTATION + + claim + splitAddProposer(AddProposer(_UserAddress:Address) #as Action:Action) + ~> call(performActionEndpoint(ActionId:Usize)) + ~> popContext + ~> evaluateReturnValue + ~> clearExternalCallEnv + ~> splitActionSigners(ActionId:Usize, ActionSigners:Map) + ~> runExternalCalls(EC:ExternalCommands) + + invariantStateStack( + NumUsers:Usize, + UserIdToAddress:Map, + (CallerAddress |-> CallerId:Usize _AddressToUserId:Map) #as AddressToUserId:Map, + NumBoardMembers:Usize, + NumProposers:Usize, + (CallerId |-> CallerRole:UserRole _UserIdToRole:Map) #as UserIdToRole:Map, + u(Quorum:Int), + ActionLastIndex0:Usize, + (ActionId |-> Action ActionData0:Map) #as ActionData:Map, + ActionSigners:Map, + CallerAddress:Address, + stack( + invariantMultisigState( + NumUsers, + UserIdToAddress, + AddressToUserId, + NumBoardMembers, + NumProposers, + UserIdToRole, + u(Quorum), + ActionLastIndex0, + ActionData, + ActionSigners), + .Map, + PerformedActions, + .stack), + PerformedActions:List) + + => + + runExternalCalls(EC) + invariantState( + ?NumUsers1:Usize, + ?UserIdToAddress1:Map, + ?AddressToUserId1:Map, + ?NumBoardMembers1:Usize, + ?NumProposers1:Usize, + ?UserIdToRole1:Map, + ?Quorum1:Usize, + ?ActionLastIndex1:Usize, + ?ActionData1:Map, + ?ActionSigners1:Map, + ?_PerformedActions:List):StateCell + + requires true + andBool invariant( + NumUsers, + UserIdToAddress, + AddressToUserId, + NumBoardMembers, + NumProposers, + UserIdToRole, + u(Quorum), + ActionLastIndex0, + ActionData0, + ActionSigners, + expand(expanded)) + andBool (CallerRole ==K BoardMember orBool CallerRole ==K Proposer) + andBool Quorum <=Int countCanSignFunction({ActionSigners[ActionId] orDefault [.]}:>ExpressionList, opaque(UserIdToRole)) + andBool notBool ActionId in_keys(ActionSigners) + ensures invariant( + ?NumUsers1, + ?UserIdToAddress1, + ?AddressToUserId1, + ?NumBoardMembers1, + ?NumProposers1, + ?UserIdToRole1, + ?Quorum1, + ?ActionLastIndex1, + ?ActionData1, + ?ActionSigners1, + usesExpanded) + //@ proof + //@ trusted + // [trusted] + //@ end +endmodule diff --git a/multisig/protocol-correctness/proof/invariant/proof-perform-parts-add-proposer-signers-eq.k b/multisig/protocol-correctness/proof/invariant/proof-perform-parts-add-proposer-signers-eq.k new file mode 100644 index 000000000..75cd8639e --- /dev/null +++ b/multisig/protocol-correctness/proof/invariant/proof-perform-parts-add-proposer-signers-eq.k @@ -0,0 +1,103 @@ +//@ proof +require "trusted-perform-parts-add-proposer-BoardMember-eq.k" //@ Bazel remove +require "trusted-perform-parts-add-proposer-BoardMember-no-quorum-eq.k" //@ Bazel remove +require "trusted-perform-parts-add-proposer-Proposer-eq.k" //@ Bazel remove + +module PROOF-PERFORM-PARTS-ADD-PROPOSER-SIGNERS-EQ + imports INVARIANT-EXECUTION + + imports TRUSTED-PERFORM-PARTS-ADD-PROPOSER-BOARDMEMBER-EQ + imports TRUSTED-PERFORM-PARTS-ADD-PROPOSER-BOARDMEMBER-NO-QUORUM-EQ + imports TRUSTED-PERFORM-PARTS-ADD-PROPOSER-PROPOSER-EQ +//@ trusted +// module TRUSTED-PERFORM-PARTS-ADD-PROPOSER-SIGNERS-EQ +//@ end + + imports PERFORM-ACTION-ENDPOINT-INSTRUMENTATION + + claim + splitAddProposer1(CallerAddress) + ~> call(performActionEndpoint(ActionId:Usize)) + ~> popContext + ~> evaluateReturnValue + ~> clearExternalCallEnv + ~> splitActionSigners(ActionId:Usize, ActionSigners:Map) + ~> runExternalCalls(EC:ExternalCommands) + + invariantStateStack( + NumUsers:Usize, + UserIdToAddress:Map, + (CallerAddress |-> CallerId:Usize _AddressToUserId:Map) #as AddressToUserId:Map, + NumBoardMembers:Usize, + NumProposers:Usize, + (CallerId |-> CallerRole:UserRole _UserIdToRole:Map) #as UserIdToRole:Map, + u(Quorum:Int), + ActionLastIndex0:Usize, + (ActionId |-> AddProposer(CallerAddress) ActionData0:Map) #as ActionData:Map, + (ActionId |-> _Signers:ExpressionList _ActionSigners:Map) #as ActionSigners:Map, + CallerAddress:Address, + stack( + invariantMultisigState( + NumUsers, + UserIdToAddress, + AddressToUserId, + NumBoardMembers, + NumProposers, + UserIdToRole, + u(Quorum), + ActionLastIndex0, + ActionData, + ActionSigners), + .Map, + PerformedActions, + .stack), + PerformedActions:List) + + => + + runExternalCalls(EC) + invariantState( + ?NumUsers1:Usize, + ?UserIdToAddress1:Map, + ?AddressToUserId1:Map, + ?NumBoardMembers1:Usize, + ?NumProposers1:Usize, + ?UserIdToRole1:Map, + ?Quorum1:Usize, + ?ActionLastIndex1:Usize, + ?ActionData1:Map, + ?ActionSigners1:Map, + ?_PerformedActions:List):StateCell + + requires true + andBool invariant( + NumUsers, + UserIdToAddress, + AddressToUserId, + NumBoardMembers, + NumProposers, + UserIdToRole, + u(Quorum), + ActionLastIndex0, + ActionData0, + ActionSigners, + expand(expanded)) + andBool (CallerRole ==K BoardMember orBool CallerRole ==K Proposer) + andBool Quorum <=Int countCanSignFunction({ActionSigners[ActionId] orDefault [.]}:>ExpressionList, opaque(UserIdToRole)) + ensures invariant( + ?NumUsers1, + ?UserIdToAddress1, + ?AddressToUserId1, + ?NumBoardMembers1, + ?NumProposers1, + ?UserIdToRole1, + ?Quorum1, + ?ActionLastIndex1, + ?ActionData1, + ?ActionSigners1, + usesExpanded) + //@ proof + //@ trusted + // [trusted] + //@ end +endmodule diff --git a/multisig/protocol-correctness/proof/invariant/proof-perform-parts-add-proposer-signers-neq.k b/multisig/protocol-correctness/proof/invariant/proof-perform-parts-add-proposer-signers-neq.k new file mode 100644 index 000000000..96efd7333 --- /dev/null +++ b/multisig/protocol-correctness/proof/invariant/proof-perform-parts-add-proposer-signers-neq.k @@ -0,0 +1,108 @@ +//@ proof +require "trusted-perform-parts-add-proposer-BoardMember.k" //@ Bazel remove +require "trusted-perform-parts-add-proposer-BoardMember-no-quorum.k" //@ Bazel remove +require "trusted-perform-parts-add-proposer-Proposer.k" //@ Bazel remove + +module PROOF-PERFORM-PARTS-ADD-PROPOSER-SIGNERS-NEQ + imports INVARIANT-EXECUTION + + imports TRUSTED-PERFORM-PARTS-ADD-PROPOSER-BOARDMEMBER + imports TRUSTED-PERFORM-PARTS-ADD-PROPOSER-BOARDMEMBER-NO-QUORUM + imports TRUSTED-PERFORM-PARTS-ADD-PROPOSER-PROPOSER +//@ trusted +// module TRUSTED-PERFORM-PARTS-ADD-PROPOSER-SIGNERS-NEQ +//@ end + + imports PERFORM-ACTION-ENDPOINT-INSTRUMENTATION + + claim + splitAddProposer3(UserAddress) + ~> call(performActionEndpoint(ActionId:Usize)) + ~> popContext + ~> evaluateReturnValue + ~> clearExternalCallEnv + ~> splitActionSigners(ActionId:Usize, ActionSigners:Map) + ~> runExternalCalls(EC:ExternalCommands) + + invariantStateStack( + NumUsers:Usize, + UserIdToAddress:Map, + (CallerAddress |-> CallerId:Usize + UserAddress |-> UserId:Usize + _AddressToUserId:Map + ) #as AddressToUserId:Map, + NumBoardMembers:Usize, + NumProposers:Usize, + (CallerId |-> CallerRole:UserRole _UserIdToRole:Map) #as UserIdToRole:Map, + u(Quorum:Int), + ActionLastIndex0:Usize, + (ActionId |-> AddProposer(UserAddress) ActionData0:Map) #as ActionData:Map, + (ActionId |-> _Signers:ExpressionList _ActionSigners:Map) #as ActionSigners:Map, + CallerAddress:Address, + stack( + invariantMultisigState( + NumUsers, + UserIdToAddress, + AddressToUserId, + NumBoardMembers, + NumProposers, + UserIdToRole, + u(Quorum), + ActionLastIndex0, + ActionData, + ActionSigners), + .Map, + PerformedActions, + .stack), + PerformedActions:List) + + => + + runExternalCalls(EC) + invariantState( + ?NumUsers1:Usize, + ?UserIdToAddress1:Map, + ?AddressToUserId1:Map, + ?NumBoardMembers1:Usize, + ?NumProposers1:Usize, + ?UserIdToRole1:Map, + ?Quorum1:Usize, + ?ActionLastIndex1:Usize, + ?ActionData1:Map, + ?ActionSigners1:Map, + ?_PerformedActions:List):StateCell + + requires true + andBool invariant( + NumUsers, + UserIdToAddress, + AddressToUserId, + NumBoardMembers, + NumProposers, + UserIdToRole, + u(Quorum), + ActionLastIndex0, + ActionData0, + ActionSigners, + expand(expanded)) + andBool (CallerRole ==K BoardMember orBool CallerRole ==K Proposer) + andBool Quorum <=Int countCanSignFunction({ActionSigners[ActionId] orDefault [.]}:>ExpressionList, opaque(UserIdToRole)) + andBool notBool UserAddress ==K CallerAddress + andBool UserId in_keys(UserIdToRole) + ensures invariant( + ?NumUsers1, + ?UserIdToAddress1, + ?AddressToUserId1, + ?NumBoardMembers1, + ?NumProposers1, + ?UserIdToRole1, + ?Quorum1, + ?ActionLastIndex1, + ?ActionData1, + ?ActionSigners1, + usesExpanded) + //@ proof + //@ trusted + // [trusted] + //@ end +endmodule diff --git a/multisig/protocol-correctness/proof/invariant/proof-perform-parts-add-proposer-signers.k b/multisig/protocol-correctness/proof/invariant/proof-perform-parts-add-proposer-signers.k new file mode 100644 index 000000000..3e100a9c0 --- /dev/null +++ b/multisig/protocol-correctness/proof/invariant/proof-perform-parts-add-proposer-signers.k @@ -0,0 +1,105 @@ +//@ proof +require "trusted-perform-parts-add-proposer-eq.k" //@ Bazel remove +require "trusted-perform-parts-add-proposer-neq.k" //@ Bazel remove +require "trusted-perform-parts-add-proposer-New.k" //@ Bazel remove +require "trusted-perform-parts-add-proposer-None.k" //@ Bazel remove + +module PROOF-PERFORM-PARTS-ADD-PROPOSER-SIGNERS + imports INVARIANT-EXECUTION + + imports TRUSTED-PERFORM-PARTS-ADD-PROPOSER-SIGNERS-EQ + imports TRUSTED-PERFORM-PARTS-ADD-PROPOSER-SIGNERS-NEQ + imports TRUSTED-PERFORM-PARTS-ADD-PROPOSER-NEW + imports TRUSTED-PERFORM-PARTS-ADD-PROPOSER-NONE +//@ trusted +// module TRUSTED-PERFORM-PARTS-ADD-PROPOSER-SIGNERS +//@ end + + imports PERFORM-ACTION-ENDPOINT-INSTRUMENTATION + + claim + splitAddProposer(AddProposer(_UserAddress:Address) #as Action:Action) + ~> call(performActionEndpoint(ActionId:Usize)) + ~> popContext + ~> evaluateReturnValue + ~> clearExternalCallEnv + ~> splitActionSigners(ActionId:Usize, ActionSigners:Map) + ~> runExternalCalls(EC:ExternalCommands) + + invariantStateStack( + NumUsers:Usize, + UserIdToAddress:Map, + (CallerAddress |-> CallerId:Usize _AddressToUserId:Map) #as AddressToUserId:Map, + NumBoardMembers:Usize, + NumProposers:Usize, + (CallerId |-> CallerRole:UserRole _UserIdToRole:Map) #as UserIdToRole:Map, + u(Quorum:Int), + ActionLastIndex0:Usize, + (ActionId |-> Action ActionData0:Map) #as ActionData:Map, + (ActionId |-> _Signers:ExpressionList _ActionSigners:Map) #as ActionSigners:Map, + CallerAddress:Address, + stack( + invariantMultisigState( + NumUsers, + UserIdToAddress, + AddressToUserId, + NumBoardMembers, + NumProposers, + UserIdToRole, + u(Quorum), + ActionLastIndex0, + ActionData, + ActionSigners), + .Map, + PerformedActions, + .stack), + PerformedActions:List) + + => + + runExternalCalls(EC) + invariantState( + ?NumUsers1:Usize, + ?UserIdToAddress1:Map, + ?AddressToUserId1:Map, + ?NumBoardMembers1:Usize, + ?NumProposers1:Usize, + ?UserIdToRole1:Map, + ?Quorum1:Usize, + ?ActionLastIndex1:Usize, + ?ActionData1:Map, + ?ActionSigners1:Map, + ?_PerformedActions:List):StateCell + + requires true + andBool invariant( + NumUsers, + UserIdToAddress, + AddressToUserId, + NumBoardMembers, + NumProposers, + UserIdToRole, + u(Quorum), + ActionLastIndex0, + ActionData0, + ActionSigners, + expand(expanded)) + andBool (CallerRole ==K BoardMember orBool CallerRole ==K Proposer) + andBool Quorum <=Int countCanSignFunction({ActionSigners[ActionId] orDefault [.]}:>ExpressionList, opaque(UserIdToRole)) + ensures invariant( + ?NumUsers1, + ?UserIdToAddress1, + ?AddressToUserId1, + ?NumBoardMembers1, + ?NumProposers1, + ?UserIdToRole1, + ?Quorum1, + ?ActionLastIndex1, + ?ActionData1, + ?ActionSigners1, + usesExpanded) + //@ proof + //@ trusted + // [trusted] + //@ end +endmodule diff --git a/multisig/protocol-correctness/proof/invariant/proof-perform-parts-change-quorum-no-quorum.k b/multisig/protocol-correctness/proof/invariant/proof-perform-parts-change-quorum-no-quorum.k new file mode 100644 index 000000000..95b23ca17 --- /dev/null +++ b/multisig/protocol-correctness/proof/invariant/proof-perform-parts-change-quorum-no-quorum.k @@ -0,0 +1,71 @@ +//@ proof +require "../functions/trusted-perform-action-endpoint-change-quorum-no-quorum.k" //@ Bazel remove + +module PROOF-PERFORM-PARTS-CHANGE-QUORUM-NO-QUORUM + imports TRUSTED-PERFORM-ACTION-ENDPOINT-CHANGE-QUORUM-NO-QUORUM +//@ trusted +// module TRUSTED-PERFORM-PARTS-CHANGE-QUORUM-NO-QUORUM +//@ end + + imports PERFORM-ACTION-ENDPOINT-INSTRUMENTATION + + claim + change-quorum-no-quorum.k ~> call(performActionEndpoint(ActionId:Usize)) ~> K:K + invariantStateFull( + NumUsers:Usize, + UserIdToAddress:Map, + (CallerAddress |-> CallerId:Usize + _AddressToUserId:Map + ) #as AddressToUserId:Map, + u(NumBoardMembers:Int), + NumProposers:Usize, + (CallerId |-> Role:UserRole + _UserIdToRole:Map + ) #as UserIdToRole:Map, + u(OldQuorum:Int), + ActionLastIndex:Usize, + ActionId |-> ChangeQuorum(u(NewQuorum:Int)) #as Action:Action + ActionData:Map, + ActionSigners:Map, + CallerAddress:Address, + Stack:Stack, + .Map, + PerformedActions:List + ) + + => + + error ~> K:K + invariantStateFull( + NumUsers, + UserIdToAddress, + AddressToUserId, + u(NumBoardMembers), + NumProposers, + UserIdToRole, + u(OldQuorum), + ActionLastIndex, + ActionId |-> Action ActionData, + ActionSigners, + CallerAddress, + Stack, + ?_Variables:Map, + PerformedActions + ) + + requires true + // perform-from-id + andBool isKResult(Action) + andBool NewQuorum >Int NumBoardMembers + + // perform-fragment + andBool actionSignersInvariant(ActionSigners) + andBool userIdToRoleInvariant(UserIdToRole) + andBool (Role ==K BoardMember orBool Role ==K Proposer) + andBool OldQuorum <=Int countCanSignFunction({ActionSigners[ActionId] orDefault [.]}:>ExpressionList, opaque(UserIdToRole)) + ensures true + //@ proof + //@ trusted + // [trusted] + //@ end +endmodule diff --git a/multisig/protocol-correctness/proof/invariant/proof-perform-parts-change-quorum-with-quorum.k b/multisig/protocol-correctness/proof/invariant/proof-perform-parts-change-quorum-with-quorum.k new file mode 100644 index 000000000..41de93ab9 --- /dev/null +++ b/multisig/protocol-correctness/proof/invariant/proof-perform-parts-change-quorum-with-quorum.k @@ -0,0 +1,71 @@ +//@ proof +require "../functions/trusted-perform-action-endpoint-change-quorum.k" //@ Bazel remove + +module PROOF-PERFORM-PARTS-CHANGE-QUORUM-WITH-QUORUM + imports TRUSTED-PERFORM-ACTION-ENDPOINT-CHANGE-QUORUM +//@ trusted +// module TRUSTED-PERFORM-PARTS-CHANGE-QUORUM-WITH-QUORUM +//@ end + + imports PERFORM-ACTION-ENDPOINT-INSTRUMENTATION + + claim + change-quorum.k ~> call(performActionEndpoint(ActionId:Usize)) ~> K:K + invariantStateFull( + NumUsers:Usize, + UserIdToAddress:Map, + (CallerAddress |-> CallerId:Usize + _AddressToUserId:Map + ) #as AddressToUserId:Map, + u(NumBoardMembers:Int), + NumProposers:Usize, + (CallerId |-> Role:UserRole + _UserIdToRole:Map + ) #as UserIdToRole:Map, + u(OldQuorum:Int), + ActionLastIndex:Usize, + ActionId |-> ChangeQuorum(u(NewQuorum:Int)) #as Action:Action + ActionData:Map, + ActionSigners:Map, + CallerAddress:Address, + Stack:Stack, + .Map, + PerformedActions:List + ) + + => + + evaluate(void) ~> K:K + invariantStateFull( + NumUsers, + UserIdToAddress, + AddressToUserId, + u(NumBoardMembers), + NumProposers, + UserIdToRole, + u(NewQuorum), + ActionLastIndex, + ActionData, + ActionSigners[ActionId <- undef], + CallerAddress, + Stack, + ?_Variables:Map, + ListItem(Action) PerformedActions + ) + + requires true + // perform-from-id + andBool isKResult(Action) + andBool NewQuorum <=Int NumBoardMembers + + // perform-fragment + andBool actionSignersInvariant(ActionSigners) + andBool userIdToRoleInvariant(UserIdToRole) + andBool (Role ==K BoardMember orBool Role ==K Proposer) + andBool OldQuorum <=Int countCanSignFunction({ActionSigners[ActionId] orDefault [.]}:>ExpressionList, opaque(UserIdToRole)) + ensures true + //@ proof + //@ trusted + // [trusted] + //@ end +endmodule diff --git a/multisig/protocol-correctness/proof/invariant/proof-perform-parts-change-quorum.k b/multisig/protocol-correctness/proof/invariant/proof-perform-parts-change-quorum.k new file mode 100644 index 000000000..6c10cbbbc --- /dev/null +++ b/multisig/protocol-correctness/proof/invariant/proof-perform-parts-change-quorum.k @@ -0,0 +1,100 @@ +//@ proof +require "trusted-perform-parts-change-quorum-no-quorum.k" //@ Bazel remove +require "trusted-perform-parts-change-quorum-with-quorum.k" //@ Bazel remove + +module PROOF-PERFORM-PARTS-CHANGE-QUORUM + imports INVARIANT-EXECUTION + + imports TRUSTED-PERFORM-PARTS-CHANGE-QUORUM-NO-QUORUM + imports TRUSTED-PERFORM-PARTS-CHANGE-QUORUM-WITH-QUORUM +//@ trusted +// module TRUSTED-PERFORM-PARTS-CHANGE-QUORUM +//@ end + imports PERFORM-ACTION-ENDPOINT-INSTRUMENTATION + + claim + splitPerformActionEndpoint4(ChangeQuorum(_NewQuorum:Usize) #as Action:Action) + ~> call(performActionEndpoint(ActionId:Usize)) + ~> popContext + ~> evaluateReturnValue + ~> clearExternalCallEnv + ~> splitActionSigners(ActionId:Usize, ActionSigners:Map) + ~> runExternalCalls(EC:ExternalCommands) + + invariantStateStack( + NumUsers:Usize, + UserIdToAddress:Map, + (CallerAddress |-> CallerId:Usize _AddressToUserId:Map) #as AddressToUserId:Map, + NumBoardMembers:Usize, + NumProposers:Usize, + (CallerId |-> CallerRole:UserRole _UserIdToRole:Map) #as UserIdToRole:Map, + u(Quorum:Int), + ActionLastIndex0:Usize, + (ActionId |-> Action _ActionData:Map) #as ActionData:Map, + ActionSigners:Map, + CallerAddress:Address, + stack( + invariantMultisigState( + NumUsers, + UserIdToAddress, + AddressToUserId, + NumBoardMembers, + NumProposers, + UserIdToRole, + u(Quorum), + ActionLastIndex0, + ActionData, + ActionSigners), + .Map, + PerformedActions, + .stack), + PerformedActions:List) + + => + + runExternalCalls(EC) + invariantState( + ?NumUsers1:Usize, + ?UserIdToAddress1:Map, + ?AddressToUserId1:Map, + ?NumBoardMembers1:Usize, + ?NumProposers1:Usize, + ?UserIdToRole1:Map, + ?Quorum1:Usize, + ?ActionLastIndex1:Usize, + ?ActionData1:Map, + ?ActionSigners1:Map, + ?_PerformedActions:List):StateCell + + requires true + andBool invariant( + NumUsers, + UserIdToAddress, + AddressToUserId, + NumBoardMembers, + NumProposers, + UserIdToRole, + u(Quorum), + ActionLastIndex0, + ActionData, + ActionSigners, + expand(expanded)) + andBool (CallerRole ==K BoardMember orBool CallerRole ==K Proposer) + andBool Quorum <=Int countCanSignFunction({ActionSigners[ActionId] orDefault [.]}:>ExpressionList, opaque(UserIdToRole)) + ensures invariant( + ?NumUsers1, + ?UserIdToAddress1, + ?AddressToUserId1, + ?NumBoardMembers1, + ?NumProposers1, + ?UserIdToRole1, + ?Quorum1, + ?ActionLastIndex1, + ?ActionData1, + ?ActionSigners1, + usesExpanded) + //@ proof + //@ trusted + // [trusted] + //@ end +endmodule diff --git a/multisig/protocol-correctness/proof/invariant/proof-perform-parts-no-quorum.k b/multisig/protocol-correctness/proof/invariant/proof-perform-parts-no-quorum.k new file mode 100644 index 000000000..ba39c37a0 --- /dev/null +++ b/multisig/protocol-correctness/proof/invariant/proof-perform-parts-no-quorum.k @@ -0,0 +1,63 @@ +//@ proof +require "../functions/trusted-perform-action-endpoint-no-quorum.k" //@ Bazel remove + +module PROOF-PERFORM-PARTS-NO-QUORUM + imports TRUSTED-PERFORM-ACTION-ENDPOINT-NO-QUORUM +//@ trusted +// module TRUSTED-PERFORM-PARTS-NO-QUORUM +//@ end + + imports PERFORM-ACTION-ENDPOINT-INSTRUMENTATION + + claim + no-quorum.k ~> call(performActionEndpoint(ActionId:Usize)) ~> K:K + invariantStateFull( + NumUsers:Usize, + UserIdToAddress:Map, + (CallerAddress |-> UserId:Usize _AddressToUserId:Map) #as AddressToUserId:Map, + NumBoardMembers:Usize, + NumProposers:Usize, + (UserId |-> Role:UserRole _UserIdToRole:Map) #as UserIdToRole:Map, + u(Quorum:Int), + ActionLastIndex:Usize, + ActionData:Map, + ActionSigners:Map, + CallerAddress:Address, + Stack:Stack, + .Map, + PerformedActions:List + ) + + => + + error ~> K:K + invariantStateFull( + NumUsers, + UserIdToAddress, + AddressToUserId, + NumBoardMembers, + NumProposers, + UserIdToRole, + u(Quorum), + ActionLastIndex, + ActionData, + ActionSigners, + CallerAddress, + Stack, + caller_address |-> CallerAddress + caller_id |-> UserId + caller_role |-> Role, + PerformedActions + ) + + requires true + andBool userIdToRoleInvariant(UserIdToRole) + andBool actionSignersInvariant(ActionSigners) + andBool (Role ==K BoardMember orBool Role ==K Proposer) + andBool Quorum >Int countCanSignFunction({ActionSigners[ActionId] orDefault [.]}:>ExpressionList, opaque(UserIdToRole)) + ensures true + //@ proof + //@ trusted + // [trusted] + //@ end +endmodule diff --git a/multisig/protocol-correctness/proof/invariant/proof-perform-parts-nothing.k b/multisig/protocol-correctness/proof/invariant/proof-perform-parts-nothing.k new file mode 100644 index 000000000..e55c9c88e --- /dev/null +++ b/multisig/protocol-correctness/proof/invariant/proof-perform-parts-nothing.k @@ -0,0 +1,69 @@ +//@ proof +require "../functions/trusted-perform-action-endpoint-nothing.k" //@ Bazel remove + +module PROOF-PERFORM-PARTS-NOTHING + imports TRUSTED-PERFORM-ACTION-ENDPOINT-NOTHING +//@ trusted +// module TRUSTED-PERFORM-PARTS-NOTHING +//@ end + + imports PERFORM-ACTION-ENDPOINT-INSTRUMENTATION + + claim + nothing.k ~> call(performActionEndpoint(ActionId:Usize)) ~> K:K + invariantStateFull( + NumUsers:Usize, + UserIdToAddress:Map, + (CallerAddress |-> CallerId:Usize + _AddressToUserId:Map + ) #as AddressToUserId:Map, + NumBoardMembers:Usize, + NumProposers:Usize, + (CallerId |-> Role:UserRole + _UserIdToRole:Map + ) #as UserIdToRole:Map, + u(Quorum:Int), + ActionLastIndex:Usize, + ActionData:Map, + ActionSigners:Map, + CallerAddress:Address, + Stack:Stack, + .Map, + PerformedActions:List + ) + + => + + evaluate(void) ~> K:K + invariantStateFull( + NumUsers, + UserIdToAddress, + AddressToUserId, + NumBoardMembers, + NumProposers, + UserIdToRole, + u(Quorum), + ActionLastIndex, + ActionData, + ActionSigners[ActionId <- undef], + CallerAddress, + Stack, + ?_Variables:Map, + ListItem(Nothing) PerformedActions + ) + + requires true + // perform-from-id + andBool notBool ActionId in_keys(ActionData) + + // perform-fragment + andBool actionSignersInvariant(ActionSigners) + andBool userIdToRoleInvariant(UserIdToRole) + andBool (Role ==K BoardMember orBool Role ==K Proposer) + andBool Quorum <=Int countCanSignFunction({ActionSigners[ActionId] orDefault [.]}:>ExpressionList, opaque(UserIdToRole)) + ensures true + //@ proof + //@ trusted + // [trusted] + //@ end +endmodule diff --git a/multisig/protocol-correctness/proof/invariant/proof-perform-parts-remove-user-BoardMember-eq.k b/multisig/protocol-correctness/proof/invariant/proof-perform-parts-remove-user-BoardMember-eq.k new file mode 100644 index 000000000..992993fce --- /dev/null +++ b/multisig/protocol-correctness/proof/invariant/proof-perform-parts-remove-user-BoardMember-eq.k @@ -0,0 +1,72 @@ +//@ proof +require "../functions/trusted-perform-action-endpoint-remove-user-BoardMember-eq.k" //@ Bazel remove + +module PROOF-PERFORM-PARTS-REMOVE-USER-BOARDMEMBER-EQ + imports TRUSTED-PERFORM-ACTION-ENDPOINT-REMOVE-USER-BOARDMEMBER-EQ +//@ trusted +// module TRUSTED-PERFORM-PARTS-REMOVE-USER-BOARDMEMBER-EQ +//@ end + + imports PERFORM-ACTION-ENDPOINT-INSTRUMENTATION + + claim + remove-user-BoardMember-eq.k ~> call(performActionEndpoint(ActionId:Usize)) ~> K:K + invariantStateFull( + NumUsers:Usize, + UserIdToAddress:Map, + (CallerAddress |-> CallerId:Usize + _AddressToUserId:Map + ) #as AddressToUserId:Map, + u(NumBoardMembers:Int), + u(NumProposers:Int), + (CallerId |-> BoardMember + UserIdToRoleInner:Map + ) #as UserIdToRole:Map, + u(Quorum:Int), + ActionLastIndex:Usize, + ActionId |-> RemoveUser(CallerAddress:Address) #as Action:Action + ActionData:Map, + ActionSigners:Map, + CallerAddress:Address, + Stack:Stack, + .Map, + PerformedActions:List + ) + + => + + evaluate(void) ~> K:K + invariantStateFull( + NumUsers, + UserIdToAddress, + AddressToUserId, + u(NumBoardMembers -Int 1), + u(NumProposers), + UserIdToRoleInner, + u(Quorum), + ActionLastIndex, + ActionData, + ActionSigners[ActionId <- undef], + CallerAddress, + Stack, + ?_Variables:Map, + ListItem(Action) PerformedActions + ) + + requires true + // perform-from-id + andBool isKResult(Action) + andBool addressToUserIdInvariant(AddressToUserId) + andBool NumBoardMembers +Int NumProposers -Int 1 >Int 0 + andBool Quorum <=Int NumBoardMembers -Int 1 + + // perform-fragment + andBool actionSignersInvariant(ActionSigners) + andBool userIdToRoleInvariant(UserIdToRole) + andBool Quorum <=Int countCanSignFunction({ActionSigners[ActionId] orDefault [.]}:>ExpressionList, opaque(UserIdToRole)) + ensures true + //@ proof + //@ trusted + // [trusted] + //@ end +endmodule diff --git a/multisig/protocol-correctness/proof/invariant/proof-perform-parts-remove-user-BoardMember-too-few-eq.k b/multisig/protocol-correctness/proof/invariant/proof-perform-parts-remove-user-BoardMember-too-few-eq.k new file mode 100644 index 000000000..af96105a1 --- /dev/null +++ b/multisig/protocol-correctness/proof/invariant/proof-perform-parts-remove-user-BoardMember-too-few-eq.k @@ -0,0 +1,74 @@ +//@ proof +require "../functions/trusted-perform-action-endpoint-remove-user-BoardMember-too-few-eq.k" //@ Bazel remove + +module PROOF-PERFORM-PARTS-REMOVE-USER-BOARDMEMBER-TOO-FEW-EQ + imports TRUSTED-PERFORM-ACTION-ENDPOINT-REMOVE-USER-BOARDMEMBER-TOO-FEW-EQ +//@ trusted +// module TRUSTED-PERFORM-PARTS-REMOVE-USER-BOARDMEMBER-TOO-FEW-EQ +//@ end + + imports PERFORM-ACTION-ENDPOINT-INSTRUMENTATION + + claim + remove-user-BoardMember-too-few-eq.k ~> call(performActionEndpoint(ActionId:Usize)) ~> K:K + invariantStateFull( + NumUsers:Usize, + UserIdToAddress:Map, + (CallerAddress |-> CallerId:Usize + _AddressToUserId:Map + ) #as AddressToUserId:Map, + u(NumBoardMembers:Int), + u(NumProposers:Int), + (CallerId |-> BoardMember + _UserIdToRole:Map + ) #as UserIdToRole:Map, + u(Quorum:Int), + ActionLastIndex:Usize, + ActionId |-> RemoveUser(CallerAddress:Address) #as Action:Action + ActionData:Map, + ActionSigners:Map, + CallerAddress:Address, + Stack:Stack, + .Map, + PerformedActions:List + ) + + => + + error ~> K:K + invariantStateFull( + NumUsers, + UserIdToAddress, + AddressToUserId, + u(NumBoardMembers), + u(NumProposers), + UserIdToRole, + u(Quorum), + ActionLastIndex, + ActionId |-> Action ActionData, + ActionSigners, + CallerAddress, + Stack, + ?_Variables:Map, + PerformedActions + ) + + requires true + // perform-from-id + andBool isKResult(Action) + andBool addressToUserIdInvariant(AddressToUserId) + andBool (false + orBool NumBoardMembers +Int NumProposers ==Int 1 + orBool Quorum ==Int NumBoardMembers + ) + + // perform-fragment + andBool actionSignersInvariant(ActionSigners) + andBool userIdToRoleInvariant(UserIdToRole) + andBool Quorum <=Int countCanSignFunction({ActionSigners[ActionId] orDefault [.]}:>ExpressionList, opaque(UserIdToRole)) + ensures true + //@ proof + //@ trusted + // [trusted] + //@ end +endmodule diff --git a/multisig/protocol-correctness/proof/invariant/proof-perform-parts-remove-user-BoardMember-too-few.k b/multisig/protocol-correctness/proof/invariant/proof-perform-parts-remove-user-BoardMember-too-few.k new file mode 100644 index 000000000..ec9d1268f --- /dev/null +++ b/multisig/protocol-correctness/proof/invariant/proof-perform-parts-remove-user-BoardMember-too-few.k @@ -0,0 +1,77 @@ +//@ proof +require "../functions/trusted-perform-action-endpoint-remove-user-BoardMember-too-few.k" //@ Bazel remove + +module PROOF-PERFORM-PARTS-REMOVE-USER-BOARDMEMBER-TOO-FEW + imports TRUSTED-PERFORM-ACTION-ENDPOINT-REMOVE-USER-BOARDMEMBER-TOO-FEW +//@ trusted +// module TRUSTED-PERFORM-PARTS-REMOVE-USER-BOARDMEMBER-TOO-FEW +//@ end + + imports PERFORM-ACTION-ENDPOINT-INSTRUMENTATION + + claim + remove-user-BoardMember-too-few.k ~> call(performActionEndpoint(ActionId:Usize)) ~> K:K + invariantStateFull( + NumUsers:Usize, + UserIdToAddress:Map, + (CallerAddress |-> CallerId:Usize + UserAddress |-> UserId:Usize + _AddressToUserId:Map + ) #as AddressToUserId:Map, + u(NumBoardMembers:Int), + u(NumProposers:Int), + (CallerId |-> Role:UserRole + UserId |-> BoardMember + _UserIdToRole:Map + ) #as UserIdToRole:Map, + u(Quorum:Int), + ActionLastIndex:Usize, + ActionId |-> RemoveUser(UserAddress:Address) #as Action:Action + ActionData:Map, + ActionSigners:Map, + CallerAddress:Address, + Stack:Stack, + .Map, + PerformedActions:List + ) + + => + + error ~> K:K + invariantStateFull( + NumUsers, + UserIdToAddress, + AddressToUserId, + u(NumBoardMembers), + u(NumProposers), + UserIdToRole, + u(Quorum), + ActionLastIndex, + ActionId |-> Action ActionData, + ActionSigners, + CallerAddress, + Stack, + ?_Variables:Map, + PerformedActions + ) + + requires true + // perform-from-id + andBool isKResult(Action) + andBool addressToUserIdInvariant(AddressToUserId) + andBool (false + orBool NumBoardMembers +Int NumProposers ==Int 1 + orBool Quorum ==Int NumBoardMembers + ) + + // perform-fragment + andBool actionSignersInvariant(ActionSigners) + andBool userIdToRoleInvariant(UserIdToRole) + andBool (Role ==K BoardMember orBool Role ==K Proposer) + andBool Quorum <=Int countCanSignFunction({ActionSigners[ActionId] orDefault [.]}:>ExpressionList, opaque(UserIdToRole)) + ensures true + //@ proof + //@ trusted + // [trusted] + //@ end +endmodule diff --git a/multisig/protocol-correctness/proof/invariant/proof-perform-parts-remove-user-BoardMember.k b/multisig/protocol-correctness/proof/invariant/proof-perform-parts-remove-user-BoardMember.k new file mode 100644 index 000000000..068decb28 --- /dev/null +++ b/multisig/protocol-correctness/proof/invariant/proof-perform-parts-remove-user-BoardMember.k @@ -0,0 +1,75 @@ +//@ proof +require "../functions/trusted-perform-action-endpoint-remove-user-BoardMember.k" //@ Bazel remove + +module PROOF-PERFORM-PARTS-REMOVE-USER-BOARDMEMBER + imports TRUSTED-PERFORM-ACTION-ENDPOINT-REMOVE-USER-BOARDMEMBER +//@ trusted +// module TRUSTED-PERFORM-PARTS-REMOVE-USER-BOARDMEMBER +//@ end + + imports PERFORM-ACTION-ENDPOINT-INSTRUMENTATION + + claim + remove-user-BoardMember.k ~> call(performActionEndpoint(ActionId:Usize)) ~> K:K + invariantStateFull( + NumUsers:Usize, + UserIdToAddress:Map, + (CallerAddress |-> CallerId:Usize + UserAddress |-> UserId:Usize + _AddressToUserId:Map + ) #as AddressToUserId:Map, + u(NumBoardMembers:Int), + u(NumProposers:Int), + (CallerId |-> Role:UserRole + UserId |-> BoardMember + UserIdToRoleInner:Map + ) #as UserIdToRole:Map, + u(Quorum:Int), + ActionLastIndex:Usize, + ActionId |-> RemoveUser(UserAddress:Address) #as Action:Action + ActionData:Map, + ActionSigners:Map, + CallerAddress:Address, + Stack:Stack, + .Map, + PerformedActions:List + ) + + => + + evaluate(void) ~> K:K + invariantStateFull( + NumUsers, + UserIdToAddress, + AddressToUserId, + u(NumBoardMembers -Int 1), + u(NumProposers), + (CallerId |-> Role UserIdToRoleInner), + u(Quorum), + ActionLastIndex, + ActionData, + ActionSigners[ActionId <- undef], + CallerAddress, + Stack, + ?_Variables:Map, + ListItem(Action) PerformedActions + ) + + requires true + // perform-from-id + andBool isKResult(Action) + andBool addressToUserIdInvariant(AddressToUserId) + andBool NumBoardMembers +Int NumProposers -Int 1 >Int 0 + andBool Quorum <=Int NumBoardMembers -Int 1 + + // perform-fragment + andBool actionSignersInvariant(ActionSigners) + andBool userIdToRoleInvariant(UserIdToRole) + andBool (Role ==K BoardMember orBool Role ==K Proposer) + andBool Quorum <=Int countCanSignFunction({ActionSigners[ActionId] orDefault [.]}:>ExpressionList, opaque(UserIdToRole)) + ensures true + //@ proof + //@ trusted + // [trusted] + //@ end +endmodule diff --git a/multisig/protocol-correctness/proof/invariant/proof-perform-parts-remove-user-New.k b/multisig/protocol-correctness/proof/invariant/proof-perform-parts-remove-user-New.k new file mode 100644 index 000000000..77e656621 --- /dev/null +++ b/multisig/protocol-correctness/proof/invariant/proof-perform-parts-remove-user-New.k @@ -0,0 +1,78 @@ +//@ proof +require "../functions/trusted-perform-action-endpoint-remove-user-New.k" //@ Bazel remove + +module PROOF-PERFORM-PARTS-REMOVE-USER-NEW + imports TRUSTED-PERFORM-ACTION-ENDPOINT-REMOVE-USER-NEW +//@ trusted +// module TRUSTED-PERFORM-PARTS-REMOVE-USER-NEW +//@ end + + imports PERFORM-ACTION-ENDPOINT-INSTRUMENTATION + + claim + remove-user-New.k ~> call(performActionEndpoint(ActionId:Usize)) ~> K:K + invariantStateFull( + u(NumUsers:Int), + UserIdToAddress:Map, + (CallerAddress |-> CallerId:Usize + _AddressToUserId:Map + ) #as AddressToUserId:Map, + u(NumBoardMembers:Int), + u(NumProposers:Int), + (CallerId |-> Role:UserRole + _UserIdToRole:Map + ) #as UserIdToRole:Map, + u(Quorum:Int), + ActionLastIndex:Usize, + ActionId |-> RemoveUser(UserAddress:Address) #as Action:Action + ActionData:Map, + ActionSigners:Map, + CallerAddress:Address, + Stack:Stack, + .Map, + PerformedActions:List + ) + + => + + evaluate(void) ~> K:K + invariantStateFull( + u(NumUsers +Int 1), + u(NumUsers +Int 1) |-> UserAddress UserIdToAddress, + UserAddress |-> u(NumUsers +Int 1) AddressToUserId, + u(NumBoardMembers), + u(NumProposers), + UserIdToRole, + u(Quorum), + ActionLastIndex, + ActionData, + ActionSigners[ActionId <- undef], + CallerAddress, + Stack, + ?_Variables:Map, + ListItem(Action) PerformedActions + ) + + requires true + // perform-from-id + andBool isKResult(Action) + andBool NumUsers >=Int 0 + // TODO: Perhaps replace with unusedIdsInMapValues(AddressToUserId) + + // something to map values to keys. + andBool unusedIdsInMapKeys(NumUsers +Int 1, keysMap(UserIdToAddress), expand(expanded)) + andBool unusedIdsInMapKeys(NumUsers +Int 1, keysMap(UserIdToRole), expand(expanded)) + andBool NumBoardMembers +Int NumProposers >Int 0 + andBool Quorum <=Int NumBoardMembers + andBool notBool (UserAddress in_keys(AddressToUserId)) + + // perform-fragment + andBool actionSignersInvariant(ActionSigners) + andBool userIdToRoleInvariant(UserIdToRole) + andBool (Role ==K BoardMember orBool Role ==K Proposer) + andBool Quorum <=Int countCanSignFunction({ActionSigners[ActionId] orDefault [.]}:>ExpressionList, opaque(UserIdToRole)) + ensures true + //@ proof + //@ trusted + // [trusted] + //@ end +endmodule diff --git a/multisig/protocol-correctness/proof/invariant/proof-perform-parts-remove-user-None.k b/multisig/protocol-correctness/proof/invariant/proof-perform-parts-remove-user-None.k new file mode 100644 index 000000000..a1fee781d --- /dev/null +++ b/multisig/protocol-correctness/proof/invariant/proof-perform-parts-remove-user-None.k @@ -0,0 +1,75 @@ +//@ proof +require "../functions/trusted-perform-action-endpoint-remove-user-None.k" //@ Bazel remove + +module PROOF-PERFORM-PARTS-REMOVE-USER-NONE + imports TRUSTED-PERFORM-ACTION-ENDPOINT-REMOVE-USER-NONE +//@ trusted +// module TRUSTED-PERFORM-PARTS-REMOVE-USER-NONE +//@ end + + imports PERFORM-ACTION-ENDPOINT-INSTRUMENTATION + + claim + remove-user-None.k ~> call(performActionEndpoint(ActionId:Usize)) ~> K:K + invariantStateFull( + NumUsers:Usize, + UserIdToAddress:Map, + (CallerAddress |-> CallerId:Usize + UserAddress |-> UserId:Usize + _AddressToUserId:Map + ) #as AddressToUserId:Map, + u(NumBoardMembers:Int), + u(NumProposers:Int), + (CallerId |-> Role:UserRole + _UserIdToRole:Map + ) #as UserIdToRole:Map, + u(Quorum:Int), + ActionLastIndex:Usize, + ActionId |-> RemoveUser(UserAddress:Address) #as Action:Action + ActionData:Map, + ActionSigners:Map, + CallerAddress:Address, + Stack:Stack, + .Map, + PerformedActions:List + ) + + => + + evaluate(void) ~> K:K + invariantStateFull( + NumUsers, + UserIdToAddress, + AddressToUserId, + u(NumBoardMembers), + u(NumProposers), + UserIdToRole, + u(Quorum), + ActionLastIndex, + ActionData, + ActionSigners[ActionId <- undef], + CallerAddress, + Stack, + ?_Variables:Map, + ListItem(Action) PerformedActions + ) + + requires true + // perform-from-id + andBool isKResult(Action) + andBool addressToUserIdInvariant(AddressToUserId) + andBool Quorum <=Int NumBoardMembers + andBool NumBoardMembers +Int NumProposers >Int 0 + andBool notBool (UserId in_keys(UserIdToRole)) + + // perform-fragment + andBool actionSignersInvariant(ActionSigners) + andBool userIdToRoleInvariant(UserIdToRole) + andBool (Role ==K BoardMember orBool Role ==K Proposer) + andBool Quorum <=Int countCanSignFunction({ActionSigners[ActionId] orDefault [.]}:>ExpressionList, opaque(UserIdToRole)) + ensures true + //@ proof + //@ trusted + // [trusted] + //@ end +endmodule diff --git a/multisig/protocol-correctness/proof/invariant/proof-perform-parts-remove-user-Proposer-eq.k b/multisig/protocol-correctness/proof/invariant/proof-perform-parts-remove-user-Proposer-eq.k new file mode 100644 index 000000000..3a9492f7c --- /dev/null +++ b/multisig/protocol-correctness/proof/invariant/proof-perform-parts-remove-user-Proposer-eq.k @@ -0,0 +1,72 @@ +//@ proof +require "../functions/trusted-perform-action-endpoint-remove-user-Proposer-eq.k" //@ Bazel remove + +module PROOF-PERFORM-PARTS-REMOVE-USER-PROPOSER-EQ + imports TRUSTED-PERFORM-ACTION-ENDPOINT-REMOVE-USER-PROPOSER-EQ +//@ trusted +// module TRUSTED-PERFORM-PARTS-REMOVE-USER-PROPOSER-EQ +//@ end + + imports PERFORM-ACTION-ENDPOINT-INSTRUMENTATION + + claim + remove-user-Proposer-eq.k ~> call(performActionEndpoint(ActionId:Usize)) ~> K:K + invariantStateFull( + NumUsers:Usize, + UserIdToAddress:Map, + (CallerAddress |-> CallerId:Usize + _AddressToUserId:Map + ) #as AddressToUserId:Map, + u(NumBoardMembers:Int), + u(NumProposers:Int), + (CallerId |-> Proposer + UserIdToRoleInner:Map + ) #as UserIdToRole, + u(Quorum:Int), + ActionLastIndex:Usize, + ActionId |-> RemoveUser(CallerAddress:Address) #as Action:Action + ActionData:Map, + ActionSigners:Map, + CallerAddress:Address, + Stack:Stack, + .Map, + PerformedActions:List + ) + + => + + evaluate(void) ~> K:K + invariantStateFull( + NumUsers, + UserIdToAddress, + AddressToUserId, + u(NumBoardMembers), + u(NumProposers -Int 1), + UserIdToRoleInner, + u(Quorum), + ActionLastIndex, + ActionData, + ActionSigners[ActionId <- undef], + CallerAddress, + Stack, + ?_Variables:Map, + ListItem(Action) PerformedActions + ) + + requires true + // perform-from-id + andBool isKResult(Action) + andBool addressToUserIdInvariant(AddressToUserId) + andBool Quorum <=Int NumBoardMembers + andBool NumBoardMembers +Int NumProposers -Int 1 >Int 0 + + // perform-fragment + andBool actionSignersInvariant(ActionSigners) + andBool userIdToRoleInvariant(UserIdToRole) + andBool Quorum <=Int countCanSignFunction({ActionSigners[ActionId] orDefault [.]}:>ExpressionList, opaque(UserIdToRole)) + ensures true + //@ proof + //@ trusted + // [trusted] + //@ end +endmodule diff --git a/multisig/protocol-correctness/proof/invariant/proof-perform-parts-remove-user-Proposer-nobody-left-eq.k b/multisig/protocol-correctness/proof/invariant/proof-perform-parts-remove-user-Proposer-nobody-left-eq.k new file mode 100644 index 000000000..83df0126f --- /dev/null +++ b/multisig/protocol-correctness/proof/invariant/proof-perform-parts-remove-user-Proposer-nobody-left-eq.k @@ -0,0 +1,72 @@ +//@ proof +require "../functions/trusted-perform-action-endpoint-remove-user-Proposer-nobody-left-eq.k" //@ Bazel remove + +module PROOF-PERFORM-PARTS-REMOVE-USER-PROPOSER-NOBODY-LEFT-EQ + imports TRUSTED-PERFORM-ACTION-ENDPOINT-REMOVE-USER-PROPOSER-NOBODY-LEFT-EQ +//@ trusted +// module TRUSTED-PERFORM-PARTS-REMOVE-USER-PROPOSER-NOBODY-LEFT-EQ +//@ end + + imports PERFORM-ACTION-ENDPOINT-INSTRUMENTATION + + claim + remove-user-Proposer-nobody-left-eq.k ~> call(performActionEndpoint(ActionId:Usize)) ~> K:K + invariantStateFull( + NumUsers:Usize, + UserIdToAddress:Map, + (CallerAddress |-> CallerId:Usize + _AddressToUserId:Map + ) #as AddressToUserId:Map, + u(NumBoardMembers:Int), + u(NumProposers:Int), + (CallerId |-> Proposer + _UserIdToRole:Map + ) #as UserIdToRole:Map, + u(Quorum:Int), + ActionLastIndex:Usize, + ActionId |-> RemoveUser(CallerAddress:Address) #as Action:Action + ActionData:Map, + ActionSigners:Map, + CallerAddress:Address, + Stack:Stack, + .Map, + PerformedActions:List + ) + + => + + error ~> K:K + invariantStateFull( + NumUsers, + UserIdToAddress, + AddressToUserId, + u(NumBoardMembers), + u(NumProposers), + UserIdToRole, + u(Quorum), + ActionLastIndex, + ActionId |-> Action ActionData, + ActionSigners, + CallerAddress, + Stack, + ?_Variables:Map, + PerformedActions + ) + + requires true + // perform-from-id + andBool isKResult(Action) + andBool addressToUserIdInvariant(AddressToUserId) + andBool Quorum <=Int NumBoardMembers + andBool NumBoardMembers +Int NumProposers ==Int 1 + + // perform-fragment + andBool actionSignersInvariant(ActionSigners) + andBool userIdToRoleInvariant(UserIdToRole) + andBool Quorum <=Int countCanSignFunction({ActionSigners[ActionId] orDefault [.]}:>ExpressionList, opaque(UserIdToRole)) + ensures true + //@ proof + //@ trusted + // [trusted] + //@ end +endmodule diff --git a/multisig/protocol-correctness/proof/invariant/proof-perform-parts-remove-user-Proposer-nobody-left.k b/multisig/protocol-correctness/proof/invariant/proof-perform-parts-remove-user-Proposer-nobody-left.k new file mode 100644 index 000000000..ab119b43a --- /dev/null +++ b/multisig/protocol-correctness/proof/invariant/proof-perform-parts-remove-user-Proposer-nobody-left.k @@ -0,0 +1,75 @@ +//@ proof +require "../functions/trusted-perform-action-endpoint-remove-user-Proposer-nobody-left.k" //@ Bazel remove + +module PROOF-PERFORM-PARTS-REMOVE-USER-PROPOSER-NOBODY-LEFT + imports TRUSTED-PERFORM-ACTION-ENDPOINT-REMOVE-USER-PROPOSER-NOBODY-LEFT +//@ trusted +// module TRUSTED-PERFORM-PARTS-REMOVE-USER-PROPOSER-NOBODY-LEFT +//@ end + + imports PERFORM-ACTION-ENDPOINT-INSTRUMENTATION + + claim + remove-user-Proposer-nobody-left.k ~> call(performActionEndpoint(ActionId:Usize)) ~> K:K + invariantStateFull( + NumUsers:Usize, + UserIdToAddress:Map, + (CallerAddress |-> CallerId:Usize + UserAddress |-> UserId:Usize + _AddressToUserId:Map + ) #as AddressToUserId:Map, + u(NumBoardMembers:Int), + u(NumProposers:Int), + (CallerId |-> Role:UserRole + UserId |-> Proposer + _UserIdToRole:Map + ) #as UserIdToRole:Map, + u(Quorum:Int), + ActionLastIndex:Usize, + ActionId |-> RemoveUser(UserAddress:Address) #as Action:Action + ActionData:Map, + ActionSigners:Map, + CallerAddress:Address, + Stack:Stack, + .Map, + PerformedActions:List + ) + + => + + error ~> K:K + invariantStateFull( + NumUsers, + UserIdToAddress, + AddressToUserId, + u(NumBoardMembers), + u(NumProposers), + UserIdToRole, + u(Quorum), + ActionLastIndex, + ActionId |-> Action ActionData, + ActionSigners, + CallerAddress, + Stack, + ?_Variables:Map, + PerformedActions + ) + + requires true + // perform-from-id + andBool isKResult(Action) + andBool addressToUserIdInvariant(AddressToUserId) + andBool Quorum <=Int NumBoardMembers + andBool NumBoardMembers +Int NumProposers ==Int 1 + + // perform-fragment + andBool actionSignersInvariant(ActionSigners) + andBool userIdToRoleInvariant(UserIdToRole) + andBool (Role ==K BoardMember orBool Role ==K Proposer) + andBool Quorum <=Int countCanSignFunction({ActionSigners[ActionId] orDefault [.]}:>ExpressionList, opaque(UserIdToRole)) + ensures true + //@ proof + //@ trusted + // [trusted] + //@ end +endmodule diff --git a/multisig/protocol-correctness/proof/invariant/proof-perform-parts-remove-user-Proposer.k b/multisig/protocol-correctness/proof/invariant/proof-perform-parts-remove-user-Proposer.k new file mode 100644 index 000000000..23175db4b --- /dev/null +++ b/multisig/protocol-correctness/proof/invariant/proof-perform-parts-remove-user-Proposer.k @@ -0,0 +1,75 @@ +//@ proof +require "../functions/trusted-perform-action-endpoint-remove-user-Proposer.k" //@ Bazel remove + +module PROOF-PERFORM-PARTS-REMOVE-USER-PROPOSER + imports TRUSTED-PERFORM-ACTION-ENDPOINT-REMOVE-USER-PROPOSER +//@ trusted +// module TRUSTED-PERFORM-PARTS-REMOVE-USER-PROPOSER +//@ end + + imports PERFORM-ACTION-ENDPOINT-INSTRUMENTATION + + claim + remove-user-Proposer.k ~> call(performActionEndpoint(ActionId:Usize)) ~> K:K + invariantStateFull( + NumUsers:Usize, + UserIdToAddress:Map, + (CallerAddress |-> CallerId:Usize + UserAddress |-> UserId:Usize + _AddressToUserId:Map + ) #as AddressToUserId:Map, + u(NumBoardMembers:Int), + u(NumProposers:Int), + (CallerId |-> Role:UserRole + UserId |-> Proposer + UserIdToRoleInner:Map + ) #as UserIdToRole:Map, + u(Quorum:Int), + ActionLastIndex:Usize, + ActionId |-> RemoveUser(UserAddress:Address) #as Action:Action + ActionData:Map, + ActionSigners:Map, + CallerAddress:Address, + Stack:Stack, + .Map, + PerformedActions:List + ) + + => + + evaluate(void) ~> K:K + invariantStateFull( + NumUsers, + UserIdToAddress, + AddressToUserId, + u(NumBoardMembers), + u(NumProposers -Int 1), + (CallerId |-> Role UserIdToRoleInner), + u(Quorum), + ActionLastIndex, + ActionData, + ActionSigners[ActionId <- undef], + CallerAddress, + Stack, + ?_Variables:Map, + ListItem(Action) PerformedActions + ) + + requires true + // perform-from-id + andBool isKResult(Action) + andBool addressToUserIdInvariant(AddressToUserId) + andBool Quorum <=Int NumBoardMembers + andBool NumBoardMembers +Int NumProposers -Int 1 >Int 0 + + // perform-fragment + andBool actionSignersInvariant(ActionSigners) + andBool userIdToRoleInvariant(UserIdToRole) + andBool (Role ==K BoardMember orBool Role ==K Proposer) + andBool Quorum <=Int countCanSignFunction({ActionSigners[ActionId] orDefault [.]}:>ExpressionList, opaque(UserIdToRole)) + ensures true + //@ proof + //@ trusted + // [trusted] + //@ end +endmodule diff --git a/multisig/protocol-correctness/proof/invariant/proof-perform-parts-remove-user-eq.k b/multisig/protocol-correctness/proof/invariant/proof-perform-parts-remove-user-eq.k new file mode 100644 index 000000000..787fac588 --- /dev/null +++ b/multisig/protocol-correctness/proof/invariant/proof-perform-parts-remove-user-eq.k @@ -0,0 +1,104 @@ +//@ proof +require "trusted-perform-parts-remove-user-BoardMember-eq.k" //@ Bazel remove +require "trusted-perform-parts-remove-user-BoardMember-too-few-eq.k" //@ Bazel remove +require "trusted-perform-parts-remove-user-Proposer-eq.k" //@ Bazel remove +require "trusted-perform-parts-remove-user-Proposer-nobody-left-eq.k" //@ Bazel remove + +module PROOF-PERFORM-PARTS-REMOVE-USER-EQ + imports INVARIANT-EXECUTION + + imports TRUSTED-PERFORM-PARTS-REMOVE-USER-BOARDMEMBER-EQ + imports TRUSTED-PERFORM-PARTS-REMOVE-USER-BOARDMEMBER-TOO-FEW-EQ + imports TRUSTED-PERFORM-PARTS-REMOVE-USER-PROPOSER-EQ + imports TRUSTED-PERFORM-PARTS-REMOVE-USER-PROPOSER-NOBODY-LEFT-EQ +//@ trusted +// module TRUSTED-PERFORM-PARTS-REMOVE-USER-EQ +//@ end + imports PERFORM-ACTION-ENDPOINT-INSTRUMENTATION + + claim + splitRemoveUser1(CallerAddress:Address) + ~> call(performActionEndpoint(ActionId:Usize)) + ~> popContext + ~> evaluateReturnValue + ~> clearExternalCallEnv + ~> splitActionSigners(ActionId:Usize, ActionSigners:Map) + ~> runExternalCalls(EC:ExternalCommands) + + invariantStateStack( + NumUsers:Usize, + UserIdToAddress:Map, + (CallerAddress |-> CallerId:Usize _AddressToUserId:Map) #as AddressToUserId:Map, + NumBoardMembers:Usize, + NumProposers:Usize, + (CallerId |-> CallerRole:UserRole _UserIdToRole:Map) #as UserIdToRole:Map, + u(Quorum:Int), + ActionLastIndex0:Usize, + (ActionId |-> RemoveUser(CallerAddress:Address) _ActionData:Map) #as ActionData:Map, + ActionSigners:Map, + CallerAddress:Address, + stack( + invariantMultisigState( + NumUsers, + UserIdToAddress, + AddressToUserId, + NumBoardMembers, + NumProposers, + UserIdToRole, + u(Quorum), + ActionLastIndex0, + ActionData, + ActionSigners), + .Map, + PerformedActions, + .stack), + PerformedActions:List) + + => + + runExternalCalls(EC) + invariantState( + ?NumUsers1:Usize, + ?UserIdToAddress1:Map, + ?AddressToUserId1:Map, + ?NumBoardMembers1:Usize, + ?NumProposers1:Usize, + ?UserIdToRole1:Map, + ?Quorum1:Usize, + ?ActionLastIndex1:Usize, + ?ActionData1:Map, + ?ActionSigners1:Map, + ?_PerformedActions:List):StateCell + + requires true + andBool invariant( + NumUsers, + UserIdToAddress, + AddressToUserId, + NumBoardMembers, + NumProposers, + UserIdToRole, + u(Quorum), + ActionLastIndex0, + ActionData, + ActionSigners, + expand(expanded)) + andBool (CallerRole ==K BoardMember orBool CallerRole ==K Proposer) + andBool Quorum <=Int countCanSignFunction({ActionSigners[ActionId] orDefault [.]}:>ExpressionList, opaque(UserIdToRole)) + ensures invariant( + ?NumUsers1, + ?UserIdToAddress1, + ?AddressToUserId1, + ?NumBoardMembers1, + ?NumProposers1, + ?UserIdToRole1, + ?Quorum1, + ?ActionLastIndex1, + ?ActionData1, + ?ActionSigners1, + usesExpanded) + //@ proof + //@ trusted + // [trusted] + //@ end +endmodule diff --git a/multisig/protocol-correctness/proof/invariant/proof-perform-parts-remove-user-neq.k b/multisig/protocol-correctness/proof/invariant/proof-perform-parts-remove-user-neq.k new file mode 100644 index 000000000..0a3624a87 --- /dev/null +++ b/multisig/protocol-correctness/proof/invariant/proof-perform-parts-remove-user-neq.k @@ -0,0 +1,111 @@ +//@ proof +require "trusted-perform-parts-remove-user-BoardMember.k" //@ Bazel remove +require "trusted-perform-parts-remove-user-BoardMember-too-few.k" //@ Bazel remove +require "trusted-perform-parts-remove-user-Proposer.k" //@ Bazel remove +require "trusted-perform-parts-remove-user-Proposer-nobody-left.k" //@ Bazel remove + +module PROOF-PERFORM-PARTS-REMOVE-USER-NEQ + imports INVARIANT-EXECUTION + + imports TRUSTED-PERFORM-PARTS-REMOVE-USER-BOARDMEMBER + imports TRUSTED-PERFORM-PARTS-REMOVE-USER-BOARDMEMBER-TOO-FEW + imports TRUSTED-PERFORM-PARTS-REMOVE-USER-PROPOSER + imports TRUSTED-PERFORM-PARTS-REMOVE-USER-PROPOSER-NOBODY-LEFT +//@ trusted +// module TRUSTED-PERFORM-PARTS-REMOVE-USER-NEQ +//@ end + imports PERFORM-ACTION-ENDPOINT-INSTRUMENTATION + + claim + splitRemoveUser3(UserAddress:Address) + ~> call(performActionEndpoint(ActionId:Usize)) + ~> popContext + ~> evaluateReturnValue + ~> clearExternalCallEnv + ~> splitActionSigners(ActionId:Usize, ActionSigners:Map) + ~> runExternalCalls(EC:ExternalCommands) + + invariantStateStack( + NumUsers:Usize, + UserIdToAddress:Map, + (CallerAddress |-> CallerId:Usize + UserAddress |-> u(UserId:Int) + _AddressToUserId:Map + ) #as AddressToUserId:Map, + NumBoardMembers:Usize, + NumProposers:Usize, + (CallerId |-> CallerRole:UserRole + _UserIdToRole:Map + ) #as UserIdToRole:Map, + u(Quorum:Int), + ActionLastIndex0:Usize, + (ActionId |-> RemoveUser(UserAddress:Address) _ActionData:Map) #as ActionData:Map, + ActionSigners:Map, + CallerAddress:Address, + stack( + invariantMultisigState( + NumUsers, + UserIdToAddress, + AddressToUserId, + NumBoardMembers, + NumProposers, + UserIdToRole, + u(Quorum), + ActionLastIndex0, + ActionData, + ActionSigners), + .Map, + PerformedActions, + .stack), + PerformedActions:List) + + => + + runExternalCalls(EC) + invariantState( + ?NumUsers1:Usize, + ?UserIdToAddress1:Map, + ?AddressToUserId1:Map, + ?NumBoardMembers1:Usize, + ?NumProposers1:Usize, + ?UserIdToRole1:Map, + ?Quorum1:Usize, + ?ActionLastIndex1:Usize, + ?ActionData1:Map, + ?ActionSigners1:Map, + ?_PerformedActions:List):StateCell + + requires true + andBool invariant( + NumUsers, + UserIdToAddress, + AddressToUserId, + NumBoardMembers, + NumProposers, + UserIdToRole, + u(Quorum), + ActionLastIndex0, + ActionData, + ActionSigners, + expand(expanded)) + andBool (CallerRole ==K BoardMember orBool CallerRole ==K Proposer) + andBool Quorum <=Int countCanSignFunction({ActionSigners[ActionId] orDefault [.]}:>ExpressionList, opaque(UserIdToRole)) + andBool notBool UserAddress ==K CallerAddress + andBool u(UserId) in_keys(UserIdToRole) + ensures invariant( + ?NumUsers1, + ?UserIdToAddress1, + ?AddressToUserId1, + ?NumBoardMembers1, + ?NumProposers1, + ?UserIdToRole1, + ?Quorum1, + ?ActionLastIndex1, + ?ActionData1, + ?ActionSigners1, + usesExpanded) + //@ proof + //@ trusted + // [trusted] + //@ end +endmodule diff --git a/multisig/protocol-correctness/proof/invariant/proof-perform-parts-remove-user.k b/multisig/protocol-correctness/proof/invariant/proof-perform-parts-remove-user.k new file mode 100644 index 000000000..3f8f944a6 --- /dev/null +++ b/multisig/protocol-correctness/proof/invariant/proof-perform-parts-remove-user.k @@ -0,0 +1,104 @@ +//@ proof +require "trusted-perform-parts-remove-user-eq.k" //@ Bazel remove +require "trusted-perform-parts-remove-user-neq.k" //@ Bazel remove +require "trusted-perform-parts-remove-user-New.k" //@ Bazel remove +require "trusted-perform-parts-remove-user-None.k" //@ Bazel remove + +module PROOF-PERFORM-PARTS-REMOVE-USER + imports INVARIANT-EXECUTION + + imports TRUSTED-PERFORM-PARTS-REMOVE-USER-EQ + imports TRUSTED-PERFORM-PARTS-REMOVE-USER-NEQ + imports TRUSTED-PERFORM-PARTS-REMOVE-USER-NEW + imports TRUSTED-PERFORM-PARTS-REMOVE-USER-NONE +//@ trusted +// module TRUSTED-PERFORM-PARTS-REMOVE-USER +//@ end + imports PERFORM-ACTION-ENDPOINT-INSTRUMENTATION + + claim + splitPerformActionEndpoint4(RemoveUser(_UserAddress:Address) #as Action:Action) + ~> call(performActionEndpoint(ActionId:Usize)) + ~> popContext + ~> evaluateReturnValue + ~> clearExternalCallEnv + ~> splitActionSigners(ActionId:Usize, ActionSigners:Map) + ~> runExternalCalls(EC:ExternalCommands) + + invariantStateStack( + NumUsers:Usize, + UserIdToAddress:Map, + (CallerAddress |-> CallerId:Usize _AddressToUserId:Map) #as AddressToUserId:Map, + NumBoardMembers:Usize, + NumProposers:Usize, + (CallerId |-> CallerRole:UserRole _UserIdToRole:Map) #as UserIdToRole:Map, + u(Quorum:Int), + ActionLastIndex0:Usize, + (ActionId |-> Action _ActionData:Map) #as ActionData:Map, + ActionSigners:Map, + CallerAddress:Address, + stack( + invariantMultisigState( + NumUsers, + UserIdToAddress, + AddressToUserId, + NumBoardMembers, + NumProposers, + UserIdToRole, + u(Quorum), + ActionLastIndex0, + ActionData, + ActionSigners), + .Map, + PerformedActions, + .stack), + PerformedActions:List) + + => + + runExternalCalls(EC) + invariantState( + ?NumUsers1:Usize, + ?UserIdToAddress1:Map, + ?AddressToUserId1:Map, + ?NumBoardMembers1:Usize, + ?NumProposers1:Usize, + ?UserIdToRole1:Map, + ?Quorum1:Usize, + ?ActionLastIndex1:Usize, + ?ActionData1:Map, + ?ActionSigners1:Map, + ?_PerformedActions:List):StateCell + + requires true + andBool invariant( + NumUsers, + UserIdToAddress, + AddressToUserId, + NumBoardMembers, + NumProposers, + UserIdToRole, + u(Quorum), + ActionLastIndex0, + ActionData, + ActionSigners, + expand(expanded)) + andBool (CallerRole ==K BoardMember orBool CallerRole ==K Proposer) + andBool Quorum <=Int countCanSignFunction({ActionSigners[ActionId] orDefault [.]}:>ExpressionList, opaque(UserIdToRole)) + ensures invariant( + ?NumUsers1, + ?UserIdToAddress1, + ?AddressToUserId1, + ?NumBoardMembers1, + ?NumProposers1, + ?UserIdToRole1, + ?Quorum1, + ?ActionLastIndex1, + ?ActionData1, + ?ActionSigners1, + usesExpanded) + //@ proof + //@ trusted + // [trusted] + //@ end +endmodule diff --git a/multisig/protocol-correctness/proof/invariant/proof-perform-parts-sc-call.k b/multisig/protocol-correctness/proof/invariant/proof-perform-parts-sc-call.k new file mode 100644 index 000000000..44166e104 --- /dev/null +++ b/multisig/protocol-correctness/proof/invariant/proof-perform-parts-sc-call.k @@ -0,0 +1,74 @@ +//@ proof +require "../functions/trusted-perform-action-endpoint-sc-call.k" //@ Bazel remove + +module PROOF-PERFORM-PARTS-SC-CALL + imports TRUSTED-PERFORM-ACTION-ENDPOINT-SC-CALL +//@ trusted +// module TRUSTED-PERFORM-PARTS-SC-CALL +//@ end + + imports PERFORM-ACTION-ENDPOINT-INSTRUMENTATION + + claim + sc-call.k ~> call(performActionEndpoint(ActionId:Usize)) ~> K:K + invariantStateFull( + NumUsers:Usize, + UserIdToAddress:Map, + (CallerAddress |-> CallerId:Usize + _AddressToUserId:Map + ) #as AddressToUserId:Map, + NumBoardMembers:Usize, + NumProposers:Usize, + (CallerId |-> Role:UserRole + _UserIdToRole:Map + ) #as UserIdToRole:Map, + u(Quorum:Int), + ActionLastIndex:Usize, + ActionId |-> SCCall( + _To:Address, + _Amount:BigUint, + _Function:BoxedBytes, + _Arguments:ExpressionList) #as Action:Action + ActionData:Map, + ActionSigners:Map, + CallerAddress:Address, + Stack:Stack, + .Map, + PerformedActions:List + ) + + => + + evaluate(void) ~> K:K + invariantStateFull( + NumUsers, + UserIdToAddress, + AddressToUserId, + NumBoardMembers, + NumProposers, + UserIdToRole, + u(Quorum), + ActionLastIndex, + ActionData, + ActionSigners[ActionId <- undef], + CallerAddress, + Stack, + ?_Variables:Map, + ListItem(Action) PerformedActions + ) + + requires true + // perform-from-id + andBool isKResult(Action) + + // perform-fragment + andBool actionSignersInvariant(ActionSigners) + andBool userIdToRoleInvariant(UserIdToRole) + andBool (Role ==K BoardMember orBool Role ==K Proposer) + andBool Quorum <=Int countCanSignFunction({ActionSigners[ActionId] orDefault [.]}:>ExpressionList, opaque(UserIdToRole)) + ensures true + //@ proof + //@ trusted + // [trusted] + //@ end +endmodule diff --git a/multisig/protocol-correctness/proof/invariant/proof-perform-parts-sc-deploy.k b/multisig/protocol-correctness/proof/invariant/proof-perform-parts-sc-deploy.k new file mode 100644 index 000000000..7c8ab2744 --- /dev/null +++ b/multisig/protocol-correctness/proof/invariant/proof-perform-parts-sc-deploy.k @@ -0,0 +1,74 @@ +//@ proof +require "../functions/trusted-perform-action-endpoint-sc-deploy.k" //@ Bazel remove + +module PROOF-PERFORM-PARTS-SC-DEPLOY + imports TRUSTED-PERFORM-ACTION-ENDPOINT-SC-DEPLOY +//@ trusted +// module TRUSTED-PERFORM-PARTS-SC-DEPLOY +//@ end + + imports PERFORM-ACTION-ENDPOINT-INSTRUMENTATION + + claim + sc-deploy.k ~> call(performActionEndpoint(ActionId:Usize)) ~> K:K + invariantStateFull( + NumUsers:Usize, + UserIdToAddress:Map, + (CallerAddress |-> CallerId:Usize + _AddressToUserId:Map + ) #as AddressToUserId:Map, + NumBoardMembers:Usize, + NumProposers:Usize, + (CallerId |-> Role:UserRole + _UserIdToRole:Map + ) #as UserIdToRole:Map, + u(Quorum:Int), + ActionLastIndex:Usize, + ActionId |-> SCDeploy( + _Amount:BigUint, + _Code:BoxedBytes, + _CodeMetadata:CodeMetadata, + _Arguments:ExpressionList) #as Action:Action + ActionData:Map, + ActionSigners:Map, + CallerAddress:Address, + Stack:Stack, + .Map, + PerformedActions:List + ) + + => + + evaluate(void) ~> K:K + invariantStateFull( + NumUsers, + UserIdToAddress, + AddressToUserId, + NumBoardMembers, + NumProposers, + UserIdToRole, + u(Quorum), + ActionLastIndex, + ActionData, + ActionSigners[ActionId <- undef], + CallerAddress, + Stack, + ?_Variables:Map, + ListItem(Action) PerformedActions + ) + + requires true + // perform-from-id + andBool isKResult(Action) + + // perform-fragment + andBool actionSignersInvariant(ActionSigners) + andBool userIdToRoleInvariant(UserIdToRole) + andBool (Role ==K BoardMember orBool Role ==K Proposer) + andBool Quorum <=Int countCanSignFunction({ActionSigners[ActionId] orDefault [.]}:>ExpressionList, opaque(UserIdToRole)) + ensures true + //@ proof + //@ trusted + // [trusted] + //@ end +endmodule diff --git a/multisig/protocol-correctness/proof/invariant/proof-perform-parts-send-egld.k b/multisig/protocol-correctness/proof/invariant/proof-perform-parts-send-egld.k new file mode 100644 index 000000000..433bb0ad7 --- /dev/null +++ b/multisig/protocol-correctness/proof/invariant/proof-perform-parts-send-egld.k @@ -0,0 +1,73 @@ +//@ proof +require "../functions/trusted-perform-action-endpoint-send-egld.k" //@ Bazel remove + +module PROOF-PERFORM-PARTS-SEND-EGLD + imports TRUSTED-PERFORM-ACTION-ENDPOINT-SEND-EGLD +//@ trusted +// module TRUSTED-PERFORM-PARTS-SEND-EGLD +//@ end + + imports PERFORM-ACTION-ENDPOINT-INSTRUMENTATION + + claim + send-egld.k ~> call(performActionEndpoint(ActionId:Usize)) ~> K:K + invariantStateFull( + NumUsers:Usize, + UserIdToAddress:Map, + (CallerAddress |-> CallerId:Usize + _AddressToUserId:Map + ) #as AddressToUserId:Map, + NumBoardMembers:Usize, + NumProposers:Usize, + (CallerId |-> Role:UserRole + _UserIdToRole:Map + ) #as UserIdToRole:Map, + u(Quorum:Int), + ActionLastIndex:Usize, + ActionId |-> SendEgld( + _To:Address, + _Amount:BigUint, + _Data:BoxedBytes) #as Action:Action + ActionData:Map, + ActionSigners:Map, + CallerAddress:Address, + Stack:Stack, + .Map, + PerformedActions:List + ) + + => + + evaluate(void) ~> K:K + invariantStateFull( + NumUsers, + UserIdToAddress, + AddressToUserId, + NumBoardMembers, + NumProposers, + UserIdToRole, + u(Quorum), + ActionLastIndex, + ActionData, + ActionSigners[ActionId <- undef], + CallerAddress, + Stack, + ?_Variables:Map, + ListItem(Action) PerformedActions + ) + + requires true + // perform-from-id + andBool isKResult(Action) + + // perform-fragment + andBool actionSignersInvariant(ActionSigners) + andBool userIdToRoleInvariant(UserIdToRole) + andBool (Role ==K BoardMember orBool Role ==K Proposer) + andBool Quorum <=Int countCanSignFunction({ActionSigners[ActionId] orDefault [.]}:>ExpressionList, opaque(UserIdToRole)) + ensures true + //@ proof + //@ trusted + // [trusted] + //@ end +endmodule diff --git a/multisig/protocol-correctness/proof/invariant/proof-perform-remove-user-1.k b/multisig/protocol-correctness/proof/invariant/proof-perform-remove-user-1.k new file mode 100644 index 000000000..9ebfa1838 --- /dev/null +++ b/multisig/protocol-correctness/proof/invariant/proof-perform-remove-user-1.k @@ -0,0 +1,140 @@ +require "../functions/functions-execute.k" + +require "../functions/trusted-change-user-role-New.k" +require "../functions/trusted-change-user-role-None.k" +require "../functions/trusted-change-user-role-BoardMember.k" +require "../functions/trusted-change-user-role-Proposer.k" + +module TRUSTED-PERFORM-REMOVE-USER-1 + imports INVARIANT-EXECUTION + + claim + + performLhs( + RemoveUser(UserAddress:Address) #as Action:Action, + K:K, + NumUsers:Usize, + UserIdToAddress:Map, + ( + UserAddress |-> UserId:Usize + _AddressToUserId:Map + ) #as AddressToUserId:Map, + u(NumBoardMembers:Int), + u(NumProposers:Int), + (UserId |-> BoardMember UserIdToRoleFinal:Map) #as UserIdToRole:Map, + u(Quorum:Int), + ActionState:ActionStateCell, + Stack:Stack, + CallerAddress:Address, + PerformedActions:List) + + => + + performRhs( + evaluate(void), + K, + u(?NumUsersFinal:Int), + ?UserIdToAddressFinal:Map, + ?AddressToUserIdFinal:Map, + u(?NumBoardMembersFinal:Int), + u(?NumProposersFinal:Int), + UserIdToRoleFinal, + u(Quorum), + ActionState, + ?_Variables:Map, + Stack:Stack, + CallerAddress, + ListItem(Action) PerformedActions:List) + + requires performRequiresHandling( + Action, + NumUsers, + UserIdToAddress, + AddressToUserId, + u(NumBoardMembers), + u(NumProposers), + UserIdToRole, + u(Quorum), + usesExpanded) + andBool Quorum <=Int NumBoardMembers -Int 1 + andBool (NumBoardMembers -Int 1 +Int NumProposers >Int 0) + ensures performEnsuresHandling( + u(?NumUsersFinal), + ?UserIdToAddressFinal, + ?AddressToUserIdFinal, + u(?NumBoardMembersFinal), + u(?NumProposersFinal), + UserIdToRoleFinal, + u(Quorum), + expanded) + [trusted] + +endmodule + +module PROOF-PERFORM-REMOVE-USER-1 + imports INVARIANT-EXECUTION + + imports TRUSTED-CHANGE-USER-ROLE-NEW + imports TRUSTED-CHANGE-USER-ROLE-NONE + imports TRUSTED-CHANGE-USER-ROLE-BOARDMEMBER + imports TRUSTED-CHANGE-USER-ROLE-PROPOSER + + claim + + performLhs( + RemoveUser(UserAddress:Address) #as Action:Action, + K:K, + NumUsers:Usize, + UserIdToAddress:Map, + ( + UserAddress |-> UserId:Usize + _AddressToUserId:Map + ) #as AddressToUserId:Map, + u(NumBoardMembers:Int), + u(NumProposers:Int), + (UserId |-> BoardMember UserIdToRoleFinal:Map) #as UserIdToRole:Map, + u(Quorum:Int), + ActionState:ActionStateCell, + Stack:Stack, + CallerAddress:Address, + PerformedActions:List) + + => + + performRhs( + evaluate(void), + K, + u(?NumUsersFinal:Int), + ?UserIdToAddressFinal:Map, + ?AddressToUserIdFinal:Map, + u(?NumBoardMembersFinal:Int), + u(?NumProposersFinal:Int), + UserIdToRoleFinal, + u(Quorum), + ActionState, + ?_Variables:Map, + Stack:Stack, + CallerAddress, + ListItem(Action) PerformedActions:List) + + requires performRequires( + Action, + NumUsers, + UserIdToAddress, + AddressToUserId, + u(NumBoardMembers), + u(NumProposers), + UserIdToRole, + u(Quorum)) + andBool Quorum <=Int NumBoardMembers -Int 1 + andBool (NumBoardMembers -Int 1 +Int NumProposers >Int 0) + ensures performEnsures( + u(?NumUsersFinal), + ?UserIdToAddressFinal, + ?AddressToUserIdFinal, + u(?NumBoardMembersFinal), + u(?NumProposersFinal), + UserIdToRoleFinal, + u(Quorum)) + +endmodule diff --git a/multisig/protocol-correctness/proof/invariant/proof-perform-remove-user-10.k b/multisig/protocol-correctness/proof/invariant/proof-perform-remove-user-10.k new file mode 100644 index 000000000..c79f2f51f --- /dev/null +++ b/multisig/protocol-correctness/proof/invariant/proof-perform-remove-user-10.k @@ -0,0 +1,130 @@ +require "../functions/functions-execute.k" + +require "../functions/trusted-change-user-role-New.k" +require "../functions/trusted-change-user-role-None.k" +require "../functions/trusted-change-user-role-BoardMember.k" +require "../functions/trusted-change-user-role-Proposer.k" + +module TRUSTED-PERFORM-REMOVE-USER-10 + imports INVARIANT-EXECUTION + + claim + + performLhs( + RemoveUser(UserAddress:Address) #as Action:Action, + K:K, + NumUsers:Usize, + UserIdToAddress:Map, + AddressToUserId:Map, + NumBoardMembers:Usize, + NumProposers:Usize, + UserIdToRole:Map, + Quorum:Usize, + ActionState:ActionStateCell, + Stack:Stack, + CallerAddress:Address, + PerformedActions:List) + + => + + performRhs( + evaluate(void), + K, + NumUsers:Usize, + UserIdToAddress:Map, + AddressToUserId:Map, + NumBoardMembers:Usize, + NumProposers:Usize, + UserIdToRole:Map, + Quorum, + ActionState, + ?_Variables:Map, + Stack:Stack, + CallerAddress, + ListItem(Action) PerformedActions:List) + + requires performRequiresHandling( + Action, + NumUsers, + UserIdToAddress, + AddressToUserId, + NumBoardMembers, + NumProposers, + UserIdToRole, + Quorum, + usesExpanded) + andBool notBool (UserAddress in_keys(AddressToUserId)) + ensures performEnsuresHandling( + NumUsers, + UserIdToAddress, + AddressToUserId, + NumBoardMembers, + NumProposers, + UserIdToRole, + Quorum, + expanded) + [trusted] +endmodule + +module PROOF-PERFORM-REMOVE-USER-10 + imports INVARIANT-EXECUTION + + imports TRUSTED-CHANGE-USER-ROLE-NEW + imports TRUSTED-CHANGE-USER-ROLE-NONE + imports TRUSTED-CHANGE-USER-ROLE-BOARDMEMBER + imports TRUSTED-CHANGE-USER-ROLE-PROPOSER + + claim + + performLhs( + RemoveUser(UserAddress:Address) #as Action:Action, + K:K, + NumUsers:Usize, + UserIdToAddress:Map, + AddressToUserId:Map, + NumBoardMembers:Usize, + NumProposers:Usize, + UserIdToRole:Map, + Quorum:Usize, + ActionState:ActionStateCell, + Stack:Stack, + CallerAddress:Address, + PerformedActions:List) + + => + + performRhs( + evaluate(void), + K, + ?NumUsers:Usize, + ?UserIdToAddress:Map, + ?AddressToUserId:Map, + NumBoardMembers:Usize, + NumProposers:Usize, + UserIdToRole:Map, + Quorum, + ActionState, + ?_Variables:Map, + Stack:Stack, + CallerAddress, + ListItem(Action) PerformedActions:List) + + requires performRequires( + Action, + NumUsers, + UserIdToAddress, + AddressToUserId, + NumBoardMembers, + NumProposers, + UserIdToRole, + Quorum) + andBool notBool (UserAddress in_keys(AddressToUserId)) + ensures performEnsures( + ?NumUsers, + ?UserIdToAddress, + ?AddressToUserId, + NumBoardMembers, + NumProposers, + UserIdToRole, + Quorum) +endmodule diff --git a/multisig/protocol-correctness/proof/invariant/proof-perform-remove-user-3.k b/multisig/protocol-correctness/proof/invariant/proof-perform-remove-user-3.k new file mode 100644 index 000000000..55eff87de --- /dev/null +++ b/multisig/protocol-correctness/proof/invariant/proof-perform-remove-user-3.k @@ -0,0 +1,115 @@ +module TRUSTED-PERFORM-REMOVE-USER-3 + imports INVARIANT-EXECUTION + + claim + + performLhs( + RemoveUser(UserAddress:Address) #as Action:Action, + K:K, + NumUsers:Usize, + UserIdToAddress:Map, + ( + UserAddress |-> UserId:Usize + _AddressToUserId:Map + ) #as AddressToUserId:Map, + u(NumBoardMembers:Int), + u(NumProposers:Int), + (UserId |-> BoardMember _UserIdToRole:Map) #as UserIdToRole:Map, + u(Quorum:Int), + ActionState:ActionStateCell, + Stack:Stack, + CallerAddress:Address, + _PerformedActions:List) + + => + + performRhs( + error, + K, + ?_NumUsersFinal, + ?_UserIdToAddressFinal, + ?_AddressToUserIdFinal, + ?_NumBoardMembersFinal, + ?_NumProposersFinal, + ?_UserIdToRoleFinal, + u(Quorum), + ActionState, + ?_Variables:Map, + Stack:Stack, + CallerAddress, + ?_PerformedActions:List) + + requires performRequiresHandling( + Action, + NumUsers, + UserIdToAddress, + AddressToUserId, + u(NumBoardMembers), + u(NumProposers), + UserIdToRole, + u(Quorum), + usesExpanded) + andBool notBool + ((Quorum <=Int NumBoardMembers -Int 1) + andBool (NumBoardMembers -Int 1 +Int NumProposers >Int 0) + ) + [trusted] + +endmodule + +module PROOF-PERFORM-REMOVE-USER-3 + imports INVARIANT-EXECUTION + + claim + + performLhs( + RemoveUser(UserAddress:Address) #as Action:Action, + K:K, + NumUsers:Usize, + UserIdToAddress:Map, + ( + UserAddress |-> UserId:Usize + _AddressToUserId:Map + ) #as AddressToUserId:Map, + u(NumBoardMembers:Int), + u(NumProposers:Int), + (UserId |-> BoardMember _UserIdToRole:Map) #as UserIdToRole:Map, + u(Quorum:Int), + ActionState:ActionStateCell, + Stack:Stack, + CallerAddress:Address, + _PerformedActions:List) + + => + + performRhs( + error, + K, + ?_NumUsersFinal, + ?_UserIdToAddressFinal, + ?_AddressToUserIdFinal, + ?_NumBoardMembersFinal, + ?_NumProposersFinal, + ?_UserIdToRoleFinal, + u(Quorum), + ActionState, + ?_Variables:Map, + Stack:Stack, + CallerAddress, + ?_PerformedActions:List) + + requires performRequires( + Action, + NumUsers, + UserIdToAddress, + AddressToUserId, + u(NumBoardMembers), + u(NumProposers), + UserIdToRole, + u(Quorum)) + andBool notBool + ((Quorum <=Int NumBoardMembers -Int 1) + andBool (NumBoardMembers -Int 1 +Int NumProposers >Int 0) + ) + +endmodule diff --git a/multisig/protocol-correctness/proof/invariant/proof-perform-remove-user-5.k b/multisig/protocol-correctness/proof/invariant/proof-perform-remove-user-5.k new file mode 100644 index 000000000..fe7c3522b --- /dev/null +++ b/multisig/protocol-correctness/proof/invariant/proof-perform-remove-user-5.k @@ -0,0 +1,144 @@ +require "../functions/functions-execute.k" + +require "../functions/trusted-change-user-role-New.k" +require "../functions/trusted-change-user-role-None.k" +require "../functions/trusted-change-user-role-BoardMember.k" +require "../functions/trusted-change-user-role-Proposer.k" + +module TRUSTED-PERFORM-REMOVE-USER-5 + imports INVARIANT-EXECUTION + + claim + + performLhs( + RemoveUser(UserAddress:Address) #as Action:Action, + K:K, + NumUsers:Usize, + UserIdToAddress:Map, + ( + UserAddress |-> UserId:Usize + _AddressToUserId:Map + ) #as AddressToUserId:Map, + u(NumBoardMembers:Int), + u(NumProposers:Int), + (UserId |-> UserRole:KItem UserIdToRoleFinal:Map) #as UserIdToRole:Map, + u(Quorum:Int), + ActionState:ActionStateCell, + Stack:Stack, + CallerAddress:Address, + PerformedActions:List) + + => + + performRhs( + evaluate(void), + K, + u(?NumUsersFinal:Int), + ?UserIdToAddressFinal:Map, + ?AddressToUserIdFinal:Map, + u(?NumBoardMembersFinal:Int), + u(?NumProposersFinal:Int), + UserIdToRoleFinal, + u(Quorum:Int), + ActionState, + ?_Variables:Map, + Stack:Stack, + CallerAddress, + ListItem(Action) PerformedActions:List) + + requires performRequiresHandling( + Action, + NumUsers, + UserIdToAddress, + AddressToUserId, + u(NumBoardMembers), + u(NumProposers), + UserIdToRole, + u(Quorum), + usesExpanded) + andBool notBool (UserRole ==K BoardMember) + andBool Quorum <=Int NumBoardMembers + andBool (NumBoardMembers +Int (NumProposers -Int 1) >Int 0) + ensures performEnsuresHandling( + u(?NumUsersFinal), + ?UserIdToAddressFinal, + ?AddressToUserIdFinal, + u(?NumBoardMembersFinal), + u(?NumProposersFinal), + UserIdToRoleFinal, + u(Quorum), + expanded) + [trusted] + +endmodule + +module PROOF-PERFORM-REMOVE-USER-5 + imports INVARIANT-EXECUTION + + imports TRUSTED-CHANGE-USER-ROLE-NEW + imports TRUSTED-CHANGE-USER-ROLE-NONE + imports TRUSTED-CHANGE-USER-ROLE-BOARDMEMBER + imports TRUSTED-CHANGE-USER-ROLE-PROPOSER + + claim + + performLhs( + RemoveUser(UserAddress:Address) #as Action:Action, + K:K, + NumUsers:Usize, + UserIdToAddress:Map, + ( + UserAddress |-> UserId:Usize + CallerAddress |-> _:Usize + _AddressToUserId:Map + ) #as AddressToUserId:Map, + u(NumBoardMembers:Int), + u(NumProposers:Int), + (UserId |-> UserRole:KItem UserIdToRoleFinal:Map) #as UserIdToRole:Map, + u(Quorum:Int), + ActionState:ActionStateCell, + Stack:Stack, + CallerAddress:Address, + PerformedActions:List) + + => + + performRhs( + evaluate(void), + K, + u(?NumUsersFinal:Int), + ?UserIdToAddressFinal:Map, + ?AddressToUserIdFinal:Map, + u(?NumBoardMembersFinal:Int), + u(?NumProposersFinal:Int), + UserIdToRoleFinal, + u(Quorum:Int), + ActionState, + ?_Variables:Map, + Stack:Stack, + CallerAddress, + ListItem(Action) PerformedActions:List) + + requires performRequires( + Action, + NumUsers, + UserIdToAddress, + AddressToUserId, + u(NumBoardMembers), + u(NumProposers), + UserIdToRole, + u(Quorum)) + andBool notBool (UserAddress ==K CallerAddress) + andBool notBool (UserRole ==K BoardMember) + andBool Quorum <=Int NumBoardMembers + andBool (NumBoardMembers +Int (NumProposers -Int 1) >Int 0) + ensures performEnsures( + u(?NumUsersFinal), + ?UserIdToAddressFinal, + ?AddressToUserIdFinal, + u(?NumBoardMembersFinal), + u(?NumProposersFinal), + UserIdToRoleFinal, + u(Quorum)) + +endmodule diff --git a/multisig/protocol-correctness/proof/invariant/proof-perform-remove-user-7.k b/multisig/protocol-correctness/proof/invariant/proof-perform-remove-user-7.k new file mode 100644 index 000000000..be42091aa --- /dev/null +++ b/multisig/protocol-correctness/proof/invariant/proof-perform-remove-user-7.k @@ -0,0 +1,113 @@ +module TRUSTED-PERFORM-REMOVE-USER-7 + imports INVARIANT-EXECUTION + + claim + + performLhs( + RemoveUser(UserAddress:Address) #as Action:Action, + K:K, + NumUsers:Usize, + UserIdToAddress:Map, + ( + UserAddress |-> UserId:Usize + _AddressToUserId:Map + ) #as AddressToUserId:Map, + u(NumBoardMembers:Int), + u(NumProposers:Int), + (UserId |-> UserRole:KItem _UserIdToRole:Map) #as UserIdToRole:Map, + u(Quorum:Int), + ActionState:ActionStateCell, + Stack:Stack, + CallerAddress:Address, + _PerformedActions:List) + + => + + performRhs( + error, + K, + ?_NumUsers, + ?_UserIdToAddress, + ?_AddressToUserId, + ?_NumBoardMembers, + ?_NumProposers, + ?_UserIdToRole, + u(Quorum:Int), + ActionState, + ?_Variables:Map, + Stack:Stack, + CallerAddress, + ?_PerformedActions:List) + + requires performRequiresHandling( + Action, + NumUsers, + UserIdToAddress, + AddressToUserId, + u(NumBoardMembers), + u(NumProposers), + UserIdToRole, + u(Quorum), + usesExpanded) + andBool notBool (UserRole ==K BoardMember) + andBool notBool ( + Quorum <=Int NumBoardMembers + andBool (NumBoardMembers +Int (NumProposers -Int 1) >Int 0)) + [trusted] +endmodule + +module PROOF-PERFORM-REMOVE-USER-7 + imports INVARIANT-EXECUTION + + claim + + performLhs( + RemoveUser(UserAddress:Address) #as Action:Action, + K:K, + NumUsers:Usize, + UserIdToAddress:Map, + ( + UserAddress |-> UserId:Usize + _AddressToUserId:Map + ) #as AddressToUserId:Map, + u(NumBoardMembers:Int), + u(NumProposers:Int), + (UserId |-> UserRole:KItem _UserIdToRole:Map) #as UserIdToRole:Map, + u(Quorum:Int), + ActionState:ActionStateCell, + Stack:Stack, + CallerAddress:Address, + _PerformedActions:List) + + => + + performRhs( + error, + K, + ?_NumUsers, + ?_UserIdToAddress, + ?_AddressToUserId, + ?_NumBoardMembers, + ?_NumProposers, + ?_UserIdToRole, + u(Quorum:Int), + ActionState, + ?_Variables:Map, + Stack:Stack, + CallerAddress, + ?_PerformedActions:List) + + requires performRequires( + Action, + NumUsers, + UserIdToAddress, + AddressToUserId, + u(NumBoardMembers), + u(NumProposers), + UserIdToRole, + u(Quorum)) + andBool notBool (UserRole ==K BoardMember) + andBool notBool ( + Quorum <=Int NumBoardMembers + andBool (NumBoardMembers +Int (NumProposers -Int 1) >Int 0)) +endmodule diff --git a/multisig/protocol-correctness/proof/invariant/proof-perform-remove-user-9.k b/multisig/protocol-correctness/proof/invariant/proof-perform-remove-user-9.k new file mode 100644 index 000000000..7e3148843 --- /dev/null +++ b/multisig/protocol-correctness/proof/invariant/proof-perform-remove-user-9.k @@ -0,0 +1,134 @@ +require "../functions/functions-execute.k" + +require "../functions/trusted-change-user-role-New.k" +require "../functions/trusted-change-user-role-None.k" +require "../functions/trusted-change-user-role-BoardMember.k" +require "../functions/trusted-change-user-role-Proposer.k" + +module TRUSTED-PERFORM-REMOVE-USER-9 + imports INVARIANT-EXECUTION + + claim + + performLhs( + RemoveUser(UserAddress:Address) #as Action:Action, + K:K, + NumUsers:Usize, + UserIdToAddress:Map, + AddressToUserId:Map, + NumBoardMembers:Usize, + NumProposers:Usize, + UserIdToRole:Map, + Quorum:Usize, + ActionState:ActionStateCell, + Stack:Stack, + CallerAddress:Address, + PerformedActions:List) + + => + + performRhs( + evaluate(void), + K, + u(?NumUsersFinal:Int), + ?UserIdToAddressFinal:Map, + ?AddressToUserIdFinal:Map, + u(?NumBoardMembersFinal:Int), + u(?NumProposersFinal:Int), + ?UserIdToRoleFinal:Map, + Quorum, + ActionState, + ?_Variables:Map, + Stack:Stack, + CallerAddress, + ListItem(Action) PerformedActions:List) + + requires performRequiresHandling( + Action, + NumUsers, + UserIdToAddress, + AddressToUserId, + NumBoardMembers, + NumProposers, + UserIdToRole, + Quorum, + usesExpanded) + andBool notBool (UserId in_keys(UserIdToRole)) + andBool UserAddress in_keys(AddressToUserId) + andBool AddressToUserId ==K (UserAddress |-> UserId:KItem _AddressToUserId:Map) + ensures performEnsuresHandling( + u(?NumUsersFinal), + ?UserIdToAddressFinal, + ?AddressToUserIdFinal, + u(?NumBoardMembersFinal), + u(?NumProposersFinal), + ?UserIdToRoleFinal, + Quorum, + usesExpanded) + [trusted] +endmodule + +module PROOF-PERFORM-REMOVE-USER-9 + imports INVARIANT-EXECUTION + + imports TRUSTED-CHANGE-USER-ROLE-NEW + imports TRUSTED-CHANGE-USER-ROLE-NONE + imports TRUSTED-CHANGE-USER-ROLE-BOARDMEMBER + imports TRUSTED-CHANGE-USER-ROLE-PROPOSER + + claim + + performLhs( + RemoveUser(UserAddress:Address) #as Action:Action, + K:K, + NumUsers:Usize, + UserIdToAddress:Map, + AddressToUserId:Map, + NumBoardMembers:Usize, + NumProposers:Usize, + UserIdToRole:Map, + Quorum:Usize, + ActionState:ActionStateCell, + Stack:Stack, + CallerAddress:Address, + PerformedActions:List) + + => + + performRhs( + evaluate(void), + K, + u(?NumUsersFinal:Int), + ?UserIdToAddressFinal:Map, + ?AddressToUserIdFinal:Map, + u(?NumBoardMembersFinal:Int), + u(?NumProposersFinal:Int), + ?UserIdToRoleFinal:Map, + Quorum, + ActionState, + ?_Variables:Map, + Stack:Stack, + CallerAddress, + ListItem(Action) PerformedActions:List) + + requires performRequires( + Action, + NumUsers, + UserIdToAddress, + AddressToUserId, + NumBoardMembers, + NumProposers, + UserIdToRole, + Quorum) + andBool notBool (UserId in_keys(UserIdToRole)) + andBool UserAddress in_keys(AddressToUserId) + andBool AddressToUserId ==K (UserAddress |-> UserId:KItem _AddressToUserId:Map) + ensures performEnsures( + u(?NumUsersFinal), + ?UserIdToAddressFinal, + ?AddressToUserIdFinal, + u(?NumBoardMembersFinal), + u(?NumProposersFinal), + ?UserIdToRoleFinal, + Quorum) +endmodule diff --git a/multisig/protocol-correctness/proof/invariant/proof-perform-s-c-call.k b/multisig/protocol-correctness/proof/invariant/proof-perform-s-c-call.k new file mode 100644 index 000000000..202ede1e1 --- /dev/null +++ b/multisig/protocol-correctness/proof/invariant/proof-perform-s-c-call.k @@ -0,0 +1,106 @@ +module TRUSTED-PERFORM-S-C-CALL + imports INVARIANT-EXECUTION + + claim + + performLhs( + SCCall( + _To:Address, + _Amount:BigUint, + _Function:BoxedBytes, + _Arguments:ExpressionList) #as Action:Action, + K:K, + NumUsers:Usize, + UserIdToAddress:Map, + AddressToUserId:Map, + NumBoardMembers:Usize, + NumProposers:Usize, + UserIdToRole:Map, + Quorum:Usize, + ActionState:ActionStateCell, + Stack:Stack, + CallerAddress:Address, + PerformedActions:List) + + => + + performRhs( + evaluate(void), + K, + NumUsers, + UserIdToAddress, + AddressToUserId, + NumBoardMembers, + NumProposers, + UserIdToRole, + Quorum, + ActionState, + ?_Variables:Map, + Stack:Stack, + CallerAddress, + ListItem(Action) PerformedActions:List) + + requires performRequires( + Action, + NumUsers, + UserIdToAddress, + AddressToUserId, + NumBoardMembers, + NumProposers, + UserIdToRole, + Quorum) + [trusted] +endmodule + +module PROOF-PERFORM-S-C-CALL + imports INVARIANT-EXECUTION + + claim + + performLhs( + SCCall( + _To:Address, + _Amount:BigUint, + _Function:BoxedBytes, + _Arguments:ExpressionList) #as Action:Action, + K:K, + NumUsers:Usize, + UserIdToAddress:Map, + AddressToUserId:Map, + NumBoardMembers:Usize, + NumProposers:Usize, + UserIdToRole:Map, + Quorum:Usize, + ActionState:ActionStateCell, + Stack:Stack, + CallerAddress:Address, + PerformedActions:List) + + => + + performRhs( + evaluate(void), + K, + NumUsers, + UserIdToAddress, + AddressToUserId, + NumBoardMembers, + NumProposers, + UserIdToRole, + Quorum, + ActionState, + ?_Variables:Map, + Stack:Stack, + CallerAddress, + ListItem(Action) PerformedActions:List) + + requires performRequires( + Action, + NumUsers, + UserIdToAddress, + AddressToUserId, + NumBoardMembers, + NumProposers, + UserIdToRole, + Quorum) +endmodule diff --git a/multisig/protocol-correctness/proof/invariant/proof-perform-s-c-deploy.k b/multisig/protocol-correctness/proof/invariant/proof-perform-s-c-deploy.k new file mode 100644 index 000000000..e4cbcb7b7 --- /dev/null +++ b/multisig/protocol-correctness/proof/invariant/proof-perform-s-c-deploy.k @@ -0,0 +1,106 @@ +module TRUSTED-PERFORM-S-C-DEPLOY + imports INVARIANT-EXECUTION + + claim + + performLhs( + SCDeploy( + _Amount:BigUint, + _Code:BoxedBytes, + _CodeMetadata:CodeMetadata, + _Arguments:ExpressionList) #as Action:Action, + K:K, + NumUsers:Usize, + UserIdToAddress:Map, + AddressToUserId:Map, + NumBoardMembers:Usize, + NumProposers:Usize, + UserIdToRole:Map, + Quorum:Usize, + ActionState:ActionStateCell, + Stack:Stack, + CallerAddress:Address, + PerformedActions:List) + + => + + performRhs( + evaluate(void), + K, + NumUsers, + UserIdToAddress, + AddressToUserId, + NumBoardMembers, + NumProposers, + UserIdToRole, + Quorum, + ActionState, + ?_Variables:Map, + Stack:Stack, + CallerAddress, + ListItem(Action) PerformedActions:List) + + requires performRequires( + Action, + NumUsers, + UserIdToAddress, + AddressToUserId, + NumBoardMembers, + NumProposers, + UserIdToRole, + Quorum) + [trusted] +endmodule + +module PROOF-PERFORM-S-C-DEPLOY + imports INVARIANT-EXECUTION + + claim + + performLhs( + SCDeploy( + _Amount:BigUint, + _Code:BoxedBytes, + _CodeMetadata:CodeMetadata, + _Arguments:ExpressionList) #as Action:Action, + K:K, + NumUsers:Usize, + UserIdToAddress:Map, + AddressToUserId:Map, + NumBoardMembers:Usize, + NumProposers:Usize, + UserIdToRole:Map, + Quorum:Usize, + ActionState:ActionStateCell, + Stack:Stack, + CallerAddress:Address, + PerformedActions:List) + + => + + performRhs( + evaluate(void), + K, + NumUsers, + UserIdToAddress, + AddressToUserId, + NumBoardMembers, + NumProposers, + UserIdToRole, + Quorum, + ActionState, + ?_Variables:Map, + Stack:Stack, + CallerAddress, + ListItem(Action) PerformedActions:List) + + requires performRequires( + Action, + NumUsers, + UserIdToAddress, + AddressToUserId, + NumBoardMembers, + NumProposers, + UserIdToRole, + Quorum) +endmodule diff --git a/multisig/protocol-correctness/proof/invariant/proof-perform-send-egld.k b/multisig/protocol-correctness/proof/invariant/proof-perform-send-egld.k new file mode 100644 index 000000000..d35fb710b --- /dev/null +++ b/multisig/protocol-correctness/proof/invariant/proof-perform-send-egld.k @@ -0,0 +1,98 @@ +module TRUSTED-PERFORM-SEND-EGLD + imports INVARIANT-EXECUTION + + claim + + performLhs( + SendEgld(_To:Address, _Amount:BigUint, _Data:BoxedBytes) #as Action:Action, + K:K, + NumUsers:Usize, + UserIdToAddress:Map, + AddressToUserId:Map, + NumBoardMembers:Usize, + NumProposers:Usize, + UserIdToRole:Map, + Quorum:Usize, + ActionState:ActionStateCell, + Stack:Stack, + CallerAddress:Address, + PerformedActions:List) + + => + + performRhs( + evaluate(void), + K, + NumUsers, + UserIdToAddress, + AddressToUserId, + NumBoardMembers, + NumProposers, + UserIdToRole, + Quorum, + ActionState, + ?_Variables:Map, + Stack:Stack, + CallerAddress, + ListItem(Action) PerformedActions:List) + + requires performRequires( + Action, + NumUsers, + UserIdToAddress, + AddressToUserId, + NumBoardMembers, + NumProposers, + UserIdToRole, + Quorum) + [trusted] +endmodule + +module PROOF-PERFORM-SEND-EGLD + imports INVARIANT-EXECUTION + + claim + + performLhs( + SendEgld(_To:Address, _Amount:BigUint, _Data:BoxedBytes) #as Action:Action, + K:K, + NumUsers:Usize, + UserIdToAddress:Map, + AddressToUserId:Map, + NumBoardMembers:Usize, + NumProposers:Usize, + UserIdToRole:Map, + Quorum:Usize, + ActionState:ActionStateCell, + Stack:Stack, + CallerAddress:Address, + PerformedActions:List) + + => + + performRhs( + evaluate(void), + K, + NumUsers, + UserIdToAddress, + AddressToUserId, + NumBoardMembers, + NumProposers, + UserIdToRole, + Quorum, + ActionState, + ?_Variables:Map, + Stack:Stack, + CallerAddress, + ListItem(Action) PerformedActions:List) + + requires performRequires( + Action, + NumUsers, + UserIdToAddress, + AddressToUserId, + NumBoardMembers, + NumProposers, + UserIdToRole, + Quorum) +endmodule diff --git a/multisig/protocol-correctness/proof/invariant/proof-propose-add-board-member.k b/multisig/protocol-correctness/proof/invariant/proof-propose-add-board-member.k new file mode 100644 index 000000000..7bd8c4d17 --- /dev/null +++ b/multisig/protocol-correctness/proof/invariant/proof-propose-add-board-member.k @@ -0,0 +1,77 @@ +require "../functions/functions-execute.k" //@ Bazel remove + +require "../functions/trusted-propose-action-BoardMember.k" //@ Bazel remove +require "../functions/trusted-propose-action-Proposer.k" //@ Bazel remove +require "../functions/trusted-propose-action-error-no-user.k" //@ Bazel remove +require "../functions/trusted-propose-action-error-no-role.k" //@ Bazel remove + +module PROOF-PROPOSE-ADD-BOARD-MEMBER + imports INVARIANT-EXECUTION + imports PSEUDOCODE + + imports TRUSTED-PROPOSE-ACTION-ERROR-NO-ROLE + imports TRUSTED-PROPOSE-ACTION-ERROR-NO-USER + imports TRUSTED-PROPOSE-ACTION-BOARDMEMBER + imports TRUSTED-PROPOSE-ACTION-PROPOSER + + claim + runExternalCalls( + ( from _:Address run proposeAddBoardMember(_Member:Address); + EC:ExternalCommands + ) + ) + + invariantState( + NumUsers:Usize, + UserIdToAddress:Map, + AddressToUserId:Map, + NumBoardMembers:Usize, + NumProposers:Usize, + UserRoles:Map, + Quorum:Usize, + ActionLastIndex0:Usize, + ActionData0:Map, + ActionSigners0:Map, + PerformedActions:List) + + => + + runExternalCalls(EC) + invariantState( + NumUsers:Usize, + UserIdToAddress:Map, + AddressToUserId:Map, + NumBoardMembers:Usize, + NumProposers:Usize, + UserRoles:Map, + Quorum:Usize, + ?ActionLastIndex1:Usize, + ?ActionData1:Map, + ?ActionSigners1:Map, + PerformedActions:List):StateCell + + requires invariant( + NumUsers:Usize, + UserIdToAddress:Map, + AddressToUserId:Map, + NumBoardMembers:Usize, + NumProposers:Usize, + UserRoles:Map, + Quorum:Usize, + ActionLastIndex0:Usize, + ActionData0:Map, + ActionSigners0:Map, + expand(expanded)) + ensures invariant( + NumUsers:Usize, + UserIdToAddress:Map, + AddressToUserId:Map, + NumBoardMembers:Usize, + NumProposers:Usize, + UserRoles:Map, + Quorum:Usize, + ?ActionLastIndex1:Usize, + ?ActionData1:Map, + ?ActionSigners1:Map, + usesExpanded) +endmodule diff --git a/multisig/protocol-correctness/proof/invariant/proof-propose-add-proposer.k b/multisig/protocol-correctness/proof/invariant/proof-propose-add-proposer.k new file mode 100644 index 000000000..ce28677e2 --- /dev/null +++ b/multisig/protocol-correctness/proof/invariant/proof-propose-add-proposer.k @@ -0,0 +1,77 @@ +require "../functions/functions-execute.k" + +require "../functions/trusted-propose-action-BoardMember.k" +require "../functions/trusted-propose-action-Proposer.k" +require "../functions/trusted-propose-action-error-no-user.k" +require "../functions/trusted-propose-action-error-no-role.k" + +module PROOF-PROPOSE-ADD-PROPOSER + imports INVARIANT-EXECUTION + imports PSEUDOCODE + + imports TRUSTED-PROPOSE-ACTION-ERROR-NO-ROLE + imports TRUSTED-PROPOSE-ACTION-ERROR-NO-USER + imports TRUSTED-PROPOSE-ACTION-BOARDMEMBER + imports TRUSTED-PROPOSE-ACTION-PROPOSER + + claim + runExternalCalls( + ( from _:Address run proposeAddProposer(_Member:Address); + EC:ExternalCommands + ) + ) + + invariantState( + NumUsers:Usize, + UserIdToAddress:Map, + AddressToUserId:Map, + NumBoardMembers:Usize, + NumProposers:Usize, + UserRoles:Map, + Quorum:Usize, + ActionLastIndex0:Usize, + ActionData0:Map, + ActionSigners0:Map, + PerformedActions:List) + + => + + runExternalCalls(EC) + invariantState( + NumUsers:Usize, + UserIdToAddress:Map, + AddressToUserId:Map, + NumBoardMembers:Usize, + NumProposers:Usize, + UserRoles:Map, + Quorum:Usize, + ?ActionLastIndex1:Usize, + ?ActionData1:Map, + ?ActionSigners1:Map, + PerformedActions:List):StateCell + + requires invariant( + NumUsers:Usize, + UserIdToAddress:Map, + AddressToUserId:Map, + NumBoardMembers:Usize, + NumProposers:Usize, + UserRoles:Map, + Quorum:Usize, + ActionLastIndex0:Usize, + ActionData0:Map, + ActionSigners0:Map, + expand(expanded)) + ensures invariant( + NumUsers:Usize, + UserIdToAddress:Map, + AddressToUserId:Map, + NumBoardMembers:Usize, + NumProposers:Usize, + UserRoles:Map, + Quorum:Usize, + ?ActionLastIndex1:Usize, + ?ActionData1:Map, + ?ActionSigners1:Map, + usesExpanded) +endmodule diff --git a/multisig/protocol-correctness/proof/invariant/proof-propose-change-quorum.k b/multisig/protocol-correctness/proof/invariant/proof-propose-change-quorum.k new file mode 100644 index 000000000..376838286 --- /dev/null +++ b/multisig/protocol-correctness/proof/invariant/proof-propose-change-quorum.k @@ -0,0 +1,77 @@ +require "../functions/functions-execute.k" + +require "../functions/trusted-propose-action-BoardMember.k" +require "../functions/trusted-propose-action-Proposer.k" +require "../functions/trusted-propose-action-error-no-user.k" +require "../functions/trusted-propose-action-error-no-role.k" + +module PROOF-PROPOSE-CHANGE-QUORUM + imports INVARIANT-EXECUTION + imports PSEUDOCODE + + imports TRUSTED-PROPOSE-ACTION-ERROR-NO-ROLE + imports TRUSTED-PROPOSE-ACTION-ERROR-NO-USER + imports TRUSTED-PROPOSE-ACTION-BOARDMEMBER + imports TRUSTED-PROPOSE-ACTION-PROPOSER + + claim + runExternalCalls( + ( from _:Address run proposeChangeQuorum(_Quorum:Usize); + EC:ExternalCommands + ) + ) + + invariantState( + NumUsers:Usize, + UserIdToAddress:Map, + AddressToUserId:Map, + NumBoardMembers:Usize, + NumProposers:Usize, + UserRoles:Map, + Quorum:Usize, + ActionLastIndex0:Usize, + ActionData0:Map, + ActionSigners0:Map, + PerformedActions:List) + + => + + runExternalCalls(EC) + invariantState( + NumUsers:Usize, + UserIdToAddress:Map, + AddressToUserId:Map, + NumBoardMembers:Usize, + NumProposers:Usize, + UserRoles:Map, + Quorum:Usize, + ?ActionLastIndex1:Usize, + ?ActionData1:Map, + ?ActionSigners1:Map, + PerformedActions:List):StateCell + + requires invariant( + NumUsers:Usize, + UserIdToAddress:Map, + AddressToUserId:Map, + NumBoardMembers:Usize, + NumProposers:Usize, + UserRoles:Map, + Quorum:Usize, + ActionLastIndex0:Usize, + ActionData0:Map, + ActionSigners0:Map, + expand(expanded)) + ensures invariant( + NumUsers:Usize, + UserIdToAddress:Map, + AddressToUserId:Map, + NumBoardMembers:Usize, + NumProposers:Usize, + UserRoles:Map, + Quorum:Usize, + ?ActionLastIndex1:Usize, + ?ActionData1:Map, + ?ActionSigners1:Map, + usesExpanded) +endmodule diff --git a/multisig/protocol-correctness/proof/invariant/proof-propose-remove-user.k b/multisig/protocol-correctness/proof/invariant/proof-propose-remove-user.k new file mode 100644 index 000000000..e90fc2fbe --- /dev/null +++ b/multisig/protocol-correctness/proof/invariant/proof-propose-remove-user.k @@ -0,0 +1,77 @@ +require "../functions/functions-execute.k" + +require "../functions/trusted-propose-action-BoardMember.k" +require "../functions/trusted-propose-action-Proposer.k" +require "../functions/trusted-propose-action-error-no-user.k" +require "../functions/trusted-propose-action-error-no-role.k" + +module PROOF-PROPOSE-REMOVE-USER + imports INVARIANT-EXECUTION + imports PSEUDOCODE + + imports TRUSTED-PROPOSE-ACTION-ERROR-NO-ROLE + imports TRUSTED-PROPOSE-ACTION-ERROR-NO-USER + imports TRUSTED-PROPOSE-ACTION-BOARDMEMBER + imports TRUSTED-PROPOSE-ACTION-PROPOSER + + claim + runExternalCalls( + ( from _:Address run proposeRemoveUser(_Member:Address); + EC:ExternalCommands + ) + ) + + invariantState( + NumUsers:Usize, + UserIdToAddress:Map, + AddressToUserId:Map, + NumBoardMembers:Usize, + NumProposers:Usize, + UserRoles:Map, + Quorum:Usize, + ActionLastIndex0:Usize, + ActionData0:Map, + ActionSigners0:Map, + PerformedActions:List) + + => + + runExternalCalls(EC) + invariantState( + NumUsers:Usize, + UserIdToAddress:Map, + AddressToUserId:Map, + NumBoardMembers:Usize, + NumProposers:Usize, + UserRoles:Map, + Quorum:Usize, + ?ActionLastIndex1:Usize, + ?ActionData1:Map, + ?ActionSigners1:Map, + PerformedActions:List):StateCell + + requires invariant( + NumUsers:Usize, + UserIdToAddress:Map, + AddressToUserId:Map, + NumBoardMembers:Usize, + NumProposers:Usize, + UserRoles:Map, + Quorum:Usize, + ActionLastIndex0:Usize, + ActionData0:Map, + ActionSigners0:Map, + expand(expanded)) + ensures invariant( + NumUsers:Usize, + UserIdToAddress:Map, + AddressToUserId:Map, + NumBoardMembers:Usize, + NumProposers:Usize, + UserRoles:Map, + Quorum:Usize, + ?ActionLastIndex1:Usize, + ?ActionData1:Map, + ?ActionSigners1:Map, + usesExpanded) +endmodule diff --git a/multisig/protocol-correctness/proof/invariant/proof-propose-sc-call.k b/multisig/protocol-correctness/proof/invariant/proof-propose-sc-call.k new file mode 100644 index 000000000..d0673b17a --- /dev/null +++ b/multisig/protocol-correctness/proof/invariant/proof-propose-sc-call.k @@ -0,0 +1,82 @@ +require "../functions/functions-execute.k" + +require "../functions/trusted-propose-action-BoardMember.k" +require "../functions/trusted-propose-action-Proposer.k" +require "../functions/trusted-propose-action-error-no-user.k" +require "../functions/trusted-propose-action-error-no-role.k" + +module PROOF-PROPOSE-SC-CALL + imports INVARIANT-EXECUTION + imports PSEUDOCODE + + imports TRUSTED-PROPOSE-ACTION-ERROR-NO-ROLE + imports TRUSTED-PROPOSE-ACTION-ERROR-NO-USER + imports TRUSTED-PROPOSE-ACTION-BOARDMEMBER + imports TRUSTED-PROPOSE-ACTION-PROPOSER + + claim + runExternalCalls( + ( from _:Address run proposeSCCall( + _To:Address, + _Amount:BigUint, + _Function:BoxedBytes, + Args:ExpressionList); + EC:ExternalCommands + ) + ) + + invariantState( + NumUsers:Usize, + UserIdToAddress:Map, + AddressToUserId:Map, + NumBoardMembers:Usize, + NumProposers:Usize, + UserRoles:Map, + Quorum:Usize, + ActionLastIndex0:Usize, + ActionData0:Map, + ActionSigners0:Map, + PerformedActions:List) + + => + + runExternalCalls(EC) + invariantState( + NumUsers:Usize, + UserIdToAddress:Map, + AddressToUserId:Map, + NumBoardMembers:Usize, + NumProposers:Usize, + UserRoles:Map, + Quorum:Usize, + ?ActionLastIndex1:Usize, + ?ActionData1:Map, + ?ActionSigners1:Map, + PerformedActions:List):StateCell + + requires invariant( + NumUsers:Usize, + UserIdToAddress:Map, + AddressToUserId:Map, + NumBoardMembers:Usize, + NumProposers:Usize, + UserRoles:Map, + Quorum:Usize, + ActionLastIndex0:Usize, + ActionData0:Map, + ActionSigners0:Map, + expand(expanded)) + andBool isKResult(Args) + ensures invariant( + NumUsers:Usize, + UserIdToAddress:Map, + AddressToUserId:Map, + NumBoardMembers:Usize, + NumProposers:Usize, + UserRoles:Map, + Quorum:Usize, + ?ActionLastIndex1:Usize, + ?ActionData1:Map, + ?ActionSigners1:Map, + usesExpanded) +endmodule diff --git a/multisig/protocol-correctness/proof/invariant/proof-propose-sc-deploy.k b/multisig/protocol-correctness/proof/invariant/proof-propose-sc-deploy.k new file mode 100644 index 000000000..db06b3175 --- /dev/null +++ b/multisig/protocol-correctness/proof/invariant/proof-propose-sc-deploy.k @@ -0,0 +1,84 @@ +require "../functions/functions-execute.k" + +require "../functions/trusted-propose-sc-deploy-BoardMember.k" +require "../functions/trusted-propose-sc-deploy-Proposer.k" +require "../functions/trusted-propose-sc-deploy-error-no-user.k" +require "../functions/trusted-propose-sc-deploy-error-no-role.k" + +module PROOF-PROPOSE-SC-DEPLOY + imports INVARIANT-EXECUTION + imports PSEUDOCODE + + imports TRUSTED-PROPOSE-SC-DEPLOY-ERROR-NO-USER + imports TRUSTED-PROPOSE-SC-DEPLOY-ERROR-NO-ROLE + imports TRUSTED-PROPOSE-SC-DEPLOY-BOARDMEMBER + imports TRUSTED-PROPOSE-SC-DEPLOY-PROPOSER + + claim + runExternalCalls( + ( from _:Address run proposeSCDeploy( + _Amount:BigUint, + _Code:BoxedBytes, + _Upgradeable:Bool, + _Payable:Bool, + _Readable:Bool, + Args:ExpressionList); + EC:ExternalCommands + ) + ) + + invariantState( + NumUsers:Usize, + UserIdToAddress:Map, + AddressToUserId:Map, + NumBoardMembers:Usize, + NumProposers:Usize, + UserRoles:Map, + Quorum:Usize, + ActionLastIndex0:Usize, + ActionData0:Map, + ActionSigners0:Map, + PerformedActions:List) + + => + + runExternalCalls(EC) + invariantState( + NumUsers:Usize, + UserIdToAddress:Map, + AddressToUserId:Map, + NumBoardMembers:Usize, + NumProposers:Usize, + UserRoles:Map, + Quorum:Usize, + ?ActionLastIndex1:Usize, + ?ActionData1:Map, + ?ActionSigners1:Map, + PerformedActions:List):StateCell + + requires invariant( + NumUsers:Usize, + UserIdToAddress:Map, + AddressToUserId:Map, + NumBoardMembers:Usize, + NumProposers:Usize, + UserRoles:Map, + Quorum:Usize, + ActionLastIndex0:Usize, + ActionData0:Map, + ActionSigners0:Map, + expand(expanded)) + andBool isKResult(Args) + ensures invariant( + NumUsers:Usize, + UserIdToAddress:Map, + AddressToUserId:Map, + NumBoardMembers:Usize, + NumProposers:Usize, + UserRoles:Map, + Quorum:Usize, + ?ActionLastIndex1:Usize, + ?ActionData1:Map, + ?ActionSigners1:Map, + usesExpanded) +endmodule diff --git a/multisig/protocol-correctness/proof/invariant/proof-propose-send-egld.k b/multisig/protocol-correctness/proof/invariant/proof-propose-send-egld.k new file mode 100644 index 000000000..4ee865f64 --- /dev/null +++ b/multisig/protocol-correctness/proof/invariant/proof-propose-send-egld.k @@ -0,0 +1,77 @@ +require "../functions/functions-execute.k" + +require "../functions/trusted-propose-action-BoardMember.k" +require "../functions/trusted-propose-action-Proposer.k" +require "../functions/trusted-propose-action-error-no-user.k" +require "../functions/trusted-propose-action-error-no-role.k" + +module PROOF-PROPOSE-SEND-EGLD + imports INVARIANT-EXECUTION + imports PSEUDOCODE + + imports TRUSTED-PROPOSE-ACTION-ERROR-NO-ROLE + imports TRUSTED-PROPOSE-ACTION-ERROR-NO-USER + imports TRUSTED-PROPOSE-ACTION-BOARDMEMBER + imports TRUSTED-PROPOSE-ACTION-PROPOSER + + claim + runExternalCalls( + ( from _:Address run proposeSendEgld(_To:Address, _Amount:BigUint); + EC:ExternalCommands + ) + ) + + invariantState( + NumUsers:Usize, + UserIdToAddress:Map, + AddressToUserId:Map, + NumBoardMembers:Usize, + NumProposers:Usize, + UserRoles:Map, + Quorum:Usize, + ActionLastIndex0:Usize, + ActionData0:Map, + ActionSigners0:Map, + PerformedActions:List) + + => + + runExternalCalls(EC) + invariantState( + NumUsers:Usize, + UserIdToAddress:Map, + AddressToUserId:Map, + NumBoardMembers:Usize, + NumProposers:Usize, + UserRoles:Map, + Quorum:Usize, + ?ActionLastIndex1:Usize, + ?ActionData1:Map, + ?ActionSigners1:Map, + PerformedActions:List):StateCell + + requires invariant( + NumUsers:Usize, + UserIdToAddress:Map, + AddressToUserId:Map, + NumBoardMembers:Usize, + NumProposers:Usize, + UserRoles:Map, + Quorum:Usize, + ActionLastIndex0:Usize, + ActionData0:Map, + ActionSigners0:Map, + expand(expanded)) + ensures invariant( + NumUsers:Usize, + UserIdToAddress:Map, + AddressToUserId:Map, + NumBoardMembers:Usize, + NumProposers:Usize, + UserRoles:Map, + Quorum:Usize, + ?ActionLastIndex1:Usize, + ?ActionData1:Map, + ?ActionSigners1:Map, + usesExpanded) +endmodule diff --git a/multisig/protocol-correctness/proof/invariant/proof-sign.k b/multisig/protocol-correctness/proof/invariant/proof-sign.k new file mode 100644 index 000000000..085da157e --- /dev/null +++ b/multisig/protocol-correctness/proof/invariant/proof-sign.k @@ -0,0 +1,81 @@ +require "../functions/trusted-sign-empty-action.k" +require "../functions/trusted-sign-caller-not-user.k" +require "../functions/trusted-sign-caller-none.k" +require "../functions/trusted-sign-caller-proposer.k" +require "../functions/trusted-sign-no-signers.k" +require "../functions/trusted-sign-existing-signers-in-list.k" +require "../functions/trusted-sign-existing-signers-not-in-list.k" + +module PROOF-SIGN + imports INVARIANT-EXECUTION + imports PSEUDOCODE + + imports TRUSTED-SIGN-EMPTY-ACTION + imports TRUSTED-SIGN-CALLER-NOT-USER + imports TRUSTED-SIGN-CALLER-NONE + imports TRUSTED-SIGN-CALLER-PROPOSER + imports TRUSTED-SIGN-NO-SIGNERS + imports TRUSTED-SIGN-EXISTING-SIGNERS-IN-LIST + imports TRUSTED-SIGN-EXISTING-SIGNERS-NOT-IN-LIST + + claim + runExternalCalls( + ( from _:Address run sign(_ActionId:Usize); + EC:ExternalCommands + ) + ) + + invariantState( + NumUsers:Usize, + UserIdToAddress:Map, + AddressToUserId:Map, + NumBoardMembers:Usize, + NumProposers:Usize, + UserRoles:Map, + Quorum:Usize, + ActionLastIndex0:Usize, + ActionData0:Map, + ActionSigners0:Map, + PerformedActions:List) + + => + + runExternalCalls(EC) + invariantState( + NumUsers:Usize, + UserIdToAddress:Map, + AddressToUserId:Map, + NumBoardMembers:Usize, + NumProposers:Usize, + UserRoles:Map, + Quorum:Usize, + ?ActionLastIndex1:Usize, + ?ActionData1:Map, + ?ActionSigners1:Map, + PerformedActions:List):StateCell + + requires invariant( + NumUsers:Usize, + UserIdToAddress:Map, + AddressToUserId:Map, + NumBoardMembers:Usize, + NumProposers:Usize, + UserRoles:Map, + Quorum:Usize, + ActionLastIndex0:Usize, + ActionData0:Map, + ActionSigners0:Map, + expand(expanded)) + ensures invariant( + NumUsers:Usize, + UserIdToAddress:Map, + AddressToUserId:Map, + NumBoardMembers:Usize, + NumProposers:Usize, + UserRoles:Map, + Quorum:Usize, + ?ActionLastIndex1:Usize, + ?ActionData1:Map, + ?ActionSigners1:Map, + usesExpanded) +endmodule diff --git a/multisig/protocol-correctness/proof/invariant/proof-unsign.k b/multisig/protocol-correctness/proof/invariant/proof-unsign.k new file mode 100644 index 000000000..0f1989a87 --- /dev/null +++ b/multisig/protocol-correctness/proof/invariant/proof-unsign.k @@ -0,0 +1,85 @@ +require "../functions/trusted-unsign-no-action.k" +require "../functions/trusted-unsign-only-signer.k" +require "../functions/trusted-unsign-other-signers-not-first.k" +require "../functions/trusted-unsign-other-signers-first.k" +require "../functions/trusted-unsign-not-signed.k" +require "../functions/trusted-unsign-no-signers.k" +require "../functions/trusted-unsign-Proposer.k" +require "../functions/trusted-unsign-no-role.k" +require "../functions/trusted-unsign-no-user.k" + +module PROOF-UNSIGN + imports INVARIANT-EXECUTION + imports PSEUDOCODE + + imports TRUSTED-UNSIGN-NO-ACTION + imports TRUSTED-UNSIGN-ONLY-SIGNER + imports TRUSTED-UNSIGN-OTHER-SIGNERS-NOT-FIRST + imports TRUSTED-UNSIGN-OTHER-SIGNERS-FIRST + imports TRUSTED-UNSIGN-NOT-SIGNED + imports TRUSTED-UNSIGN-NO-SIGNERS + imports TRUSTED-UNSIGN-PROPOSER + imports TRUSTED-UNSIGN-NO-ROLE + imports TRUSTED-UNSIGN-NO-USER + + claim + runExternalCalls( + ( from _:Address run unsign(_ActionId:Usize); + EC:ExternalCommands + ) + ) + + invariantState( + NumUsers:Usize, + UserIdToAddress:Map, + AddressToUserId:Map, + NumBoardMembers:Usize, + NumProposers:Usize, + UserRoles:Map, + Quorum:Usize, + ActionLastIndex0:Usize, + ActionData0:Map, + ActionSigners0:Map, + PerformedActions:List) + + => + + runExternalCalls(EC) + invariantState( + NumUsers:Usize, + UserIdToAddress:Map, + AddressToUserId:Map, + NumBoardMembers:Usize, + NumProposers:Usize, + UserRoles:Map, + Quorum:Usize, + ?ActionLastIndex1:Usize, + ?ActionData1:Map, + ?ActionSigners1:Map, + PerformedActions:List):StateCell + + requires invariant( + NumUsers:Usize, + UserIdToAddress:Map, + AddressToUserId:Map, + NumBoardMembers:Usize, + NumProposers:Usize, + UserRoles:Map, + Quorum:Usize, + ActionLastIndex0:Usize, + ActionData0:Map, + ActionSigners0:Map, + expand(expanded)) + ensures invariant( + NumUsers:Usize, + UserIdToAddress:Map, + AddressToUserId:Map, + NumBoardMembers:Usize, + NumProposers:Usize, + UserRoles:Map, + Quorum:Usize, + ?ActionLastIndex1:Usize, + ?ActionData1:Map, + ?ActionSigners1:Map, + usesExpanded) +endmodule diff --git a/multisig/protocol-correctness/proof/make-trusted.py b/multisig/protocol-correctness/proof/make-trusted.py new file mode 100755 index 000000000..e2f125d0e --- /dev/null +++ b/multisig/protocol-correctness/proof/make-trusted.py @@ -0,0 +1,65 @@ +#!/usr/bin/env python3 +import sys + +def naturalNumbers(): + i = 1 + while True: + yield i + i += 1 + +DEFAULT = 0 +PROOF = 1 +TRUSTED = 2 + +def makeTrusted(file_name, lines): + state = DEFAULT + for (line_number, line) in lines: + normalized = line.strip() + if normalized.startswith('//@'): + if state == DEFAULT: + if normalized == '//@ proof': + state = PROOF + else: + raise Exception( + "Unexpected trusted directive, only '//@ proof' allowed here.\n%s:%d" + % (file_name, line_number)) + elif state == PROOF: + if normalized == '//@ trusted': + state = TRUSTED + else: + raise Exception( + "Unexpected trusted directive, only '//@ trusted' allowed here.\n%s:%d" + % (file_name, line_number)) + elif state == TRUSTED: + if normalized == '//@ end': + state = DEFAULT + else: + raise Exception( + "Unexpected trusted directive, only '//@ end' allowed here.\n%s:%d" + % (file_name, line_number)) + else: + if state == DEFAULT: + pass + else: + unindented = line.lstrip() + indentation = ' ' * (len(line) - len(unindented)) + if state == PROOF: + line = indentation + '// ' + unindented + elif state == TRUSTED: + if unindented.startswith('// '): + line = indentation + unindented[3:] + else: + raise Exception( + "Expected trusted lines to be commented.\n%s:%d" + % (file_name, line_number)) + yield line + +def main(argv): + if len(argv) != 2: + raise Exception('Wrong number of arguments, expected an input and an output file name.') + with open(argv[0], 'r') as f: + with open(argv[1], 'w') as g: + g.writelines(makeTrusted(argv[0], zip(naturalNumbers(), f))) + +if __name__ == '__main__': + main(sys.argv[1:]) diff --git a/multisig/protocol-correctness/proof/malicious-user/BUILD b/multisig/protocol-correctness/proof/malicious-user/BUILD new file mode 100644 index 000000000..87f06571b --- /dev/null +++ b/multisig/protocol-correctness/proof/malicious-user/BUILD @@ -0,0 +1,12 @@ +load("//:proof.bzl", "kompile", "klibrary") + +kompile( + name = "malicious-user-execute", + srcs = ["malicious-user-execute.k"], + deps = [ + "//protocol-correctness/proof:execution-proof-files", + "//protocol-correctness/proof/invariant:invariant-execution-files", + # "//protocol-correctness/proof/functions:functions-execute-files", + ], + visibility = ["//visibility:public"], +) diff --git a/multisig/protocol-correctness/proof/malicious-user/Makefile b/multisig/protocol-correctness/proof/malicious-user/Makefile new file mode 100644 index 000000000..6a16a293f --- /dev/null +++ b/multisig/protocol-correctness/proof/malicious-user/Makefile @@ -0,0 +1,26 @@ +include ../settings.mak + +.PHONY: default +default: all ; + +SCRIPT_DIR=.. + +PROOF_DIR := .. +include ../proof-dependency.mak + +# MAP_DIR := ../map +# include $(MAP_DIR)/map.mak + +INVARIANT_DIR := ../invariant +include $(INVARIANT_DIR)/invariant.mak + +MALICIOUS_USER_DIR := . +include malicious-user.mak + +.PHONY: all clean execution + +all: out/malicious-user.proof.timestamp + +execution: out/malicious-user.execution.timestamp + +clean: malicious-user.clean diff --git a/multisig/protocol-correctness/proof/malicious-user/malicious-user-execute.k b/multisig/protocol-correctness/proof/malicious-user/malicious-user-execute.k new file mode 100644 index 000000000..706ec275e --- /dev/null +++ b/multisig/protocol-correctness/proof/malicious-user/malicious-user-execute.k @@ -0,0 +1,146 @@ +require "protocol-correctness/proof/execution-proof.k" +require "protocol-correctness/proof/invariant/invariant-execution.k" + +module MALICIOUS-USER-EXECUTE-SYNTAX + imports EXECUTION-PROOF-SYNTAX +endmodule + +module MALICIOUS-USER-INVARIANT-FUNCTIONS + imports MAP + imports PSEUDOCODE-SYNTAX + + syntax Bool ::= onlyThisSigner(addressToUserId:Map, Address, actionSigners:Map) + [function, functional] + + rule onlyThisSigner( + _AddressToUserId:Map, + _Address:Address, + .Map) + => true + rule onlyThisSigner( + AddressToUserId:Map, + Address:Address, + _Key |-> Signers ActionSigners:Map) + => + #if Address in_keys(AddressToUserId) + #then oneElementList(AddressToUserId[Address] orDefault void, Signers) + #else false + #fi + andBool onlyThisSigner(AddressToUserId, Address, ActionSigners) + [simplification] + + syntax Bool ::= oneElementList(element:KItem, ExpressionList) [function, functional] + rule oneElementList(E:Expression, [E, .]) => true + rule oneElementList(_, _) => false [owise] +endmodule + +module MALICIOUS-USER-INVARIANT + imports INVARIANT + imports MALICIOUS-USER-INVARIANT-FUNCTIONS + + syntax Bool ::= maliciousInvariant( + maliciousAddress:Address, + numUsers:Usize, + // initialUserIdToAddress:Map, + currentUserIdToAddress:Map, + // initialAddressToUserId:Map, + currentAddressToUserId:Map, + numBoardMembers:Usize, + numProposers:Usize, + userRoles:Map, + quorum:Usize, + actionLastIndex:Usize, + actionData:Map, + actionSigners:Map, + PropertyHandling) + [function, functional] + + rule maliciousInvariant( + MaliciousAddress:Address, + NumUsers:Usize, + // InitialUserIdToAddress:Map, + CurrentUserIdToAddress:Map, + // InitialAddressToUserId:Map, + CurrentAddressToUserId:Map, + NumBoardMembers:Usize, + NumProposers:Usize, + UserRoles:Map, + u(Quorum:Int), + ActionLastIndex:Usize, + ActionData:Map, + ActionSigners:Map, + Handling:PropertyHandling) + => true + andBool invariant( + NumUsers, + CurrentUserIdToAddress, + CurrentAddressToUserId, + NumBoardMembers, + NumProposers, + UserRoles, + u(Quorum), + ActionLastIndex, + ActionData, + ActionSigners, + Handling) + // andBool mapIncluded(InitialUserIdToAddress, CurrentUserIdToAddress) + // andBool mapIncluded(InitialAddressToUserId, CurrentAddressToUserId) + andBool onlyThisSigner(CurrentAddressToUserId, MaliciousAddress, ActionSigners) + andBool Quorum >=Int 2 +endmodule + + +module MALICIOUS-USER-HELPERS + imports PSEUDOCODE-SYNTAX + + syntax KItem ::= runExternalCallsFromUser(Address, steps:Int) + + rule runExternalCallsFromUser(_:Address, Steps:Int) => .K + requires Steps <=Int 0 + rule runExternalCallsFromUser(A:Address, Steps:Int) + => runExternalCallFromUser(A) ~> runExternalCallsFromUser(A, Steps -Int 1) + requires Steps >Int 0 + + syntax KItem ::= runExternalCallFromUser(Address) + + rule runExternalCallFromUser(A:Address) + => runExternalCall(from A run proposeAddBoardMember(?_UserAddress:Address);) + rule runExternalCallFromUser(A:Address) + => runExternalCall(from A run proposeAddProposer(?_UserAddress:Address);) + rule runExternalCallFromUser(A:Address) + => runExternalCall(from A run proposeRemoveUser(?_UserAddress:Address);) + rule runExternalCallFromUser(A:Address) + => runExternalCall(from A run proposeChangeQuorum(?_Quorum:Usize);) + rule runExternalCallFromUser(A:Address) + => runExternalCall(from A run proposeSendEgld( + ?_To:Address, ?_Amount:BigUint, ?_Data:BoxedBytes);) + rule runExternalCallFromUser(A:Address) + => runExternalCall(from A run proposeSCDeploy( + ?_Amount:BigUint, + ?_Code:BoxedBytes, + ?_Upgradeable:Bool, + ?_Payable:Bool, + ?_Readable:Bool, + ?_Args:ExpressionList);) + rule runExternalCallFromUser(A:Address) + => runExternalCall(from A run proposeSCCall( + ?_To:Address, + ?_Amount:BigUint, + ?_Function:BoxedBytes, + ?_Args:ExpressionList);) + rule runExternalCallFromUser(A:Address) + => runExternalCall(from A run sign(?_ActionId:Usize);) + rule runExternalCallFromUser(A:Address) + => runExternalCall(from A run unsign(?_ActionId:Usize);) + rule runExternalCallFromUser(A:Address) + => runExternalCall(from A run performActionEndpoint(?_ActionId:Usize);) + rule runExternalCallFromUser(A:Address) + => runExternalCall(from A run discardAction(?_ActionId:Usize);) +endmodule + +module MALICIOUS-USER-EXECUTE + imports EXECUTION-PROOF + imports INVARIANT-EXECUTION + imports MALICIOUS-USER-INVARIANT + imports MALICIOUS-USER-HELPERS +endmodule \ No newline at end of file diff --git a/multisig/protocol-correctness/proof/malicious-user/malicious-user.mak b/multisig/protocol-correctness/proof/malicious-user/malicious-user.mak new file mode 100644 index 000000000..774a5f0db --- /dev/null +++ b/multisig/protocol-correctness/proof/malicious-user/malicious-user.mak @@ -0,0 +1,40 @@ +MALICIOUS_USER_OUT_PREFIX=out/malicious-user. + +MALICIOUS_USER_PROOFS := $(wildcard $(MALICIOUS_USER_DIR)/proofs/*.k) +MALICIOUS_USER_EXECUTION := $(wildcard $(MALICIOUS_USER_DIR)/*.k) $(PROOF_EXECUTION) $(INVARIANT_EXECUTION) + +MALICIOUS_USER_PROOF_TIMESTAMPS := $(addprefix $(MALICIOUS_USER_OUT_PREFIX),$(notdir ${MALICIOUS_USER_PROOFS:.k=.timestamp})) +MALICIOUS_USER_PROOF_DEBUGGERS := $(addprefix $(MALICIOUS_USER_OUT_PREFIX),$(notdir ${MALICIOUS_USER_PROOFS:.k=.debugger})) + +.PHONY: malicious-user.clean ${MALICIOUS_USER_PROOF_DEBUGGERS} + +$(MALICIOUS_USER_OUT_PREFIX)proof.timestamp: ${MALICIOUS_USER_PROOF_TIMESTAMPS} + $(DIR_GUARD) + @touch $(MALICIOUS_USER_OUT_PREFIX)proof.timestamp + +$(MALICIOUS_USER_OUT_PREFIX)proof-%.timestamp: ${MALICIOUS_USER_DIR}/proofs/proof-%.k $(MALICIOUS_USER_OUT_PREFIX)execution.timestamp + $(DIR_GUARD) + @echo "Proving $*..." + @cat /proc/uptime | sed 's/\s.*//' > $(MALICIOUS_USER_OUT_PREFIX)proof-$*.duration.temp + @((kprove $< --directory $(MALICIOUS_USER_DIR) --haskell-backend-command $(BACKEND_COMMAND) > $(MALICIOUS_USER_OUT_PREFIX)proof-$*.out 2>&1) && echo "$* done") || (cat $(MALICIOUS_USER_OUT_PREFIX)proof-$*.out; echo "$* failed"; echo "$*" >> $(MALICIOUS_USER_OUT_PREFIX)failures; false) + @cat /proc/uptime | sed 's/\s.*//' >> $(MALICIOUS_USER_OUT_PREFIX)proof-$*.duration.temp + @$(SCRIPT_DIR)/compute-duration.py $(MALICIOUS_USER_OUT_PREFIX)proof-$*.duration.temp > $(MALICIOUS_USER_OUT_PREFIX)proof-$*.duration + @rm $(MALICIOUS_USER_OUT_PREFIX)proof-$*.duration.temp + @touch $(MALICIOUS_USER_OUT_PREFIX)proof-$*.timestamp + +$(MALICIOUS_USER_OUT_PREFIX)proof-%.debugger: ${MALICIOUS_USER_DIR}/proofs/proof-%.k $(MALICIOUS_USER_OUT_PREFIX)execution.timestamp + $(DIR_GUARD) + @echo "Debugging $*..." + @kprove $< --directory $(MALICIOUS_USER_DIR) --haskell-backend-command $(DEBUG_COMMAND) + +$(MALICIOUS_USER_OUT_PREFIX)execution.timestamp: $(MALICIOUS_USER_DIR)/malicious-user-execute.k $(MALICIOUS_USER_EXECUTION) + $(DIR_GUARD) + @echo "Compiling execution..." + @kompile $< --backend haskell --directory $(MALICIOUS_USER_DIR) + @touch $(MALICIOUS_USER_OUT_PREFIX)execution.timestamp + +malicious-user.clean: + -rm -r $(MALICIOUS_USER_DIR)/*-kompiled + -rm -r .kprove-* + -rm kore-*.tar.gz + -rm $(MALICIOUS_USER_OUT_PREFIX)* diff --git a/multisig/protocol-correctness/proof/malicious-user/proofs/BUILD b/multisig/protocol-correctness/proof/malicious-user/proofs/BUILD new file mode 100644 index 000000000..8fcecf690 --- /dev/null +++ b/multisig/protocol-correctness/proof/malicious-user/proofs/BUILD @@ -0,0 +1,51 @@ +load("//:proof.bzl", "kprove_test", "ktrusted") + +kprove_test( + name = "proof-cannot-perform", + srcs = ["proof-cannot-perform.k"], + trusted = [ + ":trusted-call-invariant", + ], + semantics = "//protocol-correctness/proof/malicious-user:malicious-user-execute", + timeout = "moderate", + breadth = "2", + # depth = "5" +) + +kprove_test( + name = "proof-call-invariant", + srcs = ["proof-call-invariant.k"], + trusted = [ + ":trusted-propose-add-board-member", + ], + semantics = "//protocol-correctness/proof/malicious-user:malicious-user-execute", + timeout = "eternal", +) + +kprove_test( + name = "proof-propose-add-board-member", + srcs = ["proof-propose-add-board-member.k"], + trusted = [ + "//protocol-correctness/proof/functions:trusted-propose-action-BoardMember", + "//protocol-correctness/proof/functions:trusted-propose-action-Proposer", + "//protocol-correctness/proof/functions:trusted-propose-action-error-no-user", + "//protocol-correctness/proof/functions:trusted-propose-action-error-no-role", + ], + semantics = "//protocol-correctness/proof/malicious-user:malicious-user-execute", + timeout = "eternal", + breadth = "6", + # depth = ~37 +) + +ktrusted( + name = "trusted-call-invariant", + srcs = ["proof-call-invariant.k"], + visibility = ["//visibility:public"], +) + +ktrusted( + name = "trusted-propose-add-board-member", + srcs = ["proof-propose-add-board-member.k"], + visibility = ["//visibility:public"], +) + diff --git a/multisig/protocol-correctness/proof/malicious-user/proofs/proof-call-invariant.k b/multisig/protocol-correctness/proof/malicious-user/proofs/proof-call-invariant.k new file mode 100644 index 000000000..3130fac45 --- /dev/null +++ b/multisig/protocol-correctness/proof/malicious-user/proofs/proof-call-invariant.k @@ -0,0 +1,85 @@ +//@ proof +require "trusted-propose-add-board-member.k" //@ Bazel remove + +module PROOF-CALL-INVARIANT + imports TRUSTED-PROPOSE-ADD-BOARD-MEMBER +//@ trusted +// module TRUSTED-CALL-INVARIANT +//@ end + imports MALICIOUS-USER-EXECUTE + imports PSEUDOCODE + + claim + runExternalCallFromUser(MaliciousAddress:Address) + ~> runExternalCallsFromUser(MaliciousAddress:Address, Count:Int) + ~> K:K + + invariantState( + NumUsers:Usize, + UserIdToAddress:Map, + AddressToUserId:Map, + NumBoardMembers:Usize, + NumProposers:Usize, + UserRoles:Map, + Quorum:Usize, + ActionLastIndex:Usize, + ActionData:Map, + ActionSigners:Map, + PerformedActions:List) + + => + + runExternalCallsFromUser(MaliciousAddress:Address, Count:Int) + ~> K:K + + invariantState( + NumUsers, + UserIdToAddress:Map, + AddressToUserId:Map, + NumBoardMembers, + NumProposers, + UserRoles, + Quorum, + u(?ActionLastIndex:Int), + ?ActionData:Map, + ?ActionSigners:Map, + PerformedActions:List):StateCell + + requires true + andBool maliciousInvariant( + MaliciousAddress, + NumUsers, + UserIdToAddress, + AddressToUserId, + NumBoardMembers, + NumProposers, + UserRoles, + Quorum, + ActionLastIndex, + ActionData, + ActionSigners, + expand(expanded)) + ensures true + andBool maliciousInvariant( + MaliciousAddress, + NumUsers, + UserIdToAddress, + AddressToUserId, + NumBoardMembers, + NumProposers, + UserRoles, + Quorum, + u(?ActionLastIndex), + ?ActionData, + ?ActionSigners, + //@ proof + usesExpanded + //@ trusted + // expand(expanded) + //@ end + ) + //@ proof + //@ trusted + // [trusted] + //@ end +endmodule diff --git a/multisig/protocol-correctness/proof/malicious-user/proofs/proof-cannot-perform.k b/multisig/protocol-correctness/proof/malicious-user/proofs/proof-cannot-perform.k new file mode 100644 index 000000000..b1d949058 --- /dev/null +++ b/multisig/protocol-correctness/proof/malicious-user/proofs/proof-cannot-perform.k @@ -0,0 +1,81 @@ +//@ proof +require "trusted-call-invariant.k" //@ Bazel remove + +module PROOF-CANNOT-PERFORM + imports TRUSTED-CALL-INVARIANT +//@ trusted +// module TRUSTED-CANNOT-PERFORM +//@ end + imports MALICIOUS-USER-EXECUTE + imports PSEUDOCODE + + claim + runExternalCallsFromUser(MaliciousAddress:Address, _Count:Int) ~> K:K + invariantState( + NumUsers:Usize, + UserIdToAddress:Map, + AddressToUserId:Map, + NumBoardMembers:Usize, + NumProposers:Usize, + UserRoles:Map, + u(Quorum:Int), + ActionLastIndex:Usize, + ActionData:Map, + ActionSigners:Map, + PerformedActions:List) + + => + + K + invariantState( + NumUsers, + UserIdToAddress:Map, + AddressToUserId:Map, + NumBoardMembers, + NumProposers, + UserRoles, + u(Quorum), + u(?ActionLastIndex:Int), + ?ActionData:Map, + ?ActionSigners:Map, + PerformedActions:List):StateCell + + requires true + andBool maliciousInvariant( + MaliciousAddress, + NumUsers, + // UserIdToAddress, + UserIdToAddress, + // AddressToUserId, + AddressToUserId, + NumBoardMembers, + NumProposers, + UserRoles, + u(Quorum), + ActionLastIndex, + ActionData, + ActionSigners, + expand(expanded)) + + // andBool Quorum >=Int 2 + ensures true + andBool maliciousInvariant( + MaliciousAddress, + NumUsers, + UserIdToAddress, + // ?UserIdToAddress, + AddressToUserId, + // ?AddressToUserId, + NumBoardMembers, + NumProposers, + UserRoles, + u(Quorum), + u(?ActionLastIndex), + ?ActionData, + ?ActionSigners, + usesExpanded) + //@ proof + //@ trusted + // [trusted] + //@ end +endmodule diff --git a/multisig/protocol-correctness/proof/malicious-user/proofs/proof-propose-add-board-member.k b/multisig/protocol-correctness/proof/malicious-user/proofs/proof-propose-add-board-member.k new file mode 100644 index 000000000..3448b9f13 --- /dev/null +++ b/multisig/protocol-correctness/proof/malicious-user/proofs/proof-propose-add-board-member.k @@ -0,0 +1,81 @@ +//@ proof +require "../functions/trusted-propose-action-BoardMember.k" //@ Bazel remove +require "../functions/trusted-propose-action-Proposer.k" //@ Bazel remove +require "../functions/trusted-propose-action-error-no-user.k" //@ Bazel remove +require "../functions/trusted-propose-action-error-no-role.k" //@ Bazel remove + +module PROOF-PROPOSE-ADD-BOARD-MEMBER + imports TRUSTED-PROPOSE-ACTION-ERROR-NO-ROLE + imports TRUSTED-PROPOSE-ACTION-ERROR-NO-USER + imports TRUSTED-PROPOSE-ACTION-BOARDMEMBER + imports TRUSTED-PROPOSE-ACTION-PROPOSER +//@ trusted +// module TRUSTED-PROPOSE-ADD-BOARD-MEMBER +//@ end + imports MALICIOUS-USER-EXECUTE + imports PSEUDOCODE + + claim + runExternalCall(from MaliciousAddress run proposeAddBoardMember(_UserAddress:Address);) ~> K:K + invariantState( + NumUsers:Usize, + UserIdToAddress:Map, + AddressToUserId:Map, + NumBoardMembers:Usize, + NumProposers:Usize, + UserRoles:Map, + Quorum:Usize, + ActionLastIndex:Usize, + ActionData:Map, + ActionSigners:Map, + PerformedActions:List) + + => + + K + invariantState( + NumUsers, + ?UserIdToAddress:Map, + ?AddressToUserId:Map, + NumBoardMembers, + NumProposers, + UserRoles, + Quorum, + ?ActionLastIndex:Usize, + ?ActionData:Map, + ?ActionSigners:Map, + PerformedActions:List):StateCell + + requires true + andBool maliciousInvariant( + MaliciousAddress, + NumUsers, + UserIdToAddress, + AddressToUserId, + NumBoardMembers, + NumProposers, + UserRoles, + Quorum, + ActionLastIndex, + ActionData, + ActionSigners, + expand(expanded)) + ensures true + andBool maliciousInvariant( + MaliciousAddress, + NumUsers, + ?UserIdToAddress, + ?AddressToUserId, + NumBoardMembers, + NumProposers, + UserRoles, + Quorum, + ?ActionLastIndex, + ?ActionData, + ?ActionSigners, + usesExpanded) + //@ proof + //@ trusted + // [trusted] + //@ end +endmodule diff --git a/multisig/protocol-correctness/proof/map/BUILD b/multisig/protocol-correctness/proof/map/BUILD new file mode 100644 index 000000000..89a3f385c --- /dev/null +++ b/multisig/protocol-correctness/proof/map/BUILD @@ -0,0 +1,8 @@ +load("//:proof.bzl", "klibrary") + +klibrary( + name = "map-files", + srcs = ["map-execute.k"], + deps = [], + visibility = ["//visibility:public"], +) diff --git a/multisig/protocol-correctness/proof/map/Makefile b/multisig/protocol-correctness/proof/map/Makefile new file mode 100644 index 000000000..ff0e645c5 --- /dev/null +++ b/multisig/protocol-correctness/proof/map/Makefile @@ -0,0 +1,17 @@ +include ../settings.mak + +.PHONY: default +default: all ; + +SCRIPT_DIR=.. + +MAP_DIR := . +include map.mak + +.PHONY: all clean execution + +all: .out/map.proof.timestamp + +execution: .out/map.execution.timestamp + +clean: map.clean diff --git a/multisig/protocol-correctness/proof/map/map-execute.k b/multisig/protocol-correctness/proof/map/map-execute.k new file mode 100644 index 000000000..9592909b8 --- /dev/null +++ b/multisig/protocol-correctness/proof/map/map-execute.k @@ -0,0 +1,197 @@ +module MAP-EXECUTE-SYNTAX +endmodule + +module MAP-EXECUTE + imports MAP + imports INT + + // The Haskell backend does not send functions applied to things + // that can be bottom to the SMT solver, even if the side condition restricts + // the arguments to non-bottom things. + // + // A (K |-> V M:Map) map representation is bottom if `K in_keys(M)`, hence + // the function-based representation below. This means that whatever function + // is using these can manipulate them only through simplification rules. + // + // TODO: Consider replacing these with Map[<-] or something similar. + syntax Map ::= opaque(Map) [function, functional] + | concat(key:KItem, value:KItem, Map) [function, functional, no-evaluators] + | extractMap(Map) [function, functional] + rule opaque(K:KItem |-> V:KItem M:Map) => concat(K, V, opaque(M)) + ensures notBool K in_keys(M) + [simplification] + rule extractMap(opaque(M:Map)) => M + [simplification] + rule extractMap(concat(K:KItem, V:KItem, M:Map)) => K |-> V extractMap(M) + [simplification] + + rule K:KItem in_keys(opaque(M)) => K in_keys(M) + [simplification] + rule K1:KItem in_keys(concat(K2:KItem, _:KItem, M:Map)) + => K1 ==K K2 orBool K1 in_keys(M) + [simplification] + + rule opaque(M:Map)[K:KItem] orDefault V:KItem => M[K] orDefault V + [simplification] + rule concat(K2:KItem, V2:KItem, _:Map)[K1:KItem] orDefault _:KItem + => V2 + requires K1 ==K K2 + [simplification(20)] + rule concat(K2:KItem, _:KItem, M:Map)[K1:KItem] orDefault V1:KItem + => M[K1] orDefault V1 + requires notBool (K1 ==K K2) + [simplification(20)] + // TODO: Is this needed? Is this good? + rule concat(K2:KItem, V2:KItem, M:Map)[K1:KItem] orDefault V1:KItem + => extractMap(concat(K2:KItem, V2:KItem, M:Map))[K1:KItem] orDefault V1:KItem + requires K1 ==K K2 + [simplification(50)] + + rule opaque(M:Map)[K:KItem <- undef] => opaque(M[K <- undef]) + [simplification] + rule concat(K2:KItem, _:KItem, M:Map)[K1:KItem <- undef] => M + requires K1 ==K K2 + [simplification] + rule concat(K2:KItem, V2:KItem, M:Map)[K1:KItem <- undef] + => concat(K2, V2, M[K1 <- undef]) + requires notBool (K1 ==K K2) + [simplification] + + syntax MapElementProperty ::= "MEP.AlwaysFalse" + | "MEP.AlwaysTrue" + | "MEP.AnyProperty" + | "MEP.IsValue" "(" KItem ")" + syntax Bool ::= applyMapElementProperty( + MapElementProperty, + key:KItem, + value:KItem + ) [function, functional] + syntax Bool ::= uninterpretedElementProperty(key:KItem, value:KItem) + [function, functional, no-evaluators] + + rule applyMapElementProperty(MEP.AlwaysFalse, _:KItem, _:KItem) => false + rule applyMapElementProperty(MEP.AlwaysTrue, _:KItem, _:KItem) => true + rule applyMapElementProperty(MEP.AnyProperty, Key:KItem, Value:KItem) + => uninterpretedElementProperty(Key, Value) + rule applyMapElementProperty(MEP.IsValue(V:KItem), _Key:KItem, Value:KItem) + => V ==K Value + + syntax Int ::= countMapElementProperty( + MapElementProperty, + key:KItem, + value:KItem + ) [function, functional] + + rule countMapElementProperty(Property:MapElementProperty, Key:KItem, Value:KItem) + => 0 + requires notBool applyMapElementProperty(Property, Key, Value) + rule countMapElementProperty(Property:MapElementProperty, Key:KItem, Value:KItem) + => 1 + requires applyMapElementProperty(Property, Key, Value) + + syntax Int ::= mapCount(Map, MapElementProperty) [function, functional, smtlib(mapCount)] + + // TODO: Use this everywhere + rule mapCount(.Map, _:MapElementProperty) => 0 + rule mapCount(K:KItem |-> V:KItem M:Map, Property:MapElementProperty) + => countMapElementProperty(Property, K, V) +Int mapCount(M, Property) + [simplification] + + rule mapCount(_:Map, _:MapElementProperty) >=Int 0 => true + [simplification, smt-lemma] + + rule mapCount(M:Map, MEP.AlwaysTrue) >Int 0 => notBool (M ==K .Map) + [simplification] + + syntax SelectPropertyIntermediateResult ::= found(key:KItem, value:KItem, Map) + | notFoundYet(inner:Map, MapElementProperty, checked:Map) + syntax KItem ::= lazyMapSelectProperty(Map, MapElementProperty) + syntax KItem ::= #lazyMapSelectProperty(result:SelectPropertyIntermediateResult) + syntax KItem ::= mapSelectPropertyAddBack(Map) + syntax KItem ::= "mapSelectPropertyEnd" + + syntax KItem ::= findInnerMap(Map, MapElementProperty, SelectPropertyIntermediateResult) [function, functional] + syntax KItem ::= #findInnerMap(Map, MapElementProperty, checked:Map, SelectPropertyIntermediateResult) [function, functional] + + rule lazyMapSelectProperty(M:Map, P:MapElementProperty) + => findInnerMap(M, P, ?Result:SelectPropertyIntermediateResult) + ~> #lazyMapSelectProperty(?Result) + + rule #lazyMapSelectProperty(notFoundYet(Inner:Map, Property:MapElementProperty, Checked:Map)) + => mapSelectProperty(Inner, Property) ~> mapSelectPropertyAddBack(Checked) + rule #lazyMapSelectProperty(found(Key:KItem, Value:KItem, M:Map)) => mapSelected(Key, Value, M) + + rule mapSelected(Key:KItem, Value:KItem, M:Map) ~> mapSelectPropertyAddBack(N:Map) + => mapSelected(Key, Value, M N) + rule mapNotFound ~> mapSelectPropertyAddBack(_:Map) + => mapNotFound + + rule mapSelectPropertyEnd => .K + + rule findInnerMap(M:Map, P:MapElementProperty, Result:SelectPropertyIntermediateResult) + => #findInnerMap(M, P, .Map, Result) + rule #findInnerMap(K:KItem |-> V:KItem M:Map, P:MapElementProperty, Checked:Map, Result:SelectPropertyIntermediateResult) + => #findInnerMap(M, P, K |-> V Checked, Result) + requires notBool applyMapElementProperty(P, K, V) + [simplification(20)] + rule #findInnerMap(K:KItem |-> V:KItem M:Map, P:MapElementProperty, Checked:Map, Result:SelectPropertyIntermediateResult) + => mapSelectPropertyEnd + requires applyMapElementProperty(P, K, V) + ensures Result ==K found(K, V, iterateConcat(M, Checked)) + [simplification(20)] + rule #findInnerMap(M:Map, P:MapElementProperty, Checked:Map, Result:SelectPropertyIntermediateResult) + => mapSelectPropertyEnd + ensures Result ==K notFoundYet(M, P, Checked) + [simplification(50)] + + // TODO: Remove after https://github.com/kframework/kore/issues/2494 is fixed + syntax Map ::= iterateConcat(Map, Map) [function] + rule iterateConcat(M:Map, .Map) => M + rule iterateConcat(M:Map, K:KItem |-> V:KItem N) => iterateConcat(K |-> V M, N) + requires notBool K in_keys(M) + ensures notBool K in_keys(N) + [simplification(20)] + rule iterateConcat(M, N) => M N + [simplification(50)] + + syntax KItem ::= mapSelectProperty(Map, MapElementProperty) + syntax KItem ::= #mapSelectProperty( + toProcess:Map, MapElementProperty, processed:Map) + syntax KItem ::= #mapSelectedProperty( + key:KItem, value:KItem, + toProcess:Map, MapElementProperty, processed:Map) + + syntax KItem ::= mapSelected(key:KItem, value:KItem, Map) + syntax KItem ::= "mapNotFound" + + rule mapSelectProperty(M:Map, Property:MapElementProperty) + => #mapSelectProperty(M, Property, .Map) + + rule #mapSelectProperty(.Map, _:MapElementProperty, _:Map) + => mapNotFound + rule #mapSelectProperty( + M:Map, + Property:MapElementProperty, + Processed:Map) + => #mapSelectedProperty(?Key, ?Value, ?M, Property, Processed) + requires notBool (M ==K .Map) + ensures (M ==K (?Key:KItem |-> ?Value:KItem ?M:Map)) + + rule #mapSelectedProperty( + Key:KItem, + Value:KItem, + M:Map, + Property:MapElementProperty, + Processed:Map) + => mapSelected(Key, Value, M Processed) + requires applyMapElementProperty(Property, Key, Value) + rule #mapSelectedProperty( + Key:KItem, + Value:KItem, + M:Map, + Property:MapElementProperty, + Processed:Map) + => #mapSelectProperty(M, Property, Key |-> Value Processed) + requires notBool applyMapElementProperty(Property, Key, Value) + +endmodule diff --git a/multisig/protocol-correctness/proof/map/map.mak b/multisig/protocol-correctness/proof/map/map.mak new file mode 100644 index 000000000..4bf050f66 --- /dev/null +++ b/multisig/protocol-correctness/proof/map/map.mak @@ -0,0 +1,41 @@ +MAP_OUT_PREFIX=.out/map. + +MAP_ALL := $(wildcard $(MAP_DIR)/*.k) +MAP_PROOFS := $(wildcard $(MAP_DIR)/proof-*.k) +MAP_EXECUTION := $(filter-out $(MAP_PROOFS), $(MAP_ALL)) + +MAP_PROOF_TIMESTAMPS := $(addprefix $(MAP_OUT_PREFIX),$(notdir ${MAP_PROOFS:.k=.timestamp})) +MAP_PROOF_DEBUGGERS := $(addprefix $(MAP_OUT_PREFIX),$(notdir ${MAP_PROOFS:.k=.debugger})) + +.PHONY: map.clean ${MAP_PROOF_DEBUGGERS} + +$(MAP_OUT_PREFIX)proof.timestamp: ${MAP_PROOF_TIMESTAMPS} + $(DIR_GUARD) + @touch $(MAP_OUT_PREFIX)proof.timestamp + +$(MAP_OUT_PREFIX)proof-%.timestamp: ${MAP_DIR}/proof-%.k $(MAP_OUT_PREFIX)execution.timestamp + $(DIR_GUARD) + @echo "Proving $*..." + @cat /proc/uptime | sed 's/\s.*//' > $(MAP_OUT_PREFIX)proof-$*.duration.temp + @((kprove $< --directory $(MAP_DIR) --haskell-backend-command $(BACKEND_COMMAND) > $(MAP_OUT_PREFIX)proof-$*.out 2>&1) && echo "$* done") || (cat $(MAP_OUT_PREFIX)proof-$*.out; echo "$* failed"; echo "$*" >> $(MAP_OUT_PREFIX)failures; false) + @cat /proc/uptime | sed 's/\s.*//' >> $(MAP_OUT_PREFIX)proof-$*.duration.temp + @$(SCRIPT_DIR)/compute-duration.py $(MAP_OUT_PREFIX)proof-$*.duration.temp > $(MAP_OUT_PREFIX)proof-$*.duration + @rm $(MAP_OUT_PREFIX)proof-$*.duration.temp + @touch $(MAP_OUT_PREFIX)proof-$*.timestamp + +$(MAP_OUT_PREFIX)proof-%.debugger: ${MAP_DIR}/proof-%.k $(MAP_OUT_PREFIX)execution.timestamp + $(DIR_GUARD) + @echo "Debugging $*..." + @kprove $< --directory $(MAP_DIR) --haskell-backend-command $(DEBUG_COMMAND) + +$(MAP_OUT_PREFIX)execution.timestamp: $(MAP_DIR)/map-execute.k $(MAP_EXECUTION) + $(DIR_GUARD) + @echo "Compiling execution..." + @kompile $(KOMPILE_FLAGS) $< --backend haskell --directory $(MAP_DIR) + @touch $(MAP_OUT_PREFIX)execution.timestamp + +map.clean: + -rm -r $(MAP_DIR)/*-kompiled + -rm -r .kprove-* + -rm kore-*.tar.gz + -rm $(MAP_OUT_PREFIX)* diff --git a/multisig/protocol-correctness/proof/map/proof-map-semantics.k b/multisig/protocol-correctness/proof/map/proof-map-semantics.k new file mode 100644 index 000000000..0dd608909 --- /dev/null +++ b/multisig/protocol-correctness/proof/map/proof-map-semantics.k @@ -0,0 +1,54 @@ +module TRUSTED-MAP-SEMANTICS + imports MAP-EXECUTE + + claim mapSelectProperty(M:Map, Property:MapElementProperty) + => mapSelected(?Key:KItem, ?Value:KItem, ?M:Map) + requires mapCount(M, Property) >Int 0 + ensures applyMapElementProperty(Property, ?Key, ?Value) + andBool M ==K (?Key |-> ?Value ?M) + [trusted] + + claim mapSelectProperty(M:Map, Property:MapElementProperty) + => mapNotFound + requires notBool (mapCount(M, Property) >Int 0) + [trusted] +endmodule + +module PROOF-MAP-SEMANTICS + imports MAP-EXECUTE + + claim mapSelectProperty(M:Map, Property:MapElementProperty) + => mapSelected(?Key:KItem, ?Value:KItem, ?M:Map) + requires mapCount(M, Property) >Int 0 + ensures applyMapElementProperty(Property, ?Key, ?Value) + andBool M ==K (?Key |-> ?Value ?M) + + claim mapSelectProperty(M:Map, Property:MapElementProperty) + => mapNotFound + requires notBool (mapCount(M, Property) >Int 0) + + claim #mapSelectProperty(M:Map, Property:MapElementProperty, Processed:Map) + => mapSelected(?Key:KItem, ?Value:KItem, ?M:Map) + requires mapCount(M, Property) >Int 0 + ensures applyMapElementProperty(Property, ?Key, ?Value) + andBool (?Key |-> ?Value ?M) ==K (M Processed) + + claim #mapSelectProperty(M:Map, Property:MapElementProperty, _Processed:Map) + => mapNotFound + requires notBool (mapCount(M, Property) >Int 0) + + claim lazyMapSelectProperty(M:Map, MEP.IsValue(2) #as Property:MapElementProperty) + => mapSelected(?Key:KItem, 2, ?N:Map) + requires mapCount(M, Property) >Int 0 + ensures M ==K (?Key:KItem |-> 2 ?N) + claim lazyMapSelectProperty(M:Map, MEP.IsValue(2) #as Property:MapElementProperty) + => mapNotFound + requires notBool mapCount(M, Property) >Int 0 + + claim lazyMapSelectProperty( + (2|->2 N:Map) #as M:Map, + MEP.IsValue(2) #as Property:MapElementProperty) + => mapSelected(2, 2, N) + requires mapCount(M, Property) >Int 0 + +endmodule \ No newline at end of file diff --git a/multisig/protocol-correctness/proof/proof-dependency.mak b/multisig/protocol-correctness/proof/proof-dependency.mak new file mode 100644 index 000000000..0b8e68898 --- /dev/null +++ b/multisig/protocol-correctness/proof/proof-dependency.mak @@ -0,0 +1,7 @@ +SEMANTICS_DIR = $(PROOF_DIR)/.. + +SEMANTICS_K := $(wildcard $(SEMANTICS_DIR)/*.k) + +PROOF_ALL := $(wildcard $(PROOF_DIR)/*.k) +PROOF_PROOFS := $(wildcard $(PROOF_DIR)/proof-*.k) +PROOF_EXECUTION := $(filter-out $(PROOF_PROOFS), $(PROOF_ALL)) $(SEMANTICS_K) diff --git a/multisig/protocol-correctness/proof/properties/Makefile b/multisig/protocol-correctness/proof/properties/Makefile new file mode 100644 index 000000000..c0960b6cd --- /dev/null +++ b/multisig/protocol-correctness/proof/properties/Makefile @@ -0,0 +1,26 @@ +include ../settings.mak + +.PHONY: default +default: all ; + +SCRIPT_DIR=.. + +PROOF_DIR := .. +include ../proof-dependency.mak + +MAP_DIR := ../map +include $(MAP_DIR)/map.mak + +INVARIANT_DIR := ../invariant +include $(INVARIANT_DIR)/invariant.mak + +PROPERTIES_DIR := . +include properties.mak + +.PHONY: all clean execution + +all: .out/properties.proof.timestamp + +execution: .out/properties.execution.timestamp + +clean: properties.clean diff --git a/multisig/protocol-correctness/proof/properties/proof-board-members-sign-for-2.k b/multisig/protocol-correctness/proof/properties/proof-board-members-sign-for-2.k new file mode 100644 index 000000000..f404979e6 --- /dev/null +++ b/multisig/protocol-correctness/proof/properties/proof-board-members-sign-for-2.k @@ -0,0 +1,176 @@ +require "../map/proof-map-semantics.k" + +require "../functions/trusted-sign-empty-action.k" +require "../functions/trusted-sign-caller-not-user.k" +require "../functions/trusted-sign-caller-none.k" +require "../functions/trusted-sign-caller-proposer.k" +require "../functions/trusted-sign-no-signers.k" +require "../functions/trusted-sign-existing-signers-in-list.k" +require "../functions/trusted-sign-existing-signers-not-in-list.k" + +require "proof-board-members-sign-for.k" + +module TRUSTED-BOARD-MEMBERS-SIGN-FOR-2 + imports PROPERTIES-EXECUTE + imports PSEUDOCODE + + claim + boardMembersSignFor(ActionIndex:Usize, PartialUserRoles:Map) + ~> K:K + + invariantState( + NumUsers:Usize, + UserIdToAddress:Map, + AddressToUserId:Map, + NumBoardMembers:Usize, + NumProposers:Usize, + UserRoles:Map, + Quorum:Usize, + ActionLastIndex:Usize, + (ActionIndex |-> _Action:KItem _ActionData:Map) #as ActionData:Map, + ActionSigners:Map, + PerformedActions:List) + + => + + K:K + invariantState( + NumUsers, + UserIdToAddress, + AddressToUserId, + NumBoardMembers, + NumProposers, + UserRoles, + Quorum, + ActionLastIndex, + ActionData, + (ActionIndex |-> ?Signatures) ActionSigners, + PerformedActions:List):StateCell + + requires invariant( + NumUsers, + UserIdToAddress, + AddressToUserId, + NumBoardMembers, + NumProposers, + UserRoles, + Quorum, + ActionLastIndex, + ActionData, + ActionSigners, + expand(expanded)) + + andBool newUserIdToRoleInvariant(PartialUserRoles, UserIdToAddress) + andBool userIdToAddressInvariant(UserIdToAddress, AddressToUserId) + andBool mapsAreReverse(AddressToUserId, UserIdToAddress) + andBool mapIncluded(PartialUserRoles, UserRoles) + andBool valuesAreNotEmpty(ActionData, rAction) + + andBool notBool ActionIndex in_keys(ActionSigners) + andBool countMapValues(PartialUserRoles, BoardMember) >Int 0 + + ensures invariant( + NumUsers, + UserIdToAddress, + AddressToUserId, + NumBoardMembers, + NumProposers, + UserRoles, + Quorum, + ActionLastIndex, + ActionData, + (ActionIndex |-> ?Signatures) ActionSigners, + usesExpanded) + + andBool countCanSignFunction(?Signatures, opaque(UserRoles)) + ==Int countMapValues(PartialUserRoles, BoardMember) + [trusted] +endmodule + +module PROOF-BOARD-MEMBERS-SIGN-FOR-2 + imports MAP-EXECUTE + imports PROPERTIES-EXECUTE + imports PSEUDOCODE + + imports TRUSTED-MAP-SEMANTICS + + imports TRUSTED-BOARD-MEMBERS-SIGN-FOR + + imports TRUSTED-SIGN-EMPTY-ACTION + imports TRUSTED-SIGN-CALLER-NOT-USER + imports TRUSTED-SIGN-CALLER-NONE + imports TRUSTED-SIGN-CALLER-PROPOSER + imports TRUSTED-SIGN-NO-SIGNERS + imports TRUSTED-SIGN-EXISTING-SIGNERS-IN-LIST + imports TRUSTED-SIGN-EXISTING-SIGNERS-NOT-IN-LIST + + claim + boardMembersSignFor(ActionIndex:Usize, PartialUserRoles:Map) + ~> K:K + + invariantState( + NumUsers:Usize, + UserIdToAddress:Map, + AddressToUserId:Map, + NumBoardMembers:Usize, + NumProposers:Usize, + UserRoles:Map, + Quorum:Usize, + ActionLastIndex:Usize, + (ActionIndex |-> _Action:KItem _ActionData:Map) #as ActionData:Map, + ActionSigners:Map, + PerformedActions:List) + + => + + K:K + invariantState( + NumUsers, + UserIdToAddress, + AddressToUserId, + NumBoardMembers, + NumProposers, + UserRoles, + Quorum, + ActionLastIndex, + ActionData, + (ActionIndex |-> ?Signatures) ActionSigners, + PerformedActions:List):StateCell + + requires invariant( + NumUsers, + UserIdToAddress, + AddressToUserId, + NumBoardMembers, + NumProposers, + UserRoles, + Quorum, + ActionLastIndex, + ActionData, + ActionSigners, + expand(expanded)) + + andBool newUserIdToRoleInvariant(PartialUserRoles, UserIdToAddress) + andBool userIdToAddressInvariant(UserIdToAddress, AddressToUserId) + andBool mapsAreReverse(AddressToUserId, UserIdToAddress) + andBool mapIncluded(PartialUserRoles, UserRoles) + andBool valuesAreNotEmpty(ActionData, rAction) + andBool notBool ActionIndex in_keys(ActionSigners) + andBool countMapValues(PartialUserRoles, BoardMember) >Int 0 + + ensures invariant( + NumUsers, + UserIdToAddress, + AddressToUserId, + NumBoardMembers, + NumProposers, + UserRoles, + Quorum, + ActionLastIndex, + ActionData, + (ActionIndex |-> ?Signatures) ActionSigners, + usesExpanded) + + andBool countCanSignFunction(?Signatures, opaque(UserRoles)) + ==Int countMapValues(PartialUserRoles, BoardMember) +endmodule diff --git a/multisig/protocol-correctness/proof/properties/proof-board-members-sign-for-3.k b/multisig/protocol-correctness/proof/properties/proof-board-members-sign-for-3.k new file mode 100644 index 000000000..26b080f76 --- /dev/null +++ b/multisig/protocol-correctness/proof/properties/proof-board-members-sign-for-3.k @@ -0,0 +1,131 @@ +require "../map/proof-map-semantics.k" + +module TRUSTED-BOARD-MEMBERS-SIGN-FOR-3 + imports PROPERTIES-EXECUTE + imports PSEUDOCODE + + claim + boardMembersSignFor(ActionIndex:Usize, PartialUserRoles:Map) + ~> K:K + + invariantState( + NumUsers:Usize, + UserIdToAddress:Map, + AddressToUserId:Map, + NumBoardMembers:Usize, + NumProposers:Usize, + UserRoles:Map, + Quorum:Usize, + ActionLastIndex:Usize, + (ActionIndex |-> _Action:KItem _ActionData:Map) #as ActionData:Map, + ActionSigners:Map, + PerformedActions:List) + + => + + K:K + invariantState( + NumUsers, + UserIdToAddress, + AddressToUserId, + NumBoardMembers, + NumProposers, + UserRoles, + Quorum, + ActionLastIndex, + ActionData, + ActionSigners, + PerformedActions:List):StateCell + + requires invariant( + NumUsers, + UserIdToAddress, + AddressToUserId, + NumBoardMembers, + NumProposers, + UserRoles, + Quorum, + ActionLastIndex, + ActionData, + ActionSigners, + expand(expanded)) + + andBool newUserIdToRoleInvariant(PartialUserRoles, UserIdToAddress) + andBool userIdToAddressInvariant(UserIdToAddress, AddressToUserId) + andBool mapsAreReverse(AddressToUserId, UserIdToAddress) + andBool mapIncluded(PartialUserRoles, UserRoles) + andBool valuesAreNotEmpty(ActionData, rAction) + + andBool notBool ActionIndex in_keys(ActionSigners) + andBool countMapValues(PartialUserRoles, BoardMember) <=Int 0 + andBool notBool (PartialUserRoles ==K .Map) + + ensures 0 ==Int countMapValues(PartialUserRoles, BoardMember) + [trusted] +endmodule + +module PROOF-BOARD-MEMBERS-SIGN-FOR-3 + imports MAP-EXECUTE + imports PROPERTIES-EXECUTE + imports PSEUDOCODE + + imports TRUSTED-MAP-SEMANTICS + + claim + boardMembersSignFor(ActionIndex:Usize, PartialUserRoles:Map) + ~> K:K + + invariantState( + NumUsers:Usize, + UserIdToAddress:Map, + AddressToUserId:Map, + NumBoardMembers:Usize, + NumProposers:Usize, + UserRoles:Map, + Quorum:Usize, + ActionLastIndex:Usize, + (ActionIndex |-> _Action:KItem _ActionData:Map) #as ActionData:Map, + ActionSigners:Map, + PerformedActions:List) + + => + + K:K + invariantState( + NumUsers, + UserIdToAddress, + AddressToUserId, + NumBoardMembers, + NumProposers, + UserRoles, + Quorum, + ActionLastIndex, + ActionData, + ActionSigners, + PerformedActions:List):StateCell + + requires invariant( + NumUsers, + UserIdToAddress, + AddressToUserId, + NumBoardMembers, + NumProposers, + UserRoles, + Quorum, + ActionLastIndex, + ActionData, + ActionSigners, + expand(expanded)) + + andBool newUserIdToRoleInvariant(PartialUserRoles, UserIdToAddress) + andBool userIdToAddressInvariant(UserIdToAddress, AddressToUserId) + andBool mapsAreReverse(AddressToUserId, UserIdToAddress) + andBool mapIncluded(PartialUserRoles, UserRoles) + andBool valuesAreNotEmpty(ActionData, rAction) + + andBool notBool ActionIndex in_keys(ActionSigners) + andBool countMapValues(PartialUserRoles, BoardMember) <=Int 0 + andBool notBool (PartialUserRoles ==K .Map) + + ensures 0 ==Int countMapValues(PartialUserRoles, BoardMember) +endmodule diff --git a/multisig/protocol-correctness/proof/properties/proof-board-members-sign-for.k b/multisig/protocol-correctness/proof/properties/proof-board-members-sign-for.k new file mode 100644 index 000000000..d5a9eb488 --- /dev/null +++ b/multisig/protocol-correctness/proof/properties/proof-board-members-sign-for.k @@ -0,0 +1,171 @@ +require "../map/proof-map-semantics.k" + +require "../functions/trusted-sign-empty-action.k" +require "../functions/trusted-sign-caller-not-user.k" +require "../functions/trusted-sign-caller-none.k" +require "../functions/trusted-sign-caller-proposer.k" +require "../functions/trusted-sign-no-signers.k" +require "../functions/trusted-sign-existing-signers-in-list.k" +require "../functions/trusted-sign-existing-signers-not-in-list.k" + +module TRUSTED-BOARD-MEMBERS-SIGN-FOR + imports PROPERTIES-EXECUTE + imports PSEUDOCODE + + claim + boardMembersSignFor(ActionIndex:Usize, PartialUserRoles:Map) + ~> K:K + + invariantState( + NumUsers:Usize, + UserIdToAddress:Map, + AddressToUserId:Map, + NumBoardMembers:Usize, + NumProposers:Usize, + UserRoles:Map, + Quorum:Usize, + ActionLastIndex:Usize, + (ActionIndex |-> _Action:KItem _ActionData:Map) #as ActionData:Map, + ActionIndex |-> Signatures:ExpressionList ActionSigners:Map, + PerformedActions:List) + + => + + K:K + invariantState( + NumUsers, + UserIdToAddress, + AddressToUserId, + NumBoardMembers, + NumProposers, + UserRoles, + Quorum, + ActionLastIndex, + ActionData, + ActionIndex |-> ?Signatures ActionSigners, + PerformedActions:List):StateCell + + requires invariant( + NumUsers, + UserIdToAddress, + AddressToUserId, + NumBoardMembers, + NumProposers, + UserRoles, + Quorum, + ActionLastIndex, + ActionData, + ActionIndex |-> Signatures ActionSigners, + expand(expanded)) + + andBool newUserIdToRoleInvariant(PartialUserRoles, UserIdToAddress) + andBool userIdToAddressInvariant(UserIdToAddress, AddressToUserId) + andBool mapsAreReverse(AddressToUserId, UserIdToAddress) + andBool mapIncluded(PartialUserRoles, UserRoles) + andBool valuesAreNotEmpty(ActionData, rAction) + + andBool noMapKeyInList(PartialUserRoles, Signatures) + + ensures invariant( + NumUsers, + UserIdToAddress, + AddressToUserId, + NumBoardMembers, + NumProposers, + UserRoles, + Quorum, + ActionLastIndex, + ActionData, + ActionIndex |-> ?Signatures ActionSigners, + usesExpanded) + + andBool countCanSignFunction(?Signatures, opaque(UserRoles)) + ==Int countMapValues(PartialUserRoles, BoardMember) + +Int countCanSignFunction(Signatures, opaque(UserRoles)) + [trusted] +endmodule + +module PROOF-BOARD-MEMBERS-SIGN-FOR + imports MAP-EXECUTE + imports PROPERTIES-EXECUTE + imports PSEUDOCODE + + imports TRUSTED-MAP-SEMANTICS + + imports TRUSTED-SIGN-EMPTY-ACTION + imports TRUSTED-SIGN-CALLER-NOT-USER + imports TRUSTED-SIGN-CALLER-NONE + imports TRUSTED-SIGN-CALLER-PROPOSER + imports TRUSTED-SIGN-NO-SIGNERS + imports TRUSTED-SIGN-EXISTING-SIGNERS-IN-LIST + imports TRUSTED-SIGN-EXISTING-SIGNERS-NOT-IN-LIST + + claim + boardMembersSignFor(ActionIndex:Usize, PartialUserRoles:Map) + ~> K:K + + invariantState( + NumUsers:Usize, + UserIdToAddress:Map, + AddressToUserId:Map, + NumBoardMembers:Usize, + NumProposers:Usize, + UserRoles:Map, + Quorum:Usize, + ActionLastIndex:Usize, + (ActionIndex |-> _Action:KItem _ActionData:Map) #as ActionData:Map, + ActionIndex |-> Signatures:ExpressionList ActionSigners:Map, + PerformedActions:List) + + => + + K:K + invariantState( + NumUsers, + UserIdToAddress, + AddressToUserId, + NumBoardMembers, + NumProposers, + UserRoles, + Quorum, + ActionLastIndex, + ActionData, + ActionIndex |-> ?Signatures ActionSigners, + PerformedActions:List):StateCell + + requires invariant( + NumUsers, + UserIdToAddress, + AddressToUserId, + NumBoardMembers, + NumProposers, + UserRoles, + Quorum, + ActionLastIndex, + ActionData, + ActionIndex |-> Signatures ActionSigners, + expand(expanded)) + + andBool newUserIdToRoleInvariant(PartialUserRoles, UserIdToAddress) + andBool userIdToAddressInvariant(UserIdToAddress, AddressToUserId) + andBool mapsAreReverse(AddressToUserId, UserIdToAddress) + andBool mapIncluded(PartialUserRoles, UserRoles) + andBool valuesAreNotEmpty(ActionData, rAction) + andBool noMapKeyInList(PartialUserRoles, Signatures) + ensures invariant( + NumUsers, + UserIdToAddress, + AddressToUserId, + NumBoardMembers, + NumProposers, + UserRoles, + Quorum, + ActionLastIndex, + ActionData, + ActionIndex |-> ?Signatures ActionSigners, + usesExpanded) + andBool countCanSignFunction(?Signatures, opaque(UserRoles)) + ==Int countMapValues(PartialUserRoles, BoardMember) + +Int countCanSignFunction(Signatures, opaque(UserRoles)) + +endmodule diff --git a/multisig/protocol-correctness/proof/properties/proof-can-propose-and-execute.k b/multisig/protocol-correctness/proof/properties/proof-can-propose-and-execute.k new file mode 100644 index 000000000..9ab6ebe54 --- /dev/null +++ b/multisig/protocol-correctness/proof/properties/proof-can-propose-and-execute.k @@ -0,0 +1,91 @@ +require "../invariant/proof-count-can-sign.k" +require "../map/proof-map-semantics.k" +require "proof-board-members-sign-for.k" +require "proof-board-members-sign-for-2.k" +require "proof-board-members-sign-for-3.k" + +require "../functions/trusted-propose-action-BoardMember.k" +require "../functions/trusted-propose-action-Proposer.k" +require "../functions/trusted-propose-action-error-no-user.k" +require "../functions/trusted-propose-action-error-no-role.k" + +module PROOF-CAN-PROPOSE-AND-EXECUTE + imports MAP-EXECUTE + imports PROPERTIES-EXECUTE + imports PSEUDOCODE + + imports TRUSTED-BOARD-MEMBERS-SIGN-FOR + imports TRUSTED-BOARD-MEMBERS-SIGN-FOR-2 + imports TRUSTED-BOARD-MEMBERS-SIGN-FOR-3 + + imports TRUSTED-COUNT-CAN-SIGN + imports TRUSTED-MAP-SEMANTICS + + imports TRUSTED-PROPOSE-ACTION-ERROR-NO-ROLE + imports TRUSTED-PROPOSE-ACTION-ERROR-NO-USER + imports TRUSTED-PROPOSE-ACTION-BOARDMEMBER + imports TRUSTED-PROPOSE-ACTION-PROPOSER + + claim + pickBoardMemberOrProposer(UserIdToRole) + ~> withPickedUserCall(proposeChangeQuorum(u(0))) + ~> allBoardMembersSignFor(add(ActionLastIndex, u(1))) + ~> pickBoardMemberOrProposer(UserIdToRole) + ~> withPickedUserCall(performActionEndpoint(add(ActionLastIndex, u(1)))) + + invariantState( + NumUsers:Usize, + UserIdToAddress:Map, + AddressToUserId:Map, + NumBoardMembers:Usize, + NumProposers:Usize, + UserIdToRole:Map, + Quorum:Usize, + ActionLastIndex:Usize, + ActionData:Map, + ActionSigners:Map, + _PerformedActions:List) + + => + + .K + invariantState( + NumUsers:Usize, + UserIdToAddress:Map, + AddressToUserId:Map, + NumBoardMembers:Usize, + NumProposers:Usize, + UserIdToRole:Map, + u(0), + add(ActionLastIndex, u(1)), + ActionData:Map, + ActionSigners:Map, + ?_PerformedActions:List):StateCell + + requires invariant( + NumUsers:Usize, + UserIdToAddress:Map, + AddressToUserId:Map, + NumBoardMembers:Usize, + NumProposers:Usize, + UserIdToRole:Map, + Quorum:Usize, + ActionLastIndex:Usize, + ActionData:Map, + ActionSigners:Map, + expand(expand(expanded))) + // TODO: Move everything below to the invariant. + andBool valuesAreOfType(UserIdToAddress, rAddress) + andBool valuesAreKResult(UserIdToAddress) + + andBool newUserIdToRoleInvariant(UserIdToRole, UserIdToAddress) + andBool userIdToAddressInvariant(UserIdToAddress, AddressToUserId) + andBool mapsAreReverse(AddressToUserId, UserIdToAddress) + + andBool valuesAreNotEmpty(ActionData, rAction) + + andBool mapCount(UserIdToRole, MEP.IsValue(BoardMember)) + +Int mapCount(UserIdToRole, MEP.IsValue(Proposer)) + >Int 0 + +endmodule \ No newline at end of file diff --git a/multisig/protocol-correctness/proof/properties/properties-execute.k b/multisig/protocol-correctness/proof/properties/properties-execute.k new file mode 100644 index 000000000..3060faef9 --- /dev/null +++ b/multisig/protocol-correctness/proof/properties/properties-execute.k @@ -0,0 +1,179 @@ +require "../execution-proof.k" +require "../invariant/invariant-execution.k" +// TODO: Rename to map-execution +require "../map/map-execute.k" + +module PROPERTIES-EXECUTE-SYNTAX + imports EXECUTION-PROOF-SYNTAX +endmodule + +module PROPERTIES-EXECUTE + imports EXECUTION-PROOF + imports INVARIANT-EXECUTION + imports MAP-EXECUTE + + syntax KItem ::= allBoardMembersSignFor(actionId:Usize) + syntax KItem ::= boardMembersSignFor(actionId:Usize, userRoles:Map) + syntax KItem ::= boardMembersSignForFreezer(actionId:Usize) + syntax KItem ::= #boardMembersSignFor( + actionId:Usize, + key:KItem, + value:KItem, + userRoles:Map) + syntax KItem ::= signFor(actionId:Usize, userId:KItem) + syntax KItem ::= #signFor(actionId:Usize, userId:KItem) + syntax KItem ::= lazyCastMapValue(key:KItem, Map, ReflectionType) + syntax KItem ::= castMapValue(key:KItem, Map, ReflectionType) [function, functional] + syntax KItem ::= castValue(value:KItem, ReflectionType) + + rule allBoardMembersSignFor(ActionId:Usize) + => boardMembersSignFor(ActionId, UserIdToRole) + ... + UserIdToRole:Map + ActionSigners:Map + requires notBool (ActionId in_keys(ActionSigners)) + + rule allBoardMembersSignFor(ActionId:Usize) + => boardMembersSignFor(ActionId, UserIdToRole) + ... + UserId |-> BoardMember UserIdToRole:Map + ActionId |-> [UserId:Usize, .] _ActionSigners:Map + + rule boardMembersSignFor(_ActionId:Usize, .Map) => .K + rule boardMembersSignFor(ActionId:Usize, UserIdToRole:Map) + => ( lazyMapSelectProperty(UserIdToRole, MEP.AlwaysTrue) + ~> boardMembersSignForFreezer(ActionId) + ) + requires notBool (UserIdToRole ==K .Map) + + rule ( mapSelected(Key:KItem, Value:KItem, UserIdToRole:Map) + ~> boardMembersSignForFreezer(ActionId:Usize) + ) + => #boardMembersSignFor(ActionId, Key, Value, UserIdToRole) + + rule #boardMembersSignFor( + ActionId:Usize, + UserId:KItem, + V:KItem, + UserIdToRole:Map) + => ( cast(V, rUserRole) + ~> removeValue + ~> concretizeValue(V) + ~> branchK( + V ==K BoardMember, + cast(UserId, rUsize) + ~> removeValue + ~> signFor(ActionId, UserId) + ~> boardMembersSignFor(ActionId, UserIdToRole), + boardMembersSignFor(ActionId, UserIdToRole) + ) + ) + + rule signFor(ActionId:Usize, UserId:KItem) + => ( makeConcreteValue(UserId, rAddress, UserIdToAddress) + ~> #signFor(ActionId, UserId) + ) + ... + UserIdToAddress:Map + + rule #signFor(ActionId:Usize, UserId:KItem) + => runExternalCall(from Address run sign(ActionId);) + ... + UserId |-> Address:Address _UserIdToAddress:Map + + rule lazyCastMapValue(Key:KItem, M:Map, Type:ReflectionType) + => castMapValue(Key, M, Type) + + rule castMapValue(Key:KItem, M:Map, _Type:ReflectionType) => stuck + requires notBool Key in_keys(M) + rule castMapValue(Key:KItem, (K:KItem |-> Value:KItem) _:Map, Type:ReflectionType) + => castValue(Value, Type) + requires Key ==K K + [simplification] + rule castValue(Value:KItem, Type:ReflectionType) + => cast(Value, Type) ~> removeValue + + syntax KItem ::= pickBoardMemberOrProposer(Map) + + rule pickBoardMemberOrProposer(M:Map) + => splitBoolean(mapCount(M, MEP.IsValue(BoardMember)) >Int 0) + ~> branchK( + mapCount(M, MEP.IsValue(BoardMember)) >Int 0, + lazyMapSelectProperty(M, MEP.IsValue(BoardMember)), + splitBoolean(mapCount(M, MEP.IsValue(Proposer)) >Int 0) + ~> branchK( + mapCount(M, MEP.IsValue(Proposer)) >Int 0, + lazyMapSelectProperty(M, MEP.IsValue(Proposer)), + stuck + ) + ) + + syntax KItem ::= withPickedUserCall(EndpointCall) + + rule + ( mapSelected(UserId:KItem, _UserRole:KItem, _Remainder:Map) + => nullableMapLookup(UserId, UserIdToAddress, rAddress) + ) + ~> withPickedUserCall(_:EndpointCall) + ... + UserIdToAddress:Map + rule ( Address:Address + ~> withPickedUserCall(Call:EndpointCall) + ) + => concretizeValue(Address) ~> runExternalCall(from Address run Call;) + + //////////////////////////////////////// + + syntax Bool ::= allKeysBecomeKeys(Map, Map) [function, functional] + + rule allKeysBecomeKeys(.Map, _:Map) => true + rule allKeysBecomeKeys(K:KItem |-> _:KItem M:Map, N:Map) + => K in_keys(N) andBool allKeysBecomeKeys(M, N) + [simplification] + rule allKeysBecomeKeys(M:Map, _:KItem |-> _:KItem N:Map) => true + requires allKeysBecomeKeys(M, N) + [simplification] + +// TODO: Move to the execution module. + + // TODO: Make this the main invariant + syntax Bool ::= newUserIdToRoleInvariant(userIdToRole:Map, userIdToAddress:Map) + [function, functional] + + rule newUserIdToRoleInvariant(.Map, _:Map) => true + + rule newUserIdToRoleInvariant(K:KItem |-> V:KItem UserIdToRole:Map, UserIdToAddress:Map) + => true + andBool valueOfType(V, rUserRole) // valuesAreOfType(UserIdToRole, rUserRole) + andBool isKResult(V) // valuesAreKResult(UserIdToRole) + andBool valueIsNotEmpty(V, rUserRole) // valuesAreNotEmpty(UserIdToRole, rUserRole) + andBool valueOfType(K, rUsize) // keysAreOfType(UserIdToRole, rUsize) + andBool isKResult(K) // keysAreKResult(UserIdToRole) + andBool K in_keys(UserIdToAddress) // allKeysBecomeKeys(UserIdToRole, UserIdToAddress) + + andBool newUserIdToRoleInvariant(UserIdToRole, UserIdToAddress) + [simplification] + + syntax Bool ::= userIdToAddressInvariant(userIdToAddress:Map, addressToUserId:Map) + [function, functional] + + rule userIdToAddressInvariant(.Map, _:Map) => true + + rule userIdToAddressInvariant(K:KItem |-> V:KItem UserIdToAddress:Map, AddressToUserId:Map) + => true + andBool valueOfType(V, rAddress) // valuesAreOfType(UserIdToAddress, rAddress) + andBool isKResult(V) // valuesAreKResult(UserIdToAddress) + andBool valueIsNotEmpty(V, rAddress) // valuesAreNotEmpty(UserIdToAddress, rAddress) + andBool V in_keys(AddressToUserId) andBool AddressToUserId[V] ==K K // mapsAreReverseHalf(UserIdToAddress, AddressToUserId) + + andBool userIdToAddressInvariant(UserIdToAddress, AddressToUserId) + [simplification] + + rule A:Int <=Int countCanSignFunction(L:ExpressionList, K:KItem |-> BoardMember M:Map) => true + requires true + andBool A <=Int countMapValues(M, BoardMember) +Int 1 + andBool countMapValues(M, BoardMember) +Int 1 + ==K countCanSignFunction(L:ExpressionList, K |-> BoardMember M:Map) + [simplification] + +endmodule diff --git a/multisig/protocol-correctness/proof/properties/properties.mak b/multisig/protocol-correctness/proof/properties/properties.mak new file mode 100644 index 000000000..8844866f9 --- /dev/null +++ b/multisig/protocol-correctness/proof/properties/properties.mak @@ -0,0 +1,41 @@ +PROPERTIES_OUT_PREFIX=.out/properties. + +PROPERTIES_ALL := $(wildcard $(PROPERTIES_DIR)/*.k) +PROPERTIES_PROOFS := $(wildcard $(PROPERTIES_DIR)/proof-*.k) +PROPERTIES_EXECUTION := $(filter-out $(PROPERTIES_PROOFS), $(PROPERTIES_ALL)) $(PROOF_EXECUTION) $(MAP_EXECUTION) $(INVARIANT_EXECUTION) + +PROPERTIES_PROOF_TIMESTAMPS := $(addprefix $(PROPERTIES_OUT_PREFIX),$(notdir ${PROPERTIES_PROOFS:.k=.timestamp})) +PROPERTIES_PROOF_DEBUGGERS := $(addprefix $(PROPERTIES_OUT_PREFIX),$(notdir ${PROPERTIES_PROOFS:.k=.debugger})) + +.PHONY: properties.clean ${PROPERTIES_PROOF_DEBUGGERS} + +$(PROPERTIES_OUT_PREFIX)proof.timestamp: ${PROPERTIES_PROOF_TIMESTAMPS} + $(DIR_GUARD) + @touch $(PROPERTIES_OUT_PREFIX)proof.timestamp + +$(PROPERTIES_OUT_PREFIX)proof-%.timestamp: ${PROPERTIES_DIR}/proof-%.k $(PROPERTIES_OUT_PREFIX)execution.timestamp + $(DIR_GUARD) + @echo "Proving $*..." + @cat /proc/uptime | sed 's/\s.*//' > $(PROPERTIES_OUT_PREFIX)proof-$*.duration.temp + @((kprove $< --directory $(PROPERTIES_DIR) --haskell-backend-command $(BACKEND_COMMAND) > $(PROPERTIES_OUT_PREFIX)proof-$*.out 2>&1) && echo "$* done") || (cat $(PROPERTIES_OUT_PREFIX)proof-$*.out; echo "$* failed"; echo "$*" >> $(PROPERTIES_OUT_PREFIX)failures; false) + @cat /proc/uptime | sed 's/\s.*//' >> $(PROPERTIES_OUT_PREFIX)proof-$*.duration.temp + @$(SCRIPT_DIR)/compute-duration.py $(PROPERTIES_OUT_PREFIX)proof-$*.duration.temp > $(PROPERTIES_OUT_PREFIX)proof-$*.duration + @rm $(PROPERTIES_OUT_PREFIX)proof-$*.duration.temp + @touch $(PROPERTIES_OUT_PREFIX)proof-$*.timestamp + +$(PROPERTIES_OUT_PREFIX)proof-%.debugger: ${PROPERTIES_DIR}/proof-%.k $(PROPERTIES_OUT_PREFIX)execution.timestamp + $(DIR_GUARD) + @echo "Debugging $*..." + @kprove $< --directory $(PROPERTIES_DIR) --haskell-backend-command $(DEBUG_COMMAND) + +$(PROPERTIES_OUT_PREFIX)execution.timestamp: $(PROPERTIES_DIR)/properties-execute.k $(PROPERTIES_EXECUTION) + $(DIR_GUARD) + @echo "Compiling execution..." + @kompile $(KOMPILE_FLAGS) $< --backend haskell --directory $(PROPERTIES_DIR) + @touch $(PROPERTIES_OUT_PREFIX)execution.timestamp + +properties.clean: + -rm -r $(PROPERTIES_DIR)/*-kompiled + -rm -r .kprove-* + -rm kore-*.tar.gz + -rm $(PROPERTIES_OUT_PREFIX)* diff --git a/multisig/protocol-correctness/proof/settings.mak b/multisig/protocol-correctness/proof/settings.mak new file mode 100644 index 000000000..6de6f30ac --- /dev/null +++ b/multisig/protocol-correctness/proof/settings.mak @@ -0,0 +1,7 @@ +SHELL?=/bin/bash -euo pipefail + +KOMPILE_FLAGS=-I $(shell git rev-parse --show-toplevel)/multisig + +BACKEND_COMMAND ?= "kore-exec --smt-timeout 4000" +DEBUG_COMMAND ?= "kore-repl --smt-timeout 4000 --repl-script /home/virgil/runtime-verification/k/haskell-backend/src/main/native/haskell-backend/kore/data/kast.kscript" +DIR_GUARD ?= @mkdir -p $(@D) diff --git a/multisig/protocol-correctness/proof/trusted-deps.py b/multisig/protocol-correctness/proof/trusted-deps.py new file mode 100755 index 000000000..2dd89f55b --- /dev/null +++ b/multisig/protocol-correctness/proof/trusted-deps.py @@ -0,0 +1,359 @@ +#!/usr/bin/env python3 +import sys + +def isIdentifierChar(c): + return c.isalnum() or c == '_' or c == '-' + +class StringParser: + DEFAULT = 0 + STRING = 1 + ESCAPE = 2 + def __init__(self): + self.__state = StringParser.DEFAULT + self.__terminator = '"' + self.__contents = [] + + def processCharImmediate(self, c): + list(self.processChar(c)) + + def processChar(self, c): + if self.__state == StringParser.DEFAULT: + if c == '"': + self.__state = StringParser.STRING + self.__terminator = '"' + self.__contents = [] + elif c == "'": + self.__state = StringParser.STRING + self.__terminator = "'" + self.__contents = [] + else: + return c + elif self.__state == StringParser.STRING: + if c == self.__terminator: + self.__state = StringParser.DEFAULT + return ' ' + elif c == '\\': + self.__state = StringParser.ESCAPE + self.__contents.append(c) + else: + self.__contents.append(c) + elif self.__state == StringParser.ESCAPE: + self.__state = StringParser.STRING + self.__contents.append(c) + else: + assert False + return '' + + def inString(self): + return self.__state != StringParser.DEFAULT + + def string(self): + return ''.join(self.__contents) + +class CommentParser: + DEFAULT = 0 + SLASH = 1 + LINECOMMENT = 2 + MULTILINECOMMENT = 3 + MULTILINECOMMENTSTAR = 4 + + def __init__(self): + self.__state = CommentParser.DEFAULT + + def processChar(self, c): + if self.__state == CommentParser.DEFAULT: + if c == '/': + self.__state = CommentParser.SLASH + else: + return c + elif self.__state == CommentParser.SLASH: + if c == '/': + self.__state = CommentParser.LINECOMMENT + elif c == '*': + self.__state = CommentParser.MULTILINECOMMENT + else: + return ['/', c] + elif self.__state == CommentParser.LINECOMMENT: + if c == '\n': + self.__state = CommentParser.DEFAULT + return c + elif self.__state == CommentParser.MULTILINECOMMENT: + if c == '*': + self.__state = CommentParser.MULTILINECOMMENTSTAR + elif self.__state == CommentParser.MULTILINECOMMENTSTAR: + if c == '*': + pass + elif c == '/': + self.__state = CommentParser.DEFAULT + return ' ' + else: + self.__state = CommentParser.MULTILINECOMMENT + else: + assert False + return '' + +class ModuleParser: + DEFAULT = 0 + MODULEPREFIX = 1 + MODULEPREFIXSPACE = 2 + MODULEPREFIXNAME = 3 + MODULE = 4 + MODULESUFFIX = 5 + INWORD = 6 + MODULEINWORD = 7 + + PREFIX = 'module' + SUFFIX = 'endmodule' + + def __init__(self): + self.__state = ModuleParser.DEFAULT + self.__processed = [] + + def processChar(self, c): + if self.__state == ModuleParser.DEFAULT: + if c == ModuleParser.PREFIX[0]: + self.__processed = [c] + self.__state = ModuleParser.MODULEPREFIX + elif isIdentifierChar(c): + self.__state = ModuleParser.INWORD + return c + else: + return c + elif self.__state == ModuleParser.MODULEPREFIX: + if len(self.__processed) == len(ModuleParser.PREFIX): + if c.isspace(): + self.__state = ModuleParser.MODULEPREFIXSPACE + else: + self.__processed.append(c) + if isIdentifierChar(c): + self.__state = ModuleParser.INWORD + else: + self.__state = ModuleParser.DEFAULT + return self.__processed + else: + assert len(self.__processed) < len(ModuleParser.PREFIX) + if c == ModuleParser.PREFIX[len(self.__processed)]: + self.__processed.append(c) + else: + self.__processed.append(c) + if isIdentifierChar(c): + self.__state = ModuleParser.INWORD + else: + self.__state = ModuleParser.DEFAULT + return self.__processed + elif self.__state == ModuleParser.MODULEPREFIXSPACE: + if c.isspace(): + pass + elif isIdentifierChar(c): + self.__state = ModuleParser.MODULEPREFIXNAME + else: + assert False, [c] + elif self.__state == ModuleParser.MODULEPREFIXNAME: + if isIdentifierChar(c): + pass + else: + self.__state = ModuleParser.MODULE + elif self.__state == ModuleParser.MODULE: + if c == ModuleParser.SUFFIX[0]: + self.__processed = [c] + self.__state = ModuleParser.MODULESUFFIX + elif isIdentifierChar(c): + self.__state = ModuleParser.MODULEINWORD + elif self.__state == ModuleParser.MODULESUFFIX: + if len(self.__processed) == len(ModuleParser.SUFFIX): + if c.isspace() or c == '[': + self.__state = ModuleParser.DEFAULT + return c + else: + if isIdentifierChar(c): + self.__state = ModuleParser.MODULEINWORD + else: + self.__state = ModuleParser.MODULE + else: + assert len(self.__processed) < len(ModuleParser.SUFFIX) + if c == ModuleParser.SUFFIX[len(self.__processed)]: + self.__processed.append(c) + else: + if isIdentifierChar(c): + self.__state = ModuleParser.MODULEINWORD + else: + self.__state = ModuleParser.MODULE + elif self.__state == ModuleParser.INWORD: + if not isIdentifierChar(c): + self.__state = ModuleParser.DEFAULT + return c + elif self.__state == ModuleParser.MODULEINWORD: + if not isIdentifierChar(c): + self.__state = ModuleParser.MODULE + else: + assert False + return '' + +class AttributeParser: + DEFAULT = 0 + ATTRIBUTE = 1 + def __init__(self): + self.__state = AttributeParser.DEFAULT + + def processChar(self, c): + if self.__state == AttributeParser.DEFAULT: + if c == '[': + self.__state = AttributeParser.ATTRIBUTE + else: + return c + elif self.__state == AttributeParser.ATTRIBUTE: + if c == ']': + self.__state = AttributeParser.DEFAULT + return ' ' + else: + assert False + return '' + +class RequireParser: + DEFAULT = 0 + INWORD = 1 + INPREFIX = 2 + PREFIXSPACE = 3 + INSTRING = 4 + + PREFIX = 'require' + + def __init__(self, dependencies): + self.__state = RequireParser.DEFAULT + self.__processed = [] + self.__string_parser = StringParser() + self.__dependencies = dependencies + + def processChar(self, c): + if self.__state == RequireParser.DEFAULT: + if c == RequireParser.PREFIX[0]: + self.__processed = [c] + self.__state = RequireParser.INPREFIX + elif isIdentifierChar(c): + self.__state = RequireParser.INWORD + elif self.__state == RequireParser.INWORD: + if not isIdentifierChar(c): + self.__state = RequireParser.DEFAULT + elif self.__state == RequireParser.INPREFIX: + if len(self.__processed) == len(RequireParser.PREFIX): + if c.isspace(): + self.__state = RequireParser.PREFIXSPACE + else: + self.__string_parser.processCharImmediate(c) + if self.__string_parser.inString(): + self.__state = RequireParser.INSTRING + elif isIdentifierChar(c): + self.__state = RequireParser.INWORD + else: + assert False + else: + assert len(self.__processed) < len(RequireParser.PREFIX) + if c == RequireParser.PREFIX[len(self.__processed)]: + self.__processed.append(c) + elif isIdentifierChar(c): + self.__state = RequireParser.INWORD + else: + self.state = RequireParser.DEFAULT + elif self.__state == RequireParser.PREFIXSPACE: + if not c.isspace(): + self.__string_parser.processCharImmediate(c) + if self.__string_parser.inString(): + self.__state = RequireParser.INSTRING + else: + assert False, [c] + elif self.__state == RequireParser.INSTRING: + self.__string_parser.processCharImmediate(c) + if not self.__string_parser.inString(): + self.__dependencies.append(self.__string_parser.string()) + self.__state = RequireParser.DEFAULT + else: + assert False + return '' + + def inRequire(self): + return not self.__state in [RequireParser.DEFAULT, RequireParser.INWORD] + + def inString(self): + return self.__state == RequireParser.INSTRING + + def afterKeyword(self): + return ( + self.__state in [RequireParser.PREFIXSPACE, RequireParser.INSTRING] + or ( + self.__state == RequireParser.INPREFIX + and len(self.__processed) == len(RequireParser.PREFIX)) + ) + +def conditionalProcessAndIterate(c, skip_condition, parser, next): + if skip_condition(): + if next: + next(c) + else: + for d in parser.processChar(c): + if next: + next(d) + +def extractRequire(chars): + extracted = [] + string_parser = StringParser() + comment_parser = CommentParser() + module_parser = ModuleParser() + attribute_parser = AttributeParser() + require_parser = RequireParser(extracted) + for c in chars: + conditionalProcessAndIterate(c, lambda: string_parser.inString() or require_parser.inString(), comment_parser, + lambda d: conditionalProcessAndIterate(d, require_parser.afterKeyword, string_parser, + lambda e: conditionalProcessAndIterate(e, require_parser.inString, attribute_parser, + lambda f: conditionalProcessAndIterate(f, require_parser.inRequire, module_parser, + lambda g: conditionalProcessAndIterate(g, lambda: False, require_parser, None) + ) + ) + ) + ) + return extracted + +def printRequire(rule_name, identifying_prefix, prefix_to_add, required): + required = [r for r in required if r.startswith(identifying_prefix)] + if required: + print('%s : \\' % rule_name) + for r in required[:-1]: + print('\t%s%s \\' % (prefix_to_add, r)) + print('\t%s%s' % (prefix_to_add, required[-1])) + + +def assertEquals(expected, actual): + assert expected == actual, "Expected '%s' but got '%s'." % (expected, actual) + +def runTests(): + assertEquals([], extractRequire('')) + assertEquals(['f.k'], extractRequire('require "f.k"')) + assertEquals(['f.k'], extractRequire('require/**/"f.k"')) + assertEquals(['f.k'], extractRequire('require/*/*/"f.k"')) + assertEquals(['f.k'], extractRequire('require/***/"f.k"')) + assertEquals([], extractRequire('// require "f.k"')) + assertEquals(['f.k'], extractRequire('module m endmodule require "f.k"')) + assertEquals(['f.k'], extractRequire('module m require "g.k" endmodule require "f.k"')) + assertEquals(['f.k'], extractRequire('module m /*endmodule*/ require "g.k" endmodule require "f.k"')) + assertEquals(['f.k'], extractRequire('module m // endmodule\n require "g.k" endmodule require "f.k"')) + assertEquals(['f.k'], extractRequire('module m require "g.k/*" endmodule require "f.k"')) + assertEquals(['f.k'], extractRequire('module m endmodules require "g.k" endmodule require "f.k"')) + assertEquals(['f.k'], extractRequire('endmodule require "f.k"')) + assertEquals(['f.k'], extractRequire('module m endmodulesendmodule require "g.k" endmodule require "f.k"')) + assertEquals(['f.k'], extractRequire('module m endmodule[require "g.k"]require "f.k"')) + +USAGE = '''Wrong number of arguments, expected: +* an input file +* a Makefile rule name +* a prefix that identifies dependencies +* a prefix to be added to all dependencies. +''' + +def main(argv): + runTests() + if len(argv) != 4: + raise Exception(USAGE) + with open(argv[0], 'r') as f: + printRequire(argv[1], argv[2], argv[3], extractRequire(f.read())) + +if __name__ == '__main__': + main(sys.argv[1:]) \ No newline at end of file diff --git a/multisig/protocol-correctness/pseudocode.k b/multisig/protocol-correctness/pseudocode.k new file mode 100644 index 000000000..8fb1d8010 --- /dev/null +++ b/multisig/protocol-correctness/pseudocode.k @@ -0,0 +1,1321 @@ +module PSEUDOCODE-SYNTAX + imports INT + imports LIST + imports STRING + + syntax CodeMetadata ::= "CodeMetadata::DEFAULT" [function] + | "CodeMetadata::UPGRADEABLE" [function] + | "CodeMetadata::PAYABLE" [function] + | "CodeMetadata::READABLE" [function] + + syntax Usize ::= u(Int) // TODO: int32 + syntax BigUint ::= big(Int) // Assumes no operations on this. + syntax CodeMetadata ::= meta(Int) // Assumes no operations on this. + syntax UserRole ::= "None" | "Proposer" | "BoardMember" + syntax BoxedBytes ::= bytes(String) + syntax Address ::= address(Int) + syntax Action ::= "Nothing" + | AddBoardMember(Address) + | AddProposer(Address) + | RemoveUser(Address) + | ChangeQuorum(Usize) + | SendEgld(to: Address, amount: BigUint, data: BoxedBytes) + | SCDeploy( + amount: BigUint, + code: BoxedBytes, + codeMetadata: CodeMetadata, + arguments: ExpressionList) // list of BoxedBytes + | SCCall( + to: Address, + amount: BigUint, + function: BoxedBytes, + arguments: ExpressionList) // list of BoxedBytes + + syntax Variable ::= r"[A-Za-z_][A-Za-z_0-9]*" [token] + syntax Variable ::= "action" [token] + | "action_id" [token] + | "address" [token] + | "caller" [token] + | "caller_id" [token] + | "caller_role" [token] + | "code_metadata" [token] + | "data" [token] + | "gas_left" [token] + | "i" [token] + | "new_address" [token] + | "quorum" [token] + | "user_id" [token] + | "result" [token] + + syntax ExternalCommands ::= ExternalCommand + | ExternalCommand ExternalCommands + syntax ExternalCommand ::= "from" Address "run" EndpointCall ";" + + syntax Block ::= "{" Instructions "}" + syntax Instructions ::= Instruction + | Instruction Instructions + syntax Instruction ::= "require" "(" Expression ")" ";" + | Variable "=" Expression ";" + | "if" "(" Expression ")" Block [avoid] + | "if" "(" Expression ")" Block "else" Block [prefer] + | "for" "(" index:Variable "," value:Variable ")" "in" Expression Block + | Expression ";" + | "ok" "(" Expression ")" ";" + syntax Value ::= Usize + | "void" + | Bool + | UserRole + | Address + | BoxedBytes + | BigUint + | CodeMetadata + syntax Expression ::= FunctionCall + | Variable + | ExpressionList + | Action + | Value + | Expression "+" Expression + | Expression "-" Expression + | Expression "|" Expression + > Expression "==" Expression + | Expression "<=" Expression + | Expression ">" Expression + | "!" Expression + + syntax ExpressionCSV ::= "." + | Expression "," ExpressionCSV + + syntax ArgumentCSV ::= Expression + | Expression "," ArgumentCSV + + syntax ExpressionList ::= "[" ExpressionCSV "]" + + syntax FunctionCall ::= FunctionTag "(" ")" + | FunctionTag "(" ArgumentCSV ")" + + syntax FunctionTag ::= "proposeAction" // (action) + | "setQuorum" // (quorum) + | "setActionLastIndex" // (index) + | "setActionData" // (action_id, action) + | "setActionSignerIDs" // (action_id, signer_list) + | "setNumBoardMembers" // (usize) + | "setNumProposers" // (usize) + | "setNumUsers" // (usize) + | "setUserId" // (address, user_id) + | "setUserAddress" // (user_id, address) + | "setUserIdToRole" // (user_id, role) + | "getActionData" // (action_id) + | "getActionSignerIds" // (action_id) + | "getActionValidSignerCount" // (action_id) + | "getCaller" // () + | "getNumBoardMembers" // () + | "getNumProposers" // () + | "getNumUsers" // () + | "getOrCreateUser" // (address) + | "getUserId" // (address) + | "getUserIdToRole" // (user_id) + | "getActionLastIndex" // () + | "getQuorum" // () + | "getGasLeft" // () + | "deployContract" // (gas_left, amount, code, code_metadata, arguments) + | "userRoleCanPropose" // (user_role) + | "userRoleCanSign" // (user_role) + | "userRoleCanPerformAction" // (user_role) + | "userRoleCanDiscardAction" // (user_role) + | "listContains" // ([list], Usize) + | "listFind" // ([list], Usize) + | "listLen" // ([list]) + | "listSwapRemove" // ([list]) + | "isEmptyList" // ([list]) + | "pushList" // ([list], Usize) + | "isEmptyActionData" // (action_id) + | "canSign" // (user_id) + | "performAction" // (action) + | "performActionNoLogging" // (action) + | "performActionFromId" // (action_id) + | "quorumReached" // (action_id) + | "clearAction" // (action_id) + | "changeUserRole" // (user_id, user_role) + | "countCanSign" // ([list]) + | "sendTx" // (address, amount, data) + | "asyncCall" // (address, amount, [data]) + | EndpointTag + + syntax EndpointCall ::= EndpointTag "(" ")" + | EndpointTag "(" ArgumentCSV ")" + + syntax EndpointTag ::= "init" // (quorum, board) + | "proposeAddBoardMember" // (user_id) + | "proposeAddProposer" // (user_id) + | "proposeRemoveUser" // (user_id) + | "proposeChangeQuorum" // (quorum) + | "proposeSendEgld" // (address, amount, args) + | "proposeSCDeploy" // (amount, code, upgradeable, payable, readable, args) + | "proposeSCCall" // (to_address, amount, function, args) + | "sign" // (action_id) + | "unsign" // (action_id) + | "performActionEndpoint" // (action_id) + | "discardAction" // (action_id) + + syntax KItem ::= runExternalCalls(ExternalCommands) + syntax KItem ::= runExternalCall(ExternalCommand) + syntax KItem ::= runPseudoCode(Instructions) + syntax KItem ::= runInstruction(Instruction) + syntax KItem ::= evaluate(Expression) + syntax KItem ::= evaluateEc(ExpressionCSV) + syntax KItem ::= evaluateAc(ArgumentCSV) + +endmodule + +module PSEUDOCODE + imports PSEUDOCODE-CONFIGURATION + imports PSEUDOCODE-DETAILS + imports PSEUDOCODE-EXPRESSION + imports PSEUDOCODE-EXTERNAL + imports PSEUDOCODE-FOR + imports PSEUDOCODE-FUNCTIONS + imports PSEUDOCODE-IF + imports PSEUDOCODE-INSTRUCTIONS + imports PSEUDOCODE-MEMORY + imports PSEUDOCODE-SYNTAX +endmodule + +module PSEUDOCODE-TYPE-REFLECTION + imports MAYBE + imports PSEUDOCODE-COMMON + imports PSEUDOCODE-SYNTAX + + syntax ReflectionType ::= "rUsize" + | "rUserRole" + | "rExpressionList" + | "rBool" + | "rAction" + | "rAddress" + | "rBoxedBytes" + | "rBigUint" + | "rCodeMetadata" + + syntax KItem ::= cast(KItem, ReflectionType) [strict(1)] + + /* + rule cast(nothing, _:ReflectionType) => nothing + rule cast(just(K:KItem) => K, _:ReflectionType) + */ + + rule cast(value(K:KItem) => K, _:ReflectionType) [label(castValue)] + + rule cast(U:Usize, rUsize) => U [label(castUsize)] + rule (.K => stuck) ~> cast(V:KItem, rUsize) + ensures notBool isUsize(V) + [owise, label(castUsizeStuck)] + + rule cast(U:UserRole, rUserRole) => U [label(castUserRole)] + rule (.K => stuck) ~> cast(V:KItem, rUserRole) + ensures notBool isUserRole(V) + [owise, label(castUserRoleStuck)] + + rule cast(V:ExpressionList, rExpressionList) => V [label(castExpressionList)] + rule (.K => stuck) ~> cast(V:KItem, rExpressionList) + ensures notBool isExpressionList(V) + [owise, label(castExpressionListStuck)] + + rule cast(A:Action, rAction) => A [label(castAction)] + rule (.K => stuck) ~> cast(V:KItem, rAction) + ensures notBool isAction(V) + [owise, label(castActionStuck)] + + rule cast(A:Address, rAddress) => A [label(castAddress)] + rule (.K => stuck) ~> cast(V:KItem, rAddress) + ensures notBool isAddress(V) + [owise, label(castAddressStuck)] + + syntax KItem ::= defaultValue(ReflectionType) [function, functional] + rule defaultValue(rUsize) => u(0) + rule defaultValue(rUserRole) => None + rule defaultValue(rExpressionList) => [.] + rule defaultValue(rBool) => false + rule defaultValue(rAction) => Nothing + rule defaultValue(rAddress) => address(0) + rule defaultValue(rBoxedBytes) => bytes("") + rule defaultValue(rBigUint) => big(0) + rule defaultValue(rCodeMetadata) => CodeMetadata::DEFAULT + + syntax Bool ::= isDefaultValue(KItem, ReflectionType) [function, functional] + rule isDefaultValue(K:KItem, T:ReflectionType) => K ==K defaultValue(T) + [owise] // allow overriding + + syntax Bool ::= valueOfType(KItem, ReflectionType) [function, functional] + rule valueOfType(V:KItem, rUsize) => isUsize(V) + rule valueOfType(V:KItem, rUserRole) => isUserRole(V) + rule valueOfType(V:KItem, rExpressionList) => isExpressionList(V) + rule valueOfType(V:KItem, rBool) => isBool(V) + rule valueOfType(V:KItem, rAction) => isAction(V) + rule valueOfType(V:KItem, rAddress) => isAddress(V) + rule valueOfType(V:KItem, rBoxedBytes) => isBoxedBytes(V) + rule valueOfType(V:KItem, rBigUint) => isBigUint(V) + rule valueOfType(V:KItem, rCodeMetadata) => isCodeMetadata(V) +endmodule + +module PSEUDOCODE-INSTRUCTIONS + imports PSEUDOCODE-COMMON + imports PSEUDOCODE-CONFIGURATION + imports PSEUDOCODE-SYNTAX + + rule runPseudoCode(I:Instruction) => runInstruction(I) + rule runPseudoCode(I:Instruction Is:Instructions) + => runInstruction(I) ~> runPseudoCode(Is) + + rule error ~> (runPseudoCode(_) => .K) ... + rule error => .K + .stack + + rule runInstruction(E:Expression;) => evaluate(E) + rule (evaluate(E:Expression) => .K) ~> runInstruction(_) + requires isKResult(E) + rule (evaluate(E:Expression) => .K) ~> runPseudoCode(_) + requires isKResult(E) + + context runInstruction(require({HOLE:Expression => evaluate(HOLE)}:>Expression);) + rule runInstruction(require(true);) => evaluate(void) + rule runInstruction(require(false);) => error +endmodule + +module PSEUDOCODE-EXTERNAL + imports PSEUDOCODE-COMMON + imports PSEUDOCODE-CONFIGURATION + imports PSEUDOCODE-SYNTAX + + rule runExternalCalls(C:ExternalCommand) => runExternalCall(C) + rule runExternalCalls(C:ExternalCommand Cs:ExternalCommands) + => runExternalCall(C) ~> runExternalCalls(Cs) + + syntax KItem ::= "clearExternalCallEnv" + rule clearExternalCallEnv => .K ... + _ => uninitialized + + rule (evaluate(E:Expression) => .K) ~> clearExternalCallEnv + requires isKResult(E) + + rule (E:Expression => .K) ~> clearExternalCallEnv + requires isKResult(E) + + rule (error => .K) ~> clearExternalCallEnv ... + + syntax KItem ::= endpointToInstruction(EndpointCall) + rule endpointToInstruction(Tag:EndpointTag()) => runInstruction(Tag();) + rule endpointToInstruction(Tag:EndpointTag(Es:ArgumentCSV)) => runInstruction(Tag(Es);) + + rule + runExternalCall(from A:Address run Call:EndpointCall;) + => endpointToInstruction(Call) ~> clearExternalCallEnv + ... + uninitialized => A + +endmodule + +module PSEUDOCODE-MEMORY + imports MAP-UTILS + imports PSEUDOCODE-COMMON + imports PSEUDOCODE-CONFIGURATION + imports PSEUDOCODE-SYNTAX + + context runInstruction(_:Variable = {HOLE => evaluate(HOLE)}:>Expression;) + + rule (runInstruction(V:Variable = E:Expression;) => evaluate(void)) ... + M:Map => M[V <- E] + requires isKResult(E) + + rule evaluate(V:Variable => {M[V]}:>Expression) ... + M:Map + requires V in_keys(M) +endmodule + +module PSEUDOCODE-FOR + imports PSEUDOCODE-COMMON + imports PSEUDOCODE-SYNTAX + + syntax Instruction ::= "for" "(" indexVar:Variable "=" value:Usize "," valueVar:Variable ")" "in" ExpressionList Block + + context runInstruction(for(_:Variable, _:Variable) in {HOLE:Expression => evaluate(HOLE)}:>Expression _:Block) + rule runInstruction(for(Index:Variable, Value:Variable) in (L:ExpressionList) B:Block) + => runInstruction(for(Index = u(0), Value) in L B) + requires isKResult(L) + + rule runInstruction(for(_:Variable = _:Usize, _:Variable) in [.] _:Block) + => evaluate(void) + rule runInstruction( + for (IndexVar:Variable = u(Index:Int), ValueVar:Variable) + in [E:Expression, Es:ExpressionCSV] + {B:Instructions} + ) + => runPseudoCode(IndexVar = u(Index); ValueVar = E; B) + ~> runInstruction(for(IndexVar = u(Index +Int 1), ValueVar) in [Es:ExpressionCSV] {B}) +endmodule + +module PSEUDOCODE-IF + imports PSEUDOCODE-COMMON + imports PSEUDOCODE-SYNTAX + + context runInstruction(if({HOLE:Expression => evaluate(HOLE)}:>Expression) _:Block) + context runInstruction(if({HOLE:Expression => evaluate(HOLE)}:>Expression) _:Block else _:Block) + + rule runInstruction(if(true) {Is:Instructions}) => runPseudoCode(Is) + rule runInstruction(if(false) _:Block) => evaluate(void) + + rule runInstruction(if(true) {Is:Instructions} else _:Block) => runPseudoCode(Is) + rule runInstruction(if(false) _:Block else {Is:Instructions}) => runPseudoCode(Is) +endmodule + +module PSEUDOCODE-EXPRESSION + imports PSEUDOCODE-COMMON + imports PSEUDOCODE-SYNTAX + + rule add(u(A:Int), u(B:Int)) => u(A +Int B) + rule sub(u(A:Int), u(B:Int)) => u(A -Int B) + + context evaluate(! {HOLE:Expression => evaluate(HOLE)}:>Expression) + rule evaluate((! false) => true) + rule evaluate((! true) => false) + + context evaluate({HOLE:Expression => evaluate(HOLE)}:>Expression <= _:Expression) + context evaluate(A:Expression <= {HOLE:Expression => evaluate(HOLE)}:>Expression) requires isKResult(A) + rule evaluate((u(A:Int) <= u(B:Int)) => (A <=Int B)) + + context evaluate({HOLE:Expression => evaluate(HOLE)}:>Expression > _:Expression) + context evaluate(A:Expression > {HOLE:Expression => evaluate(HOLE)}:>Expression) requires isKResult(A) + rule evaluate((u(A:Int) > u(B:Int)) => (A >Int B)) + + context evaluate({HOLE:Expression => evaluate(HOLE)}:>Expression == _:Expression) + context evaluate(A:Expression == {HOLE:Expression => evaluate(HOLE)}:>Expression) requires isKResult(A) + rule evaluate((A:Expression == B:Expression) => (A ==K B)) + requires isKResult(A) andBool isKResult(B) + + context evaluate({HOLE:Expression => evaluate(HOLE)}:>Expression + _:Expression) + context evaluate(A:Expression + {HOLE:Expression => evaluate(HOLE)}:>Expression) requires isKResult(A) + rule evaluate(A:Usize + B:Usize => add(A, B)) + + context evaluate({HOLE:Expression => evaluate(HOLE)}:>Expression - _:Expression) + context evaluate(A:Expression - {HOLE:Expression => evaluate(HOLE)}:>Expression) requires isKResult(A) + rule evaluate(A:Usize - B:Usize => sub(A, B)) + + context evaluate({HOLE:Expression => evaluate(HOLE)}:>Expression | _:Expression) + context evaluate(A:Expression | {HOLE:Expression => evaluate(HOLE)}:>Expression) requires isKResult(A) + rule evaluate((u(A:Int) | u(B:Int)) => u(A |Int B)) + rule evaluate((meta(A:Int) | meta(B:Int)) => meta(A |Int B)) + + context evaluate([{HOLE:ExpressionCSV => evaluateEc(HOLE)}:>ExpressionCSV]) +endmodule + +module PSEUDOCODE-COMMON + imports MAP + imports PSEUDOCODE-SYNTAX + + syntax KResult ::= Value + + rule CodeMetadata::DEFAULT => meta(0) + rule CodeMetadata::UPGRADEABLE => meta(1 < meta(1 < meta(1 < removeValue) => .K + requires isKResult(E) + + syntax Stack ::= ".stack" + syntax Stack ::= stack(MultisigStateCell, variables:Map, performedActions:List, next:Stack) +endmodule + +module PSEUDOCODE-DETAILS + imports PSEUDOCODE-COMMON + imports PSEUDOCODE-SYNTAX + + context evaluateAc({HOLE:Expression => evaluate(HOLE)}:>ArgumentCSV) + context evaluateAc({HOLE:Expression => evaluate(HOLE)}:>Expression , _:ArgumentCSV) + context evaluateAc(E:Expression , {HOLE:ArgumentCSV => evaluateAc(HOLE)}:>ArgumentCSV) + requires isKResult(E) + + context evaluateEc({HOLE:Expression => evaluate(HOLE)}:>Expression , _:ExpressionCSV) + context evaluateEc(E:Expression , {HOLE:ExpressionCSV => evaluateEc(HOLE)}:>ExpressionCSV) + requires isKResult(E) + + rule isKResult(E:Expression , Es:ArgumentCSV) => isKResult(E) andBool isKResult(Es) + + rule isKResult(.:ExpressionCSV) => true + rule isKResult(E:Expression , Es:ExpressionCSV) => isKResult(E) andBool isKResult(Es) + + rule isKResult([Es:ExpressionCSV]) => isKResult(Es) + + rule isKResult(A:Action) => isKResultAction(A) + + syntax Bool ::= isKResultAction(Action) [function, functional] + + rule isKResultAction(Nothing) => true + rule isKResultAction(AddBoardMember(A:Address)) => isKResult(A) + rule isKResultAction(AddProposer(A:Address)) => isKResult(A) + rule isKResultAction(RemoveUser(A:Address)) => isKResult(A) + rule isKResultAction(ChangeQuorum(U:Usize)) => isKResult(U) + rule isKResultAction(SendEgld(To:Address, Amount:BigUint, Data:BoxedBytes)) + => isKResult(To) andBool isKResult(Amount) andBool isKResult(Data) + rule isKResultAction(SCDeploy( + Amount:BigUint, + Code:BoxedBytes, + CodeMetadata:CodeMetadata, + Arguments:ExpressionList)) + => isKResult(Amount) + andBool isKResult(Code) + andBool isKResult(CodeMetadata) + andBool isKResult(Arguments) + rule isKResultAction(SCCall( + To:Address, + Amount:BigUint, + Function:BoxedBytes, + Arguments:ExpressionList)) + => isKResult(To) + andBool isKResult(Amount) + andBool isKResult(Function) + andBool isKResult(Arguments) +endmodule + +module PSEUDOCODE-FUNCTIONS + imports BOOL + imports MAP + + imports MAP-UTILS + imports PSEUDOCODE-COMMON + imports PSEUDOCODE-CONFIGURATION + imports PSEUDOCODE-MAP-UTILS + imports PSEUDOCODE-SYNTAX + imports PSEUDOCODE-TYPE-REFLECTION + + syntax KResult + + syntax KItem ::= "pushContext" | "popContext" | "evaluateReturnValue" | "preCall" + syntax KItem ::= stuck(KItem) + syntax KItem ::= call(Expression) + syntax KItem ::= Expression + + context evaluate(_:FunctionTag( + {HOLE => evaluateAc(HOLE)}:>ArgumentCSV + )) + + rule evaluate(_:FunctionTag(Args:ArgumentCSV) #as FunctionCall) + => (pushContext ~> preCall ~> call(FunctionCall) ~> popContext ~> evaluateReturnValue) + ... + requires isKResult(Args) + rule evaluate(_:FunctionTag() #as FunctionCall) + => (pushContext ~> preCall ~> call(FunctionCall) ~> popContext ~> evaluateReturnValue) + ... + + rule preCall => .K + + rule pushContext => .K ... + + S:MultisigStateCell + + V:Map => .Map + Stack:Stack => stack(S, V, Log, Stack) + + _:ExternalCallEnvCell + + Log:List + + + + rule (evaluate(E:Expression) => E) ~> popContext ... + requires isKResult(E) + + rule E:Expression ~> (popContext => .K) ... + _ => V + stack(_, V:Map, _, Stack:Stack) => Stack + requires isKResult(E) + + rule (E:Expression ~> evaluateReturnValue) => evaluate(E) ... + requires isKResult(E) + + rule error ~> (popContext => .K) ... + + (_ => S) + + _ => V + stack(S:MultisigStateCell, V:Map, Log:List, Stack:Stack) => Stack + + _:ExternalCallEnvCell + + _:List => Log + + + + rule error ~> (evaluateReturnValue => .K) ... + + context runInstruction(ok({HOLE:Expression => evaluate(HOLE)}:>Expression);) + rule runInstruction(ok(E:Expression);) => E requires isKResult(E) + + rule call(init(Quorum:Usize, Board:ExpressionList)) => + runPseudoCode( + require(!isEmptyList(Board)); + require(Quorum <= listLen(Board)); + setQuorum(Quorum); + for (i, address) in Board { + user_id = i + u(1); + require(getUserId(address) == u(0)); + setUserId(address, user_id); + setUserAddress(user_id, address); + setUserIdToRole(user_id, BoardMember); + } + setNumUsers(listLen(Board)); + setNumBoardMembers(listLen(Board)); + ok(void); + ) + + rule call(proposeAddBoardMember(Member:Address)) => + runPseudoCode( + proposeAction(AddBoardMember(Member)); + ) + + rule call(proposeAddProposer(Member:Address)) => + runPseudoCode( + proposeAction(AddProposer(Member)); + ) + + rule call(proposeRemoveUser(Member:Address)) => + runPseudoCode( + proposeAction(RemoveUser(Member)); + ) + + rule call(proposeChangeQuorum(Quorum:Usize)) => + runPseudoCode( + proposeAction(ChangeQuorum(Quorum)); + ) + + rule call(proposeSendEgld(To:Address, Amount:BigUint)) => + runPseudoCode( + proposeAction(SendEgld(To, Amount, bytes(""))); + ) + + rule call(proposeSendEgld(To:Address, Amount:BigUint, Data:BoxedBytes)) => + runPseudoCode( + proposeAction(SendEgld(To, Amount, Data)); + ) + + rule call(proposeSCDeploy( + Amount:BigUint, + Code:BoxedBytes, + Upgradeable:Bool, + Payable:Bool, + Readable:Bool, + Args:ExpressionList)) => + runPseudoCode( + code_metadata = CodeMetadata::DEFAULT; + if (Upgradeable) { + code_metadata = code_metadata | CodeMetadata::UPGRADEABLE; + } + if (Payable) { + code_metadata = code_metadata | CodeMetadata::PAYABLE; + } + if (Readable) { + code_metadata = code_metadata | CodeMetadata::READABLE; + } + proposeActionSCDeploy(Amount, Code, code_metadata, Args); + ) + + syntax FunctionTag ::= "proposeActionSCDeploy" + rule call(proposeActionSCDeploy(Amount:BigUint, Code:BoxedBytes, CodeMetadata:CodeMetadata, Args:ExpressionList)) + => runPseudoCode(proposeAction(SCDeploy(Amount, Code, CodeMetadata, Args));) + + rule call(proposeSCCall(To:Address, Amount:BigUint, Function:BoxedBytes, Args:ExpressionList)) => + runPseudoCode( + proposeAction(SCCall(To, Amount, Function, Args)); + ) + + rule call(sign(ActionId:Usize)) => + runPseudoCode( + require(!isEmptyActionData(ActionId)); + caller_address = getCaller(); + caller_id = getUserId(caller_address); + caller_role = getUserIdToRole(caller_id); + require(canSign(caller_role)); + + signer_ids = getActionSignerIds(ActionId); + if (!listContains(signer_ids, caller_id)) { + signer_ids = pushList(signer_ids, caller_id); + setActionSignerIDs(ActionId, signer_ids); + } + + ok(void); + ) + + rule call(unsign(ActionId:Usize)) => + runPseudoCode( + require(!isEmptyActionData(ActionId)); + + caller_address = getCaller(); + caller_id = getUserId(caller_address); + caller_role = getUserIdToRole(caller_id); + require(canSign(caller_role)); + + signer_ids = getActionSignerIds(ActionId); + signer_pos = listFind(signer_ids, caller_id); + if (u(0) <= signer_pos) { + signer_ids = listSwapRemove(signer_ids, signer_pos); + setActionSignerIDs(ActionId, signer_ids); + } + + ok(void); + ) + + rule call(proposeAction(A:Action)) + => runPseudoCode( + caller = getCaller(); + caller_id = getUserId(caller); + caller_role = getUserIdToRole(caller_id); + require(userRoleCanPropose(caller_role)); + action_id = getActionLastIndex() + u(1); + setActionLastIndex(action_id); + setActionData(action_id, A); + if (userRoleCanSign(caller_role)) { + setActionSignerIDs(action_id, [caller_id, .]); // TODO + } + ok(action_id); + ) + + rule call(performActionEndpoint(ActionId:Usize)) + => runPseudoCode( + caller_address = getCaller(); + caller_id = getUserId(caller_address); + caller_role = getUserIdToRole(caller_id); + require(userRoleCanPerformAction(caller_role)); + require(quorumReached(ActionId)); + performActionFromId(ActionId); + ) + + rule call(discardAction(ActionId:Usize)) + => runPseudoCode( + caller_address = getCaller(); + caller_id = getUserId(caller_address); + caller_role = getUserIdToRole(caller_id); + require(userRoleCanDiscardAction(caller_role)); + require(getActionValidSignerCount(ActionId) == u(0)); + clearAction(ActionId); + ok(void); + ) + + rule call(userRoleCanPropose(None)) => false [label(userRoleCanProposeNone)] + rule call(userRoleCanPropose(Proposer)) => true [label(userRoleCanProposeProposer)] + rule call(userRoleCanPropose(BoardMember)) => true [label(userRoleCanProposeBoardMember)] + + rule call(userRoleCanSign(None)) => false + rule call(userRoleCanSign(Proposer)) => false + rule call(userRoleCanSign(BoardMember)) => true + + rule call(userRoleCanPerformAction(R:UserRole) => userRoleCanPropose(R)) + + rule call(userRoleCanDiscardAction(R:UserRole) => userRoleCanPropose(R)) + + rule call(isEmptyList([.])) => true + rule call(isEmptyList(_:ExpressionList)) => false [owise] + + rule call(listLen([.])) => u(0) + rule call(listLen([_:Expression , Es:ExpressionCSV])) + => call(listLen([Es])) ~> plusOne + + syntax KItem ::= "plusOne" + rule (I:Usize ~> plusOne) => add(I, u(1)) + + rule call(setQuorum(Quorum:Usize)) => void ... + _ => Quorum + + rule call(setNumUsers(Users:Usize)) => void ... + _ => Users + + rule call(setNumBoardMembers(Members:Usize)) => void ... + _ => Members + + rule call(setNumProposers(Proposers:Usize)) => void ... + _ => Proposers + + rule (.K => nullableMapSet(E, I, M, rUsize)) ~> call(setUserId(E:Expression, I:Usize)) ... + M:Map + rule (M:Map ~> call(setUserId(_:Expression, _:Usize))) => void ... + _:Map => M + + rule (.K => mapSet(I, E, M)) ~> call(setUserAddress(I:Usize, E:Expression)) ... + M:Map + rule (M:Map ~> call(setUserAddress(_:Usize, _:Expression))) => void ... + _:Map => M + + rule (.K => nullableMapSet(I, R, M, rUserRole)) ~> call(setUserIdToRole(I:Usize, R:UserRole)) ... + M:Map + rule (M:Map ~> call(setUserIdToRole(_:Usize, _:UserRole))) => void ... + _:Map => M + + rule call(getCaller()) => A ... + A:Address + + rule call(getQuorum()) => Quorum ... + Quorum:Usize + + rule call(getUserId(A:Expression)) + => cast(A, rAddress) + ~> removeValue + ~> nullableMapLookup(A, M, rUsize) + ... + M:Map + + rule call(getUserIdToRole(I:Usize)) => nullableMapLookup(I, M, rUserRole) ... + M:Map + + rule call(getActionLastIndex()) => Index ... + Index:Usize + + rule call(setActionLastIndex(Index:Usize)) => void ... + _ => Index + + rule call(getNumUsers()) => Users ... + Users:Usize + + rule call(getNumBoardMembers()) => Members ... + Members:Usize + + rule call(getNumProposers()) => Proposers ... + Proposers:Usize + + rule (.K => nullableMapSet(ActionId, A, M, rAction)) ~> call(setActionData(ActionId:Usize, A:Action)) ... + M:Map + rule (M:Map ~> call(setActionData(_:Usize, _:Action))) => void ... + _:Map => M + + rule call(getActionData(ActionId:Usize)) => nullableMapLookup(ActionId, M, rAction) ... + M:Map + + rule (.K => nullableMapSet(ActionId, Signers, M, rExpressionList)) + ~> call(setActionSignerIDs(ActionId:Usize, Signers:ExpressionList)) + ... + M:Map + + rule (M:Map ~> call(setActionSignerIDs(_:Usize, _:ExpressionList))) => void ... + _:Map => M + + rule (.K => call(getActionData(ActionId))) ~> call(isEmptyActionData(ActionId:Usize)) ... + rule Action:Action ~> call(isEmptyActionData(_:Usize)) => Action ==K Nothing + + rule call(canSign(BoardMember)) => true + rule call(canSign(_)) => false [owise] + + rule call(getActionSignerIds(ActionId:Usize)) + => nullableMapLookup(ActionId, M:Map, rExpressionList) + ... + M:Map + + rule call(listContains(Es:ExpressionList, E:Expression)) => #listContains(Es, E) + + syntax Bool ::= #listContains(ExpressionList, KItem) [function, functional] + + rule #listContains([.], _) => false + rule #listContains([E:Expression, _:ExpressionCSV], E) => true + rule #listContains([_:Expression, Es:ExpressionCSV], X:KItem) + => #listContains([Es], X) [owise] + + rule call(listFind(Es:ExpressionList, E:Expression)) => u(#listFind(Es, E)) + + syntax Int ::= #listFind(ExpressionList, Expression) [function, functional] + + rule #listFind([.], _:Expression) => -1 + rule #listFind([X:Usize, _:ExpressionCSV], X) => 0 + rule #listFind([_:Usize, Es:ExpressionCSV], X:Usize) => addOneIfNotNegative(#listFind([Es], X)) + [owise] + + syntax Int ::= addOneIfNotNegative(Int) [function, functional] + rule addOneIfNotNegative(X:Int) => X +Int 1 + requires X >=Int 0 + rule addOneIfNotNegative(X) => X + requires X 0 + rule pListLen([_:Expression, Es:ExpressionCSV]) => 1 +Int pListLen([Es]) + + rule call(listSwapRemove([L:ExpressionCSV], u(I:Int))) + => [#listSwapRemove(L, I)] + // TODO: Do things work with this requires? + requires I >=Int 0 + + syntax ExpressionCSV ::= #listSwapRemove(ExpressionCSV, Int) [function, functional] + rule #listSwapRemove(_:Expression , Es:ExpressionCSV, 0) + => lastToStart(Es) + rule #listSwapRemove(E:Expression , Es:ExpressionCSV, I:Int) + => E , #listSwapRemove(Es, I -Int 1) + requires I >Int 0 + rule #listSwapRemove(Es:ExpressionCSV, I:Int) + => Es + requires I .:ExpressionCSV + rule lastToStart(Es:ExpressionCSV) => last(Es), removeLast(Es) + requires pListLen([Es]) >Int 0 + + syntax Expression ::= last(ExpressionCSV) [function] + rule last(E:Expression, .) => E + rule last(_:Expression, Es:ExpressionCSV) => last(Es) + requires pListLen([Es]) >Int 0 + + rule #Ceil(last(@Es:ExpressionCSV)) + => {pListLen([@Es]) >Int 0 #Equals true} + #And #Ceil(@Es) + [anywhere, simplification] + + syntax ExpressionCSV ::= removeLast(ExpressionCSV) [function] + rule removeLast(_:Expression, .) => .:ExpressionCSV + rule removeLast(E:Expression, Es:ExpressionCSV) => E, removeLast(Es) + requires pListLen([Es]) >Int 0 + + rule #Ceil(removeLast(@Es:ExpressionCSV)) + => {pListLen([@Es]) >Int 0 #Equals true} + #And #Ceil(@Es) + [anywhere, simplification] + + // rule lastToStart(L1:ExpressionCSV, (E:Expression, .)) + // => E , reverseExpressionCsv(L1, .) + // rule lastToStart(L1:ExpressionCSV, (E:Expression , L2:ExpressionCSV)) + // => lastToStart((E , L1), L2) + + syntax ExpressionCSV ::= reverseExpressionCsv(ExpressionCSV, ExpressionCSV) [function, functional] + rule reverseExpressionCsv(., L2:ExpressionCSV) => L2 + rule reverseExpressionCsv((E:Expression , Es:ExpressionCSV), L2:ExpressionCSV) => reverseExpressionCsv(Es, (E , L2)) + + rule call(performActionFromId(ActionId:Usize)) + => runPseudoCode( + action = getActionData(ActionId); + clearAction(ActionId); + performAction(action); + + ) + + rule call(performAction(Action:Action)) + => call(performActionNoLogging(Action)) + ... + Log:List => ListItem(Action) Log + + rule call(performActionNoLogging(Nothing)) => evaluate(void) + + rule call(performActionNoLogging(AddBoardMember(BoardMemberAddress:Address))) + => runPseudoCode( + changeUserRole(BoardMemberAddress, BoardMember); + ) + + rule call(performActionNoLogging(AddProposer(ProposerAddress:Address))) + => runPseudoCode( + changeUserRole(ProposerAddress, Proposer); + new_board_members = getNumBoardMembers(); + require(getQuorum() <= new_board_members); + ) + + rule call(performActionNoLogging(RemoveUser(UserAddress:Address))) + => runPseudoCode( + changeUserRole(UserAddress, None); + num_board_members = getNumBoardMembers(); + num_proposers = getNumProposers(); + require(num_board_members + num_proposers > u(0)); + require(getQuorum() <= num_board_members); + ) + + rule call(performActionNoLogging(ChangeQuorum(NewQuorum))) + => runPseudoCode( + require(NewQuorum <= getNumBoardMembers()); + setQuorum(NewQuorum); + ) + + rule call(performActionNoLogging(SendEgld(To:Address, Amount:BigUint, Data:BoxedBytes))) + => runPseudoCode( + sendTx(To, Amount, Data); + ) + + rule call(performActionNoLogging(SCDeploy( + Amount:BigUint, + Code:BoxedBytes, + CodeMetadata:CodeMetadata, + Arguments:ExpressionList))) + => runPseudoCode( + gas_left = getGasLeft(); + new_address = deployContract(gas_left, Amount, Code, CodeMetadata, Arguments); + [new_address, .]; + void; + ) + + rule call(performActionNoLogging(SCCall(To:Address, Amount:BigUint, Function:BoxedBytes, [Arguments:ExpressionCSV]))) + => runPseudoCode( + asyncCall(To, Amount, [Function , Arguments]); + ) + + rule call(clearAction(ActionId:Usize)) + => runPseudoCode( + setActionData(ActionId, Nothing); + setActionSignerIDs(ActionId, [.]); + ) + + rule call(quorumReached(ActionId:Usize)) + => runPseudoCode( + quorum = getQuorum(); + valid_signers_count = getActionValidSignerCount(ActionId); + quorum <= valid_signers_count; + ) + + rule call(getActionValidSignerCount(ActionId:Usize)) + => runPseudoCode( + signer_ids = getActionSignerIds(ActionId); + countCanSign(signer_ids); + ) + + rule call(countCanSign([.])) => evaluate(u(0)) + rule call(countCanSign([SignerId:Usize , SignerIds:ExpressionCSV])) + => runPseudoCode( + result = u(0); + user_role = getUserIdToRole(SignerId); + if (userRoleCanSign(user_role)) { + result = u(1); + } + result + countCanSign([SignerIds]); + ) + rule (.K => stuck) ~> call(countCanSign([E:Expression , _:ExpressionCSV])) + ensures notBool isUsize(E) + [owise] + + rule call(changeUserRole(UserAddress:Address, NewRole:UserRole)) + => runPseudoCode( + user_id = getOrCreateUser(UserAddress); + old_role = None; + if (!(user_id == u(0))) { + old_role = getUserIdToRole(user_id); + } + setUserIdToRole(user_id, NewRole); + + if (old_role == BoardMember) { + if (!(NewRole == BoardMember)) { + new_board_members = getNumBoardMembers() - u(1); + setNumBoardMembers(new_board_members); + } + } else { + if (NewRole == BoardMember) { + setNumBoardMembers(getNumBoardMembers() + u(1)); + } + } + + if (old_role == Proposer) { + if (!(NewRole == Proposer)) { + setNumProposers(getNumProposers() - u(1)); + } + } else { + if (NewRole == Proposer) { + setNumProposers(getNumProposers() + u(1)); + } + } + ) + + rule call(getOrCreateUser(Address:Address)) + => runPseudoCode( + user_id = getUserId(Address); + if (user_id == u(0)) { + num_users = getNumUsers(); + num_users = num_users + u(1); + setNumUsers(num_users); + user_id = num_users; + setUserId(Address, user_id); + setUserAddress(user_id, Address); + } + user_id; + ) + + rule call(pushList([Es:ExpressionCSV], E:Expression)) + => [#pushList(Es, E)] + + syntax ExpressionCSV ::= #pushList(ExpressionCSV, Expression) + [function, functional] + + rule #pushList(., E:Expression) + => E, . + rule #pushList(E:Expression , Es:ExpressionCSV, E2:Expression) + => prepend(#pushList(Es, E2), E) + + syntax ExpressionCSV ::= prepend(ExpressionCSV, Expression) + [function, functional] + rule prepend(Es:ExpressionCSV, E:Expression) => E , Es + + rule call(sendTx(_To:Address, _Amount:BigUint, _Data:BoxedBytes)) + => evaluate(void) + + rule call(getGasLeft()) => evaluate(u(-1)) + + rule call(deployContract( + _GasLeft:Usize, + _Amount:BigUint, + _Code:BoxedBytes, + _:CodeMetadata, + Arguments:ExpressionList)) + => evaluate(void) + requires isKResult(Arguments) + + rule call(asyncCall( + _:Address, + _Amount:BigUint, + Arguments:ExpressionList)) + => evaluate(void) + requires isKResult(Arguments) + +endmodule + +module MAYBE + syntax Maybe ::= just(KItem) | "nothing" + syntax KItem ::= Maybe + + syntax KItem ::= value(KItem) + rule isKResult(value(K:KItem) => K) + + syntax KResult ::= Maybe + + syntax KItem ::= orElse(KItem, KItem) [strict(1)] + rule orElse(nothing, K:KItem) => value(K) + rule orElse(just(K:KItem), _:KItem) => value(K) +endmodule + +module MAP-UTILS + imports BOOL + imports K-EQUAL + imports MAP + imports MAYBE + imports PSEUDOCODE-COMMON + + syntax KItem ::= splitMap(key:KItem, toSplit:Map, value:KItem, remainder:Map) + [function, functional] + syntax KItem ::= "endSplitMap" + rule endSplitMap => .K + + rule splitMap(Key:KItem, M:Map, _Value:KItem, _Remainder:Map) => stuck + requires notBool Key in_keys(M) + rule splitMap(Key:KItem, (Key |-> _:KItem) _:Map, _Value:KItem, _Remainder:Map) + => endSplitMap + [simplification(30)] + rule splitMap(Key:KItem, (K1:KItem |-> _SomeValue:KItem) M:Map, Value:KItem, Remainder:Map) + => splitMap(Key, M, Value, Remainder) + requires notBool (Key ==K K1) andBool Key in_keys(M) + [simplification(30)] + rule splitMap(Key:KItem, M:Map, Value:KItem, Remainder:Map) + => endSplitMap + requires Key in_keys(M) + ensures M ==K (Key |-> Value Remainder) + [simplification(50)] + + /* + syntax Map ::= splitMap(key:KItem, Map, Map) [function, functional] + + rule splitMap(K:KItem, (K |-> _:KItem _:Map) #as _:Map, M:Map) + => M + [simplification] + rule splitMap(K:KItem, (K1 |-> _ M:Map) #as _:Map, N:Map) + => splitMap(K, M, N) + requires notBool (K ==K K1) + [simplification] + rule splitMap(K:KItem, M:Map, N:Map) + => + ( + (#Ceil(M #And (K |-> ?_:KItem ?_:Map))) + #And + {true #Equals (K in_keys(M))} + #And N + ) + #Or (N #And {true #Equals (notBool (K in_keys(M)))}) + + rule splitMap(K:KItem, M:Map, N:Map) + =>( + ( + (#Ceil(M #And (K |-> ?_:KItem ?_:Map))) + #And + {true #Equals (K in_keys(M))} + ) + #Or + ({true #Equals (notBool (K in_keys(M)))}) + ) + #And N + + + rule splitMap(K:KItem, M:Map, N:Map) => N + ensures + ( + ( + (#Ceil(M #And (K |-> ?_:KItem ?_:Map))) + #And + {true #Equals (K in_keys(M))} + ) + #Or + ({true #Equals (notBool (K in_keys(M)))}) + ) + + + + */ + + // Do the map lookups in a way that makes the Haskell backend happy. + + syntax KItem ::= mapLookup(KItem, Map) + rule mapLookup(K:KItem, M:Map) + => splitMap(K, M, ?_Value:KItem, ?_Remainder:Map) + ~> #mapLookup(K, M) + requires K in_keys(M) + [label(mapLookupInKeys)] + rule mapLookup(K:KItem, M:Map) + => nothing + requires notBool K in_keys(M) + [label(mapLookupNotInKeys)] + /* + rule mapLookup(K:KItem, M:Map) => #mapLookup(K, splitMap(K, M, M)) + */ + + syntax KItem ::= #mapLookup(KItem, Map) + rule #mapLookup(K:KItem, ((K |-> V:KItem) _:Map) #as M:Map) => just(V) + ensures K in_keys(M) + rule #mapLookup(K:KItem, M:Map) => nothing + ensures notBool (K in_keys(M)) + [owise] + + syntax KItem ::= mapDelete(key:KItem, Map) + rule mapDelete(K:KItem, M:Map) => #mapDelete(K, M) + requires K in_keys(M) + rule mapDelete(K:KItem, M:Map) => M + requires notBool (K in_keys(M)) + + syntax KItem ::= #mapDelete(key:KItem, Map) + rule #mapDelete(K:KItem, (K |-> _:KItem) M:Map) => M + rule #mapDelete(_:KItem, M:Map) => M + ensures false + [owise] + + syntax KItem ::= mapSet(key:KItem, value:KItem, Map) + rule mapSet(K:KItem, V:KItem, M:Map) => #mapSet(K, V, M) + requires K in_keys(M) + rule mapSet(K:KItem, V:KItem, M:Map) => K |-> V M + requires notBool (K in_keys(M)) + + syntax KItem ::= #mapSet(key:KItem, value:KItem, Map) + rule #mapSet(K:KItem, V:KItem, (K |-> _:KItem) M:Map) => K |-> V M + rule #mapSet(_:KItem, _:KItem, M:Map) => M + ensures false + [owise] + + rule X:KItem in_keys((Y:KItem |-> _:KItem M:Map) #as _:Map) + => X ==K Y orBool X in_keys(M) + [simplification] + + rule M:Map[Key:KItem] orDefault _:KItem => M[Key] + requires Key in_keys(M) + [simplification] + rule M:Map[Key:KItem] orDefault D:KItem => D + requires notBool Key in_keys(M) + [simplification] +endmodule + +module PSEUDOCODE-MAP-UTILS + imports MAP-UTILS + imports PSEUDOCODE-TYPE-REFLECTION + + syntax KItem ::= nullableMapLookup(key:KItem, Map, ReflectionType) + + rule nullableMapLookup(K:KItem, M:Map, T:ReflectionType) + => cast(orElse(mapLookup(K, M), defaultValue(T)), T) + + syntax KItem ::= nullableMapSet(key:KItem, value:KItem, Map, ReflectionType) + rule nullableMapSet(Key:KItem, Value:KItem, M:Map, T:ReflectionType) + => mapDelete(Key, M) + requires isDefaultValue(Value, T) + rule nullableMapSet(Key:KItem, Value:KItem, M:Map, T:ReflectionType) + => mapSet(Key, Value, M) + requires notBool isDefaultValue(Value, T) + +endmodule + +module PSEUDOCODE-CONFIGURATION + imports MAP + + imports PSEUDOCODE-SYNTAX + imports PSEUDOCODE-COMMON + + syntax KItem ::= "uninitialized" + + configuration + + + runExternalCalls($PGM:ExternalCommands) + + + + + u(0) + .Map + .Map + + + u(0) + u(0) + .Map + u(0) + + + u(0) + + .Map + .Map + + + + + .Map + .stack + + + uninitialized + + + .List + + + + + + syntax StateCell ::= "initialState" [function] + rule initialState => + + + + u(0) + .Map + .Map + + + u(0) + u(0) + .Map + u(0) + + + u(0) + + .Map + .Map + + + + + .Map + .stack + + + uninitialized + + + .List + + +endmodule diff --git a/multisig/protocol-correctness/tests/add-board-member.golden b/multisig/protocol-correctness/tests/add-board-member.golden new file mode 100644 index 000000000..8bfb91876 --- /dev/null +++ b/multisig/protocol-correctness/tests/add-board-member.golden @@ -0,0 +1,65 @@ + + + + . + + + + + + u ( 2 ) + + + u ( 1 ) |-> address ( 7 ) + u ( 2 ) |-> address ( 8 ) + + + address ( 7 ) |-> u ( 1 ) + address ( 8 ) |-> u ( 2 ) + + + + + u ( 2 ) + + + u ( 0 ) + + + u ( 1 ) |-> BoardMember + u ( 2 ) |-> BoardMember + + + u ( 1 ) + + + + + u ( 1 ) + + + + .Map + + + .Map + + + + + + + .Map + + + .List + + + + + uninitialized + + + + + diff --git a/multisig/protocol-correctness/tests/add-board-member.msig b/multisig/protocol-correctness/tests/add-board-member.msig new file mode 100644 index 000000000..572df6bdf --- /dev/null +++ b/multisig/protocol-correctness/tests/add-board-member.msig @@ -0,0 +1,4 @@ +from address(7) run init(u(1), [address(7), .]); +from address(7) run proposeAddBoardMember(address(8)); +from address(7) run sign(u(1)); +from address(7) run performActionEndpoint(u(1)); diff --git a/multisig/protocol-correctness/tests/add-proposer.golden b/multisig/protocol-correctness/tests/add-proposer.golden new file mode 100644 index 000000000..b97a15e19 --- /dev/null +++ b/multisig/protocol-correctness/tests/add-proposer.golden @@ -0,0 +1,68 @@ + + + + . + + + + + + u ( 3 ) + + + u ( 1 ) |-> address ( 7 ) + u ( 2 ) |-> address ( 10 ) + u ( 3 ) |-> address ( 11 ) + + + address ( 7 ) |-> u ( 1 ) + address ( 10 ) |-> u ( 2 ) + address ( 11 ) |-> u ( 3 ) + + + + + u ( 1 ) + + + u ( 2 ) + + + u ( 1 ) |-> BoardMember + u ( 2 ) |-> Proposer + u ( 3 ) |-> Proposer + + + u ( 1 ) + + + + + u ( 2 ) + + + + .Map + + + .Map + + + + + + + .Map + + + .List + + + + + uninitialized + + + + + diff --git a/multisig/protocol-correctness/tests/add-proposer.msig b/multisig/protocol-correctness/tests/add-proposer.msig new file mode 100644 index 000000000..c72a3eb7b --- /dev/null +++ b/multisig/protocol-correctness/tests/add-proposer.msig @@ -0,0 +1,7 @@ +from address(7) run init(u(1), [address(7), .]); +from address(7) run proposeAddProposer(address(10)); +from address(7) run proposeAddProposer(address(11)); +from address(7) run sign(u(1)); +from address(7) run sign(u(2)); +from address(7) run performActionEndpoint(u(1)); +from address(7) run performActionEndpoint(u(2)); diff --git a/multisig/protocol-correctness/tests/board-member-to-proposer.golden b/multisig/protocol-correctness/tests/board-member-to-proposer.golden new file mode 100644 index 000000000..8951c0fa6 --- /dev/null +++ b/multisig/protocol-correctness/tests/board-member-to-proposer.golden @@ -0,0 +1,65 @@ + + + + . + + + + + + u ( 2 ) + + + u ( 1 ) |-> address ( 7 ) + u ( 2 ) |-> address ( 9 ) + + + address ( 7 ) |-> u ( 1 ) + address ( 9 ) |-> u ( 2 ) + + + + + u ( 1 ) + + + u ( 1 ) + + + u ( 1 ) |-> BoardMember + u ( 2 ) |-> Proposer + + + u ( 1 ) + + + + + u ( 2 ) + + + + .Map + + + .Map + + + + + + + .Map + + + .List + + + + + uninitialized + + + + + diff --git a/multisig/protocol-correctness/tests/board-member-to-proposer.msig b/multisig/protocol-correctness/tests/board-member-to-proposer.msig new file mode 100644 index 000000000..2de582f7d --- /dev/null +++ b/multisig/protocol-correctness/tests/board-member-to-proposer.msig @@ -0,0 +1,7 @@ +from address(7) run init(u(1), [address(7), .]); +from address(7) run proposeAddBoardMember(address(9)); +from address(7) run proposeAddProposer(address(9)); +from address(7) run sign(u(1)); +from address(7) run sign(u(2)); +from address(7) run performActionEndpoint(u(1)); +from address(7) run performActionEndpoint(u(2)); diff --git a/multisig/protocol-correctness/tests/change-quorum.golden b/multisig/protocol-correctness/tests/change-quorum.golden new file mode 100644 index 000000000..d7868bfca --- /dev/null +++ b/multisig/protocol-correctness/tests/change-quorum.golden @@ -0,0 +1,65 @@ + + + + . + + + + + + u ( 2 ) + + + u ( 1 ) |-> address ( 7 ) + u ( 2 ) |-> address ( 8 ) + + + address ( 7 ) |-> u ( 1 ) + address ( 8 ) |-> u ( 2 ) + + + + + u ( 2 ) + + + u ( 0 ) + + + u ( 1 ) |-> BoardMember + u ( 2 ) |-> BoardMember + + + u ( 2 ) + + + + + u ( 2 ) + + + + .Map + + + .Map + + + + + + + .Map + + + .List + + + + + uninitialized + + + + + diff --git a/multisig/protocol-correctness/tests/change-quorum.msig b/multisig/protocol-correctness/tests/change-quorum.msig new file mode 100644 index 000000000..31e9df8ad --- /dev/null +++ b/multisig/protocol-correctness/tests/change-quorum.msig @@ -0,0 +1,7 @@ +from address(7) run init(u(1), [address(7), .]); +from address(7) run proposeAddBoardMember(address(8)); +from address(7) run proposeChangeQuorum(u(2)); +from address(7) run sign(u(1)); +from address(7) run sign(u(2)); +from address(7) run performActionEndpoint(u(1)); +from address(7) run performActionEndpoint(u(2)); diff --git a/multisig/protocol-correctness/tests/discard-action.golden b/multisig/protocol-correctness/tests/discard-action.golden new file mode 100644 index 000000000..104b03b9f --- /dev/null +++ b/multisig/protocol-correctness/tests/discard-action.golden @@ -0,0 +1,62 @@ + + + + . + + + + + + u ( 1 ) + + + u ( 1 ) |-> address ( 7 ) + + + address ( 7 ) |-> u ( 1 ) + + + + + u ( 1 ) + + + u ( 0 ) + + + u ( 1 ) |-> BoardMember + + + u ( 1 ) + + + + + u ( 1 ) + + + + .Map + + + .Map + + + + + + + .Map + + + .List + + + + + uninitialized + + + + + diff --git a/multisig/protocol-correctness/tests/discard-action.msig b/multisig/protocol-correctness/tests/discard-action.msig new file mode 100644 index 000000000..0b74c1b42 --- /dev/null +++ b/multisig/protocol-correctness/tests/discard-action.msig @@ -0,0 +1,4 @@ +from address(7) run init(u(1), [address(7), .]); +from address(7) run proposeAddProposer(address(9)); +from address(7) run unsign(u(1)); +from address(7) run discardAction(u(1)); diff --git a/multisig/protocol-correctness/tests/perform-discarded.golden b/multisig/protocol-correctness/tests/perform-discarded.golden new file mode 100644 index 000000000..104b03b9f --- /dev/null +++ b/multisig/protocol-correctness/tests/perform-discarded.golden @@ -0,0 +1,62 @@ + + + + . + + + + + + u ( 1 ) + + + u ( 1 ) |-> address ( 7 ) + + + address ( 7 ) |-> u ( 1 ) + + + + + u ( 1 ) + + + u ( 0 ) + + + u ( 1 ) |-> BoardMember + + + u ( 1 ) + + + + + u ( 1 ) + + + + .Map + + + .Map + + + + + + + .Map + + + .List + + + + + uninitialized + + + + + diff --git a/multisig/protocol-correctness/tests/perform-discarded.msig b/multisig/protocol-correctness/tests/perform-discarded.msig new file mode 100644 index 000000000..cad8978ab --- /dev/null +++ b/multisig/protocol-correctness/tests/perform-discarded.msig @@ -0,0 +1,6 @@ +from address(7) run init(u(1), [address(7), .]); +from address(7) run proposeAddProposer(address(9)); +from address(7) run unsign(u(1)); +from address(7) run discardAction(u(1)); +from address(7) run sign(u(1)); +from address(7) run performActionEndpoint(u(1)); diff --git a/multisig/protocol-correctness/tests/remove-user.golden b/multisig/protocol-correctness/tests/remove-user.golden new file mode 100644 index 000000000..0158e195e --- /dev/null +++ b/multisig/protocol-correctness/tests/remove-user.golden @@ -0,0 +1,64 @@ + + + + . + + + + + + u ( 2 ) + + + u ( 1 ) |-> address ( 7 ) + u ( 2 ) |-> address ( 8 ) + + + address ( 7 ) |-> u ( 1 ) + address ( 8 ) |-> u ( 2 ) + + + + + u ( 1 ) + + + u ( 0 ) + + + u ( 1 ) |-> BoardMember + + + u ( 1 ) + + + + + u ( 2 ) + + + + .Map + + + .Map + + + + + + + .Map + + + .List + + + + + uninitialized + + + + + diff --git a/multisig/protocol-correctness/tests/remove-user.msig b/multisig/protocol-correctness/tests/remove-user.msig new file mode 100644 index 000000000..2f490caf7 --- /dev/null +++ b/multisig/protocol-correctness/tests/remove-user.msig @@ -0,0 +1,7 @@ +from address(7) run init(u(1), [address(7), .]); +from address(7) run proposeAddBoardMember(address(8)); +from address(7) run proposeRemoveUser(address(8)); +from address(7) run sign(u(1)); +from address(7) run sign(u(2)); +from address(7) run performActionEndpoint(u(1)); +from address(7) run performActionEndpoint(u(2)); diff --git a/multisig/protocol-correctness/tests/sc-call.golden b/multisig/protocol-correctness/tests/sc-call.golden new file mode 100644 index 000000000..104b03b9f --- /dev/null +++ b/multisig/protocol-correctness/tests/sc-call.golden @@ -0,0 +1,62 @@ + + + + . + + + + + + u ( 1 ) + + + u ( 1 ) |-> address ( 7 ) + + + address ( 7 ) |-> u ( 1 ) + + + + + u ( 1 ) + + + u ( 0 ) + + + u ( 1 ) |-> BoardMember + + + u ( 1 ) + + + + + u ( 1 ) + + + + .Map + + + .Map + + + + + + + .Map + + + .List + + + + + uninitialized + + + + + diff --git a/multisig/protocol-correctness/tests/sc-call.msig b/multisig/protocol-correctness/tests/sc-call.msig new file mode 100644 index 000000000..20fce3aff --- /dev/null +++ b/multisig/protocol-correctness/tests/sc-call.msig @@ -0,0 +1,4 @@ +from address(7) run init(u(1), [address(7), .]); +from address(7) run proposeSCCall(address(123), big(10), bytes("function"), [.]); +from address(7) run sign(u(1)); +from address(7) run performActionEndpoint(u(1)); diff --git a/multisig/protocol-correctness/tests/sc-deploy.golden b/multisig/protocol-correctness/tests/sc-deploy.golden new file mode 100644 index 000000000..104b03b9f --- /dev/null +++ b/multisig/protocol-correctness/tests/sc-deploy.golden @@ -0,0 +1,62 @@ + + + + . + + + + + + u ( 1 ) + + + u ( 1 ) |-> address ( 7 ) + + + address ( 7 ) |-> u ( 1 ) + + + + + u ( 1 ) + + + u ( 0 ) + + + u ( 1 ) |-> BoardMember + + + u ( 1 ) + + + + + u ( 1 ) + + + + .Map + + + .Map + + + + + + + .Map + + + .List + + + + + uninitialized + + + + + diff --git a/multisig/protocol-correctness/tests/sc-deploy.msig b/multisig/protocol-correctness/tests/sc-deploy.msig new file mode 100644 index 000000000..7abf7dedf --- /dev/null +++ b/multisig/protocol-correctness/tests/sc-deploy.msig @@ -0,0 +1,4 @@ +from address(7) run init(u(1), [address(7), .]); +from address(7) run proposeSCDeploy(big(10), bytes("code"), false, false, false, [.]); +from address(7) run sign(u(1)); +from address(7) run performActionEndpoint(u(1)); diff --git a/multisig/protocol-correctness/tests/send-egld.golden b/multisig/protocol-correctness/tests/send-egld.golden new file mode 100644 index 000000000..104b03b9f --- /dev/null +++ b/multisig/protocol-correctness/tests/send-egld.golden @@ -0,0 +1,62 @@ + + + + . + + + + + + u ( 1 ) + + + u ( 1 ) |-> address ( 7 ) + + + address ( 7 ) |-> u ( 1 ) + + + + + u ( 1 ) + + + u ( 0 ) + + + u ( 1 ) |-> BoardMember + + + u ( 1 ) + + + + + u ( 1 ) + + + + .Map + + + .Map + + + + + + + .Map + + + .List + + + + + uninitialized + + + + + diff --git a/multisig/protocol-correctness/tests/send-egld.msig b/multisig/protocol-correctness/tests/send-egld.msig new file mode 100644 index 000000000..97931c55f --- /dev/null +++ b/multisig/protocol-correctness/tests/send-egld.msig @@ -0,0 +1,4 @@ +from address(7) run init(u(1), [address(7), .]); +from address(7) run proposeSendEgld(address(123), big(10), bytes("stuff")); +from address(7) run sign(u(1)); +from address(7) run performActionEndpoint(u(1)); diff --git a/multisig/protocol-correctness/tests/sign.golden b/multisig/protocol-correctness/tests/sign.golden new file mode 100644 index 000000000..57956a852 --- /dev/null +++ b/multisig/protocol-correctness/tests/sign.golden @@ -0,0 +1,68 @@ + + + + . + + + + + + u ( 3 ) + + + u ( 1 ) |-> address ( 7 ) + u ( 2 ) |-> address ( 8 ) + u ( 3 ) |-> address ( 10 ) + + + address ( 7 ) |-> u ( 1 ) + address ( 8 ) |-> u ( 2 ) + address ( 10 ) |-> u ( 3 ) + + + + + u ( 2 ) + + + u ( 1 ) + + + u ( 1 ) |-> BoardMember + u ( 2 ) |-> BoardMember + u ( 3 ) |-> Proposer + + + u ( 2 ) + + + + + u ( 3 ) + + + + .Map + + + .Map + + + + + + + .Map + + + .List + + + + + uninitialized + + + + + diff --git a/multisig/protocol-correctness/tests/sign.msig b/multisig/protocol-correctness/tests/sign.msig new file mode 100644 index 000000000..235f0c827 --- /dev/null +++ b/multisig/protocol-correctness/tests/sign.msig @@ -0,0 +1,8 @@ +from address(7) run init(u(1), [address(7), .]); +from address(7) run proposeAddBoardMember(address(8)); +from address(7) run proposeChangeQuorum(u(2)); +from address(7) run proposeAddProposer(address(10)); +from address(7) run performActionEndpoint(u(1)); +from address(7) run performActionEndpoint(u(2)); +from address(8) run sign(u(3)); +from address(7) run performActionEndpoint(u(3)); diff --git a/multisig/protocol-correctness/tests/unsign-all.golden b/multisig/protocol-correctness/tests/unsign-all.golden new file mode 100644 index 000000000..183df9040 --- /dev/null +++ b/multisig/protocol-correctness/tests/unsign-all.golden @@ -0,0 +1,62 @@ + + + + . + + + + + + u ( 1 ) + + + u ( 1 ) |-> address ( 7 ) + + + address ( 7 ) |-> u ( 1 ) + + + + + u ( 1 ) + + + u ( 0 ) + + + u ( 1 ) |-> BoardMember + + + u ( 1 ) + + + + + u ( 1 ) + + + + u ( 1 ) |-> AddProposer ( address ( 9 ) ) + + + .Map + + + + + + + .Map + + + .List + + + + + uninitialized + + + + + diff --git a/multisig/protocol-correctness/tests/unsign-all.msig b/multisig/protocol-correctness/tests/unsign-all.msig new file mode 100644 index 000000000..a1c42196c --- /dev/null +++ b/multisig/protocol-correctness/tests/unsign-all.msig @@ -0,0 +1,3 @@ +from address(7) run init(u(1), [address(7), .]); +from address(7) run proposeAddProposer(address(9)); +from address(7) run unsign(u(1));