diff --git a/.github/workflows/coq.yml b/.github/workflows/coq.yml new file mode 100644 index 0000000..5949cec --- /dev/null +++ b/.github/workflows/coq.yml @@ -0,0 +1,34 @@ +name: Coq + +on: + push: + branches: ["main"] + pull_request: + branches: ["main"] + +env: + CARGO_TERM_COLOR: always + +jobs: + build: + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v3 + - name: Download Git submodules + run: git submodule update --init --recursive + - uses: coq-community/docker-coq-action@v1 + with: + custom_image: coqorg/coq:8.17-ocaml-4.14-flambda + custom_script: | + startGroup "Install dependencies" + opam install -y --deps-only CoqOfPython/coq-of-python.opam + endGroup + startGroup "Set the rights" + sudo chown -R $(whoami) . + endGroup + startGroup "Compile Coq translations" + cd CoqOfPython + make + cd .. + endGroup diff --git a/.gitignore b/.gitignore index 1616cf4..192b82b 100644 --- a/.gitignore +++ b/.gitignore @@ -1,5 +1,6 @@ # Coq rules .CoqMakefile.d +CoqMakefile CoqMakefile.conf *.vo *.vok diff --git a/CoqOfPython/CoqMakefile b/CoqOfPython/CoqMakefile deleted file mode 100644 index 7d44ffe..0000000 --- a/CoqOfPython/CoqMakefile +++ /dev/null @@ -1,981 +0,0 @@ -########################################################################## -## # The Coq Proof Assistant / The Coq Development Team ## -## v # Copyright INRIA, CNRS and contributors ## -## /dev/null 2>/dev/null; echo $$?)) -STDTIME?=command time -f $(TIMEFMT) -else -ifeq (0,$(shell gtime -f "" true >/dev/null 2>/dev/null; echo $$?)) -STDTIME?=gtime -f $(TIMEFMT) -else -STDTIME?=command time -endif -endif -else -STDTIME?=command time -f $(TIMEFMT) -endif - -COQBIN?= -ifneq (,$(COQBIN)) -# add an ending / -COQBIN:=$(COQBIN)/ -endif - -# Coq binaries -COQC ?= "$(COQBIN)coqc" -COQTOP ?= "$(COQBIN)coqtop" -COQCHK ?= "$(COQBIN)coqchk" -COQNATIVE ?= "$(COQBIN)coqnative" -COQDEP ?= "$(COQBIN)coqdep" -COQDOC ?= "$(COQBIN)coqdoc" -COQPP ?= "$(COQBIN)coqpp" -COQMKFILE ?= "$(COQBIN)coq_makefile" -OCAMLLIBDEP ?= "$(COQBIN)ocamllibdep" - -# Timing scripts -COQMAKE_ONE_TIME_FILE ?= "$(COQCORELIB)/tools/make-one-time-file.py" -COQMAKE_BOTH_TIME_FILES ?= "$(COQCORELIB)/tools/make-both-time-files.py" -COQMAKE_BOTH_SINGLE_TIMING_FILES ?= "$(COQCORELIB)/tools/make-both-single-timing-files.py" -BEFORE ?= -AFTER ?= - -# OCaml binaries -CAMLC ?= "$(OCAMLFIND)" ocamlc -c -CAMLOPTC ?= "$(OCAMLFIND)" opt -c -CAMLLINK ?= "$(OCAMLFIND)" ocamlc -linkall -CAMLOPTLINK ?= "$(OCAMLFIND)" opt -linkall -CAMLDOC ?= "$(OCAMLFIND)" ocamldoc -CAMLDEP ?= "$(OCAMLFIND)" ocamldep -slash -ml-synonym .mlpack - -# DESTDIR is prepended to all installation paths -DESTDIR ?= - -# Debug builds, typically -g to OCaml, -debug to Coq. -CAMLDEBUG ?= -COQDEBUG ?= - -# Extra packages to be linked in (as in findlib -package) -CAMLPKGS ?= -FINDLIBPKGS = -package coq-core.plugins.ltac $(CAMLPKGS) - -# Option for making timing files -TIMING?= -# Option for changing sorting of timing output file -TIMING_SORT_BY ?= auto -# Option for changing the fuzz parameter on the output file -TIMING_FUZZ ?= 0 -# Option for changing whether to use real or user time for timing tables -TIMING_REAL?= -# Option for including the memory column(s) -TIMING_INCLUDE_MEM?= -# Option for sorting by the memory column -TIMING_SORT_BY_MEM?= -# Output file names for timed builds -TIME_OF_BUILD_FILE ?= time-of-build.log -TIME_OF_BUILD_BEFORE_FILE ?= time-of-build-before.log -TIME_OF_BUILD_AFTER_FILE ?= time-of-build-after.log -TIME_OF_PRETTY_BUILD_FILE ?= time-of-build-pretty.log -TIME_OF_PRETTY_BOTH_BUILD_FILE ?= time-of-build-both.log -TIME_OF_PRETTY_BUILD_EXTRA_FILES ?= - # also output to the command line - -TGTS ?= - -# Retro compatibility (DESTDIR is standard on Unix, DSTROOT is not) -ifdef DSTROOT -DESTDIR := $(DSTROOT) -endif - -# Substitution of the path by appending $(DESTDIR) if needed. -# The variable $(COQMF_WINDRIVE) can be needed for Cygwin environments. -windrive_path = $(if $(COQMF_WINDRIVE),$(subst $(COQMF_WINDRIVE),/,$(1)),$(1)) -destination_path = $(if $(DESTDIR),$(DESTDIR)/$(call windrive_path,$(1)),$(1)) - -# Installation paths of libraries and documentation. -COQLIBINSTALL ?= $(call destination_path,$(COQLIB)/user-contrib) -COQDOCINSTALL ?= $(call destination_path,$(DOCDIR)/coq/user-contrib) -COQPLUGININSTALL ?= $(call destination_path,$(COQCORELIB)/..) -COQTOPINSTALL ?= $(call destination_path,$(COQLIB)/toploop) # FIXME: Unused variable? - -# findlib files installation -FINDLIBPREINST= mkdir -p "$(COQPLUGININSTALL)/" -FINDLIBDESTDIR= -destdir "$(COQPLUGININSTALL)/" - -# we need to move out of sight $(METAFILE) otherwise findlib thinks the -# package is already installed -findlib_install = \ - $(HIDE)if [ "$(METAFILE)" ]; then \ - $(FINDLIBPREINST) && \ - mv "$(METAFILE)" "$(METAFILE).skip" ; \ - "$(OCAMLFIND)" install $(2) $(FINDLIBDESTDIR) $(FINDLIBPACKAGE) $(1); \ - rc=$$?; \ - mv "$(METAFILE).skip" "$(METAFILE)"; \ - exit $$rc; \ - fi -findlib_remove = \ - $(HIDE)if [ ! -z "$(METAFILE)" ]; then\ - "$(OCAMLFIND)" remove $(FINDLIBDESTDIR) $(FINDLIBPACKAGE); \ - fi - - -########## End of parameters ################################################## -# What follows may be relevant to you only if you need to -# extend this Makefile. If so, look for 'Extension point' here and -# put in CoqMakefile.local double colon rules accordingly. -# E.g. to perform some work after the all target completes you can write -# -# post-all:: -# echo "All done!" -# -# in CoqMakefile.local -# -############################################################################### - - - - -# Flags ####################################################################### -# -# We define a bunch of variables combining the parameters. -# To add additional flags to coq, coqchk or coqdoc, set the -# {COQ,COQCHK,COQDOC}EXTRAFLAGS variable to whatever you want to add. -# To overwrite the default choice and set your own flags entirely, set the -# {COQ,COQCHK,COQDOC}FLAGS variable. - -SHOW := $(if $(VERBOSE),@true "",@echo "") -HIDE := $(if $(VERBOSE),,@) - -TIMER=$(if $(TIMED), $(STDTIME), $(TIMECMD)) - -OPT?= - -# The DYNOBJ and DYNLIB variables are used by "coqdep -dyndep var" in .v.d -ifeq '$(OPT)' '-byte' -USEBYTE:=true -DYNOBJ:=.cma -DYNLIB:=.cma -else -USEBYTE:= -DYNOBJ:=.cmxs -DYNLIB:=.cmxs -endif - -# these variables are meant to be overridden if you want to add *extra* flags -COQEXTRAFLAGS?= -COQCHKEXTRAFLAGS?= -COQDOCEXTRAFLAGS?= - -# Find the last argument of the form "-native-compiler FLAG" -COQUSERNATIVEFLAG:=$(strip \ -$(subst -native-compiler-,,\ -$(lastword \ -$(filter -native-compiler-%,\ -$(subst -native-compiler ,-native-compiler-,\ -$(strip $(COQEXTRAFLAGS))))))) - -COQFILTEREDEXTRAFLAGS:=$(strip \ -$(filter-out -native-compiler-%,\ -$(subst -native-compiler ,-native-compiler-,\ -$(strip $(COQEXTRAFLAGS))))) - -COQACTUALNATIVEFLAG:=$(lastword $(COQMF_COQ_NATIVE_COMPILER_DEFAULT) $(COQMF_COQPROJECTNATIVEFLAG) $(COQUSERNATIVEFLAG)) - -ifeq '$(COQACTUALNATIVEFLAG)' 'yes' - COQNATIVEFLAG="-w" "-deprecated-native-compiler-option" "-native-compiler" "ondemand" - COQDONATIVE="yes" -else -ifeq '$(COQACTUALNATIVEFLAG)' 'ondemand' - COQNATIVEFLAG="-w" "-deprecated-native-compiler-option" "-native-compiler" "ondemand" - COQDONATIVE="no" -else - COQNATIVEFLAG="-w" "-deprecated-native-compiler-option" "-native-compiler" "no" - COQDONATIVE="no" -endif -endif - -# these flags do NOT contain the libraries, to make them easier to overwrite -COQFLAGS?=-q $(OTHERFLAGS) $(COQFILTEREDEXTRAFLAGS) $(COQNATIVEFLAG) -COQCHKFLAGS?=-silent -o $(COQCHKEXTRAFLAGS) -COQDOCFLAGS?=-interpolate -utf8 $(COQDOCEXTRAFLAGS) - -COQDOCLIBS?=$(COQLIBS_NOML) - -# The version of Coq being run and the version of coq_makefile that -# generated this makefile -COQ_VERSION:=$(shell $(COQC) --print-version | cut -d " " -f 1) -COQMAKEFILE_VERSION:=8.17.1 - -# COQ_SRC_SUBDIRS is for user-overriding, usually to add -# `user-contrib/Foo` to the includes, we keep COQCORE_SRC_SUBDIRS for -# Coq's own core libraries, which should be replaced by ocamlfind -# options at some point. -COQ_SRC_SUBDIRS?= -COQSRCLIBS?= $(foreach d,$(COQ_SRC_SUBDIRS), -I "$(COQLIB)/$(d)") - -CAMLFLAGS+=$(OCAMLLIBS) $(COQSRCLIBS) -# ocamldoc fails with unknown argument otherwise -CAMLDOCFLAGS:=$(filter-out -annot, $(filter-out -bin-annot, $(CAMLFLAGS))) -CAMLFLAGS+=$(OCAMLWARN) - -ifneq (,$(TIMING)) -TIMING_ARG=-time -ifeq (after,$(TIMING)) -TIMING_EXT=after-timing -else -ifeq (before,$(TIMING)) -TIMING_EXT=before-timing -else -TIMING_EXT=timing -endif -endif -else -TIMING_ARG= -endif - -# Files ####################################################################### -# -# We here define a bunch of variables about the files being part of the -# Coq project in order to ease the writing of build target and build rules - -VDFILE := .CoqMakefile.d - -ALLSRCFILES := \ - $(MLGFILES) \ - $(MLFILES) \ - $(MLPACKFILES) \ - $(MLLIBFILES) \ - $(MLIFILES) - -# helpers -vo_to_obj = $(addsuffix .o,\ - $(filter-out Warning: Error:,\ - $(shell $(COQTOP) -q -noinit -batch -quiet -print-mod-uid $(1)))) -strip_dotslash = $(patsubst ./%,%,$(1)) - -# without this we get undefined variables in the expansion for the -# targets of the [deprecated,use-mllib-or-mlpack] rule -with_undef = $(if $(filter-out undefined, $(origin $(1))),$($(1))) - -VO = vo -VOS = vos - -VOFILES = $(VFILES:.v=.$(VO)) -GLOBFILES = $(VFILES:.v=.glob) -HTMLFILES = $(VFILES:.v=.html) -GHTMLFILES = $(VFILES:.v=.g.html) -BEAUTYFILES = $(addsuffix .beautified,$(VFILES)) -TEXFILES = $(VFILES:.v=.tex) -GTEXFILES = $(VFILES:.v=.g.tex) -CMOFILES = \ - $(MLGFILES:.mlg=.cmo) \ - $(MLFILES:.ml=.cmo) \ - $(MLPACKFILES:.mlpack=.cmo) -CMXFILES = $(CMOFILES:.cmo=.cmx) -OFILES = $(CMXFILES:.cmx=.o) -CMAFILES = $(MLLIBFILES:.mllib=.cma) $(MLPACKFILES:.mlpack=.cma) -CMXAFILES = $(CMAFILES:.cma=.cmxa) -CMIFILES = \ - $(CMOFILES:.cmo=.cmi) \ - $(MLIFILES:.mli=.cmi) -# the /if/ is because old _CoqProject did not list a .ml(pack|lib) but just -# a .mlg file -CMXSFILES = \ - $(MLPACKFILES:.mlpack=.cmxs) \ - $(CMXAFILES:.cmxa=.cmxs) \ - $(if $(MLPACKFILES)$(CMXAFILES),,\ - $(MLGFILES:.mlg=.cmxs) $(MLFILES:.ml=.cmxs)) - -# files that are packed into a plugin (no extension) -PACKEDFILES = \ - $(call strip_dotslash, \ - $(foreach lib, \ - $(call strip_dotslash, \ - $(MLPACKFILES:.mlpack=_MLPACK_DEPENDENCIES)),$(call with_undef,$(lib)))) -# files that are archived into a .cma (mllib) -LIBEDFILES = \ - $(call strip_dotslash, \ - $(foreach lib, \ - $(call strip_dotslash, \ - $(MLLIBFILES:.mllib=_MLLIB_DEPENDENCIES)),$(call with_undef,$(lib)))) -CMIFILESTOINSTALL = $(filter-out $(addsuffix .cmi,$(PACKEDFILES)),$(CMIFILES)) -CMOFILESTOINSTALL = $(filter-out $(addsuffix .cmo,$(PACKEDFILES)),$(CMOFILES)) -OBJFILES = $(call vo_to_obj,$(VOFILES)) -ALLNATIVEFILES = \ - $(OBJFILES:.o=.cmi) \ - $(OBJFILES:.o=.cmx) \ - $(OBJFILES:.o=.cmxs) -FINDLIBPACKAGE=$(patsubst .%,%,$(suffix $(METAFILE))) - -# trick: wildcard filters out non-existing files, so that `install` doesn't show -# warnings and `clean` doesn't pass to rm a list of files that is too long for -# the shell. -NATIVEFILES = $(wildcard $(ALLNATIVEFILES)) -FILESTOINSTALL = \ - $(VOFILES) \ - $(VFILES) \ - $(GLOBFILES) \ - $(NATIVEFILES) \ - $(CMXSFILES) # to be removed when we remove legacy loading -FINDLIBFILESTOINSTALL = \ - $(CMIFILESTOINSTALL) -ifeq '$(HASNATDYNLINK)' 'true' -DO_NATDYNLINK = yes -FINDLIBFILESTOINSTALL += $(CMXSFILES) $(CMXAFILES) $(CMOFILESTOINSTALL:.cmo=.cmx) -else -DO_NATDYNLINK = -endif - -ALLDFILES = $(addsuffix .d,$(ALLSRCFILES)) $(VDFILE) - -# Compilation targets ######################################################### - -all: - $(HIDE)$(MAKE) --no-print-directory -f "$(SELF)" pre-all - $(HIDE)$(MAKE) --no-print-directory -f "$(SELF)" real-all - $(HIDE)$(MAKE) --no-print-directory -f "$(SELF)" post-all -.PHONY: all - -all.timing.diff: - $(HIDE)$(MAKE) --no-print-directory -f "$(SELF)" pre-all - $(HIDE)$(MAKE) --no-print-directory -f "$(SELF)" real-all.timing.diff TIME_OF_PRETTY_BUILD_EXTRA_FILES="" - $(HIDE)$(MAKE) --no-print-directory -f "$(SELF)" post-all -.PHONY: all.timing.diff - -ifeq (0,$(TIMING_REAL)) -TIMING_REAL_ARG := -TIMING_USER_ARG := --user -else -ifeq (1,$(TIMING_REAL)) -TIMING_REAL_ARG := --real -TIMING_USER_ARG := -else -TIMING_REAL_ARG := -TIMING_USER_ARG := -endif -endif - -ifeq (0,$(TIMING_INCLUDE_MEM)) -TIMING_INCLUDE_MEM_ARG := --no-include-mem -else -TIMING_INCLUDE_MEM_ARG := -endif - -ifeq (1,$(TIMING_SORT_BY_MEM)) -TIMING_SORT_BY_MEM_ARG := --sort-by-mem -else -TIMING_SORT_BY_MEM_ARG := -endif - -make-pretty-timed-before:: TIME_OF_BUILD_FILE=$(TIME_OF_BUILD_BEFORE_FILE) -make-pretty-timed-after:: TIME_OF_BUILD_FILE=$(TIME_OF_BUILD_AFTER_FILE) -make-pretty-timed make-pretty-timed-before make-pretty-timed-after:: - $(HIDE)rm -f pretty-timed-success.ok - $(HIDE)($(MAKE) --no-print-directory -f "$(PARENT)" $(TGTS) TIMED=1 2>&1 && touch pretty-timed-success.ok) | tee -a $(TIME_OF_BUILD_FILE) - $(HIDE)rm pretty-timed-success.ok # must not be -f; must fail if the touch failed -print-pretty-timed:: - $(HIDE)$(COQMAKE_ONE_TIME_FILE) $(TIMING_INCLUDE_MEM_ARG) $(TIMING_SORT_BY_MEM_ARG) $(TIMING_REAL_ARG) $(TIME_OF_BUILD_FILE) $(TIME_OF_PRETTY_BUILD_FILE) $(TIME_OF_PRETTY_BUILD_EXTRA_FILES) -print-pretty-timed-diff:: - $(HIDE)$(COQMAKE_BOTH_TIME_FILES) --sort-by=$(TIMING_SORT_BY) $(TIMING_INCLUDE_MEM_ARG) $(TIMING_SORT_BY_MEM_ARG) $(TIMING_REAL_ARG) $(TIME_OF_BUILD_AFTER_FILE) $(TIME_OF_BUILD_BEFORE_FILE) $(TIME_OF_PRETTY_BOTH_BUILD_FILE) $(TIME_OF_PRETTY_BUILD_EXTRA_FILES) -ifeq (,$(BEFORE)) -print-pretty-single-time-diff:: - @echo 'Error: Usage: $(MAKE) print-pretty-single-time-diff AFTER=path/to/file.v.after-timing BEFORE=path/to/file.v.before-timing' - $(HIDE)false -else -ifeq (,$(AFTER)) -print-pretty-single-time-diff:: - @echo 'Error: Usage: $(MAKE) print-pretty-single-time-diff AFTER=path/to/file.v.after-timing BEFORE=path/to/file.v.before-timing' - $(HIDE)false -else -print-pretty-single-time-diff:: - $(HIDE)$(COQMAKE_BOTH_SINGLE_TIMING_FILES) --fuzz=$(TIMING_FUZZ) --sort-by=$(TIMING_SORT_BY) $(TIMING_USER_ARG) $(AFTER) $(BEFORE) $(TIME_OF_PRETTY_BUILD_FILE) $(TIME_OF_PRETTY_BUILD_EXTRA_FILES) -endif -endif -pretty-timed: - $(HIDE)$(MAKE) --no-print-directory -f "$(PARENT)" make-pretty-timed - $(HIDE)$(MAKE) --no-print-directory -f "$(SELF)" print-pretty-timed -.PHONY: pretty-timed make-pretty-timed make-pretty-timed-before make-pretty-timed-after print-pretty-timed print-pretty-timed-diff print-pretty-single-time-diff - -# Extension points for actions to be performed before/after the all target -pre-all:: - @# Extension point - $(HIDE)if [ "$(COQMAKEFILE_VERSION)" != "$(COQ_VERSION)" ]; then\ - echo "W: This Makefile was generated by Coq $(COQMAKEFILE_VERSION)";\ - echo "W: while the current Coq version is $(COQ_VERSION)";\ - fi -.PHONY: pre-all - -post-all:: - @# Extension point -.PHONY: post-all - -real-all: $(VOFILES) $(if $(USEBYTE),bytefiles,optfiles) -.PHONY: real-all - -real-all.timing.diff: $(VOFILES:.vo=.v.timing.diff) -.PHONY: real-all.timing.diff - -bytefiles: $(CMOFILES) $(CMAFILES) -.PHONY: bytefiles - -optfiles: $(if $(DO_NATDYNLINK),$(CMXSFILES)) -.PHONY: optfiles - -# FIXME, see Ralf's bugreport -# quick is deprecated, now renamed vio -vio: $(VOFILES:.vo=.vio) -.PHONY: vio -quick: vio - $(warning "'make quick' is deprecated, use 'make vio' or consider using 'vos' files") -.PHONY: quick - -vio2vo: - $(TIMER) $(COQC) $(COQDEBUG) $(COQFLAGS) $(COQLIBS) \ - -schedule-vio2vo $(J) $(VOFILES:%.vo=%.vio) -.PHONY: vio2vo - -# quick2vo is undocumented -quick2vo: - $(HIDE)make -j $(J) vio - $(HIDE)VIOFILES=$$(for vofile in $(VOFILES); do \ - viofile="$$(echo "$$vofile" | sed "s/\.vo$$/.vio/")"; \ - if [ "$$vofile" -ot "$$viofile" -o ! -e "$$vofile" ]; then printf "$$viofile "; fi; \ - done); \ - echo "VIO2VO: $$VIOFILES"; \ - if [ -n "$$VIOFILES" ]; then \ - $(TIMER) $(COQC) $(COQDEBUG) $(COQFLAGS) $(COQLIBS) -schedule-vio2vo $(J) $$VIOFILES; \ - fi -.PHONY: quick2vo - -checkproofs: - $(TIMER) $(COQC) $(COQDEBUG) $(COQFLAGS) $(COQLIBS) \ - -schedule-vio-checking $(J) $(VOFILES:%.vo=%.vio) -.PHONY: checkproofs - -vos: $(VOFILES:%.vo=%.vos) -.PHONY: vos - -vok: $(VOFILES:%.vo=%.vok) -.PHONY: vok - -validate: $(VOFILES) - $(TIMER) $(COQCHK) $(COQCHKFLAGS) $(COQLIBS_NOML) $^ -.PHONY: validate - -only: $(TGTS) -.PHONY: only - -# Documentation targets ####################################################### - -html: $(GLOBFILES) $(VFILES) - $(SHOW)'COQDOC -d html $(GAL)' - $(HIDE)mkdir -p html - $(HIDE)$(COQDOC) \ - -toc $(COQDOCFLAGS) -html $(GAL) $(COQDOCLIBS) -d html $(VFILES) - -mlihtml: $(MLIFILES:.mli=.cmi) - $(SHOW)'CAMLDOC -d $@' - $(HIDE)mkdir $@ || rm -rf $@/* - $(HIDE)$(CAMLDOC) -html \ - -d $@ -m A $(CAMLDEBUG) $(CAMLDOCFLAGS) $(MLIFILES) $(FINDLIBPKGS) - -all-mli.tex: $(MLIFILES:.mli=.cmi) - $(SHOW)'CAMLDOC -latex $@' - $(HIDE)$(CAMLDOC) -latex \ - -o $@ -m A $(CAMLDEBUG) $(CAMLDOCFLAGS) $(MLIFILES) $(FINDLIBPKGS) - -all.ps: $(VFILES) - $(SHOW)'COQDOC -ps $(GAL)' - $(HIDE)$(COQDOC) \ - -toc $(COQDOCFLAGS) -ps $(GAL) $(COQDOCLIBS) \ - -o $@ `$(COQDEP) -sort $(VFILES)` - -all.pdf: $(VFILES) - $(SHOW)'COQDOC -pdf $(GAL)' - $(HIDE)$(COQDOC) \ - -toc $(COQDOCFLAGS) -pdf $(GAL) $(COQDOCLIBS) \ - -o $@ `$(COQDEP) -sort $(VFILES)` - -# FIXME: not quite right, since the output name is different -gallinahtml: GAL=-g -gallinahtml: html - -all-gal.ps: GAL=-g -all-gal.ps: all.ps - -all-gal.pdf: GAL=-g -all-gal.pdf: all.pdf - -# ? -beautify: $(BEAUTYFILES) - for file in $^; do mv $${file%.beautified} $${file%beautified}old && mv $${file} $${file%.beautified}; done - @echo 'Do not do "make clean" until you are sure that everything went well!' - @echo 'If there were a problem, execute "for file in $$(find . -name \*.v.old -print); do mv $${file} $${file%.old}; done" in your shell/' -.PHONY: beautify - -# Installation targets ######################################################## -# -# There rules can be extended in CoqMakefile.local -# Extensions can't assume when they run. - -# findlib needs the package to not be installed, so we remove it before -# installing it (see the call to findlib_remove) -install: META - $(HIDE)code=0; for f in $(FILESTOINSTALL); do\ - if ! [ -f "$$f" ]; then >&2 echo $$f does not exist; code=1; fi \ - done; exit $$code - $(HIDE)for f in $(FILESTOINSTALL); do\ - df="`$(COQMKFILE) -destination-of "$$f" $(COQLIBS)`";\ - if [ "$$?" != "0" -o -z "$$df" ]; then\ - echo SKIP "$$f" since it has no logical path;\ - else\ - install -d "$(COQLIBINSTALL)/$$df" &&\ - install -m 0644 "$$f" "$(COQLIBINSTALL)/$$df" &&\ - echo INSTALL "$$f" "$(COQLIBINSTALL)/$$df";\ - fi;\ - done - $(call findlib_remove) - $(call findlib_install, META $(FINDLIBFILESTOINSTALL)) - $(HIDE)$(MAKE) install-extra -f "$(SELF)" -install-extra:: - @# Extension point -.PHONY: install install-extra - -META: $(METAFILE) - $(HIDE)if [ "$(METAFILE)" ]; then \ - cat "$(METAFILE)" | grep -v 'directory.*=.*' > META; \ - fi - -install-byte: - $(call findlib_install, $(CMAFILES) $(CMOFILESTOINSTALL), -add) - -install-doc:: html mlihtml - @# Extension point - $(HIDE)install -d "$(COQDOCINSTALL)/$(INSTALLCOQDOCROOT)/html" - $(HIDE)for i in html/*; do \ - dest="$(COQDOCINSTALL)/$(INSTALLCOQDOCROOT)/$$i";\ - install -m 0644 "$$i" "$$dest";\ - echo INSTALL "$$i" "$$dest";\ - done - $(HIDE)install -d \ - "$(COQDOCINSTALL)/$(INSTALLCOQDOCROOT)/mlihtml" - $(HIDE)for i in mlihtml/*; do \ - dest="$(COQDOCINSTALL)/$(INSTALLCOQDOCROOT)/$$i";\ - install -m 0644 "$$i" "$$dest";\ - echo INSTALL "$$i" "$$dest";\ - done -.PHONY: install-doc - -uninstall:: - @# Extension point - $(call findlib_remove) - $(HIDE)for f in $(FILESTOINSTALL); do \ - df="`$(COQMKFILE) -destination-of "$$f" $(COQLIBS)`" &&\ - instf="$(COQLIBINSTALL)/$$df/`basename $$f`" &&\ - rm -f "$$instf" &&\ - echo RM "$$instf" ;\ - done - $(HIDE)for f in $(FILESTOINSTALL); do \ - df="`$(COQMKFILE) -destination-of "$$f" $(COQLIBS)`" &&\ - echo RMDIR "$(COQLIBINSTALL)/$$df/" &&\ - (rmdir "$(COQLIBINSTALL)/$$df/" 2>/dev/null || true); \ - done - -.PHONY: uninstall - -uninstall-doc:: - @# Extension point - $(SHOW)'RM $(COQDOCINSTALL)/$(INSTALLCOQDOCROOT)/html' - $(HIDE)rm -rf "$(COQDOCINSTALL)/$(INSTALLCOQDOCROOT)/html" - $(SHOW)'RM $(COQDOCINSTALL)/$(INSTALLCOQDOCROOT)/mlihtml' - $(HIDE)rm -rf "$(COQDOCINSTALL)/$(INSTALLCOQDOCROOT)/mlihtml" - $(HIDE) rmdir "$(COQDOCINSTALL)/$(INSTALLCOQDOCROOT)/" || true -.PHONY: uninstall-doc - -# Cleaning #################################################################### -# -# There rules can be extended in CoqMakefile.local -# Extensions can't assume when they run. - -clean:: - @# Extension point - $(SHOW)'CLEAN' - $(HIDE)rm -f $(CMOFILES) - $(HIDE)rm -f $(CMIFILES) - $(HIDE)rm -f $(CMAFILES) - $(HIDE)rm -f $(CMXFILES) - $(HIDE)rm -f $(CMXAFILES) - $(HIDE)rm -f $(CMXSFILES) - $(HIDE)rm -f $(OFILES) - $(HIDE)rm -f $(CMXAFILES:.cmxa=.a) - $(HIDE)rm -f $(MLGFILES:.mlg=.ml) - $(HIDE)rm -f $(CMXFILES:.cmx=.cmt) - $(HIDE)rm -f $(MLIFILES:.mli=.cmti) - $(HIDE)rm -f $(ALLDFILES) - $(HIDE)rm -f $(NATIVEFILES) - $(HIDE)find . -name .coq-native -type d -empty -delete - $(HIDE)rm -f $(VOFILES) - $(HIDE)rm -f $(VOFILES:.vo=.vio) - $(HIDE)rm -f $(VOFILES:.vo=.vos) - $(HIDE)rm -f $(VOFILES:.vo=.vok) - $(HIDE)rm -f $(BEAUTYFILES) $(VFILES:=.old) - $(HIDE)rm -f all.ps all-gal.ps all.pdf all-gal.pdf all.glob all-mli.tex - $(HIDE)rm -f $(VFILES:.v=.glob) - $(HIDE)rm -f $(VFILES:.v=.tex) - $(HIDE)rm -f $(VFILES:.v=.g.tex) - $(HIDE)rm -f pretty-timed-success.ok - $(HIDE)rm -f META - $(HIDE)rm -rf html mlihtml -.PHONY: clean - -cleanall:: clean - @# Extension point - $(SHOW)'CLEAN *.aux *.timing' - $(HIDE)rm -f $(foreach f,$(VFILES:.v=),$(dir $(f)).$(notdir $(f)).aux) - $(HIDE)rm -f $(TIME_OF_BUILD_FILE) $(TIME_OF_BUILD_BEFORE_FILE) $(TIME_OF_BUILD_AFTER_FILE) $(TIME_OF_PRETTY_BUILD_FILE) $(TIME_OF_PRETTY_BOTH_BUILD_FILE) - $(HIDE)rm -f $(VOFILES:.vo=.v.timing) - $(HIDE)rm -f $(VOFILES:.vo=.v.before-timing) - $(HIDE)rm -f $(VOFILES:.vo=.v.after-timing) - $(HIDE)rm -f $(VOFILES:.vo=.v.timing.diff) - $(HIDE)rm -f .lia.cache .nia.cache -.PHONY: cleanall - -archclean:: - @# Extension point - $(SHOW)'CLEAN *.cmx *.o' - $(HIDE)rm -f $(NATIVEFILES) - $(HIDE)rm -f $(CMOFILES:%.cmo=%.cmx) -.PHONY: archclean - - -# Compilation rules ########################################################### - -$(MLIFILES:.mli=.cmi): %.cmi: %.mli - $(SHOW)'CAMLC -c $<' - $(HIDE)$(TIMER) $(CAMLC) $(CAMLDEBUG) $(CAMLFLAGS) $(FINDLIBPKGS) $< - -$(MLGFILES:.mlg=.ml): %.ml: %.mlg - $(SHOW)'COQPP $<' - $(HIDE)$(COQPP) $< - -# Stupid hack around a deficient syntax: we cannot concatenate two expansions -$(filter %.cmo, $(MLFILES:.ml=.cmo) $(MLGFILES:.mlg=.cmo)): %.cmo: %.ml - $(SHOW)'CAMLC -c $<' - $(HIDE)$(TIMER) $(CAMLC) $(CAMLDEBUG) $(CAMLFLAGS) $(FINDLIBPKGS) $< - -# Same hack -$(filter %.cmx, $(MLFILES:.ml=.cmx) $(MLGFILES:.mlg=.cmx)): %.cmx: %.ml - $(SHOW)'CAMLOPT -c $(FOR_PACK) $<' - $(HIDE)$(TIMER) $(CAMLOPTC) $(CAMLDEBUG) $(CAMLFLAGS) $(FINDLIBPKGS) $(FOR_PACK) $< - - -$(MLLIBFILES:.mllib=.cmxs): %.cmxs: %.cmxa - $(SHOW)'CAMLOPT -shared -o $@' - $(HIDE)$(TIMER) $(CAMLOPTLINK) $(CAMLDEBUG) $(CAMLFLAGS) $(FINDLIBPKGS) \ - -shared -o $@ $< - -$(MLLIBFILES:.mllib=.cma): %.cma: | %.mllib - $(SHOW)'CAMLC -a -o $@' - $(HIDE)$(TIMER) $(CAMLLINK) $(CAMLDEBUG) $(CAMLFLAGS) $(FINDLIBPKGS) -a -o $@ $^ - -$(MLLIBFILES:.mllib=.cmxa): %.cmxa: | %.mllib - $(SHOW)'CAMLOPT -a -o $@' - $(HIDE)$(TIMER) $(CAMLOPTLINK) $(CAMLDEBUG) $(CAMLFLAGS) $(FINDLIBPKGS) -a -o $@ $^ - - -$(MLPACKFILES:.mlpack=.cmxs): %.cmxs: %.cmxa - $(SHOW)'CAMLOPT -shared -o $@' - $(HIDE)$(TIMER) $(CAMLOPTLINK) $(CAMLDEBUG) $(CAMLFLAGS) $(FINDLIBPKGS) \ - -shared -o $@ $< - -$(MLPACKFILES:.mlpack=.cmxa): %.cmxa: %.cmx | %.mlpack - $(SHOW)'CAMLOPT -a -o $@' - $(HIDE)$(TIMER) $(CAMLOPTLINK) $(CAMLDEBUG) $(CAMLFLAGS) $(FINDLIBPKGS) -a -o $@ $< - -$(MLPACKFILES:.mlpack=.cma): %.cma: %.cmo | %.mlpack - $(SHOW)'CAMLC -a -o $@' - $(HIDE)$(TIMER) $(CAMLLINK) $(CAMLDEBUG) $(CAMLFLAGS) $(FINDLIBPKGS) -a -o $@ $^ - -$(MLPACKFILES:.mlpack=.cmo): %.cmo: | %.mlpack - $(SHOW)'CAMLC -pack -o $@' - $(HIDE)$(TIMER) $(CAMLLINK) $(CAMLDEBUG) $(CAMLFLAGS) $(FINDLIBPKGS) -pack -o $@ $^ - -$(MLPACKFILES:.mlpack=.cmx): %.cmx: | %.mlpack - $(SHOW)'CAMLOPT -pack -o $@' - $(HIDE)$(TIMER) $(CAMLOPTLINK) $(CAMLDEBUG) $(CAMLFLAGS) $(FINDLIBPKGS) -pack -o $@ $^ - -# This rule is for _CoqProject with no .mllib nor .mlpack -$(filter-out $(MLLIBFILES:.mllib=.cmxs) $(MLPACKFILES:.mlpack=.cmxs) $(addsuffix .cmxs,$(PACKEDFILES)) $(addsuffix .cmxs,$(LIBEDFILES)),$(MLFILES:.ml=.cmxs) $(MLGFILES:.mlg=.cmxs)): %.cmxs: %.cmx - $(SHOW)'[deprecated,use-mllib-or-mlpack] CAMLOPT -shared -o $@' - $(HIDE)$(TIMER) $(CAMLOPTLINK) $(CAMLDEBUG) $(CAMLFLAGS) $(FINDLIBPKGS) \ - -shared -o $@ $< - -ifneq (,$(TIMING)) -TIMING_EXTRA = > $<.$(TIMING_EXT) -else -TIMING_EXTRA = -endif - -# can't make -# https://www.gnu.org/software/make/manual/make.html#Static-Pattern -# work with multiple target rules -# so use eval in a loop instead -# with grouped targets https://www.gnu.org/software/make/manual/make.html#Multiple-Targets -# if available (GNU Make >= 4.3) -ifneq (,$(filter grouped-target,$(.FEATURES))) -define globvorule= - -# take care to $$ variables using $< etc - $(1).vo $(1).glob &: $(1).v | $(VDFILE) - $(SHOW)COQC $(1).v - $(HIDE)$$(TIMER) $(COQC) $(COQDEBUG) $(TIMING_ARG) $(COQFLAGS) $(COQLIBS) $(1).v $$(TIMING_EXTRA) -ifeq ($(COQDONATIVE), "yes") - $(SHOW)COQNATIVE $(1).vo - $(HIDE)$(call TIMER,$(1).vo.native) $(COQNATIVE) $(COQLIBS) $(1).vo -endif - -endef -else - -$(VOFILES): %.vo: %.v | $(VDFILE) - $(SHOW)COQC $< - $(HIDE)$(TIMER) $(COQC) $(COQDEBUG) $(TIMING_ARG) $(COQFLAGS) $(COQLIBS) $< $(TIMING_EXTRA) -ifeq ($(COQDONATIVE), "yes") - $(SHOW)COQNATIVE $@ - $(HIDE)$(call TIMER,$@.native) $(COQNATIVE) $(COQLIBS) $@ -endif - -# this is broken :( todo fix if we ever find a solution that doesn't need grouped targets -$(GLOBFILES): %.glob: %.v - $(SHOW)'COQC $< (for .glob)' - $(HIDE)$(TIMER) $(COQC) $(COQDEBUG) $(COQFLAGS) $(COQLIBS) $< - -endif - -$(foreach vfile,$(VFILES:.v=),$(eval $(call globvorule,$(vfile)))) - -$(VFILES:.v=.vio): %.vio: %.v - $(SHOW)COQC -vio $< - $(HIDE)$(TIMER) $(COQC) -vio $(COQDEBUG) $(COQFLAGS) $(COQLIBS) $< - -$(VFILES:.v=.vos): %.vos: %.v - $(SHOW)COQC -vos $< - $(HIDE)$(TIMER) $(COQC) -vos $(COQDEBUG) $(COQFLAGS) $(COQLIBS) $< - -$(VFILES:.v=.vok): %.vok: %.v - $(SHOW)COQC -vok $< - $(HIDE)$(TIMER) $(COQC) -vok $(COQDEBUG) $(COQFLAGS) $(COQLIBS) $< - -$(addsuffix .timing.diff,$(VFILES)): %.timing.diff : %.before-timing %.after-timing - $(SHOW)PYTHON TIMING-DIFF $*.{before,after}-timing - $(HIDE)$(MAKE) --no-print-directory -f "$(SELF)" print-pretty-single-time-diff BEFORE=$*.before-timing AFTER=$*.after-timing TIME_OF_PRETTY_BUILD_FILE="$@" - -$(BEAUTYFILES): %.v.beautified: %.v - $(SHOW)'BEAUTIFY $<' - $(HIDE)$(TIMER) $(COQC) $(COQDEBUG) $(COQFLAGS) $(COQLIBS) -beautify $< - -$(TEXFILES): %.tex: %.v - $(SHOW)'COQDOC -latex $<' - $(HIDE)$(COQDOC) $(COQDOCFLAGS) -latex $< -o $@ - -$(GTEXFILES): %.g.tex: %.v - $(SHOW)'COQDOC -latex -g $<' - $(HIDE)$(COQDOC) $(COQDOCFLAGS) -latex -g $< -o $@ - -$(HTMLFILES): %.html: %.v %.glob - $(SHOW)'COQDOC -html $<' - $(HIDE)$(COQDOC) $(COQDOCFLAGS) -html $< -o $@ - -$(GHTMLFILES): %.g.html: %.v %.glob - $(SHOW)'COQDOC -html -g $<' - $(HIDE)$(COQDOC) $(COQDOCFLAGS) -html -g $< -o $@ - -# Dependency files ############################################################ - -ifndef MAKECMDGOALS - -include $(ALLDFILES) -else - ifneq ($(filter-out archclean clean cleanall printenv make-pretty-timed make-pretty-timed-before make-pretty-timed-after print-pretty-timed print-pretty-timed-diff print-pretty-single-time-diff,$(MAKECMDGOALS)),) - -include $(ALLDFILES) - endif -endif - -.SECONDARY: $(ALLDFILES) - -redir_if_ok = > "$@" || ( RV=$$?; rm -f "$@"; exit $$RV ) - -GENMLFILES:=$(MLGFILES:.mlg=.ml) -$(addsuffix .d,$(ALLSRCFILES)): $(GENMLFILES) - -$(addsuffix .d,$(MLIFILES)): %.mli.d: %.mli - $(SHOW)'CAMLDEP $<' - $(HIDE)$(CAMLDEP) $(OCAMLLIBS) "$<" $(redir_if_ok) - -$(addsuffix .d,$(MLGFILES)): %.mlg.d: %.ml - $(SHOW)'CAMLDEP $<' - $(HIDE)$(CAMLDEP) $(OCAMLLIBS) "$<" $(redir_if_ok) - -$(addsuffix .d,$(MLFILES)): %.ml.d: %.ml - $(SHOW)'CAMLDEP $<' - $(HIDE)$(CAMLDEP) $(OCAMLLIBS) "$<" $(redir_if_ok) - -$(addsuffix .d,$(MLLIBFILES)): %.mllib.d: %.mllib - $(SHOW)'OCAMLLIBDEP $<' - $(HIDE)$(OCAMLLIBDEP) -c $(OCAMLLIBS) "$<" $(redir_if_ok) - -$(addsuffix .d,$(MLPACKFILES)): %.mlpack.d: %.mlpack - $(SHOW)'OCAMLLIBDEP $<' - $(HIDE)$(OCAMLLIBDEP) -c $(OCAMLLIBS) "$<" $(redir_if_ok) - -# If this makefile is created using a _CoqProject we have coqdep get -# options from it. This avoids argument length limits for pathological -# projects. Note that extra options might be on the command line. -VDFILE_FLAGS:=$(if _CoqProject,-f _CoqProject,) $(CMDLINE_COQLIBS) $(CMDLINE_VFILES) - -$(VDFILE): _CoqProject $(VFILES) - $(SHOW)'COQDEP VFILES' - $(HIDE)$(COQDEP) $(if $(strip $(METAFILE)),-m "$(METAFILE)") -vos -dyndep var $(VDFILE_FLAGS) $(redir_if_ok) - -# Misc ######################################################################## - -byte: - $(HIDE)$(MAKE) all "OPT:=-byte" -f "$(SELF)" -.PHONY: byte - -opt: - $(HIDE)$(MAKE) all "OPT:=-opt" -f "$(SELF)" -.PHONY: opt - -# This is deprecated. To extend this makefile use -# extension points and CoqMakefile.local -printenv:: - $(warning printenv is deprecated) - $(warning write extensions in CoqMakefile.local or include CoqMakefile.conf) - @echo 'COQLIB = $(COQLIB)' - @echo 'COQCORELIB = $(COQCORELIB)' - @echo 'DOCDIR = $(DOCDIR)' - @echo 'OCAMLFIND = $(OCAMLFIND)' - @echo 'HASNATDYNLINK = $(HASNATDYNLINK)' - @echo 'SRC_SUBDIRS = $(SRC_SUBDIRS)' - @echo 'COQ_SRC_SUBDIRS = $(COQ_SRC_SUBDIRS)' - @echo 'COQCORE_SRC_SUBDIRS = $(COQCORE_SRC_SUBDIRS)' - @echo 'OCAMLFIND = $(OCAMLFIND)' - @echo 'PP = $(PP)' - @echo 'COQFLAGS = $(COQFLAGS)' - @echo 'COQLIB = $(COQLIBS)' - @echo 'COQLIBINSTALL = $(COQLIBINSTALL)' - @echo 'COQDOCINSTALL = $(COQDOCINSTALL)' -.PHONY: printenv - -# Generate a .merlin file. If you need to append directives to this -# file you can extend the merlin-hook target in CoqMakefile.local -.merlin: - $(SHOW)'FILL .merlin' - $(HIDE)echo 'FLG $(COQMF_CAMLFLAGS)' > .merlin - $(HIDE)echo 'B $(COQCORELIB)' >> .merlin - $(HIDE)echo 'S $(COQCORELIB)' >> .merlin - $(HIDE)$(foreach d,$(COQCORE_SRC_SUBDIRS), \ - echo 'B $(COQCORELIB)$(d)' >> .merlin;) - $(HIDE)$(foreach d,$(COQ_SRC_SUBDIRS), \ - echo 'S $(COQLIB)$(d)' >> .merlin;) - $(HIDE)$(foreach d,$(SRC_SUBDIRS), echo 'B $(d)' >> .merlin;) - $(HIDE)$(foreach d,$(SRC_SUBDIRS), echo 'S $(d)' >> .merlin;) - $(HIDE)$(MAKE) merlin-hook -f "$(SELF)" -.PHONY: merlin - -merlin-hook:: - @# Extension point -.PHONY: merlin-hook - -# prints all variables -debug: - $(foreach v,\ - $(sort $(filter-out $(INITIAL_VARS) INITIAL_VARS,\ - $(.VARIABLES))),\ - $(info $(v) = $($(v)))) -.PHONY: debug - -.DEFAULT_GOAL := all - -# Users can create CoqMakefile.local-late to hook into double-colon rules -# or add other needed Makefile code, using defined -# variables if necessary. --include CoqMakefile.local-late - -# Local Variables: -# mode: makefile-gmake -# End: diff --git a/CoqOfPython/CoqOfPython.v b/CoqOfPython/CoqOfPython.v index 487e316..b6128c3 100644 --- a/CoqOfPython/CoqOfPython.v +++ b/CoqOfPython/CoqOfPython.v @@ -20,8 +20,10 @@ Module Data. internally to represent integers, closures, ... that can be made accessible in a special field of objects. *) Inductive t (Value : Set) : Set := + | Ellipsis | Bool (b : bool) | Integer (z : Z) + | Float (f : string) | String (s : string) | Tuple (items : list Value) (** Lists and tuples are very similar. The distinction between the two is conventional. We use @@ -31,11 +33,13 @@ Module Data. | Dict (dict : list (string * Value)) | Closure {Value M : Set} (f : Value -> Value -> M) | Klass {Value M : Set} - (bases : list (Set * string)) + (bases : list (string * string)) (class_methods : list (string * (Value -> Value -> M))) (methods : list (string * (Value -> Value -> M))). + Arguments Ellipsis {_}. Arguments Bool {_}. Arguments Integer {_}. + Arguments Float {_}. Arguments String {_}. Arguments Tuple {_}. Arguments List {_}. @@ -71,17 +75,14 @@ End Pointer. Module Value. Inductive t : Set := - | Make (globals : Set) (klass : string) (value : Pointer.t t). + | Make (globals : string) (klass : string) (value : Pointer.t t). End Value. Parameter M : Set. -Parameter IsInGlobals : Set -> Value.t -> string -> Prop. +Parameter IsInGlobals : string -> Value.t -> string -> Prop. -Definition IsGlobalAlias (globals required_globals : Set) (name : string) : Prop := - forall (value : Value.t), - IsInGlobals required_globals value name -> - IsInGlobals globals value name. +Parameter IsImported : string -> string -> string -> Prop. Module M. Parameter pure : Value.t -> M. @@ -95,15 +96,31 @@ Module M. (** For the `x[i]` syntax. *) Parameter get_subscript : Value.t -> Value.t -> M. - Parameter get_name : Set -> string -> M. + Parameter slice : Value.t -> Value.t -> Value.t -> Value.t -> M. + + Parameter get_name : string -> string -> M. Parameter set_locals : Value.t -> Value.t -> list string -> M. Parameter assign : Value.t -> Value.t -> M. + Parameter assign_local : string -> Value.t -> M. + + Parameter assign_op : (Value.t -> Value.t -> M) -> Value.t -> Value.t -> M. + + Parameter assign_op_local : (Value.t -> Value.t -> M) -> string -> Value.t -> M. + + Parameter delete : Value.t -> M. + Parameter return_ : Value.t -> M. - Parameter raise : Value.t -> M. + Parameter pass : M. + + Parameter break : M. + + Parameter continue : M. + + Parameter raise : option Value.t -> M. Parameter assert : Value.t -> M. @@ -111,6 +128,10 @@ Module M. Parameter if_then_else : Value.t -> M -> M -> M. + Parameter for_ : Value.t -> Value.t -> M -> M -> M. + + Parameter while : Value.t -> M -> M -> M. + Parameter run : M -> Value.t. Module Notations. @@ -118,7 +139,7 @@ Module M. (run ((.. (e e1) ..) en)) (at level 100). - Notation "e (||)" := + Notation "e (| |)" := (run e) (at level 100). End Notations. @@ -168,7 +189,7 @@ End M. Export M.Notations. -Parameter Inherit : Set -> Set -> Prop. +Parameter Inherit : string -> string -> Prop. Module BoolOp. Parameter and : Value.t -> M -> M. @@ -183,7 +204,7 @@ Module BinOp. Parameter mult : Value.t -> Value.t -> M. - Parameter matmult : Value.t -> Value.t -> M. + Parameter mat_mult : Value.t -> Value.t -> M. Parameter div : Value.t -> Value.t -> M. @@ -191,9 +212,9 @@ Module BinOp. Parameter pow : Value.t -> Value.t -> M. - Parameter lshift : Value.t -> Value.t -> M. + Parameter l_shift : Value.t -> Value.t -> M. - Parameter rshift : Value.t -> Value.t -> M. + Parameter r_shift : Value.t -> Value.t -> M. Parameter bit_or : Value.t -> Value.t -> M. @@ -238,10 +259,10 @@ End Compare. (** ** Builtins *) Module builtins. - Inductive globals : Set :=. + Definition globals : string := "builtins". Definition make_klass - (bases : list (Set * string)) + (bases : list (string * string)) (class_methods : list (string * (Value.t -> Value.t -> M))) (methods : list (string * (Value.t -> Value.t -> M))) : Value.t := @@ -269,14 +290,23 @@ Module Constant. Object.fields := []; |}). + Definition ellipsis : Value.t := + Value.Make builtins.globals "ellipsis" (Pointer.Imm (Object.wrapper Data.Ellipsis)). + Definition bool (b : bool) : Value.t := Value.Make builtins.globals "bool" (Pointer.Imm (Object.wrapper (Data.Bool b))). Definition int (z : Z) : Value.t := Value.Make builtins.globals "int" (Pointer.Imm (Object.wrapper (Data.Integer z))). + Definition float (f : string) : Value.t := + Value.Make builtins.globals "float" (Pointer.Imm (Object.wrapper (Data.Float f))). + Definition str (s : string) : Value.t := Value.Make builtins.globals "str" (Pointer.Imm (Object.wrapper (Data.String s))). + + Definition bytes (b : string) : Value.t := + Value.Make builtins.globals "bytes" (Pointer.Imm (Object.wrapper (Data.String b))). End Constant. Definition make_tuple (items : list Value.t) : Value.t := diff --git a/CoqOfPython/blacklist.txt b/CoqOfPython/blacklist.txt index e69de29..1cb514b 100644 --- a/CoqOfPython/blacklist.txt +++ b/CoqOfPython/blacklist.txt @@ -0,0 +1 @@ +ethereum/ethash.v diff --git a/CoqOfPython/coq-of-python.opam b/CoqOfPython/coq-of-python.opam new file mode 100644 index 0000000..5204e4d --- /dev/null +++ b/CoqOfPython/coq-of-python.opam @@ -0,0 +1,23 @@ +opam-version: "2.0" +name: "coq-of-python" +version: "0.1" +synopsis: "Coq of Python" +description: """ +Formal verification for Python by translation to the proof system Coq +""" +maintainer: "Guillaume Claret " +authors: [ + "Formal Land " +] +license: "MIT" +homepage: "https://github.com/formal-land/coq-of-python" +bug-reports: "https://github.com/formal-land/coq-of-python/issues" +dev-repo: "git+https://github.com/formal-land/coq-of-python.git" +depends: [ + "ocaml" {>= "4.08"} + "coq" {>= "8.17.1" & < "8.18"} + "coq-hammer" {>= "1.3.2+8.17" & < "1.3.2+8.18"} +] +build: [ + [make] +] diff --git a/CoqOfPython/ethereum/__init__.v b/CoqOfPython/ethereum/__init__.v new file mode 100644 index 0000000..e1c92c1 --- /dev/null +++ b/CoqOfPython/ethereum/__init__.v @@ -0,0 +1,56 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.__init__". + +Definition expr_1 : Value.t := + Constant.str " +### Introduction + +Seeing as internet connections have been vastly expanding across the +world, spreading information has become as cheap as ever. Bitcoin, for +example, has demonstrated the possibility of creating a decentralized, +trade system that is accessible around the world. Namecoin is another +system that built off of Bitcoin's currency structure to create other +simple technological applications. + +Ethereum's goal is to create a cryptographically secure system in which +any and all types of transaction-based concepts can be built. It provides +an exceptionally accessible and decentralized system to build software +and execute transactions. + +This package contains a reference implementation, written as simply as +possible, to aid in defining the behavior of Ethereum clients. +". + +(* At top_level_stmt: unsupported node type: Import *) + +Definition __version__ : Value.t := M.run ltac:(M.monadic ( + Constant.str "0.1.0" +)). + +Definition EVM_RECURSION_LIMIT : Value.t := M.run ltac:(M.monadic ( + BinOp.mult (| + Constant.int 1024, + Constant.int 12 + |) +)). + +Definition expr_27 : Value.t := + M.call (| + M.get_field (| M.get_name (| globals, "sys" |), "setrecursionlimit" |), + make_list [ + M.call (| + M.get_name (| globals, "max" |), + make_list [ + M.get_name (| globals, "EVM_RECURSION_LIMIT" |); + M.call (| + M.get_field (| M.get_name (| globals, "sys" |), "getrecursionlimit" |), + make_list [], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |). diff --git a/CoqOfPython/ethereum/arrow_glacier/__init__.v b/CoqOfPython/ethereum/arrow_glacier/__init__.v new file mode 100644 index 0000000..6adb453 --- /dev/null +++ b/CoqOfPython/ethereum/arrow_glacier/__init__.v @@ -0,0 +1,22 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.arrow_glacier.__init__". + +Definition expr_1 : Value.t := + Constant.str " +The Arrow Glacier fork delays the difficulty bomb. There are no other changes +in this fork. +". + +Axiom ethereum_fork_criteria_imports_ByBlockNumber : + IsImported globals "ethereum.fork_criteria" "ByBlockNumber". + +Definition FORK_CRITERIA : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "ByBlockNumber" |), + make_list [ + Constant.int 13773000 + ], + make_dict [] + |) +)). diff --git a/CoqOfPython/ethereum/arrow_glacier/blocks.v b/CoqOfPython/ethereum/arrow_glacier/blocks.v new file mode 100644 index 0000000..09a6083 --- /dev/null +++ b/CoqOfPython/ethereum/arrow_glacier/blocks.v @@ -0,0 +1,89 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.arrow_glacier.blocks". + +Definition expr_1 : Value.t := + Constant.str " +A `Block` is a single link in the chain that is Ethereum. Each `Block` contains +a `Header` and zero or more transactions. Each `Header` contains associated +metadata like the block number, parent block hash, and how much gas was +consumed by its transactions. + +Together, these blocks form a cryptographically secure journal recording the +history of all state transitions that have happened since the genesis of the +chain. +". + +Axiom dataclasses_imports_dataclass : + IsImported globals "dataclasses" "dataclass". + +Axiom typing_imports_Tuple : + IsImported globals "typing" "Tuple". +Axiom typing_imports_Union : + IsImported globals "typing" "Union". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_Bytes : + IsImported globals "ethereum.base_types" "Bytes". +Axiom ethereum_base_types_imports_Bytes8 : + IsImported globals "ethereum.base_types" "Bytes8". +Axiom ethereum_base_types_imports_Bytes32 : + IsImported globals "ethereum.base_types" "Bytes32". +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". +Axiom ethereum_base_types_imports_slotted_freezable : + IsImported globals "ethereum.base_types" "slotted_freezable". + +Axiom ethereum_crypto_hash_imports_Hash32 : + IsImported globals "ethereum.crypto.hash" "Hash32". + +Axiom ethereum_arrow_glacier_fork_types_imports_Address : + IsImported globals "ethereum.arrow_glacier.fork_types" "Address". +Axiom ethereum_arrow_glacier_fork_types_imports_Bloom : + IsImported globals "ethereum.arrow_glacier.fork_types" "Bloom". +Axiom ethereum_arrow_glacier_fork_types_imports_Root : + IsImported globals "ethereum.arrow_glacier.fork_types" "Root". + +Axiom ethereum_arrow_glacier_transactions_imports_LegacyTransaction : + IsImported globals "ethereum.arrow_glacier.transactions" "LegacyTransaction". + +Definition Header : Value.t := + builtins.make_klass + [] + [ + + ] + [ + + ]. + +Definition Block : Value.t := + builtins.make_klass + [] + [ + + ] + [ + + ]. + +Definition Log : Value.t := + builtins.make_klass + [] + [ + + ] + [ + + ]. + +Definition Receipt : Value.t := + builtins.make_klass + [] + [ + + ] + [ + + ]. diff --git a/CoqOfPython/ethereum/arrow_glacier/bloom.v b/CoqOfPython/ethereum/arrow_glacier/bloom.v new file mode 100644 index 0000000..9f27d32 --- /dev/null +++ b/CoqOfPython/ethereum/arrow_glacier/bloom.v @@ -0,0 +1,207 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.arrow_glacier.bloom". + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Logs Bloom +^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +This modules defines functions for calculating bloom filters of logs. For the +general theory of bloom filters see e.g. `Wikipedia +`_. Bloom filters are used to allow +for efficient searching of logs by address and/or topic, by rapidly +eliminating blocks and receipts from their search. +". + +Axiom typing_imports_Tuple : + IsImported globals "typing" "Tuple". + +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". + +Axiom ethereum_crypto_hash_imports_keccak256 : + IsImported globals "ethereum.crypto.hash" "keccak256". + +Axiom ethereum_arrow_glacier_blocks_imports_Log : + IsImported globals "ethereum.arrow_glacier.blocks" "Log". + +Axiom ethereum_arrow_glacier_fork_types_imports_Bloom : + IsImported globals "ethereum.arrow_glacier.fork_types" "Bloom". + +Definition add_to_bloom : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "bloom"; "bloom_entry" ] |) in + let _ := Constant.str " + Add a bloom entry to the bloom filter (`bloom`). + + The number of hash functions used is 3. They are calculated by taking the + least significant 11 bits from the first 3 16-bit words of the + `keccak_256()` hash of `bloom_entry`. + + Parameters + ---------- + bloom : + The bloom filter. + bloom_entry : + An entry which is to be added to bloom filter. + " in + let _ := M.assign_local (| + "hash" , + M.call (| + M.get_name (| globals, "keccak256" |), + make_list [ + M.get_name (| globals, "bloom_entry" |) + ], + make_dict [] + |) + |) in + let _ := + M.for_ (| + M.get_name (| globals, "idx" |), + make_tuple [ Constant.int 0; Constant.int 2; Constant.int 4 ], + ltac:(M.monadic ( + let _ := M.assign_local (| + "bit_to_set" , + BinOp.bit_and (| + M.call (| + M.get_field (| M.get_name (| globals, "Uint" |), "from_be_bytes" |), + make_list [ + M.slice (| + M.get_name (| globals, "hash" |), + M.get_name (| globals, "idx" |), + BinOp.add (| + M.get_name (| globals, "idx" |), + Constant.int 2 + |), + Constant.None_ + |) + ], + make_dict [] + |), + Constant.int 2047 + |) + |) in + let _ := M.assign_local (| + "bit_index" , + BinOp.sub (| + Constant.int 2047, + M.get_name (| globals, "bit_to_set" |) + |) + |) in + let _ := M.assign_local (| + "byte_index" , + BinOp.floor_div (| + M.get_name (| globals, "bit_index" |), + Constant.int 8 + |) + |) in + let _ := M.assign_local (| + "bit_value" , + BinOp.l_shift (| + Constant.int 1, + BinOp.sub (| + Constant.int 7, + BinOp.mod_ (| + M.get_name (| globals, "bit_index" |), + Constant.int 8 + |) + |) + |) + |) in + let _ := M.assign (| + M.get_subscript (| + M.get_name (| globals, "bloom" |), + M.get_name (| globals, "byte_index" |) + |), + BinOp.bit_or (| + M.get_subscript (| + M.get_name (| globals, "bloom" |), + M.get_name (| globals, "byte_index" |) + |), + M.get_name (| globals, "bit_value" |) + |) + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + M.pure Constant.None_)). + +Definition logs_bloom : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "logs" ] |) in + let _ := Constant.str " + Obtain the logs bloom from a list of log entries. + + The address and each topic of a log are added to the bloom filter. + + Parameters + ---------- + logs : + List of logs for which the logs bloom is to be obtained. + + Returns + ------- + logs_bloom : `Bloom` + The logs bloom obtained which is 256 bytes with some bits set as per + the caller address and the log topics. + " in +(* At stmt: unsupported node type: AnnAssign *) + let _ := + M.for_ (| + M.get_name (| globals, "log" |), + M.get_name (| globals, "logs" |), + ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, "add_to_bloom" |), + make_list [ + M.get_name (| globals, "bloom" |); + M.get_field (| M.get_name (| globals, "log" |), "address" |) + ], + make_dict [] + |) in + let _ := + M.for_ (| + M.get_name (| globals, "topic" |), + M.get_field (| M.get_name (| globals, "log" |), "topics" |), + ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, "add_to_bloom" |), + make_list [ + M.get_name (| globals, "bloom" |); + M.get_name (| globals, "topic" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, "Bloom" |), + make_list [ + M.get_name (| globals, "bloom" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). diff --git a/CoqOfPython/ethereum/arrow_glacier/fork.v b/CoqOfPython/ethereum/arrow_glacier/fork.v new file mode 100644 index 0000000..00cdb50 --- /dev/null +++ b/CoqOfPython/ethereum/arrow_glacier/fork.v @@ -0,0 +1,3353 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.arrow_glacier.fork". + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Specification +^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Entry point for the Ethereum specification. +". + +Axiom dataclasses_imports_dataclass : + IsImported globals "dataclasses" "dataclass". + +Axiom typing_imports_List : + IsImported globals "typing" "List". +Axiom typing_imports_Optional : + IsImported globals "typing" "Optional". +Axiom typing_imports_Set : + IsImported globals "typing" "Set". +Axiom typing_imports_Tuple : + IsImported globals "typing" "Tuple". +Axiom typing_imports_Union : + IsImported globals "typing" "Union". + +Axiom ethereum_base_types_imports_Bytes0 : + IsImported globals "ethereum.base_types" "Bytes0". + +Axiom ethereum_crypto_elliptic_curve_imports_SECP256K1N : + IsImported globals "ethereum.crypto.elliptic_curve" "SECP256K1N". +Axiom ethereum_crypto_elliptic_curve_imports_secp256k1_recover : + IsImported globals "ethereum.crypto.elliptic_curve" "secp256k1_recover". + +Axiom ethereum_crypto_hash_imports_Hash32 : + IsImported globals "ethereum.crypto.hash" "Hash32". +Axiom ethereum_crypto_hash_imports_keccak256 : + IsImported globals "ethereum.crypto.hash" "keccak256". + +Axiom ethereum_ethash_imports_dataset_size : + IsImported globals "ethereum.ethash" "dataset_size". +Axiom ethereum_ethash_imports_generate_cache : + IsImported globals "ethereum.ethash" "generate_cache". +Axiom ethereum_ethash_imports_hashimoto_light : + IsImported globals "ethereum.ethash" "hashimoto_light". + +Axiom ethereum_exceptions_imports_InvalidBlock : + IsImported globals "ethereum.exceptions" "InvalidBlock". + +Axiom ethereum_utils_ensure_imports_ensure : + IsImported globals "ethereum.utils.ensure" "ensure". + +Axiom ethereum_imports_rlp : + IsImported globals "ethereum" "rlp". + +Axiom ethereum_base_types_imports_U64 : + IsImported globals "ethereum.base_types" "U64". +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_U256_CEIL_VALUE : + IsImported globals "ethereum.base_types" "U256_CEIL_VALUE". +Axiom ethereum_base_types_imports_Bytes : + IsImported globals "ethereum.base_types" "Bytes". +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". + +Axiom ethereum_arrow_glacier_imports_vm : + IsImported globals "ethereum.arrow_glacier" "vm". + +Axiom ethereum_arrow_glacier_blocks_imports_Block : + IsImported globals "ethereum.arrow_glacier.blocks" "Block". +Axiom ethereum_arrow_glacier_blocks_imports_Header : + IsImported globals "ethereum.arrow_glacier.blocks" "Header". +Axiom ethereum_arrow_glacier_blocks_imports_Log : + IsImported globals "ethereum.arrow_glacier.blocks" "Log". +Axiom ethereum_arrow_glacier_blocks_imports_Receipt : + IsImported globals "ethereum.arrow_glacier.blocks" "Receipt". + +Axiom ethereum_arrow_glacier_bloom_imports_logs_bloom : + IsImported globals "ethereum.arrow_glacier.bloom" "logs_bloom". + +Axiom ethereum_arrow_glacier_fork_types_imports_Address : + IsImported globals "ethereum.arrow_glacier.fork_types" "Address". +Axiom ethereum_arrow_glacier_fork_types_imports_Bloom : + IsImported globals "ethereum.arrow_glacier.fork_types" "Bloom". +Axiom ethereum_arrow_glacier_fork_types_imports_Root : + IsImported globals "ethereum.arrow_glacier.fork_types" "Root". + +Axiom ethereum_arrow_glacier_state_imports_State : + IsImported globals "ethereum.arrow_glacier.state" "State". +Axiom ethereum_arrow_glacier_state_imports_account_exists_and_is_empty : + IsImported globals "ethereum.arrow_glacier.state" "account_exists_and_is_empty". +Axiom ethereum_arrow_glacier_state_imports_create_ether : + IsImported globals "ethereum.arrow_glacier.state" "create_ether". +Axiom ethereum_arrow_glacier_state_imports_destroy_account : + IsImported globals "ethereum.arrow_glacier.state" "destroy_account". +Axiom ethereum_arrow_glacier_state_imports_get_account : + IsImported globals "ethereum.arrow_glacier.state" "get_account". +Axiom ethereum_arrow_glacier_state_imports_increment_nonce : + IsImported globals "ethereum.arrow_glacier.state" "increment_nonce". +Axiom ethereum_arrow_glacier_state_imports_set_account_balance : + IsImported globals "ethereum.arrow_glacier.state" "set_account_balance". +Axiom ethereum_arrow_glacier_state_imports_state_root : + IsImported globals "ethereum.arrow_glacier.state" "state_root". + +Axiom ethereum_arrow_glacier_transactions_imports_TX_ACCESS_LIST_ADDRESS_COST : + IsImported globals "ethereum.arrow_glacier.transactions" "TX_ACCESS_LIST_ADDRESS_COST". +Axiom ethereum_arrow_glacier_transactions_imports_TX_ACCESS_LIST_STORAGE_KEY_COST : + IsImported globals "ethereum.arrow_glacier.transactions" "TX_ACCESS_LIST_STORAGE_KEY_COST". +Axiom ethereum_arrow_glacier_transactions_imports_TX_BASE_COST : + IsImported globals "ethereum.arrow_glacier.transactions" "TX_BASE_COST". +Axiom ethereum_arrow_glacier_transactions_imports_TX_CREATE_COST : + IsImported globals "ethereum.arrow_glacier.transactions" "TX_CREATE_COST". +Axiom ethereum_arrow_glacier_transactions_imports_TX_DATA_COST_PER_NON_ZERO : + IsImported globals "ethereum.arrow_glacier.transactions" "TX_DATA_COST_PER_NON_ZERO". +Axiom ethereum_arrow_glacier_transactions_imports_TX_DATA_COST_PER_ZERO : + IsImported globals "ethereum.arrow_glacier.transactions" "TX_DATA_COST_PER_ZERO". +Axiom ethereum_arrow_glacier_transactions_imports_AccessListTransaction : + IsImported globals "ethereum.arrow_glacier.transactions" "AccessListTransaction". +Axiom ethereum_arrow_glacier_transactions_imports_FeeMarketTransaction : + IsImported globals "ethereum.arrow_glacier.transactions" "FeeMarketTransaction". +Axiom ethereum_arrow_glacier_transactions_imports_LegacyTransaction : + IsImported globals "ethereum.arrow_glacier.transactions" "LegacyTransaction". +Axiom ethereum_arrow_glacier_transactions_imports_Transaction : + IsImported globals "ethereum.arrow_glacier.transactions" "Transaction". +Axiom ethereum_arrow_glacier_transactions_imports_decode_transaction : + IsImported globals "ethereum.arrow_glacier.transactions" "decode_transaction". +Axiom ethereum_arrow_glacier_transactions_imports_encode_transaction : + IsImported globals "ethereum.arrow_glacier.transactions" "encode_transaction". + +Axiom ethereum_arrow_glacier_trie_imports_Trie : + IsImported globals "ethereum.arrow_glacier.trie" "Trie". +Axiom ethereum_arrow_glacier_trie_imports_root : + IsImported globals "ethereum.arrow_glacier.trie" "root". +Axiom ethereum_arrow_glacier_trie_imports_trie_set : + IsImported globals "ethereum.arrow_glacier.trie" "trie_set". + +Axiom ethereum_arrow_glacier_utils_message_imports_prepare_message : + IsImported globals "ethereum.arrow_glacier.utils.message" "prepare_message". + +Axiom ethereum_arrow_glacier_vm_interpreter_imports_process_message_call : + IsImported globals "ethereum.arrow_glacier.vm.interpreter" "process_message_call". + +Definition BLOCK_REWARD : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + BinOp.mult (| + Constant.int 2, + BinOp.pow (| + Constant.int 10, + Constant.int 18 + |) + |) + ], + make_dict [] + |) +)). + +Definition BASE_FEE_MAX_CHANGE_DENOMINATOR : Value.t := M.run ltac:(M.monadic ( + Constant.int 8 +)). + +Definition ELASTICITY_MULTIPLIER : Value.t := M.run ltac:(M.monadic ( + Constant.int 2 +)). + +Definition GAS_LIMIT_ADJUSTMENT_FACTOR : Value.t := M.run ltac:(M.monadic ( + Constant.int 1024 +)). + +Definition GAS_LIMIT_MINIMUM : Value.t := M.run ltac:(M.monadic ( + Constant.int 5000 +)). + +Definition MINIMUM_DIFFICULTY : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 131072 + ], + make_dict [] + |) +)). + +Definition MAX_OMMER_DEPTH : Value.t := M.run ltac:(M.monadic ( + Constant.int 6 +)). + +Definition BOMB_DELAY_BLOCKS : Value.t := M.run ltac:(M.monadic ( + Constant.int 10700000 +)). + +Definition EMPTY_OMMER_HASH : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "keccak256" |), + make_list [ + M.call (| + M.get_field (| M.get_name (| globals, "rlp" |), "encode" |), + make_list [ + make_list [] + ], + make_dict [] + |) + ], + make_dict [] + |) +)). + +Definition BlockChain : Value.t := + builtins.make_klass + [] + [ + + ] + [ + + ]. + +Definition apply_fork : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "old" ] |) in + let _ := Constant.str " + Transforms the state from the previous hard fork (`old`) into the block + chain object for this hard fork and returns it. + + When forks need to implement an irregular state transition, this function + is used to handle the irregularity. See the :ref:`DAO Fork ` for + an example. + + Parameters + ---------- + old : + Previous block chain object. + + Returns + ------- + new : `BlockChain` + Upgraded block chain object for this hard fork. + " in + let _ := M.return_ (| + M.get_name (| globals, "old" |) + |) in + M.pure Constant.None_)). + +Definition get_last_256_block_hashes : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "chain" ] |) in + let _ := Constant.str " + Obtain the list of hashes of the previous 256 blocks in order of + increasing block number. + + This function will return less hashes for the first 256 blocks. + + The ``BLOCKHASH`` opcode needs to access the latest hashes on the chain, + therefore this function retrieves them. + + Parameters + ---------- + chain : + History and current state. + + Returns + ------- + recent_block_hashes : `List[Hash32]` + Hashes of the recent 256 blocks in order of increasing block number. + " in + let _ := M.assign_local (| + "recent_blocks" , + M.slice (| + M.get_field (| M.get_name (| globals, "chain" |), "blocks" |), + UnOp.sub (| Constant.int 255 |), + Constant.None_, + Constant.None_ + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_name (| globals, "recent_blocks" |) + ], + make_dict [] + |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + make_list [] + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "recent_block_hashes" , + make_list [] + |) in + let _ := + M.for_ (| + M.get_name (| globals, "block" |), + M.get_name (| globals, "recent_blocks" |), + ltac:(M.monadic ( + let _ := M.assign_local (| + "prev_block_hash" , + M.get_field (| M.get_field (| M.get_name (| globals, "block" |), "header" |), "parent_hash" |) + |) in + let _ := M.call (| + M.get_field (| M.get_name (| globals, "recent_block_hashes" |), "append" |), + make_list [ + M.get_name (| globals, "prev_block_hash" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := M.assign_local (| + "most_recent_block_hash" , + M.call (| + M.get_name (| globals, "keccak256" |), + make_list [ + M.call (| + M.get_field (| M.get_name (| globals, "rlp" |), "encode" |), + make_list [ + M.get_field (| M.get_subscript (| + M.get_name (| globals, "recent_blocks" |), + UnOp.sub (| Constant.int 1 |) + |), "header" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_field (| M.get_name (| globals, "recent_block_hashes" |), "append" |), + make_list [ + M.get_name (| globals, "most_recent_block_hash" |) + ], + make_dict [] + |) in + let _ := M.return_ (| + M.get_name (| globals, "recent_block_hashes" |) + |) in + M.pure Constant.None_)). + +Definition state_transition : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "chain"; "block" ] |) in + let _ := Constant.str " + Attempts to apply a block to an existing block chain. + + All parts of the block's contents need to be verified before being added + to the chain. Blocks are verified by ensuring that the contents of the + block make logical sense with the contents of the parent block. The + information in the block's header must also match the corresponding + information in the block. + + To implement Ethereum, in theory clients are only required to store the + most recent 255 blocks of the chain since as far as execution is + concerned, only those blocks are accessed. Practically, however, clients + should store more blocks to handle reorgs. + + Parameters + ---------- + chain : + History and current state. + block : + Block to apply to `chain`. + " in + let _ := M.assign_local (| + "parent_header" , + M.get_field (| M.get_subscript (| + M.get_field (| M.get_name (| globals, "chain" |), "blocks" |), + UnOp.sub (| Constant.int 1 |) + |), "header" |) + |) in + let _ := M.call (| + M.get_name (| globals, "validate_header" |), + make_list [ + M.get_field (| M.get_name (| globals, "block" |), "header" |); + M.get_name (| globals, "parent_header" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "validate_ommers" |), + make_list [ + M.get_field (| M.get_name (| globals, "block" |), "ommers" |); + M.get_field (| M.get_name (| globals, "block" |), "header" |); + M.get_name (| globals, "chain" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "apply_body_output" , + M.call (| + M.get_name (| globals, "apply_body" |), + make_list [ + M.get_field (| M.get_name (| globals, "chain" |), "state" |); + M.call (| + M.get_name (| globals, "get_last_256_block_hashes" |), + make_list [ + M.get_name (| globals, "chain" |) + ], + make_dict [] + |); + M.get_field (| M.get_field (| M.get_name (| globals, "block" |), "header" |), "coinbase" |); + M.get_field (| M.get_field (| M.get_name (| globals, "block" |), "header" |), "number" |); + M.get_field (| M.get_field (| M.get_name (| globals, "block" |), "header" |), "base_fee_per_gas" |); + M.get_field (| M.get_field (| M.get_name (| globals, "block" |), "header" |), "gas_limit" |); + M.get_field (| M.get_field (| M.get_name (| globals, "block" |), "header" |), "timestamp" |); + M.get_field (| M.get_field (| M.get_name (| globals, "block" |), "header" |), "difficulty" |); + M.get_field (| M.get_name (| globals, "block" |), "transactions" |); + M.get_field (| M.get_name (| globals, "block" |), "ommers" |); + M.get_field (| M.get_name (| globals, "chain" |), "chain_id" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + Compare.eq (| + M.get_field (| M.get_name (| globals, "apply_body_output" |), "block_gas_used" |), + M.get_field (| M.get_field (| M.get_name (| globals, "block" |), "header" |), "gas_used" |) + |); + M.get_name (| globals, "InvalidBlock" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + Compare.eq (| + M.get_field (| M.get_name (| globals, "apply_body_output" |), "transactions_root" |), + M.get_field (| M.get_field (| M.get_name (| globals, "block" |), "header" |), "transactions_root" |) + |); + M.get_name (| globals, "InvalidBlock" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + Compare.eq (| + M.get_field (| M.get_name (| globals, "apply_body_output" |), "state_root" |), + M.get_field (| M.get_field (| M.get_name (| globals, "block" |), "header" |), "state_root" |) + |); + M.get_name (| globals, "InvalidBlock" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + Compare.eq (| + M.get_field (| M.get_name (| globals, "apply_body_output" |), "receipt_root" |), + M.get_field (| M.get_field (| M.get_name (| globals, "block" |), "header" |), "receipt_root" |) + |); + M.get_name (| globals, "InvalidBlock" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + Compare.eq (| + M.get_field (| M.get_name (| globals, "apply_body_output" |), "block_logs_bloom" |), + M.get_field (| M.get_field (| M.get_name (| globals, "block" |), "header" |), "bloom" |) + |); + M.get_name (| globals, "InvalidBlock" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, "chain" |), "blocks" |), "append" |), + make_list [ + M.get_name (| globals, "block" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.gt (| + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_field (| M.get_name (| globals, "chain" |), "blocks" |) + ], + make_dict [] + |), + Constant.int 255 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign (| + M.get_field (| M.get_name (| globals, "chain" |), "blocks" |), + M.slice (| + M.get_field (| M.get_name (| globals, "chain" |), "blocks" |), + UnOp.sub (| Constant.int 255 |), + Constant.None_, + Constant.None_ + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + M.pure Constant.None_)). + +Definition calculate_base_fee_per_gas : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "block_gas_limit"; "parent_gas_limit"; "parent_gas_used"; "parent_base_fee_per_gas" ] |) in + let _ := Constant.str " + Calculates the base fee per gas for the block. + + Parameters + ---------- + block_gas_limit : + Gas limit of the block for which the base fee is being calculated. + parent_gas_limit : + Gas limit of the parent block. + parent_gas_used : + Gas used in the parent block. + parent_base_fee_per_gas : + Base fee per gas of the parent block. + + Returns + ------- + base_fee_per_gas : `Uint` + Base fee per gas for the block. + " in + let _ := M.assign_local (| + "parent_gas_target" , + BinOp.floor_div (| + M.get_name (| globals, "parent_gas_limit" |), + M.get_name (| globals, "ELASTICITY_MULTIPLIER" |) + |) + |) in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + M.call (| + M.get_name (| globals, "check_gas_limit" |), + make_list [ + M.get_name (| globals, "block_gas_limit" |); + M.get_name (| globals, "parent_gas_limit" |) + ], + make_dict [] + |); + M.get_name (| globals, "InvalidBlock" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, "parent_gas_used" |), + M.get_name (| globals, "parent_gas_target" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "expected_base_fee_per_gas" , + M.get_name (| globals, "parent_base_fee_per_gas" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + Compare.gt (| + M.get_name (| globals, "parent_gas_used" |), + M.get_name (| globals, "parent_gas_target" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "gas_used_delta" , + BinOp.sub (| + M.get_name (| globals, "parent_gas_used" |), + M.get_name (| globals, "parent_gas_target" |) + |) + |) in + let _ := M.assign_local (| + "parent_fee_gas_delta" , + BinOp.mult (| + M.get_name (| globals, "parent_base_fee_per_gas" |), + M.get_name (| globals, "gas_used_delta" |) + |) + |) in + let _ := M.assign_local (| + "target_fee_gas_delta" , + BinOp.floor_div (| + M.get_name (| globals, "parent_fee_gas_delta" |), + M.get_name (| globals, "parent_gas_target" |) + |) + |) in + let _ := M.assign_local (| + "base_fee_per_gas_delta" , + M.call (| + M.get_name (| globals, "max" |), + make_list [ + BinOp.floor_div (| + M.get_name (| globals, "target_fee_gas_delta" |), + M.get_name (| globals, "BASE_FEE_MAX_CHANGE_DENOMINATOR" |) + |); + Constant.int 1 + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "expected_base_fee_per_gas" , + BinOp.add (| + M.get_name (| globals, "parent_base_fee_per_gas" |), + M.get_name (| globals, "base_fee_per_gas_delta" |) + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "gas_used_delta" , + BinOp.sub (| + M.get_name (| globals, "parent_gas_target" |), + M.get_name (| globals, "parent_gas_used" |) + |) + |) in + let _ := M.assign_local (| + "parent_fee_gas_delta" , + BinOp.mult (| + M.get_name (| globals, "parent_base_fee_per_gas" |), + M.get_name (| globals, "gas_used_delta" |) + |) + |) in + let _ := M.assign_local (| + "target_fee_gas_delta" , + BinOp.floor_div (| + M.get_name (| globals, "parent_fee_gas_delta" |), + M.get_name (| globals, "parent_gas_target" |) + |) + |) in + let _ := M.assign_local (| + "base_fee_per_gas_delta" , + BinOp.floor_div (| + M.get_name (| globals, "target_fee_gas_delta" |), + M.get_name (| globals, "BASE_FEE_MAX_CHANGE_DENOMINATOR" |) + |) + |) in + let _ := M.assign_local (| + "expected_base_fee_per_gas" , + BinOp.sub (| + M.get_name (| globals, "parent_base_fee_per_gas" |), + M.get_name (| globals, "base_fee_per_gas_delta" |) + |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )) |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.get_name (| globals, "expected_base_fee_per_gas" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Definition validate_header : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "header"; "parent_header" ] |) in + let _ := Constant.str " + Verifies a block header. + + In order to consider a block's header valid, the logic for the + quantities in the header should match the logic for the block itself. + For example the header timestamp should be greater than the block's parent + timestamp because the block was created *after* the parent block. + Additionally, the block's number should be directly following the parent + block's number since it is the next block in the sequence. + + Parameters + ---------- + header : + Header to check for correctness. + parent_header : + Parent Header of the header to check for correctness + " in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + Compare.lt_e (| + M.get_field (| M.get_name (| globals, "header" |), "gas_used" |), + M.get_field (| M.get_name (| globals, "header" |), "gas_limit" |) + |); + M.get_name (| globals, "InvalidBlock" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "expected_base_fee_per_gas" , + M.call (| + M.get_name (| globals, "calculate_base_fee_per_gas" |), + make_list [ + M.get_field (| M.get_name (| globals, "header" |), "gas_limit" |); + M.get_field (| M.get_name (| globals, "parent_header" |), "gas_limit" |); + M.get_field (| M.get_name (| globals, "parent_header" |), "gas_used" |); + M.get_field (| M.get_name (| globals, "parent_header" |), "base_fee_per_gas" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + Compare.eq (| + M.get_name (| globals, "expected_base_fee_per_gas" |), + M.get_field (| M.get_name (| globals, "header" |), "base_fee_per_gas" |) + |); + M.get_name (| globals, "InvalidBlock" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "parent_has_ommers" , + Compare.not_eq (| + M.get_field (| M.get_name (| globals, "parent_header" |), "ommers_hash" |), + M.get_name (| globals, "EMPTY_OMMER_HASH" |) + |) + |) in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + Compare.gt (| + M.get_field (| M.get_name (| globals, "header" |), "timestamp" |), + M.get_field (| M.get_name (| globals, "parent_header" |), "timestamp" |) + |); + M.get_name (| globals, "InvalidBlock" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + Compare.eq (| + M.get_field (| M.get_name (| globals, "header" |), "number" |), + BinOp.add (| + M.get_field (| M.get_name (| globals, "parent_header" |), "number" |), + Constant.int 1 + |) + |); + M.get_name (| globals, "InvalidBlock" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + Compare.lt_e (| + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_field (| M.get_name (| globals, "header" |), "extra_data" |) + ], + make_dict [] + |), + Constant.int 32 + |); + M.get_name (| globals, "InvalidBlock" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "block_difficulty" , + M.call (| + M.get_name (| globals, "calculate_block_difficulty" |), + make_list [ + M.get_field (| M.get_name (| globals, "header" |), "number" |); + M.get_field (| M.get_name (| globals, "header" |), "timestamp" |); + M.get_field (| M.get_name (| globals, "parent_header" |), "timestamp" |); + M.get_field (| M.get_name (| globals, "parent_header" |), "difficulty" |); + M.get_name (| globals, "parent_has_ommers" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + Compare.eq (| + M.get_field (| M.get_name (| globals, "header" |), "difficulty" |), + M.get_name (| globals, "block_difficulty" |) + |); + M.get_name (| globals, "InvalidBlock" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "block_parent_hash" , + M.call (| + M.get_name (| globals, "keccak256" |), + make_list [ + M.call (| + M.get_field (| M.get_name (| globals, "rlp" |), "encode" |), + make_list [ + M.get_name (| globals, "parent_header" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + Compare.eq (| + M.get_field (| M.get_name (| globals, "header" |), "parent_hash" |), + M.get_name (| globals, "block_parent_hash" |) + |); + M.get_name (| globals, "InvalidBlock" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "validate_proof_of_work" |), + make_list [ + M.get_name (| globals, "header" |) + ], + make_dict [] + |) in + M.pure Constant.None_)). + +Definition generate_header_hash_for_pow : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "header" ] |) in + let _ := Constant.str " + Generate rlp hash of the header which is to be used for Proof-of-Work + verification. + + In other words, the PoW artefacts `mix_digest` and `nonce` are ignored + while calculating this hash. + + A particular PoW is valid for a single hash, that hash is computed by + this function. The `nonce` and `mix_digest` are omitted from this hash + because they are being changed by miners in their search for a sufficient + proof-of-work. + + Parameters + ---------- + header : + The header object for which the hash is to be generated. + + Returns + ------- + hash : `Hash32` + The PoW valid rlp hash of the passed in header. + " in + let _ := M.assign_local (| + "header_data_without_pow_artefacts" , + make_list [ + M.get_field (| M.get_name (| globals, "header" |), "parent_hash" |); + M.get_field (| M.get_name (| globals, "header" |), "ommers_hash" |); + M.get_field (| M.get_name (| globals, "header" |), "coinbase" |); + M.get_field (| M.get_name (| globals, "header" |), "state_root" |); + M.get_field (| M.get_name (| globals, "header" |), "transactions_root" |); + M.get_field (| M.get_name (| globals, "header" |), "receipt_root" |); + M.get_field (| M.get_name (| globals, "header" |), "bloom" |); + M.get_field (| M.get_name (| globals, "header" |), "difficulty" |); + M.get_field (| M.get_name (| globals, "header" |), "number" |); + M.get_field (| M.get_name (| globals, "header" |), "gas_limit" |); + M.get_field (| M.get_name (| globals, "header" |), "gas_used" |); + M.get_field (| M.get_name (| globals, "header" |), "timestamp" |); + M.get_field (| M.get_name (| globals, "header" |), "extra_data" |); + M.get_field (| M.get_name (| globals, "header" |), "base_fee_per_gas" |) + ] + |) in + let _ := M.return_ (| + M.call (| + M.get_field (| M.get_name (| globals, "rlp" |), "rlp_hash" |), + make_list [ + M.get_name (| globals, "header_data_without_pow_artefacts" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Definition validate_proof_of_work : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "header" ] |) in + let _ := Constant.str " + Validates the Proof of Work constraints. + + In order to verify that a miner's proof-of-work is valid for a block, a + ``mix-digest`` and ``result`` are calculated using the ``hashimoto_light`` + hash function. The mix digest is a hash of the header and the nonce that + is passed through and it confirms whether or not proof-of-work was done + on the correct block. The result is the actual hash value of the block. + + Parameters + ---------- + header : + Header of interest. + " in + let _ := M.assign_local (| + "header_hash" , + M.call (| + M.get_name (| globals, "generate_header_hash_for_pow" |), + make_list [ + M.get_name (| globals, "header" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "cache" , + M.call (| + M.get_name (| globals, "generate_cache" |), + make_list [ + M.get_field (| M.get_name (| globals, "header" |), "number" |) + ], + make_dict [] + |) + |) in + let _ := M.assign (| + make_tuple [ M.get_name (| globals, "mix_digest" |); M.get_name (| globals, "result" |) ], + M.call (| + M.get_name (| globals, "hashimoto_light" |), + make_list [ + M.get_name (| globals, "header_hash" |); + M.get_field (| M.get_name (| globals, "header" |), "nonce" |); + M.get_name (| globals, "cache" |); + M.call (| + M.get_name (| globals, "dataset_size" |), + make_list [ + M.get_field (| M.get_name (| globals, "header" |), "number" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + Compare.eq (| + M.get_name (| globals, "mix_digest" |), + M.get_field (| M.get_name (| globals, "header" |), "mix_digest" |) + |); + M.get_name (| globals, "InvalidBlock" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + Compare.lt_e (| + M.call (| + M.get_field (| M.get_name (| globals, "Uint" |), "from_be_bytes" |), + make_list [ + M.get_name (| globals, "result" |) + ], + make_dict [] + |), + BinOp.floor_div (| + M.get_name (| globals, "U256_CEIL_VALUE" |), + M.get_field (| M.get_name (| globals, "header" |), "difficulty" |) + |) + |); + M.get_name (| globals, "InvalidBlock" |) + ], + make_dict [] + |) in + M.pure Constant.None_)). + +Definition check_transaction : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "tx"; "base_fee_per_gas"; "gas_available"; "chain_id" ] |) in + let _ := Constant.str " + Check if the transaction is includable in the block. + + Parameters + ---------- + tx : + The transaction. + base_fee_per_gas : + The block base fee. + gas_available : + The gas remaining in the block. + chain_id : + The ID of the current chain. + + Returns + ------- + sender_address : + The sender of the transaction. + effective_gas_price : + The price to charge for gas when the transaction is executed. + + Raises + ------ + InvalidBlock : + If the transaction is not includable. + " in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + Compare.lt_e (| + M.get_field (| M.get_name (| globals, "tx" |), "gas" |), + M.get_name (| globals, "gas_available" |) + |); + M.get_name (| globals, "InvalidBlock" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "sender_address" , + M.call (| + M.get_name (| globals, "recover_sender" |), + make_list [ + M.get_name (| globals, "chain_id" |); + M.get_name (| globals, "tx" |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, "isinstance" |), + make_list [ + M.get_name (| globals, "tx" |); + M.get_name (| globals, "FeeMarketTransaction" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + Compare.gt_e (| + M.get_field (| M.get_name (| globals, "tx" |), "max_fee_per_gas" |), + M.get_field (| M.get_name (| globals, "tx" |), "max_priority_fee_per_gas" |) + |); + M.get_name (| globals, "InvalidBlock" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + Compare.gt_e (| + M.get_field (| M.get_name (| globals, "tx" |), "max_fee_per_gas" |), + M.get_name (| globals, "base_fee_per_gas" |) + |); + M.get_name (| globals, "InvalidBlock" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "priority_fee_per_gas" , + M.call (| + M.get_name (| globals, "min" |), + make_list [ + M.get_field (| M.get_name (| globals, "tx" |), "max_priority_fee_per_gas" |); + BinOp.sub (| + M.get_field (| M.get_name (| globals, "tx" |), "max_fee_per_gas" |), + M.get_name (| globals, "base_fee_per_gas" |) + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "effective_gas_price" , + BinOp.add (| + M.get_name (| globals, "priority_fee_per_gas" |), + M.get_name (| globals, "base_fee_per_gas" |) + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + Compare.gt_e (| + M.get_field (| M.get_name (| globals, "tx" |), "gas_price" |), + M.get_name (| globals, "base_fee_per_gas" |) + |); + M.get_name (| globals, "InvalidBlock" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "effective_gas_price" , + M.get_field (| M.get_name (| globals, "tx" |), "gas_price" |) + |) in + M.pure Constant.None_ + )) |) in + let _ := M.return_ (| + make_tuple [ M.get_name (| globals, "sender_address" |); M.get_name (| globals, "effective_gas_price" |) ] + |) in + M.pure Constant.None_)). + +Definition make_receipt : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "tx"; "error"; "cumulative_gas_used"; "logs" ] |) in + let _ := Constant.str " + Make the receipt for a transaction that was executed. + + Parameters + ---------- + tx : + The executed transaction. + error : + Error in the top level frame of the transaction, if any. + cumulative_gas_used : + The total gas used so far in the block after the transaction was + executed. + logs : + The logs produced by the transaction. + + Returns + ------- + receipt : + The receipt for the transaction. + " in + let _ := M.assign_local (| + "receipt" , + M.call (| + M.get_name (| globals, "Receipt" |), + make_list [], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, "isinstance" |), + make_list [ + M.get_name (| globals, "tx" |); + M.get_name (| globals, "AccessListTransaction" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + BinOp.add (| + Constant.bytes "01", + M.call (| + M.get_field (| M.get_name (| globals, "rlp" |), "encode" |), + make_list [ + M.get_name (| globals, "receipt" |) + ], + make_dict [] + |) + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, "isinstance" |), + make_list [ + M.get_name (| globals, "tx" |); + M.get_name (| globals, "FeeMarketTransaction" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + BinOp.add (| + Constant.bytes "02", + M.call (| + M.get_field (| M.get_name (| globals, "rlp" |), "encode" |), + make_list [ + M.get_name (| globals, "receipt" |) + ], + make_dict [] + |) + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.return_ (| + M.get_name (| globals, "receipt" |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_)). + +Definition ApplyBodyOutput : Value.t := + builtins.make_klass + [] + [ + + ] + [ + + ]. + +Definition apply_body : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "state"; "block_hashes"; "coinbase"; "block_number"; "base_fee_per_gas"; "block_gas_limit"; "block_time"; "block_difficulty"; "transactions"; "ommers"; "chain_id" ] |) in + let _ := Constant.str " + Executes a block. + + Many of the contents of a block are stored in data structures called + tries. There is a transactions trie which is similar to a ledger of the + transactions stored in the current block. There is also a receipts trie + which stores the results of executing a transaction, like the post state + and gas used. This function creates and executes the block that is to be + added to the chain. + + Parameters + ---------- + state : + Current account state. + block_hashes : + List of hashes of the previous 256 blocks in the order of + increasing block number. + coinbase : + Address of account which receives block reward and transaction fees. + block_number : + Position of the block within the chain. + base_fee_per_gas : + Base fee per gas of within the block. + block_gas_limit : + Initial amount of gas available for execution in this block. + block_time : + Time the block was produced, measured in seconds since the epoch. + block_difficulty : + Difficulty of the block. + transactions : + Transactions included in the block. + ommers : + Headers of ancestor blocks which are not direct parents (formerly + uncles.) + chain_id : + ID of the executing chain. + + Returns + ------- + apply_body_output : `ApplyBodyOutput` + Output of applying the block body to the state. + " in + let _ := M.assign_local (| + "gas_available" , + M.get_name (| globals, "block_gas_limit" |) + |) in +(* At stmt: unsupported node type: AnnAssign *) +(* At stmt: unsupported node type: AnnAssign *) +(* At stmt: unsupported node type: AnnAssign *) + let _ := + M.for_ (| + make_tuple [ M.get_name (| globals, "i" |); M.get_name (| globals, "tx" |) ], + M.call (| + M.get_name (| globals, "enumerate" |), + make_list [ + M.call (| + M.get_name (| globals, "map" |), + make_list [ + M.get_name (| globals, "decode_transaction" |); + M.get_name (| globals, "transactions" |) + ], + make_dict [] + |) + ], + make_dict [] + |), + ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, "trie_set" |), + make_list [ + M.get_name (| globals, "transactions_trie" |); + M.call (| + M.get_field (| M.get_name (| globals, "rlp" |), "encode" |), + make_list [ + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.get_name (| globals, "i" |) + ], + make_dict [] + |) + ], + make_dict [] + |); + M.call (| + M.get_name (| globals, "encode_transaction" |), + make_list [ + M.get_name (| globals, "tx" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign (| + make_tuple [ M.get_name (| globals, "sender_address" |); M.get_name (| globals, "effective_gas_price" |) ], + M.call (| + M.get_name (| globals, "check_transaction" |), + make_list [ + M.get_name (| globals, "tx" |); + M.get_name (| globals, "base_fee_per_gas" |); + M.get_name (| globals, "gas_available" |); + M.get_name (| globals, "chain_id" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "env" , + M.call (| + M.get_field (| M.get_name (| globals, "vm" |), "Environment" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.assign (| + make_tuple [ M.get_name (| globals, "gas_used" |); M.get_name (| globals, "logs" |); M.get_name (| globals, "error" |) ], + M.call (| + M.get_name (| globals, "process_transaction" |), + make_list [ + M.get_name (| globals, "env" |); + M.get_name (| globals, "tx" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_op_local (| + BinOp.sub, + "gas_available", + M.get_name (| globals, "gas_used" |) + |) in + let _ := M.assign_local (| + "receipt" , + M.call (| + M.get_name (| globals, "make_receipt" |), + make_list [ + M.get_name (| globals, "tx" |); + M.get_name (| globals, "error" |); + BinOp.sub (| + M.get_name (| globals, "block_gas_limit" |), + M.get_name (| globals, "gas_available" |) + |); + M.get_name (| globals, "logs" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "trie_set" |), + make_list [ + M.get_name (| globals, "receipts_trie" |); + M.call (| + M.get_field (| M.get_name (| globals, "rlp" |), "encode" |), + make_list [ + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.get_name (| globals, "i" |) + ], + make_dict [] + |) + ], + make_dict [] + |); + M.get_name (| globals, "receipt" |) + ], + make_dict [] + |) in + let _ := M.assign_op_local (| + BinOp.add, + "block_logs", + M.get_name (| globals, "logs" |) + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := M.call (| + M.get_name (| globals, "pay_rewards" |), + make_list [ + M.get_name (| globals, "state" |); + M.get_name (| globals, "block_number" |); + M.get_name (| globals, "coinbase" |); + M.get_name (| globals, "ommers" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "block_gas_used" , + BinOp.sub (| + M.get_name (| globals, "block_gas_limit" |), + M.get_name (| globals, "gas_available" |) + |) + |) in + let _ := M.assign_local (| + "block_logs_bloom" , + M.call (| + M.get_name (| globals, "logs_bloom" |), + make_list [ + M.get_name (| globals, "block_logs" |) + ], + make_dict [] + |) + |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, "ApplyBodyOutput" |), + make_list [ + M.get_name (| globals, "block_gas_used" |); + M.call (| + M.get_name (| globals, "root" |), + make_list [ + M.get_name (| globals, "transactions_trie" |) + ], + make_dict [] + |); + M.call (| + M.get_name (| globals, "root" |), + make_list [ + M.get_name (| globals, "receipts_trie" |) + ], + make_dict [] + |); + M.get_name (| globals, "block_logs_bloom" |); + M.call (| + M.get_name (| globals, "state_root" |), + make_list [ + M.get_name (| globals, "state" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Definition validate_ommers : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "ommers"; "block_header"; "chain" ] |) in + let _ := Constant.str " + Validates the ommers mentioned in the block. + + An ommer block is a block that wasn't canonically added to the + blockchain because it wasn't validated as fast as the canonical block + but was mined at the same time. + + To be considered valid, the ommers must adhere to the rules defined in + the Ethereum protocol. The maximum amount of ommers is 2 per block and + there cannot be duplicate ommers in a block. Many of the other ommer + constraints are listed in the in-line comments of this function. + + Parameters + ---------- + ommers : + List of ommers mentioned in the current block. + block_header: + The header of current block. + chain : + History and current state. + " in + let _ := M.assign_local (| + "block_hash" , + M.call (| + M.get_field (| M.get_name (| globals, "rlp" |), "rlp_hash" |), + make_list [ + M.get_name (| globals, "block_header" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + Compare.eq (| + M.call (| + M.get_field (| M.get_name (| globals, "rlp" |), "rlp_hash" |), + make_list [ + M.get_name (| globals, "ommers" |) + ], + make_dict [] + |), + M.get_field (| M.get_name (| globals, "block_header" |), "ommers_hash" |) + |); + M.get_name (| globals, "InvalidBlock" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_name (| globals, "ommers" |) + ], + make_dict [] + |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + Constant.None_ + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + M.for_ (| + M.get_name (| globals, "ommer" |), + M.get_name (| globals, "ommers" |), + ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + BoolOp.and (| + Compare.lt_e (| + Constant.int 1, + M.get_field (| M.get_name (| globals, "ommer" |), "number" |) + |), + ltac:(M.monadic ( + Compare.lt (| + M.get_field (| M.get_name (| globals, "ommer" |), "number" |), + M.get_field (| M.get_name (| globals, "block_header" |), "number" |) + |) + )) + |); + M.get_name (| globals, "InvalidBlock" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "ommer_parent_header" , + M.get_field (| M.get_subscript (| + M.get_field (| M.get_name (| globals, "chain" |), "blocks" |), + BinOp.sub (| + UnOp.sub (| BinOp.sub (| + M.get_field (| M.get_name (| globals, "block_header" |), "number" |), + M.get_field (| M.get_name (| globals, "ommer" |), "number" |) + |) |), + Constant.int 1 + |) + |), "header" |) + |) in + let _ := M.call (| + M.get_name (| globals, "validate_header" |), + make_list [ + M.get_name (| globals, "ommer" |); + M.get_name (| globals, "ommer_parent_header" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + Compare.lt_e (| + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_name (| globals, "ommers" |) + ], + make_dict [] + |), + Constant.int 2 + |); + M.get_name (| globals, "InvalidBlock" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "ommers_hashes" , + Constant.str "(* At expr: unsupported node type: ListComp *)" + |) in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + Compare.eq (| + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_name (| globals, "ommers_hashes" |) + ], + make_dict [] + |), + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.call (| + M.get_name (| globals, "set" |), + make_list [ + M.get_name (| globals, "ommers_hashes" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |); + M.get_name (| globals, "InvalidBlock" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "recent_canonical_blocks" , + M.slice (| + M.get_field (| M.get_name (| globals, "chain" |), "blocks" |), + UnOp.sub (| BinOp.add (| + M.get_name (| globals, "MAX_OMMER_DEPTH" |), + Constant.int 1 + |) |), + Constant.None_, + Constant.None_ + |) + |) in + let _ := M.assign_local (| + "recent_canonical_block_hashes" , + Constant.str "(* At expr: unsupported node type: SetComp *)" + |) in +(* At stmt: unsupported node type: AnnAssign *) + let _ := + M.for_ (| + M.get_name (| globals, "block" |), + M.get_name (| globals, "recent_canonical_blocks" |), + ltac:(M.monadic ( + let _ := M.assign_local (| + "recent_ommers_hashes" , + M.call (| + M.get_field (| M.get_name (| globals, "recent_ommers_hashes" |), "union" |), + make_list [ + Constant.str "(* At expr: unsupported node type: SetComp *)" + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := + M.for_ (| + make_tuple [ M.get_name (| globals, "ommer_index" |); M.get_name (| globals, "ommer" |) ], + M.call (| + M.get_name (| globals, "enumerate" |), + make_list [ + M.get_name (| globals, "ommers" |) + ], + make_dict [] + |), + ltac:(M.monadic ( + let _ := M.assign_local (| + "ommer_hash" , + M.get_subscript (| + M.get_name (| globals, "ommers_hashes" |), + M.get_name (| globals, "ommer_index" |) + |) + |) in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + Compare.not_eq (| + M.get_name (| globals, "ommer_hash" |), + M.get_name (| globals, "block_hash" |) + |); + M.get_name (| globals, "InvalidBlock" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + Compare.not_in (| + M.get_name (| globals, "ommer_hash" |), + M.get_name (| globals, "recent_canonical_block_hashes" |) + |); + M.get_name (| globals, "InvalidBlock" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + Compare.not_in (| + M.get_name (| globals, "ommer_hash" |), + M.get_name (| globals, "recent_ommers_hashes" |) + |); + M.get_name (| globals, "InvalidBlock" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "ommer_age" , + BinOp.sub (| + M.get_field (| M.get_name (| globals, "block_header" |), "number" |), + M.get_field (| M.get_name (| globals, "ommer" |), "number" |) + |) + |) in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + BoolOp.and (| + Compare.lt_e (| + Constant.int 1, + M.get_name (| globals, "ommer_age" |) + |), + ltac:(M.monadic ( + Compare.lt_e (| + M.get_name (| globals, "ommer_age" |), + M.get_name (| globals, "MAX_OMMER_DEPTH" |) + |) + )) + |); + M.get_name (| globals, "InvalidBlock" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + Compare.in_ (| + M.get_field (| M.get_name (| globals, "ommer" |), "parent_hash" |), + M.get_name (| globals, "recent_canonical_block_hashes" |) + |); + M.get_name (| globals, "InvalidBlock" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + Compare.not_eq (| + M.get_field (| M.get_name (| globals, "ommer" |), "parent_hash" |), + M.get_field (| M.get_name (| globals, "block_header" |), "parent_hash" |) + |); + M.get_name (| globals, "InvalidBlock" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + M.pure Constant.None_)). + +Definition pay_rewards : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "state"; "block_number"; "coinbase"; "ommers" ] |) in + let _ := Constant.str " + Pay rewards to the block miner as well as the ommers miners. + + The miner of the canonical block is rewarded with the predetermined + block reward, ``BLOCK_REWARD``, plus a variable award based off of the + number of ommer blocks that were mined around the same time, and included + in the canonical block's header. An ommer block is a block that wasn't + added to the canonical blockchain because it wasn't validated as fast as + the accepted block but was mined at the same time. Although not all blocks + that are mined are added to the canonical chain, miners are still paid a + reward for their efforts. This reward is called an ommer reward and is + calculated based on the number associated with the ommer block that they + mined. + + Parameters + ---------- + state : + Current account state. + block_number : + Position of the block within the chain. + coinbase : + Address of account which receives block reward and transaction fees. + ommers : + List of ommers mentioned in the current block. + " in + let _ := M.assign_local (| + "miner_reward" , + BinOp.add (| + M.get_name (| globals, "BLOCK_REWARD" |), + BinOp.mult (| + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_name (| globals, "ommers" |) + ], + make_dict [] + |), + BinOp.floor_div (| + M.get_name (| globals, "BLOCK_REWARD" |), + Constant.int 32 + |) + |) + |) + |) in + let _ := M.call (| + M.get_name (| globals, "create_ether" |), + make_list [ + M.get_name (| globals, "state" |); + M.get_name (| globals, "coinbase" |); + M.get_name (| globals, "miner_reward" |) + ], + make_dict [] + |) in + let _ := + M.for_ (| + M.get_name (| globals, "ommer" |), + M.get_name (| globals, "ommers" |), + ltac:(M.monadic ( + let _ := M.assign_local (| + "ommer_age" , + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + BinOp.sub (| + M.get_name (| globals, "block_number" |), + M.get_field (| M.get_name (| globals, "ommer" |), "number" |) + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "ommer_miner_reward" , + BinOp.floor_div (| + BinOp.mult (| + BinOp.sub (| + Constant.int 8, + M.get_name (| globals, "ommer_age" |) + |), + M.get_name (| globals, "BLOCK_REWARD" |) + |), + Constant.int 8 + |) + |) in + let _ := M.call (| + M.get_name (| globals, "create_ether" |), + make_list [ + M.get_name (| globals, "state" |); + M.get_field (| M.get_name (| globals, "ommer" |), "coinbase" |); + M.get_name (| globals, "ommer_miner_reward" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + M.pure Constant.None_)). + +Definition process_transaction : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "env"; "tx" ] |) in + let _ := Constant.str " + Execute a transaction against the provided environment. + + This function processes the actions needed to execute a transaction. + It decrements the sender's account after calculating the gas fee and + refunds them the proper amount after execution. Calling contracts, + deploying code, and incrementing nonces are all examples of actions that + happen within this function or from a call made within this function. + + Accounts that are marked for deletion are processed and destroyed after + execution. + + Parameters + ---------- + env : + Environment for the Ethereum Virtual Machine. + tx : + Transaction to execute. + + Returns + ------- + gas_left : `ethereum.base_types.U256` + Remaining gas after execution. + logs : `Tuple[ethereum.blocks.Log, ...]` + Logs generated during execution. + " in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + M.call (| + M.get_name (| globals, "validate_transaction" |), + make_list [ + M.get_name (| globals, "tx" |) + ], + make_dict [] + |); + M.get_name (| globals, "InvalidBlock" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "sender" , + M.get_field (| M.get_name (| globals, "env" |), "origin" |) + |) in + let _ := M.assign_local (| + "sender_account" , + M.call (| + M.get_name (| globals, "get_account" |), + make_list [ + M.get_field (| M.get_name (| globals, "env" |), "state" |); + M.get_name (| globals, "sender" |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, "isinstance" |), + make_list [ + M.get_name (| globals, "tx" |); + M.get_name (| globals, "FeeMarketTransaction" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "max_gas_fee" , + BinOp.mult (| + M.get_field (| M.get_name (| globals, "tx" |), "gas" |), + M.get_field (| M.get_name (| globals, "tx" |), "max_fee_per_gas" |) + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "max_gas_fee" , + BinOp.mult (| + M.get_field (| M.get_name (| globals, "tx" |), "gas" |), + M.get_field (| M.get_name (| globals, "tx" |), "gas_price" |) + |) + |) in + M.pure Constant.None_ + )) |) in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + Compare.eq (| + M.get_field (| M.get_name (| globals, "sender_account" |), "nonce" |), + M.get_field (| M.get_name (| globals, "tx" |), "nonce" |) + |); + M.get_name (| globals, "InvalidBlock" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + Compare.gt_e (| + M.get_field (| M.get_name (| globals, "sender_account" |), "balance" |), + BinOp.add (| + M.get_name (| globals, "max_gas_fee" |), + M.get_field (| M.get_name (| globals, "tx" |), "value" |) + |) + |); + M.get_name (| globals, "InvalidBlock" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + Compare.eq (| + M.get_field (| M.get_name (| globals, "sender_account" |), "code" |), + M.call (| + M.get_name (| globals, "bytearray" |), + make_list [], + make_dict [] + |) + |); + M.get_name (| globals, "InvalidBlock" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "effective_gas_fee" , + BinOp.mult (| + M.get_field (| M.get_name (| globals, "tx" |), "gas" |), + M.get_field (| M.get_name (| globals, "env" |), "gas_price" |) + |) + |) in + let _ := M.assign_local (| + "gas" , + BinOp.sub (| + M.get_field (| M.get_name (| globals, "tx" |), "gas" |), + M.call (| + M.get_name (| globals, "calculate_intrinsic_cost" |), + make_list [ + M.get_name (| globals, "tx" |) + ], + make_dict [] + |) + |) + |) in + let _ := M.call (| + M.get_name (| globals, "increment_nonce" |), + make_list [ + M.get_field (| M.get_name (| globals, "env" |), "state" |); + M.get_name (| globals, "sender" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "sender_balance_after_gas_fee" , + BinOp.sub (| + M.get_field (| M.get_name (| globals, "sender_account" |), "balance" |), + M.get_name (| globals, "effective_gas_fee" |) + |) + |) in + let _ := M.call (| + M.get_name (| globals, "set_account_balance" |), + make_list [ + M.get_field (| M.get_name (| globals, "env" |), "state" |); + M.get_name (| globals, "sender" |); + M.get_name (| globals, "sender_balance_after_gas_fee" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "preaccessed_addresses" , + M.call (| + M.get_name (| globals, "set" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "preaccessed_storage_keys" , + M.call (| + M.get_name (| globals, "set" |), + make_list [], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, "isinstance" |), + make_list [ + M.get_name (| globals, "tx" |); + make_tuple [ M.get_name (| globals, "AccessListTransaction" |); M.get_name (| globals, "FeeMarketTransaction" |) ] + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := + M.for_ (| + make_tuple [ M.get_name (| globals, "address" |); M.get_name (| globals, "keys" |) ], + M.get_field (| M.get_name (| globals, "tx" |), "access_list" |), + ltac:(M.monadic ( + let _ := M.call (| + M.get_field (| M.get_name (| globals, "preaccessed_addresses" |), "add" |), + make_list [ + M.get_name (| globals, "address" |) + ], + make_dict [] + |) in + let _ := + M.for_ (| + M.get_name (| globals, "key" |), + M.get_name (| globals, "keys" |), + ltac:(M.monadic ( + let _ := M.call (| + M.get_field (| M.get_name (| globals, "preaccessed_storage_keys" |), "add" |), + make_list [ + make_tuple [ M.get_name (| globals, "address" |); M.get_name (| globals, "key" |) ] + ], + make_dict [] + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "message" , + M.call (| + M.get_name (| globals, "prepare_message" |), + make_list [ + M.get_name (| globals, "sender" |); + M.get_field (| M.get_name (| globals, "tx" |), "to" |); + M.get_field (| M.get_name (| globals, "tx" |), "value" |); + M.get_field (| M.get_name (| globals, "tx" |), "data" |); + M.get_name (| globals, "gas" |); + M.get_name (| globals, "env" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "output" , + M.call (| + M.get_name (| globals, "process_message_call" |), + make_list [ + M.get_name (| globals, "message" |); + M.get_name (| globals, "env" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "gas_used" , + BinOp.sub (| + M.get_field (| M.get_name (| globals, "tx" |), "gas" |), + M.get_field (| M.get_name (| globals, "output" |), "gas_left" |) + |) + |) in + let _ := M.assign_local (| + "gas_refund" , + M.call (| + M.get_name (| globals, "min" |), + make_list [ + BinOp.floor_div (| + M.get_name (| globals, "gas_used" |), + Constant.int 5 + |); + M.get_field (| M.get_name (| globals, "output" |), "refund_counter" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "gas_refund_amount" , + BinOp.mult (| + BinOp.add (| + M.get_field (| M.get_name (| globals, "output" |), "gas_left" |), + M.get_name (| globals, "gas_refund" |) + |), + M.get_field (| M.get_name (| globals, "env" |), "gas_price" |) + |) + |) in + let _ := M.assign_local (| + "priority_fee_per_gas" , + BinOp.sub (| + M.get_field (| M.get_name (| globals, "env" |), "gas_price" |), + M.get_field (| M.get_name (| globals, "env" |), "base_fee_per_gas" |) + |) + |) in + let _ := M.assign_local (| + "transaction_fee" , + BinOp.mult (| + BinOp.sub (| + BinOp.sub (| + M.get_field (| M.get_name (| globals, "tx" |), "gas" |), + M.get_field (| M.get_name (| globals, "output" |), "gas_left" |) + |), + M.get_name (| globals, "gas_refund" |) + |), + M.get_name (| globals, "priority_fee_per_gas" |) + |) + |) in + let _ := M.assign_local (| + "total_gas_used" , + BinOp.sub (| + M.get_name (| globals, "gas_used" |), + M.get_name (| globals, "gas_refund" |) + |) + |) in + let _ := M.assign_local (| + "sender_balance_after_refund" , + BinOp.add (| + M.get_field (| M.call (| + M.get_name (| globals, "get_account" |), + make_list [ + M.get_field (| M.get_name (| globals, "env" |), "state" |); + M.get_name (| globals, "sender" |) + ], + make_dict [] + |), "balance" |), + M.get_name (| globals, "gas_refund_amount" |) + |) + |) in + let _ := M.call (| + M.get_name (| globals, "set_account_balance" |), + make_list [ + M.get_field (| M.get_name (| globals, "env" |), "state" |); + M.get_name (| globals, "sender" |); + M.get_name (| globals, "sender_balance_after_refund" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "coinbase_balance_after_mining_fee" , + BinOp.add (| + M.get_field (| M.call (| + M.get_name (| globals, "get_account" |), + make_list [ + M.get_field (| M.get_name (| globals, "env" |), "state" |); + M.get_field (| M.get_name (| globals, "env" |), "coinbase" |) + ], + make_dict [] + |), "balance" |), + M.get_name (| globals, "transaction_fee" |) + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.not_eq (| + M.get_name (| globals, "coinbase_balance_after_mining_fee" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, "set_account_balance" |), + make_list [ + M.get_field (| M.get_name (| globals, "env" |), "state" |); + M.get_field (| M.get_name (| globals, "env" |), "coinbase" |); + M.get_name (| globals, "coinbase_balance_after_mining_fee" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, "account_exists_and_is_empty" |), + make_list [ + M.get_field (| M.get_name (| globals, "env" |), "state" |); + M.get_field (| M.get_name (| globals, "env" |), "coinbase" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, "destroy_account" |), + make_list [ + M.get_field (| M.get_name (| globals, "env" |), "state" |); + M.get_field (| M.get_name (| globals, "env" |), "coinbase" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )) |) in + let _ := + M.for_ (| + M.get_name (| globals, "address" |), + M.get_field (| M.get_name (| globals, "output" |), "accounts_to_delete" |), + ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, "destroy_account" |), + make_list [ + M.get_field (| M.get_name (| globals, "env" |), "state" |); + M.get_name (| globals, "address" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := + M.for_ (| + M.get_name (| globals, "address" |), + M.get_field (| M.get_name (| globals, "output" |), "touched_accounts" |), + ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, "account_exists_and_is_empty" |), + make_list [ + M.get_field (| M.get_name (| globals, "env" |), "state" |); + M.get_name (| globals, "address" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, "destroy_account" |), + make_list [ + M.get_field (| M.get_name (| globals, "env" |), "state" |); + M.get_name (| globals, "address" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := M.return_ (| + make_tuple [ M.get_name (| globals, "total_gas_used" |); M.get_field (| M.get_name (| globals, "output" |), "logs" |); M.get_field (| M.get_name (| globals, "output" |), "error" |) ] + |) in + M.pure Constant.None_)). + +Definition validate_transaction : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "tx" ] |) in + let _ := Constant.str " + Verifies a transaction. + + The gas in a transaction gets used to pay for the intrinsic cost of + operations, therefore if there is insufficient gas then it would not + be possible to execute a transaction and it will be declared invalid. + + Additionally, the nonce of a transaction must not equal or exceed the + limit defined in `EIP-2681 `_. + In practice, defining the limit as ``2**64-1`` has no impact because + sending ``2**64-1`` transactions is improbable. It's not strictly + impossible though, ``2**64-1`` transactions is the entire capacity of the + Ethereum blockchain at 2022 gas limits for a little over 22 years. + + Parameters + ---------- + tx : + Transaction to validate. + + Returns + ------- + verified : `bool` + True if the transaction can be executed, or False otherwise. + " in + let _ := M.return_ (| + BoolOp.and (| + Compare.lt_e (| + M.call (| + M.get_name (| globals, "calculate_intrinsic_cost" |), + make_list [ + M.get_name (| globals, "tx" |) + ], + make_dict [] + |), + M.get_field (| M.get_name (| globals, "tx" |), "gas" |) + |), + ltac:(M.monadic ( + Compare.lt (| + M.get_field (| M.get_name (| globals, "tx" |), "nonce" |), + BinOp.sub (| + BinOp.pow (| + Constant.int 2, + Constant.int 64 + |), + Constant.int 1 + |) + |) + )) + |) + |) in + M.pure Constant.None_)). + +Definition calculate_intrinsic_cost : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "tx" ] |) in + let _ := Constant.str " + Calculates the gas that is charged before execution is started. + + The intrinsic cost of the transaction is charged before execution has + begun. Functions/operations in the EVM cost money to execute so this + intrinsic cost is for the operations that need to be paid for as part of + the transaction. Data transfer, for example, is part of this intrinsic + cost. It costs ether to send data over the wire and that ether is + accounted for in the intrinsic cost calculated in this function. This + intrinsic cost must be calculated and paid for before execution in order + for all operations to be implemented. + + Parameters + ---------- + tx : + Transaction to compute the intrinsic cost of. + + Returns + ------- + verified : `ethereum.base_types.Uint` + The intrinsic cost of the transaction. + " in + let _ := M.assign_local (| + "data_cost" , + Constant.int 0 + |) in + let _ := + M.for_ (| + M.get_name (| globals, "byte" |), + M.get_field (| M.get_name (| globals, "tx" |), "data" |), + ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, "byte" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_op_local (| + BinOp.add, + "data_cost", + M.get_name (| globals, "TX_DATA_COST_PER_ZERO" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_op_local (| + BinOp.add, + "data_cost", + M.get_name (| globals, "TX_DATA_COST_PER_NON_ZERO" |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_field (| M.get_name (| globals, "tx" |), "to" |), + M.call (| + M.get_name (| globals, "Bytes0" |), + make_list [ + Constant.bytes "" + ], + make_dict [] + |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "create_cost" , + M.get_name (| globals, "TX_CREATE_COST" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "create_cost" , + Constant.int 0 + |) in + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "access_list_cost" , + Constant.int 0 + |) in + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, "isinstance" |), + make_list [ + M.get_name (| globals, "tx" |); + make_tuple [ M.get_name (| globals, "AccessListTransaction" |); M.get_name (| globals, "FeeMarketTransaction" |) ] + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := + M.for_ (| + make_tuple [ M.get_name (| globals, "_address" |); M.get_name (| globals, "keys" |) ], + M.get_field (| M.get_name (| globals, "tx" |), "access_list" |), + ltac:(M.monadic ( + let _ := M.assign_op_local (| + BinOp.add, + "access_list_cost", + M.get_name (| globals, "TX_ACCESS_LIST_ADDRESS_COST" |) + |) in + let _ := M.assign_op_local (| + BinOp.add, + "access_list_cost", + BinOp.mult (| + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_name (| globals, "keys" |) + ], + make_dict [] + |), + M.get_name (| globals, "TX_ACCESS_LIST_STORAGE_KEY_COST" |) + |) + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + BinOp.add (| + BinOp.add (| + BinOp.add (| + M.get_name (| globals, "TX_BASE_COST" |), + M.get_name (| globals, "data_cost" |) + |), + M.get_name (| globals, "create_cost" |) + |), + M.get_name (| globals, "access_list_cost" |) + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Definition recover_sender : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "chain_id"; "tx" ] |) in + let _ := Constant.str " + Extracts the sender address from a transaction. + + The v, r, and s values are the three parts that make up the signature + of a transaction. In order to recover the sender of a transaction the two + components needed are the signature (``v``, ``r``, and ``s``) and the + signing hash of the transaction. The sender's public key can be obtained + with these two values and therefore the sender address can be retrieved. + + Parameters + ---------- + tx : + Transaction of interest. + chain_id : + ID of the executing chain. + + Returns + ------- + sender : `ethereum.fork_types.Address` + The address of the account that signed the transaction. + " in + let _ := M.assign (| + make_tuple [ M.get_name (| globals, "r" |); M.get_name (| globals, "s" |) ], + make_tuple [ M.get_field (| M.get_name (| globals, "tx" |), "r" |); M.get_field (| M.get_name (| globals, "tx" |), "s" |) ] + |) in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + BoolOp.and (| + Compare.lt (| + Constant.int 0, + M.get_name (| globals, "r" |) + |), + ltac:(M.monadic ( + Compare.lt (| + M.get_name (| globals, "r" |), + M.get_name (| globals, "SECP256K1N" |) + |) + )) + |); + M.get_name (| globals, "InvalidBlock" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + BoolOp.and (| + Compare.lt (| + Constant.int 0, + M.get_name (| globals, "s" |) + |), + ltac:(M.monadic ( + Compare.lt_e (| + M.get_name (| globals, "s" |), + BinOp.floor_div (| + M.get_name (| globals, "SECP256K1N" |), + Constant.int 2 + |) + |) + )) + |); + M.get_name (| globals, "InvalidBlock" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, "isinstance" |), + make_list [ + M.get_name (| globals, "tx" |); + M.get_name (| globals, "LegacyTransaction" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "v" , + M.get_field (| M.get_name (| globals, "tx" |), "v" |) + |) in + let _ := + (* if *) + M.if_then_else (| + BoolOp.or (| + Compare.eq (| + M.get_name (| globals, "v" |), + Constant.int 27 + |), + ltac:(M.monadic ( + Compare.eq (| + M.get_name (| globals, "v" |), + Constant.int 28 + |) + )) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "public_key" , + M.call (| + M.get_name (| globals, "secp256k1_recover" |), + make_list [ + M.get_name (| globals, "r" |); + M.get_name (| globals, "s" |); + BinOp.sub (| + M.get_name (| globals, "v" |), + Constant.int 27 + |); + M.call (| + M.get_name (| globals, "signing_hash_pre155" |), + make_list [ + M.get_name (| globals, "tx" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + BoolOp.or (| + Compare.eq (| + M.get_name (| globals, "v" |), + BinOp.add (| + Constant.int 35, + BinOp.mult (| + M.get_name (| globals, "chain_id" |), + Constant.int 2 + |) + |) + |), + ltac:(M.monadic ( + Compare.eq (| + M.get_name (| globals, "v" |), + BinOp.add (| + Constant.int 36, + BinOp.mult (| + M.get_name (| globals, "chain_id" |), + Constant.int 2 + |) + |) + |) + )) + |); + M.get_name (| globals, "InvalidBlock" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "public_key" , + M.call (| + M.get_name (| globals, "secp256k1_recover" |), + make_list [ + M.get_name (| globals, "r" |); + M.get_name (| globals, "s" |); + BinOp.sub (| + BinOp.sub (| + M.get_name (| globals, "v" |), + Constant.int 35 + |), + BinOp.mult (| + M.get_name (| globals, "chain_id" |), + Constant.int 2 + |) + |); + M.call (| + M.get_name (| globals, "signing_hash_155" |), + make_list [ + M.get_name (| globals, "tx" |); + M.get_name (| globals, "chain_id" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, "isinstance" |), + make_list [ + M.get_name (| globals, "tx" |); + M.get_name (| globals, "AccessListTransaction" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "public_key" , + M.call (| + M.get_name (| globals, "secp256k1_recover" |), + make_list [ + M.get_name (| globals, "r" |); + M.get_name (| globals, "s" |); + M.get_field (| M.get_name (| globals, "tx" |), "y_parity" |); + M.call (| + M.get_name (| globals, "signing_hash_2930" |), + make_list [ + M.get_name (| globals, "tx" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, "isinstance" |), + make_list [ + M.get_name (| globals, "tx" |); + M.get_name (| globals, "FeeMarketTransaction" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "public_key" , + M.call (| + M.get_name (| globals, "secp256k1_recover" |), + make_list [ + M.get_name (| globals, "r" |); + M.get_name (| globals, "s" |); + M.get_field (| M.get_name (| globals, "tx" |), "y_parity" |); + M.call (| + M.get_name (| globals, "signing_hash_1559" |), + make_list [ + M.get_name (| globals, "tx" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )) |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, "Address" |), + make_list [ + M.slice (| + M.call (| + M.get_name (| globals, "keccak256" |), + make_list [ + M.get_name (| globals, "public_key" |) + ], + make_dict [] + |), + Constant.int 12, + Constant.int 32, + Constant.None_ + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Definition signing_hash_pre155 : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "tx" ] |) in + let _ := Constant.str " + Compute the hash of a transaction used in a legacy (pre EIP 155) signature. + + Parameters + ---------- + tx : + Transaction of interest. + + Returns + ------- + hash : `ethereum.crypto.hash.Hash32` + Hash of the transaction. + " in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, "keccak256" |), + make_list [ + M.call (| + M.get_field (| M.get_name (| globals, "rlp" |), "encode" |), + make_list [ + make_tuple [ M.get_field (| M.get_name (| globals, "tx" |), "nonce" |); M.get_field (| M.get_name (| globals, "tx" |), "gas_price" |); M.get_field (| M.get_name (| globals, "tx" |), "gas" |); M.get_field (| M.get_name (| globals, "tx" |), "to" |); M.get_field (| M.get_name (| globals, "tx" |), "value" |); M.get_field (| M.get_name (| globals, "tx" |), "data" |) ] + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Definition signing_hash_155 : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "tx"; "chain_id" ] |) in + let _ := Constant.str " + Compute the hash of a transaction used in a EIP 155 signature. + + Parameters + ---------- + tx : + Transaction of interest. + chain_id : + The id of the current chain. + + Returns + ------- + hash : `ethereum.crypto.hash.Hash32` + Hash of the transaction. + " in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, "keccak256" |), + make_list [ + M.call (| + M.get_field (| M.get_name (| globals, "rlp" |), "encode" |), + make_list [ + make_tuple [ M.get_field (| M.get_name (| globals, "tx" |), "nonce" |); M.get_field (| M.get_name (| globals, "tx" |), "gas_price" |); M.get_field (| M.get_name (| globals, "tx" |), "gas" |); M.get_field (| M.get_name (| globals, "tx" |), "to" |); M.get_field (| M.get_name (| globals, "tx" |), "value" |); M.get_field (| M.get_name (| globals, "tx" |), "data" |); M.get_name (| globals, "chain_id" |); M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |); M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) ] + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Definition signing_hash_2930 : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "tx" ] |) in + let _ := Constant.str " + Compute the hash of a transaction used in a EIP 2930 signature. + + Parameters + ---------- + tx : + Transaction of interest. + + Returns + ------- + hash : `ethereum.crypto.hash.Hash32` + Hash of the transaction. + " in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, "keccak256" |), + make_list [ + BinOp.add (| + Constant.bytes "01", + M.call (| + M.get_field (| M.get_name (| globals, "rlp" |), "encode" |), + make_list [ + make_tuple [ M.get_field (| M.get_name (| globals, "tx" |), "chain_id" |); M.get_field (| M.get_name (| globals, "tx" |), "nonce" |); M.get_field (| M.get_name (| globals, "tx" |), "gas_price" |); M.get_field (| M.get_name (| globals, "tx" |), "gas" |); M.get_field (| M.get_name (| globals, "tx" |), "to" |); M.get_field (| M.get_name (| globals, "tx" |), "value" |); M.get_field (| M.get_name (| globals, "tx" |), "data" |); M.get_field (| M.get_name (| globals, "tx" |), "access_list" |) ] + ], + make_dict [] + |) + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Definition signing_hash_1559 : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "tx" ] |) in + let _ := Constant.str " + Compute the hash of a transaction used in a EIP 1559 signature. + + Parameters + ---------- + tx : + Transaction of interest. + + Returns + ------- + hash : `ethereum.crypto.hash.Hash32` + Hash of the transaction. + " in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, "keccak256" |), + make_list [ + BinOp.add (| + Constant.bytes "02", + M.call (| + M.get_field (| M.get_name (| globals, "rlp" |), "encode" |), + make_list [ + make_tuple [ M.get_field (| M.get_name (| globals, "tx" |), "chain_id" |); M.get_field (| M.get_name (| globals, "tx" |), "nonce" |); M.get_field (| M.get_name (| globals, "tx" |), "max_priority_fee_per_gas" |); M.get_field (| M.get_name (| globals, "tx" |), "max_fee_per_gas" |); M.get_field (| M.get_name (| globals, "tx" |), "gas" |); M.get_field (| M.get_name (| globals, "tx" |), "to" |); M.get_field (| M.get_name (| globals, "tx" |), "value" |); M.get_field (| M.get_name (| globals, "tx" |), "data" |); M.get_field (| M.get_name (| globals, "tx" |), "access_list" |) ] + ], + make_dict [] + |) + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Definition compute_header_hash : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "header" ] |) in + let _ := Constant.str " + Computes the hash of a block header. + + The header hash of a block is the canonical hash that is used to refer + to a specific block and completely distinguishes a block from another. + + ``keccak256`` is a function that produces a 256 bit hash of any input. + It also takes in any number of bytes as an input and produces a single + hash for them. A hash is a completely unique output for a single input. + So an input corresponds to one unique hash that can be used to identify + the input exactly. + + Prior to using the ``keccak256`` hash function, the header must be + encoded using the Recursive-Length Prefix. See :ref:`rlp`. + RLP encoding the header converts it into a space-efficient format that + allows for easy transfer of data between nodes. The purpose of RLP is to + encode arbitrarily nested arrays of binary data, and RLP is the primary + encoding method used to serialize objects in Ethereum's execution layer. + The only purpose of RLP is to encode structure; encoding specific data + types (e.g. strings, floats) is left up to higher-order protocols. + + Parameters + ---------- + header : + Header of interest. + + Returns + ------- + hash : `ethereum.crypto.hash.Hash32` + Hash of the header. + " in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, "keccak256" |), + make_list [ + M.call (| + M.get_field (| M.get_name (| globals, "rlp" |), "encode" |), + make_list [ + M.get_name (| globals, "header" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Definition check_gas_limit : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "gas_limit"; "parent_gas_limit" ] |) in + let _ := Constant.str " + Validates the gas limit for a block. + + The bounds of the gas limit, ``max_adjustment_delta``, is set as the + quotient of the parent block's gas limit and the + ``GAS_LIMIT_ADJUSTMENT_FACTOR``. Therefore, if the gas limit that is + passed through as a parameter is greater than or equal to the *sum* of + the parent's gas and the adjustment delta then the limit for gas is too + high and fails this function's check. Similarly, if the limit is less + than or equal to the *difference* of the parent's gas and the adjustment + delta *or* the predefined ``GAS_LIMIT_MINIMUM`` then this function's + check fails because the gas limit doesn't allow for a sufficient or + reasonable amount of gas to be used on a block. + + Parameters + ---------- + gas_limit : + Gas limit to validate. + + parent_gas_limit : + Gas limit of the parent block. + + Returns + ------- + check : `bool` + True if gas limit constraints are satisfied, False otherwise. + " in + let _ := M.assign_local (| + "max_adjustment_delta" , + BinOp.floor_div (| + M.get_name (| globals, "parent_gas_limit" |), + M.get_name (| globals, "GAS_LIMIT_ADJUSTMENT_FACTOR" |) + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.gt_e (| + M.get_name (| globals, "gas_limit" |), + BinOp.add (| + M.get_name (| globals, "parent_gas_limit" |), + M.get_name (| globals, "max_adjustment_delta" |) + |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + Constant.bool false + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + Compare.lt_e (| + M.get_name (| globals, "gas_limit" |), + BinOp.sub (| + M.get_name (| globals, "parent_gas_limit" |), + M.get_name (| globals, "max_adjustment_delta" |) + |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + Constant.bool false + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + Compare.lt (| + M.get_name (| globals, "gas_limit" |), + M.get_name (| globals, "GAS_LIMIT_MINIMUM" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + Constant.bool false + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.return_ (| + Constant.bool true + |) in + M.pure Constant.None_)). + +Definition calculate_block_difficulty : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "block_number"; "block_timestamp"; "parent_timestamp"; "parent_difficulty"; "parent_has_ommers" ] |) in + let _ := Constant.str " + Computes difficulty of a block using its header and parent header. + + The difficulty is determined by the time the block was created after its + parent. The ``offset`` is calculated using the parent block's difficulty, + ``parent_difficulty``, and the timestamp between blocks. This offset is + then added to the parent difficulty and is stored as the ``difficulty`` + variable. If the time between the block and its parent is too short, the + offset will result in a positive number thus making the sum of + ``parent_difficulty`` and ``offset`` to be a greater value in order to + avoid mass forking. But, if the time is long enough, then the offset + results in a negative value making the block less difficult than + its parent. + + The base standard for a block's difficulty is the predefined value + set for the genesis block since it has no parent. So, a block + can't be less difficult than the genesis block, therefore each block's + difficulty is set to the maximum value between the calculated + difficulty and the ``GENESIS_DIFFICULTY``. + + Parameters + ---------- + block_number : + Block number of the block. + block_timestamp : + Timestamp of the block. + parent_timestamp : + Timestamp of the parent block. + parent_difficulty : + difficulty of the parent block. + parent_has_ommers: + does the parent have ommers. + + Returns + ------- + difficulty : `ethereum.base_types.Uint` + Computed difficulty for a block. + " in + let _ := M.assign_local (| + "offset" , + BinOp.mult (| + BinOp.floor_div (| + M.call (| + M.get_name (| globals, "int" |), + make_list [ + M.get_name (| globals, "parent_difficulty" |) + ], + make_dict [] + |), + Constant.int 2048 + |), + M.call (| + M.get_name (| globals, "max" |), + make_list [ + BinOp.sub (| + (* if *) + M.if_then_else (| + M.get_name (| globals, "parent_has_ommers" |), + (* then *) + ltac:(M.monadic ( +Constant.int 2 + (* else *) + )), ltac:(M.monadic ( +Constant.int 1 + )) |), + BinOp.floor_div (| + M.call (| + M.get_name (| globals, "int" |), + make_list [ + BinOp.sub (| + M.get_name (| globals, "block_timestamp" |), + M.get_name (| globals, "parent_timestamp" |) + |) + ], + make_dict [] + |), + Constant.int 9 + |) + |); + UnOp.sub (| Constant.int 99 |) + ], + make_dict [] + |) + |) + |) in + let _ := M.assign_local (| + "difficulty" , + BinOp.add (| + M.call (| + M.get_name (| globals, "int" |), + make_list [ + M.get_name (| globals, "parent_difficulty" |) + ], + make_dict [] + |), + M.get_name (| globals, "offset" |) + |) + |) in + let _ := M.assign_local (| + "num_bomb_periods" , + BinOp.sub (| + BinOp.floor_div (| + BinOp.sub (| + M.call (| + M.get_name (| globals, "int" |), + make_list [ + M.get_name (| globals, "block_number" |) + ], + make_dict [] + |), + M.get_name (| globals, "BOMB_DELAY_BLOCKS" |) + |), + Constant.int 100000 + |), + Constant.int 2 + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.gt_e (| + M.get_name (| globals, "num_bomb_periods" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_op_local (| + BinOp.add, + "difficulty", + BinOp.pow (| + Constant.int 2, + M.get_name (| globals, "num_bomb_periods" |) + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, "max" |), + make_list [ + M.get_name (| globals, "difficulty" |); + M.get_name (| globals, "MINIMUM_DIFFICULTY" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). diff --git a/CoqOfPython/ethereum/arrow_glacier/fork_types.v b/CoqOfPython/ethereum/arrow_glacier/fork_types.v new file mode 100644 index 0000000..e46e8cb --- /dev/null +++ b/CoqOfPython/ethereum/arrow_glacier/fork_types.v @@ -0,0 +1,98 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.arrow_glacier.fork_types". + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Types +^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Types re-used throughout the specification, which are specific to Ethereum. +". + +Axiom dataclasses_imports_dataclass : + IsImported globals "dataclasses" "dataclass". + +Axiom ethereum_imports_rlp : + IsImported globals "ethereum" "rlp". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_Bytes : + IsImported globals "ethereum.base_types" "Bytes". +Axiom ethereum_base_types_imports_Bytes20 : + IsImported globals "ethereum.base_types" "Bytes20". +Axiom ethereum_base_types_imports_Bytes256 : + IsImported globals "ethereum.base_types" "Bytes256". +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". +Axiom ethereum_base_types_imports_slotted_freezable : + IsImported globals "ethereum.base_types" "slotted_freezable". + +Axiom ethereum_crypto_hash_imports_Hash32 : + IsImported globals "ethereum.crypto.hash" "Hash32". +Axiom ethereum_crypto_hash_imports_keccak256 : + IsImported globals "ethereum.crypto.hash" "keccak256". + +Definition Address : Value.t := M.run ltac:(M.monadic ( + M.get_name (| globals, "Bytes20" |) +)). + +Definition Root : Value.t := M.run ltac:(M.monadic ( + M.get_name (| globals, "Hash32" |) +)). + +Definition Bloom : Value.t := M.run ltac:(M.monadic ( + M.get_name (| globals, "Bytes256" |) +)). + +Definition Account : Value.t := + builtins.make_klass + [] + [ + + ] + [ + + ]. + +Definition EMPTY_ACCOUNT : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Account" |), + make_list [], + make_dict [] + |) +)). + +Definition encode_account : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "raw_account_data"; "storage_root" ] |) in + let _ := Constant.str " + Encode `Account` dataclass. + + Storage is not stored in the `Account` dataclass, so `Accounts` cannot be + encoded with providing a storage root. + " in + let _ := M.return_ (| + M.call (| + M.get_field (| M.get_name (| globals, "rlp" |), "encode" |), + make_list [ + make_tuple [ M.get_field (| M.get_name (| globals, "raw_account_data" |), "nonce" |); M.get_field (| M.get_name (| globals, "raw_account_data" |), "balance" |); M.get_name (| globals, "storage_root" |); M.call (| + M.get_name (| globals, "keccak256" |), + make_list [ + M.get_field (| M.get_name (| globals, "raw_account_data" |), "code" |) + ], + make_dict [] + |) ] + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). diff --git a/CoqOfPython/ethereum/arrow_glacier/state.v b/CoqOfPython/ethereum/arrow_glacier/state.v new file mode 100644 index 0000000..455bfaa --- /dev/null +++ b/CoqOfPython/ethereum/arrow_glacier/state.v @@ -0,0 +1,1279 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.arrow_glacier.state". + +Definition expr_1 : Value.t := + Constant.str " +State +^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +The state contains all information that is preserved between transactions. + +It consists of a main account trie and storage tries for each contract. + +There is a distinction between an account that does not exist and +`EMPTY_ACCOUNT`. +". + +Axiom dataclasses_imports_dataclass : + IsImported globals "dataclasses" "dataclass". +Axiom dataclasses_imports_field : + IsImported globals "dataclasses" "field". + +Axiom typing_imports_Callable : + IsImported globals "typing" "Callable". +Axiom typing_imports_Dict : + IsImported globals "typing" "Dict". +Axiom typing_imports_List : + IsImported globals "typing" "List". +Axiom typing_imports_Optional : + IsImported globals "typing" "Optional". +Axiom typing_imports_Set : + IsImported globals "typing" "Set". +Axiom typing_imports_Tuple : + IsImported globals "typing" "Tuple". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_Bytes : + IsImported globals "ethereum.base_types" "Bytes". +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". +Axiom ethereum_base_types_imports_modify : + IsImported globals "ethereum.base_types" "modify". + +Axiom ethereum_utils_ensure_imports_ensure : + IsImported globals "ethereum.utils.ensure" "ensure". + +Axiom ethereum_arrow_glacier_fork_types_imports_EMPTY_ACCOUNT : + IsImported globals "ethereum.arrow_glacier.fork_types" "EMPTY_ACCOUNT". +Axiom ethereum_arrow_glacier_fork_types_imports_Account : + IsImported globals "ethereum.arrow_glacier.fork_types" "Account". +Axiom ethereum_arrow_glacier_fork_types_imports_Address : + IsImported globals "ethereum.arrow_glacier.fork_types" "Address". +Axiom ethereum_arrow_glacier_fork_types_imports_Root : + IsImported globals "ethereum.arrow_glacier.fork_types" "Root". + +Axiom ethereum_arrow_glacier_trie_imports_EMPTY_TRIE_ROOT : + IsImported globals "ethereum.arrow_glacier.trie" "EMPTY_TRIE_ROOT". +Axiom ethereum_arrow_glacier_trie_imports_Trie : + IsImported globals "ethereum.arrow_glacier.trie" "Trie". +Axiom ethereum_arrow_glacier_trie_imports_copy_trie : + IsImported globals "ethereum.arrow_glacier.trie" "copy_trie". +Axiom ethereum_arrow_glacier_trie_imports_root : + IsImported globals "ethereum.arrow_glacier.trie" "root". +Axiom ethereum_arrow_glacier_trie_imports_trie_get : + IsImported globals "ethereum.arrow_glacier.trie" "trie_get". +Axiom ethereum_arrow_glacier_trie_imports_trie_set : + IsImported globals "ethereum.arrow_glacier.trie" "trie_set". + +Definition State : Value.t := + builtins.make_klass + [] + [ + + ] + [ + + ]. + +Definition close_state : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "state" ] |) in + let _ := Constant.str " + Free resources held by the state. Used by optimized implementations to + release file descriptors. + " in + let _ := M.delete (| M.get_field (| M.get_name (| globals, "state" |), "_main_trie" |) |) in + let _ := M.delete (| M.get_field (| M.get_name (| globals, "state" |), "_storage_tries" |) |) in + let _ := M.delete (| M.get_field (| M.get_name (| globals, "state" |), "_snapshots" |) |) in + let _ := M.delete (| M.get_field (| M.get_name (| globals, "state" |), "_created_accounts" |) |) in + M.pure Constant.None_)). + +Definition begin_transaction : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "state" ] |) in + let _ := Constant.str " + Start a state transaction. + + Transactions are entirely implicit and can be nested. It is not possible to + calculate the state root during a transaction. + + Parameters + ---------- + state : State + The state. + " in + let _ := M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, "state" |), "_snapshots" |), "append" |), + make_list [ + make_tuple [ M.call (| + M.get_name (| globals, "copy_trie" |), + make_list [ + M.get_field (| M.get_name (| globals, "state" |), "_main_trie" |) + ], + make_dict [] + |); Constant.str "(* At expr: unsupported node type: DictComp *)" ] + ], + make_dict [] + |) in + M.pure Constant.None_)). + +Definition commit_transaction : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "state" ] |) in + let _ := Constant.str " + Commit a state transaction. + + Parameters + ---------- + state : State + The state. + " in + let _ := M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, "state" |), "_snapshots" |), "pop" |), + make_list [], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + UnOp.not (| M.get_field (| M.get_name (| globals, "state" |), "_snapshots" |) |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, "state" |), "_created_accounts" |), "clear" |), + make_list [], + make_dict [] + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + M.pure Constant.None_)). + +Definition rollback_transaction : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "state" ] |) in + let _ := Constant.str " + Rollback a state transaction, resetting the state to the point when the + corresponding `start_transaction()` call was made. + + Parameters + ---------- + state : State + The state. + " in + let _ := M.assign (| + make_tuple [ M.get_field (| M.get_name (| globals, "state" |), "_main_trie" |); M.get_field (| M.get_name (| globals, "state" |), "_storage_tries" |) ], + M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, "state" |), "_snapshots" |), "pop" |), + make_list [], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + UnOp.not (| M.get_field (| M.get_name (| globals, "state" |), "_snapshots" |) |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, "state" |), "_created_accounts" |), "clear" |), + make_list [], + make_dict [] + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + M.pure Constant.None_)). + +Definition get_account : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "state"; "address" ] |) in + let _ := Constant.str " + Get the `Account` object at an address. Returns `EMPTY_ACCOUNT` if there + is no account at the address. + + Use `get_account_optional()` if you care about the difference between a + non-existent account and `EMPTY_ACCOUNT`. + + Parameters + ---------- + state: `State` + The state + address : `Address` + Address to lookup. + + Returns + ------- + account : `Account` + Account at address. + " in + let _ := M.assign_local (| + "account" , + M.call (| + M.get_name (| globals, "get_account_optional" |), + make_list [ + M.get_name (| globals, "state" |); + M.get_name (| globals, "address" |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, "isinstance" |), + make_list [ + M.get_name (| globals, "account" |); + M.get_name (| globals, "Account" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + M.get_name (| globals, "account" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.return_ (| + M.get_name (| globals, "EMPTY_ACCOUNT" |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_)). + +Definition get_account_optional : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "state"; "address" ] |) in + let _ := Constant.str " + Get the `Account` object at an address. Returns `None` (rather than + `EMPTY_ACCOUNT`) if there is no account at the address. + + Parameters + ---------- + state: `State` + The state + address : `Address` + Address to lookup. + + Returns + ------- + account : `Account` + Account at address. + " in + let _ := M.assign_local (| + "account" , + M.call (| + M.get_name (| globals, "trie_get" |), + make_list [ + M.get_field (| M.get_name (| globals, "state" |), "_main_trie" |); + M.get_name (| globals, "address" |) + ], + make_dict [] + |) + |) in + let _ := M.return_ (| + M.get_name (| globals, "account" |) + |) in + M.pure Constant.None_)). + +Definition set_account : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "state"; "address"; "account" ] |) in + let _ := Constant.str " + Set the `Account` object at an address. Setting to `None` deletes + the account (but not its storage, see `destroy_account()`). + + Parameters + ---------- + state: `State` + The state + address : `Address` + Address to set. + account : `Account` + Account to set at address. + " in + let _ := M.call (| + M.get_name (| globals, "trie_set" |), + make_list [ + M.get_field (| M.get_name (| globals, "state" |), "_main_trie" |); + M.get_name (| globals, "address" |); + M.get_name (| globals, "account" |) + ], + make_dict [] + |) in + M.pure Constant.None_)). + +Definition destroy_account : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "state"; "address" ] |) in + let _ := Constant.str " + Completely remove the account at `address` and all of its storage. + + This function is made available exclusively for the `SELFDESTRUCT` + opcode. It is expected that `SELFDESTRUCT` will be disabled in a future + hardfork and this function will be removed. + + Parameters + ---------- + state: `State` + The state + address : `Address` + Address of account to destroy. + " in + let _ := M.call (| + M.get_name (| globals, "destroy_storage" |), + make_list [ + M.get_name (| globals, "state" |); + M.get_name (| globals, "address" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "set_account" |), + make_list [ + M.get_name (| globals, "state" |); + M.get_name (| globals, "address" |); + Constant.None_ + ], + make_dict [] + |) in + M.pure Constant.None_)). + +Definition destroy_storage : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "state"; "address" ] |) in + let _ := Constant.str " + Completely remove the storage at `address`. + + Parameters + ---------- + state: `State` + The state + address : `Address` + Address of account whose storage is to be deleted. + " in + let _ := + (* if *) + M.if_then_else (| + Compare.in_ (| + M.get_name (| globals, "address" |), + M.get_field (| M.get_name (| globals, "state" |), "_storage_tries" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.delete (| M.get_subscript (| + M.get_field (| M.get_name (| globals, "state" |), "_storage_tries" |), + M.get_name (| globals, "address" |) + |) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + M.pure Constant.None_)). + +Definition mark_account_created : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "state"; "address" ] |) in + let _ := Constant.str " + Mark an account as having been created in the current transaction. + This information is used by `get_storage_original()` to handle an obscure + edgecase. + + The marker is not removed even if the account creation reverts. Since the + account cannot have had code prior to its creation and can't call + `get_storage_original()`, this is harmless. + + Parameters + ---------- + state: `State` + The state + address : `Address` + Address of the account that has been created. + " in + let _ := M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, "state" |), "_created_accounts" |), "add" |), + make_list [ + M.get_name (| globals, "address" |) + ], + make_dict [] + |) in + M.pure Constant.None_)). + +Definition get_storage : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "state"; "address"; "key" ] |) in + let _ := Constant.str " + Get a value at a storage key on an account. Returns `U256(0)` if the + storage key has not been set previously. + + Parameters + ---------- + state: `State` + The state + address : `Address` + Address of the account. + key : `Bytes` + Key to lookup. + + Returns + ------- + value : `U256` + Value at the key. + " in + let _ := M.assign_local (| + "trie" , + M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, "state" |), "_storage_tries" |), "get" |), + make_list [ + M.get_name (| globals, "address" |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.is (| + M.get_name (| globals, "trie" |), + Constant.None_ + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "value" , + M.call (| + M.get_name (| globals, "trie_get" |), + make_list [ + M.get_name (| globals, "trie" |); + M.get_name (| globals, "key" |) + ], + make_dict [] + |) + |) in + let _ := M.assert (| M.call (| + M.get_name (| globals, "isinstance" |), + make_list [ + M.get_name (| globals, "value" |); + M.get_name (| globals, "U256" |) + ], + make_dict [] + |) |) in + let _ := M.return_ (| + M.get_name (| globals, "value" |) + |) in + M.pure Constant.None_)). + +Definition set_storage : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "state"; "address"; "key"; "value" ] |) in + let _ := Constant.str " + Set a value at a storage key on an account. Setting to `U256(0)` deletes + the key. + + Parameters + ---------- + state: `State` + The state + address : `Address` + Address of the account. + key : `Bytes` + Key to set. + value : `U256` + Value to set at the key. + " in + let _ := M.assert (| Compare.is_not (| + M.call (| + M.get_name (| globals, "trie_get" |), + make_list [ + M.get_field (| M.get_name (| globals, "state" |), "_main_trie" |); + M.get_name (| globals, "address" |) + ], + make_dict [] + |), + Constant.None_ + |) |) in + let _ := M.assign_local (| + "trie" , + M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, "state" |), "_storage_tries" |), "get" |), + make_list [ + M.get_name (| globals, "address" |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.is (| + M.get_name (| globals, "trie" |), + Constant.None_ + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "trie" , + M.call (| + M.get_name (| globals, "Trie" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.assign (| + M.get_subscript (| + M.get_field (| M.get_name (| globals, "state" |), "_storage_tries" |), + M.get_name (| globals, "address" |) + |), + M.get_name (| globals, "trie" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.call (| + M.get_name (| globals, "trie_set" |), + make_list [ + M.get_name (| globals, "trie" |); + M.get_name (| globals, "key" |); + M.get_name (| globals, "value" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_field (| M.get_name (| globals, "trie" |), "_data" |), + Constant.str "(* At expr: unsupported node type: Dict *)" + |), + (* then *) + ltac:(M.monadic ( + let _ := M.delete (| M.get_subscript (| + M.get_field (| M.get_name (| globals, "state" |), "_storage_tries" |), + M.get_name (| globals, "address" |) + |) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + M.pure Constant.None_)). + +Definition storage_root : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "state"; "address" ] |) in + let _ := Constant.str " + Calculate the storage root of an account. + + Parameters + ---------- + state: + The state + address : + Address of the account. + + Returns + ------- + root : `Root` + Storage root of the account. + " in + let _ := M.assert (| UnOp.not (| M.get_field (| M.get_name (| globals, "state" |), "_snapshots" |) |) |) in + let _ := + (* if *) + M.if_then_else (| + Compare.in_ (| + M.get_name (| globals, "address" |), + M.get_field (| M.get_name (| globals, "state" |), "_storage_tries" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + M.call (| + M.get_name (| globals, "root" |), + make_list [ + M.get_subscript (| + M.get_field (| M.get_name (| globals, "state" |), "_storage_tries" |), + M.get_name (| globals, "address" |) + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.return_ (| + M.get_name (| globals, "EMPTY_TRIE_ROOT" |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_)). + +Definition state_root : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "state" ] |) in + let _ := Constant.str " + Calculate the state root. + + Parameters + ---------- + state: + The current state. + + Returns + ------- + root : `Root` + The state root. + " in + let _ := M.assert (| UnOp.not (| M.get_field (| M.get_name (| globals, "state" |), "_snapshots" |) |) |) in +(* At stmt: unsupported node type: FunctionDef *) + let _ := M.return_ (| + M.call (| + M.get_name (| globals, "root" |), + make_list [ + M.get_field (| M.get_name (| globals, "state" |), "_main_trie" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Definition account_exists : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "state"; "address" ] |) in + let _ := Constant.str " + Checks if an account exists in the state trie + + Parameters + ---------- + state: + The state + address: + Address of the account that needs to be checked. + + Returns + ------- + account_exists : `bool` + True if account exists in the state trie, False otherwise + " in + let _ := M.return_ (| + Compare.is_not (| + M.call (| + M.get_name (| globals, "get_account_optional" |), + make_list [ + M.get_name (| globals, "state" |); + M.get_name (| globals, "address" |) + ], + make_dict [] + |), + Constant.None_ + |) + |) in + M.pure Constant.None_)). + +Definition account_has_code_or_nonce : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "state"; "address" ] |) in + let _ := Constant.str " + Checks if an account has non zero nonce or non empty code + + Parameters + ---------- + state: + The state + address: + Address of the account that needs to be checked. + + Returns + ------- + has_code_or_nonce : `bool` + True if if an account has non zero nonce or non empty code, + False otherwise. + " in + let _ := M.assign_local (| + "account" , + M.call (| + M.get_name (| globals, "get_account" |), + make_list [ + M.get_name (| globals, "state" |); + M.get_name (| globals, "address" |) + ], + make_dict [] + |) + |) in + let _ := M.return_ (| + BoolOp.or (| + Compare.not_eq (| + M.get_field (| M.get_name (| globals, "account" |), "nonce" |), + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + |), + ltac:(M.monadic ( + Compare.not_eq (| + M.get_field (| M.get_name (| globals, "account" |), "code" |), + Constant.bytes "" + |) + )) + |) + |) in + M.pure Constant.None_)). + +Definition is_account_empty : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "state"; "address" ] |) in + let _ := Constant.str " + Checks if an account has zero nonce, empty code and zero balance. + + Parameters + ---------- + state: + The state + address: + Address of the account that needs to be checked. + + Returns + ------- + is_empty : `bool` + True if if an account has zero nonce, empty code and zero balance, + False otherwise. + " in + let _ := M.assign_local (| + "account" , + M.call (| + M.get_name (| globals, "get_account" |), + make_list [ + M.get_name (| globals, "state" |); + M.get_name (| globals, "address" |) + ], + make_dict [] + |) + |) in + let _ := M.return_ (| + BoolOp.and (| + Compare.eq (| + M.get_field (| M.get_name (| globals, "account" |), "nonce" |), + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + |), + ltac:(M.monadic ( + BoolOp.and (| + Compare.eq (| + M.get_field (| M.get_name (| globals, "account" |), "code" |), + Constant.bytes "" + |), + ltac:(M.monadic ( + Compare.eq (| + M.get_field (| M.get_name (| globals, "account" |), "balance" |), + Constant.int 0 + |) + )) + |) + )) + |) + |) in + M.pure Constant.None_)). + +Definition account_exists_and_is_empty : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "state"; "address" ] |) in + let _ := Constant.str " + Checks if an account exists and has zero nonce, empty code and zero + balance. + + Parameters + ---------- + state: + The state + address: + Address of the account that needs to be checked. + + Returns + ------- + exists_and_is_empty : `bool` + True if an account exists and has zero nonce, empty code and zero + balance, False otherwise. + " in + let _ := M.assign_local (| + "account" , + M.call (| + M.get_name (| globals, "get_account_optional" |), + make_list [ + M.get_name (| globals, "state" |); + M.get_name (| globals, "address" |) + ], + make_dict [] + |) + |) in + let _ := M.return_ (| + BoolOp.and (| + Compare.is_not (| + M.get_name (| globals, "account" |), + Constant.None_ + |), + ltac:(M.monadic ( + BoolOp.and (| + Compare.eq (| + M.get_field (| M.get_name (| globals, "account" |), "nonce" |), + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + |), + ltac:(M.monadic ( + BoolOp.and (| + Compare.eq (| + M.get_field (| M.get_name (| globals, "account" |), "code" |), + Constant.bytes "" + |), + ltac:(M.monadic ( + Compare.eq (| + M.get_field (| M.get_name (| globals, "account" |), "balance" |), + Constant.int 0 + |) + )) + |) + )) + |) + )) + |) + |) in + M.pure Constant.None_)). + +Definition is_account_alive : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "state"; "address" ] |) in + let _ := Constant.str " + Check whether is an account is both in the state and non empty. + + Parameters + ---------- + state: + The state + address: + Address of the account that needs to be checked. + + Returns + ------- + is_alive : `bool` + True if the account is alive. + " in + let _ := M.assign_local (| + "account" , + M.call (| + M.get_name (| globals, "get_account_optional" |), + make_list [ + M.get_name (| globals, "state" |); + M.get_name (| globals, "address" |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.is (| + M.get_name (| globals, "account" |), + Constant.None_ + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + Constant.bool false + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.return_ (| + UnOp.not (| BoolOp.and (| + Compare.eq (| + M.get_field (| M.get_name (| globals, "account" |), "nonce" |), + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + |), + ltac:(M.monadic ( + BoolOp.and (| + Compare.eq (| + M.get_field (| M.get_name (| globals, "account" |), "code" |), + Constant.bytes "" + |), + ltac:(M.monadic ( + Compare.eq (| + M.get_field (| M.get_name (| globals, "account" |), "balance" |), + Constant.int 0 + |) + )) + |) + )) + |) |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_)). + +Definition modify_state : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "state"; "address"; "f" ] |) in + let _ := Constant.str " + Modify an `Account` in the `State`. + " in + let _ := M.call (| + M.get_name (| globals, "set_account" |), + make_list [ + M.get_name (| globals, "state" |); + M.get_name (| globals, "address" |); + M.call (| + M.get_name (| globals, "modify" |), + make_list [ + M.call (| + M.get_name (| globals, "get_account" |), + make_list [ + M.get_name (| globals, "state" |); + M.get_name (| globals, "address" |) + ], + make_dict [] + |); + M.get_name (| globals, "f" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + M.pure Constant.None_)). + +Definition move_ether : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "state"; "sender_address"; "recipient_address"; "amount" ] |) in + let _ := Constant.str " + Move funds between accounts. + " in +(* At stmt: unsupported node type: FunctionDef *) +(* At stmt: unsupported node type: FunctionDef *) + let _ := M.call (| + M.get_name (| globals, "modify_state" |), + make_list [ + M.get_name (| globals, "state" |); + M.get_name (| globals, "sender_address" |); + M.get_name (| globals, "reduce_sender_balance" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "modify_state" |), + make_list [ + M.get_name (| globals, "state" |); + M.get_name (| globals, "recipient_address" |); + M.get_name (| globals, "increase_recipient_balance" |) + ], + make_dict [] + |) in + M.pure Constant.None_)). + +Definition set_account_balance : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "state"; "address"; "amount" ] |) in + let _ := Constant.str " + Sets the balance of an account. + + Parameters + ---------- + state: + The current state. + + address: + Address of the account whose nonce needs to be incremented. + + amount: + The amount that needs to set in balance. + " in +(* At stmt: unsupported node type: FunctionDef *) + let _ := M.call (| + M.get_name (| globals, "modify_state" |), + make_list [ + M.get_name (| globals, "state" |); + M.get_name (| globals, "address" |); + M.get_name (| globals, "set_balance" |) + ], + make_dict [] + |) in + M.pure Constant.None_)). + +Definition touch_account : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "state"; "address" ] |) in + let _ := Constant.str " + Initializes an account to state. + + Parameters + ---------- + state: + The current state. + + address: + The address of the account that need to initialised. + " in + let _ := + (* if *) + M.if_then_else (| + UnOp.not (| M.call (| + M.get_name (| globals, "account_exists" |), + make_list [ + M.get_name (| globals, "state" |); + M.get_name (| globals, "address" |) + ], + make_dict [] + |) |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, "set_account" |), + make_list [ + M.get_name (| globals, "state" |); + M.get_name (| globals, "address" |); + M.get_name (| globals, "EMPTY_ACCOUNT" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + M.pure Constant.None_)). + +Definition increment_nonce : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "state"; "address" ] |) in + let _ := Constant.str " + Increments the nonce of an account. + + Parameters + ---------- + state: + The current state. + + address: + Address of the account whose nonce needs to be incremented. + " in +(* At stmt: unsupported node type: FunctionDef *) + let _ := M.call (| + M.get_name (| globals, "modify_state" |), + make_list [ + M.get_name (| globals, "state" |); + M.get_name (| globals, "address" |); + M.get_name (| globals, "increase_nonce" |) + ], + make_dict [] + |) in + M.pure Constant.None_)). + +Definition set_code : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "state"; "address"; "code" ] |) in + let _ := Constant.str " + Sets Account code. + + Parameters + ---------- + state: + The current state. + + address: + Address of the account whose code needs to be update. + + code: + The bytecode that needs to be set. + " in +(* At stmt: unsupported node type: FunctionDef *) + let _ := M.call (| + M.get_name (| globals, "modify_state" |), + make_list [ + M.get_name (| globals, "state" |); + M.get_name (| globals, "address" |); + M.get_name (| globals, "write_code" |) + ], + make_dict [] + |) in + M.pure Constant.None_)). + +Definition create_ether : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "state"; "address"; "amount" ] |) in + let _ := Constant.str " + Add newly created ether to an account. + + Parameters + ---------- + state: + The current state. + address: + Address of the account to which ether is added. + amount: + The amount of ether to be added to the account of interest. + " in +(* At stmt: unsupported node type: FunctionDef *) + let _ := M.call (| + M.get_name (| globals, "modify_state" |), + make_list [ + M.get_name (| globals, "state" |); + M.get_name (| globals, "address" |); + M.get_name (| globals, "increase_balance" |) + ], + make_dict [] + |) in + M.pure Constant.None_)). + +Definition get_storage_original : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "state"; "address"; "key" ] |) in + let _ := Constant.str " + Get the original value in a storage slot i.e. the value before the current + transaction began. This function reads the value from the snapshots taken + before executing the transaction. + + Parameters + ---------- + state: + The current state. + address: + Address of the account to read the value from. + key: + Key of the storage slot. + " in + let _ := + (* if *) + M.if_then_else (| + Compare.in_ (| + M.get_name (| globals, "address" |), + M.get_field (| M.get_name (| globals, "state" |), "_created_accounts" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign (| + make_tuple [ M.get_name (| globals, "_" |); M.get_name (| globals, "original_trie" |) ], + M.get_subscript (| + M.get_field (| M.get_name (| globals, "state" |), "_snapshots" |), + Constant.int 0 + |) + |) in + let _ := M.assign_local (| + "original_account_trie" , + M.call (| + M.get_field (| M.get_name (| globals, "original_trie" |), "get" |), + make_list [ + M.get_name (| globals, "address" |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.is (| + M.get_name (| globals, "original_account_trie" |), + Constant.None_ + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "original_value" , + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "original_value" , + M.call (| + M.get_name (| globals, "trie_get" |), + make_list [ + M.get_name (| globals, "original_account_trie" |); + M.get_name (| globals, "key" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + )) |) in + let _ := M.assert (| M.call (| + M.get_name (| globals, "isinstance" |), + make_list [ + M.get_name (| globals, "original_value" |); + M.get_name (| globals, "U256" |) + ], + make_dict [] + |) |) in + let _ := M.return_ (| + M.get_name (| globals, "original_value" |) + |) in + M.pure Constant.None_)). diff --git a/CoqOfPython/ethereum/arrow_glacier/transactions.v b/CoqOfPython/ethereum/arrow_glacier/transactions.v new file mode 100644 index 0000000..67ba8e4 --- /dev/null +++ b/CoqOfPython/ethereum/arrow_glacier/transactions.v @@ -0,0 +1,293 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.arrow_glacier.transactions". + +Definition expr_1 : Value.t := + Constant.str " +Transactions are atomic units of work created externally to Ethereum and +submitted to be executed. If Ethereum is viewed as a state machine, +transactions are the events that move between states. +". + +Axiom dataclasses_imports_dataclass : + IsImported globals "dataclasses" "dataclass". + +Axiom typing_imports_Tuple : + IsImported globals "typing" "Tuple". +Axiom typing_imports_Union : + IsImported globals "typing" "Union". + +Axiom ethereum_imports_rlp : + IsImported globals "ethereum" "rlp". + +Axiom ethereum_base_types_imports_U64 : + IsImported globals "ethereum.base_types" "U64". +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_Bytes : + IsImported globals "ethereum.base_types" "Bytes". +Axiom ethereum_base_types_imports_Bytes0 : + IsImported globals "ethereum.base_types" "Bytes0". +Axiom ethereum_base_types_imports_Bytes32 : + IsImported globals "ethereum.base_types" "Bytes32". +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". +Axiom ethereum_base_types_imports_slotted_freezable : + IsImported globals "ethereum.base_types" "slotted_freezable". + +Axiom ethereum_exceptions_imports_InvalidBlock : + IsImported globals "ethereum.exceptions" "InvalidBlock". + +Axiom ethereum_arrow_glacier_fork_types_imports_Address : + IsImported globals "ethereum.arrow_glacier.fork_types" "Address". + +Definition TX_BASE_COST : Value.t := M.run ltac:(M.monadic ( + Constant.int 21000 +)). + +Definition TX_DATA_COST_PER_NON_ZERO : Value.t := M.run ltac:(M.monadic ( + Constant.int 16 +)). + +Definition TX_DATA_COST_PER_ZERO : Value.t := M.run ltac:(M.monadic ( + Constant.int 4 +)). + +Definition TX_CREATE_COST : Value.t := M.run ltac:(M.monadic ( + Constant.int 32000 +)). + +Definition TX_ACCESS_LIST_ADDRESS_COST : Value.t := M.run ltac:(M.monadic ( + Constant.int 2400 +)). + +Definition TX_ACCESS_LIST_STORAGE_KEY_COST : Value.t := M.run ltac:(M.monadic ( + Constant.int 1900 +)). + +Definition LegacyTransaction : Value.t := + builtins.make_klass + [] + [ + + ] + [ + + ]. + +Definition AccessListTransaction : Value.t := + builtins.make_klass + [] + [ + + ] + [ + + ]. + +Definition FeeMarketTransaction : Value.t := + builtins.make_klass + [] + [ + + ] + [ + + ]. + +Definition Transaction : Value.t := M.run ltac:(M.monadic ( + M.get_subscript (| + M.get_name (| globals, "Union" |), + make_tuple [ M.get_name (| globals, "LegacyTransaction" |); M.get_name (| globals, "AccessListTransaction" |); M.get_name (| globals, "FeeMarketTransaction" |) ] + |) +)). + +Definition encode_transaction : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "tx" ] |) in + let _ := Constant.str " + Encode a transaction. Needed because non-legacy transactions aren't RLP. + " in + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, "isinstance" |), + make_list [ + M.get_name (| globals, "tx" |); + M.get_name (| globals, "LegacyTransaction" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + M.get_name (| globals, "tx" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, "isinstance" |), + make_list [ + M.get_name (| globals, "tx" |); + M.get_name (| globals, "AccessListTransaction" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + BinOp.add (| + Constant.bytes "01", + M.call (| + M.get_field (| M.get_name (| globals, "rlp" |), "encode" |), + make_list [ + M.get_name (| globals, "tx" |) + ], + make_dict [] + |) + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, "isinstance" |), + make_list [ + M.get_name (| globals, "tx" |); + M.get_name (| globals, "FeeMarketTransaction" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + BinOp.add (| + Constant.bytes "02", + M.call (| + M.get_field (| M.get_name (| globals, "rlp" |), "encode" |), + make_list [ + M.get_name (| globals, "tx" |) + ], + make_dict [] + |) + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.raise (| Some (M.call (| + M.get_name (| globals, "Exception" |), + make_list [ + Constant.str "(* At expr: unsupported node type: JoinedStr *)" + ], + make_dict [] + |)) |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_)). + +Definition decode_transaction : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "tx" ] |) in + let _ := Constant.str " + Decode a transaction. Needed because non-legacy transactions aren't RLP. + " in + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, "isinstance" |), + make_list [ + M.get_name (| globals, "tx" |); + M.get_name (| globals, "Bytes" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_subscript (| + M.get_name (| globals, "tx" |), + Constant.int 0 + |), + Constant.int 1 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + M.call (| + M.get_field (| M.get_name (| globals, "rlp" |), "decode_to" |), + make_list [ + M.get_name (| globals, "AccessListTransaction" |); + M.slice (| + M.get_name (| globals, "tx" |), + Constant.int 1, + Constant.None_, + Constant.None_ + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_subscript (| + M.get_name (| globals, "tx" |), + Constant.int 0 + |), + Constant.int 2 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + M.call (| + M.get_field (| M.get_name (| globals, "rlp" |), "decode_to" |), + make_list [ + M.get_name (| globals, "FeeMarketTransaction" |); + M.slice (| + M.get_name (| globals, "tx" |), + Constant.int 1, + Constant.None_, + Constant.None_ + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, "InvalidBlock" |)) |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.return_ (| + M.get_name (| globals, "tx" |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_)). diff --git a/CoqOfPython/ethereum/arrow_glacier/trie.v b/CoqOfPython/ethereum/arrow_glacier/trie.v new file mode 100644 index 0000000..0941ddc --- /dev/null +++ b/CoqOfPython/ethereum/arrow_glacier/trie.v @@ -0,0 +1,1595 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.arrow_glacier.trie". + +Definition expr_1 : Value.t := + Constant.str " +State Trie +^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +The state trie is the structure responsible for storing +`.fork_types.Account` objects. +". + +(* At top_level_stmt: unsupported node type: Import *) + +Axiom dataclasses_imports_dataclass : + IsImported globals "dataclasses" "dataclass". +Axiom dataclasses_imports_field : + IsImported globals "dataclasses" "field". + +Axiom typing_imports_Callable : + IsImported globals "typing" "Callable". +Axiom typing_imports_Dict : + IsImported globals "typing" "Dict". +Axiom typing_imports_Generic : + IsImported globals "typing" "Generic". +Axiom typing_imports_List : + IsImported globals "typing" "List". +Axiom typing_imports_Mapping : + IsImported globals "typing" "Mapping". +Axiom typing_imports_MutableMapping : + IsImported globals "typing" "MutableMapping". +Axiom typing_imports_Optional : + IsImported globals "typing" "Optional". +Axiom typing_imports_Sequence : + IsImported globals "typing" "Sequence". +Axiom typing_imports_TypeVar : + IsImported globals "typing" "TypeVar". +Axiom typing_imports_Union : + IsImported globals "typing" "Union". +Axiom typing_imports_cast : + IsImported globals "typing" "cast". + +Axiom ethereum_crypto_hash_imports_keccak256 : + IsImported globals "ethereum.crypto.hash" "keccak256". + +Axiom ethereum_london_imports_trie : + IsImported globals "ethereum.london" "trie". + +Axiom ethereum_utils_ensure_imports_ensure : + IsImported globals "ethereum.utils.ensure" "ensure". + +Axiom ethereum_utils_hexadecimal_imports_hex_to_bytes : + IsImported globals "ethereum.utils.hexadecimal" "hex_to_bytes". + +Axiom ethereum_imports_rlp : + IsImported globals "ethereum" "rlp". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_Bytes : + IsImported globals "ethereum.base_types" "Bytes". +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". +Axiom ethereum_base_types_imports_slotted_freezable : + IsImported globals "ethereum.base_types" "slotted_freezable". + +Axiom ethereum_arrow_glacier_blocks_imports_Receipt : + IsImported globals "ethereum.arrow_glacier.blocks" "Receipt". + +Axiom ethereum_arrow_glacier_fork_types_imports_Account : + IsImported globals "ethereum.arrow_glacier.fork_types" "Account". +Axiom ethereum_arrow_glacier_fork_types_imports_Address : + IsImported globals "ethereum.arrow_glacier.fork_types" "Address". +Axiom ethereum_arrow_glacier_fork_types_imports_Root : + IsImported globals "ethereum.arrow_glacier.fork_types" "Root". +Axiom ethereum_arrow_glacier_fork_types_imports_encode_account : + IsImported globals "ethereum.arrow_glacier.fork_types" "encode_account". + +Axiom ethereum_arrow_glacier_transactions_imports_LegacyTransaction : + IsImported globals "ethereum.arrow_glacier.transactions" "LegacyTransaction". + +Definition EMPTY_TRIE_ROOT : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Root" |), + make_list [ + M.call (| + M.get_name (| globals, "hex_to_bytes" |), + make_list [ + Constant.str "56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421" + ], + make_dict [] + |) + ], + make_dict [] + |) +)). + +Definition Node : Value.t := M.run ltac:(M.monadic ( + M.get_subscript (| + M.get_name (| globals, "Union" |), + make_tuple [ M.get_name (| globals, "Account" |); M.get_name (| globals, "Bytes" |); M.get_name (| globals, "LegacyTransaction" |); M.get_name (| globals, "Receipt" |); M.get_name (| globals, "Uint" |); M.get_name (| globals, "U256" |); Constant.None_ ] + |) +)). + +Definition K : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "TypeVar" |), + make_list [ + Constant.str "K" + ], + make_dict [] + |) +)). + +Definition V : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "TypeVar" |), + make_list [ + Constant.str "V"; + M.get_subscript (| + M.get_name (| globals, "Optional" |), + M.get_name (| globals, "Account" |) + |); + M.get_subscript (| + M.get_name (| globals, "Optional" |), + M.get_name (| globals, "Bytes" |) + |); + M.get_name (| globals, "Bytes" |); + M.get_subscript (| + M.get_name (| globals, "Optional" |), + M.get_subscript (| + M.get_name (| globals, "Union" |), + make_tuple [ M.get_name (| globals, "LegacyTransaction" |); M.get_name (| globals, "Bytes" |) ] + |) + |); + M.get_subscript (| + M.get_name (| globals, "Optional" |), + M.get_subscript (| + M.get_name (| globals, "Union" |), + make_tuple [ M.get_name (| globals, "Receipt" |); M.get_name (| globals, "Bytes" |) ] + |) + |); + M.get_name (| globals, "Uint" |); + M.get_name (| globals, "U256" |) + ], + make_dict [] + |) +)). + +Definition LeafNode : Value.t := + builtins.make_klass + [] + [ + + ] + [ + + ]. + +Definition ExtensionNode : Value.t := + builtins.make_klass + [] + [ + + ] + [ + + ]. + +Definition BranchNode : Value.t := + builtins.make_klass + [] + [ + + ] + [ + + ]. + +Definition InternalNode : Value.t := M.run ltac:(M.monadic ( + M.get_subscript (| + M.get_name (| globals, "Union" |), + make_tuple [ M.get_name (| globals, "LeafNode" |); M.get_name (| globals, "ExtensionNode" |); M.get_name (| globals, "BranchNode" |) ] + |) +)). + +Definition encode_internal_node : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "node" ] |) in + let _ := Constant.str " + Encodes a Merkle Trie node into its RLP form. The RLP will then be + serialized into a `Bytes` and hashed unless it is less that 32 bytes + when serialized. + + This function also accepts `None`, representing the absence of a node, + which is encoded to `b""""`. + + Parameters + ---------- + node : Optional[InternalNode] + The node to encode. + + Returns + ------- + encoded : `rlp.RLP` + The node encoded as RLP. + " in +(* At stmt: unsupported node type: AnnAssign *) + let _ := + (* if *) + M.if_then_else (| + Compare.is (| + M.get_name (| globals, "node" |), + Constant.None_ + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "unencoded" , + Constant.bytes "" + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, "isinstance" |), + make_list [ + M.get_name (| globals, "node" |); + M.get_name (| globals, "LeafNode" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "unencoded" , + make_tuple [ M.call (| + M.get_name (| globals, "nibble_list_to_compact" |), + make_list [ + M.get_field (| M.get_name (| globals, "node" |), "rest_of_key" |); + Constant.bool true + ], + make_dict [] + |); M.get_field (| M.get_name (| globals, "node" |), "value" |) ] + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, "isinstance" |), + make_list [ + M.get_name (| globals, "node" |); + M.get_name (| globals, "ExtensionNode" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "unencoded" , + make_tuple [ M.call (| + M.get_name (| globals, "nibble_list_to_compact" |), + make_list [ + M.get_field (| M.get_name (| globals, "node" |), "key_segment" |); + Constant.bool false + ], + make_dict [] + |); M.get_field (| M.get_name (| globals, "node" |), "subnode" |) ] + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, "isinstance" |), + make_list [ + M.get_name (| globals, "node" |); + M.get_name (| globals, "BranchNode" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "unencoded" , + BinOp.add (| + M.get_field (| M.get_name (| globals, "node" |), "subnodes" |), + make_list [ + M.get_field (| M.get_name (| globals, "node" |), "value" |) + ] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.raise (| Some (M.call (| + M.get_name (| globals, "AssertionError" |), + make_list [ + Constant.str "(* At expr: unsupported node type: JoinedStr *)" + ], + make_dict [] + |)) |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "encoded" , + M.call (| + M.get_field (| M.get_name (| globals, "rlp" |), "encode" |), + make_list [ + M.get_name (| globals, "unencoded" |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.lt (| + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_name (| globals, "encoded" |) + ], + make_dict [] + |), + Constant.int 32 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + M.get_name (| globals, "unencoded" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.return_ (| + M.call (| + M.get_name (| globals, "keccak256" |), + make_list [ + M.get_name (| globals, "encoded" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_)). + +Definition encode_node : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "node"; "storage_root" ] |) in + let _ := Constant.str " + Encode a Node for storage in the Merkle Trie. + + Currently mostly an unimplemented stub. + " in + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, "isinstance" |), + make_list [ + M.get_name (| globals, "node" |); + M.get_name (| globals, "Account" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assert (| Compare.is_not (| + M.get_name (| globals, "storage_root" |), + Constant.None_ + |) |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, "encode_account" |), + make_list [ + M.get_name (| globals, "node" |); + M.get_name (| globals, "storage_root" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, "isinstance" |), + make_list [ + M.get_name (| globals, "node" |); + make_tuple [ M.get_name (| globals, "LegacyTransaction" |); M.get_name (| globals, "Receipt" |); M.get_name (| globals, "U256" |) ] + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + M.call (| + M.get_field (| M.get_name (| globals, "rlp" |), "encode" |), + make_list [ + M.call (| + M.get_name (| globals, "cast" |), + make_list [ + M.get_field (| M.get_name (| globals, "rlp" |), "RLP" |); + M.get_name (| globals, "node" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, "isinstance" |), + make_list [ + M.get_name (| globals, "node" |); + M.get_name (| globals, "Bytes" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + M.get_name (| globals, "node" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.return_ (| + M.call (| + M.get_field (| M.get_name (| globals, "previous_trie" |), "encode_node" |), + make_list [ + M.get_name (| globals, "node" |); + M.get_name (| globals, "storage_root" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_)). + +Definition Trie : Value.t := + builtins.make_klass + [(* At base: unsupported node type: Subscript *)] + [ + + ] + [ + + ]. + +Definition copy_trie : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "trie" ] |) in + let _ := Constant.str " + Create a copy of `trie`. Since only frozen objects may be stored in tries, + the contents are reused. + + Parameters + ---------- + trie: `Trie` + Trie to copy. + + Returns + ------- + new_trie : `Trie[K, V]` + A copy of the trie. + " in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, "Trie" |), + make_list [ + M.get_field (| M.get_name (| globals, "trie" |), "secured" |); + M.get_field (| M.get_name (| globals, "trie" |), "default" |); + M.call (| + M.get_field (| M.get_name (| globals, "copy" |), "copy" |), + make_list [ + M.get_field (| M.get_name (| globals, "trie" |), "_data" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Definition trie_set : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "trie"; "key"; "value" ] |) in + let _ := Constant.str " + Stores an item in a Merkle Trie. + + This method deletes the key if `value == trie.default`, because the Merkle + Trie represents the default value by omitting it from the trie. + + Parameters + ---------- + trie: `Trie` + Trie to store in. + key : `Bytes` + Key to lookup. + value : `V` + Node to insert at `key`. + " in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, "value" |), + M.get_field (| M.get_name (| globals, "trie" |), "default" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + Compare.in_ (| + M.get_name (| globals, "key" |), + M.get_field (| M.get_name (| globals, "trie" |), "_data" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.delete (| M.get_subscript (| + M.get_field (| M.get_name (| globals, "trie" |), "_data" |), + M.get_name (| globals, "key" |) + |) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign (| + M.get_subscript (| + M.get_field (| M.get_name (| globals, "trie" |), "_data" |), + M.get_name (| globals, "key" |) + |), + M.get_name (| globals, "value" |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_)). + +Definition trie_get : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "trie"; "key" ] |) in + let _ := Constant.str " + Gets an item from the Merkle Trie. + + This method returns `trie.default` if the key is missing. + + Parameters + ---------- + trie: + Trie to lookup in. + key : + Key to lookup. + + Returns + ------- + node : `V` + Node at `key` in the trie. + " in + let _ := M.return_ (| + M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, "trie" |), "_data" |), "get" |), + make_list [ + M.get_name (| globals, "key" |); + M.get_field (| M.get_name (| globals, "trie" |), "default" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Definition common_prefix_length : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "a"; "b" ] |) in + let _ := Constant.str " + Find the longest common prefix of two sequences. + " in + let _ := + M.for_ (| + M.get_name (| globals, "i" |), + M.call (| + M.get_name (| globals, "range" |), + make_list [ + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_name (| globals, "a" |) + ], + make_dict [] + |) + ], + make_dict [] + |), + ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + BoolOp.or (| + Compare.gt_e (| + M.get_name (| globals, "i" |), + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_name (| globals, "b" |) + ], + make_dict [] + |) + |), + ltac:(M.monadic ( + Compare.not_eq (| + M.get_subscript (| + M.get_name (| globals, "a" |), + M.get_name (| globals, "i" |) + |), + M.get_subscript (| + M.get_name (| globals, "b" |), + M.get_name (| globals, "i" |) + |) + |) + )) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + M.get_name (| globals, "i" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_name (| globals, "a" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Definition nibble_list_to_compact : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "x"; "is_leaf" ] |) in + let _ := Constant.str " + Compresses nibble-list into a standard byte array with a flag. + + A nibble-list is a list of byte values no greater than `15`. The flag is + encoded in high nibble of the highest byte. The flag nibble can be broken + down into two two-bit flags. + + Highest nibble:: + + +---+---+----------+--------+ + | _ | _ | is_leaf | parity | + +---+---+----------+--------+ + 3 2 1 0 + + + The lowest bit of the nibble encodes the parity of the length of the + remaining nibbles -- `0` when even and `1` when odd. The second lowest bit + is used to distinguish leaf and extension nodes. The other two bits are not + used. + + Parameters + ---------- + x : + Array of nibbles. + is_leaf : + True if this is part of a leaf node, or false if it is an extension + node. + + Returns + ------- + compressed : `bytearray` + Compact byte array. + " in + let _ := M.assign_local (| + "compact" , + M.call (| + M.get_name (| globals, "bytearray" |), + make_list [], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + BinOp.mod_ (| + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_name (| globals, "x" |) + ], + make_dict [] + |), + Constant.int 2 + |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_field (| M.get_name (| globals, "compact" |), "append" |), + make_list [ + BinOp.mult (| + Constant.int 16, + BinOp.mult (| + Constant.int 2, + M.get_name (| globals, "is_leaf" |) + |) + |) + ], + make_dict [] + |) in + let _ := + M.for_ (| + M.get_name (| globals, "i" |), + M.call (| + M.get_name (| globals, "range" |), + make_list [ + Constant.int 0; + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_name (| globals, "x" |) + ], + make_dict [] + |); + Constant.int 2 + ], + make_dict [] + |), + ltac:(M.monadic ( + let _ := M.call (| + M.get_field (| M.get_name (| globals, "compact" |), "append" |), + make_list [ + BinOp.add (| + BinOp.mult (| + Constant.int 16, + M.get_subscript (| + M.get_name (| globals, "x" |), + M.get_name (| globals, "i" |) + |) + |), + M.get_subscript (| + M.get_name (| globals, "x" |), + BinOp.add (| + M.get_name (| globals, "i" |), + Constant.int 1 + |) + |) + |) + ], + make_dict [] + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.call (| + M.get_field (| M.get_name (| globals, "compact" |), "append" |), + make_list [ + BinOp.add (| + BinOp.mult (| + Constant.int 16, + BinOp.add (| + BinOp.mult (| + Constant.int 2, + M.get_name (| globals, "is_leaf" |) + |), + Constant.int 1 + |) + |), + M.get_subscript (| + M.get_name (| globals, "x" |), + Constant.int 0 + |) + |) + ], + make_dict [] + |) in + let _ := + M.for_ (| + M.get_name (| globals, "i" |), + M.call (| + M.get_name (| globals, "range" |), + make_list [ + Constant.int 1; + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_name (| globals, "x" |) + ], + make_dict [] + |); + Constant.int 2 + ], + make_dict [] + |), + ltac:(M.monadic ( + let _ := M.call (| + M.get_field (| M.get_name (| globals, "compact" |), "append" |), + make_list [ + BinOp.add (| + BinOp.mult (| + Constant.int 16, + M.get_subscript (| + M.get_name (| globals, "x" |), + M.get_name (| globals, "i" |) + |) + |), + M.get_subscript (| + M.get_name (| globals, "x" |), + BinOp.add (| + M.get_name (| globals, "i" |), + Constant.int 1 + |) + |) + |) + ], + make_dict [] + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + M.pure Constant.None_ + )) |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, "Bytes" |), + make_list [ + M.get_name (| globals, "compact" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Definition bytes_to_nibble_list : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "bytes_" ] |) in + let _ := Constant.str " + Converts a `Bytes` into to a sequence of nibbles (bytes with value < 16). + + Parameters + ---------- + bytes_: + The `Bytes` to convert. + + Returns + ------- + nibble_list : `Bytes` + The `Bytes` in nibble-list format. + " in + let _ := M.assign_local (| + "nibble_list" , + M.call (| + M.get_name (| globals, "bytearray" |), + make_list [ + BinOp.mult (| + Constant.int 2, + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_name (| globals, "bytes_" |) + ], + make_dict [] + |) + |) + ], + make_dict [] + |) + |) in + let _ := + M.for_ (| + make_tuple [ M.get_name (| globals, "byte_index" |); M.get_name (| globals, "byte" |) ], + M.call (| + M.get_name (| globals, "enumerate" |), + make_list [ + M.get_name (| globals, "bytes_" |) + ], + make_dict [] + |), + ltac:(M.monadic ( + let _ := M.assign (| + M.get_subscript (| + M.get_name (| globals, "nibble_list" |), + BinOp.mult (| + M.get_name (| globals, "byte_index" |), + Constant.int 2 + |) + |), + BinOp.r_shift (| + BinOp.bit_and (| + M.get_name (| globals, "byte" |), + Constant.int 240 + |), + Constant.int 4 + |) + |) in + let _ := M.assign (| + M.get_subscript (| + M.get_name (| globals, "nibble_list" |), + BinOp.add (| + BinOp.mult (| + M.get_name (| globals, "byte_index" |), + Constant.int 2 + |), + Constant.int 1 + |) + |), + BinOp.bit_and (| + M.get_name (| globals, "byte" |), + Constant.int 15 + |) + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, "Bytes" |), + make_list [ + M.get_name (| globals, "nibble_list" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Definition _prepare_trie : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "trie"; "get_storage_root" ] |) in + let _ := Constant.str " + Prepares the trie for root calculation. Removes values that are empty, + hashes the keys (if `secured == True`) and encodes all the nodes. + + Parameters + ---------- + trie : + The `Trie` to prepare. + get_storage_root : + Function to get the storage root of an account. Needed to encode + `Account` objects. + + Returns + ------- + out : `Mapping[ethereum.base_types.Bytes, Node]` + Object with keys mapped to nibble-byte form. + " in +(* At stmt: unsupported node type: AnnAssign *) + let _ := + M.for_ (| + make_tuple [ M.get_name (| globals, "preimage" |); M.get_name (| globals, "value" |) ], + M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, "trie" |), "_data" |), "items" |), + make_list [], + make_dict [] + |), + ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, "isinstance" |), + make_list [ + M.get_name (| globals, "value" |); + M.get_name (| globals, "Account" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assert (| Compare.is_not (| + M.get_name (| globals, "get_storage_root" |), + Constant.None_ + |) |) in + let _ := M.assign_local (| + "address" , + M.call (| + M.get_name (| globals, "Address" |), + make_list [ + M.get_name (| globals, "preimage" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "encoded_value" , + M.call (| + M.get_name (| globals, "encode_node" |), + make_list [ + M.get_name (| globals, "value" |); + M.call (| + M.get_name (| globals, "get_storage_root" |), + make_list [ + M.get_name (| globals, "address" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "encoded_value" , + M.call (| + M.get_name (| globals, "encode_node" |), + make_list [ + M.get_name (| globals, "value" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + )) |) in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + Compare.not_eq (| + M.get_name (| globals, "encoded_value" |), + Constant.bytes "" + |); + M.get_name (| globals, "AssertionError" |) + ], + make_dict [] + |) in +(* At stmt: unsupported node type: AnnAssign *) + let _ := + (* if *) + M.if_then_else (| + M.get_field (| M.get_name (| globals, "trie" |), "secured" |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "key" , + M.call (| + M.get_name (| globals, "keccak256" |), + make_list [ + M.get_name (| globals, "preimage" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "key" , + M.get_name (| globals, "preimage" |) + |) in + M.pure Constant.None_ + )) |) in + let _ := M.assign (| + M.get_subscript (| + M.get_name (| globals, "mapped" |), + M.call (| + M.get_name (| globals, "bytes_to_nibble_list" |), + make_list [ + M.get_name (| globals, "key" |) + ], + make_dict [] + |) + |), + M.get_name (| globals, "encoded_value" |) + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := M.return_ (| + M.get_name (| globals, "mapped" |) + |) in + M.pure Constant.None_)). + +Definition root : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "trie"; "get_storage_root" ] |) in + let _ := Constant.str " + Computes the root of a modified merkle patricia trie (MPT). + + Parameters + ---------- + trie : + `Trie` to get the root of. + get_storage_root : + Function to get the storage root of an account. Needed to encode + `Account` objects. + + + Returns + ------- + root : `.fork_types.Root` + MPT root of the underlying key-value pairs. + " in + let _ := M.assign_local (| + "obj" , + M.call (| + M.get_name (| globals, "_prepare_trie" |), + make_list [ + M.get_name (| globals, "trie" |); + M.get_name (| globals, "get_storage_root" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "root_node" , + M.call (| + M.get_name (| globals, "encode_internal_node" |), + make_list [ + M.call (| + M.get_name (| globals, "patricialize" |), + make_list [ + M.get_name (| globals, "obj" |); + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.lt (| + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.call (| + M.get_field (| M.get_name (| globals, "rlp" |), "encode" |), + make_list [ + M.get_name (| globals, "root_node" |) + ], + make_dict [] + |) + ], + make_dict [] + |), + Constant.int 32 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + M.call (| + M.get_name (| globals, "keccak256" |), + make_list [ + M.call (| + M.get_field (| M.get_name (| globals, "rlp" |), "encode" |), + make_list [ + M.get_name (| globals, "root_node" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assert (| M.call (| + M.get_name (| globals, "isinstance" |), + make_list [ + M.get_name (| globals, "root_node" |); + M.get_name (| globals, "Bytes" |) + ], + make_dict [] + |) |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, "Root" |), + make_list [ + M.get_name (| globals, "root_node" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_)). + +Definition patricialize : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "obj"; "level" ] |) in + let _ := Constant.str " + Structural composition function. + + Used to recursively patricialize and merkleize a dictionary. Includes + memoization of the tree structure and hashes. + + Parameters + ---------- + obj : + Underlying trie key-value pairs, with keys in nibble-list format. + level : + Current trie level. + + Returns + ------- + node : `ethereum.base_types.Bytes` + Root node of `obj`. + " in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_name (| globals, "obj" |) + ], + make_dict [] + |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + Constant.None_ + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "arbitrary_key" , + M.call (| + M.get_name (| globals, "next" |), + make_list [ + M.call (| + M.get_name (| globals, "iter" |), + make_list [ + M.get_name (| globals, "obj" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_name (| globals, "obj" |) + ], + make_dict [] + |), + Constant.int 1 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "leaf" , + M.call (| + M.get_name (| globals, "LeafNode" |), + make_list [ + M.slice (| + M.get_name (| globals, "arbitrary_key" |), + M.get_name (| globals, "level" |), + Constant.None_, + Constant.None_ + |); + M.get_subscript (| + M.get_name (| globals, "obj" |), + M.get_name (| globals, "arbitrary_key" |) + |) + ], + make_dict [] + |) + |) in + let _ := M.return_ (| + M.get_name (| globals, "leaf" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "substring" , + M.slice (| + M.get_name (| globals, "arbitrary_key" |), + M.get_name (| globals, "level" |), + Constant.None_, + Constant.None_ + |) + |) in + let _ := M.assign_local (| + "prefix_length" , + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_name (| globals, "substring" |) + ], + make_dict [] + |) + |) in + let _ := + M.for_ (| + M.get_name (| globals, "key" |), + M.get_name (| globals, "obj" |), + ltac:(M.monadic ( + let _ := M.assign_local (| + "prefix_length" , + M.call (| + M.get_name (| globals, "min" |), + make_list [ + M.get_name (| globals, "prefix_length" |); + M.call (| + M.get_name (| globals, "common_prefix_length" |), + make_list [ + M.get_name (| globals, "substring" |); + M.slice (| + M.get_name (| globals, "key" |), + M.get_name (| globals, "level" |), + Constant.None_, + Constant.None_ + |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, "prefix_length" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.break (| |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.gt (| + M.get_name (| globals, "prefix_length" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "prefix" , + M.slice (| + M.get_name (| globals, "arbitrary_key" |), + M.get_name (| globals, "level" |), + BinOp.add (| + M.get_name (| globals, "level" |), + M.get_name (| globals, "prefix_length" |) + |), + Constant.None_ + |) + |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, "ExtensionNode" |), + make_list [ + M.get_name (| globals, "prefix" |); + M.call (| + M.get_name (| globals, "encode_internal_node" |), + make_list [ + M.call (| + M.get_name (| globals, "patricialize" |), + make_list [ + M.get_name (| globals, "obj" |); + BinOp.add (| + M.get_name (| globals, "level" |), + M.get_name (| globals, "prefix_length" |) + |) + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in +(* At stmt: unsupported node type: AnnAssign *) + let _ := + M.for_ (| + M.get_name (| globals, "_" |), + M.call (| + M.get_name (| globals, "range" |), + make_list [ + Constant.int 16 + ], + make_dict [] + |), + ltac:(M.monadic ( + let _ := M.call (| + M.get_field (| M.get_name (| globals, "branches" |), "append" |), + make_list [ + Constant.str "(* At expr: unsupported node type: Dict *)" + ], + make_dict [] + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := M.assign_local (| + "value" , + Constant.bytes "" + |) in + let _ := + M.for_ (| + M.get_name (| globals, "key" |), + M.get_name (| globals, "obj" |), + ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_name (| globals, "key" |) + ], + make_dict [] + |), + M.get_name (| globals, "level" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, "isinstance" |), + make_list [ + M.get_subscript (| + M.get_name (| globals, "obj" |), + M.get_name (| globals, "key" |) + |); + make_tuple [ M.get_name (| globals, "Account" |); M.get_name (| globals, "Receipt" |); M.get_name (| globals, "Uint" |) ] + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, "AssertionError" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "value" , + M.get_subscript (| + M.get_name (| globals, "obj" |), + M.get_name (| globals, "key" |) + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign (| + M.get_subscript (| + M.get_subscript (| + M.get_name (| globals, "branches" |), + M.get_subscript (| + M.get_name (| globals, "key" |), + M.get_name (| globals, "level" |) + |) + |), + M.get_name (| globals, "key" |) + |), + M.get_subscript (| + M.get_name (| globals, "obj" |), + M.get_name (| globals, "key" |) + |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, "BranchNode" |), + make_list [ + Constant.str "(* At expr: unsupported node type: ListComp *)"; + M.get_name (| globals, "value" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). diff --git a/CoqOfPython/ethereum/arrow_glacier/utils/__init__.v b/CoqOfPython/ethereum/arrow_glacier/utils/__init__.v new file mode 100644 index 0000000..15ee17f --- /dev/null +++ b/CoqOfPython/ethereum/arrow_glacier/utils/__init__.v @@ -0,0 +1,8 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.arrow_glacier.utils.__init__". + +Definition expr_1 : Value.t := + Constant.str " +Utility functions unique to this particular fork. +". diff --git a/CoqOfPython/ethereum/arrow_glacier/utils/address.v b/CoqOfPython/ethereum/arrow_glacier/utils/address.v new file mode 100644 index 0000000..34dfc3f --- /dev/null +++ b/CoqOfPython/ethereum/arrow_glacier/utils/address.v @@ -0,0 +1,227 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.arrow_glacier.utils.address". + +Definition expr_1 : Value.t := + Constant.str " +Hardfork Utility Functions For Addresses +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Address specific functions used in this arrow_glacier version of +specification. +". + +Axiom typing_imports_Union : + IsImported globals "typing" "Union". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_Bytes32 : + IsImported globals "ethereum.base_types" "Bytes32". +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". + +Axiom ethereum_crypto_hash_imports_keccak256 : + IsImported globals "ethereum.crypto.hash" "keccak256". + +Axiom ethereum_utils_byte_imports_left_pad_zero_bytes : + IsImported globals "ethereum.utils.byte" "left_pad_zero_bytes". + +Axiom ethereum_imports_rlp : + IsImported globals "ethereum" "rlp". + +Axiom ethereum_arrow_glacier_fork_types_imports_Address : + IsImported globals "ethereum.arrow_glacier.fork_types" "Address". + +Definition to_address : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "data" ] |) in + let _ := Constant.str " + Convert a Uint or U256 value to a valid address (20 bytes). + + Parameters + ---------- + data : + The string to be converted to bytes. + + Returns + ------- + address : `Address` + The obtained address. + " in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, "Address" |), + make_list [ + M.slice (| + M.call (| + M.get_field (| M.get_name (| globals, "data" |), "to_be_bytes32" |), + make_list [], + make_dict [] + |), + UnOp.sub (| Constant.int 20 |), + Constant.None_, + Constant.None_ + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Definition compute_contract_address : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "address"; "nonce" ] |) in + let _ := Constant.str " + Computes address of the new account that needs to be created. + + Parameters + ---------- + address : + The address of the account that wants to create the new account. + nonce : + The transaction count of the account that wants to create the new + account. + + Returns + ------- + address: `Address` + The computed address of the new account. + " in + let _ := M.assign_local (| + "computed_address" , + M.call (| + M.get_name (| globals, "keccak256" |), + make_list [ + M.call (| + M.get_field (| M.get_name (| globals, "rlp" |), "encode" |), + make_list [ + make_list [ + M.get_name (| globals, "address" |); + M.get_name (| globals, "nonce" |) + ] + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "canonical_address" , + M.slice (| + M.get_name (| globals, "computed_address" |), + UnOp.sub (| Constant.int 20 |), + Constant.None_, + Constant.None_ + |) + |) in + let _ := M.assign_local (| + "padded_address" , + M.call (| + M.get_name (| globals, "left_pad_zero_bytes" |), + make_list [ + M.get_name (| globals, "canonical_address" |); + Constant.int 20 + ], + make_dict [] + |) + |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, "Address" |), + make_list [ + M.get_name (| globals, "padded_address" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Definition compute_create2_contract_address : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "address"; "salt"; "call_data" ] |) in + let _ := Constant.str " + Computes address of the new account that needs to be created, which is + based on the sender address, salt and the call data as well. + + Parameters + ---------- + address : + The address of the account that wants to create the new account. + salt : + Address generation salt. + call_data : + The code of the new account which is to be created. + + Returns + ------- + address: `ethereum.arrow_glacier.fork_types.Address` + The computed address of the new account. + " in + let _ := M.assign_local (| + "preimage" , + BinOp.add (| + BinOp.add (| + BinOp.add (| + Constant.bytes "ff", + M.get_name (| globals, "address" |) + |), + M.get_name (| globals, "salt" |) + |), + M.call (| + M.get_name (| globals, "keccak256" |), + make_list [ + M.get_name (| globals, "call_data" |) + ], + make_dict [] + |) + |) + |) in + let _ := M.assign_local (| + "computed_address" , + M.call (| + M.get_name (| globals, "keccak256" |), + make_list [ + M.get_name (| globals, "preimage" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "canonical_address" , + M.slice (| + M.get_name (| globals, "computed_address" |), + UnOp.sub (| Constant.int 20 |), + Constant.None_, + Constant.None_ + |) + |) in + let _ := M.assign_local (| + "padded_address" , + M.call (| + M.get_name (| globals, "left_pad_zero_bytes" |), + make_list [ + M.get_name (| globals, "canonical_address" |); + Constant.int 20 + ], + make_dict [] + |) + |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, "Address" |), + make_list [ + M.get_name (| globals, "padded_address" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). diff --git a/CoqOfPython/ethereum/arrow_glacier/utils/hexadecimal.v b/CoqOfPython/ethereum/arrow_glacier/utils/hexadecimal.v new file mode 100644 index 0000000..7d39659 --- /dev/null +++ b/CoqOfPython/ethereum/arrow_glacier/utils/hexadecimal.v @@ -0,0 +1,153 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.arrow_glacier.utils.hexadecimal". + +Definition expr_1 : Value.t := + Constant.str " +Utility Functions For Hexadecimal Strings +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Hexadecimal utility functions used in this specification, specific to +Arrow Glacier types. +". + +Axiom ethereum_utils_hexadecimal_imports_remove_hex_prefix : + IsImported globals "ethereum.utils.hexadecimal" "remove_hex_prefix". + +Axiom ethereum_arrow_glacier_fork_types_imports_Address : + IsImported globals "ethereum.arrow_glacier.fork_types" "Address". +Axiom ethereum_arrow_glacier_fork_types_imports_Bloom : + IsImported globals "ethereum.arrow_glacier.fork_types" "Bloom". +Axiom ethereum_arrow_glacier_fork_types_imports_Root : + IsImported globals "ethereum.arrow_glacier.fork_types" "Root". + +Definition hex_to_root : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "hex_string" ] |) in + let _ := Constant.str " + Convert hex string to trie root. + + Parameters + ---------- + hex_string : + The hexadecimal string to be converted to trie root. + + Returns + ------- + root : `Root` + Trie root obtained from the given hexadecimal string. + " in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, "Root" |), + make_list [ + M.call (| + M.get_field (| M.get_name (| globals, "bytes" |), "fromhex" |), + make_list [ + M.call (| + M.get_name (| globals, "remove_hex_prefix" |), + make_list [ + M.get_name (| globals, "hex_string" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Definition hex_to_bloom : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "hex_string" ] |) in + let _ := Constant.str " + Convert hex string to bloom. + + Parameters + ---------- + hex_string : + The hexadecimal string to be converted to bloom. + + Returns + ------- + bloom : `Bloom` + Bloom obtained from the given hexadecimal string. + " in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, "Bloom" |), + make_list [ + M.call (| + M.get_field (| M.get_name (| globals, "bytes" |), "fromhex" |), + make_list [ + M.call (| + M.get_name (| globals, "remove_hex_prefix" |), + make_list [ + M.get_name (| globals, "hex_string" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Definition hex_to_address : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "hex_string" ] |) in + let _ := Constant.str " + Convert hex string to Address (20 bytes). + + Parameters + ---------- + hex_string : + The hexadecimal string to be converted to Address. + + Returns + ------- + address : `Address` + The address obtained from the given hexadecimal string. + " in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, "Address" |), + make_list [ + M.call (| + M.get_field (| M.get_name (| globals, "bytes" |), "fromhex" |), + make_list [ + M.call (| + M.get_field (| M.call (| + M.get_name (| globals, "remove_hex_prefix" |), + make_list [ + M.get_name (| globals, "hex_string" |) + ], + make_dict [] + |), "rjust" |), + make_list [ + Constant.int 40; + Constant.str "0" + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). diff --git a/CoqOfPython/ethereum/arrow_glacier/utils/message.v b/CoqOfPython/ethereum/arrow_glacier/utils/message.v new file mode 100644 index 0000000..c8a6555 --- /dev/null +++ b/CoqOfPython/ethereum/arrow_glacier/utils/message.v @@ -0,0 +1,266 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.arrow_glacier.utils.message". + +Definition expr_1 : Value.t := + Constant.str " +Hardfork Utility Functions For The Message Data-structure +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Message specific functions used in this arrow_glacier version of +specification. +". + +Axiom typing_imports_FrozenSet : + IsImported globals "typing" "FrozenSet". +Axiom typing_imports_Optional : + IsImported globals "typing" "Optional". +Axiom typing_imports_Tuple : + IsImported globals "typing" "Tuple". +Axiom typing_imports_Union : + IsImported globals "typing" "Union". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_Bytes : + IsImported globals "ethereum.base_types" "Bytes". +Axiom ethereum_base_types_imports_Bytes0 : + IsImported globals "ethereum.base_types" "Bytes0". +Axiom ethereum_base_types_imports_Bytes32 : + IsImported globals "ethereum.base_types" "Bytes32". +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". + +Axiom ethereum_arrow_glacier_fork_types_imports_Address : + IsImported globals "ethereum.arrow_glacier.fork_types" "Address". + +Axiom ethereum_arrow_glacier_state_imports_get_account : + IsImported globals "ethereum.arrow_glacier.state" "get_account". + +Axiom ethereum_arrow_glacier_vm_imports_Environment : + IsImported globals "ethereum.arrow_glacier.vm" "Environment". +Axiom ethereum_arrow_glacier_vm_imports_Message : + IsImported globals "ethereum.arrow_glacier.vm" "Message". + +Axiom ethereum_arrow_glacier_vm_precompiled_contracts_mapping_imports_PRE_COMPILED_CONTRACTS : + IsImported globals "ethereum.arrow_glacier.vm.precompiled_contracts.mapping" "PRE_COMPILED_CONTRACTS". + +Axiom ethereum_arrow_glacier_utils_address_imports_compute_contract_address : + IsImported globals "ethereum.arrow_glacier.utils.address" "compute_contract_address". + +Definition prepare_message : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "caller"; "target"; "value"; "data"; "gas"; "env"; "code_address"; "should_transfer_value"; "is_static"; "preaccessed_addresses"; "preaccessed_storage_keys" ] |) in + let _ := Constant.str " + Execute a transaction against the provided environment. + + Parameters + ---------- + caller : + Address which initiated the transaction + target : + Address whose code will be executed + value : + Value to be transferred. + data : + Array of bytes provided to the code in `target`. + gas : + Gas provided for the code in `target`. + env : + Environment for the Ethereum Virtual Machine. + code_address : + This is usually same as the `target` address except when an alternative + accounts code needs to be executed. + eg. `CALLCODE` calling a precompile. + should_transfer_value : + if True ETH should be transferred while executing a message call. + is_static: + if True then it prevents all state-changing operations from being + executed. + preaccessed_addresses: + Addresses that should be marked as accessed prior to the message call + preaccessed_storage_keys: + Storage keys that should be marked as accessed prior to the message + call + + Returns + ------- + message: `ethereum.arrow_glacier.vm.Message` + Items containing contract creation or message call specific data. + " in + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, "isinstance" |), + make_list [ + M.get_name (| globals, "target" |); + M.get_name (| globals, "Bytes0" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "current_target" , + M.call (| + M.get_name (| globals, "compute_contract_address" |), + make_list [ + M.get_name (| globals, "caller" |); + BinOp.sub (| + M.get_field (| M.call (| + M.get_name (| globals, "get_account" |), + make_list [ + M.get_field (| M.get_name (| globals, "env" |), "state" |); + M.get_name (| globals, "caller" |) + ], + make_dict [] + |), "nonce" |), + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 1 + ], + make_dict [] + |) + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "msg_data" , + M.call (| + M.get_name (| globals, "Bytes" |), + make_list [ + Constant.bytes "" + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "code" , + M.get_name (| globals, "data" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, "isinstance" |), + make_list [ + M.get_name (| globals, "target" |); + M.get_name (| globals, "Address" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "current_target" , + M.get_name (| globals, "target" |) + |) in + let _ := M.assign_local (| + "msg_data" , + M.get_name (| globals, "data" |) + |) in + let _ := M.assign_local (| + "code" , + M.get_field (| M.call (| + M.get_name (| globals, "get_account" |), + make_list [ + M.get_field (| M.get_name (| globals, "env" |), "state" |); + M.get_name (| globals, "target" |) + ], + make_dict [] + |), "code" |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.is (| + M.get_name (| globals, "code_address" |), + Constant.None_ + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "code_address" , + M.get_name (| globals, "target" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.raise (| Some (M.call (| + M.get_name (| globals, "AssertionError" |), + make_list [ + Constant.str "Target must be address or empty bytes" + ], + make_dict [] + |)) |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "accessed_addresses" , + M.call (| + M.get_name (| globals, "set" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_field (| M.get_name (| globals, "accessed_addresses" |), "add" |), + make_list [ + M.get_name (| globals, "current_target" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_field (| M.get_name (| globals, "accessed_addresses" |), "add" |), + make_list [ + M.get_name (| globals, "caller" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_field (| M.get_name (| globals, "accessed_addresses" |), "update" |), + make_list [ + M.call (| + M.get_field (| M.get_name (| globals, "PRE_COMPILED_CONTRACTS" |), "keys" |), + make_list [], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_field (| M.get_name (| globals, "accessed_addresses" |), "update" |), + make_list [ + M.get_name (| globals, "preaccessed_addresses" |) + ], + make_dict [] + |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, "Message" |), + make_list [], + make_dict [] + |) + |) in + M.pure Constant.None_)). diff --git a/CoqOfPython/ethereum/arrow_glacier/vm/__init__.v b/CoqOfPython/ethereum/arrow_glacier/vm/__init__.v new file mode 100644 index 0000000..19418af --- /dev/null +++ b/CoqOfPython/ethereum/arrow_glacier/vm/__init__.v @@ -0,0 +1,260 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.arrow_glacier.vm.__init__". + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +The abstract computer which runs the code stored in an +`.fork_types.Account`. +". + +Axiom dataclasses_imports_dataclass : + IsImported globals "dataclasses" "dataclass". + +Axiom typing_imports_List : + IsImported globals "typing" "List". +Axiom typing_imports_Optional : + IsImported globals "typing" "Optional". +Axiom typing_imports_Set : + IsImported globals "typing" "Set". +Axiom typing_imports_Tuple : + IsImported globals "typing" "Tuple". +Axiom typing_imports_Union : + IsImported globals "typing" "Union". + +Axiom ethereum_base_types_imports_U64 : + IsImported globals "ethereum.base_types" "U64". +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_Bytes : + IsImported globals "ethereum.base_types" "Bytes". +Axiom ethereum_base_types_imports_Bytes0 : + IsImported globals "ethereum.base_types" "Bytes0". +Axiom ethereum_base_types_imports_Bytes32 : + IsImported globals "ethereum.base_types" "Bytes32". +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". + +Axiom ethereum_crypto_hash_imports_Hash32 : + IsImported globals "ethereum.crypto.hash" "Hash32". + +Axiom ethereum_arrow_glacier_blocks_imports_Log : + IsImported globals "ethereum.arrow_glacier.blocks" "Log". + +Axiom ethereum_arrow_glacier_fork_types_imports_Address : + IsImported globals "ethereum.arrow_glacier.fork_types" "Address". + +Axiom ethereum_arrow_glacier_state_imports_State : + IsImported globals "ethereum.arrow_glacier.state" "State". +Axiom ethereum_arrow_glacier_state_imports_account_exists_and_is_empty : + IsImported globals "ethereum.arrow_glacier.state" "account_exists_and_is_empty". + +Axiom ethereum_arrow_glacier_vm_precompiled_contracts_imports_RIPEMD160_ADDRESS : + IsImported globals "ethereum.arrow_glacier.vm.precompiled_contracts" "RIPEMD160_ADDRESS". + +Definition __all__ : Value.t := M.run ltac:(M.monadic ( + make_tuple [ Constant.str "Environment"; Constant.str "Evm"; Constant.str "Message" ] +)). + +Definition Environment : Value.t := + builtins.make_klass + [] + [ + + ] + [ + + ]. + +Definition Message : Value.t := + builtins.make_klass + [] + [ + + ] + [ + + ]. + +Definition Evm : Value.t := + builtins.make_klass + [] + [ + + ] + [ + + ]. + +Definition incorporate_child_on_success : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm"; "child_evm" ] |) in + let _ := Constant.str " + Incorporate the state of a successful `child_evm` into the parent `evm`. + + Parameters + ---------- + evm : + The parent `EVM`. + child_evm : + The child evm to incorporate. + " in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "gas_left" |), + M.get_field (| M.get_name (| globals, "child_evm" |), "gas_left" |) + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "logs" |), + M.get_field (| M.get_name (| globals, "child_evm" |), "logs" |) + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "refund_counter" |), + M.get_field (| M.get_name (| globals, "child_evm" |), "refund_counter" |) + |) in + let _ := M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "accounts_to_delete" |), "update" |), + make_list [ + M.get_field (| M.get_name (| globals, "child_evm" |), "accounts_to_delete" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "touched_accounts" |), "update" |), + make_list [ + M.get_field (| M.get_name (| globals, "child_evm" |), "touched_accounts" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, "account_exists_and_is_empty" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "env" |), "state" |); + M.get_field (| M.get_field (| M.get_name (| globals, "child_evm" |), "message" |), "current_target" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "touched_accounts" |), "add" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "child_evm" |), "message" |), "current_target" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "accessed_addresses" |), "update" |), + make_list [ + M.get_field (| M.get_name (| globals, "child_evm" |), "accessed_addresses" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "accessed_storage_keys" |), "update" |), + make_list [ + M.get_field (| M.get_name (| globals, "child_evm" |), "accessed_storage_keys" |) + ], + make_dict [] + |) in + M.pure Constant.None_)). + +Definition incorporate_child_on_error : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm"; "child_evm" ] |) in + let _ := Constant.str " + Incorporate the state of an unsuccessful `child_evm` into the parent `evm`. + + Parameters + ---------- + evm : + The parent `EVM`. + child_evm : + The child evm to incorporate. + " in + let _ := + (* if *) + M.if_then_else (| + Compare.in_ (| + M.get_name (| globals, "RIPEMD160_ADDRESS" |), + M.get_field (| M.get_name (| globals, "child_evm" |), "touched_accounts" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "touched_accounts" |), "add" |), + make_list [ + M.get_name (| globals, "RIPEMD160_ADDRESS" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_field (| M.get_field (| M.get_name (| globals, "child_evm" |), "message" |), "current_target" |), + M.get_name (| globals, "RIPEMD160_ADDRESS" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, "account_exists_and_is_empty" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "env" |), "state" |); + M.get_field (| M.get_field (| M.get_name (| globals, "child_evm" |), "message" |), "current_target" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "touched_accounts" |), "add" |), + make_list [ + M.get_name (| globals, "RIPEMD160_ADDRESS" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "gas_left" |), + M.get_field (| M.get_name (| globals, "child_evm" |), "gas_left" |) + |) in + M.pure Constant.None_)). diff --git a/CoqOfPython/ethereum/arrow_glacier/vm/exceptions.v b/CoqOfPython/ethereum/arrow_glacier/vm/exceptions.v new file mode 100644 index 0000000..c699641 --- /dev/null +++ b/CoqOfPython/ethereum/arrow_glacier/vm/exceptions.v @@ -0,0 +1,171 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.arrow_glacier.vm.exceptions". + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) Exceptions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Exceptions which cause the EVM to halt exceptionally. +". + +Axiom ethereum_exceptions_imports_EthereumException : + IsImported globals "ethereum.exceptions" "EthereumException". + +Definition ExceptionalHalt : Value.t := + builtins.make_klass + [(globals, "EthereumException")] + [ + + ] + [ + + ]. + +Definition Revert : Value.t := + builtins.make_klass + [(globals, "EthereumException")] + [ + + ] + [ + + ]. + +Definition StackUnderflowError : Value.t := + builtins.make_klass + [(globals, "ExceptionalHalt")] + [ + + ] + [ + + ]. + +Definition StackOverflowError : Value.t := + builtins.make_klass + [(globals, "ExceptionalHalt")] + [ + + ] + [ + + ]. + +Definition OutOfGasError : Value.t := + builtins.make_klass + [(globals, "ExceptionalHalt")] + [ + + ] + [ + + ]. + +Definition InvalidOpcode : Value.t := + builtins.make_klass + [(globals, "ExceptionalHalt")] + [ + + ] + [ + ( + "__init__", + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "self"; "code" ] |) in + let _ := M.call (| + M.get_field (| M.call (| + M.get_name (| globals, "super" |), + make_list [], + make_dict [] + |), "__init__" |), + make_list [ + M.get_name (| globals, "code" |) + ], + make_dict [] + |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, "self" |), "code" |), + M.get_name (| globals, "code" |) + |) in + M.pure Constant.None_)) + ) + ]. + +Definition InvalidJumpDestError : Value.t := + builtins.make_klass + [(globals, "ExceptionalHalt")] + [ + + ] + [ + + ]. + +Definition StackDepthLimitError : Value.t := + builtins.make_klass + [(globals, "ExceptionalHalt")] + [ + + ] + [ + + ]. + +Definition WriteInStaticContext : Value.t := + builtins.make_klass + [(globals, "ExceptionalHalt")] + [ + + ] + [ + + ]. + +Definition OutOfBoundsRead : Value.t := + builtins.make_klass + [(globals, "ExceptionalHalt")] + [ + + ] + [ + + ]. + +Definition InvalidParameter : Value.t := + builtins.make_klass + [(globals, "ExceptionalHalt")] + [ + + ] + [ + + ]. + +Definition InvalidContractPrefix : Value.t := + builtins.make_klass + [(globals, "ExceptionalHalt")] + [ + + ] + [ + + ]. + +Definition AddressCollision : Value.t := + builtins.make_klass + [(globals, "ExceptionalHalt")] + [ + + ] + [ + + ]. diff --git a/CoqOfPython/ethereum/arrow_glacier/vm/gas.v b/CoqOfPython/ethereum/arrow_glacier/vm/gas.v new file mode 100644 index 0000000..ca2cac0 --- /dev/null +++ b/CoqOfPython/ethereum/arrow_glacier/vm/gas.v @@ -0,0 +1,912 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.arrow_glacier.vm.gas". + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) Gas +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +EVM gas constants and calculators. +". + +Axiom dataclasses_imports_dataclass : + IsImported globals "dataclasses" "dataclass". + +Axiom typing_imports_List : + IsImported globals "typing" "List". +Axiom typing_imports_Tuple : + IsImported globals "typing" "Tuple". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". + +Axiom ethereum_trace_imports_GasAndRefund : + IsImported globals "ethereum.trace" "GasAndRefund". +Axiom ethereum_trace_imports_evm_trace : + IsImported globals "ethereum.trace" "evm_trace". + +Axiom ethereum_utils_numeric_imports_ceil32 : + IsImported globals "ethereum.utils.numeric" "ceil32". + +Axiom ethereum_arrow_glacier_vm_imports_Evm : + IsImported globals "ethereum.arrow_glacier.vm" "Evm". + +Axiom ethereum_arrow_glacier_vm_exceptions_imports_OutOfGasError : + IsImported globals "ethereum.arrow_glacier.vm.exceptions" "OutOfGasError". + +Definition GAS_JUMPDEST : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 1 + ], + make_dict [] + |) +)). + +Definition GAS_BASE : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 2 + ], + make_dict [] + |) +)). + +Definition GAS_VERY_LOW : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 3 + ], + make_dict [] + |) +)). + +Definition GAS_STORAGE_SET : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 20000 + ], + make_dict [] + |) +)). + +Definition GAS_STORAGE_UPDATE : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 5000 + ], + make_dict [] + |) +)). + +Definition GAS_STORAGE_CLEAR_REFUND : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 4800 + ], + make_dict [] + |) +)). + +Definition GAS_LOW : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 5 + ], + make_dict [] + |) +)). + +Definition GAS_MID : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 8 + ], + make_dict [] + |) +)). + +Definition GAS_HIGH : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 10 + ], + make_dict [] + |) +)). + +Definition GAS_EXPONENTIATION : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 10 + ], + make_dict [] + |) +)). + +Definition GAS_EXPONENTIATION_PER_BYTE : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 50 + ], + make_dict [] + |) +)). + +Definition GAS_MEMORY : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 3 + ], + make_dict [] + |) +)). + +Definition GAS_KECCAK256 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 30 + ], + make_dict [] + |) +)). + +Definition GAS_KECCAK256_WORD : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 6 + ], + make_dict [] + |) +)). + +Definition GAS_COPY : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 3 + ], + make_dict [] + |) +)). + +Definition GAS_BLOCK_HASH : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 20 + ], + make_dict [] + |) +)). + +Definition GAS_LOG : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 375 + ], + make_dict [] + |) +)). + +Definition GAS_LOG_DATA : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 8 + ], + make_dict [] + |) +)). + +Definition GAS_LOG_TOPIC : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 375 + ], + make_dict [] + |) +)). + +Definition GAS_CREATE : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 32000 + ], + make_dict [] + |) +)). + +Definition GAS_CODE_DEPOSIT : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 200 + ], + make_dict [] + |) +)). + +Definition GAS_ZERO : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) +)). + +Definition GAS_NEW_ACCOUNT : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 25000 + ], + make_dict [] + |) +)). + +Definition GAS_CALL_VALUE : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 9000 + ], + make_dict [] + |) +)). + +Definition GAS_CALL_STIPEND : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 2300 + ], + make_dict [] + |) +)). + +Definition GAS_SELF_DESTRUCT : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 5000 + ], + make_dict [] + |) +)). + +Definition GAS_SELF_DESTRUCT_NEW_ACCOUNT : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 25000 + ], + make_dict [] + |) +)). + +Definition GAS_ECRECOVER : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 3000 + ], + make_dict [] + |) +)). + +Definition GAS_SHA256 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 60 + ], + make_dict [] + |) +)). + +Definition GAS_SHA256_WORD : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 12 + ], + make_dict [] + |) +)). + +Definition GAS_RIPEMD160 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 600 + ], + make_dict [] + |) +)). + +Definition GAS_RIPEMD160_WORD : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 120 + ], + make_dict [] + |) +)). + +Definition GAS_IDENTITY : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 15 + ], + make_dict [] + |) +)). + +Definition GAS_IDENTITY_WORD : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 3 + ], + make_dict [] + |) +)). + +Definition GAS_RETURN_DATA_COPY : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 3 + ], + make_dict [] + |) +)). + +Definition GAS_FAST_STEP : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 5 + ], + make_dict [] + |) +)). + +Definition GAS_BLAKE2_PER_ROUND : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 1 + ], + make_dict [] + |) +)). + +Definition GAS_COLD_SLOAD : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 2100 + ], + make_dict [] + |) +)). + +Definition GAS_COLD_ACCOUNT_ACCESS : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 2600 + ], + make_dict [] + |) +)). + +Definition GAS_WARM_ACCESS : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 100 + ], + make_dict [] + |) +)). + +Definition ExtendMemory : Value.t := + builtins.make_klass + [] + [ + + ] + [ + + ]. + +Definition MessageCallGas : Value.t := + builtins.make_klass + [] + [ + + ] + [ + + ]. + +Definition charge_gas : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm"; "amount" ] |) in + let _ := Constant.str " + Subtracts `amount` from `evm.gas_left`. + + Parameters + ---------- + evm : + The current EVM. + amount : + The amount of gas the current operation requires. + + " in + let _ := M.call (| + M.get_name (| globals, "evm_trace" |), + make_list [ + M.get_name (| globals, "evm" |); + M.call (| + M.get_name (| globals, "GasAndRefund" |), + make_list [ + M.get_name (| globals, "amount" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.lt (| + M.get_field (| M.get_name (| globals, "evm" |), "gas_left" |), + M.get_name (| globals, "amount" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, "OutOfGasError" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_op (| + BinOp.sub, + M.get_field (| M.get_name (| globals, "evm" |), "gas_left" |), + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + M.get_name (| globals, "amount" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_)). + +Definition calculate_memory_gas_cost : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "size_in_bytes" ] |) in + let _ := Constant.str " + Calculates the gas cost for allocating memory + to the smallest multiple of 32 bytes, + such that the allocated size is at least as big as the given size. + + Parameters + ---------- + size_in_bytes : + The size of the data in bytes. + + Returns + ------- + total_gas_cost : `ethereum.base_types.Uint` + The gas cost for storing data in memory. + " in + let _ := M.assign_local (| + "size_in_words" , + BinOp.floor_div (| + M.call (| + M.get_name (| globals, "ceil32" |), + make_list [ + M.get_name (| globals, "size_in_bytes" |) + ], + make_dict [] + |), + Constant.int 32 + |) + |) in + let _ := M.assign_local (| + "linear_cost" , + BinOp.mult (| + M.get_name (| globals, "size_in_words" |), + M.get_name (| globals, "GAS_MEMORY" |) + |) + |) in + let _ := M.assign_local (| + "quadratic_cost" , + BinOp.floor_div (| + BinOp.pow (| + M.get_name (| globals, "size_in_words" |), + Constant.int 2 + |), + Constant.int 512 + |) + |) in + let _ := M.assign_local (| + "total_gas_cost" , + BinOp.add (| + M.get_name (| globals, "linear_cost" |), + M.get_name (| globals, "quadratic_cost" |) + |) + |) in +(* At stmt: unsupported node type: Try *) + M.pure Constant.None_)). + +Definition calculate_gas_extend_memory : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "memory"; "extensions" ] |) in + let _ := Constant.str " + Calculates the gas amount to extend memory + + Parameters + ---------- + memory : + Memory contents of the EVM. + extensions: + List of extensions to be made to the memory. + Consists of a tuple of start position and size. + + Returns + ------- + extend_memory: `ExtendMemory` + " in + let _ := M.assign_local (| + "size_to_extend" , + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "to_be_paid" , + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "current_size" , + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_name (| globals, "memory" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := + M.for_ (| + make_tuple [ M.get_name (| globals, "start_position" |); M.get_name (| globals, "size" |) ], + M.get_name (| globals, "extensions" |), + ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, "size" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.continue (| |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "before_size" , + M.call (| + M.get_name (| globals, "ceil32" |), + make_list [ + M.get_name (| globals, "current_size" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "after_size" , + M.call (| + M.get_name (| globals, "ceil32" |), + make_list [ + BinOp.add (| + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.get_name (| globals, "start_position" |) + ], + make_dict [] + |), + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.get_name (| globals, "size" |) + ], + make_dict [] + |) + |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.lt_e (| + M.get_name (| globals, "after_size" |), + M.get_name (| globals, "before_size" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.continue (| |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_op_local (| + BinOp.add, + "size_to_extend", + BinOp.sub (| + M.get_name (| globals, "after_size" |), + M.get_name (| globals, "before_size" |) + |) + |) in + let _ := M.assign_local (| + "already_paid" , + M.call (| + M.get_name (| globals, "calculate_memory_gas_cost" |), + make_list [ + M.get_name (| globals, "before_size" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "total_cost" , + M.call (| + M.get_name (| globals, "calculate_memory_gas_cost" |), + make_list [ + M.get_name (| globals, "after_size" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_op_local (| + BinOp.add, + "to_be_paid", + BinOp.sub (| + M.get_name (| globals, "total_cost" |), + M.get_name (| globals, "already_paid" |) + |) + |) in + let _ := M.assign_local (| + "current_size" , + M.get_name (| globals, "after_size" |) + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, "ExtendMemory" |), + make_list [ + M.get_name (| globals, "to_be_paid" |); + M.get_name (| globals, "size_to_extend" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Definition calculate_message_call_gas : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "value"; "gas"; "gas_left"; "memory_cost"; "extra_gas"; "call_stipend" ] |) in + let _ := Constant.str " + Calculates the MessageCallGas (cost and stipend) for + executing call Opcodes. + + Parameters + ---------- + value: + The amount of `ETH` that needs to be transferred. + gas : + The amount of gas provided to the message-call. + gas_left : + The amount of gas left in the current frame. + memory_cost : + The amount needed to extend the memory in the current frame. + extra_gas : + The amount of gas needed for transferring value + creating a new + account inside a message call. + call_stipend : + The amount of stipend provided to a message call to execute code while + transferring value(ETH). + + Returns + ------- + message_call_gas: `MessageCallGas` + " in + let _ := M.assign_local (| + "call_stipend" , + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, "value" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( +M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + (* else *) + )), ltac:(M.monadic ( +M.get_name (| globals, "call_stipend" |) + )) |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.lt (| + M.get_name (| globals, "gas_left" |), + BinOp.add (| + M.get_name (| globals, "extra_gas" |), + M.get_name (| globals, "memory_cost" |) + |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + M.call (| + M.get_name (| globals, "MessageCallGas" |), + make_list [ + BinOp.add (| + M.get_name (| globals, "gas" |), + M.get_name (| globals, "extra_gas" |) + |); + BinOp.add (| + M.get_name (| globals, "gas" |), + M.get_name (| globals, "call_stipend" |) + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "gas" , + M.call (| + M.get_name (| globals, "min" |), + make_list [ + M.get_name (| globals, "gas" |); + M.call (| + M.get_name (| globals, "max_message_call_gas" |), + make_list [ + BinOp.sub (| + BinOp.sub (| + M.get_name (| globals, "gas_left" |), + M.get_name (| globals, "memory_cost" |) + |), + M.get_name (| globals, "extra_gas" |) + |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, "MessageCallGas" |), + make_list [ + BinOp.add (| + M.get_name (| globals, "gas" |), + M.get_name (| globals, "extra_gas" |) + |); + BinOp.add (| + M.get_name (| globals, "gas" |), + M.get_name (| globals, "call_stipend" |) + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Definition max_message_call_gas : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "gas" ] |) in + let _ := Constant.str " + Calculates the maximum gas that is allowed for making a message call + + Parameters + ---------- + gas : + The amount of gas provided to the message-call. + + Returns + ------- + max_allowed_message_call_gas: `ethereum.base_types.Uint` + The maximum gas allowed for making the message-call. + " in + let _ := M.return_ (| + BinOp.sub (| + M.get_name (| globals, "gas" |), + BinOp.floor_div (| + M.get_name (| globals, "gas" |), + Constant.int 64 + |) + |) + |) in + M.pure Constant.None_)). diff --git a/CoqOfPython/ethereum/arrow_glacier/vm/instructions/__init__.v b/CoqOfPython/ethereum/arrow_glacier/vm/instructions/__init__.v new file mode 100644 index 0000000..2163ec5 --- /dev/null +++ b/CoqOfPython/ethereum/arrow_glacier/vm/instructions/__init__.v @@ -0,0 +1,74 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.arrow_glacier.vm.instructions.__init__". + +Definition expr_1 : Value.t := + Constant.str " +EVM Instruction Encoding (Opcodes) +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Machine readable representations of EVM instructions, and a mapping to their +implementations. +". + +(* At top_level_stmt: unsupported node type: Import *) + +Axiom typing_imports_Callable : + IsImported globals "typing" "Callable". +Axiom typing_imports_Dict : + IsImported globals "typing" "Dict". + +Axiom ethereum_arrow_glacier_vm_instructions_imports_arithmetic : + IsImported globals "ethereum.arrow_glacier.vm.instructions" "arithmetic". + +Axiom ethereum_arrow_glacier_vm_instructions_imports_bitwise : + IsImported globals "ethereum.arrow_glacier.vm.instructions" "bitwise". + +Axiom ethereum_arrow_glacier_vm_instructions_imports_block : + IsImported globals "ethereum.arrow_glacier.vm.instructions" "block". + +Axiom ethereum_arrow_glacier_vm_instructions_imports_comparison : + IsImported globals "ethereum.arrow_glacier.vm.instructions" "comparison". + +Axiom ethereum_arrow_glacier_vm_instructions_imports_control_flow : + IsImported globals "ethereum.arrow_glacier.vm.instructions" "control_flow". + +Axiom ethereum_arrow_glacier_vm_instructions_imports_environment : + IsImported globals "ethereum.arrow_glacier.vm.instructions" "environment". + +Axiom ethereum_arrow_glacier_vm_instructions_imports_keccak : + IsImported globals "ethereum.arrow_glacier.vm.instructions" "keccak". + +Axiom ethereum_arrow_glacier_vm_instructions_imports_log : + IsImported globals "ethereum.arrow_glacier.vm.instructions" "log". + +Axiom ethereum_arrow_glacier_vm_instructions_imports_memory : + IsImported globals "ethereum.arrow_glacier.vm.instructions" "memory". + +Axiom ethereum_arrow_glacier_vm_instructions_imports_stack : + IsImported globals "ethereum.arrow_glacier.vm.instructions" "stack". + +Axiom ethereum_arrow_glacier_vm_instructions_imports_storage : + IsImported globals "ethereum.arrow_glacier.vm.instructions" "storage". + +Axiom ethereum_arrow_glacier_vm_instructions_imports_system : + IsImported globals "ethereum.arrow_glacier.vm.instructions" "system". + +Definition Ops : Value.t := + builtins.make_klass + [(* At base: unsupported node type: Attribute *)] + [ + + ] + [ + + ]. + +(* At top_level_stmt: unsupported node type: AnnAssign *) diff --git a/CoqOfPython/ethereum/arrow_glacier/vm/instructions/arithmetic.v b/CoqOfPython/ethereum/arrow_glacier/vm/instructions/arithmetic.v new file mode 100644 index 0000000..9c026ce --- /dev/null +++ b/CoqOfPython/ethereum/arrow_glacier/vm/instructions/arithmetic.v @@ -0,0 +1,1220 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.arrow_glacier.vm.instructions.arithmetic". + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) Arithmetic Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM Arithmetic instructions. +". + +Axiom ethereum_base_types_imports_U255_CEIL_VALUE : + IsImported globals "ethereum.base_types" "U255_CEIL_VALUE". +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_U256_CEIL_VALUE : + IsImported globals "ethereum.base_types" "U256_CEIL_VALUE". +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". + +Axiom ethereum_utils_numeric_imports_get_sign : + IsImported globals "ethereum.utils.numeric" "get_sign". + +Axiom ethereum_arrow_glacier_vm_imports_Evm : + IsImported globals "ethereum.arrow_glacier.vm" "Evm". + +Axiom ethereum_arrow_glacier_vm_gas_imports_GAS_EXPONENTIATION : + IsImported globals "ethereum.arrow_glacier.vm.gas" "GAS_EXPONENTIATION". +Axiom ethereum_arrow_glacier_vm_gas_imports_GAS_EXPONENTIATION_PER_BYTE : + IsImported globals "ethereum.arrow_glacier.vm.gas" "GAS_EXPONENTIATION_PER_BYTE". +Axiom ethereum_arrow_glacier_vm_gas_imports_GAS_LOW : + IsImported globals "ethereum.arrow_glacier.vm.gas" "GAS_LOW". +Axiom ethereum_arrow_glacier_vm_gas_imports_GAS_MID : + IsImported globals "ethereum.arrow_glacier.vm.gas" "GAS_MID". +Axiom ethereum_arrow_glacier_vm_gas_imports_GAS_VERY_LOW : + IsImported globals "ethereum.arrow_glacier.vm.gas" "GAS_VERY_LOW". +Axiom ethereum_arrow_glacier_vm_gas_imports_charge_gas : + IsImported globals "ethereum.arrow_glacier.vm.gas" "charge_gas". + +Axiom ethereum_arrow_glacier_vm_stack_imports_pop : + IsImported globals "ethereum.arrow_glacier.vm.stack" "pop". +Axiom ethereum_arrow_glacier_vm_stack_imports_push : + IsImported globals "ethereum.arrow_glacier.vm.stack" "push". + +Definition add : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Adds the top two elements of the stack together, and pushes the result back + on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "x" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "y" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_VERY_LOW" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "result" , + M.call (| + M.get_field (| M.get_name (| globals, "x" |), "wrapping_add" |), + make_list [ + M.get_name (| globals, "y" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.get_name (| globals, "result" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition sub : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Subtracts the top two elements of the stack, and pushes the result back + on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "x" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "y" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_VERY_LOW" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "result" , + M.call (| + M.get_field (| M.get_name (| globals, "x" |), "wrapping_sub" |), + make_list [ + M.get_name (| globals, "y" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.get_name (| globals, "result" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition mul : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Multiply the top two elements of the stack, and pushes the result back + on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "x" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "y" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_LOW" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "result" , + M.call (| + M.get_field (| M.get_name (| globals, "x" |), "wrapping_mul" |), + make_list [ + M.get_name (| globals, "y" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.get_name (| globals, "result" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition div : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Integer division of the top two elements of the stack. Pushes the result + back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "dividend" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "divisor" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_LOW" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, "divisor" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "quotient" , + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "quotient" , + BinOp.floor_div (| + M.get_name (| globals, "dividend" |), + M.get_name (| globals, "divisor" |) + |) + |) in + M.pure Constant.None_ + )) |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.get_name (| globals, "quotient" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition sdiv : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Signed integer division of the top two elements of the stack. Pushes the + result back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "dividend" , + M.call (| + M.get_field (| M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |), "to_signed" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "divisor" , + M.call (| + M.get_field (| M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |), "to_signed" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_LOW" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, "divisor" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "quotient" , + Constant.int 0 + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + BoolOp.and (| + Compare.eq (| + M.get_name (| globals, "dividend" |), + UnOp.sub (| M.get_name (| globals, "U255_CEIL_VALUE" |) |) + |), + ltac:(M.monadic ( + Compare.eq (| + M.get_name (| globals, "divisor" |), + UnOp.sub (| Constant.int 1 |) + |) + )) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "quotient" , + UnOp.sub (| M.get_name (| globals, "U255_CEIL_VALUE" |) |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "sign" , + M.call (| + M.get_name (| globals, "get_sign" |), + make_list [ + BinOp.mult (| + M.get_name (| globals, "dividend" |), + M.get_name (| globals, "divisor" |) + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "quotient" , + BinOp.mult (| + M.get_name (| globals, "sign" |), + BinOp.floor_div (| + M.call (| + M.get_name (| globals, "abs" |), + make_list [ + M.get_name (| globals, "dividend" |) + ], + make_dict [] + |), + M.call (| + M.get_name (| globals, "abs" |), + make_list [ + M.get_name (| globals, "divisor" |) + ], + make_dict [] + |) + |) + |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )) |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.call (| + M.get_field (| M.get_name (| globals, "U256" |), "from_signed" |), + make_list [ + M.get_name (| globals, "quotient" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition mod_ : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Modulo remainder of the top two elements of the stack. Pushes the result + back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "x" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "y" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_LOW" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, "y" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "remainder" , + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "remainder" , + BinOp.mod_ (| + M.get_name (| globals, "x" |), + M.get_name (| globals, "y" |) + |) + |) in + M.pure Constant.None_ + )) |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.get_name (| globals, "remainder" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition smod : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Signed modulo remainder of the top two elements of the stack. Pushes the + result back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "x" , + M.call (| + M.get_field (| M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |), "to_signed" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "y" , + M.call (| + M.get_field (| M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |), "to_signed" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_LOW" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, "y" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "remainder" , + Constant.int 0 + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "remainder" , + BinOp.mult (| + M.call (| + M.get_name (| globals, "get_sign" |), + make_list [ + M.get_name (| globals, "x" |) + ], + make_dict [] + |), + BinOp.mod_ (| + M.call (| + M.get_name (| globals, "abs" |), + make_list [ + M.get_name (| globals, "x" |) + ], + make_dict [] + |), + M.call (| + M.get_name (| globals, "abs" |), + make_list [ + M.get_name (| globals, "y" |) + ], + make_dict [] + |) + |) + |) + |) in + M.pure Constant.None_ + )) |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.call (| + M.get_field (| M.get_name (| globals, "U256" |), "from_signed" |), + make_list [ + M.get_name (| globals, "remainder" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition addmod : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Modulo addition of the top 2 elements with the 3rd element. Pushes the + result back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "x" , + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "y" , + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "z" , + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_MID" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, "z" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "result" , + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "result" , + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + BinOp.mod_ (| + BinOp.add (| + M.get_name (| globals, "x" |), + M.get_name (| globals, "y" |) + |), + M.get_name (| globals, "z" |) + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + )) |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.get_name (| globals, "result" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition mulmod : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Modulo multiplication of the top 2 elements with the 3rd element. Pushes + the result back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "x" , + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "y" , + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "z" , + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_MID" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, "z" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "result" , + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "result" , + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + BinOp.mod_ (| + BinOp.mult (| + M.get_name (| globals, "x" |), + M.get_name (| globals, "y" |) + |), + M.get_name (| globals, "z" |) + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + )) |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.get_name (| globals, "result" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition exp : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Exponential operation of the top 2 elements. Pushes the result back on + the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "base" , + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "exponent" , + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "exponent_bits" , + M.call (| + M.get_field (| M.get_name (| globals, "exponent" |), "bit_length" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "exponent_bytes" , + BinOp.floor_div (| + BinOp.add (| + M.get_name (| globals, "exponent_bits" |), + Constant.int 7 + |), + Constant.int 8 + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + BinOp.add (| + M.get_name (| globals, "GAS_EXPONENTIATION" |), + BinOp.mult (| + M.get_name (| globals, "GAS_EXPONENTIATION_PER_BYTE" |), + M.get_name (| globals, "exponent_bytes" |) + |) + |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "result" , + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + M.call (| + M.get_name (| globals, "pow" |), + make_list [ + M.get_name (| globals, "base" |); + M.get_name (| globals, "exponent" |); + M.get_name (| globals, "U256_CEIL_VALUE" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.get_name (| globals, "result" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition signextend : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Sign extend operation. In other words, extend a signed number which + fits in N bytes to 32 bytes. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "byte_num" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "value" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_LOW" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.gt (| + M.get_name (| globals, "byte_num" |), + Constant.int 31 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "result" , + M.get_name (| globals, "value" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "value_bytes" , + M.call (| + M.get_name (| globals, "bytes" |), + make_list [ + M.call (| + M.get_field (| M.get_name (| globals, "value" |), "to_be_bytes32" |), + make_list [], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "value_bytes" , + M.slice (| + M.get_name (| globals, "value_bytes" |), + BinOp.sub (| + Constant.int 31, + M.call (| + M.get_name (| globals, "int" |), + make_list [ + M.get_name (| globals, "byte_num" |) + ], + make_dict [] + |) + |), + Constant.None_, + Constant.None_ + |) + |) in + let _ := M.assign_local (| + "sign_bit" , + BinOp.r_shift (| + M.get_subscript (| + M.get_name (| globals, "value_bytes" |), + Constant.int 0 + |), + Constant.int 7 + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, "sign_bit" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "result" , + M.call (| + M.get_field (| M.get_name (| globals, "U256" |), "from_be_bytes" |), + make_list [ + M.get_name (| globals, "value_bytes" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "num_bytes_prepend" , + BinOp.sub (| + Constant.int 32, + BinOp.add (| + M.get_name (| globals, "byte_num" |), + Constant.int 1 + |) + |) + |) in + let _ := M.assign_local (| + "result" , + M.call (| + M.get_field (| M.get_name (| globals, "U256" |), "from_be_bytes" |), + make_list [ + BinOp.add (| + M.call (| + M.get_name (| globals, "bytearray" |), + make_list [ + BinOp.mult (| + make_list [ + Constant.int 255 + ], + M.get_name (| globals, "num_bytes_prepend" |) + |) + ], + make_dict [] + |), + M.get_name (| globals, "value_bytes" |) + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )) |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.get_name (| globals, "result" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). diff --git a/CoqOfPython/ethereum/arrow_glacier/vm/instructions/bitwise.v b/CoqOfPython/ethereum/arrow_glacier/vm/instructions/bitwise.v new file mode 100644 index 0000000..db4eddd --- /dev/null +++ b/CoqOfPython/ethereum/arrow_glacier/vm/instructions/bitwise.v @@ -0,0 +1,666 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.arrow_glacier.vm.instructions.bitwise". + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) Bitwise Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM bitwise instructions. +". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_U256_CEIL_VALUE : + IsImported globals "ethereum.base_types" "U256_CEIL_VALUE". + +Axiom ethereum_arrow_glacier_vm_imports_Evm : + IsImported globals "ethereum.arrow_glacier.vm" "Evm". + +Axiom ethereum_arrow_glacier_vm_gas_imports_GAS_VERY_LOW : + IsImported globals "ethereum.arrow_glacier.vm.gas" "GAS_VERY_LOW". +Axiom ethereum_arrow_glacier_vm_gas_imports_charge_gas : + IsImported globals "ethereum.arrow_glacier.vm.gas" "charge_gas". + +Axiom ethereum_arrow_glacier_vm_stack_imports_pop : + IsImported globals "ethereum.arrow_glacier.vm.stack" "pop". +Axiom ethereum_arrow_glacier_vm_stack_imports_push : + IsImported globals "ethereum.arrow_glacier.vm.stack" "push". + +Definition bitwise_and : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Bitwise AND operation of the top 2 elements of the stack. Pushes the + result back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "x" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "y" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_VERY_LOW" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + BinOp.bit_and (| + M.get_name (| globals, "x" |), + M.get_name (| globals, "y" |) + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition bitwise_or : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Bitwise OR operation of the top 2 elements of the stack. Pushes the + result back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "x" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "y" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_VERY_LOW" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + BinOp.bit_or (| + M.get_name (| globals, "x" |), + M.get_name (| globals, "y" |) + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition bitwise_xor : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Bitwise XOR operation of the top 2 elements of the stack. Pushes the + result back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "x" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "y" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_VERY_LOW" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + BinOp.bit_xor (| + M.get_name (| globals, "x" |), + M.get_name (| globals, "y" |) + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition bitwise_not : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Bitwise NOT operation of the top element of the stack. Pushes the + result back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "x" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_VERY_LOW" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + UnOp.invert (| M.get_name (| globals, "x" |) |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition get_byte : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + For a word (defined by next top element of the stack), retrieve the + Nth byte (0-indexed and defined by top element of stack) from the + left (most significant) to right (least significant). + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "byte_index" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "word" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_VERY_LOW" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.gt_e (| + M.get_name (| globals, "byte_index" |), + Constant.int 32 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "result" , + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "extra_bytes_to_right" , + BinOp.sub (| + Constant.int 31, + M.get_name (| globals, "byte_index" |) + |) + |) in + let _ := M.assign_local (| + "word" , + BinOp.r_shift (| + M.get_name (| globals, "word" |), + BinOp.mult (| + M.get_name (| globals, "extra_bytes_to_right" |), + Constant.int 8 + |) + |) + |) in + let _ := M.assign_local (| + "word" , + BinOp.bit_and (| + M.get_name (| globals, "word" |), + Constant.int 255 + |) + |) in + let _ := M.assign_local (| + "result" , + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + M.get_name (| globals, "word" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + )) |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.get_name (| globals, "result" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition bitwise_shl : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Logical shift left (SHL) operation of the top 2 elements of the stack. + Pushes the result back on the stack. + Parameters + ---------- + evm : + The current EVM frame. + " in + let _ := M.assign_local (| + "shift" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "value" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_VERY_LOW" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.lt (| + M.get_name (| globals, "shift" |), + Constant.int 256 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "result" , + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + BinOp.mod_ (| + BinOp.l_shift (| + M.get_name (| globals, "value" |), + M.get_name (| globals, "shift" |) + |), + M.get_name (| globals, "U256_CEIL_VALUE" |) + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "result" , + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + )) |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.get_name (| globals, "result" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition bitwise_shr : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Logical shift right (SHR) operation of the top 2 elements of the stack. + Pushes the result back on the stack. + Parameters + ---------- + evm : + The current EVM frame. + " in + let _ := M.assign_local (| + "shift" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "value" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_VERY_LOW" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.lt (| + M.get_name (| globals, "shift" |), + Constant.int 256 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "result" , + BinOp.r_shift (| + M.get_name (| globals, "value" |), + M.get_name (| globals, "shift" |) + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "result" , + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + )) |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.get_name (| globals, "result" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition bitwise_sar : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Arithmetic shift right (SAR) operation of the top 2 elements of the stack. + Pushes the result back on the stack. + Parameters + ---------- + evm : + The current EVM frame. + " in + let _ := M.assign_local (| + "shift" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "signed_value" , + M.call (| + M.get_field (| M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |), "to_signed" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_VERY_LOW" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.lt (| + M.get_name (| globals, "shift" |), + Constant.int 256 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "result" , + M.call (| + M.get_field (| M.get_name (| globals, "U256" |), "from_signed" |), + make_list [ + BinOp.r_shift (| + M.get_name (| globals, "signed_value" |), + M.get_name (| globals, "shift" |) + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + Compare.gt_e (| + M.get_name (| globals, "signed_value" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "result" , + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "result" , + M.get_field (| M.get_name (| globals, "U256" |), "MAX_VALUE" |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )) |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.get_name (| globals, "result" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). diff --git a/CoqOfPython/ethereum/arrow_glacier/vm/instructions/block.v b/CoqOfPython/ethereum/arrow_glacier/vm/instructions/block.v new file mode 100644 index 0000000..b5df822 --- /dev/null +++ b/CoqOfPython/ethereum/arrow_glacier/vm/instructions/block.v @@ -0,0 +1,390 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.arrow_glacier.vm.instructions.block". + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) Block Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM block instructions. +". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". + +Axiom ethereum_arrow_glacier_vm_imports_Evm : + IsImported globals "ethereum.arrow_glacier.vm" "Evm". + +Axiom ethereum_arrow_glacier_vm_gas_imports_GAS_BASE : + IsImported globals "ethereum.arrow_glacier.vm.gas" "GAS_BASE". +Axiom ethereum_arrow_glacier_vm_gas_imports_GAS_BLOCK_HASH : + IsImported globals "ethereum.arrow_glacier.vm.gas" "GAS_BLOCK_HASH". +Axiom ethereum_arrow_glacier_vm_gas_imports_charge_gas : + IsImported globals "ethereum.arrow_glacier.vm.gas" "charge_gas". + +Axiom ethereum_arrow_glacier_vm_stack_imports_pop : + IsImported globals "ethereum.arrow_glacier.vm.stack" "pop". +Axiom ethereum_arrow_glacier_vm_stack_imports_push : + IsImported globals "ethereum.arrow_glacier.vm.stack" "push". + +Definition block_hash : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Push the hash of one of the 256 most recent complete blocks onto the + stack. The block number to hash is present at the top of the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "block_number" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_BLOCK_HASH" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + BoolOp.or (| + Compare.lt_e (| + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "env" |), "number" |), + M.get_name (| globals, "block_number" |) + |), + ltac:(M.monadic ( + Compare.gt (| + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "env" |), "number" |), + BinOp.add (| + M.get_name (| globals, "block_number" |), + Constant.int 256 + |) + |) + )) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "hash" , + Constant.bytes "00" + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "hash" , + M.get_subscript (| + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "env" |), "block_hashes" |), + UnOp.sub (| BinOp.sub (| + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "env" |), "number" |), + M.get_name (| globals, "block_number" |) + |) |) + |) + |) in + M.pure Constant.None_ + )) |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.call (| + M.get_field (| M.get_name (| globals, "U256" |), "from_be_bytes" |), + make_list [ + M.get_name (| globals, "hash" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition coinbase : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Push the current block's beneficiary address (address of the block miner) + onto the stack. + + Here the current block refers to the block in which the currently + executing transaction/call resides. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_BASE" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.call (| + M.get_field (| M.get_name (| globals, "U256" |), "from_be_bytes" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "env" |), "coinbase" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition timestamp : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Push the current block's timestamp onto the stack. Here the timestamp + being referred is actually the unix timestamp in seconds. + + Here the current block refers to the block in which the currently + executing transaction/call resides. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_BASE" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "env" |), "time" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition number : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Push the current block's number onto the stack. + + Here the current block refers to the block in which the currently + executing transaction/call resides. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_BASE" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "env" |), "number" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition difficulty : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Push the current block's difficulty onto the stack. + + Here the current block refers to the block in which the currently + executing transaction/call resides. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_BASE" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "env" |), "difficulty" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition gas_limit : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Push the current block's gas limit onto the stack. + + Here the current block refers to the block in which the currently + executing transaction/call resides. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_BASE" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "env" |), "gas_limit" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition chain_id : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Push the chain id onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_BASE" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "env" |), "chain_id" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). diff --git a/CoqOfPython/ethereum/arrow_glacier/vm/instructions/comparison.v b/CoqOfPython/ethereum/arrow_glacier/vm/instructions/comparison.v new file mode 100644 index 0000000..a48a324 --- /dev/null +++ b/CoqOfPython/ethereum/arrow_glacier/vm/instructions/comparison.v @@ -0,0 +1,452 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.arrow_glacier.vm.instructions.comparison". + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) Comparison Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM Comparison instructions. +". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". + +Axiom ethereum_arrow_glacier_vm_imports_Evm : + IsImported globals "ethereum.arrow_glacier.vm" "Evm". + +Axiom ethereum_arrow_glacier_vm_gas_imports_GAS_VERY_LOW : + IsImported globals "ethereum.arrow_glacier.vm.gas" "GAS_VERY_LOW". +Axiom ethereum_arrow_glacier_vm_gas_imports_charge_gas : + IsImported globals "ethereum.arrow_glacier.vm.gas" "charge_gas". + +Axiom ethereum_arrow_glacier_vm_stack_imports_pop : + IsImported globals "ethereum.arrow_glacier.vm.stack" "pop". +Axiom ethereum_arrow_glacier_vm_stack_imports_push : + IsImported globals "ethereum.arrow_glacier.vm.stack" "push". + +Definition less_than : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Checks if the top element is less than the next top element. Pushes the + result back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "left" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "right" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_VERY_LOW" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "result" , + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Compare.lt (| + M.get_name (| globals, "left" |), + M.get_name (| globals, "right" |) + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.get_name (| globals, "result" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition signed_less_than : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Signed less-than comparison. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "left" , + M.call (| + M.get_field (| M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |), "to_signed" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "right" , + M.call (| + M.get_field (| M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |), "to_signed" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_VERY_LOW" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "result" , + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Compare.lt (| + M.get_name (| globals, "left" |), + M.get_name (| globals, "right" |) + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.get_name (| globals, "result" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition greater_than : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Checks if the top element is greater than the next top element. Pushes + the result back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "left" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "right" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_VERY_LOW" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "result" , + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Compare.gt (| + M.get_name (| globals, "left" |), + M.get_name (| globals, "right" |) + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.get_name (| globals, "result" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition signed_greater_than : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Signed greater-than comparison. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "left" , + M.call (| + M.get_field (| M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |), "to_signed" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "right" , + M.call (| + M.get_field (| M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |), "to_signed" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_VERY_LOW" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "result" , + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Compare.gt (| + M.get_name (| globals, "left" |), + M.get_name (| globals, "right" |) + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.get_name (| globals, "result" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition equal : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Checks if the top element is equal to the next top element. Pushes + the result back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "left" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "right" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_VERY_LOW" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "result" , + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Compare.eq (| + M.get_name (| globals, "left" |), + M.get_name (| globals, "right" |) + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.get_name (| globals, "result" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition is_zero : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Checks if the top element is equal to 0. Pushes the result back on the + stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "x" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_VERY_LOW" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "result" , + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Compare.eq (| + M.get_name (| globals, "x" |), + Constant.int 0 + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.get_name (| globals, "result" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). diff --git a/CoqOfPython/ethereum/arrow_glacier/vm/instructions/control_flow.v b/CoqOfPython/ethereum/arrow_glacier/vm/instructions/control_flow.v new file mode 100644 index 0000000..ab3b78d --- /dev/null +++ b/CoqOfPython/ethereum/arrow_glacier/vm/instructions/control_flow.v @@ -0,0 +1,350 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.arrow_glacier.vm.instructions.control_flow". + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) Control Flow Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM control flow instructions. +". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". + +Axiom ethereum_arrow_glacier_vm_gas_imports_GAS_BASE : + IsImported globals "ethereum.arrow_glacier.vm.gas" "GAS_BASE". +Axiom ethereum_arrow_glacier_vm_gas_imports_GAS_HIGH : + IsImported globals "ethereum.arrow_glacier.vm.gas" "GAS_HIGH". +Axiom ethereum_arrow_glacier_vm_gas_imports_GAS_JUMPDEST : + IsImported globals "ethereum.arrow_glacier.vm.gas" "GAS_JUMPDEST". +Axiom ethereum_arrow_glacier_vm_gas_imports_GAS_MID : + IsImported globals "ethereum.arrow_glacier.vm.gas" "GAS_MID". +Axiom ethereum_arrow_glacier_vm_gas_imports_charge_gas : + IsImported globals "ethereum.arrow_glacier.vm.gas" "charge_gas". + +Axiom ethereum_arrow_glacier_vm_imports_Evm : + IsImported globals "ethereum.arrow_glacier.vm" "Evm". + +Axiom ethereum_arrow_glacier_vm_exceptions_imports_InvalidJumpDestError : + IsImported globals "ethereum.arrow_glacier.vm.exceptions" "InvalidJumpDestError". + +Axiom ethereum_arrow_glacier_vm_stack_imports_pop : + IsImported globals "ethereum.arrow_glacier.vm.stack" "pop". +Axiom ethereum_arrow_glacier_vm_stack_imports_push : + IsImported globals "ethereum.arrow_glacier.vm.stack" "push". + +Definition stop : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Stop further execution of EVM code. + + Parameters + ---------- + evm : + The current EVM frame. + " in + let _ := M.pass (| |) in + let _ := M.pass (| |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, "evm" |), "running" |), + Constant.bool false + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition jump : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Alter the program counter to the location specified by the top of the + stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "jump_dest" , + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_MID" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.not_in (| + M.get_name (| globals, "jump_dest" |), + M.get_field (| M.get_name (| globals, "evm" |), "valid_jump_destinations" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, "InvalidJumpDestError" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.get_name (| globals, "jump_dest" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Definition jumpi : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Alter the program counter to the specified location if and only if a + condition is true. If the condition is not true, then the program counter + would increase only by 1. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "jump_dest" , + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "conditional_value" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_HIGH" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, "conditional_value" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "destination" , + BinOp.add (| + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + Compare.not_in (| + M.get_name (| globals, "jump_dest" |), + M.get_field (| M.get_name (| globals, "evm" |), "valid_jump_destinations" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, "InvalidJumpDestError" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "destination" , + M.get_name (| globals, "jump_dest" |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )) |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.get_name (| globals, "destination" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Definition pc : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Push onto the stack the value of the program counter after reaching the + current instruction and without increasing it for the next instruction. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_BASE" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "pc" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition gas_left : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Push the amount of available gas (including the corresponding reduction + for the cost of this instruction) onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_BASE" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "gas_left" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition jumpdest : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Mark a valid destination for jumps. This is a noop, present only + to be used by `JUMP` and `JUMPI` opcodes to verify that their jump is + valid. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_JUMPDEST" |) + ], + make_dict [] + |) in + let _ := M.pass (| |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). diff --git a/CoqOfPython/ethereum/arrow_glacier/vm/instructions/environment.v b/CoqOfPython/ethereum/arrow_glacier/vm/instructions/environment.v new file mode 100644 index 0000000..182c5e4 --- /dev/null +++ b/CoqOfPython/ethereum/arrow_glacier/vm/instructions/environment.v @@ -0,0 +1,1529 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.arrow_glacier.vm.instructions.environment". + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) Environmental Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM environment related instructions. +". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". + +Axiom ethereum_crypto_hash_imports_keccak256 : + IsImported globals "ethereum.crypto.hash" "keccak256". + +Axiom ethereum_utils_ensure_imports_ensure : + IsImported globals "ethereum.utils.ensure" "ensure". + +Axiom ethereum_utils_numeric_imports_ceil32 : + IsImported globals "ethereum.utils.numeric" "ceil32". + +Axiom ethereum_arrow_glacier_fork_types_imports_EMPTY_ACCOUNT : + IsImported globals "ethereum.arrow_glacier.fork_types" "EMPTY_ACCOUNT". + +Axiom ethereum_arrow_glacier_state_imports_get_account : + IsImported globals "ethereum.arrow_glacier.state" "get_account". + +Axiom ethereum_arrow_glacier_utils_address_imports_to_address : + IsImported globals "ethereum.arrow_glacier.utils.address" "to_address". + +Axiom ethereum_arrow_glacier_vm_memory_imports_buffer_read : + IsImported globals "ethereum.arrow_glacier.vm.memory" "buffer_read". +Axiom ethereum_arrow_glacier_vm_memory_imports_memory_write : + IsImported globals "ethereum.arrow_glacier.vm.memory" "memory_write". + +Axiom ethereum_arrow_glacier_vm_imports_Evm : + IsImported globals "ethereum.arrow_glacier.vm" "Evm". + +Axiom ethereum_arrow_glacier_vm_exceptions_imports_OutOfBoundsRead : + IsImported globals "ethereum.arrow_glacier.vm.exceptions" "OutOfBoundsRead". + +Axiom ethereum_arrow_glacier_vm_gas_imports_GAS_BASE : + IsImported globals "ethereum.arrow_glacier.vm.gas" "GAS_BASE". +Axiom ethereum_arrow_glacier_vm_gas_imports_GAS_COLD_ACCOUNT_ACCESS : + IsImported globals "ethereum.arrow_glacier.vm.gas" "GAS_COLD_ACCOUNT_ACCESS". +Axiom ethereum_arrow_glacier_vm_gas_imports_GAS_COPY : + IsImported globals "ethereum.arrow_glacier.vm.gas" "GAS_COPY". +Axiom ethereum_arrow_glacier_vm_gas_imports_GAS_FAST_STEP : + IsImported globals "ethereum.arrow_glacier.vm.gas" "GAS_FAST_STEP". +Axiom ethereum_arrow_glacier_vm_gas_imports_GAS_RETURN_DATA_COPY : + IsImported globals "ethereum.arrow_glacier.vm.gas" "GAS_RETURN_DATA_COPY". +Axiom ethereum_arrow_glacier_vm_gas_imports_GAS_VERY_LOW : + IsImported globals "ethereum.arrow_glacier.vm.gas" "GAS_VERY_LOW". +Axiom ethereum_arrow_glacier_vm_gas_imports_GAS_WARM_ACCESS : + IsImported globals "ethereum.arrow_glacier.vm.gas" "GAS_WARM_ACCESS". +Axiom ethereum_arrow_glacier_vm_gas_imports_calculate_gas_extend_memory : + IsImported globals "ethereum.arrow_glacier.vm.gas" "calculate_gas_extend_memory". +Axiom ethereum_arrow_glacier_vm_gas_imports_charge_gas : + IsImported globals "ethereum.arrow_glacier.vm.gas" "charge_gas". + +Axiom ethereum_arrow_glacier_vm_stack_imports_pop : + IsImported globals "ethereum.arrow_glacier.vm.stack" "pop". +Axiom ethereum_arrow_glacier_vm_stack_imports_push : + IsImported globals "ethereum.arrow_glacier.vm.stack" "push". + +Definition address : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Pushes the address of the current executing account to the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_BASE" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.call (| + M.get_field (| M.get_name (| globals, "U256" |), "from_be_bytes" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "current_target" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition balance : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Pushes the balance of the given account onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "address" , + M.call (| + M.get_name (| globals, "to_address" |), + make_list [ + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.in_ (| + M.get_name (| globals, "address" |), + M.get_field (| M.get_name (| globals, "evm" |), "accessed_addresses" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_WARM_ACCESS" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "accessed_addresses" |), "add" |), + make_list [ + M.get_name (| globals, "address" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_COLD_ACCOUNT_ACCESS" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "balance" , + M.get_field (| M.call (| + M.get_name (| globals, "get_account" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "env" |), "state" |); + M.get_name (| globals, "address" |) + ], + make_dict [] + |), "balance" |) + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.get_name (| globals, "balance" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition origin : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Pushes the address of the original transaction sender to the stack. + The origin address can only be an EOA. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_BASE" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.call (| + M.get_field (| M.get_name (| globals, "U256" |), "from_be_bytes" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "env" |), "origin" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition caller : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Pushes the address of the caller onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_BASE" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.call (| + M.get_field (| M.get_name (| globals, "U256" |), "from_be_bytes" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "caller" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition callvalue : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Push the value (in wei) sent with the call onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_BASE" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "value" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition calldataload : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Push a word (32 bytes) of the input data belonging to the current + environment onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "start_index" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_VERY_LOW" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "value" , + M.call (| + M.get_name (| globals, "buffer_read" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "data" |); + M.get_name (| globals, "start_index" |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 32 + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.call (| + M.get_field (| M.get_name (| globals, "U256" |), "from_be_bytes" |), + make_list [ + M.get_name (| globals, "value" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition calldatasize : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Push the size of input data in current environment onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_BASE" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "data" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition calldatacopy : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Copy a portion of the input data in current environment to memory. + + This will also expand the memory, in case that the memory is insufficient + to store the data. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "memory_start_index" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "data_start_index" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "size" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "words" , + BinOp.floor_div (| + M.call (| + M.get_name (| globals, "ceil32" |), + make_list [ + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.get_name (| globals, "size" |) + ], + make_dict [] + |) + ], + make_dict [] + |), + Constant.int 32 + |) + |) in + let _ := M.assign_local (| + "copy_gas_cost" , + BinOp.mult (| + M.get_name (| globals, "GAS_COPY" |), + M.get_name (| globals, "words" |) + |) + |) in + let _ := M.assign_local (| + "extend_memory" , + M.call (| + M.get_name (| globals, "calculate_gas_extend_memory" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "memory" |); + make_list [ + make_tuple [ M.get_name (| globals, "memory_start_index" |); M.get_name (| globals, "size" |) ] + ] + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + BinOp.add (| + BinOp.add (| + M.get_name (| globals, "GAS_VERY_LOW" |), + M.get_name (| globals, "copy_gas_cost" |) + |), + M.get_field (| M.get_name (| globals, "extend_memory" |), "cost" |) + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "memory" |), + BinOp.mult (| + Constant.bytes "00", + M.get_field (| M.get_name (| globals, "extend_memory" |), "expand_by" |) + |) + |) in + let _ := M.assign_local (| + "value" , + M.call (| + M.get_name (| globals, "buffer_read" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "data" |); + M.get_name (| globals, "data_start_index" |); + M.get_name (| globals, "size" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "memory_write" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "memory" |); + M.get_name (| globals, "memory_start_index" |); + M.get_name (| globals, "value" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition codesize : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Push the size of code running in current environment onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_BASE" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "code" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition codecopy : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Copy a portion of the code in current environment to memory. + + This will also expand the memory, in case that the memory is insufficient + to store the data. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "memory_start_index" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "code_start_index" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "size" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "words" , + BinOp.floor_div (| + M.call (| + M.get_name (| globals, "ceil32" |), + make_list [ + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.get_name (| globals, "size" |) + ], + make_dict [] + |) + ], + make_dict [] + |), + Constant.int 32 + |) + |) in + let _ := M.assign_local (| + "copy_gas_cost" , + BinOp.mult (| + M.get_name (| globals, "GAS_COPY" |), + M.get_name (| globals, "words" |) + |) + |) in + let _ := M.assign_local (| + "extend_memory" , + M.call (| + M.get_name (| globals, "calculate_gas_extend_memory" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "memory" |); + make_list [ + make_tuple [ M.get_name (| globals, "memory_start_index" |); M.get_name (| globals, "size" |) ] + ] + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + BinOp.add (| + BinOp.add (| + M.get_name (| globals, "GAS_VERY_LOW" |), + M.get_name (| globals, "copy_gas_cost" |) + |), + M.get_field (| M.get_name (| globals, "extend_memory" |), "cost" |) + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "memory" |), + BinOp.mult (| + Constant.bytes "00", + M.get_field (| M.get_name (| globals, "extend_memory" |), "expand_by" |) + |) + |) in + let _ := M.assign_local (| + "value" , + M.call (| + M.get_name (| globals, "buffer_read" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "code" |); + M.get_name (| globals, "code_start_index" |); + M.get_name (| globals, "size" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "memory_write" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "memory" |); + M.get_name (| globals, "memory_start_index" |); + M.get_name (| globals, "value" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition gasprice : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Push the gas price used in current environment onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_BASE" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "env" |), "gas_price" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition extcodesize : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Push the code size of a given account onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "address" , + M.call (| + M.get_name (| globals, "to_address" |), + make_list [ + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.in_ (| + M.get_name (| globals, "address" |), + M.get_field (| M.get_name (| globals, "evm" |), "accessed_addresses" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_WARM_ACCESS" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "accessed_addresses" |), "add" |), + make_list [ + M.get_name (| globals, "address" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_COLD_ACCOUNT_ACCESS" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "codesize" , + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_field (| M.call (| + M.get_name (| globals, "get_account" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "env" |), "state" |); + M.get_name (| globals, "address" |) + ], + make_dict [] + |), "code" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.get_name (| globals, "codesize" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition extcodecopy : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Copy a portion of an account's code to memory. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "address" , + M.call (| + M.get_name (| globals, "to_address" |), + make_list [ + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_start_index" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "code_start_index" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "size" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "words" , + BinOp.floor_div (| + M.call (| + M.get_name (| globals, "ceil32" |), + make_list [ + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.get_name (| globals, "size" |) + ], + make_dict [] + |) + ], + make_dict [] + |), + Constant.int 32 + |) + |) in + let _ := M.assign_local (| + "copy_gas_cost" , + BinOp.mult (| + M.get_name (| globals, "GAS_COPY" |), + M.get_name (| globals, "words" |) + |) + |) in + let _ := M.assign_local (| + "extend_memory" , + M.call (| + M.get_name (| globals, "calculate_gas_extend_memory" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "memory" |); + make_list [ + make_tuple [ M.get_name (| globals, "memory_start_index" |); M.get_name (| globals, "size" |) ] + ] + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.in_ (| + M.get_name (| globals, "address" |), + M.get_field (| M.get_name (| globals, "evm" |), "accessed_addresses" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + BinOp.add (| + BinOp.add (| + M.get_name (| globals, "GAS_WARM_ACCESS" |), + M.get_name (| globals, "copy_gas_cost" |) + |), + M.get_field (| M.get_name (| globals, "extend_memory" |), "cost" |) + |) + ], + make_dict [] + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "accessed_addresses" |), "add" |), + make_list [ + M.get_name (| globals, "address" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + BinOp.add (| + BinOp.add (| + M.get_name (| globals, "GAS_COLD_ACCOUNT_ACCESS" |), + M.get_name (| globals, "copy_gas_cost" |) + |), + M.get_field (| M.get_name (| globals, "extend_memory" |), "cost" |) + |) + ], + make_dict [] + |) in + M.pure Constant.None_ + )) |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "memory" |), + BinOp.mult (| + Constant.bytes "00", + M.get_field (| M.get_name (| globals, "extend_memory" |), "expand_by" |) + |) + |) in + let _ := M.assign_local (| + "code" , + M.get_field (| M.call (| + M.get_name (| globals, "get_account" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "env" |), "state" |); + M.get_name (| globals, "address" |) + ], + make_dict [] + |), "code" |) + |) in + let _ := M.assign_local (| + "value" , + M.call (| + M.get_name (| globals, "buffer_read" |), + make_list [ + M.get_name (| globals, "code" |); + M.get_name (| globals, "code_start_index" |); + M.get_name (| globals, "size" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "memory_write" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "memory" |); + M.get_name (| globals, "memory_start_index" |); + M.get_name (| globals, "value" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition returndatasize : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Pushes the size of the return data buffer onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_BASE" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "return_data" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition returndatacopy : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Copies data from the return data buffer code to memory + + Parameters + ---------- + evm : + The current EVM frame. + " in + let _ := M.assign_local (| + "memory_start_index" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "return_data_start_position" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "size" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "words" , + BinOp.floor_div (| + M.call (| + M.get_name (| globals, "ceil32" |), + make_list [ + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.get_name (| globals, "size" |) + ], + make_dict [] + |) + ], + make_dict [] + |), + Constant.int 32 + |) + |) in + let _ := M.assign_local (| + "copy_gas_cost" , + BinOp.mult (| + M.get_name (| globals, "GAS_RETURN_DATA_COPY" |), + M.get_name (| globals, "words" |) + |) + |) in + let _ := M.assign_local (| + "extend_memory" , + M.call (| + M.get_name (| globals, "calculate_gas_extend_memory" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "memory" |); + make_list [ + make_tuple [ M.get_name (| globals, "memory_start_index" |); M.get_name (| globals, "size" |) ] + ] + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + BinOp.add (| + BinOp.add (| + M.get_name (| globals, "GAS_VERY_LOW" |), + M.get_name (| globals, "copy_gas_cost" |) + |), + M.get_field (| M.get_name (| globals, "extend_memory" |), "cost" |) + |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + Compare.lt_e (| + BinOp.add (| + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.get_name (| globals, "return_data_start_position" |) + ], + make_dict [] + |), + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.get_name (| globals, "size" |) + ], + make_dict [] + |) + |), + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "return_data" |) + ], + make_dict [] + |) + |); + M.get_name (| globals, "OutOfBoundsRead" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "memory" |), + BinOp.mult (| + Constant.bytes "00", + M.get_field (| M.get_name (| globals, "extend_memory" |), "expand_by" |) + |) + |) in + let _ := M.assign_local (| + "value" , + M.slice (| + M.get_field (| M.get_name (| globals, "evm" |), "return_data" |), + M.get_name (| globals, "return_data_start_position" |), + BinOp.add (| + M.get_name (| globals, "return_data_start_position" |), + M.get_name (| globals, "size" |) + |), + Constant.None_ + |) + |) in + let _ := M.call (| + M.get_name (| globals, "memory_write" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "memory" |); + M.get_name (| globals, "memory_start_index" |); + M.get_name (| globals, "value" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition extcodehash : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Returns the keccak256 hash of a contract’s bytecode + Parameters + ---------- + evm : + The current EVM frame. + " in + let _ := M.assign_local (| + "address" , + M.call (| + M.get_name (| globals, "to_address" |), + make_list [ + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.in_ (| + M.get_name (| globals, "address" |), + M.get_field (| M.get_name (| globals, "evm" |), "accessed_addresses" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_WARM_ACCESS" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "accessed_addresses" |), "add" |), + make_list [ + M.get_name (| globals, "address" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_COLD_ACCOUNT_ACCESS" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "account" , + M.call (| + M.get_name (| globals, "get_account" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "env" |), "state" |); + M.get_name (| globals, "address" |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, "account" |), + M.get_name (| globals, "EMPTY_ACCOUNT" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "codehash" , + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "codehash" , + M.call (| + M.get_field (| M.get_name (| globals, "U256" |), "from_be_bytes" |), + make_list [ + M.call (| + M.get_name (| globals, "keccak256" |), + make_list [ + M.get_field (| M.get_name (| globals, "account" |), "code" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + )) |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.get_name (| globals, "codehash" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition self_balance : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Pushes the balance of the current address to the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_FAST_STEP" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "balance" , + M.get_field (| M.call (| + M.get_name (| globals, "get_account" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "env" |), "state" |); + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "current_target" |) + ], + make_dict [] + |), "balance" |) + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.get_name (| globals, "balance" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition base_fee : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Pushes the base fee of the current block on to the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_BASE" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "env" |), "base_fee_per_gas" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). diff --git a/CoqOfPython/ethereum/arrow_glacier/vm/instructions/keccak.v b/CoqOfPython/ethereum/arrow_glacier/vm/instructions/keccak.v new file mode 100644 index 0000000..eea02f8 --- /dev/null +++ b/CoqOfPython/ethereum/arrow_glacier/vm/instructions/keccak.v @@ -0,0 +1,188 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.arrow_glacier.vm.instructions.keccak". + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) Keccak Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM keccak instructions. +". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". + +Axiom ethereum_crypto_hash_imports_keccak256 : + IsImported globals "ethereum.crypto.hash" "keccak256". + +Axiom ethereum_utils_numeric_imports_ceil32 : + IsImported globals "ethereum.utils.numeric" "ceil32". + +Axiom ethereum_arrow_glacier_vm_imports_Evm : + IsImported globals "ethereum.arrow_glacier.vm" "Evm". + +Axiom ethereum_arrow_glacier_vm_gas_imports_GAS_KECCAK256 : + IsImported globals "ethereum.arrow_glacier.vm.gas" "GAS_KECCAK256". +Axiom ethereum_arrow_glacier_vm_gas_imports_GAS_KECCAK256_WORD : + IsImported globals "ethereum.arrow_glacier.vm.gas" "GAS_KECCAK256_WORD". +Axiom ethereum_arrow_glacier_vm_gas_imports_calculate_gas_extend_memory : + IsImported globals "ethereum.arrow_glacier.vm.gas" "calculate_gas_extend_memory". +Axiom ethereum_arrow_glacier_vm_gas_imports_charge_gas : + IsImported globals "ethereum.arrow_glacier.vm.gas" "charge_gas". + +Axiom ethereum_arrow_glacier_vm_memory_imports_memory_read_bytes : + IsImported globals "ethereum.arrow_glacier.vm.memory" "memory_read_bytes". + +Axiom ethereum_arrow_glacier_vm_stack_imports_pop : + IsImported globals "ethereum.arrow_glacier.vm.stack" "pop". +Axiom ethereum_arrow_glacier_vm_stack_imports_push : + IsImported globals "ethereum.arrow_glacier.vm.stack" "push". + +Definition keccak : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Pushes to the stack the Keccak-256 hash of a region of memory. + + This also expands the memory, in case the memory is insufficient to + access the data's memory location. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "memory_start_index" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "size" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "words" , + BinOp.floor_div (| + M.call (| + M.get_name (| globals, "ceil32" |), + make_list [ + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.get_name (| globals, "size" |) + ], + make_dict [] + |) + ], + make_dict [] + |), + Constant.int 32 + |) + |) in + let _ := M.assign_local (| + "word_gas_cost" , + BinOp.mult (| + M.get_name (| globals, "GAS_KECCAK256_WORD" |), + M.get_name (| globals, "words" |) + |) + |) in + let _ := M.assign_local (| + "extend_memory" , + M.call (| + M.get_name (| globals, "calculate_gas_extend_memory" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "memory" |); + make_list [ + make_tuple [ M.get_name (| globals, "memory_start_index" |); M.get_name (| globals, "size" |) ] + ] + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + BinOp.add (| + BinOp.add (| + M.get_name (| globals, "GAS_KECCAK256" |), + M.get_name (| globals, "word_gas_cost" |) + |), + M.get_field (| M.get_name (| globals, "extend_memory" |), "cost" |) + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "memory" |), + BinOp.mult (| + Constant.bytes "00", + M.get_field (| M.get_name (| globals, "extend_memory" |), "expand_by" |) + |) + |) in + let _ := M.assign_local (| + "data" , + M.call (| + M.get_name (| globals, "memory_read_bytes" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "memory" |); + M.get_name (| globals, "memory_start_index" |); + M.get_name (| globals, "size" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "hash" , + M.call (| + M.get_name (| globals, "keccak256" |), + make_list [ + M.get_name (| globals, "data" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.call (| + M.get_field (| M.get_name (| globals, "U256" |), "from_be_bytes" |), + make_list [ + M.get_name (| globals, "hash" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). diff --git a/CoqOfPython/ethereum/arrow_glacier/vm/instructions/log.v b/CoqOfPython/ethereum/arrow_glacier/vm/instructions/log.v new file mode 100644 index 0000000..77cb339 --- /dev/null +++ b/CoqOfPython/ethereum/arrow_glacier/vm/instructions/log.v @@ -0,0 +1,256 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.arrow_glacier.vm.instructions.log". + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) Logging Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM logging instructions. +". + +Axiom functools_imports_partial : + IsImported globals "functools" "partial". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". + +Axiom ethereum_utils_ensure_imports_ensure : + IsImported globals "ethereum.utils.ensure" "ensure". + +Axiom ethereum_arrow_glacier_blocks_imports_Log : + IsImported globals "ethereum.arrow_glacier.blocks" "Log". + +Axiom ethereum_arrow_glacier_vm_imports_Evm : + IsImported globals "ethereum.arrow_glacier.vm" "Evm". + +Axiom ethereum_arrow_glacier_vm_exceptions_imports_WriteInStaticContext : + IsImported globals "ethereum.arrow_glacier.vm.exceptions" "WriteInStaticContext". + +Axiom ethereum_arrow_glacier_vm_gas_imports_GAS_LOG : + IsImported globals "ethereum.arrow_glacier.vm.gas" "GAS_LOG". +Axiom ethereum_arrow_glacier_vm_gas_imports_GAS_LOG_DATA : + IsImported globals "ethereum.arrow_glacier.vm.gas" "GAS_LOG_DATA". +Axiom ethereum_arrow_glacier_vm_gas_imports_GAS_LOG_TOPIC : + IsImported globals "ethereum.arrow_glacier.vm.gas" "GAS_LOG_TOPIC". +Axiom ethereum_arrow_glacier_vm_gas_imports_calculate_gas_extend_memory : + IsImported globals "ethereum.arrow_glacier.vm.gas" "calculate_gas_extend_memory". +Axiom ethereum_arrow_glacier_vm_gas_imports_charge_gas : + IsImported globals "ethereum.arrow_glacier.vm.gas" "charge_gas". + +Axiom ethereum_arrow_glacier_vm_memory_imports_memory_read_bytes : + IsImported globals "ethereum.arrow_glacier.vm.memory" "memory_read_bytes". + +Axiom ethereum_arrow_glacier_vm_stack_imports_pop : + IsImported globals "ethereum.arrow_glacier.vm.stack" "pop". + +Definition log_n : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm"; "num_topics" ] |) in + let _ := Constant.str " + Appends a log entry, having `num_topics` topics, to the evm logs. + + This will also expand the memory if the data (required by the log entry) + corresponding to the memory is not accessible. + + Parameters + ---------- + evm : + The current EVM frame. + num_topics : + The number of topics to be included in the log entry. + + " in + let _ := M.assign_local (| + "memory_start_index" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "size" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "topics" , + make_list [] + |) in + let _ := + M.for_ (| + M.get_name (| globals, "_" |), + M.call (| + M.get_name (| globals, "range" |), + make_list [ + M.get_name (| globals, "num_topics" |) + ], + make_dict [] + |), + ltac:(M.monadic ( + let _ := M.assign_local (| + "topic" , + M.call (| + M.get_field (| M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |), "to_be_bytes32" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_field (| M.get_name (| globals, "topics" |), "append" |), + make_list [ + M.get_name (| globals, "topic" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := M.assign_local (| + "extend_memory" , + M.call (| + M.get_name (| globals, "calculate_gas_extend_memory" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "memory" |); + make_list [ + make_tuple [ M.get_name (| globals, "memory_start_index" |); M.get_name (| globals, "size" |) ] + ] + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + BinOp.add (| + BinOp.add (| + BinOp.add (| + M.get_name (| globals, "GAS_LOG" |), + BinOp.mult (| + M.get_name (| globals, "GAS_LOG_DATA" |), + M.get_name (| globals, "size" |) + |) + |), + BinOp.mult (| + M.get_name (| globals, "GAS_LOG_TOPIC" |), + M.get_name (| globals, "num_topics" |) + |) + |), + M.get_field (| M.get_name (| globals, "extend_memory" |), "cost" |) + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "memory" |), + BinOp.mult (| + Constant.bytes "00", + M.get_field (| M.get_name (| globals, "extend_memory" |), "expand_by" |) + |) + |) in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + UnOp.not (| M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "is_static" |) |); + M.get_name (| globals, "WriteInStaticContext" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "log_entry" , + M.call (| + M.get_name (| globals, "Log" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, "evm" |), "logs" |), + BinOp.add (| + M.get_field (| M.get_name (| globals, "evm" |), "logs" |), + make_tuple [ M.get_name (| globals, "log_entry" |) ] + |) + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition log0 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "log_n" |) + ], + make_dict [] + |) +)). + +Definition log1 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "log_n" |) + ], + make_dict [] + |) +)). + +Definition log2 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "log_n" |) + ], + make_dict [] + |) +)). + +Definition log3 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "log_n" |) + ], + make_dict [] + |) +)). + +Definition log4 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "log_n" |) + ], + make_dict [] + |) +)). diff --git a/CoqOfPython/ethereum/arrow_glacier/vm/instructions/memory.v b/CoqOfPython/ethereum/arrow_glacier/vm/instructions/memory.v new file mode 100644 index 0000000..4fdbe0d --- /dev/null +++ b/CoqOfPython/ethereum/arrow_glacier/vm/instructions/memory.v @@ -0,0 +1,393 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.arrow_glacier.vm.instructions.memory". + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) Memory Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM Memory instructions. +". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_Bytes : + IsImported globals "ethereum.base_types" "Bytes". + +Axiom ethereum_arrow_glacier_vm_imports_Evm : + IsImported globals "ethereum.arrow_glacier.vm" "Evm". + +Axiom ethereum_arrow_glacier_vm_gas_imports_GAS_BASE : + IsImported globals "ethereum.arrow_glacier.vm.gas" "GAS_BASE". +Axiom ethereum_arrow_glacier_vm_gas_imports_GAS_VERY_LOW : + IsImported globals "ethereum.arrow_glacier.vm.gas" "GAS_VERY_LOW". +Axiom ethereum_arrow_glacier_vm_gas_imports_calculate_gas_extend_memory : + IsImported globals "ethereum.arrow_glacier.vm.gas" "calculate_gas_extend_memory". +Axiom ethereum_arrow_glacier_vm_gas_imports_charge_gas : + IsImported globals "ethereum.arrow_glacier.vm.gas" "charge_gas". + +Axiom ethereum_arrow_glacier_vm_memory_imports_memory_read_bytes : + IsImported globals "ethereum.arrow_glacier.vm.memory" "memory_read_bytes". +Axiom ethereum_arrow_glacier_vm_memory_imports_memory_write : + IsImported globals "ethereum.arrow_glacier.vm.memory" "memory_write". + +Axiom ethereum_arrow_glacier_vm_stack_imports_pop : + IsImported globals "ethereum.arrow_glacier.vm.stack" "pop". +Axiom ethereum_arrow_glacier_vm_stack_imports_push : + IsImported globals "ethereum.arrow_glacier.vm.stack" "push". + +Definition mstore : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Stores a word to memory. + This also expands the memory, if the memory is + insufficient to store the word. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "start_position" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "value" , + M.call (| + M.get_field (| M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |), "to_be_bytes32" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "extend_memory" , + M.call (| + M.get_name (| globals, "calculate_gas_extend_memory" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "memory" |); + make_list [ + make_tuple [ M.get_name (| globals, "start_position" |); M.call (| + M.get_name (| globals, "U256" |), + make_list [ + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_name (| globals, "value" |) + ], + make_dict [] + |) + ], + make_dict [] + |) ] + ] + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + BinOp.add (| + M.get_name (| globals, "GAS_VERY_LOW" |), + M.get_field (| M.get_name (| globals, "extend_memory" |), "cost" |) + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "memory" |), + BinOp.mult (| + Constant.bytes "00", + M.get_field (| M.get_name (| globals, "extend_memory" |), "expand_by" |) + |) + |) in + let _ := M.call (| + M.get_name (| globals, "memory_write" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "memory" |); + M.get_name (| globals, "start_position" |); + M.get_name (| globals, "value" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition mstore8 : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Stores a byte to memory. + This also expands the memory, if the memory is + insufficient to store the word. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "start_position" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "value" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "extend_memory" , + M.call (| + M.get_name (| globals, "calculate_gas_extend_memory" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "memory" |); + make_list [ + make_tuple [ M.get_name (| globals, "start_position" |); M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 1 + ], + make_dict [] + |) ] + ] + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + BinOp.add (| + M.get_name (| globals, "GAS_VERY_LOW" |), + M.get_field (| M.get_name (| globals, "extend_memory" |), "cost" |) + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "memory" |), + BinOp.mult (| + Constant.bytes "00", + M.get_field (| M.get_name (| globals, "extend_memory" |), "expand_by" |) + |) + |) in + let _ := M.assign_local (| + "normalized_bytes_value" , + M.call (| + M.get_name (| globals, "Bytes" |), + make_list [ + make_list [ + BinOp.bit_and (| + M.get_name (| globals, "value" |), + Constant.int 255 + |) + ] + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "memory_write" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "memory" |); + M.get_name (| globals, "start_position" |); + M.get_name (| globals, "normalized_bytes_value" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition mload : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Load word from memory. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "start_position" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "extend_memory" , + M.call (| + M.get_name (| globals, "calculate_gas_extend_memory" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "memory" |); + make_list [ + make_tuple [ M.get_name (| globals, "start_position" |); M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 32 + ], + make_dict [] + |) ] + ] + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + BinOp.add (| + M.get_name (| globals, "GAS_VERY_LOW" |), + M.get_field (| M.get_name (| globals, "extend_memory" |), "cost" |) + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "memory" |), + BinOp.mult (| + Constant.bytes "00", + M.get_field (| M.get_name (| globals, "extend_memory" |), "expand_by" |) + |) + |) in + let _ := M.assign_local (| + "value" , + M.call (| + M.get_field (| M.get_name (| globals, "U256" |), "from_be_bytes" |), + make_list [ + M.call (| + M.get_name (| globals, "memory_read_bytes" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "memory" |); + M.get_name (| globals, "start_position" |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 32 + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.get_name (| globals, "value" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition msize : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Push the size of active memory in bytes onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_BASE" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "memory" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). diff --git a/CoqOfPython/ethereum/arrow_glacier/vm/instructions/stack.v b/CoqOfPython/ethereum/arrow_glacier/vm/instructions/stack.v new file mode 100644 index 0000000..ba06637 --- /dev/null +++ b/CoqOfPython/ethereum/arrow_glacier/vm/instructions/stack.v @@ -0,0 +1,947 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.arrow_glacier.vm.instructions.stack". + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) Stack Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM stack related instructions. +". + +Axiom functools_imports_partial : + IsImported globals "functools" "partial". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". + +Axiom ethereum_utils_ensure_imports_ensure : + IsImported globals "ethereum.utils.ensure" "ensure". + +Axiom ethereum_arrow_glacier_vm_imports_Evm : + IsImported globals "ethereum.arrow_glacier.vm" "Evm". +Axiom ethereum_arrow_glacier_vm_imports_stack : + IsImported globals "ethereum.arrow_glacier.vm" "stack". + +Axiom ethereum_arrow_glacier_vm_exceptions_imports_StackUnderflowError : + IsImported globals "ethereum.arrow_glacier.vm.exceptions" "StackUnderflowError". + +Axiom ethereum_arrow_glacier_vm_gas_imports_GAS_BASE : + IsImported globals "ethereum.arrow_glacier.vm.gas" "GAS_BASE". +Axiom ethereum_arrow_glacier_vm_gas_imports_GAS_VERY_LOW : + IsImported globals "ethereum.arrow_glacier.vm.gas" "GAS_VERY_LOW". +Axiom ethereum_arrow_glacier_vm_gas_imports_charge_gas : + IsImported globals "ethereum.arrow_glacier.vm.gas" "charge_gas". + +Axiom ethereum_arrow_glacier_vm_memory_imports_buffer_read : + IsImported globals "ethereum.arrow_glacier.vm.memory" "buffer_read". + +Definition pop : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Remove item from stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.call (| + M.get_field (| M.get_name (| globals, "stack" |), "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_BASE" |) + ], + make_dict [] + |) in + let _ := M.pass (| |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition push_n : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm"; "num_bytes" ] |) in + let _ := Constant.str " + Pushes a N-byte immediate onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + num_bytes : + The number of immediate bytes to be read from the code and pushed to + the stack. + + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_VERY_LOW" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "data_to_push" , + M.call (| + M.get_field (| M.get_name (| globals, "U256" |), "from_be_bytes" |), + make_list [ + M.call (| + M.get_name (| globals, "buffer_read" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "code" |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + BinOp.add (| + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) + ], + make_dict [] + |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + M.get_name (| globals, "num_bytes" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_field (| M.get_name (| globals, "stack" |), "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.get_name (| globals, "data_to_push" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + BinOp.add (| + Constant.int 1, + M.get_name (| globals, "num_bytes" |) + |) + |) in + M.pure Constant.None_)). + +Definition dup_n : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm"; "item_number" ] |) in + let _ := Constant.str " + Duplicate the Nth stack item (from top of the stack) to the top of stack. + + Parameters + ---------- + evm : + The current EVM frame. + + item_number : + The stack item number (0-indexed from top of stack) to be duplicated + to the top of stack. + + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_VERY_LOW" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + Compare.lt (| + M.get_name (| globals, "item_number" |), + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |); + M.get_name (| globals, "StackUnderflowError" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "data_to_duplicate" , + M.get_subscript (| + M.get_field (| M.get_name (| globals, "evm" |), "stack" |), + BinOp.sub (| + BinOp.sub (| + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |), + Constant.int 1 + |), + M.get_name (| globals, "item_number" |) + |) + |) + |) in + let _ := M.call (| + M.get_field (| M.get_name (| globals, "stack" |), "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.get_name (| globals, "data_to_duplicate" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition swap_n : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm"; "item_number" ] |) in + let _ := Constant.str " + Swap the top and the `item_number` element of the stack, where + the top of the stack is position zero. + + If `item_number` is zero, this function does nothing (which should not be + possible, since there is no `SWAP0` instruction). + + Parameters + ---------- + evm : + The current EVM frame. + + item_number : + The stack item number (0-indexed from top of stack) to be swapped + with the top of stack element. + + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_VERY_LOW" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + Compare.lt (| + M.get_name (| globals, "item_number" |), + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |); + M.get_name (| globals, "StackUnderflowError" |) + ], + make_dict [] + |) in + let _ := M.assign (| + make_tuple [ M.get_subscript (| + M.get_field (| M.get_name (| globals, "evm" |), "stack" |), + UnOp.sub (| Constant.int 1 |) + |); M.get_subscript (| + M.get_field (| M.get_name (| globals, "evm" |), "stack" |), + BinOp.sub (| + UnOp.sub (| Constant.int 1 |), + M.get_name (| globals, "item_number" |) + |) + |) ], + make_tuple [ M.get_subscript (| + M.get_field (| M.get_name (| globals, "evm" |), "stack" |), + BinOp.sub (| + UnOp.sub (| Constant.int 1 |), + M.get_name (| globals, "item_number" |) + |) + |); M.get_subscript (| + M.get_field (| M.get_name (| globals, "evm" |), "stack" |), + UnOp.sub (| Constant.int 1 |) + |) ] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition push1 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push2 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push3 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push4 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push5 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push6 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push7 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push8 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push9 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push10 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push11 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push12 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push13 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push14 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push15 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push16 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push17 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push18 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push19 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push20 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push21 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push22 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push23 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push24 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push25 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push26 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push27 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push28 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push29 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push30 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push31 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push32 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "push_n" |) + ], + make_dict [] + |) +)). + +Definition dup1 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "dup_n" |) + ], + make_dict [] + |) +)). + +Definition dup2 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "dup_n" |) + ], + make_dict [] + |) +)). + +Definition dup3 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "dup_n" |) + ], + make_dict [] + |) +)). + +Definition dup4 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "dup_n" |) + ], + make_dict [] + |) +)). + +Definition dup5 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "dup_n" |) + ], + make_dict [] + |) +)). + +Definition dup6 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "dup_n" |) + ], + make_dict [] + |) +)). + +Definition dup7 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "dup_n" |) + ], + make_dict [] + |) +)). + +Definition dup8 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "dup_n" |) + ], + make_dict [] + |) +)). + +Definition dup9 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "dup_n" |) + ], + make_dict [] + |) +)). + +Definition dup10 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "dup_n" |) + ], + make_dict [] + |) +)). + +Definition dup11 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "dup_n" |) + ], + make_dict [] + |) +)). + +Definition dup12 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "dup_n" |) + ], + make_dict [] + |) +)). + +Definition dup13 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "dup_n" |) + ], + make_dict [] + |) +)). + +Definition dup14 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "dup_n" |) + ], + make_dict [] + |) +)). + +Definition dup15 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "dup_n" |) + ], + make_dict [] + |) +)). + +Definition dup16 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "dup_n" |) + ], + make_dict [] + |) +)). + +Definition swap1 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "swap_n" |) + ], + make_dict [] + |) +)). + +Definition swap2 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "swap_n" |) + ], + make_dict [] + |) +)). + +Definition swap3 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "swap_n" |) + ], + make_dict [] + |) +)). + +Definition swap4 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "swap_n" |) + ], + make_dict [] + |) +)). + +Definition swap5 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "swap_n" |) + ], + make_dict [] + |) +)). + +Definition swap6 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "swap_n" |) + ], + make_dict [] + |) +)). + +Definition swap7 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "swap_n" |) + ], + make_dict [] + |) +)). + +Definition swap8 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "swap_n" |) + ], + make_dict [] + |) +)). + +Definition swap9 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "swap_n" |) + ], + make_dict [] + |) +)). + +Definition swap10 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "swap_n" |) + ], + make_dict [] + |) +)). + +Definition swap11 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "swap_n" |) + ], + make_dict [] + |) +)). + +Definition swap12 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "swap_n" |) + ], + make_dict [] + |) +)). + +Definition swap13 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "swap_n" |) + ], + make_dict [] + |) +)). + +Definition swap14 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "swap_n" |) + ], + make_dict [] + |) +)). + +Definition swap15 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "swap_n" |) + ], + make_dict [] + |) +)). + +Definition swap16 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "swap_n" |) + ], + make_dict [] + |) +)). diff --git a/CoqOfPython/ethereum/arrow_glacier/vm/instructions/storage.v b/CoqOfPython/ethereum/arrow_glacier/vm/instructions/storage.v new file mode 100644 index 0000000..b104e43 --- /dev/null +++ b/CoqOfPython/ethereum/arrow_glacier/vm/instructions/storage.v @@ -0,0 +1,491 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.arrow_glacier.vm.instructions.storage". + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) Storage Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM storage related instructions. +". + +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". + +Axiom ethereum_utils_ensure_imports_ensure : + IsImported globals "ethereum.utils.ensure" "ensure". + +Axiom ethereum_arrow_glacier_state_imports_get_storage : + IsImported globals "ethereum.arrow_glacier.state" "get_storage". +Axiom ethereum_arrow_glacier_state_imports_get_storage_original : + IsImported globals "ethereum.arrow_glacier.state" "get_storage_original". +Axiom ethereum_arrow_glacier_state_imports_set_storage : + IsImported globals "ethereum.arrow_glacier.state" "set_storage". + +Axiom ethereum_arrow_glacier_vm_imports_Evm : + IsImported globals "ethereum.arrow_glacier.vm" "Evm". + +Axiom ethereum_arrow_glacier_vm_exceptions_imports_OutOfGasError : + IsImported globals "ethereum.arrow_glacier.vm.exceptions" "OutOfGasError". +Axiom ethereum_arrow_glacier_vm_exceptions_imports_WriteInStaticContext : + IsImported globals "ethereum.arrow_glacier.vm.exceptions" "WriteInStaticContext". + +Axiom ethereum_arrow_glacier_vm_gas_imports_GAS_CALL_STIPEND : + IsImported globals "ethereum.arrow_glacier.vm.gas" "GAS_CALL_STIPEND". +Axiom ethereum_arrow_glacier_vm_gas_imports_GAS_COLD_SLOAD : + IsImported globals "ethereum.arrow_glacier.vm.gas" "GAS_COLD_SLOAD". +Axiom ethereum_arrow_glacier_vm_gas_imports_GAS_STORAGE_CLEAR_REFUND : + IsImported globals "ethereum.arrow_glacier.vm.gas" "GAS_STORAGE_CLEAR_REFUND". +Axiom ethereum_arrow_glacier_vm_gas_imports_GAS_STORAGE_SET : + IsImported globals "ethereum.arrow_glacier.vm.gas" "GAS_STORAGE_SET". +Axiom ethereum_arrow_glacier_vm_gas_imports_GAS_STORAGE_UPDATE : + IsImported globals "ethereum.arrow_glacier.vm.gas" "GAS_STORAGE_UPDATE". +Axiom ethereum_arrow_glacier_vm_gas_imports_GAS_WARM_ACCESS : + IsImported globals "ethereum.arrow_glacier.vm.gas" "GAS_WARM_ACCESS". +Axiom ethereum_arrow_glacier_vm_gas_imports_charge_gas : + IsImported globals "ethereum.arrow_glacier.vm.gas" "charge_gas". + +Axiom ethereum_arrow_glacier_vm_stack_imports_pop : + IsImported globals "ethereum.arrow_glacier.vm.stack" "pop". +Axiom ethereum_arrow_glacier_vm_stack_imports_push : + IsImported globals "ethereum.arrow_glacier.vm.stack" "push". + +Definition sload : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Loads to the stack, the value corresponding to a certain key from the + storage of the current account. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "key" , + M.call (| + M.get_field (| M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |), "to_be_bytes32" |), + make_list [], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.in_ (| + make_tuple [ M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "current_target" |); M.get_name (| globals, "key" |) ], + M.get_field (| M.get_name (| globals, "evm" |), "accessed_storage_keys" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_WARM_ACCESS" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "accessed_storage_keys" |), "add" |), + make_list [ + make_tuple [ M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "current_target" |); M.get_name (| globals, "key" |) ] + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_COLD_SLOAD" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "value" , + M.call (| + M.get_name (| globals, "get_storage" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "env" |), "state" |); + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "current_target" |); + M.get_name (| globals, "key" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.get_name (| globals, "value" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition sstore : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Stores a value at a certain key in the current context's storage. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "key" , + M.call (| + M.get_field (| M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |), "to_be_bytes32" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "new_value" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + Compare.gt (| + M.get_field (| M.get_name (| globals, "evm" |), "gas_left" |), + M.get_name (| globals, "GAS_CALL_STIPEND" |) + |); + M.get_name (| globals, "OutOfGasError" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "original_value" , + M.call (| + M.get_name (| globals, "get_storage_original" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "env" |), "state" |); + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "current_target" |); + M.get_name (| globals, "key" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "current_value" , + M.call (| + M.get_name (| globals, "get_storage" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "env" |), "state" |); + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "current_target" |); + M.get_name (| globals, "key" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "gas_cost" , + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.not_in (| + make_tuple [ M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "current_target" |); M.get_name (| globals, "key" |) ], + M.get_field (| M.get_name (| globals, "evm" |), "accessed_storage_keys" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "accessed_storage_keys" |), "add" |), + make_list [ + make_tuple [ M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "current_target" |); M.get_name (| globals, "key" |) ] + ], + make_dict [] + |) in + let _ := M.assign_op_local (| + BinOp.add, + "gas_cost", + M.get_name (| globals, "GAS_COLD_SLOAD" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + BoolOp.and (| + Compare.eq (| + M.get_name (| globals, "original_value" |), + M.get_name (| globals, "current_value" |) + |), + ltac:(M.monadic ( + Compare.not_eq (| + M.get_name (| globals, "current_value" |), + M.get_name (| globals, "new_value" |) + |) + )) + |), + (* then *) + ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, "original_value" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_op_local (| + BinOp.add, + "gas_cost", + M.get_name (| globals, "GAS_STORAGE_SET" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_op_local (| + BinOp.add, + "gas_cost", + BinOp.sub (| + M.get_name (| globals, "GAS_STORAGE_UPDATE" |), + M.get_name (| globals, "GAS_COLD_SLOAD" |) + |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_op_local (| + BinOp.add, + "gas_cost", + M.get_name (| globals, "GAS_WARM_ACCESS" |) + |) in + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + Compare.not_eq (| + M.get_name (| globals, "current_value" |), + M.get_name (| globals, "new_value" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + BoolOp.and (| + Compare.not_eq (| + M.get_name (| globals, "original_value" |), + Constant.int 0 + |), + ltac:(M.monadic ( + BoolOp.and (| + Compare.not_eq (| + M.get_name (| globals, "current_value" |), + Constant.int 0 + |), + ltac:(M.monadic ( + Compare.eq (| + M.get_name (| globals, "new_value" |), + Constant.int 0 + |) + )) + |) + )) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "refund_counter" |), + M.call (| + M.get_name (| globals, "int" |), + make_list [ + M.get_name (| globals, "GAS_STORAGE_CLEAR_REFUND" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + BoolOp.and (| + Compare.not_eq (| + M.get_name (| globals, "original_value" |), + Constant.int 0 + |), + ltac:(M.monadic ( + Compare.eq (| + M.get_name (| globals, "current_value" |), + Constant.int 0 + |) + )) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_op (| + BinOp.sub, + M.get_field (| M.get_name (| globals, "evm" |), "refund_counter" |), + M.call (| + M.get_name (| globals, "int" |), + make_list [ + M.get_name (| globals, "GAS_STORAGE_CLEAR_REFUND" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, "original_value" |), + M.get_name (| globals, "new_value" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, "original_value" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "refund_counter" |), + M.call (| + M.get_name (| globals, "int" |), + make_list [ + BinOp.sub (| + M.get_name (| globals, "GAS_STORAGE_SET" |), + M.get_name (| globals, "GAS_WARM_ACCESS" |) + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "refund_counter" |), + M.call (| + M.get_name (| globals, "int" |), + make_list [ + BinOp.sub (| + BinOp.sub (| + M.get_name (| globals, "GAS_STORAGE_UPDATE" |), + M.get_name (| globals, "GAS_COLD_SLOAD" |) + |), + M.get_name (| globals, "GAS_WARM_ACCESS" |) + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "gas_cost" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + UnOp.not (| M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "is_static" |) |); + M.get_name (| globals, "WriteInStaticContext" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "set_storage" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "env" |), "state" |); + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "current_target" |); + M.get_name (| globals, "key" |); + M.get_name (| globals, "new_value" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). diff --git a/CoqOfPython/ethereum/arrow_glacier/vm/instructions/system.v b/CoqOfPython/ethereum/arrow_glacier/vm/instructions/system.v new file mode 100644 index 0000000..315f8d0 --- /dev/null +++ b/CoqOfPython/ethereum/arrow_glacier/vm/instructions/system.v @@ -0,0 +1,2215 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.arrow_glacier.vm.instructions.system". + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) System Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM system related instructions. +". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_Bytes0 : + IsImported globals "ethereum.base_types" "Bytes0". +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". + +Axiom ethereum_utils_ensure_imports_ensure : + IsImported globals "ethereum.utils.ensure" "ensure". + +Axiom ethereum_utils_numeric_imports_ceil32 : + IsImported globals "ethereum.utils.numeric" "ceil32". + +Axiom ethereum_arrow_glacier_fork_types_imports_Address : + IsImported globals "ethereum.arrow_glacier.fork_types" "Address". + +Axiom ethereum_arrow_glacier_state_imports_account_exists_and_is_empty : + IsImported globals "ethereum.arrow_glacier.state" "account_exists_and_is_empty". +Axiom ethereum_arrow_glacier_state_imports_account_has_code_or_nonce : + IsImported globals "ethereum.arrow_glacier.state" "account_has_code_or_nonce". +Axiom ethereum_arrow_glacier_state_imports_get_account : + IsImported globals "ethereum.arrow_glacier.state" "get_account". +Axiom ethereum_arrow_glacier_state_imports_increment_nonce : + IsImported globals "ethereum.arrow_glacier.state" "increment_nonce". +Axiom ethereum_arrow_glacier_state_imports_is_account_alive : + IsImported globals "ethereum.arrow_glacier.state" "is_account_alive". +Axiom ethereum_arrow_glacier_state_imports_set_account_balance : + IsImported globals "ethereum.arrow_glacier.state" "set_account_balance". + +Axiom ethereum_arrow_glacier_utils_address_imports_compute_contract_address : + IsImported globals "ethereum.arrow_glacier.utils.address" "compute_contract_address". +Axiom ethereum_arrow_glacier_utils_address_imports_compute_create2_contract_address : + IsImported globals "ethereum.arrow_glacier.utils.address" "compute_create2_contract_address". +Axiom ethereum_arrow_glacier_utils_address_imports_to_address : + IsImported globals "ethereum.arrow_glacier.utils.address" "to_address". + +Axiom ethereum_arrow_glacier_vm_imports_Evm : + IsImported globals "ethereum.arrow_glacier.vm" "Evm". +Axiom ethereum_arrow_glacier_vm_imports_Message : + IsImported globals "ethereum.arrow_glacier.vm" "Message". +Axiom ethereum_arrow_glacier_vm_imports_incorporate_child_on_error : + IsImported globals "ethereum.arrow_glacier.vm" "incorporate_child_on_error". +Axiom ethereum_arrow_glacier_vm_imports_incorporate_child_on_success : + IsImported globals "ethereum.arrow_glacier.vm" "incorporate_child_on_success". + +Axiom ethereum_arrow_glacier_vm_exceptions_imports_Revert : + IsImported globals "ethereum.arrow_glacier.vm.exceptions" "Revert". +Axiom ethereum_arrow_glacier_vm_exceptions_imports_WriteInStaticContext : + IsImported globals "ethereum.arrow_glacier.vm.exceptions" "WriteInStaticContext". + +Axiom ethereum_arrow_glacier_vm_gas_imports_GAS_CALL_VALUE : + IsImported globals "ethereum.arrow_glacier.vm.gas" "GAS_CALL_VALUE". +Axiom ethereum_arrow_glacier_vm_gas_imports_GAS_COLD_ACCOUNT_ACCESS : + IsImported globals "ethereum.arrow_glacier.vm.gas" "GAS_COLD_ACCOUNT_ACCESS". +Axiom ethereum_arrow_glacier_vm_gas_imports_GAS_CREATE : + IsImported globals "ethereum.arrow_glacier.vm.gas" "GAS_CREATE". +Axiom ethereum_arrow_glacier_vm_gas_imports_GAS_KECCAK256_WORD : + IsImported globals "ethereum.arrow_glacier.vm.gas" "GAS_KECCAK256_WORD". +Axiom ethereum_arrow_glacier_vm_gas_imports_GAS_NEW_ACCOUNT : + IsImported globals "ethereum.arrow_glacier.vm.gas" "GAS_NEW_ACCOUNT". +Axiom ethereum_arrow_glacier_vm_gas_imports_GAS_SELF_DESTRUCT : + IsImported globals "ethereum.arrow_glacier.vm.gas" "GAS_SELF_DESTRUCT". +Axiom ethereum_arrow_glacier_vm_gas_imports_GAS_SELF_DESTRUCT_NEW_ACCOUNT : + IsImported globals "ethereum.arrow_glacier.vm.gas" "GAS_SELF_DESTRUCT_NEW_ACCOUNT". +Axiom ethereum_arrow_glacier_vm_gas_imports_GAS_WARM_ACCESS : + IsImported globals "ethereum.arrow_glacier.vm.gas" "GAS_WARM_ACCESS". +Axiom ethereum_arrow_glacier_vm_gas_imports_GAS_ZERO : + IsImported globals "ethereum.arrow_glacier.vm.gas" "GAS_ZERO". +Axiom ethereum_arrow_glacier_vm_gas_imports_calculate_gas_extend_memory : + IsImported globals "ethereum.arrow_glacier.vm.gas" "calculate_gas_extend_memory". +Axiom ethereum_arrow_glacier_vm_gas_imports_calculate_message_call_gas : + IsImported globals "ethereum.arrow_glacier.vm.gas" "calculate_message_call_gas". +Axiom ethereum_arrow_glacier_vm_gas_imports_charge_gas : + IsImported globals "ethereum.arrow_glacier.vm.gas" "charge_gas". +Axiom ethereum_arrow_glacier_vm_gas_imports_max_message_call_gas : + IsImported globals "ethereum.arrow_glacier.vm.gas" "max_message_call_gas". + +Axiom ethereum_arrow_glacier_vm_memory_imports_memory_read_bytes : + IsImported globals "ethereum.arrow_glacier.vm.memory" "memory_read_bytes". +Axiom ethereum_arrow_glacier_vm_memory_imports_memory_write : + IsImported globals "ethereum.arrow_glacier.vm.memory" "memory_write". + +Axiom ethereum_arrow_glacier_vm_stack_imports_pop : + IsImported globals "ethereum.arrow_glacier.vm.stack" "pop". +Axiom ethereum_arrow_glacier_vm_stack_imports_push : + IsImported globals "ethereum.arrow_glacier.vm.stack" "push". + +Definition generic_create : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm"; "endowment"; "contract_address"; "memory_start_position"; "memory_size" ] |) in + let _ := Constant.str " + Core logic used by the `CREATE*` family of opcodes. + " in +(* At stmt: unsupported node type: ImportFrom *) + let _ := M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "accessed_addresses" |), "add" |), + make_list [ + M.get_name (| globals, "contract_address" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "create_message_gas" , + M.call (| + M.get_name (| globals, "max_message_call_gas" |), + make_list [ + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "gas_left" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_op (| + BinOp.sub, + M.get_field (| M.get_name (| globals, "evm" |), "gas_left" |), + M.get_name (| globals, "create_message_gas" |) + |) in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + UnOp.not (| M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "is_static" |) |); + M.get_name (| globals, "WriteInStaticContext" |) + ], + make_dict [] + |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, "evm" |), "return_data" |), + Constant.bytes "" + |) in + let _ := M.assign_local (| + "sender_address" , + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "current_target" |) + |) in + let _ := M.assign_local (| + "sender" , + M.call (| + M.get_name (| globals, "get_account" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "env" |), "state" |); + M.get_name (| globals, "sender_address" |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + BoolOp.or (| + Compare.lt (| + M.get_field (| M.get_name (| globals, "sender" |), "balance" |), + M.get_name (| globals, "endowment" |) + |), + ltac:(M.monadic ( + BoolOp.or (| + Compare.eq (| + M.get_field (| M.get_name (| globals, "sender" |), "nonce" |), + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + BinOp.sub (| + BinOp.pow (| + Constant.int 2, + Constant.int 64 + |), + Constant.int 1 + |) + ], + make_dict [] + |) + |), + ltac:(M.monadic ( + Compare.gt (| + BinOp.add (| + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "depth" |), + Constant.int 1 + |), + M.get_name (| globals, "STACK_DEPTH_LIMIT" |) + |) + )) + |) + )) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "gas_left" |), + M.get_name (| globals, "create_message_gas" |) + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.return_ (| + Constant.None_ + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, "account_has_code_or_nonce" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "env" |), "state" |); + M.get_name (| globals, "contract_address" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, "increment_nonce" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "env" |), "state" |); + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "current_target" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.return_ (| + Constant.None_ + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "call_data" , + M.call (| + M.get_name (| globals, "memory_read_bytes" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "memory" |); + M.get_name (| globals, "memory_start_position" |); + M.get_name (| globals, "memory_size" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "increment_nonce" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "env" |), "state" |); + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "current_target" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "child_message" , + M.call (| + M.get_name (| globals, "Message" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "child_evm" , + M.call (| + M.get_name (| globals, "process_create_message" |), + make_list [ + M.get_name (| globals, "child_message" |); + M.get_field (| M.get_name (| globals, "evm" |), "env" |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + M.get_field (| M.get_name (| globals, "child_evm" |), "error" |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, "incorporate_child_on_error" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "child_evm" |) + ], + make_dict [] + |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, "evm" |), "return_data" |), + M.get_field (| M.get_name (| globals, "child_evm" |), "output" |) + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + ], + make_dict [] + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, "incorporate_child_on_success" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "child_evm" |) + ], + make_dict [] + |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, "evm" |), "return_data" |), + Constant.bytes "" + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.call (| + M.get_field (| M.get_name (| globals, "U256" |), "from_be_bytes" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "child_evm" |), "message" |), "current_target" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_)). + +Definition create : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Creates a new account with associated code. + + Parameters + ---------- + evm : + The current EVM frame. + " in + let _ := M.assign_local (| + "endowment" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_start_position" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_size" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "extend_memory" , + M.call (| + M.get_name (| globals, "calculate_gas_extend_memory" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "memory" |); + make_list [ + make_tuple [ M.get_name (| globals, "memory_start_position" |); M.get_name (| globals, "memory_size" |) ] + ] + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + BinOp.add (| + M.get_name (| globals, "GAS_CREATE" |), + M.get_field (| M.get_name (| globals, "extend_memory" |), "cost" |) + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "memory" |), + BinOp.mult (| + Constant.bytes "00", + M.get_field (| M.get_name (| globals, "extend_memory" |), "expand_by" |) + |) + |) in + let _ := M.assign_local (| + "contract_address" , + M.call (| + M.get_name (| globals, "compute_contract_address" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "current_target" |); + M.get_field (| M.call (| + M.get_name (| globals, "get_account" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "env" |), "state" |); + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "current_target" |) + ], + make_dict [] + |), "nonce" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "generic_create" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "endowment" |); + M.get_name (| globals, "contract_address" |); + M.get_name (| globals, "memory_start_position" |); + M.get_name (| globals, "memory_size" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition create2 : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Creates a new account with associated code. + + It's similar to CREATE opcode except that the address of new account + depends on the init_code instead of the nonce of sender. + + Parameters + ---------- + evm : + The current EVM frame. + " in + let _ := M.assign_local (| + "endowment" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_start_position" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_size" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "salt" , + M.call (| + M.get_field (| M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |), "to_be_bytes32" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "extend_memory" , + M.call (| + M.get_name (| globals, "calculate_gas_extend_memory" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "memory" |); + make_list [ + make_tuple [ M.get_name (| globals, "memory_start_position" |); M.get_name (| globals, "memory_size" |) ] + ] + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "call_data_words" , + BinOp.floor_div (| + M.call (| + M.get_name (| globals, "ceil32" |), + make_list [ + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.get_name (| globals, "memory_size" |) + ], + make_dict [] + |) + ], + make_dict [] + |), + Constant.int 32 + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + BinOp.add (| + BinOp.add (| + M.get_name (| globals, "GAS_CREATE" |), + BinOp.mult (| + M.get_name (| globals, "GAS_KECCAK256_WORD" |), + M.get_name (| globals, "call_data_words" |) + |) + |), + M.get_field (| M.get_name (| globals, "extend_memory" |), "cost" |) + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "memory" |), + BinOp.mult (| + Constant.bytes "00", + M.get_field (| M.get_name (| globals, "extend_memory" |), "expand_by" |) + |) + |) in + let _ := M.assign_local (| + "contract_address" , + M.call (| + M.get_name (| globals, "compute_create2_contract_address" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "current_target" |); + M.get_name (| globals, "salt" |); + M.call (| + M.get_name (| globals, "memory_read_bytes" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "memory" |); + M.get_name (| globals, "memory_start_position" |); + M.get_name (| globals, "memory_size" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "generic_create" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "endowment" |); + M.get_name (| globals, "contract_address" |); + M.get_name (| globals, "memory_start_position" |); + M.get_name (| globals, "memory_size" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition return_ : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Halts execution returning output data. + + Parameters + ---------- + evm : + The current EVM frame. + " in + let _ := M.assign_local (| + "memory_start_position" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_size" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "extend_memory" , + M.call (| + M.get_name (| globals, "calculate_gas_extend_memory" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "memory" |); + make_list [ + make_tuple [ M.get_name (| globals, "memory_start_position" |); M.get_name (| globals, "memory_size" |) ] + ] + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + BinOp.add (| + M.get_name (| globals, "GAS_ZERO" |), + M.get_field (| M.get_name (| globals, "extend_memory" |), "cost" |) + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "memory" |), + BinOp.mult (| + Constant.bytes "00", + M.get_field (| M.get_name (| globals, "extend_memory" |), "expand_by" |) + |) + |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, "evm" |), "output" |), + M.call (| + M.get_name (| globals, "memory_read_bytes" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "memory" |); + M.get_name (| globals, "memory_start_position" |); + M.get_name (| globals, "memory_size" |) + ], + make_dict [] + |) + |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, "evm" |), "running" |), + Constant.bool false + |) in + let _ := M.pass (| |) in + M.pure Constant.None_)). + +Definition generic_call : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm"; "gas"; "value"; "caller"; "to"; "code_address"; "should_transfer_value"; "is_staticcall"; "memory_input_start_position"; "memory_input_size"; "memory_output_start_position"; "memory_output_size" ] |) in + let _ := Constant.str " + Perform the core logic of the `CALL*` family of opcodes. + " in +(* At stmt: unsupported node type: ImportFrom *) + let _ := M.assign (| + M.get_field (| M.get_name (| globals, "evm" |), "return_data" |), + Constant.bytes "" + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.gt (| + BinOp.add (| + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "depth" |), + Constant.int 1 + |), + M.get_name (| globals, "STACK_DEPTH_LIMIT" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "gas_left" |), + M.get_name (| globals, "gas" |) + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.return_ (| + Constant.None_ + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "call_data" , + M.call (| + M.get_name (| globals, "memory_read_bytes" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "memory" |); + M.get_name (| globals, "memory_input_start_position" |); + M.get_name (| globals, "memory_input_size" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "code" , + M.get_field (| M.call (| + M.get_name (| globals, "get_account" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "env" |), "state" |); + M.get_name (| globals, "code_address" |) + ], + make_dict [] + |), "code" |) + |) in + let _ := M.assign_local (| + "child_message" , + M.call (| + M.get_name (| globals, "Message" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "child_evm" , + M.call (| + M.get_name (| globals, "process_message" |), + make_list [ + M.get_name (| globals, "child_message" |); + M.get_field (| M.get_name (| globals, "evm" |), "env" |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + M.get_field (| M.get_name (| globals, "child_evm" |), "error" |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, "incorporate_child_on_error" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "child_evm" |) + ], + make_dict [] + |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, "evm" |), "return_data" |), + M.get_field (| M.get_name (| globals, "child_evm" |), "output" |) + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + ], + make_dict [] + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, "incorporate_child_on_success" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "child_evm" |) + ], + make_dict [] + |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, "evm" |), "return_data" |), + M.get_field (| M.get_name (| globals, "child_evm" |), "output" |) + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 1 + ], + make_dict [] + |) + ], + make_dict [] + |) in + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "actual_output_size" , + M.call (| + M.get_name (| globals, "min" |), + make_list [ + M.get_name (| globals, "memory_output_size" |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_field (| M.get_name (| globals, "child_evm" |), "output" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "memory_write" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "memory" |); + M.get_name (| globals, "memory_output_start_position" |); + M.slice (| + M.get_field (| M.get_name (| globals, "child_evm" |), "output" |), + Constant.None_, + M.get_name (| globals, "actual_output_size" |), + Constant.None_ + |) + ], + make_dict [] + |) in + M.pure Constant.None_)). + +Definition call : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Message-call into an account. + + Parameters + ---------- + evm : + The current EVM frame. + " in + let _ := M.assign_local (| + "gas" , + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "to" , + M.call (| + M.get_name (| globals, "to_address" |), + make_list [ + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "value" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_input_start_position" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_input_size" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_output_start_position" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_output_size" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "extend_memory" , + M.call (| + M.get_name (| globals, "calculate_gas_extend_memory" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "memory" |); + make_list [ + make_tuple [ M.get_name (| globals, "memory_input_start_position" |); M.get_name (| globals, "memory_input_size" |) ]; + make_tuple [ M.get_name (| globals, "memory_output_start_position" |); M.get_name (| globals, "memory_output_size" |) ] + ] + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.in_ (| + M.get_name (| globals, "to" |), + M.get_field (| M.get_name (| globals, "evm" |), "accessed_addresses" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "access_gas_cost" , + M.get_name (| globals, "GAS_WARM_ACCESS" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "accessed_addresses" |), "add" |), + make_list [ + M.get_name (| globals, "to" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "access_gas_cost" , + M.get_name (| globals, "GAS_COLD_ACCOUNT_ACCESS" |) + |) in + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "create_gas_cost" , + (* if *) + M.if_then_else (| + BoolOp.or (| + M.call (| + M.get_name (| globals, "is_account_alive" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "env" |), "state" |); + M.get_name (| globals, "to" |) + ], + make_dict [] + |), + ltac:(M.monadic ( + Compare.eq (| + M.get_name (| globals, "value" |), + Constant.int 0 + |) + )) + |), + (* then *) + ltac:(M.monadic ( +M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + (* else *) + )), ltac:(M.monadic ( +M.get_name (| globals, "GAS_NEW_ACCOUNT" |) + )) |) + |) in + let _ := M.assign_local (| + "transfer_gas_cost" , + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, "value" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( +M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + (* else *) + )), ltac:(M.monadic ( +M.get_name (| globals, "GAS_CALL_VALUE" |) + )) |) + |) in + let _ := M.assign_local (| + "message_call_gas" , + M.call (| + M.get_name (| globals, "calculate_message_call_gas" |), + make_list [ + M.get_name (| globals, "value" |); + M.get_name (| globals, "gas" |); + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "gas_left" |) + ], + make_dict [] + |); + M.get_field (| M.get_name (| globals, "extend_memory" |), "cost" |); + BinOp.add (| + BinOp.add (| + M.get_name (| globals, "access_gas_cost" |), + M.get_name (| globals, "create_gas_cost" |) + |), + M.get_name (| globals, "transfer_gas_cost" |) + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + BinOp.add (| + M.get_field (| M.get_name (| globals, "message_call_gas" |), "cost" |), + M.get_field (| M.get_name (| globals, "extend_memory" |), "cost" |) + |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + BoolOp.or (| + UnOp.not (| M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "is_static" |) |), + ltac:(M.monadic ( + Compare.eq (| + M.get_name (| globals, "value" |), + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + |) + )) + |); + M.get_name (| globals, "WriteInStaticContext" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "memory" |), + BinOp.mult (| + Constant.bytes "00", + M.get_field (| M.get_name (| globals, "extend_memory" |), "expand_by" |) + |) + |) in + let _ := M.assign_local (| + "sender_balance" , + M.get_field (| M.call (| + M.get_name (| globals, "get_account" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "env" |), "state" |); + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "current_target" |) + ], + make_dict [] + |), "balance" |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.lt (| + M.get_name (| globals, "sender_balance" |), + M.get_name (| globals, "value" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, "evm" |), "return_data" |), + Constant.bytes "" + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "gas_left" |), + M.get_field (| M.get_name (| globals, "message_call_gas" |), "stipend" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, "generic_call" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_field (| M.get_name (| globals, "message_call_gas" |), "stipend" |); + M.get_name (| globals, "value" |); + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "current_target" |); + M.get_name (| globals, "to" |); + M.get_name (| globals, "to" |); + Constant.bool true; + Constant.bool false; + M.get_name (| globals, "memory_input_start_position" |); + M.get_name (| globals, "memory_input_size" |); + M.get_name (| globals, "memory_output_start_position" |); + M.get_name (| globals, "memory_output_size" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + )) |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition callcode : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Message-call into this account with alternative account’s code. + + Parameters + ---------- + evm : + The current EVM frame. + " in + let _ := M.assign_local (| + "gas" , + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "code_address" , + M.call (| + M.get_name (| globals, "to_address" |), + make_list [ + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "value" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_input_start_position" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_input_size" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_output_start_position" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_output_size" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "to" , + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "current_target" |) + |) in + let _ := M.assign_local (| + "extend_memory" , + M.call (| + M.get_name (| globals, "calculate_gas_extend_memory" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "memory" |); + make_list [ + make_tuple [ M.get_name (| globals, "memory_input_start_position" |); M.get_name (| globals, "memory_input_size" |) ]; + make_tuple [ M.get_name (| globals, "memory_output_start_position" |); M.get_name (| globals, "memory_output_size" |) ] + ] + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.in_ (| + M.get_name (| globals, "code_address" |), + M.get_field (| M.get_name (| globals, "evm" |), "accessed_addresses" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "access_gas_cost" , + M.get_name (| globals, "GAS_WARM_ACCESS" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "accessed_addresses" |), "add" |), + make_list [ + M.get_name (| globals, "code_address" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "access_gas_cost" , + M.get_name (| globals, "GAS_COLD_ACCOUNT_ACCESS" |) + |) in + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "transfer_gas_cost" , + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, "value" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( +M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + (* else *) + )), ltac:(M.monadic ( +M.get_name (| globals, "GAS_CALL_VALUE" |) + )) |) + |) in + let _ := M.assign_local (| + "message_call_gas" , + M.call (| + M.get_name (| globals, "calculate_message_call_gas" |), + make_list [ + M.get_name (| globals, "value" |); + M.get_name (| globals, "gas" |); + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "gas_left" |) + ], + make_dict [] + |); + M.get_field (| M.get_name (| globals, "extend_memory" |), "cost" |); + BinOp.add (| + M.get_name (| globals, "access_gas_cost" |), + M.get_name (| globals, "transfer_gas_cost" |) + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + BinOp.add (| + M.get_field (| M.get_name (| globals, "message_call_gas" |), "cost" |), + M.get_field (| M.get_name (| globals, "extend_memory" |), "cost" |) + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "memory" |), + BinOp.mult (| + Constant.bytes "00", + M.get_field (| M.get_name (| globals, "extend_memory" |), "expand_by" |) + |) + |) in + let _ := M.assign_local (| + "sender_balance" , + M.get_field (| M.call (| + M.get_name (| globals, "get_account" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "env" |), "state" |); + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "current_target" |) + ], + make_dict [] + |), "balance" |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.lt (| + M.get_name (| globals, "sender_balance" |), + M.get_name (| globals, "value" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, "evm" |), "return_data" |), + Constant.bytes "" + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "gas_left" |), + M.get_field (| M.get_name (| globals, "message_call_gas" |), "stipend" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, "generic_call" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_field (| M.get_name (| globals, "message_call_gas" |), "stipend" |); + M.get_name (| globals, "value" |); + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "current_target" |); + M.get_name (| globals, "to" |); + M.get_name (| globals, "code_address" |); + Constant.bool true; + Constant.bool false; + M.get_name (| globals, "memory_input_start_position" |); + M.get_name (| globals, "memory_input_size" |); + M.get_name (| globals, "memory_output_start_position" |); + M.get_name (| globals, "memory_output_size" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + )) |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition selfdestruct : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Halt execution and register account for later deletion. + + Parameters + ---------- + evm : + The current EVM frame. + " in + let _ := M.assign_local (| + "beneficiary" , + M.call (| + M.get_name (| globals, "to_address" |), + make_list [ + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "gas_cost" , + M.get_name (| globals, "GAS_SELF_DESTRUCT" |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.not_in (| + M.get_name (| globals, "beneficiary" |), + M.get_field (| M.get_name (| globals, "evm" |), "accessed_addresses" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "accessed_addresses" |), "add" |), + make_list [ + M.get_name (| globals, "beneficiary" |) + ], + make_dict [] + |) in + let _ := M.assign_op_local (| + BinOp.add, + "gas_cost", + M.get_name (| globals, "GAS_COLD_ACCOUNT_ACCESS" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + BoolOp.and (| + UnOp.not (| M.call (| + M.get_name (| globals, "is_account_alive" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "env" |), "state" |); + M.get_name (| globals, "beneficiary" |) + ], + make_dict [] + |) |), + ltac:(M.monadic ( + Compare.not_eq (| + M.get_field (| M.call (| + M.get_name (| globals, "get_account" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "env" |), "state" |); + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "current_target" |) + ], + make_dict [] + |), "balance" |), + Constant.int 0 + |) + )) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_op_local (| + BinOp.add, + "gas_cost", + M.get_name (| globals, "GAS_SELF_DESTRUCT_NEW_ACCOUNT" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "gas_cost" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + UnOp.not (| M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "is_static" |) |); + M.get_name (| globals, "WriteInStaticContext" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "originator" , + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "current_target" |) + |) in + let _ := M.assign_local (| + "beneficiary_balance" , + M.get_field (| M.call (| + M.get_name (| globals, "get_account" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "env" |), "state" |); + M.get_name (| globals, "beneficiary" |) + ], + make_dict [] + |), "balance" |) + |) in + let _ := M.assign_local (| + "originator_balance" , + M.get_field (| M.call (| + M.get_name (| globals, "get_account" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "env" |), "state" |); + M.get_name (| globals, "originator" |) + ], + make_dict [] + |), "balance" |) + |) in + let _ := M.call (| + M.get_name (| globals, "set_account_balance" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "env" |), "state" |); + M.get_name (| globals, "beneficiary" |); + BinOp.add (| + M.get_name (| globals, "beneficiary_balance" |), + M.get_name (| globals, "originator_balance" |) + |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "set_account_balance" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "env" |), "state" |); + M.get_name (| globals, "originator" |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "accounts_to_delete" |), "add" |), + make_list [ + M.get_name (| globals, "originator" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, "account_exists_and_is_empty" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "env" |), "state" |); + M.get_name (| globals, "beneficiary" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "touched_accounts" |), "add" |), + make_list [ + M.get_name (| globals, "beneficiary" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, "evm" |), "running" |), + Constant.bool false + |) in + let _ := M.pass (| |) in + M.pure Constant.None_)). + +Definition delegatecall : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Message-call into an account. + + Parameters + ---------- + evm : + The current EVM frame. + " in + let _ := M.assign_local (| + "gas" , + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "code_address" , + M.call (| + M.get_name (| globals, "to_address" |), + make_list [ + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_input_start_position" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_input_size" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_output_start_position" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_output_size" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "extend_memory" , + M.call (| + M.get_name (| globals, "calculate_gas_extend_memory" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "memory" |); + make_list [ + make_tuple [ M.get_name (| globals, "memory_input_start_position" |); M.get_name (| globals, "memory_input_size" |) ]; + make_tuple [ M.get_name (| globals, "memory_output_start_position" |); M.get_name (| globals, "memory_output_size" |) ] + ] + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.in_ (| + M.get_name (| globals, "code_address" |), + M.get_field (| M.get_name (| globals, "evm" |), "accessed_addresses" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "access_gas_cost" , + M.get_name (| globals, "GAS_WARM_ACCESS" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "accessed_addresses" |), "add" |), + make_list [ + M.get_name (| globals, "code_address" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "access_gas_cost" , + M.get_name (| globals, "GAS_COLD_ACCOUNT_ACCESS" |) + |) in + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "message_call_gas" , + M.call (| + M.get_name (| globals, "calculate_message_call_gas" |), + make_list [ + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |); + M.get_name (| globals, "gas" |); + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "gas_left" |) + ], + make_dict [] + |); + M.get_field (| M.get_name (| globals, "extend_memory" |), "cost" |); + M.get_name (| globals, "access_gas_cost" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + BinOp.add (| + M.get_field (| M.get_name (| globals, "message_call_gas" |), "cost" |), + M.get_field (| M.get_name (| globals, "extend_memory" |), "cost" |) + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "memory" |), + BinOp.mult (| + Constant.bytes "00", + M.get_field (| M.get_name (| globals, "extend_memory" |), "expand_by" |) + |) + |) in + let _ := M.call (| + M.get_name (| globals, "generic_call" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_field (| M.get_name (| globals, "message_call_gas" |), "stipend" |); + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "value" |); + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "caller" |); + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "current_target" |); + M.get_name (| globals, "code_address" |); + Constant.bool false; + Constant.bool false; + M.get_name (| globals, "memory_input_start_position" |); + M.get_name (| globals, "memory_input_size" |); + M.get_name (| globals, "memory_output_start_position" |); + M.get_name (| globals, "memory_output_size" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition staticcall : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Message-call into an account. + + Parameters + ---------- + evm : + The current EVM frame. + " in + let _ := M.assign_local (| + "gas" , + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "to" , + M.call (| + M.get_name (| globals, "to_address" |), + make_list [ + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_input_start_position" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_input_size" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_output_start_position" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_output_size" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "extend_memory" , + M.call (| + M.get_name (| globals, "calculate_gas_extend_memory" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "memory" |); + make_list [ + make_tuple [ M.get_name (| globals, "memory_input_start_position" |); M.get_name (| globals, "memory_input_size" |) ]; + make_tuple [ M.get_name (| globals, "memory_output_start_position" |); M.get_name (| globals, "memory_output_size" |) ] + ] + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.in_ (| + M.get_name (| globals, "to" |), + M.get_field (| M.get_name (| globals, "evm" |), "accessed_addresses" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "access_gas_cost" , + M.get_name (| globals, "GAS_WARM_ACCESS" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "accessed_addresses" |), "add" |), + make_list [ + M.get_name (| globals, "to" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "access_gas_cost" , + M.get_name (| globals, "GAS_COLD_ACCOUNT_ACCESS" |) + |) in + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "message_call_gas" , + M.call (| + M.get_name (| globals, "calculate_message_call_gas" |), + make_list [ + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |); + M.get_name (| globals, "gas" |); + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "gas_left" |) + ], + make_dict [] + |); + M.get_field (| M.get_name (| globals, "extend_memory" |), "cost" |); + M.get_name (| globals, "access_gas_cost" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + BinOp.add (| + M.get_field (| M.get_name (| globals, "message_call_gas" |), "cost" |), + M.get_field (| M.get_name (| globals, "extend_memory" |), "cost" |) + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "memory" |), + BinOp.mult (| + Constant.bytes "00", + M.get_field (| M.get_name (| globals, "extend_memory" |), "expand_by" |) + |) + |) in + let _ := M.call (| + M.get_name (| globals, "generic_call" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_field (| M.get_name (| globals, "message_call_gas" |), "stipend" |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |); + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "current_target" |); + M.get_name (| globals, "to" |); + M.get_name (| globals, "to" |); + Constant.bool true; + Constant.bool true; + M.get_name (| globals, "memory_input_start_position" |); + M.get_name (| globals, "memory_input_size" |); + M.get_name (| globals, "memory_output_start_position" |); + M.get_name (| globals, "memory_output_size" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition revert : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Stop execution and revert state changes, without consuming all provided gas + and also has the ability to return a reason + Parameters + ---------- + evm : + The current EVM frame. + " in + let _ := M.assign_local (| + "memory_start_index" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "size" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "extend_memory" , + M.call (| + M.get_name (| globals, "calculate_gas_extend_memory" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "memory" |); + make_list [ + make_tuple [ M.get_name (| globals, "memory_start_index" |); M.get_name (| globals, "size" |) ] + ] + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_field (| M.get_name (| globals, "extend_memory" |), "cost" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "memory" |), + BinOp.mult (| + Constant.bytes "00", + M.get_field (| M.get_name (| globals, "extend_memory" |), "expand_by" |) + |) + |) in + let _ := M.assign_local (| + "output" , + M.call (| + M.get_name (| globals, "memory_read_bytes" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "memory" |); + M.get_name (| globals, "memory_start_index" |); + M.get_name (| globals, "size" |) + ], + make_dict [] + |) + |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, "evm" |), "output" |), + M.call (| + M.get_name (| globals, "bytes" |), + make_list [ + M.get_name (| globals, "output" |) + ], + make_dict [] + |) + |) in + let _ := M.raise (| Some (M.get_name (| globals, "Revert" |)) |) in + let _ := M.pass (| |) in + M.pure Constant.None_)). diff --git a/CoqOfPython/ethereum/arrow_glacier/vm/interpreter.v b/CoqOfPython/ethereum/arrow_glacier/vm/interpreter.v new file mode 100644 index 0000000..7958dd7 --- /dev/null +++ b/CoqOfPython/ethereum/arrow_glacier/vm/interpreter.v @@ -0,0 +1,675 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.arrow_glacier.vm.interpreter". + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) Interpreter +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +A straightforward interpreter that executes EVM code. +". + +Axiom dataclasses_imports_dataclass : + IsImported globals "dataclasses" "dataclass". + +Axiom typing_imports_Iterable : + IsImported globals "typing" "Iterable". +Axiom typing_imports_Optional : + IsImported globals "typing" "Optional". +Axiom typing_imports_Set : + IsImported globals "typing" "Set". +Axiom typing_imports_Tuple : + IsImported globals "typing" "Tuple". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_Bytes0 : + IsImported globals "ethereum.base_types" "Bytes0". +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". + +Axiom ethereum_trace_imports_EvmStop : + IsImported globals "ethereum.trace" "EvmStop". +Axiom ethereum_trace_imports_OpEnd : + IsImported globals "ethereum.trace" "OpEnd". +Axiom ethereum_trace_imports_OpException : + IsImported globals "ethereum.trace" "OpException". +Axiom ethereum_trace_imports_OpStart : + IsImported globals "ethereum.trace" "OpStart". +Axiom ethereum_trace_imports_PrecompileEnd : + IsImported globals "ethereum.trace" "PrecompileEnd". +Axiom ethereum_trace_imports_PrecompileStart : + IsImported globals "ethereum.trace" "PrecompileStart". +Axiom ethereum_trace_imports_TransactionEnd : + IsImported globals "ethereum.trace" "TransactionEnd". +Axiom ethereum_trace_imports_evm_trace : + IsImported globals "ethereum.trace" "evm_trace". + +Axiom ethereum_utils_ensure_imports_ensure : + IsImported globals "ethereum.utils.ensure" "ensure". + +Axiom ethereum_arrow_glacier_blocks_imports_Log : + IsImported globals "ethereum.arrow_glacier.blocks" "Log". + +Axiom ethereum_arrow_glacier_fork_types_imports_Address : + IsImported globals "ethereum.arrow_glacier.fork_types" "Address". + +Axiom ethereum_arrow_glacier_state_imports_account_exists_and_is_empty : + IsImported globals "ethereum.arrow_glacier.state" "account_exists_and_is_empty". +Axiom ethereum_arrow_glacier_state_imports_account_has_code_or_nonce : + IsImported globals "ethereum.arrow_glacier.state" "account_has_code_or_nonce". +Axiom ethereum_arrow_glacier_state_imports_begin_transaction : + IsImported globals "ethereum.arrow_glacier.state" "begin_transaction". +Axiom ethereum_arrow_glacier_state_imports_commit_transaction : + IsImported globals "ethereum.arrow_glacier.state" "commit_transaction". +Axiom ethereum_arrow_glacier_state_imports_destroy_storage : + IsImported globals "ethereum.arrow_glacier.state" "destroy_storage". +Axiom ethereum_arrow_glacier_state_imports_increment_nonce : + IsImported globals "ethereum.arrow_glacier.state" "increment_nonce". +Axiom ethereum_arrow_glacier_state_imports_mark_account_created : + IsImported globals "ethereum.arrow_glacier.state" "mark_account_created". +Axiom ethereum_arrow_glacier_state_imports_move_ether : + IsImported globals "ethereum.arrow_glacier.state" "move_ether". +Axiom ethereum_arrow_glacier_state_imports_rollback_transaction : + IsImported globals "ethereum.arrow_glacier.state" "rollback_transaction". +Axiom ethereum_arrow_glacier_state_imports_set_code : + IsImported globals "ethereum.arrow_glacier.state" "set_code". +Axiom ethereum_arrow_glacier_state_imports_touch_account : + IsImported globals "ethereum.arrow_glacier.state" "touch_account". + +Axiom ethereum_arrow_glacier_vm_imports_Message : + IsImported globals "ethereum.arrow_glacier.vm" "Message". + +Axiom ethereum_arrow_glacier_vm_gas_imports_GAS_CODE_DEPOSIT : + IsImported globals "ethereum.arrow_glacier.vm.gas" "GAS_CODE_DEPOSIT". +Axiom ethereum_arrow_glacier_vm_gas_imports_charge_gas : + IsImported globals "ethereum.arrow_glacier.vm.gas" "charge_gas". + +Axiom ethereum_arrow_glacier_vm_precompiled_contracts_mapping_imports_PRE_COMPILED_CONTRACTS : + IsImported globals "ethereum.arrow_glacier.vm.precompiled_contracts.mapping" "PRE_COMPILED_CONTRACTS". + +Axiom ethereum_arrow_glacier_vm_imports_Environment : + IsImported globals "ethereum.arrow_glacier.vm" "Environment". +Axiom ethereum_arrow_glacier_vm_imports_Evm : + IsImported globals "ethereum.arrow_glacier.vm" "Evm". + +Axiom ethereum_arrow_glacier_vm_exceptions_imports_AddressCollision : + IsImported globals "ethereum.arrow_glacier.vm.exceptions" "AddressCollision". +Axiom ethereum_arrow_glacier_vm_exceptions_imports_ExceptionalHalt : + IsImported globals "ethereum.arrow_glacier.vm.exceptions" "ExceptionalHalt". +Axiom ethereum_arrow_glacier_vm_exceptions_imports_InvalidContractPrefix : + IsImported globals "ethereum.arrow_glacier.vm.exceptions" "InvalidContractPrefix". +Axiom ethereum_arrow_glacier_vm_exceptions_imports_InvalidOpcode : + IsImported globals "ethereum.arrow_glacier.vm.exceptions" "InvalidOpcode". +Axiom ethereum_arrow_glacier_vm_exceptions_imports_OutOfGasError : + IsImported globals "ethereum.arrow_glacier.vm.exceptions" "OutOfGasError". +Axiom ethereum_arrow_glacier_vm_exceptions_imports_Revert : + IsImported globals "ethereum.arrow_glacier.vm.exceptions" "Revert". +Axiom ethereum_arrow_glacier_vm_exceptions_imports_StackDepthLimitError : + IsImported globals "ethereum.arrow_glacier.vm.exceptions" "StackDepthLimitError". + +Axiom ethereum_arrow_glacier_vm_instructions_imports_Ops : + IsImported globals "ethereum.arrow_glacier.vm.instructions" "Ops". +Axiom ethereum_arrow_glacier_vm_instructions_imports_op_implementation : + IsImported globals "ethereum.arrow_glacier.vm.instructions" "op_implementation". + +Axiom ethereum_arrow_glacier_vm_runtime_imports_get_valid_jump_destinations : + IsImported globals "ethereum.arrow_glacier.vm.runtime" "get_valid_jump_destinations". + +Definition STACK_DEPTH_LIMIT : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 1024 + ], + make_dict [] + |) +)). + +Definition MAX_CODE_SIZE : Value.t := M.run ltac:(M.monadic ( + Constant.int 24576 +)). + +Definition MessageCallOutput : Value.t := + builtins.make_klass + [] + [ + + ] + [ + + ]. + +Definition process_message_call : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "message"; "env" ] |) in + let _ := Constant.str " + If `message.current` is empty then it creates a smart contract + else it executes a call from the `message.caller` to the `message.target`. + + Parameters + ---------- + message : + Transaction specific items. + + env : + External items required for EVM execution. + + Returns + ------- + output : `MessageCallOutput` + Output of the message call + " in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_field (| M.get_name (| globals, "message" |), "target" |), + M.call (| + M.get_name (| globals, "Bytes0" |), + make_list [ + Constant.bytes "" + ], + make_dict [] + |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "is_collision" , + M.call (| + M.get_name (| globals, "account_has_code_or_nonce" |), + make_list [ + M.get_field (| M.get_name (| globals, "env" |), "state" |); + M.get_field (| M.get_name (| globals, "message" |), "current_target" |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + M.get_name (| globals, "is_collision" |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + M.call (| + M.get_name (| globals, "MessageCallOutput" |), + make_list [ + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |); + M.call (| + M.get_name (| globals, "tuple" |), + make_list [], + make_dict [] + |); + M.call (| + M.get_name (| globals, "set" |), + make_list [], + make_dict [] + |); + M.call (| + M.get_name (| globals, "set" |), + make_list [], + make_dict [] + |); + M.call (| + M.get_name (| globals, "AddressCollision" |), + make_list [], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "evm" , + M.call (| + M.get_name (| globals, "process_create_message" |), + make_list [ + M.get_name (| globals, "message" |); + M.get_name (| globals, "env" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "evm" , + M.call (| + M.get_name (| globals, "process_message" |), + make_list [ + M.get_name (| globals, "message" |); + M.get_name (| globals, "env" |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, "account_exists_and_is_empty" |), + make_list [ + M.get_field (| M.get_name (| globals, "env" |), "state" |); + M.call (| + M.get_name (| globals, "Address" |), + make_list [ + M.get_field (| M.get_name (| globals, "message" |), "target" |) + ], + make_dict [] + |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "touched_accounts" |), "add" |), + make_list [ + M.call (| + M.get_name (| globals, "Address" |), + make_list [ + M.get_field (| M.get_name (| globals, "message" |), "target" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + M.get_field (| M.get_name (| globals, "evm" |), "error" |), + (* then *) + ltac:(M.monadic ( +(* At stmt: unsupported node type: AnnAssign *) + let _ := M.assign_local (| + "accounts_to_delete" , + M.call (| + M.get_name (| globals, "set" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "touched_accounts" , + M.call (| + M.get_name (| globals, "set" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "refund_counter" , + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "logs" , + M.get_field (| M.get_name (| globals, "evm" |), "logs" |) + |) in + let _ := M.assign_local (| + "accounts_to_delete" , + M.get_field (| M.get_name (| globals, "evm" |), "accounts_to_delete" |) + |) in + let _ := M.assign_local (| + "touched_accounts" , + M.get_field (| M.get_name (| globals, "evm" |), "touched_accounts" |) + |) in + let _ := M.assign_local (| + "refund_counter" , + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "refund_counter" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "tx_end" , + M.call (| + M.get_name (| globals, "TransactionEnd" |), + make_list [ + BinOp.sub (| + M.get_field (| M.get_name (| globals, "message" |), "gas" |), + M.get_field (| M.get_name (| globals, "evm" |), "gas_left" |) + |); + M.get_field (| M.get_name (| globals, "evm" |), "output" |); + M.get_field (| M.get_name (| globals, "evm" |), "error" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "evm_trace" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "tx_end" |) + ], + make_dict [] + |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, "MessageCallOutput" |), + make_list [], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Definition process_create_message : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "message"; "env" ] |) in + let _ := Constant.str " + Executes a call to create a smart contract. + + Parameters + ---------- + message : + Transaction specific items. + env : + External items required for EVM execution. + + Returns + ------- + evm: :py:class:`~ethereum.london.vm.Evm` + Items containing execution specific objects. + " in + let _ := M.call (| + M.get_name (| globals, "begin_transaction" |), + make_list [ + M.get_field (| M.get_name (| globals, "env" |), "state" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "destroy_storage" |), + make_list [ + M.get_field (| M.get_name (| globals, "env" |), "state" |); + M.get_field (| M.get_name (| globals, "message" |), "current_target" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "mark_account_created" |), + make_list [ + M.get_field (| M.get_name (| globals, "env" |), "state" |); + M.get_field (| M.get_name (| globals, "message" |), "current_target" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "increment_nonce" |), + make_list [ + M.get_field (| M.get_name (| globals, "env" |), "state" |); + M.get_field (| M.get_name (| globals, "message" |), "current_target" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "evm" , + M.call (| + M.get_name (| globals, "process_message" |), + make_list [ + M.get_name (| globals, "message" |); + M.get_name (| globals, "env" |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + UnOp.not (| M.get_field (| M.get_name (| globals, "evm" |), "error" |) |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "contract_code" , + M.get_field (| M.get_name (| globals, "evm" |), "output" |) + |) in + let _ := M.assign_local (| + "contract_code_gas" , + BinOp.mult (| + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_name (| globals, "contract_code" |) + ], + make_dict [] + |), + M.get_name (| globals, "GAS_CODE_DEPOSIT" |) + |) + |) in +(* At stmt: unsupported node type: Try *) + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, "rollback_transaction" |), + make_list [ + M.get_field (| M.get_name (| globals, "env" |), "state" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + )) |) in + let _ := M.return_ (| + M.get_name (| globals, "evm" |) + |) in + M.pure Constant.None_)). + +Definition process_message : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "message"; "env" ] |) in + let _ := Constant.str " + Executes a call to create a smart contract. + + Parameters + ---------- + message : + Transaction specific items. + env : + External items required for EVM execution. + + Returns + ------- + evm: :py:class:`~ethereum.london.vm.Evm` + Items containing execution specific objects + " in + let _ := + (* if *) + M.if_then_else (| + Compare.gt (| + M.get_field (| M.get_name (| globals, "message" |), "depth" |), + M.get_name (| globals, "STACK_DEPTH_LIMIT" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.call (| + M.get_name (| globals, "StackDepthLimitError" |), + make_list [ + Constant.str "Stack depth limit reached" + ], + make_dict [] + |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.call (| + M.get_name (| globals, "begin_transaction" |), + make_list [ + M.get_field (| M.get_name (| globals, "env" |), "state" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "touch_account" |), + make_list [ + M.get_field (| M.get_name (| globals, "env" |), "state" |); + M.get_field (| M.get_name (| globals, "message" |), "current_target" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + BoolOp.and (| + M.get_field (| M.get_name (| globals, "message" |), "should_transfer_value" |), + ltac:(M.monadic ( + Compare.not_eq (| + M.get_field (| M.get_name (| globals, "message" |), "value" |), + Constant.int 0 + |) + )) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, "move_ether" |), + make_list [ + M.get_field (| M.get_name (| globals, "env" |), "state" |); + M.get_field (| M.get_name (| globals, "message" |), "caller" |); + M.get_field (| M.get_name (| globals, "message" |), "current_target" |); + M.get_field (| M.get_name (| globals, "message" |), "value" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "evm" , + M.call (| + M.get_name (| globals, "execute_code" |), + make_list [ + M.get_name (| globals, "message" |); + M.get_name (| globals, "env" |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + M.get_field (| M.get_name (| globals, "evm" |), "error" |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, "rollback_transaction" |), + make_list [ + M.get_field (| M.get_name (| globals, "env" |), "state" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, "commit_transaction" |), + make_list [ + M.get_field (| M.get_name (| globals, "env" |), "state" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + )) |) in + let _ := M.return_ (| + M.get_name (| globals, "evm" |) + |) in + M.pure Constant.None_)). + +Definition execute_code : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "message"; "env" ] |) in + let _ := Constant.str " + Executes bytecode present in the `message`. + + Parameters + ---------- + message : + Transaction specific items. + env : + External items required for EVM execution. + + Returns + ------- + evm: `ethereum.vm.EVM` + Items containing execution specific objects + " in + let _ := M.assign_local (| + "code" , + M.get_field (| M.get_name (| globals, "message" |), "code" |) + |) in + let _ := M.assign_local (| + "valid_jump_destinations" , + M.call (| + M.get_name (| globals, "get_valid_jump_destinations" |), + make_list [ + M.get_name (| globals, "code" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "evm" , + M.call (| + M.get_name (| globals, "Evm" |), + make_list [], + make_dict [] + |) + |) in +(* At stmt: unsupported node type: Try *) + let _ := M.return_ (| + M.get_name (| globals, "evm" |) + |) in + M.pure Constant.None_)). diff --git a/CoqOfPython/ethereum/arrow_glacier/vm/memory.v b/CoqOfPython/ethereum/arrow_glacier/vm/memory.v new file mode 100644 index 0000000..207f7fb --- /dev/null +++ b/CoqOfPython/ethereum/arrow_glacier/vm/memory.v @@ -0,0 +1,166 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.arrow_glacier.vm.memory". + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) Memory +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +EVM memory operations. +". + +Axiom ethereum_utils_byte_imports_right_pad_zero_bytes : + IsImported globals "ethereum.utils.byte" "right_pad_zero_bytes". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_Bytes : + IsImported globals "ethereum.base_types" "Bytes". +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". + +Definition memory_write : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "memory"; "start_position"; "value" ] |) in + let _ := Constant.str " + Writes to memory. + + Parameters + ---------- + memory : + Memory contents of the EVM. + start_position : + Starting pointer to the memory. + value : + Data to write to memory. + " in + let _ := M.assign (| + M.slice (| + M.get_name (| globals, "memory" |), + M.get_name (| globals, "start_position" |), + BinOp.add (| + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.get_name (| globals, "start_position" |) + ], + make_dict [] + |), + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_name (| globals, "value" |) + ], + make_dict [] + |) + |), + Constant.None_ + |), + M.get_name (| globals, "value" |) + |) in + M.pure Constant.None_)). + +Definition memory_read_bytes : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "memory"; "start_position"; "size" ] |) in + let _ := Constant.str " + Read bytes from memory. + + Parameters + ---------- + memory : + Memory contents of the EVM. + start_position : + Starting pointer to the memory. + size : + Size of the data that needs to be read from `start_position`. + + Returns + ------- + data_bytes : + Data read from memory. + " in + let _ := M.return_ (| + M.slice (| + M.get_name (| globals, "memory" |), + M.get_name (| globals, "start_position" |), + BinOp.add (| + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.get_name (| globals, "start_position" |) + ], + make_dict [] + |), + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.get_name (| globals, "size" |) + ], + make_dict [] + |) + |), + Constant.None_ + |) + |) in + M.pure Constant.None_)). + +Definition buffer_read : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "buffer"; "start_position"; "size" ] |) in + let _ := Constant.str " + Read bytes from a buffer. Padding with zeros if necessary. + + Parameters + ---------- + buffer : + Memory contents of the EVM. + start_position : + Starting pointer to the memory. + size : + Size of the data that needs to be read from `start_position`. + + Returns + ------- + data_bytes : + Data read from memory. + " in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, "right_pad_zero_bytes" |), + make_list [ + M.slice (| + M.get_name (| globals, "buffer" |), + M.get_name (| globals, "start_position" |), + BinOp.add (| + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.get_name (| globals, "start_position" |) + ], + make_dict [] + |), + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.get_name (| globals, "size" |) + ], + make_dict [] + |) + |), + Constant.None_ + |); + M.get_name (| globals, "size" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). diff --git a/CoqOfPython/ethereum/arrow_glacier/vm/precompiled_contracts/__init__.v b/CoqOfPython/ethereum/arrow_glacier/vm/precompiled_contracts/__init__.v new file mode 100644 index 0000000..2d091ab --- /dev/null +++ b/CoqOfPython/ethereum/arrow_glacier/vm/precompiled_contracts/__init__.v @@ -0,0 +1,116 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.arrow_glacier.vm.precompiled_contracts.__init__". + +Definition expr_1 : Value.t := + Constant.str " +Precompiled Contract Addresses +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Addresses of precompiled contracts and mappings to their +implementations. +". + +Axiom ethereum_arrow_glacier_utils_hexadecimal_imports_hex_to_address : + IsImported globals "ethereum.arrow_glacier.utils.hexadecimal" "hex_to_address". + +Definition __all__ : Value.t := M.run ltac:(M.monadic ( + make_tuple [ Constant.str "ECRECOVER_ADDRESS"; Constant.str "SHA256_ADDRESS"; Constant.str "RIPEMD160_ADDRESS"; Constant.str "IDENTITY_ADDRESS"; Constant.str "MODEXP_ADDRESS"; Constant.str "ALT_BN128_ADD_ADDRESS"; Constant.str "ALT_BN128_MUL_ADDRESS"; Constant.str "ALT_BN128_PAIRING_CHECK_ADDRESS"; Constant.str "BLAKE2F_ADDRESS" ] +)). + +Definition ECRECOVER_ADDRESS : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "hex_to_address" |), + make_list [ + Constant.str "0x01" + ], + make_dict [] + |) +)). + +Definition SHA256_ADDRESS : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "hex_to_address" |), + make_list [ + Constant.str "0x02" + ], + make_dict [] + |) +)). + +Definition RIPEMD160_ADDRESS : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "hex_to_address" |), + make_list [ + Constant.str "0x03" + ], + make_dict [] + |) +)). + +Definition IDENTITY_ADDRESS : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "hex_to_address" |), + make_list [ + Constant.str "0x04" + ], + make_dict [] + |) +)). + +Definition MODEXP_ADDRESS : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "hex_to_address" |), + make_list [ + Constant.str "0x05" + ], + make_dict [] + |) +)). + +Definition ALT_BN128_ADD_ADDRESS : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "hex_to_address" |), + make_list [ + Constant.str "0x06" + ], + make_dict [] + |) +)). + +Definition ALT_BN128_MUL_ADDRESS : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "hex_to_address" |), + make_list [ + Constant.str "0x07" + ], + make_dict [] + |) +)). + +Definition ALT_BN128_PAIRING_CHECK_ADDRESS : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "hex_to_address" |), + make_list [ + Constant.str "0x08" + ], + make_dict [] + |) +)). + +Definition BLAKE2F_ADDRESS : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "hex_to_address" |), + make_list [ + Constant.str "0x09" + ], + make_dict [] + |) +)). diff --git a/CoqOfPython/ethereum/arrow_glacier/vm/precompiled_contracts/alt_bn128.v b/CoqOfPython/ethereum/arrow_glacier/vm/precompiled_contracts/alt_bn128.v new file mode 100644 index 0000000..4649b5a --- /dev/null +++ b/CoqOfPython/ethereum/arrow_glacier/vm/precompiled_contracts/alt_bn128.v @@ -0,0 +1,778 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.arrow_glacier.vm.precompiled_contracts.alt_bn128". + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) ALT_BN128 CONTRACTS +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementation of the ALT_BN128 precompiled contracts. +". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". + +Axiom ethereum_crypto_alt_bn128_imports_ALT_BN128_CURVE_ORDER : + IsImported globals "ethereum.crypto.alt_bn128" "ALT_BN128_CURVE_ORDER". +Axiom ethereum_crypto_alt_bn128_imports_ALT_BN128_PRIME : + IsImported globals "ethereum.crypto.alt_bn128" "ALT_BN128_PRIME". +Axiom ethereum_crypto_alt_bn128_imports_BNF : + IsImported globals "ethereum.crypto.alt_bn128" "BNF". +Axiom ethereum_crypto_alt_bn128_imports_BNF2 : + IsImported globals "ethereum.crypto.alt_bn128" "BNF2". +Axiom ethereum_crypto_alt_bn128_imports_BNF12 : + IsImported globals "ethereum.crypto.alt_bn128" "BNF12". +Axiom ethereum_crypto_alt_bn128_imports_BNP : + IsImported globals "ethereum.crypto.alt_bn128" "BNP". +Axiom ethereum_crypto_alt_bn128_imports_BNP2 : + IsImported globals "ethereum.crypto.alt_bn128" "BNP2". +Axiom ethereum_crypto_alt_bn128_imports_pairing : + IsImported globals "ethereum.crypto.alt_bn128" "pairing". + +Axiom ethereum_utils_ensure_imports_ensure : + IsImported globals "ethereum.utils.ensure" "ensure". + +Axiom ethereum_arrow_glacier_vm_imports_Evm : + IsImported globals "ethereum.arrow_glacier.vm" "Evm". + +Axiom ethereum_arrow_glacier_vm_gas_imports_charge_gas : + IsImported globals "ethereum.arrow_glacier.vm.gas" "charge_gas". + +Axiom ethereum_arrow_glacier_vm_memory_imports_buffer_read : + IsImported globals "ethereum.arrow_glacier.vm.memory" "buffer_read". + +Axiom ethereum_arrow_glacier_vm_exceptions_imports_OutOfGasError : + IsImported globals "ethereum.arrow_glacier.vm.exceptions" "OutOfGasError". + +Definition alt_bn128_add : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + The ALT_BN128 addition precompiled contract. + + Parameters + ---------- + evm : + The current EVM frame. + " in + let _ := M.assign_local (| + "data" , + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "data" |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 150 + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "x0_bytes" , + M.call (| + M.get_name (| globals, "buffer_read" |), + make_list [ + M.get_name (| globals, "data" |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 32 + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "x0_value" , + M.call (| + M.get_field (| M.get_name (| globals, "U256" |), "from_be_bytes" |), + make_list [ + M.get_name (| globals, "x0_bytes" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "y0_bytes" , + M.call (| + M.get_name (| globals, "buffer_read" |), + make_list [ + M.get_name (| globals, "data" |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 32 + ], + make_dict [] + |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 32 + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "y0_value" , + M.call (| + M.get_field (| M.get_name (| globals, "U256" |), "from_be_bytes" |), + make_list [ + M.get_name (| globals, "y0_bytes" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "x1_bytes" , + M.call (| + M.get_name (| globals, "buffer_read" |), + make_list [ + M.get_name (| globals, "data" |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 64 + ], + make_dict [] + |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 32 + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "x1_value" , + M.call (| + M.get_field (| M.get_name (| globals, "U256" |), "from_be_bytes" |), + make_list [ + M.get_name (| globals, "x1_bytes" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "y1_bytes" , + M.call (| + M.get_name (| globals, "buffer_read" |), + make_list [ + M.get_name (| globals, "data" |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 96 + ], + make_dict [] + |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 32 + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "y1_value" , + M.call (| + M.get_field (| M.get_name (| globals, "U256" |), "from_be_bytes" |), + make_list [ + M.get_name (| globals, "y1_bytes" |) + ], + make_dict [] + |) + |) in + let _ := + M.for_ (| + M.get_name (| globals, "i" |), + make_tuple [ M.get_name (| globals, "x0_value" |); M.get_name (| globals, "y0_value" |); M.get_name (| globals, "x1_value" |); M.get_name (| globals, "y1_value" |) ], + ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + Compare.gt_e (| + M.get_name (| globals, "i" |), + M.get_name (| globals, "ALT_BN128_PRIME" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, "OutOfGasError" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in +(* At stmt: unsupported node type: Try *) + let _ := M.assign_local (| + "p" , + BinOp.add (| + M.get_name (| globals, "p0" |), + M.get_name (| globals, "p1" |) + |) + |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, "evm" |), "output" |), + BinOp.add (| + M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, "p" |), "x" |), "to_be_bytes32" |), + make_list [], + make_dict [] + |), + M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, "p" |), "y" |), "to_be_bytes32" |), + make_list [], + make_dict [] + |) + |) + |) in + M.pure Constant.None_)). + +Definition alt_bn128_mul : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + The ALT_BN128 multiplication precompiled contract. + + Parameters + ---------- + evm : + The current EVM frame. + " in + let _ := M.assign_local (| + "data" , + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "data" |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 6000 + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "x0_bytes" , + M.call (| + M.get_name (| globals, "buffer_read" |), + make_list [ + M.get_name (| globals, "data" |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 32 + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "x0_value" , + M.call (| + M.get_field (| M.get_name (| globals, "U256" |), "from_be_bytes" |), + make_list [ + M.get_name (| globals, "x0_bytes" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "y0_bytes" , + M.call (| + M.get_name (| globals, "buffer_read" |), + make_list [ + M.get_name (| globals, "data" |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 32 + ], + make_dict [] + |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 32 + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "y0_value" , + M.call (| + M.get_field (| M.get_name (| globals, "U256" |), "from_be_bytes" |), + make_list [ + M.get_name (| globals, "y0_bytes" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "n" , + M.call (| + M.get_field (| M.get_name (| globals, "U256" |), "from_be_bytes" |), + make_list [ + M.call (| + M.get_name (| globals, "buffer_read" |), + make_list [ + M.get_name (| globals, "data" |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 64 + ], + make_dict [] + |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 32 + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := + M.for_ (| + M.get_name (| globals, "i" |), + make_tuple [ M.get_name (| globals, "x0_value" |); M.get_name (| globals, "y0_value" |) ], + ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + Compare.gt_e (| + M.get_name (| globals, "i" |), + M.get_name (| globals, "ALT_BN128_PRIME" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, "OutOfGasError" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in +(* At stmt: unsupported node type: Try *) + let _ := M.assign_local (| + "p" , + M.call (| + M.get_field (| M.get_name (| globals, "p0" |), "mul_by" |), + make_list [ + M.get_name (| globals, "n" |) + ], + make_dict [] + |) + |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, "evm" |), "output" |), + BinOp.add (| + M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, "p" |), "x" |), "to_be_bytes32" |), + make_list [], + make_dict [] + |), + M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, "p" |), "y" |), "to_be_bytes32" |), + make_list [], + make_dict [] + |) + |) + |) in + M.pure Constant.None_)). + +Definition alt_bn128_pairing_check : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + The ALT_BN128 pairing check precompiled contract. + + Parameters + ---------- + evm : + The current EVM frame. + " in + let _ := M.assign_local (| + "data" , + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "data" |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + BinOp.add (| + BinOp.mult (| + Constant.int 34000, + BinOp.floor_div (| + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_name (| globals, "data" |) + ], + make_dict [] + |), + Constant.int 192 + |) + |), + Constant.int 45000 + |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.not_eq (| + BinOp.mod_ (| + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_name (| globals, "data" |) + ], + make_dict [] + |), + Constant.int 192 + |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, "OutOfGasError" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "result" , + M.call (| + M.get_field (| M.get_name (| globals, "BNF12" |), "from_int" |), + make_list [ + Constant.int 1 + ], + make_dict [] + |) + |) in + let _ := + M.for_ (| + M.get_name (| globals, "i" |), + M.call (| + M.get_name (| globals, "range" |), + make_list [ + BinOp.floor_div (| + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_name (| globals, "data" |) + ], + make_dict [] + |), + Constant.int 192 + |) + ], + make_dict [] + |), + ltac:(M.monadic ( + let _ := M.assign_local (| + "values" , + make_list [] + |) in + let _ := + M.for_ (| + M.get_name (| globals, "j" |), + M.call (| + M.get_name (| globals, "range" |), + make_list [ + Constant.int 6 + ], + make_dict [] + |), + ltac:(M.monadic ( + let _ := M.assign_local (| + "value" , + M.call (| + M.get_field (| M.get_name (| globals, "U256" |), "from_be_bytes" |), + make_list [ + M.slice (| + M.get_name (| globals, "data" |), + BinOp.add (| + BinOp.mult (| + M.get_name (| globals, "i" |), + Constant.int 192 + |), + BinOp.mult (| + Constant.int 32, + M.get_name (| globals, "j" |) + |) + |), + BinOp.add (| + BinOp.mult (| + M.get_name (| globals, "i" |), + Constant.int 192 + |), + BinOp.mult (| + Constant.int 32, + BinOp.add (| + M.get_name (| globals, "j" |), + Constant.int 1 + |) + |) + |), + Constant.None_ + |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.gt_e (| + M.get_name (| globals, "value" |), + M.get_name (| globals, "ALT_BN128_PRIME" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, "OutOfGasError" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.call (| + M.get_field (| M.get_name (| globals, "values" |), "append" |), + make_list [ + M.call (| + M.get_name (| globals, "int" |), + make_list [ + M.get_name (| globals, "value" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in +(* At stmt: unsupported node type: Try *) + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + Compare.eq (| + M.call (| + M.get_field (| M.get_name (| globals, "p" |), "mul_by" |), + make_list [ + M.get_name (| globals, "ALT_BN128_CURVE_ORDER" |) + ], + make_dict [] + |), + M.call (| + M.get_field (| M.get_name (| globals, "BNP" |), "point_at_infinity" |), + make_list [], + make_dict [] + |) + |); + M.get_name (| globals, "OutOfGasError" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + Compare.eq (| + M.call (| + M.get_field (| M.get_name (| globals, "q" |), "mul_by" |), + make_list [ + M.get_name (| globals, "ALT_BN128_CURVE_ORDER" |) + ], + make_dict [] + |), + M.call (| + M.get_field (| M.get_name (| globals, "BNP2" |), "point_at_infinity" |), + make_list [], + make_dict [] + |) + |); + M.get_name (| globals, "OutOfGasError" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + BoolOp.and (| + Compare.not_eq (| + M.get_name (| globals, "p" |), + M.call (| + M.get_field (| M.get_name (| globals, "BNP" |), "point_at_infinity" |), + make_list [], + make_dict [] + |) + |), + ltac:(M.monadic ( + Compare.not_eq (| + M.get_name (| globals, "q" |), + M.call (| + M.get_field (| M.get_name (| globals, "BNP2" |), "point_at_infinity" |), + make_list [], + make_dict [] + |) + |) + )) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "result" , + BinOp.mult (| + M.get_name (| globals, "result" |), + M.call (| + M.get_name (| globals, "pairing" |), + make_list [ + M.get_name (| globals, "q" |); + M.get_name (| globals, "p" |) + ], + make_dict [] + |) + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, "result" |), + M.call (| + M.get_field (| M.get_name (| globals, "BNF12" |), "from_int" |), + make_list [ + Constant.int 1 + ], + make_dict [] + |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign (| + M.get_field (| M.get_name (| globals, "evm" |), "output" |), + M.call (| + M.get_field (| M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 1 + ], + make_dict [] + |), "to_be_bytes32" |), + make_list [], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign (| + M.get_field (| M.get_name (| globals, "evm" |), "output" |), + M.call (| + M.get_field (| M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |), "to_be_bytes32" |), + make_list [], + make_dict [] + |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_)). diff --git a/CoqOfPython/ethereum/arrow_glacier/vm/precompiled_contracts/blake2f.v b/CoqOfPython/ethereum/arrow_glacier/vm/precompiled_contracts/blake2f.v new file mode 100644 index 0000000..0cad2c6 --- /dev/null +++ b/CoqOfPython/ethereum/arrow_glacier/vm/precompiled_contracts/blake2f.v @@ -0,0 +1,127 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.arrow_glacier.vm.precompiled_contracts.blake2f". + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) Blake2 PRECOMPILED CONTRACT +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementation of the `Blake2` precompiled contract. +". + +Axiom ethereum_crypto_blake2_imports_Blake2b : + IsImported globals "ethereum.crypto.blake2" "Blake2b". + +Axiom ethereum_utils_ensure_imports_ensure : + IsImported globals "ethereum.utils.ensure" "ensure". + +Axiom ethereum_arrow_glacier_vm_imports_Evm : + IsImported globals "ethereum.arrow_glacier.vm" "Evm". + +Axiom ethereum_arrow_glacier_vm_gas_imports_GAS_BLAKE2_PER_ROUND : + IsImported globals "ethereum.arrow_glacier.vm.gas" "GAS_BLAKE2_PER_ROUND". +Axiom ethereum_arrow_glacier_vm_gas_imports_charge_gas : + IsImported globals "ethereum.arrow_glacier.vm.gas" "charge_gas". + +Axiom ethereum_arrow_glacier_vm_exceptions_imports_InvalidParameter : + IsImported globals "ethereum.arrow_glacier.vm.exceptions" "InvalidParameter". + +Definition blake2f : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Writes the Blake2 hash to output. + + Parameters + ---------- + evm : + The current EVM frame. + " in + let _ := M.assign_local (| + "data" , + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "data" |) + |) in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + Compare.eq (| + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_name (| globals, "data" |) + ], + make_dict [] + |), + Constant.int 213 + |); + M.get_name (| globals, "InvalidParameter" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "blake2b" , + M.call (| + M.get_name (| globals, "Blake2b" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.assign (| + make_tuple [ M.get_name (| globals, "rounds" |); M.get_name (| globals, "h" |); M.get_name (| globals, "m" |); M.get_name (| globals, "t_0" |); M.get_name (| globals, "t_1" |); M.get_name (| globals, "f" |) ], + M.call (| + M.get_field (| M.get_name (| globals, "blake2b" |), "get_blake2_parameters" |), + make_list [ + M.get_name (| globals, "data" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + BinOp.mult (| + M.get_name (| globals, "GAS_BLAKE2_PER_ROUND" |), + M.get_name (| globals, "rounds" |) + |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + Compare.in_ (| + M.get_name (| globals, "f" |), + make_list [ + Constant.int 0; + Constant.int 1 + ] + |); + M.get_name (| globals, "InvalidParameter" |) + ], + make_dict [] + |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, "evm" |), "output" |), + M.call (| + M.get_field (| M.get_name (| globals, "blake2b" |), "compress" |), + make_list [ + M.get_name (| globals, "rounds" |); + M.get_name (| globals, "h" |); + M.get_name (| globals, "m" |); + M.get_name (| globals, "t_0" |); + M.get_name (| globals, "t_1" |); + M.get_name (| globals, "f" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). diff --git a/CoqOfPython/ethereum/arrow_glacier/vm/precompiled_contracts/ecrecover.v b/CoqOfPython/ethereum/arrow_glacier/vm/precompiled_contracts/ecrecover.v new file mode 100644 index 0000000..aaa3942 --- /dev/null +++ b/CoqOfPython/ethereum/arrow_glacier/vm/precompiled_contracts/ecrecover.v @@ -0,0 +1,301 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.arrow_glacier.vm.precompiled_contracts.ecrecover". + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) ECRECOVER PRECOMPILED CONTRACT +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementation of the ECRECOVER precompiled contract. +". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". + +Axiom ethereum_crypto_elliptic_curve_imports_SECP256K1N : + IsImported globals "ethereum.crypto.elliptic_curve" "SECP256K1N". +Axiom ethereum_crypto_elliptic_curve_imports_secp256k1_recover : + IsImported globals "ethereum.crypto.elliptic_curve" "secp256k1_recover". + +Axiom ethereum_crypto_hash_imports_Hash32 : + IsImported globals "ethereum.crypto.hash" "Hash32". +Axiom ethereum_crypto_hash_imports_keccak256 : + IsImported globals "ethereum.crypto.hash" "keccak256". + +Axiom ethereum_utils_byte_imports_left_pad_zero_bytes : + IsImported globals "ethereum.utils.byte" "left_pad_zero_bytes". + +Axiom ethereum_arrow_glacier_vm_imports_Evm : + IsImported globals "ethereum.arrow_glacier.vm" "Evm". + +Axiom ethereum_arrow_glacier_vm_gas_imports_GAS_ECRECOVER : + IsImported globals "ethereum.arrow_glacier.vm.gas" "GAS_ECRECOVER". +Axiom ethereum_arrow_glacier_vm_gas_imports_charge_gas : + IsImported globals "ethereum.arrow_glacier.vm.gas" "charge_gas". + +Axiom ethereum_arrow_glacier_vm_memory_imports_buffer_read : + IsImported globals "ethereum.arrow_glacier.vm.memory" "buffer_read". + +Definition ecrecover : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Decrypts the address using elliptic curve DSA recovery mechanism and writes + the address to output. + + Parameters + ---------- + evm : + The current EVM frame. + " in + let _ := M.assign_local (| + "data" , + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "data" |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_ECRECOVER" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "message_hash_bytes" , + M.call (| + M.get_name (| globals, "buffer_read" |), + make_list [ + M.get_name (| globals, "data" |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 32 + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "message_hash" , + M.call (| + M.get_name (| globals, "Hash32" |), + make_list [ + M.get_name (| globals, "message_hash_bytes" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "v" , + M.call (| + M.get_field (| M.get_name (| globals, "U256" |), "from_be_bytes" |), + make_list [ + M.call (| + M.get_name (| globals, "buffer_read" |), + make_list [ + M.get_name (| globals, "data" |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 32 + ], + make_dict [] + |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 32 + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "r" , + M.call (| + M.get_field (| M.get_name (| globals, "U256" |), "from_be_bytes" |), + make_list [ + M.call (| + M.get_name (| globals, "buffer_read" |), + make_list [ + M.get_name (| globals, "data" |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 64 + ], + make_dict [] + |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 32 + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "s" , + M.call (| + M.get_field (| M.get_name (| globals, "U256" |), "from_be_bytes" |), + make_list [ + M.call (| + M.get_name (| globals, "buffer_read" |), + make_list [ + M.get_name (| globals, "data" |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 96 + ], + make_dict [] + |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 32 + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + BoolOp.and (| + Compare.not_eq (| + M.get_name (| globals, "v" |), + Constant.int 27 + |), + ltac:(M.monadic ( + Compare.not_eq (| + M.get_name (| globals, "v" |), + Constant.int 28 + |) + )) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + Constant.None_ + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + BoolOp.or (| + Compare.gt_e (| + Constant.int 0, + M.get_name (| globals, "r" |) + |), + ltac:(M.monadic ( + Compare.gt_e (| + M.get_name (| globals, "r" |), + M.get_name (| globals, "SECP256K1N" |) + |) + )) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + Constant.None_ + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + BoolOp.or (| + Compare.gt_e (| + Constant.int 0, + M.get_name (| globals, "s" |) + |), + ltac:(M.monadic ( + Compare.gt_e (| + M.get_name (| globals, "s" |), + M.get_name (| globals, "SECP256K1N" |) + |) + )) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + Constant.None_ + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in +(* At stmt: unsupported node type: Try *) + let _ := M.assign_local (| + "address" , + M.slice (| + M.call (| + M.get_name (| globals, "keccak256" |), + make_list [ + M.get_name (| globals, "public_key" |) + ], + make_dict [] + |), + Constant.int 12, + Constant.int 32, + Constant.None_ + |) + |) in + let _ := M.assign_local (| + "padded_address" , + M.call (| + M.get_name (| globals, "left_pad_zero_bytes" |), + make_list [ + M.get_name (| globals, "address" |); + Constant.int 32 + ], + make_dict [] + |) + |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, "evm" |), "output" |), + M.get_name (| globals, "padded_address" |) + |) in + M.pure Constant.None_)). diff --git a/CoqOfPython/ethereum/arrow_glacier/vm/precompiled_contracts/identity.v b/CoqOfPython/ethereum/arrow_glacier/vm/precompiled_contracts/identity.v new file mode 100644 index 0000000..7443148 --- /dev/null +++ b/CoqOfPython/ethereum/arrow_glacier/vm/precompiled_contracts/identity.v @@ -0,0 +1,94 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.arrow_glacier.vm.precompiled_contracts.identity". + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) IDENTITY PRECOMPILED CONTRACT +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementation of the `IDENTITY` precompiled contract. +". + +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". + +Axiom ethereum_utils_numeric_imports_ceil32 : + IsImported globals "ethereum.utils.numeric" "ceil32". + +Axiom ethereum_arrow_glacier_vm_imports_Evm : + IsImported globals "ethereum.arrow_glacier.vm" "Evm". + +Axiom ethereum_arrow_glacier_vm_gas_imports_GAS_IDENTITY : + IsImported globals "ethereum.arrow_glacier.vm.gas" "GAS_IDENTITY". +Axiom ethereum_arrow_glacier_vm_gas_imports_GAS_IDENTITY_WORD : + IsImported globals "ethereum.arrow_glacier.vm.gas" "GAS_IDENTITY_WORD". +Axiom ethereum_arrow_glacier_vm_gas_imports_charge_gas : + IsImported globals "ethereum.arrow_glacier.vm.gas" "charge_gas". + +Definition identity : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Writes the message data to output. + + Parameters + ---------- + evm : + The current EVM frame. + " in + let _ := M.assign_local (| + "data" , + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "data" |) + |) in + let _ := M.assign_local (| + "word_count" , + BinOp.floor_div (| + M.call (| + M.get_name (| globals, "ceil32" |), + make_list [ + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_name (| globals, "data" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |), + Constant.int 32 + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + BinOp.add (| + M.get_name (| globals, "GAS_IDENTITY" |), + BinOp.mult (| + M.get_name (| globals, "GAS_IDENTITY_WORD" |), + M.get_name (| globals, "word_count" |) + |) + |) + ], + make_dict [] + |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, "evm" |), "output" |), + M.get_name (| globals, "data" |) + |) in + M.pure Constant.None_)). diff --git a/CoqOfPython/ethereum/arrow_glacier/vm/precompiled_contracts/mapping.v b/CoqOfPython/ethereum/arrow_glacier/vm/precompiled_contracts/mapping.v new file mode 100644 index 0000000..d47d1fc --- /dev/null +++ b/CoqOfPython/ethereum/arrow_glacier/vm/precompiled_contracts/mapping.v @@ -0,0 +1,72 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.arrow_glacier.vm.precompiled_contracts.mapping". + +Definition expr_1 : Value.t := + Constant.str " +Precompiled Contract Addresses +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Mapping of precompiled contracts their implementations. +". + +Axiom typing_imports_Callable : + IsImported globals "typing" "Callable". +Axiom typing_imports_Dict : + IsImported globals "typing" "Dict". + +Axiom ethereum_arrow_glacier_fork_types_imports_Address : + IsImported globals "ethereum.arrow_glacier.fork_types" "Address". + +Axiom ethereum_arrow_glacier_vm_precompiled_contracts_imports_ALT_BN128_ADD_ADDRESS : + IsImported globals "ethereum.arrow_glacier.vm.precompiled_contracts" "ALT_BN128_ADD_ADDRESS". +Axiom ethereum_arrow_glacier_vm_precompiled_contracts_imports_ALT_BN128_MUL_ADDRESS : + IsImported globals "ethereum.arrow_glacier.vm.precompiled_contracts" "ALT_BN128_MUL_ADDRESS". +Axiom ethereum_arrow_glacier_vm_precompiled_contracts_imports_ALT_BN128_PAIRING_CHECK_ADDRESS : + IsImported globals "ethereum.arrow_glacier.vm.precompiled_contracts" "ALT_BN128_PAIRING_CHECK_ADDRESS". +Axiom ethereum_arrow_glacier_vm_precompiled_contracts_imports_BLAKE2F_ADDRESS : + IsImported globals "ethereum.arrow_glacier.vm.precompiled_contracts" "BLAKE2F_ADDRESS". +Axiom ethereum_arrow_glacier_vm_precompiled_contracts_imports_ECRECOVER_ADDRESS : + IsImported globals "ethereum.arrow_glacier.vm.precompiled_contracts" "ECRECOVER_ADDRESS". +Axiom ethereum_arrow_glacier_vm_precompiled_contracts_imports_IDENTITY_ADDRESS : + IsImported globals "ethereum.arrow_glacier.vm.precompiled_contracts" "IDENTITY_ADDRESS". +Axiom ethereum_arrow_glacier_vm_precompiled_contracts_imports_MODEXP_ADDRESS : + IsImported globals "ethereum.arrow_glacier.vm.precompiled_contracts" "MODEXP_ADDRESS". +Axiom ethereum_arrow_glacier_vm_precompiled_contracts_imports_RIPEMD160_ADDRESS : + IsImported globals "ethereum.arrow_glacier.vm.precompiled_contracts" "RIPEMD160_ADDRESS". +Axiom ethereum_arrow_glacier_vm_precompiled_contracts_imports_SHA256_ADDRESS : + IsImported globals "ethereum.arrow_glacier.vm.precompiled_contracts" "SHA256_ADDRESS". + +Axiom ethereum_arrow_glacier_vm_precompiled_contracts_alt_bn128_imports_alt_bn128_add : + IsImported globals "ethereum.arrow_glacier.vm.precompiled_contracts.alt_bn128" "alt_bn128_add". +Axiom ethereum_arrow_glacier_vm_precompiled_contracts_alt_bn128_imports_alt_bn128_mul : + IsImported globals "ethereum.arrow_glacier.vm.precompiled_contracts.alt_bn128" "alt_bn128_mul". +Axiom ethereum_arrow_glacier_vm_precompiled_contracts_alt_bn128_imports_alt_bn128_pairing_check : + IsImported globals "ethereum.arrow_glacier.vm.precompiled_contracts.alt_bn128" "alt_bn128_pairing_check". + +Axiom ethereum_arrow_glacier_vm_precompiled_contracts_blake2f_imports_blake2f : + IsImported globals "ethereum.arrow_glacier.vm.precompiled_contracts.blake2f" "blake2f". + +Axiom ethereum_arrow_glacier_vm_precompiled_contracts_ecrecover_imports_ecrecover : + IsImported globals "ethereum.arrow_glacier.vm.precompiled_contracts.ecrecover" "ecrecover". + +Axiom ethereum_arrow_glacier_vm_precompiled_contracts_identity_imports_identity : + IsImported globals "ethereum.arrow_glacier.vm.precompiled_contracts.identity" "identity". + +Axiom ethereum_arrow_glacier_vm_precompiled_contracts_modexp_imports_modexp : + IsImported globals "ethereum.arrow_glacier.vm.precompiled_contracts.modexp" "modexp". + +Axiom ethereum_arrow_glacier_vm_precompiled_contracts_ripemd160_imports_ripemd160 : + IsImported globals "ethereum.arrow_glacier.vm.precompiled_contracts.ripemd160" "ripemd160". + +Axiom ethereum_arrow_glacier_vm_precompiled_contracts_sha256_imports_sha256 : + IsImported globals "ethereum.arrow_glacier.vm.precompiled_contracts.sha256" "sha256". + +(* At top_level_stmt: unsupported node type: AnnAssign *) diff --git a/CoqOfPython/ethereum/arrow_glacier/vm/precompiled_contracts/modexp.v b/CoqOfPython/ethereum/arrow_glacier/vm/precompiled_contracts/modexp.v new file mode 100644 index 0000000..df32505 --- /dev/null +++ b/CoqOfPython/ethereum/arrow_glacier/vm/precompiled_contracts/modexp.v @@ -0,0 +1,676 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.arrow_glacier.vm.precompiled_contracts.modexp". + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) MODEXP PRECOMPILED CONTRACT +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementation of the `MODEXP` precompiled contract. +". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_Bytes : + IsImported globals "ethereum.base_types" "Bytes". +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". + +Axiom ethereum_arrow_glacier_vm_imports_Evm : + IsImported globals "ethereum.arrow_glacier.vm" "Evm". + +Axiom ethereum_arrow_glacier_vm_gas_imports_charge_gas : + IsImported globals "ethereum.arrow_glacier.vm.gas" "charge_gas". + +Axiom ethereum_arrow_glacier_vm_memory_imports_buffer_read : + IsImported globals "ethereum.arrow_glacier.vm.memory" "buffer_read". + +Definition GQUADDIVISOR : Value.t := M.run ltac:(M.monadic ( + Constant.int 3 +)). + +Definition modexp : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Calculates `(base**exp) % modulus` for arbitrary sized `base`, `exp` and. + `modulus`. The return value is the same length as the modulus. + " in + let _ := M.assign_local (| + "data" , + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "data" |) + |) in + let _ := M.assign_local (| + "base_length" , + M.call (| + M.get_field (| M.get_name (| globals, "U256" |), "from_be_bytes" |), + make_list [ + M.call (| + M.get_name (| globals, "buffer_read" |), + make_list [ + M.get_name (| globals, "data" |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 32 + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "exp_length" , + M.call (| + M.get_field (| M.get_name (| globals, "U256" |), "from_be_bytes" |), + make_list [ + M.call (| + M.get_name (| globals, "buffer_read" |), + make_list [ + M.get_name (| globals, "data" |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 32 + ], + make_dict [] + |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 32 + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "modulus_length" , + M.call (| + M.get_field (| M.get_name (| globals, "U256" |), "from_be_bytes" |), + make_list [ + M.call (| + M.get_name (| globals, "buffer_read" |), + make_list [ + M.get_name (| globals, "data" |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 64 + ], + make_dict [] + |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 32 + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "exp_start" , + BinOp.add (| + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 96 + ], + make_dict [] + |), + M.get_name (| globals, "base_length" |) + |) + |) in + let _ := M.assign_local (| + "exp_head" , + M.call (| + M.get_field (| M.get_name (| globals, "Uint" |), "from_be_bytes" |), + make_list [ + M.call (| + M.get_name (| globals, "buffer_read" |), + make_list [ + M.get_name (| globals, "data" |); + M.get_name (| globals, "exp_start" |); + M.call (| + M.get_name (| globals, "min" |), + make_list [ + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 32 + ], + make_dict [] + |); + M.get_name (| globals, "exp_length" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.call (| + M.get_name (| globals, "gas_cost" |), + make_list [ + M.get_name (| globals, "base_length" |); + M.get_name (| globals, "modulus_length" |); + M.get_name (| globals, "exp_length" |); + M.get_name (| globals, "exp_head" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + BoolOp.and (| + Compare.eq (| + M.get_name (| globals, "base_length" |), + Constant.int 0 + |), + ltac:(M.monadic ( + Compare.eq (| + M.get_name (| globals, "modulus_length" |), + Constant.int 0 + |) + )) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign (| + M.get_field (| M.get_name (| globals, "evm" |), "output" |), + M.call (| + M.get_name (| globals, "Bytes" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.return_ (| + Constant.None_ + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "base" , + M.call (| + M.get_field (| M.get_name (| globals, "Uint" |), "from_be_bytes" |), + make_list [ + M.call (| + M.get_name (| globals, "buffer_read" |), + make_list [ + M.get_name (| globals, "data" |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 96 + ], + make_dict [] + |); + M.get_name (| globals, "base_length" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "exp" , + M.call (| + M.get_field (| M.get_name (| globals, "Uint" |), "from_be_bytes" |), + make_list [ + M.call (| + M.get_name (| globals, "buffer_read" |), + make_list [ + M.get_name (| globals, "data" |); + M.get_name (| globals, "exp_start" |); + M.get_name (| globals, "exp_length" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "modulus_start" , + BinOp.add (| + M.get_name (| globals, "exp_start" |), + M.get_name (| globals, "exp_length" |) + |) + |) in + let _ := M.assign_local (| + "modulus" , + M.call (| + M.get_field (| M.get_name (| globals, "Uint" |), "from_be_bytes" |), + make_list [ + M.call (| + M.get_name (| globals, "buffer_read" |), + make_list [ + M.get_name (| globals, "data" |); + M.get_name (| globals, "modulus_start" |); + M.get_name (| globals, "modulus_length" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, "modulus" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign (| + M.get_field (| M.get_name (| globals, "evm" |), "output" |), + BinOp.mult (| + M.call (| + M.get_name (| globals, "Bytes" |), + make_list [ + Constant.bytes "00" + ], + make_dict [] + |), + M.get_name (| globals, "modulus_length" |) + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign (| + M.get_field (| M.get_name (| globals, "evm" |), "output" |), + M.call (| + M.get_field (| M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, "pow" |), + make_list [ + M.get_name (| globals, "base" |); + M.get_name (| globals, "exp" |); + M.get_name (| globals, "modulus" |) + ], + make_dict [] + |) + ], + make_dict [] + |), "to_bytes" |), + make_list [ + M.get_name (| globals, "modulus_length" |); + Constant.str "big" + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_)). + +Definition complexity : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "base_length"; "modulus_length" ] |) in + let _ := Constant.str " + Estimate the complexity of performing a modular exponentiation. + + Parameters + ---------- + + base_length : + Length of the array representing the base integer. + + modulus_length : + Length of the array representing the modulus integer. + + Returns + ------- + + complexity : `Uint` + Complexity of performing the operation. + " in + let _ := M.assign_local (| + "max_length" , + M.call (| + M.get_name (| globals, "max" |), + make_list [ + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.get_name (| globals, "base_length" |) + ], + make_dict [] + |); + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.get_name (| globals, "modulus_length" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "words" , + BinOp.floor_div (| + BinOp.add (| + M.get_name (| globals, "max_length" |), + Constant.int 7 + |), + Constant.int 8 + |) + |) in + let _ := M.return_ (| + BinOp.pow (| + M.get_name (| globals, "words" |), + Constant.int 2 + |) + |) in + M.pure Constant.None_)). + +Definition iterations : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "exponent_length"; "exponent_head" ] |) in + let _ := Constant.str " + Calculate the number of iterations required to perform a modular + exponentiation. + + Parameters + ---------- + + exponent_length : + Length of the array representing the exponent integer. + + exponent_head : + First 32 bytes of the exponent (with leading zero padding if it is + shorter than 32 bytes), as an unsigned integer. + + Returns + ------- + + iterations : `Uint` + Number of iterations. + " in + let _ := + (* if *) + M.if_then_else (| + BoolOp.and (| + Compare.lt_e (| + M.get_name (| globals, "exponent_length" |), + Constant.int 32 + |), + ltac:(M.monadic ( + Compare.eq (| + M.get_name (| globals, "exponent_head" |), + Constant.int 0 + |) + )) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "count" , + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + Compare.lt_e (| + M.get_name (| globals, "exponent_length" |), + Constant.int 32 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "bit_length" , + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.call (| + M.get_field (| M.get_name (| globals, "exponent_head" |), "bit_length" |), + make_list [], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.gt (| + M.get_name (| globals, "bit_length" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_op_local (| + BinOp.sub, + "bit_length", + Constant.int 1 + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "count" , + M.get_name (| globals, "bit_length" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "length_part" , + BinOp.mult (| + Constant.int 8, + BinOp.sub (| + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.get_name (| globals, "exponent_length" |) + ], + make_dict [] + |), + Constant.int 32 + |) + |) + |) in + let _ := M.assign_local (| + "bits_part" , + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.call (| + M.get_field (| M.get_name (| globals, "exponent_head" |), "bit_length" |), + make_list [], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.gt (| + M.get_name (| globals, "bits_part" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_op_local (| + BinOp.sub, + "bits_part", + Constant.int 1 + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "count" , + BinOp.add (| + M.get_name (| globals, "length_part" |), + M.get_name (| globals, "bits_part" |) + |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )) |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, "max" |), + make_list [ + M.get_name (| globals, "count" |); + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 1 + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Definition gas_cost : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "base_length"; "modulus_length"; "exponent_length"; "exponent_head" ] |) in + let _ := Constant.str " + Calculate the gas cost of performing a modular exponentiation. + + Parameters + ---------- + + base_length : + Length of the array representing the base integer. + + modulus_length : + Length of the array representing the modulus integer. + + exponent_length : + Length of the array representing the exponent integer. + + exponent_head : + First 32 bytes of the exponent (with leading zero padding if it is + shorter than 32 bytes), as an unsigned integer. + + Returns + ------- + + gas_cost : `Uint` + Gas required for performing the operation. + " in + let _ := M.assign_local (| + "multiplication_complexity" , + M.call (| + M.get_name (| globals, "complexity" |), + make_list [ + M.get_name (| globals, "base_length" |); + M.get_name (| globals, "modulus_length" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "iteration_count" , + M.call (| + M.get_name (| globals, "iterations" |), + make_list [ + M.get_name (| globals, "exponent_length" |); + M.get_name (| globals, "exponent_head" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "cost" , + BinOp.mult (| + M.get_name (| globals, "multiplication_complexity" |), + M.get_name (| globals, "iteration_count" |) + |) + |) in + let _ := M.assign_op_local (| + BinOp.floor_div, + "cost", + M.get_name (| globals, "GQUADDIVISOR" |) + |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, "max" |), + make_list [ + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 200 + ], + make_dict [] + |); + M.get_name (| globals, "cost" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). diff --git a/CoqOfPython/ethereum/arrow_glacier/vm/precompiled_contracts/ripemd160.v b/CoqOfPython/ethereum/arrow_glacier/vm/precompiled_contracts/ripemd160.v new file mode 100644 index 0000000..cc2bc0a --- /dev/null +++ b/CoqOfPython/ethereum/arrow_glacier/vm/precompiled_contracts/ripemd160.v @@ -0,0 +1,125 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.arrow_glacier.vm.precompiled_contracts.ripemd160". + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) RIPEMD160 PRECOMPILED CONTRACT +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementation of the `RIPEMD160` precompiled contract. +". + +(* At top_level_stmt: unsupported node type: Import *) + +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". + +Axiom ethereum_utils_byte_imports_left_pad_zero_bytes : + IsImported globals "ethereum.utils.byte" "left_pad_zero_bytes". + +Axiom ethereum_utils_numeric_imports_ceil32 : + IsImported globals "ethereum.utils.numeric" "ceil32". + +Axiom ethereum_arrow_glacier_vm_imports_Evm : + IsImported globals "ethereum.arrow_glacier.vm" "Evm". + +Axiom ethereum_arrow_glacier_vm_gas_imports_GAS_RIPEMD160 : + IsImported globals "ethereum.arrow_glacier.vm.gas" "GAS_RIPEMD160". +Axiom ethereum_arrow_glacier_vm_gas_imports_GAS_RIPEMD160_WORD : + IsImported globals "ethereum.arrow_glacier.vm.gas" "GAS_RIPEMD160_WORD". +Axiom ethereum_arrow_glacier_vm_gas_imports_charge_gas : + IsImported globals "ethereum.arrow_glacier.vm.gas" "charge_gas". + +Definition ripemd160 : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Writes the ripemd160 hash to output. + + Parameters + ---------- + evm : + The current EVM frame. + " in + let _ := M.assign_local (| + "data" , + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "data" |) + |) in + let _ := M.assign_local (| + "word_count" , + BinOp.floor_div (| + M.call (| + M.get_name (| globals, "ceil32" |), + make_list [ + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_name (| globals, "data" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |), + Constant.int 32 + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + BinOp.add (| + M.get_name (| globals, "GAS_RIPEMD160" |), + BinOp.mult (| + M.get_name (| globals, "GAS_RIPEMD160_WORD" |), + M.get_name (| globals, "word_count" |) + |) + |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "hash_bytes" , + M.call (| + M.get_field (| M.call (| + M.get_field (| M.get_name (| globals, "hashlib" |), "new" |), + make_list [ + Constant.str "ripemd160"; + M.get_name (| globals, "data" |) + ], + make_dict [] + |), "digest" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "padded_hash" , + M.call (| + M.get_name (| globals, "left_pad_zero_bytes" |), + make_list [ + M.get_name (| globals, "hash_bytes" |); + Constant.int 32 + ], + make_dict [] + |) + |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, "evm" |), "output" |), + M.get_name (| globals, "padded_hash" |) + |) in + M.pure Constant.None_)). diff --git a/CoqOfPython/ethereum/arrow_glacier/vm/precompiled_contracts/sha256.v b/CoqOfPython/ethereum/arrow_glacier/vm/precompiled_contracts/sha256.v new file mode 100644 index 0000000..ce66ace --- /dev/null +++ b/CoqOfPython/ethereum/arrow_glacier/vm/precompiled_contracts/sha256.v @@ -0,0 +1,106 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.arrow_glacier.vm.precompiled_contracts.sha256". + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) SHA256 PRECOMPILED CONTRACT +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementation of the `SHA256` precompiled contract. +". + +(* At top_level_stmt: unsupported node type: Import *) + +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". + +Axiom ethereum_utils_numeric_imports_ceil32 : + IsImported globals "ethereum.utils.numeric" "ceil32". + +Axiom ethereum_arrow_glacier_vm_imports_Evm : + IsImported globals "ethereum.arrow_glacier.vm" "Evm". + +Axiom ethereum_arrow_glacier_vm_gas_imports_GAS_SHA256 : + IsImported globals "ethereum.arrow_glacier.vm.gas" "GAS_SHA256". +Axiom ethereum_arrow_glacier_vm_gas_imports_GAS_SHA256_WORD : + IsImported globals "ethereum.arrow_glacier.vm.gas" "GAS_SHA256_WORD". +Axiom ethereum_arrow_glacier_vm_gas_imports_charge_gas : + IsImported globals "ethereum.arrow_glacier.vm.gas" "charge_gas". + +Definition sha256 : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Writes the sha256 hash to output. + + Parameters + ---------- + evm : + The current EVM frame. + " in + let _ := M.assign_local (| + "data" , + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "data" |) + |) in + let _ := M.assign_local (| + "word_count" , + BinOp.floor_div (| + M.call (| + M.get_name (| globals, "ceil32" |), + make_list [ + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_name (| globals, "data" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |), + Constant.int 32 + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + BinOp.add (| + M.get_name (| globals, "GAS_SHA256" |), + BinOp.mult (| + M.get_name (| globals, "GAS_SHA256_WORD" |), + M.get_name (| globals, "word_count" |) + |) + |) + ], + make_dict [] + |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, "evm" |), "output" |), + M.call (| + M.get_field (| M.call (| + M.get_field (| M.get_name (| globals, "hashlib" |), "sha256" |), + make_list [ + M.get_name (| globals, "data" |) + ], + make_dict [] + |), "digest" |), + make_list [], + make_dict [] + |) + |) in + M.pure Constant.None_)). diff --git a/CoqOfPython/ethereum/arrow_glacier/vm/runtime.v b/CoqOfPython/ethereum/arrow_glacier/vm/runtime.v new file mode 100644 index 0000000..4e59678 --- /dev/null +++ b/CoqOfPython/ethereum/arrow_glacier/vm/runtime.v @@ -0,0 +1,157 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.arrow_glacier.vm.runtime". + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) Runtime Operations +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Runtime related operations used while executing EVM code. +". + +Axiom typing_imports_Set : + IsImported globals "typing" "Set". + +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". + +Axiom ethereum_arrow_glacier_vm_instructions_imports_Ops : + IsImported globals "ethereum.arrow_glacier.vm.instructions" "Ops". + +Definition get_valid_jump_destinations : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "code" ] |) in + let _ := Constant.str " + Analyze the evm code to obtain the set of valid jump destinations. + + Valid jump destinations are defined as follows: + * The jump destination is less than the length of the code. + * The jump destination should have the `JUMPDEST` opcode (0x5B). + * The jump destination shouldn't be part of the data corresponding to + `PUSH-N` opcodes. + + Note - Jump destinations are 0-indexed. + + Parameters + ---------- + code : + The EVM code which is to be executed. + + Returns + ------- + valid_jump_destinations: `Set[Uint]` + The set of valid jump destinations in the code. + " in + let _ := M.assign_local (| + "valid_jump_destinations" , + M.call (| + M.get_name (| globals, "set" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "pc" , + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + |) in + let _ := + M.while (| + Compare.lt (| + M.get_name (| globals, "pc" |), + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_name (| globals, "code" |) + ], + make_dict [] + |) + |), + ltac:(M.monadic ( +(* At stmt: unsupported node type: Try *) + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, "current_opcode" |), + M.get_field (| M.get_name (| globals, "Ops" |), "JUMPDEST" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_field (| M.get_name (| globals, "valid_jump_destinations" |), "add" |), + make_list [ + M.get_name (| globals, "pc" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + BoolOp.and (| + Compare.lt_e (| + M.get_field (| M.get_field (| M.get_name (| globals, "Ops" |), "PUSH1" |), "value" |), + M.get_field (| M.get_name (| globals, "current_opcode" |), "value" |) + |), + ltac:(M.monadic ( + Compare.lt_e (| + M.get_field (| M.get_name (| globals, "current_opcode" |), "value" |), + M.get_field (| M.get_field (| M.get_name (| globals, "Ops" |), "PUSH32" |), "value" |) + |) + )) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "push_data_size" , + BinOp.add (| + BinOp.sub (| + M.get_field (| M.get_name (| globals, "current_opcode" |), "value" |), + M.get_field (| M.get_field (| M.get_name (| globals, "Ops" |), "PUSH1" |), "value" |) + |), + Constant.int 1 + |) + |) in + let _ := M.assign_op_local (| + BinOp.add, + "pc", + M.get_name (| globals, "push_data_size" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )) |) in + let _ := M.assign_op_local (| + BinOp.add, + "pc", + Constant.int 1 + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := M.return_ (| + M.get_name (| globals, "valid_jump_destinations" |) + |) in + M.pure Constant.None_)). diff --git a/CoqOfPython/ethereum/arrow_glacier/vm/stack.v b/CoqOfPython/ethereum/arrow_glacier/vm/stack.v new file mode 100644 index 0000000..9258f93 --- /dev/null +++ b/CoqOfPython/ethereum/arrow_glacier/vm/stack.v @@ -0,0 +1,123 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.arrow_glacier.vm.stack". + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) Stack +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementation of the stack operators for the EVM. +". + +Axiom typing_imports_List : + IsImported globals "typing" "List". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". + +Axiom ethereum_arrow_glacier_vm_exceptions_imports_StackOverflowError : + IsImported globals "ethereum.arrow_glacier.vm.exceptions" "StackOverflowError". +Axiom ethereum_arrow_glacier_vm_exceptions_imports_StackUnderflowError : + IsImported globals "ethereum.arrow_glacier.vm.exceptions" "StackUnderflowError". + +Definition pop : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "stack" ] |) in + let _ := Constant.str " + Pops the top item off of `stack`. + + Parameters + ---------- + stack : + EVM stack. + + Returns + ------- + value : `U256` + The top element on the stack. + + " in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_name (| globals, "stack" |) + ], + make_dict [] + |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, "StackUnderflowError" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.return_ (| + M.call (| + M.get_field (| M.get_name (| globals, "stack" |), "pop" |), + make_list [], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Definition push : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "stack"; "value" ] |) in + let _ := Constant.str " + Pushes `value` onto `stack`. + + Parameters + ---------- + stack : + EVM stack. + + value : + Item to be pushed onto `stack`. + + " in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_name (| globals, "stack" |) + ], + make_dict [] + |), + Constant.int 1024 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, "StackOverflowError" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.return_ (| + M.call (| + M.get_field (| M.get_name (| globals, "stack" |), "append" |), + make_list [ + M.get_name (| globals, "value" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). diff --git a/CoqOfPython/ethereum/base_types.v b/CoqOfPython/ethereum/base_types.v index 66b442e..4229846 100644 --- a/CoqOfPython/ethereum/base_types.v +++ b/CoqOfPython/ethereum/base_types.v @@ -1,6 +1,6 @@ Require Import CoqOfPython.CoqOfPython. -Inductive globals : Set :=. +Definition globals : string := "ethereum.base_types". Definition expr_1 : Value.t := Constant.str " @@ -24,31 +24,29 @@ sequences containing an exact number of bytes. [`Bytes64`]: ref:ethereum.base_types.Bytes64 ". -Require dataclasses. -Axiom dataclasses_is_dataclass : - IsGlobalAlias globals dataclasses.globals "is_dataclass". -Axiom dataclasses_replace : - IsGlobalAlias globals dataclasses.globals "replace". +Axiom dataclasses_imports_is_dataclass : + IsImported globals "dataclasses" "is_dataclass". +Axiom dataclasses_imports_replace : + IsImported globals "dataclasses" "replace". -Require typing. -Axiom typing_Any : - IsGlobalAlias globals typing.globals "Any". -Axiom typing_Callable : - IsGlobalAlias globals typing.globals "Callable". -Axiom typing_ClassVar : - IsGlobalAlias globals typing.globals "ClassVar". -Axiom typing_Optional : - IsGlobalAlias globals typing.globals "Optional". -Axiom typing_Protocol : - IsGlobalAlias globals typing.globals "Protocol". -Axiom typing_Tuple : - IsGlobalAlias globals typing.globals "Tuple". -Axiom typing_Type_ : - IsGlobalAlias globals typing.globals "Type_". -Axiom typing_TypeVar : - IsGlobalAlias globals typing.globals "TypeVar". -Axiom typing_runtime_checkable : - IsGlobalAlias globals typing.globals "runtime_checkable". +Axiom typing_imports_Any : + IsImported globals "typing" "Any". +Axiom typing_imports_Callable : + IsImported globals "typing" "Callable". +Axiom typing_imports_ClassVar : + IsImported globals "typing" "ClassVar". +Axiom typing_imports_Optional : + IsImported globals "typing" "Optional". +Axiom typing_imports_Protocol : + IsImported globals "typing" "Protocol". +Axiom typing_imports_Tuple : + IsImported globals "typing" "Tuple". +Axiom typing_imports_Type : + IsImported globals "typing" "Type". +Axiom typing_imports_TypeVar : + IsImported globals "typing" "TypeVar". +Axiom typing_imports_runtime_checkable : + IsImported globals "typing" "runtime_checkable". Definition SlottedFreezable : Value.t := builtins.make_klass @@ -166,11 +164,11 @@ Definition Uint : Value.t := |) |), (* then *) ltac:(M.monadic ( - let _ := M.raise (| M.call (| + let _ := M.raise (| Some (M.call (| M.get_name (| globals, "TypeError" |), make_list [], make_dict [] - |) |) in + |)) |) in M.pure Constant.None_ (* else *) )), ltac:(M.monadic ( @@ -179,14 +177,17 @@ Definition Uint : Value.t := let _ := (* if *) M.if_then_else (| - Compare.lt (| M.get_name (| globals, "value" |), Constant.int 0 |), + Compare.lt (| + M.get_name (| globals, "value" |), + Constant.int 0 + |), (* then *) ltac:(M.monadic ( - let _ := M.raise (| M.call (| + let _ := M.raise (| Some (M.call (| M.get_name (| globals, "OverflowError" |), make_list [], make_dict [] - |) |) in + |)) |) in M.pure Constant.None_ (* else *) )), ltac:(M.monadic ( @@ -237,14 +238,17 @@ Definition Uint : Value.t := let _ := (* if *) M.if_then_else (| - Compare.lt (| M.get_name (| globals, "right" |), Constant.int 0 |), + Compare.lt (| + M.get_name (| globals, "right" |), + Constant.int 0 + |), (* then *) ltac:(M.monadic ( - let _ := M.raise (| M.call (| + let _ := M.raise (| Some (M.call (| M.get_name (| globals, "OverflowError" |), make_list [], make_dict [] - |) |) in + |)) |) in M.pure Constant.None_ (* else *) )), ltac:(M.monadic ( @@ -313,18 +317,24 @@ Definition Uint : Value.t := (* if *) M.if_then_else (| BoolOp.or (| - Compare.lt (| M.get_name (| globals, "right" |), Constant.int 0 |), + Compare.lt (| + M.get_name (| globals, "right" |), + Constant.int 0 + |), ltac:(M.monadic ( - Compare.lt (| M.get_name (| globals, "self" |), M.get_name (| globals, "right" |) |) + Compare.lt (| + M.get_name (| globals, "self" |), + M.get_name (| globals, "right" |) + |) )) |), (* then *) ltac:(M.monadic ( - let _ := M.raise (| M.call (| + let _ := M.raise (| Some (M.call (| M.get_name (| globals, "OverflowError" |), make_list [], make_dict [] - |) |) in + |)) |) in M.pure Constant.None_ (* else *) )), ltac:(M.monadic ( @@ -378,18 +388,24 @@ Definition Uint : Value.t := (* if *) M.if_then_else (| BoolOp.or (| - Compare.lt (| M.get_name (| globals, "left" |), Constant.int 0 |), + Compare.lt (| + M.get_name (| globals, "left" |), + Constant.int 0 + |), ltac:(M.monadic ( - Compare.gt (| M.get_name (| globals, "self" |), M.get_name (| globals, "left" |) |) + Compare.gt (| + M.get_name (| globals, "self" |), + M.get_name (| globals, "left" |) + |) )) |), (* then *) ltac:(M.monadic ( - let _ := M.raise (| M.call (| + let _ := M.raise (| Some (M.call (| M.get_name (| globals, "OverflowError" |), make_list [], make_dict [] - |) |) in + |)) |) in M.pure Constant.None_ (* else *) )), ltac:(M.monadic ( @@ -457,14 +473,17 @@ Definition Uint : Value.t := let _ := (* if *) M.if_then_else (| - Compare.lt (| M.get_name (| globals, "right" |), Constant.int 0 |), + Compare.lt (| + M.get_name (| globals, "right" |), + Constant.int 0 + |), (* then *) ltac:(M.monadic ( - let _ := M.raise (| M.call (| + let _ := M.raise (| Some (M.call (| M.get_name (| globals, "OverflowError" |), make_list [], make_dict [] - |) |) in + |)) |) in M.pure Constant.None_ (* else *) )), ltac:(M.monadic ( @@ -547,14 +566,17 @@ Definition Uint : Value.t := let _ := (* if *) M.if_then_else (| - Compare.lt (| M.get_name (| globals, "right" |), Constant.int 0 |), + Compare.lt (| + M.get_name (| globals, "right" |), + Constant.int 0 + |), (* then *) ltac:(M.monadic ( - let _ := M.raise (| M.call (| + let _ := M.raise (| Some (M.call (| M.get_name (| globals, "OverflowError" |), make_list [], make_dict [] - |) |) in + |)) |) in M.pure Constant.None_ (* else *) )), ltac:(M.monadic ( @@ -607,14 +629,17 @@ Definition Uint : Value.t := let _ := (* if *) M.if_then_else (| - Compare.lt (| M.get_name (| globals, "left" |), Constant.int 0 |), + Compare.lt (| + M.get_name (| globals, "left" |), + Constant.int 0 + |), (* then *) ltac:(M.monadic ( - let _ := M.raise (| M.call (| + let _ := M.raise (| Some (M.call (| M.get_name (| globals, "OverflowError" |), make_list [], make_dict [] - |) |) in + |)) |) in M.pure Constant.None_ (* else *) )), ltac:(M.monadic ( @@ -682,14 +707,17 @@ Definition Uint : Value.t := let _ := (* if *) M.if_then_else (| - Compare.lt (| M.get_name (| globals, "right" |), Constant.int 0 |), + Compare.lt (| + M.get_name (| globals, "right" |), + Constant.int 0 + |), (* then *) ltac:(M.monadic ( - let _ := M.raise (| M.call (| + let _ := M.raise (| Some (M.call (| M.get_name (| globals, "OverflowError" |), make_list [], make_dict [] - |) |) in + |)) |) in M.pure Constant.None_ (* else *) )), ltac:(M.monadic ( @@ -742,14 +770,17 @@ Definition Uint : Value.t := let _ := (* if *) M.if_then_else (| - Compare.lt (| M.get_name (| globals, "left" |), Constant.int 0 |), + Compare.lt (| + M.get_name (| globals, "left" |), + Constant.int 0 + |), (* then *) ltac:(M.monadic ( - let _ := M.raise (| M.call (| + let _ := M.raise (| Some (M.call (| M.get_name (| globals, "OverflowError" |), make_list [], make_dict [] - |) |) in + |)) |) in M.pure Constant.None_ (* else *) )), ltac:(M.monadic ( @@ -817,20 +848,24 @@ Definition Uint : Value.t := let _ := (* if *) M.if_then_else (| - Compare.lt (| M.get_name (| globals, "right" |), Constant.int 0 |), + Compare.lt (| + M.get_name (| globals, "right" |), + Constant.int 0 + |), (* then *) ltac:(M.monadic ( - let _ := M.raise (| M.call (| + let _ := M.raise (| Some (M.call (| M.get_name (| globals, "OverflowError" |), make_list [], make_dict [] - |) |) in + |)) |) in M.pure Constant.None_ (* else *) )), ltac:(M.monadic ( M.pure Constant.None_ )) |) in - let result := + let _ := M.assign_local (| + "result" , M.call (| M.get_field (| M.get_name (| globals, "int" |), "__divmod__" |), make_list [ @@ -838,20 +873,27 @@ Definition Uint : Value.t := M.get_name (| globals, "right" |) ], make_dict [] - |) in + |) + |) in let _ := M.return_ (| make_tuple [ M.call (| M.get_field (| M.get_name (| globals, "int" |), "__new__" |), make_list [ M.get_field (| M.get_name (| globals, "self" |), "__class__" |); - M.get_subscript (| M.get_name (| globals, "result" |), Constant.int 0 |) + M.get_subscript (| + M.get_name (| globals, "result" |), + Constant.int 0 + |) ], make_dict [] |); M.call (| M.get_field (| M.get_name (| globals, "int" |), "__new__" |), make_list [ M.get_field (| M.get_name (| globals, "self" |), "__class__" |); - M.get_subscript (| M.get_name (| globals, "result" |), Constant.int 1 |) + M.get_subscript (| + M.get_name (| globals, "result" |), + Constant.int 1 + |) ], make_dict [] |) ] @@ -886,20 +928,24 @@ Definition Uint : Value.t := let _ := (* if *) M.if_then_else (| - Compare.lt (| M.get_name (| globals, "left" |), Constant.int 0 |), + Compare.lt (| + M.get_name (| globals, "left" |), + Constant.int 0 + |), (* then *) ltac:(M.monadic ( - let _ := M.raise (| M.call (| + let _ := M.raise (| Some (M.call (| M.get_name (| globals, "OverflowError" |), make_list [], make_dict [] - |) |) in + |)) |) in M.pure Constant.None_ (* else *) )), ltac:(M.monadic ( M.pure Constant.None_ )) |) in - let result := + let _ := M.assign_local (| + "result" , M.call (| M.get_field (| M.get_name (| globals, "int" |), "__rdivmod__" |), make_list [ @@ -907,20 +953,27 @@ Definition Uint : Value.t := M.get_name (| globals, "left" |) ], make_dict [] - |) in + |) + |) in let _ := M.return_ (| make_tuple [ M.call (| M.get_field (| M.get_name (| globals, "int" |), "__new__" |), make_list [ M.get_field (| M.get_name (| globals, "self" |), "__class__" |); - M.get_subscript (| M.get_name (| globals, "result" |), Constant.int 0 |) + M.get_subscript (| + M.get_name (| globals, "result" |), + Constant.int 0 + |) ], make_dict [] |); M.call (| M.get_field (| M.get_name (| globals, "int" |), "__new__" |), make_list [ M.get_field (| M.get_name (| globals, "self" |), "__class__" |); - M.get_subscript (| M.get_name (| globals, "result" |), Constant.int 1 |) + M.get_subscript (| + M.get_name (| globals, "result" |), + Constant.int 1 + |) ], make_dict [] |) ] @@ -934,7 +987,10 @@ Definition Uint : Value.t := let _ := (* if *) M.if_then_else (| - Compare.is_not (| M.get_name (| globals, "modulo" |), Constant.None_ |), + Compare.is_not (| + M.get_name (| globals, "modulo" |), + Constant.None_ + |), (* then *) ltac:(M.monadic ( let _ := @@ -961,14 +1017,17 @@ Definition Uint : Value.t := let _ := (* if *) M.if_then_else (| - Compare.lt (| M.get_name (| globals, "modulo" |), Constant.int 0 |), + Compare.lt (| + M.get_name (| globals, "modulo" |), + Constant.int 0 + |), (* then *) ltac:(M.monadic ( - let _ := M.raise (| M.call (| + let _ := M.raise (| Some (M.call (| M.get_name (| globals, "OverflowError" |), make_list [], make_dict [] - |) |) in + |)) |) in M.pure Constant.None_ (* else *) )), ltac:(M.monadic ( @@ -1003,14 +1062,17 @@ Definition Uint : Value.t := let _ := (* if *) M.if_then_else (| - Compare.lt (| M.get_name (| globals, "right" |), Constant.int 0 |), + Compare.lt (| + M.get_name (| globals, "right" |), + Constant.int 0 + |), (* then *) ltac:(M.monadic ( - let _ := M.raise (| M.call (| + let _ := M.raise (| Some (M.call (| M.get_name (| globals, "OverflowError" |), make_list [], make_dict [] - |) |) in + |)) |) in M.pure Constant.None_ (* else *) )), ltac:(M.monadic ( @@ -1043,7 +1105,10 @@ Definition Uint : Value.t := let _ := (* if *) M.if_then_else (| - Compare.is_not (| M.get_name (| globals, "modulo" |), Constant.None_ |), + Compare.is_not (| + M.get_name (| globals, "modulo" |), + Constant.None_ + |), (* then *) ltac:(M.monadic ( let _ := @@ -1070,14 +1135,17 @@ Definition Uint : Value.t := let _ := (* if *) M.if_then_else (| - Compare.lt (| M.get_name (| globals, "modulo" |), Constant.int 0 |), + Compare.lt (| + M.get_name (| globals, "modulo" |), + Constant.int 0 + |), (* then *) ltac:(M.monadic ( - let _ := M.raise (| M.call (| + let _ := M.raise (| Some (M.call (| M.get_name (| globals, "OverflowError" |), make_list [], make_dict [] - |) |) in + |)) |) in M.pure Constant.None_ (* else *) )), ltac:(M.monadic ( @@ -1112,14 +1180,17 @@ Definition Uint : Value.t := let _ := (* if *) M.if_then_else (| - Compare.lt (| M.get_name (| globals, "left" |), Constant.int 0 |), + Compare.lt (| + M.get_name (| globals, "left" |), + Constant.int 0 + |), (* then *) ltac:(M.monadic ( - let _ := M.raise (| M.call (| + let _ := M.raise (| Some (M.call (| M.get_name (| globals, "OverflowError" |), make_list [], make_dict [] - |) |) in + |)) |) in M.pure Constant.None_ (* else *) )), ltac:(M.monadic ( @@ -1189,14 +1260,17 @@ Definition Uint : Value.t := let _ := (* if *) M.if_then_else (| - Compare.lt (| M.get_name (| globals, "right" |), Constant.int 0 |), + Compare.lt (| + M.get_name (| globals, "right" |), + Constant.int 0 + |), (* then *) ltac:(M.monadic ( - let _ := M.raise (| M.call (| + let _ := M.raise (| Some (M.call (| M.get_name (| globals, "OverflowError" |), make_list [], make_dict [] - |) |) in + |)) |) in M.pure Constant.None_ (* else *) )), ltac:(M.monadic ( @@ -1249,14 +1323,17 @@ Definition Uint : Value.t := let _ := (* if *) M.if_then_else (| - Compare.lt (| M.get_name (| globals, "left" |), Constant.int 0 |), + Compare.lt (| + M.get_name (| globals, "left" |), + Constant.int 0 + |), (* then *) ltac:(M.monadic ( - let _ := M.raise (| M.call (| + let _ := M.raise (| Some (M.call (| M.get_name (| globals, "OverflowError" |), make_list [], make_dict [] - |) |) in + |)) |) in M.pure Constant.None_ (* else *) )), ltac:(M.monadic ( @@ -1330,20 +1407,24 @@ Definition Uint : Value.t := Converts this arbitrarily sized unsigned integer into its big endian representation, without padding. " in - let bit_length := + let _ := M.assign_local (| + "bit_length" , M.call (| M.get_field (| M.get_name (| globals, "self" |), "bit_length" |), make_list [], make_dict [] - |) in - let byte_length := + |) + |) in + let _ := M.assign_local (| + "byte_length" , BinOp.floor_div (| BinOp.add (| M.get_name (| globals, "bit_length" |), Constant.int 7 |), Constant.int 8 - |) in + |) + |) in let _ := M.return_ (| M.call (| M.get_field (| M.get_name (| globals, "self" |), "to_bytes" |), @@ -1367,23 +1448,30 @@ Definition Uint : Value.t := let _ := (* if *) M.if_then_else (| - Compare.is (| M.get_name (| globals, "number_bytes" |), Constant.None_ |), + Compare.is (| + M.get_name (| globals, "number_bytes" |), + Constant.None_ + |), (* then *) ltac:(M.monadic ( - let bit_length := + let _ := M.assign_local (| + "bit_length" , M.call (| M.get_field (| M.get_name (| globals, "self" |), "bit_length" |), make_list [], make_dict [] - |) in - let number_bytes := + |) + |) in + let _ := M.assign_local (| + "number_bytes" , BinOp.floor_div (| BinOp.add (| M.get_name (| globals, "bit_length" |), Constant.int 7 |), Constant.int 8 - |) in + |) + |) in M.pure Constant.None_ (* else *) )), ltac:(M.monadic ( @@ -1437,11 +1525,11 @@ Definition FixedUint : Value.t := |) |), (* then *) ltac:(M.monadic ( - let _ := M.raise (| M.call (| + let _ := M.raise (| Some (M.call (| M.get_name (| globals, "TypeError" |), make_list [], make_dict [] - |) |) in + |)) |) in M.pure Constant.None_ (* else *) )), ltac:(M.monadic ( @@ -1451,18 +1539,24 @@ Definition FixedUint : Value.t := (* if *) M.if_then_else (| BoolOp.or (| - Compare.lt (| M.get_name (| globals, "value" |), Constant.int 0 |), + Compare.lt (| + M.get_name (| globals, "value" |), + Constant.int 0 + |), ltac:(M.monadic ( - Compare.gt (| M.get_name (| globals, "value" |), M.get_field (| M.get_name (| globals, "self" |), "MAX_VALUE" |) |) + Compare.gt (| + M.get_name (| globals, "value" |), + M.get_field (| M.get_name (| globals, "self" |), "MAX_VALUE" |) + |) )) |), (* then *) ltac:(M.monadic ( - let _ := M.raise (| M.call (| + let _ := M.raise (| Some (M.call (| M.get_name (| globals, "OverflowError" |), make_list [], make_dict [] - |) |) in + |)) |) in M.pure Constant.None_ (* else *) )), ltac:(M.monadic ( @@ -1510,7 +1604,8 @@ Definition FixedUint : Value.t := )), ltac:(M.monadic ( M.pure Constant.None_ )) |) in - let result := + let _ := M.assign_local (| + "result" , M.call (| M.get_field (| M.get_name (| globals, "int" |), "__add__" |), make_list [ @@ -1518,23 +1613,30 @@ Definition FixedUint : Value.t := M.get_name (| globals, "right" |) ], make_dict [] - |) in + |) + |) in let _ := (* if *) M.if_then_else (| BoolOp.or (| - Compare.lt (| M.get_name (| globals, "right" |), Constant.int 0 |), + Compare.lt (| + M.get_name (| globals, "right" |), + Constant.int 0 + |), ltac:(M.monadic ( - Compare.gt (| M.get_name (| globals, "result" |), M.get_field (| M.get_name (| globals, "self" |), "MAX_VALUE" |) |) + Compare.gt (| + M.get_name (| globals, "result" |), + M.get_field (| M.get_name (| globals, "self" |), "MAX_VALUE" |) + |) )) |), (* then *) ltac:(M.monadic ( - let _ := M.raise (| M.call (| + let _ := M.raise (| Some (M.call (| M.get_name (| globals, "OverflowError" |), make_list [], make_dict [] - |) |) in + |)) |) in M.pure Constant.None_ (* else *) )), ltac:(M.monadic ( @@ -1590,18 +1692,24 @@ Definition FixedUint : Value.t := (* if *) M.if_then_else (| BoolOp.or (| - Compare.lt (| M.get_name (| globals, "right" |), Constant.int 0 |), + Compare.lt (| + M.get_name (| globals, "right" |), + Constant.int 0 + |), ltac:(M.monadic ( - Compare.gt (| M.get_name (| globals, "right" |), M.get_field (| M.get_name (| globals, "self" |), "MAX_VALUE" |) |) + Compare.gt (| + M.get_name (| globals, "right" |), + M.get_field (| M.get_name (| globals, "self" |), "MAX_VALUE" |) + |) )) |), (* then *) ltac:(M.monadic ( - let _ := M.raise (| M.call (| + let _ := M.raise (| Some (M.call (| M.get_name (| globals, "OverflowError" |), make_list [], make_dict [] - |) |) in + |)) |) in M.pure Constant.None_ (* else *) )), ltac:(M.monadic ( @@ -1673,23 +1781,32 @@ Definition FixedUint : Value.t := (* if *) M.if_then_else (| BoolOp.or (| - Compare.lt (| M.get_name (| globals, "right" |), Constant.int 0 |), + Compare.lt (| + M.get_name (| globals, "right" |), + Constant.int 0 + |), ltac:(M.monadic ( BoolOp.or (| - Compare.gt (| M.get_name (| globals, "right" |), M.get_field (| M.get_name (| globals, "self" |), "MAX_VALUE" |) |), + Compare.gt (| + M.get_name (| globals, "right" |), + M.get_field (| M.get_name (| globals, "self" |), "MAX_VALUE" |) + |), ltac:(M.monadic ( - Compare.lt (| M.get_name (| globals, "self" |), M.get_name (| globals, "right" |) |) + Compare.lt (| + M.get_name (| globals, "self" |), + M.get_name (| globals, "right" |) + |) )) |) )) |), (* then *) ltac:(M.monadic ( - let _ := M.raise (| M.call (| + let _ := M.raise (| Some (M.call (| M.get_name (| globals, "OverflowError" |), make_list [], make_dict [] - |) |) in + |)) |) in M.pure Constant.None_ (* else *) )), ltac:(M.monadic ( @@ -1752,18 +1869,24 @@ Definition FixedUint : Value.t := (* if *) M.if_then_else (| BoolOp.or (| - Compare.lt (| M.get_name (| globals, "right" |), Constant.int 0 |), + Compare.lt (| + M.get_name (| globals, "right" |), + Constant.int 0 + |), ltac:(M.monadic ( - Compare.gt (| M.get_name (| globals, "right" |), M.get_field (| M.get_name (| globals, "self" |), "MAX_VALUE" |) |) + Compare.gt (| + M.get_name (| globals, "right" |), + M.get_field (| M.get_name (| globals, "self" |), "MAX_VALUE" |) + |) )) |), (* then *) ltac:(M.monadic ( - let _ := M.raise (| M.call (| + let _ := M.raise (| Some (M.call (| M.get_name (| globals, "OverflowError" |), make_list [], make_dict [] - |) |) in + |)) |) in M.pure Constant.None_ (* else *) )), ltac:(M.monadic ( @@ -1820,23 +1943,32 @@ Definition FixedUint : Value.t := (* if *) M.if_then_else (| BoolOp.or (| - Compare.lt (| M.get_name (| globals, "left" |), Constant.int 0 |), + Compare.lt (| + M.get_name (| globals, "left" |), + Constant.int 0 + |), ltac:(M.monadic ( BoolOp.or (| - Compare.gt (| M.get_name (| globals, "left" |), M.get_field (| M.get_name (| globals, "self" |), "MAX_VALUE" |) |), + Compare.gt (| + M.get_name (| globals, "left" |), + M.get_field (| M.get_name (| globals, "self" |), "MAX_VALUE" |) + |), ltac:(M.monadic ( - Compare.gt (| M.get_name (| globals, "self" |), M.get_name (| globals, "left" |) |) + Compare.gt (| + M.get_name (| globals, "self" |), + M.get_name (| globals, "left" |) + |) )) |) )) |), (* then *) ltac:(M.monadic ( - let _ := M.raise (| M.call (| + let _ := M.raise (| Some (M.call (| M.get_name (| globals, "OverflowError" |), make_list [], make_dict [] - |) |) in + |)) |) in M.pure Constant.None_ (* else *) )), ltac:(M.monadic ( @@ -1901,7 +2033,8 @@ Definition FixedUint : Value.t := )), ltac:(M.monadic ( M.pure Constant.None_ )) |) in - let result := + let _ := M.assign_local (| + "result" , M.call (| M.get_field (| M.get_name (| globals, "int" |), "__mul__" |), make_list [ @@ -1909,23 +2042,30 @@ Definition FixedUint : Value.t := M.get_name (| globals, "right" |) ], make_dict [] - |) in + |) + |) in let _ := (* if *) M.if_then_else (| BoolOp.or (| - Compare.lt (| M.get_name (| globals, "right" |), Constant.int 0 |), + Compare.lt (| + M.get_name (| globals, "right" |), + Constant.int 0 + |), ltac:(M.monadic ( - Compare.gt (| M.get_name (| globals, "result" |), M.get_field (| M.get_name (| globals, "self" |), "MAX_VALUE" |) |) + Compare.gt (| + M.get_name (| globals, "result" |), + M.get_field (| M.get_name (| globals, "self" |), "MAX_VALUE" |) + |) )) |), (* then *) ltac:(M.monadic ( - let _ := M.raise (| M.call (| + let _ := M.raise (| Some (M.call (| M.get_name (| globals, "OverflowError" |), make_list [], make_dict [] - |) |) in + |)) |) in M.pure Constant.None_ (* else *) )), ltac:(M.monadic ( @@ -1981,18 +2121,24 @@ Definition FixedUint : Value.t := (* if *) M.if_then_else (| BoolOp.or (| - Compare.lt (| M.get_name (| globals, "right" |), Constant.int 0 |), + Compare.lt (| + M.get_name (| globals, "right" |), + Constant.int 0 + |), ltac:(M.monadic ( - Compare.gt (| M.get_name (| globals, "right" |), M.get_field (| M.get_name (| globals, "self" |), "MAX_VALUE" |) |) + Compare.gt (| + M.get_name (| globals, "right" |), + M.get_field (| M.get_name (| globals, "self" |), "MAX_VALUE" |) + |) )) |), (* then *) ltac:(M.monadic ( - let _ := M.raise (| M.call (| + let _ := M.raise (| Some (M.call (| M.get_name (| globals, "OverflowError" |), make_list [], make_dict [] - |) |) in + |)) |) in M.pure Constant.None_ (* else *) )), ltac:(M.monadic ( @@ -2079,18 +2225,24 @@ Definition FixedUint : Value.t := (* if *) M.if_then_else (| BoolOp.or (| - Compare.lt (| M.get_name (| globals, "right" |), Constant.int 0 |), + Compare.lt (| + M.get_name (| globals, "right" |), + Constant.int 0 + |), ltac:(M.monadic ( - Compare.gt (| M.get_name (| globals, "right" |), M.get_field (| M.get_name (| globals, "self" |), "MAX_VALUE" |) |) + Compare.gt (| + M.get_name (| globals, "right" |), + M.get_field (| M.get_name (| globals, "self" |), "MAX_VALUE" |) + |) )) |), (* then *) ltac:(M.monadic ( - let _ := M.raise (| M.call (| + let _ := M.raise (| Some (M.call (| M.get_name (| globals, "OverflowError" |), make_list [], make_dict [] - |) |) in + |)) |) in M.pure Constant.None_ (* else *) )), ltac:(M.monadic ( @@ -2144,18 +2296,24 @@ Definition FixedUint : Value.t := (* if *) M.if_then_else (| BoolOp.or (| - Compare.lt (| M.get_name (| globals, "left" |), Constant.int 0 |), + Compare.lt (| + M.get_name (| globals, "left" |), + Constant.int 0 + |), ltac:(M.monadic ( - Compare.gt (| M.get_name (| globals, "left" |), M.get_field (| M.get_name (| globals, "self" |), "MAX_VALUE" |) |) + Compare.gt (| + M.get_name (| globals, "left" |), + M.get_field (| M.get_name (| globals, "self" |), "MAX_VALUE" |) + |) )) |), (* then *) ltac:(M.monadic ( - let _ := M.raise (| M.call (| + let _ := M.raise (| Some (M.call (| M.get_name (| globals, "OverflowError" |), make_list [], make_dict [] - |) |) in + |)) |) in M.pure Constant.None_ (* else *) )), ltac:(M.monadic ( @@ -2224,18 +2382,24 @@ Definition FixedUint : Value.t := (* if *) M.if_then_else (| BoolOp.or (| - Compare.lt (| M.get_name (| globals, "right" |), Constant.int 0 |), + Compare.lt (| + M.get_name (| globals, "right" |), + Constant.int 0 + |), ltac:(M.monadic ( - Compare.gt (| M.get_name (| globals, "right" |), M.get_field (| M.get_name (| globals, "self" |), "MAX_VALUE" |) |) + Compare.gt (| + M.get_name (| globals, "right" |), + M.get_field (| M.get_name (| globals, "self" |), "MAX_VALUE" |) + |) )) |), (* then *) ltac:(M.monadic ( - let _ := M.raise (| M.call (| + let _ := M.raise (| Some (M.call (| M.get_name (| globals, "OverflowError" |), make_list [], make_dict [] - |) |) in + |)) |) in M.pure Constant.None_ (* else *) )), ltac:(M.monadic ( @@ -2289,18 +2453,24 @@ Definition FixedUint : Value.t := (* if *) M.if_then_else (| BoolOp.or (| - Compare.lt (| M.get_name (| globals, "left" |), Constant.int 0 |), + Compare.lt (| + M.get_name (| globals, "left" |), + Constant.int 0 + |), ltac:(M.monadic ( - Compare.gt (| M.get_name (| globals, "left" |), M.get_field (| M.get_name (| globals, "self" |), "MAX_VALUE" |) |) + Compare.gt (| + M.get_name (| globals, "left" |), + M.get_field (| M.get_name (| globals, "self" |), "MAX_VALUE" |) + |) )) |), (* then *) ltac:(M.monadic ( - let _ := M.raise (| M.call (| + let _ := M.raise (| Some (M.call (| M.get_name (| globals, "OverflowError" |), make_list [], make_dict [] - |) |) in + |)) |) in M.pure Constant.None_ (* else *) )), ltac:(M.monadic ( @@ -2369,24 +2539,31 @@ Definition FixedUint : Value.t := (* if *) M.if_then_else (| BoolOp.or (| - Compare.lt (| M.get_name (| globals, "right" |), Constant.int 0 |), + Compare.lt (| + M.get_name (| globals, "right" |), + Constant.int 0 + |), ltac:(M.monadic ( - Compare.gt (| M.get_name (| globals, "right" |), M.get_field (| M.get_name (| globals, "self" |), "MAX_VALUE" |) |) + Compare.gt (| + M.get_name (| globals, "right" |), + M.get_field (| M.get_name (| globals, "self" |), "MAX_VALUE" |) + |) )) |), (* then *) ltac:(M.monadic ( - let _ := M.raise (| M.call (| + let _ := M.raise (| Some (M.call (| M.get_name (| globals, "OverflowError" |), make_list [], make_dict [] - |) |) in + |)) |) in M.pure Constant.None_ (* else *) )), ltac:(M.monadic ( M.pure Constant.None_ )) |) in - let result := + let _ := M.assign_local (| + "result" , M.call (| M.get_field (| M.call (| M.get_name (| globals, "super" |), @@ -2400,20 +2577,27 @@ Definition FixedUint : Value.t := M.get_name (| globals, "right" |) ], make_dict [] - |) in + |) + |) in let _ := M.return_ (| make_tuple [ M.call (| M.get_field (| M.get_name (| globals, "int" |), "__new__" |), make_list [ M.get_field (| M.get_name (| globals, "self" |), "__class__" |); - M.get_subscript (| M.get_name (| globals, "result" |), Constant.int 0 |) + M.get_subscript (| + M.get_name (| globals, "result" |), + Constant.int 0 + |) ], make_dict [] |); M.call (| M.get_field (| M.get_name (| globals, "int" |), "__new__" |), make_list [ M.get_field (| M.get_name (| globals, "self" |), "__class__" |); - M.get_subscript (| M.get_name (| globals, "result" |), Constant.int 1 |) + M.get_subscript (| + M.get_name (| globals, "result" |), + Constant.int 1 + |) ], make_dict [] |) ] @@ -2449,24 +2633,31 @@ Definition FixedUint : Value.t := (* if *) M.if_then_else (| BoolOp.or (| - Compare.lt (| M.get_name (| globals, "left" |), Constant.int 0 |), + Compare.lt (| + M.get_name (| globals, "left" |), + Constant.int 0 + |), ltac:(M.monadic ( - Compare.gt (| M.get_name (| globals, "left" |), M.get_field (| M.get_name (| globals, "self" |), "MAX_VALUE" |) |) + Compare.gt (| + M.get_name (| globals, "left" |), + M.get_field (| M.get_name (| globals, "self" |), "MAX_VALUE" |) + |) )) |), (* then *) ltac:(M.monadic ( - let _ := M.raise (| M.call (| + let _ := M.raise (| Some (M.call (| M.get_name (| globals, "OverflowError" |), make_list [], make_dict [] - |) |) in + |)) |) in M.pure Constant.None_ (* else *) )), ltac:(M.monadic ( M.pure Constant.None_ )) |) in - let result := + let _ := M.assign_local (| + "result" , M.call (| M.get_field (| M.call (| M.get_name (| globals, "super" |), @@ -2480,20 +2671,27 @@ Definition FixedUint : Value.t := M.get_name (| globals, "left" |) ], make_dict [] - |) in + |) + |) in let _ := M.return_ (| make_tuple [ M.call (| M.get_field (| M.get_name (| globals, "int" |), "__new__" |), make_list [ M.get_field (| M.get_name (| globals, "self" |), "__class__" |); - M.get_subscript (| M.get_name (| globals, "result" |), Constant.int 0 |) + M.get_subscript (| + M.get_name (| globals, "result" |), + Constant.int 0 + |) ], make_dict [] |); M.call (| M.get_field (| M.get_name (| globals, "int" |), "__new__" |), make_list [ M.get_field (| M.get_name (| globals, "self" |), "__class__" |); - M.get_subscript (| M.get_name (| globals, "result" |), Constant.int 1 |) + M.get_subscript (| + M.get_name (| globals, "result" |), + Constant.int 1 + |) ], make_dict [] |) ] @@ -2507,7 +2705,10 @@ Definition FixedUint : Value.t := let _ := (* if *) M.if_then_else (| - Compare.is_not (| M.get_name (| globals, "modulo" |), Constant.None_ |), + Compare.is_not (| + M.get_name (| globals, "modulo" |), + Constant.None_ + |), (* then *) ltac:(M.monadic ( let _ := @@ -2535,18 +2736,24 @@ Definition FixedUint : Value.t := (* if *) M.if_then_else (| BoolOp.or (| - Compare.lt (| M.get_name (| globals, "modulo" |), Constant.int 0 |), + Compare.lt (| + M.get_name (| globals, "modulo" |), + Constant.int 0 + |), ltac:(M.monadic ( - Compare.gt (| M.get_name (| globals, "modulo" |), M.get_field (| M.get_name (| globals, "self" |), "MAX_VALUE" |) |) + Compare.gt (| + M.get_name (| globals, "modulo" |), + M.get_field (| M.get_name (| globals, "self" |), "MAX_VALUE" |) + |) )) |), (* then *) ltac:(M.monadic ( - let _ := M.raise (| M.call (| + let _ := M.raise (| Some (M.call (| M.get_name (| globals, "OverflowError" |), make_list [], make_dict [] - |) |) in + |)) |) in M.pure Constant.None_ (* else *) )), ltac:(M.monadic ( @@ -2578,7 +2785,8 @@ Definition FixedUint : Value.t := )), ltac:(M.monadic ( M.pure Constant.None_ )) |) in - let result := + let _ := M.assign_local (| + "result" , M.call (| M.get_field (| M.get_name (| globals, "int" |), "__pow__" |), make_list [ @@ -2587,28 +2795,38 @@ Definition FixedUint : Value.t := M.get_name (| globals, "modulo" |) ], make_dict [] - |) in + |) + |) in let _ := (* if *) M.if_then_else (| BoolOp.or (| - Compare.lt (| M.get_name (| globals, "right" |), Constant.int 0 |), + Compare.lt (| + M.get_name (| globals, "right" |), + Constant.int 0 + |), ltac:(M.monadic ( BoolOp.or (| - Compare.gt (| M.get_name (| globals, "right" |), M.get_field (| M.get_name (| globals, "self" |), "MAX_VALUE" |) |), + Compare.gt (| + M.get_name (| globals, "right" |), + M.get_field (| M.get_name (| globals, "self" |), "MAX_VALUE" |) + |), ltac:(M.monadic ( - Compare.gt (| M.get_name (| globals, "result" |), M.get_field (| M.get_name (| globals, "self" |), "MAX_VALUE" |) |) + Compare.gt (| + M.get_name (| globals, "result" |), + M.get_field (| M.get_name (| globals, "self" |), "MAX_VALUE" |) + |) )) |) )) |), (* then *) ltac:(M.monadic ( - let _ := M.raise (| M.call (| + let _ := M.raise (| Some (M.call (| M.get_name (| globals, "OverflowError" |), make_list [], make_dict [] - |) |) in + |)) |) in M.pure Constant.None_ (* else *) )), ltac:(M.monadic ( @@ -2644,7 +2862,10 @@ Definition FixedUint : Value.t := let _ := (* if *) M.if_then_else (| - Compare.is_not (| M.get_name (| globals, "modulo" |), Constant.None_ |), + Compare.is_not (| + M.get_name (| globals, "modulo" |), + Constant.None_ + |), (* then *) ltac:(M.monadic ( let _ := @@ -2672,18 +2893,24 @@ Definition FixedUint : Value.t := (* if *) M.if_then_else (| BoolOp.or (| - Compare.lt (| M.get_name (| globals, "modulo" |), Constant.int 0 |), + Compare.lt (| + M.get_name (| globals, "modulo" |), + Constant.int 0 + |), ltac:(M.monadic ( - Compare.gt (| M.get_name (| globals, "modulo" |), M.get_field (| M.get_name (| globals, "self" |), "MAX_VALUE" |) |) + Compare.gt (| + M.get_name (| globals, "modulo" |), + M.get_field (| M.get_name (| globals, "self" |), "MAX_VALUE" |) + |) )) |), (* then *) ltac:(M.monadic ( - let _ := M.raise (| M.call (| + let _ := M.raise (| Some (M.call (| M.get_name (| globals, "OverflowError" |), make_list [], make_dict [] - |) |) in + |)) |) in M.pure Constant.None_ (* else *) )), ltac:(M.monadic ( @@ -2719,18 +2946,24 @@ Definition FixedUint : Value.t := (* if *) M.if_then_else (| BoolOp.or (| - Compare.lt (| M.get_name (| globals, "right" |), Constant.int 0 |), + Compare.lt (| + M.get_name (| globals, "right" |), + Constant.int 0 + |), ltac:(M.monadic ( - Compare.gt (| M.get_name (| globals, "right" |), M.get_field (| M.get_name (| globals, "self" |), "MAX_VALUE" |) |) + Compare.gt (| + M.get_name (| globals, "right" |), + M.get_field (| M.get_name (| globals, "self" |), "MAX_VALUE" |) + |) )) |), (* then *) ltac:(M.monadic ( - let _ := M.raise (| M.call (| + let _ := M.raise (| Some (M.call (| M.get_name (| globals, "OverflowError" |), make_list [], make_dict [] - |) |) in + |)) |) in M.pure Constant.None_ (* else *) )), ltac:(M.monadic ( @@ -2766,7 +2999,10 @@ Definition FixedUint : Value.t := let _ := (* if *) M.if_then_else (| - Compare.is_not (| M.get_name (| globals, "modulo" |), Constant.None_ |), + Compare.is_not (| + M.get_name (| globals, "modulo" |), + Constant.None_ + |), (* then *) ltac:(M.monadic ( let _ := @@ -2794,18 +3030,24 @@ Definition FixedUint : Value.t := (* if *) M.if_then_else (| BoolOp.or (| - Compare.lt (| M.get_name (| globals, "modulo" |), Constant.int 0 |), + Compare.lt (| + M.get_name (| globals, "modulo" |), + Constant.int 0 + |), ltac:(M.monadic ( - Compare.gt (| M.get_name (| globals, "modulo" |), M.get_field (| M.get_name (| globals, "self" |), "MAX_VALUE" |) |) + Compare.gt (| + M.get_name (| globals, "modulo" |), + M.get_field (| M.get_name (| globals, "self" |), "MAX_VALUE" |) + |) )) |), (* then *) ltac:(M.monadic ( - let _ := M.raise (| M.call (| + let _ := M.raise (| Some (M.call (| M.get_name (| globals, "OverflowError" |), make_list [], make_dict [] - |) |) in + |)) |) in M.pure Constant.None_ (* else *) )), ltac:(M.monadic ( @@ -2841,18 +3083,24 @@ Definition FixedUint : Value.t := (* if *) M.if_then_else (| BoolOp.or (| - Compare.lt (| M.get_name (| globals, "left" |), Constant.int 0 |), + Compare.lt (| + M.get_name (| globals, "left" |), + Constant.int 0 + |), ltac:(M.monadic ( - Compare.gt (| M.get_name (| globals, "left" |), M.get_field (| M.get_name (| globals, "self" |), "MAX_VALUE" |) |) + Compare.gt (| + M.get_name (| globals, "left" |), + M.get_field (| M.get_name (| globals, "self" |), "MAX_VALUE" |) + |) )) |), (* then *) ltac:(M.monadic ( - let _ := M.raise (| M.call (| + let _ := M.raise (| Some (M.call (| M.get_name (| globals, "OverflowError" |), make_list [], make_dict [] - |) |) in + |)) |) in M.pure Constant.None_ (* else *) )), ltac:(M.monadic ( @@ -2923,18 +3171,24 @@ Definition FixedUint : Value.t := (* if *) M.if_then_else (| BoolOp.or (| - Compare.lt (| M.get_name (| globals, "right" |), Constant.int 0 |), + Compare.lt (| + M.get_name (| globals, "right" |), + Constant.int 0 + |), ltac:(M.monadic ( - Compare.gt (| M.get_name (| globals, "right" |), M.get_field (| M.get_name (| globals, "self" |), "MAX_VALUE" |) |) + Compare.gt (| + M.get_name (| globals, "right" |), + M.get_field (| M.get_name (| globals, "self" |), "MAX_VALUE" |) + |) )) |), (* then *) ltac:(M.monadic ( - let _ := M.raise (| M.call (| + let _ := M.raise (| Some (M.call (| M.get_name (| globals, "OverflowError" |), make_list [], make_dict [] - |) |) in + |)) |) in M.pure Constant.None_ (* else *) )), ltac:(M.monadic ( @@ -2988,18 +3242,24 @@ Definition FixedUint : Value.t := (* if *) M.if_then_else (| BoolOp.or (| - Compare.lt (| M.get_name (| globals, "right" |), Constant.int 0 |), + Compare.lt (| + M.get_name (| globals, "right" |), + Constant.int 0 + |), ltac:(M.monadic ( - Compare.gt (| M.get_name (| globals, "right" |), M.get_field (| M.get_name (| globals, "self" |), "MAX_VALUE" |) |) + Compare.gt (| + M.get_name (| globals, "right" |), + M.get_field (| M.get_name (| globals, "self" |), "MAX_VALUE" |) + |) )) |), (* then *) ltac:(M.monadic ( - let _ := M.raise (| M.call (| + let _ := M.raise (| Some (M.call (| M.get_name (| globals, "OverflowError" |), make_list [], make_dict [] - |) |) in + |)) |) in M.pure Constant.None_ (* else *) )), ltac:(M.monadic ( @@ -3053,18 +3313,24 @@ Definition FixedUint : Value.t := (* if *) M.if_then_else (| BoolOp.or (| - Compare.lt (| M.get_name (| globals, "right" |), Constant.int 0 |), + Compare.lt (| + M.get_name (| globals, "right" |), + Constant.int 0 + |), ltac:(M.monadic ( - Compare.gt (| M.get_name (| globals, "right" |), M.get_field (| M.get_name (| globals, "self" |), "MAX_VALUE" |) |) + Compare.gt (| + M.get_name (| globals, "right" |), + M.get_field (| M.get_name (| globals, "self" |), "MAX_VALUE" |) + |) )) |), (* then *) ltac:(M.monadic ( - let _ := M.raise (| M.call (| + let _ := M.raise (| Some (M.call (| M.get_name (| globals, "OverflowError" |), make_list [], make_dict [] - |) |) in + |)) |) in M.pure Constant.None_ (* else *) )), ltac:(M.monadic ( @@ -3118,18 +3384,24 @@ Definition FixedUint : Value.t := (* if *) M.if_then_else (| BoolOp.or (| - Compare.lt (| M.get_name (| globals, "left" |), Constant.int 0 |), + Compare.lt (| + M.get_name (| globals, "left" |), + Constant.int 0 + |), ltac:(M.monadic ( - Compare.gt (| M.get_name (| globals, "left" |), M.get_field (| M.get_name (| globals, "self" |), "MAX_VALUE" |) |) + Compare.gt (| + M.get_name (| globals, "left" |), + M.get_field (| M.get_name (| globals, "self" |), "MAX_VALUE" |) + |) )) |), (* then *) ltac:(M.monadic ( - let _ := M.raise (| M.call (| + let _ := M.raise (| Some (M.call (| M.get_name (| globals, "OverflowError" |), make_list [], make_dict [] - |) |) in + |)) |) in M.pure Constant.None_ (* else *) )), ltac:(M.monadic ( @@ -3246,20 +3518,24 @@ Definition FixedUint : Value.t := Converts this unsigned integer into its big endian representation, omitting leading zero bytes. " in - let bit_length := + let _ := M.assign_local (| + "bit_length" , M.call (| M.get_field (| M.get_name (| globals, "self" |), "bit_length" |), make_list [], make_dict [] - |) in - let byte_length := + |) + |) in + let _ := M.assign_local (| + "byte_length" , BinOp.floor_div (| BinOp.add (| M.get_name (| globals, "bit_length" |), Constant.int 7 |), Constant.int 8 - |) in + |) + |) in let _ := M.return_ (| M.call (| M.get_field (| M.get_name (| globals, "self" |), "to_bytes" |), @@ -3289,20 +3565,23 @@ Definition U256 : Value.t := let _ := (* if *) M.if_then_else (| - Compare.gt (| M.call (| - M.get_name (| globals, "len" |), - make_list [ - M.get_name (| globals, "buffer" |) - ], - make_dict [] - |), Constant.int 32 |), + Compare.gt (| + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_name (| globals, "buffer" |) + ], + make_dict [] + |), + Constant.int 32 + |), (* then *) ltac:(M.monadic ( - let _ := M.raise (| M.call (| + let _ := M.raise (| Some (M.call (| M.get_name (| globals, "ValueError" |), make_list [], make_dict [] - |) |) in + |)) |) in M.pure Constant.None_ (* else *) )), ltac:(M.monadic ( @@ -3337,7 +3616,10 @@ Definition U256 : Value.t := let _ := (* if *) M.if_then_else (| - Compare.gt_e (| M.get_name (| globals, "value" |), Constant.int 0 |), + Compare.gt_e (| + M.get_name (| globals, "value" |), + Constant.int 0 + |), (* then *) ltac:(M.monadic ( let _ := M.return_ (| @@ -3406,11 +3688,14 @@ Definition U256 : Value.t := let _ := (* if *) M.if_then_else (| - Compare.lt (| M.call (| - M.get_field (| M.get_name (| globals, "self" |), "bit_length" |), - make_list [], - make_dict [] - |), Constant.int 256 |), + Compare.lt (| + M.call (| + M.get_field (| M.get_name (| globals, "self" |), "bit_length" |), + make_list [], + make_dict [] + |), + Constant.int 256 + |), (* then *) ltac:(M.monadic ( let _ := M.return_ (| @@ -3460,20 +3745,23 @@ Definition U32 : Value.t := let _ := (* if *) M.if_then_else (| - Compare.gt (| M.call (| - M.get_name (| globals, "len" |), - make_list [ - M.get_name (| globals, "buffer" |) - ], - make_dict [] - |), Constant.int 4 |), + Compare.gt (| + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_name (| globals, "buffer" |) + ], + make_dict [] + |), + Constant.int 4 + |), (* then *) ltac:(M.monadic ( - let _ := M.raise (| M.call (| + let _ := M.raise (| Some (M.call (| M.get_name (| globals, "ValueError" |), make_list [], make_dict [] - |) |) in + |)) |) in M.pure Constant.None_ (* else *) )), ltac:(M.monadic ( @@ -3533,20 +3821,24 @@ Definition U32 : Value.t := Converts this fixed sized unsigned integer into its little endian representation, in the fewest bytes possible. " in - let bit_length := + let _ := M.assign_local (| + "bit_length" , M.call (| M.get_field (| M.get_name (| globals, "self" |), "bit_length" |), make_list [], make_dict [] - |) in - let byte_length := + |) + |) in + let _ := M.assign_local (| + "byte_length" , BinOp.floor_div (| BinOp.add (| M.get_name (| globals, "bit_length" |), Constant.int 7 |), Constant.int 8 - |) in + |) + |) in let _ := M.return_ (| M.call (| M.get_field (| M.get_name (| globals, "self" |), "to_bytes" |), @@ -3578,20 +3870,23 @@ Definition U64 : Value.t := let _ := (* if *) M.if_then_else (| - Compare.gt (| M.call (| - M.get_name (| globals, "len" |), - make_list [ - M.get_name (| globals, "buffer" |) - ], - make_dict [] - |), Constant.int 8 |), + Compare.gt (| + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_name (| globals, "buffer" |) + ], + make_dict [] + |), + Constant.int 8 + |), (* then *) ltac:(M.monadic ( - let _ := M.raise (| M.call (| + let _ := M.raise (| Some (M.call (| M.get_name (| globals, "ValueError" |), make_list [], make_dict [] - |) |) in + |)) |) in M.pure Constant.None_ (* else *) )), ltac:(M.monadic ( @@ -3626,20 +3921,23 @@ Definition U64 : Value.t := let _ := (* if *) M.if_then_else (| - Compare.gt (| M.call (| - M.get_name (| globals, "len" |), - make_list [ - M.get_name (| globals, "buffer" |) - ], - make_dict [] - |), Constant.int 8 |), + Compare.gt (| + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_name (| globals, "buffer" |) + ], + make_dict [] + |), + Constant.int 8 + |), (* then *) ltac:(M.monadic ( - let _ := M.raise (| M.call (| + let _ := M.raise (| Some (M.call (| M.get_name (| globals, "ValueError" |), make_list [], make_dict [] - |) |) in + |)) |) in M.pure Constant.None_ (* else *) )), ltac:(M.monadic ( @@ -3699,20 +3997,24 @@ Definition U64 : Value.t := Converts this fixed sized unsigned integer into its little endian representation, in the fewest bytes possible. " in - let bit_length := + let _ := M.assign_local (| + "bit_length" , M.call (| M.get_field (| M.get_name (| globals, "self" |), "bit_length" |), make_list [], make_dict [] - |) in - let byte_length := + |) + |) in + let _ := M.assign_local (| + "byte_length" , BinOp.floor_div (| BinOp.add (| M.get_name (| globals, "bit_length" |), Constant.int 7 |), Constant.int 8 - |) in + |) + |) in let _ := M.return_ (| M.call (| M.get_field (| M.get_name (| globals, "self" |), "to_bytes" |), @@ -3753,22 +4055,8 @@ Definition FixedBytes : Value.t := let _ := Constant.str " Create a new instance, ensuring the result has the correct length. " in - let x := - make_list_concat (| [ - make_list [ - Constant.int 1; - Constant.int 2 - ]; - make_list [ - Constant.str "x"; - Constant.str "y"; - Constant.str "z" - ]; - make_list [ - Constant.int 3 - ] - ] |) in - let result := + let _ := M.assign_local (| + "result" , M.call (| M.get_field (| M.call (| M.get_name (| globals, "super" |), @@ -3785,26 +4073,30 @@ Definition FixedBytes : Value.t := M.get_name (| globals, "args" |) ] |), make_dict [] - |) in + |) + |) in let _ := (* if *) M.if_then_else (| - Compare.not_eq (| M.call (| - M.get_name (| globals, "len" |), - make_list [ - M.get_name (| globals, "result" |) - ], - make_dict [] - |), M.get_field (| M.get_name (| globals, "cls" |), "LENGTH" |) |), + Compare.not_eq (| + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_name (| globals, "result" |) + ], + make_dict [] + |), + M.get_field (| M.get_name (| globals, "cls" |), "LENGTH" |) + |), (* then *) ltac:(M.monadic ( - let _ := M.raise (| M.call (| + let _ := M.raise (| Some (M.call (| M.get_name (| globals, "ValueError" |), make_list [ - (* At expr: unsupported node type: JoinedStr *) + Constant.str "(* At expr: unsupported node type: JoinedStr *)" ], make_dict [] - |) |) in + |)) |) in M.pure Constant.None_ (* else *) )), ltac:(M.monadic ( @@ -3901,7 +4193,7 @@ Definition Bytes : Value.t := M.run ltac:(M.monadic ( M.get_name (| globals, "bytes" |) )). -Definition expr_926 : Value.t := +Definition expr_925 : Value.t := Constant.str " Sequence of bytes (octets) of arbitrary length. ". @@ -3923,13 +4215,13 @@ Definition _setattr_function : Value.t -> Value.t -> M := |), (* then *) ltac:(M.monadic ( - let _ := M.raise (| M.call (| + let _ := M.raise (| Some (M.call (| M.get_name (| globals, "Exception" |), make_list [ Constant.str "Mutating frozen dataclasses is not allowed." ], make_dict [] - |) |) in + |)) |) in M.pure Constant.None_ (* else *) )), ltac:(M.monadic ( @@ -3955,13 +4247,13 @@ Definition _delattr_function : Value.t -> Value.t -> M := M.get_field (| M.get_name (| globals, "self" |), "_frozen" |), (* then *) ltac:(M.monadic ( - let _ := M.raise (| M.call (| + let _ := M.raise (| Some (M.call (| M.get_name (| globals, "Exception" |), make_list [ Constant.str "Mutating frozen dataclasses is not allowed." ], make_dict [] - |) |) in + |)) |) in M.pure Constant.None_ (* else *) )), ltac:(M.monadic ( @@ -4086,14 +4378,16 @@ Definition modify : Value.t -> Value.t -> M := ], make_dict [] |) |) in - let new_obj := + let _ := M.assign_local (| + "new_obj" , M.call (| M.get_name (| globals, "replace" |), make_list [ M.get_name (| globals, "obj" |) ], make_dict [] - |) in + |) + |) in let _ := M.call (| M.get_name (| globals, "f" |), make_list [ diff --git a/CoqOfPython/ethereum/berlin/__init__.v b/CoqOfPython/ethereum/berlin/__init__.v new file mode 100644 index 0000000..9616412 --- /dev/null +++ b/CoqOfPython/ethereum/berlin/__init__.v @@ -0,0 +1,23 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.berlin.__init__". + +Definition expr_1 : Value.t := + Constant.str " +The Berlin fork adjusts the gas costs of the `ModExp` precompile and several +state access EVM instructions, introduces typed transaction envelopes along +with the first new transaction type—optional access lists. +". + +Axiom ethereum_fork_criteria_imports_ByBlockNumber : + IsImported globals "ethereum.fork_criteria" "ByBlockNumber". + +Definition FORK_CRITERIA : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "ByBlockNumber" |), + make_list [ + Constant.int 12244000 + ], + make_dict [] + |) +)). diff --git a/CoqOfPython/ethereum/berlin/blocks.v b/CoqOfPython/ethereum/berlin/blocks.v new file mode 100644 index 0000000..8ab9689 --- /dev/null +++ b/CoqOfPython/ethereum/berlin/blocks.v @@ -0,0 +1,89 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.berlin.blocks". + +Definition expr_1 : Value.t := + Constant.str " +A `Block` is a single link in the chain that is Ethereum. Each `Block` contains +a `Header` and zero or more transactions. Each `Header` contains associated +metadata like the block number, parent block hash, and how much gas was +consumed by its transactions. + +Together, these blocks form a cryptographically secure journal recording the +history of all state transitions that have happened since the genesis of the +chain. +". + +Axiom dataclasses_imports_dataclass : + IsImported globals "dataclasses" "dataclass". + +Axiom typing_imports_Tuple : + IsImported globals "typing" "Tuple". +Axiom typing_imports_Union : + IsImported globals "typing" "Union". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_Bytes : + IsImported globals "ethereum.base_types" "Bytes". +Axiom ethereum_base_types_imports_Bytes8 : + IsImported globals "ethereum.base_types" "Bytes8". +Axiom ethereum_base_types_imports_Bytes32 : + IsImported globals "ethereum.base_types" "Bytes32". +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". +Axiom ethereum_base_types_imports_slotted_freezable : + IsImported globals "ethereum.base_types" "slotted_freezable". + +Axiom ethereum_crypto_hash_imports_Hash32 : + IsImported globals "ethereum.crypto.hash" "Hash32". + +Axiom ethereum_berlin_fork_types_imports_Address : + IsImported globals "ethereum.berlin.fork_types" "Address". +Axiom ethereum_berlin_fork_types_imports_Bloom : + IsImported globals "ethereum.berlin.fork_types" "Bloom". +Axiom ethereum_berlin_fork_types_imports_Root : + IsImported globals "ethereum.berlin.fork_types" "Root". + +Axiom ethereum_berlin_transactions_imports_LegacyTransaction : + IsImported globals "ethereum.berlin.transactions" "LegacyTransaction". + +Definition Header : Value.t := + builtins.make_klass + [] + [ + + ] + [ + + ]. + +Definition Block : Value.t := + builtins.make_klass + [] + [ + + ] + [ + + ]. + +Definition Log : Value.t := + builtins.make_klass + [] + [ + + ] + [ + + ]. + +Definition Receipt : Value.t := + builtins.make_klass + [] + [ + + ] + [ + + ]. diff --git a/CoqOfPython/ethereum/berlin/bloom.v b/CoqOfPython/ethereum/berlin/bloom.v new file mode 100644 index 0000000..a94f117 --- /dev/null +++ b/CoqOfPython/ethereum/berlin/bloom.v @@ -0,0 +1,207 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.berlin.bloom". + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Logs Bloom +^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +This modules defines functions for calculating bloom filters of logs. For the +general theory of bloom filters see e.g. `Wikipedia +`_. Bloom filters are used to allow +for efficient searching of logs by address and/or topic, by rapidly +eliminating blocks and receipts from their search. +". + +Axiom typing_imports_Tuple : + IsImported globals "typing" "Tuple". + +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". + +Axiom ethereum_crypto_hash_imports_keccak256 : + IsImported globals "ethereum.crypto.hash" "keccak256". + +Axiom ethereum_berlin_blocks_imports_Log : + IsImported globals "ethereum.berlin.blocks" "Log". + +Axiom ethereum_berlin_fork_types_imports_Bloom : + IsImported globals "ethereum.berlin.fork_types" "Bloom". + +Definition add_to_bloom : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "bloom"; "bloom_entry" ] |) in + let _ := Constant.str " + Add a bloom entry to the bloom filter (`bloom`). + + The number of hash functions used is 3. They are calculated by taking the + least significant 11 bits from the first 3 16-bit words of the + `keccak_256()` hash of `bloom_entry`. + + Parameters + ---------- + bloom : + The bloom filter. + bloom_entry : + An entry which is to be added to bloom filter. + " in + let _ := M.assign_local (| + "hash" , + M.call (| + M.get_name (| globals, "keccak256" |), + make_list [ + M.get_name (| globals, "bloom_entry" |) + ], + make_dict [] + |) + |) in + let _ := + M.for_ (| + M.get_name (| globals, "idx" |), + make_tuple [ Constant.int 0; Constant.int 2; Constant.int 4 ], + ltac:(M.monadic ( + let _ := M.assign_local (| + "bit_to_set" , + BinOp.bit_and (| + M.call (| + M.get_field (| M.get_name (| globals, "Uint" |), "from_be_bytes" |), + make_list [ + M.slice (| + M.get_name (| globals, "hash" |), + M.get_name (| globals, "idx" |), + BinOp.add (| + M.get_name (| globals, "idx" |), + Constant.int 2 + |), + Constant.None_ + |) + ], + make_dict [] + |), + Constant.int 2047 + |) + |) in + let _ := M.assign_local (| + "bit_index" , + BinOp.sub (| + Constant.int 2047, + M.get_name (| globals, "bit_to_set" |) + |) + |) in + let _ := M.assign_local (| + "byte_index" , + BinOp.floor_div (| + M.get_name (| globals, "bit_index" |), + Constant.int 8 + |) + |) in + let _ := M.assign_local (| + "bit_value" , + BinOp.l_shift (| + Constant.int 1, + BinOp.sub (| + Constant.int 7, + BinOp.mod_ (| + M.get_name (| globals, "bit_index" |), + Constant.int 8 + |) + |) + |) + |) in + let _ := M.assign (| + M.get_subscript (| + M.get_name (| globals, "bloom" |), + M.get_name (| globals, "byte_index" |) + |), + BinOp.bit_or (| + M.get_subscript (| + M.get_name (| globals, "bloom" |), + M.get_name (| globals, "byte_index" |) + |), + M.get_name (| globals, "bit_value" |) + |) + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + M.pure Constant.None_)). + +Definition logs_bloom : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "logs" ] |) in + let _ := Constant.str " + Obtain the logs bloom from a list of log entries. + + The address and each topic of a log are added to the bloom filter. + + Parameters + ---------- + logs : + List of logs for which the logs bloom is to be obtained. + + Returns + ------- + logs_bloom : `Bloom` + The logs bloom obtained which is 256 bytes with some bits set as per + the caller address and the log topics. + " in +(* At stmt: unsupported node type: AnnAssign *) + let _ := + M.for_ (| + M.get_name (| globals, "log" |), + M.get_name (| globals, "logs" |), + ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, "add_to_bloom" |), + make_list [ + M.get_name (| globals, "bloom" |); + M.get_field (| M.get_name (| globals, "log" |), "address" |) + ], + make_dict [] + |) in + let _ := + M.for_ (| + M.get_name (| globals, "topic" |), + M.get_field (| M.get_name (| globals, "log" |), "topics" |), + ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, "add_to_bloom" |), + make_list [ + M.get_name (| globals, "bloom" |); + M.get_name (| globals, "topic" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, "Bloom" |), + make_list [ + M.get_name (| globals, "bloom" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). diff --git a/CoqOfPython/ethereum/berlin/fork.v b/CoqOfPython/ethereum/berlin/fork.v new file mode 100644 index 0000000..3a85cfb --- /dev/null +++ b/CoqOfPython/ethereum/berlin/fork.v @@ -0,0 +1,2932 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.berlin.fork". + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Specification +^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Entry point for the Ethereum specification. +". + +Axiom dataclasses_imports_dataclass : + IsImported globals "dataclasses" "dataclass". + +Axiom typing_imports_List : + IsImported globals "typing" "List". +Axiom typing_imports_Optional : + IsImported globals "typing" "Optional". +Axiom typing_imports_Set : + IsImported globals "typing" "Set". +Axiom typing_imports_Tuple : + IsImported globals "typing" "Tuple". +Axiom typing_imports_Union : + IsImported globals "typing" "Union". + +Axiom ethereum_base_types_imports_Bytes0 : + IsImported globals "ethereum.base_types" "Bytes0". + +Axiom ethereum_crypto_elliptic_curve_imports_SECP256K1N : + IsImported globals "ethereum.crypto.elliptic_curve" "SECP256K1N". +Axiom ethereum_crypto_elliptic_curve_imports_secp256k1_recover : + IsImported globals "ethereum.crypto.elliptic_curve" "secp256k1_recover". + +Axiom ethereum_crypto_hash_imports_Hash32 : + IsImported globals "ethereum.crypto.hash" "Hash32". +Axiom ethereum_crypto_hash_imports_keccak256 : + IsImported globals "ethereum.crypto.hash" "keccak256". + +Axiom ethereum_ethash_imports_dataset_size : + IsImported globals "ethereum.ethash" "dataset_size". +Axiom ethereum_ethash_imports_generate_cache : + IsImported globals "ethereum.ethash" "generate_cache". +Axiom ethereum_ethash_imports_hashimoto_light : + IsImported globals "ethereum.ethash" "hashimoto_light". + +Axiom ethereum_exceptions_imports_InvalidBlock : + IsImported globals "ethereum.exceptions" "InvalidBlock". + +Axiom ethereum_utils_ensure_imports_ensure : + IsImported globals "ethereum.utils.ensure" "ensure". + +Axiom ethereum_imports_rlp : + IsImported globals "ethereum" "rlp". + +Axiom ethereum_base_types_imports_U64 : + IsImported globals "ethereum.base_types" "U64". +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_U256_CEIL_VALUE : + IsImported globals "ethereum.base_types" "U256_CEIL_VALUE". +Axiom ethereum_base_types_imports_Bytes : + IsImported globals "ethereum.base_types" "Bytes". +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". + +Axiom ethereum_berlin_imports_vm : + IsImported globals "ethereum.berlin" "vm". + +Axiom ethereum_berlin_blocks_imports_Block : + IsImported globals "ethereum.berlin.blocks" "Block". +Axiom ethereum_berlin_blocks_imports_Header : + IsImported globals "ethereum.berlin.blocks" "Header". +Axiom ethereum_berlin_blocks_imports_Log : + IsImported globals "ethereum.berlin.blocks" "Log". +Axiom ethereum_berlin_blocks_imports_Receipt : + IsImported globals "ethereum.berlin.blocks" "Receipt". + +Axiom ethereum_berlin_bloom_imports_logs_bloom : + IsImported globals "ethereum.berlin.bloom" "logs_bloom". + +Axiom ethereum_berlin_fork_types_imports_Address : + IsImported globals "ethereum.berlin.fork_types" "Address". +Axiom ethereum_berlin_fork_types_imports_Bloom : + IsImported globals "ethereum.berlin.fork_types" "Bloom". +Axiom ethereum_berlin_fork_types_imports_Root : + IsImported globals "ethereum.berlin.fork_types" "Root". + +Axiom ethereum_berlin_state_imports_State : + IsImported globals "ethereum.berlin.state" "State". +Axiom ethereum_berlin_state_imports_account_exists_and_is_empty : + IsImported globals "ethereum.berlin.state" "account_exists_and_is_empty". +Axiom ethereum_berlin_state_imports_create_ether : + IsImported globals "ethereum.berlin.state" "create_ether". +Axiom ethereum_berlin_state_imports_destroy_account : + IsImported globals "ethereum.berlin.state" "destroy_account". +Axiom ethereum_berlin_state_imports_get_account : + IsImported globals "ethereum.berlin.state" "get_account". +Axiom ethereum_berlin_state_imports_increment_nonce : + IsImported globals "ethereum.berlin.state" "increment_nonce". +Axiom ethereum_berlin_state_imports_set_account_balance : + IsImported globals "ethereum.berlin.state" "set_account_balance". +Axiom ethereum_berlin_state_imports_state_root : + IsImported globals "ethereum.berlin.state" "state_root". + +Axiom ethereum_berlin_transactions_imports_TX_ACCESS_LIST_ADDRESS_COST : + IsImported globals "ethereum.berlin.transactions" "TX_ACCESS_LIST_ADDRESS_COST". +Axiom ethereum_berlin_transactions_imports_TX_ACCESS_LIST_STORAGE_KEY_COST : + IsImported globals "ethereum.berlin.transactions" "TX_ACCESS_LIST_STORAGE_KEY_COST". +Axiom ethereum_berlin_transactions_imports_TX_BASE_COST : + IsImported globals "ethereum.berlin.transactions" "TX_BASE_COST". +Axiom ethereum_berlin_transactions_imports_TX_CREATE_COST : + IsImported globals "ethereum.berlin.transactions" "TX_CREATE_COST". +Axiom ethereum_berlin_transactions_imports_TX_DATA_COST_PER_NON_ZERO : + IsImported globals "ethereum.berlin.transactions" "TX_DATA_COST_PER_NON_ZERO". +Axiom ethereum_berlin_transactions_imports_TX_DATA_COST_PER_ZERO : + IsImported globals "ethereum.berlin.transactions" "TX_DATA_COST_PER_ZERO". +Axiom ethereum_berlin_transactions_imports_AccessListTransaction : + IsImported globals "ethereum.berlin.transactions" "AccessListTransaction". +Axiom ethereum_berlin_transactions_imports_LegacyTransaction : + IsImported globals "ethereum.berlin.transactions" "LegacyTransaction". +Axiom ethereum_berlin_transactions_imports_Transaction : + IsImported globals "ethereum.berlin.transactions" "Transaction". +Axiom ethereum_berlin_transactions_imports_decode_transaction : + IsImported globals "ethereum.berlin.transactions" "decode_transaction". +Axiom ethereum_berlin_transactions_imports_encode_transaction : + IsImported globals "ethereum.berlin.transactions" "encode_transaction". + +Axiom ethereum_berlin_trie_imports_Trie : + IsImported globals "ethereum.berlin.trie" "Trie". +Axiom ethereum_berlin_trie_imports_root : + IsImported globals "ethereum.berlin.trie" "root". +Axiom ethereum_berlin_trie_imports_trie_set : + IsImported globals "ethereum.berlin.trie" "trie_set". + +Axiom ethereum_berlin_utils_message_imports_prepare_message : + IsImported globals "ethereum.berlin.utils.message" "prepare_message". + +Axiom ethereum_berlin_vm_interpreter_imports_process_message_call : + IsImported globals "ethereum.berlin.vm.interpreter" "process_message_call". + +Definition BLOCK_REWARD : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + BinOp.mult (| + Constant.int 2, + BinOp.pow (| + Constant.int 10, + Constant.int 18 + |) + |) + ], + make_dict [] + |) +)). + +Definition GAS_LIMIT_ADJUSTMENT_FACTOR : Value.t := M.run ltac:(M.monadic ( + Constant.int 1024 +)). + +Definition GAS_LIMIT_MINIMUM : Value.t := M.run ltac:(M.monadic ( + Constant.int 5000 +)). + +Definition MINIMUM_DIFFICULTY : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 131072 + ], + make_dict [] + |) +)). + +Definition MAX_OMMER_DEPTH : Value.t := M.run ltac:(M.monadic ( + Constant.int 6 +)). + +Definition BOMB_DELAY_BLOCKS : Value.t := M.run ltac:(M.monadic ( + Constant.int 9000000 +)). + +Definition EMPTY_OMMER_HASH : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "keccak256" |), + make_list [ + M.call (| + M.get_field (| M.get_name (| globals, "rlp" |), "encode" |), + make_list [ + make_list [] + ], + make_dict [] + |) + ], + make_dict [] + |) +)). + +Definition BlockChain : Value.t := + builtins.make_klass + [] + [ + + ] + [ + + ]. + +Definition apply_fork : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "old" ] |) in + let _ := Constant.str " + Transforms the state from the previous hard fork (`old`) into the block + chain object for this hard fork and returns it. + + When forks need to implement an irregular state transition, this function + is used to handle the irregularity. See the :ref:`DAO Fork ` for + an example. + + Parameters + ---------- + old : + Previous block chain object. + + Returns + ------- + new : `BlockChain` + Upgraded block chain object for this hard fork. + " in + let _ := M.return_ (| + M.get_name (| globals, "old" |) + |) in + M.pure Constant.None_)). + +Definition get_last_256_block_hashes : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "chain" ] |) in + let _ := Constant.str " + Obtain the list of hashes of the previous 256 blocks in order of + increasing block number. + + This function will return less hashes for the first 256 blocks. + + The ``BLOCKHASH`` opcode needs to access the latest hashes on the chain, + therefore this function retrieves them. + + Parameters + ---------- + chain : + History and current state. + + Returns + ------- + recent_block_hashes : `List[Hash32]` + Hashes of the recent 256 blocks in order of increasing block number. + " in + let _ := M.assign_local (| + "recent_blocks" , + M.slice (| + M.get_field (| M.get_name (| globals, "chain" |), "blocks" |), + UnOp.sub (| Constant.int 255 |), + Constant.None_, + Constant.None_ + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_name (| globals, "recent_blocks" |) + ], + make_dict [] + |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + make_list [] + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "recent_block_hashes" , + make_list [] + |) in + let _ := + M.for_ (| + M.get_name (| globals, "block" |), + M.get_name (| globals, "recent_blocks" |), + ltac:(M.monadic ( + let _ := M.assign_local (| + "prev_block_hash" , + M.get_field (| M.get_field (| M.get_name (| globals, "block" |), "header" |), "parent_hash" |) + |) in + let _ := M.call (| + M.get_field (| M.get_name (| globals, "recent_block_hashes" |), "append" |), + make_list [ + M.get_name (| globals, "prev_block_hash" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := M.assign_local (| + "most_recent_block_hash" , + M.call (| + M.get_name (| globals, "keccak256" |), + make_list [ + M.call (| + M.get_field (| M.get_name (| globals, "rlp" |), "encode" |), + make_list [ + M.get_field (| M.get_subscript (| + M.get_name (| globals, "recent_blocks" |), + UnOp.sub (| Constant.int 1 |) + |), "header" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_field (| M.get_name (| globals, "recent_block_hashes" |), "append" |), + make_list [ + M.get_name (| globals, "most_recent_block_hash" |) + ], + make_dict [] + |) in + let _ := M.return_ (| + M.get_name (| globals, "recent_block_hashes" |) + |) in + M.pure Constant.None_)). + +Definition state_transition : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "chain"; "block" ] |) in + let _ := Constant.str " + Attempts to apply a block to an existing block chain. + + All parts of the block's contents need to be verified before being added + to the chain. Blocks are verified by ensuring that the contents of the + block make logical sense with the contents of the parent block. The + information in the block's header must also match the corresponding + information in the block. + + To implement Ethereum, in theory clients are only required to store the + most recent 255 blocks of the chain since as far as execution is + concerned, only those blocks are accessed. Practically, however, clients + should store more blocks to handle reorgs. + + Parameters + ---------- + chain : + History and current state. + block : + Block to apply to `chain`. + " in + let _ := M.assign_local (| + "parent_header" , + M.get_field (| M.get_subscript (| + M.get_field (| M.get_name (| globals, "chain" |), "blocks" |), + UnOp.sub (| Constant.int 1 |) + |), "header" |) + |) in + let _ := M.call (| + M.get_name (| globals, "validate_header" |), + make_list [ + M.get_field (| M.get_name (| globals, "block" |), "header" |); + M.get_name (| globals, "parent_header" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "validate_ommers" |), + make_list [ + M.get_field (| M.get_name (| globals, "block" |), "ommers" |); + M.get_field (| M.get_name (| globals, "block" |), "header" |); + M.get_name (| globals, "chain" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "apply_body_output" , + M.call (| + M.get_name (| globals, "apply_body" |), + make_list [ + M.get_field (| M.get_name (| globals, "chain" |), "state" |); + M.call (| + M.get_name (| globals, "get_last_256_block_hashes" |), + make_list [ + M.get_name (| globals, "chain" |) + ], + make_dict [] + |); + M.get_field (| M.get_field (| M.get_name (| globals, "block" |), "header" |), "coinbase" |); + M.get_field (| M.get_field (| M.get_name (| globals, "block" |), "header" |), "number" |); + M.get_field (| M.get_field (| M.get_name (| globals, "block" |), "header" |), "gas_limit" |); + M.get_field (| M.get_field (| M.get_name (| globals, "block" |), "header" |), "timestamp" |); + M.get_field (| M.get_field (| M.get_name (| globals, "block" |), "header" |), "difficulty" |); + M.get_field (| M.get_name (| globals, "block" |), "transactions" |); + M.get_field (| M.get_name (| globals, "block" |), "ommers" |); + M.get_field (| M.get_name (| globals, "chain" |), "chain_id" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + Compare.eq (| + M.get_field (| M.get_name (| globals, "apply_body_output" |), "block_gas_used" |), + M.get_field (| M.get_field (| M.get_name (| globals, "block" |), "header" |), "gas_used" |) + |); + M.get_name (| globals, "InvalidBlock" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + Compare.eq (| + M.get_field (| M.get_name (| globals, "apply_body_output" |), "transactions_root" |), + M.get_field (| M.get_field (| M.get_name (| globals, "block" |), "header" |), "transactions_root" |) + |); + M.get_name (| globals, "InvalidBlock" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + Compare.eq (| + M.get_field (| M.get_name (| globals, "apply_body_output" |), "state_root" |), + M.get_field (| M.get_field (| M.get_name (| globals, "block" |), "header" |), "state_root" |) + |); + M.get_name (| globals, "InvalidBlock" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + Compare.eq (| + M.get_field (| M.get_name (| globals, "apply_body_output" |), "receipt_root" |), + M.get_field (| M.get_field (| M.get_name (| globals, "block" |), "header" |), "receipt_root" |) + |); + M.get_name (| globals, "InvalidBlock" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + Compare.eq (| + M.get_field (| M.get_name (| globals, "apply_body_output" |), "block_logs_bloom" |), + M.get_field (| M.get_field (| M.get_name (| globals, "block" |), "header" |), "bloom" |) + |); + M.get_name (| globals, "InvalidBlock" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, "chain" |), "blocks" |), "append" |), + make_list [ + M.get_name (| globals, "block" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.gt (| + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_field (| M.get_name (| globals, "chain" |), "blocks" |) + ], + make_dict [] + |), + Constant.int 255 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign (| + M.get_field (| M.get_name (| globals, "chain" |), "blocks" |), + M.slice (| + M.get_field (| M.get_name (| globals, "chain" |), "blocks" |), + UnOp.sub (| Constant.int 255 |), + Constant.None_, + Constant.None_ + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + M.pure Constant.None_)). + +Definition validate_header : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "header"; "parent_header" ] |) in + let _ := Constant.str " + Verifies a block header. + + In order to consider a block's header valid, the logic for the + quantities in the header should match the logic for the block itself. + For example the header timestamp should be greater than the block's parent + timestamp because the block was created *after* the parent block. + Additionally, the block's number should be directly following the parent + block's number since it is the next block in the sequence. + + Parameters + ---------- + header : + Header to check for correctness. + parent_header : + Parent Header of the header to check for correctness + " in + let _ := M.assign_local (| + "parent_has_ommers" , + Compare.not_eq (| + M.get_field (| M.get_name (| globals, "parent_header" |), "ommers_hash" |), + M.get_name (| globals, "EMPTY_OMMER_HASH" |) + |) + |) in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + Compare.gt (| + M.get_field (| M.get_name (| globals, "header" |), "timestamp" |), + M.get_field (| M.get_name (| globals, "parent_header" |), "timestamp" |) + |); + M.get_name (| globals, "InvalidBlock" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + Compare.eq (| + M.get_field (| M.get_name (| globals, "header" |), "number" |), + BinOp.add (| + M.get_field (| M.get_name (| globals, "parent_header" |), "number" |), + Constant.int 1 + |) + |); + M.get_name (| globals, "InvalidBlock" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + M.call (| + M.get_name (| globals, "check_gas_limit" |), + make_list [ + M.get_field (| M.get_name (| globals, "header" |), "gas_limit" |); + M.get_field (| M.get_name (| globals, "parent_header" |), "gas_limit" |) + ], + make_dict [] + |); + M.get_name (| globals, "InvalidBlock" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + Compare.lt_e (| + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_field (| M.get_name (| globals, "header" |), "extra_data" |) + ], + make_dict [] + |), + Constant.int 32 + |); + M.get_name (| globals, "InvalidBlock" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "block_difficulty" , + M.call (| + M.get_name (| globals, "calculate_block_difficulty" |), + make_list [ + M.get_field (| M.get_name (| globals, "header" |), "number" |); + M.get_field (| M.get_name (| globals, "header" |), "timestamp" |); + M.get_field (| M.get_name (| globals, "parent_header" |), "timestamp" |); + M.get_field (| M.get_name (| globals, "parent_header" |), "difficulty" |); + M.get_name (| globals, "parent_has_ommers" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + Compare.eq (| + M.get_field (| M.get_name (| globals, "header" |), "difficulty" |), + M.get_name (| globals, "block_difficulty" |) + |); + M.get_name (| globals, "InvalidBlock" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "block_parent_hash" , + M.call (| + M.get_name (| globals, "keccak256" |), + make_list [ + M.call (| + M.get_field (| M.get_name (| globals, "rlp" |), "encode" |), + make_list [ + M.get_name (| globals, "parent_header" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + Compare.eq (| + M.get_field (| M.get_name (| globals, "header" |), "parent_hash" |), + M.get_name (| globals, "block_parent_hash" |) + |); + M.get_name (| globals, "InvalidBlock" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "validate_proof_of_work" |), + make_list [ + M.get_name (| globals, "header" |) + ], + make_dict [] + |) in + M.pure Constant.None_)). + +Definition generate_header_hash_for_pow : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "header" ] |) in + let _ := Constant.str " + Generate rlp hash of the header which is to be used for Proof-of-Work + verification. + + In other words, the PoW artefacts `mix_digest` and `nonce` are ignored + while calculating this hash. + + A particular PoW is valid for a single hash, that hash is computed by + this function. The `nonce` and `mix_digest` are omitted from this hash + because they are being changed by miners in their search for a sufficient + proof-of-work. + + Parameters + ---------- + header : + The header object for which the hash is to be generated. + + Returns + ------- + hash : `Hash32` + The PoW valid rlp hash of the passed in header. + " in + let _ := M.assign_local (| + "header_data_without_pow_artefacts" , + make_list [ + M.get_field (| M.get_name (| globals, "header" |), "parent_hash" |); + M.get_field (| M.get_name (| globals, "header" |), "ommers_hash" |); + M.get_field (| M.get_name (| globals, "header" |), "coinbase" |); + M.get_field (| M.get_name (| globals, "header" |), "state_root" |); + M.get_field (| M.get_name (| globals, "header" |), "transactions_root" |); + M.get_field (| M.get_name (| globals, "header" |), "receipt_root" |); + M.get_field (| M.get_name (| globals, "header" |), "bloom" |); + M.get_field (| M.get_name (| globals, "header" |), "difficulty" |); + M.get_field (| M.get_name (| globals, "header" |), "number" |); + M.get_field (| M.get_name (| globals, "header" |), "gas_limit" |); + M.get_field (| M.get_name (| globals, "header" |), "gas_used" |); + M.get_field (| M.get_name (| globals, "header" |), "timestamp" |); + M.get_field (| M.get_name (| globals, "header" |), "extra_data" |) + ] + |) in + let _ := M.return_ (| + M.call (| + M.get_field (| M.get_name (| globals, "rlp" |), "rlp_hash" |), + make_list [ + M.get_name (| globals, "header_data_without_pow_artefacts" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Definition validate_proof_of_work : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "header" ] |) in + let _ := Constant.str " + Validates the Proof of Work constraints. + + In order to verify that a miner's proof-of-work is valid for a block, a + ``mix-digest`` and ``result`` are calculated using the ``hashimoto_light`` + hash function. The mix digest is a hash of the header and the nonce that + is passed through and it confirms whether or not proof-of-work was done + on the correct block. The result is the actual hash value of the block. + + Parameters + ---------- + header : + Header of interest. + " in + let _ := M.assign_local (| + "header_hash" , + M.call (| + M.get_name (| globals, "generate_header_hash_for_pow" |), + make_list [ + M.get_name (| globals, "header" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "cache" , + M.call (| + M.get_name (| globals, "generate_cache" |), + make_list [ + M.get_field (| M.get_name (| globals, "header" |), "number" |) + ], + make_dict [] + |) + |) in + let _ := M.assign (| + make_tuple [ M.get_name (| globals, "mix_digest" |); M.get_name (| globals, "result" |) ], + M.call (| + M.get_name (| globals, "hashimoto_light" |), + make_list [ + M.get_name (| globals, "header_hash" |); + M.get_field (| M.get_name (| globals, "header" |), "nonce" |); + M.get_name (| globals, "cache" |); + M.call (| + M.get_name (| globals, "dataset_size" |), + make_list [ + M.get_field (| M.get_name (| globals, "header" |), "number" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + Compare.eq (| + M.get_name (| globals, "mix_digest" |), + M.get_field (| M.get_name (| globals, "header" |), "mix_digest" |) + |); + M.get_name (| globals, "InvalidBlock" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + Compare.lt_e (| + M.call (| + M.get_field (| M.get_name (| globals, "Uint" |), "from_be_bytes" |), + make_list [ + M.get_name (| globals, "result" |) + ], + make_dict [] + |), + BinOp.floor_div (| + M.get_name (| globals, "U256_CEIL_VALUE" |), + M.get_field (| M.get_name (| globals, "header" |), "difficulty" |) + |) + |); + M.get_name (| globals, "InvalidBlock" |) + ], + make_dict [] + |) in + M.pure Constant.None_)). + +Definition check_transaction : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "tx"; "gas_available"; "chain_id" ] |) in + let _ := Constant.str " + Check if the transaction is includable in the block. + + Parameters + ---------- + tx : + The transaction. + gas_available : + The gas remaining in the block. + chain_id : + The ID of the current chain. + + Returns + ------- + sender_address : + The sender of the transaction. + + Raises + ------ + InvalidBlock : + If the transaction is not includable. + " in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + Compare.lt_e (| + M.get_field (| M.get_name (| globals, "tx" |), "gas" |), + M.get_name (| globals, "gas_available" |) + |); + M.get_name (| globals, "InvalidBlock" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "sender_address" , + M.call (| + M.get_name (| globals, "recover_sender" |), + make_list [ + M.get_name (| globals, "chain_id" |); + M.get_name (| globals, "tx" |) + ], + make_dict [] + |) + |) in + let _ := M.return_ (| + M.get_name (| globals, "sender_address" |) + |) in + M.pure Constant.None_)). + +Definition make_receipt : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "tx"; "error"; "cumulative_gas_used"; "logs" ] |) in + let _ := Constant.str " + Make the receipt for a transaction that was executed. + + Parameters + ---------- + tx : + The executed transaction. + error : + Error in the top level frame of the transaction, if any. + cumulative_gas_used : + The total gas used so far in the block after the transaction was + executed. + logs : + The logs produced by the transaction. + + Returns + ------- + receipt : + The receipt for the transaction. + " in + let _ := M.assign_local (| + "receipt" , + M.call (| + M.get_name (| globals, "Receipt" |), + make_list [], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, "isinstance" |), + make_list [ + M.get_name (| globals, "tx" |); + M.get_name (| globals, "AccessListTransaction" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + BinOp.add (| + Constant.bytes "01", + M.call (| + M.get_field (| M.get_name (| globals, "rlp" |), "encode" |), + make_list [ + M.get_name (| globals, "receipt" |) + ], + make_dict [] + |) + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.return_ (| + M.get_name (| globals, "receipt" |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_)). + +Definition ApplyBodyOutput : Value.t := + builtins.make_klass + [] + [ + + ] + [ + + ]. + +Definition apply_body : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "state"; "block_hashes"; "coinbase"; "block_number"; "block_gas_limit"; "block_time"; "block_difficulty"; "transactions"; "ommers"; "chain_id" ] |) in + let _ := Constant.str " + Executes a block. + + Many of the contents of a block are stored in data structures called + tries. There is a transactions trie which is similar to a ledger of the + transactions stored in the current block. There is also a receipts trie + which stores the results of executing a transaction, like the post state + and gas used. This function creates and executes the block that is to be + added to the chain. + + Parameters + ---------- + state : + Current account state. + block_hashes : + List of hashes of the previous 256 blocks in the order of + increasing block number. + coinbase : + Address of account which receives block reward and transaction fees. + block_number : + Position of the block within the chain. + block_gas_limit : + Initial amount of gas available for execution in this block. + block_time : + Time the block was produced, measured in seconds since the epoch. + block_difficulty : + Difficulty of the block. + transactions : + Transactions included in the block. + ommers : + Headers of ancestor blocks which are not direct parents (formerly + uncles.) + chain_id : + ID of the executing chain. + + Returns + ------- + apply_body_output : `ApplyBodyOutput` + Output of applying the block body to the state. + " in + let _ := M.assign_local (| + "gas_available" , + M.get_name (| globals, "block_gas_limit" |) + |) in +(* At stmt: unsupported node type: AnnAssign *) +(* At stmt: unsupported node type: AnnAssign *) +(* At stmt: unsupported node type: AnnAssign *) + let _ := + M.for_ (| + make_tuple [ M.get_name (| globals, "i" |); M.get_name (| globals, "tx" |) ], + M.call (| + M.get_name (| globals, "enumerate" |), + make_list [ + M.call (| + M.get_name (| globals, "map" |), + make_list [ + M.get_name (| globals, "decode_transaction" |); + M.get_name (| globals, "transactions" |) + ], + make_dict [] + |) + ], + make_dict [] + |), + ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, "trie_set" |), + make_list [ + M.get_name (| globals, "transactions_trie" |); + M.call (| + M.get_field (| M.get_name (| globals, "rlp" |), "encode" |), + make_list [ + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.get_name (| globals, "i" |) + ], + make_dict [] + |) + ], + make_dict [] + |); + M.call (| + M.get_name (| globals, "encode_transaction" |), + make_list [ + M.get_name (| globals, "tx" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "sender_address" , + M.call (| + M.get_name (| globals, "check_transaction" |), + make_list [ + M.get_name (| globals, "tx" |); + M.get_name (| globals, "gas_available" |); + M.get_name (| globals, "chain_id" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "env" , + M.call (| + M.get_field (| M.get_name (| globals, "vm" |), "Environment" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.assign (| + make_tuple [ M.get_name (| globals, "gas_used" |); M.get_name (| globals, "logs" |); M.get_name (| globals, "error" |) ], + M.call (| + M.get_name (| globals, "process_transaction" |), + make_list [ + M.get_name (| globals, "env" |); + M.get_name (| globals, "tx" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_op_local (| + BinOp.sub, + "gas_available", + M.get_name (| globals, "gas_used" |) + |) in + let _ := M.assign_local (| + "receipt" , + M.call (| + M.get_name (| globals, "make_receipt" |), + make_list [ + M.get_name (| globals, "tx" |); + M.get_name (| globals, "error" |); + BinOp.sub (| + M.get_name (| globals, "block_gas_limit" |), + M.get_name (| globals, "gas_available" |) + |); + M.get_name (| globals, "logs" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "trie_set" |), + make_list [ + M.get_name (| globals, "receipts_trie" |); + M.call (| + M.get_field (| M.get_name (| globals, "rlp" |), "encode" |), + make_list [ + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.get_name (| globals, "i" |) + ], + make_dict [] + |) + ], + make_dict [] + |); + M.get_name (| globals, "receipt" |) + ], + make_dict [] + |) in + let _ := M.assign_op_local (| + BinOp.add, + "block_logs", + M.get_name (| globals, "logs" |) + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := M.call (| + M.get_name (| globals, "pay_rewards" |), + make_list [ + M.get_name (| globals, "state" |); + M.get_name (| globals, "block_number" |); + M.get_name (| globals, "coinbase" |); + M.get_name (| globals, "ommers" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "block_gas_used" , + BinOp.sub (| + M.get_name (| globals, "block_gas_limit" |), + M.get_name (| globals, "gas_available" |) + |) + |) in + let _ := M.assign_local (| + "block_logs_bloom" , + M.call (| + M.get_name (| globals, "logs_bloom" |), + make_list [ + M.get_name (| globals, "block_logs" |) + ], + make_dict [] + |) + |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, "ApplyBodyOutput" |), + make_list [ + M.get_name (| globals, "block_gas_used" |); + M.call (| + M.get_name (| globals, "root" |), + make_list [ + M.get_name (| globals, "transactions_trie" |) + ], + make_dict [] + |); + M.call (| + M.get_name (| globals, "root" |), + make_list [ + M.get_name (| globals, "receipts_trie" |) + ], + make_dict [] + |); + M.get_name (| globals, "block_logs_bloom" |); + M.call (| + M.get_name (| globals, "state_root" |), + make_list [ + M.get_name (| globals, "state" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Definition validate_ommers : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "ommers"; "block_header"; "chain" ] |) in + let _ := Constant.str " + Validates the ommers mentioned in the block. + + An ommer block is a block that wasn't canonically added to the + blockchain because it wasn't validated as fast as the canonical block + but was mined at the same time. + + To be considered valid, the ommers must adhere to the rules defined in + the Ethereum protocol. The maximum amount of ommers is 2 per block and + there cannot be duplicate ommers in a block. Many of the other ommer + constraints are listed in the in-line comments of this function. + + Parameters + ---------- + ommers : + List of ommers mentioned in the current block. + block_header: + The header of current block. + chain : + History and current state. + " in + let _ := M.assign_local (| + "block_hash" , + M.call (| + M.get_field (| M.get_name (| globals, "rlp" |), "rlp_hash" |), + make_list [ + M.get_name (| globals, "block_header" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + Compare.eq (| + M.call (| + M.get_field (| M.get_name (| globals, "rlp" |), "rlp_hash" |), + make_list [ + M.get_name (| globals, "ommers" |) + ], + make_dict [] + |), + M.get_field (| M.get_name (| globals, "block_header" |), "ommers_hash" |) + |); + M.get_name (| globals, "InvalidBlock" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_name (| globals, "ommers" |) + ], + make_dict [] + |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + Constant.None_ + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + M.for_ (| + M.get_name (| globals, "ommer" |), + M.get_name (| globals, "ommers" |), + ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + BoolOp.and (| + Compare.lt_e (| + Constant.int 1, + M.get_field (| M.get_name (| globals, "ommer" |), "number" |) + |), + ltac:(M.monadic ( + Compare.lt (| + M.get_field (| M.get_name (| globals, "ommer" |), "number" |), + M.get_field (| M.get_name (| globals, "block_header" |), "number" |) + |) + )) + |); + M.get_name (| globals, "InvalidBlock" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "ommer_parent_header" , + M.get_field (| M.get_subscript (| + M.get_field (| M.get_name (| globals, "chain" |), "blocks" |), + BinOp.sub (| + UnOp.sub (| BinOp.sub (| + M.get_field (| M.get_name (| globals, "block_header" |), "number" |), + M.get_field (| M.get_name (| globals, "ommer" |), "number" |) + |) |), + Constant.int 1 + |) + |), "header" |) + |) in + let _ := M.call (| + M.get_name (| globals, "validate_header" |), + make_list [ + M.get_name (| globals, "ommer" |); + M.get_name (| globals, "ommer_parent_header" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + Compare.lt_e (| + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_name (| globals, "ommers" |) + ], + make_dict [] + |), + Constant.int 2 + |); + M.get_name (| globals, "InvalidBlock" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "ommers_hashes" , + Constant.str "(* At expr: unsupported node type: ListComp *)" + |) in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + Compare.eq (| + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_name (| globals, "ommers_hashes" |) + ], + make_dict [] + |), + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.call (| + M.get_name (| globals, "set" |), + make_list [ + M.get_name (| globals, "ommers_hashes" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |); + M.get_name (| globals, "InvalidBlock" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "recent_canonical_blocks" , + M.slice (| + M.get_field (| M.get_name (| globals, "chain" |), "blocks" |), + UnOp.sub (| BinOp.add (| + M.get_name (| globals, "MAX_OMMER_DEPTH" |), + Constant.int 1 + |) |), + Constant.None_, + Constant.None_ + |) + |) in + let _ := M.assign_local (| + "recent_canonical_block_hashes" , + Constant.str "(* At expr: unsupported node type: SetComp *)" + |) in +(* At stmt: unsupported node type: AnnAssign *) + let _ := + M.for_ (| + M.get_name (| globals, "block" |), + M.get_name (| globals, "recent_canonical_blocks" |), + ltac:(M.monadic ( + let _ := M.assign_local (| + "recent_ommers_hashes" , + M.call (| + M.get_field (| M.get_name (| globals, "recent_ommers_hashes" |), "union" |), + make_list [ + Constant.str "(* At expr: unsupported node type: SetComp *)" + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := + M.for_ (| + make_tuple [ M.get_name (| globals, "ommer_index" |); M.get_name (| globals, "ommer" |) ], + M.call (| + M.get_name (| globals, "enumerate" |), + make_list [ + M.get_name (| globals, "ommers" |) + ], + make_dict [] + |), + ltac:(M.monadic ( + let _ := M.assign_local (| + "ommer_hash" , + M.get_subscript (| + M.get_name (| globals, "ommers_hashes" |), + M.get_name (| globals, "ommer_index" |) + |) + |) in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + Compare.not_eq (| + M.get_name (| globals, "ommer_hash" |), + M.get_name (| globals, "block_hash" |) + |); + M.get_name (| globals, "InvalidBlock" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + Compare.not_in (| + M.get_name (| globals, "ommer_hash" |), + M.get_name (| globals, "recent_canonical_block_hashes" |) + |); + M.get_name (| globals, "InvalidBlock" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + Compare.not_in (| + M.get_name (| globals, "ommer_hash" |), + M.get_name (| globals, "recent_ommers_hashes" |) + |); + M.get_name (| globals, "InvalidBlock" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "ommer_age" , + BinOp.sub (| + M.get_field (| M.get_name (| globals, "block_header" |), "number" |), + M.get_field (| M.get_name (| globals, "ommer" |), "number" |) + |) + |) in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + BoolOp.and (| + Compare.lt_e (| + Constant.int 1, + M.get_name (| globals, "ommer_age" |) + |), + ltac:(M.monadic ( + Compare.lt_e (| + M.get_name (| globals, "ommer_age" |), + M.get_name (| globals, "MAX_OMMER_DEPTH" |) + |) + )) + |); + M.get_name (| globals, "InvalidBlock" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + Compare.in_ (| + M.get_field (| M.get_name (| globals, "ommer" |), "parent_hash" |), + M.get_name (| globals, "recent_canonical_block_hashes" |) + |); + M.get_name (| globals, "InvalidBlock" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + Compare.not_eq (| + M.get_field (| M.get_name (| globals, "ommer" |), "parent_hash" |), + M.get_field (| M.get_name (| globals, "block_header" |), "parent_hash" |) + |); + M.get_name (| globals, "InvalidBlock" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + M.pure Constant.None_)). + +Definition pay_rewards : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "state"; "block_number"; "coinbase"; "ommers" ] |) in + let _ := Constant.str " + Pay rewards to the block miner as well as the ommers miners. + + The miner of the canonical block is rewarded with the predetermined + block reward, ``BLOCK_REWARD``, plus a variable award based off of the + number of ommer blocks that were mined around the same time, and included + in the canonical block's header. An ommer block is a block that wasn't + added to the canonical blockchain because it wasn't validated as fast as + the accepted block but was mined at the same time. Although not all blocks + that are mined are added to the canonical chain, miners are still paid a + reward for their efforts. This reward is called an ommer reward and is + calculated based on the number associated with the ommer block that they + mined. + + Parameters + ---------- + state : + Current account state. + block_number : + Position of the block within the chain. + coinbase : + Address of account which receives block reward and transaction fees. + ommers : + List of ommers mentioned in the current block. + " in + let _ := M.assign_local (| + "miner_reward" , + BinOp.add (| + M.get_name (| globals, "BLOCK_REWARD" |), + BinOp.mult (| + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_name (| globals, "ommers" |) + ], + make_dict [] + |), + BinOp.floor_div (| + M.get_name (| globals, "BLOCK_REWARD" |), + Constant.int 32 + |) + |) + |) + |) in + let _ := M.call (| + M.get_name (| globals, "create_ether" |), + make_list [ + M.get_name (| globals, "state" |); + M.get_name (| globals, "coinbase" |); + M.get_name (| globals, "miner_reward" |) + ], + make_dict [] + |) in + let _ := + M.for_ (| + M.get_name (| globals, "ommer" |), + M.get_name (| globals, "ommers" |), + ltac:(M.monadic ( + let _ := M.assign_local (| + "ommer_age" , + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + BinOp.sub (| + M.get_name (| globals, "block_number" |), + M.get_field (| M.get_name (| globals, "ommer" |), "number" |) + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "ommer_miner_reward" , + BinOp.floor_div (| + BinOp.mult (| + BinOp.sub (| + Constant.int 8, + M.get_name (| globals, "ommer_age" |) + |), + M.get_name (| globals, "BLOCK_REWARD" |) + |), + Constant.int 8 + |) + |) in + let _ := M.call (| + M.get_name (| globals, "create_ether" |), + make_list [ + M.get_name (| globals, "state" |); + M.get_field (| M.get_name (| globals, "ommer" |), "coinbase" |); + M.get_name (| globals, "ommer_miner_reward" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + M.pure Constant.None_)). + +Definition process_transaction : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "env"; "tx" ] |) in + let _ := Constant.str " + Execute a transaction against the provided environment. + + This function processes the actions needed to execute a transaction. + It decrements the sender's account after calculating the gas fee and + refunds them the proper amount after execution. Calling contracts, + deploying code, and incrementing nonces are all examples of actions that + happen within this function or from a call made within this function. + + Accounts that are marked for deletion are processed and destroyed after + execution. + + Parameters + ---------- + env : + Environment for the Ethereum Virtual Machine. + tx : + Transaction to execute. + + Returns + ------- + gas_left : `ethereum.base_types.U256` + Remaining gas after execution. + logs : `Tuple[ethereum.blocks.Log, ...]` + Logs generated during execution. + " in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + M.call (| + M.get_name (| globals, "validate_transaction" |), + make_list [ + M.get_name (| globals, "tx" |) + ], + make_dict [] + |); + M.get_name (| globals, "InvalidBlock" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "sender" , + M.get_field (| M.get_name (| globals, "env" |), "origin" |) + |) in + let _ := M.assign_local (| + "sender_account" , + M.call (| + M.get_name (| globals, "get_account" |), + make_list [ + M.get_field (| M.get_name (| globals, "env" |), "state" |); + M.get_name (| globals, "sender" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "gas_fee" , + BinOp.mult (| + M.get_field (| M.get_name (| globals, "tx" |), "gas" |), + M.get_field (| M.get_name (| globals, "tx" |), "gas_price" |) + |) + |) in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + Compare.eq (| + M.get_field (| M.get_name (| globals, "sender_account" |), "nonce" |), + M.get_field (| M.get_name (| globals, "tx" |), "nonce" |) + |); + M.get_name (| globals, "InvalidBlock" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + Compare.gt_e (| + M.get_field (| M.get_name (| globals, "sender_account" |), "balance" |), + BinOp.add (| + M.get_name (| globals, "gas_fee" |), + M.get_field (| M.get_name (| globals, "tx" |), "value" |) + |) + |); + M.get_name (| globals, "InvalidBlock" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + Compare.eq (| + M.get_field (| M.get_name (| globals, "sender_account" |), "code" |), + M.call (| + M.get_name (| globals, "bytearray" |), + make_list [], + make_dict [] + |) + |); + M.get_name (| globals, "InvalidBlock" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "gas" , + BinOp.sub (| + M.get_field (| M.get_name (| globals, "tx" |), "gas" |), + M.call (| + M.get_name (| globals, "calculate_intrinsic_cost" |), + make_list [ + M.get_name (| globals, "tx" |) + ], + make_dict [] + |) + |) + |) in + let _ := M.call (| + M.get_name (| globals, "increment_nonce" |), + make_list [ + M.get_field (| M.get_name (| globals, "env" |), "state" |); + M.get_name (| globals, "sender" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "sender_balance_after_gas_fee" , + BinOp.sub (| + M.get_field (| M.get_name (| globals, "sender_account" |), "balance" |), + M.get_name (| globals, "gas_fee" |) + |) + |) in + let _ := M.call (| + M.get_name (| globals, "set_account_balance" |), + make_list [ + M.get_field (| M.get_name (| globals, "env" |), "state" |); + M.get_name (| globals, "sender" |); + M.get_name (| globals, "sender_balance_after_gas_fee" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "preaccessed_addresses" , + M.call (| + M.get_name (| globals, "set" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "preaccessed_storage_keys" , + M.call (| + M.get_name (| globals, "set" |), + make_list [], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, "isinstance" |), + make_list [ + M.get_name (| globals, "tx" |); + M.get_name (| globals, "AccessListTransaction" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := + M.for_ (| + make_tuple [ M.get_name (| globals, "address" |); M.get_name (| globals, "keys" |) ], + M.get_field (| M.get_name (| globals, "tx" |), "access_list" |), + ltac:(M.monadic ( + let _ := M.call (| + M.get_field (| M.get_name (| globals, "preaccessed_addresses" |), "add" |), + make_list [ + M.get_name (| globals, "address" |) + ], + make_dict [] + |) in + let _ := + M.for_ (| + M.get_name (| globals, "key" |), + M.get_name (| globals, "keys" |), + ltac:(M.monadic ( + let _ := M.call (| + M.get_field (| M.get_name (| globals, "preaccessed_storage_keys" |), "add" |), + make_list [ + make_tuple [ M.get_name (| globals, "address" |); M.get_name (| globals, "key" |) ] + ], + make_dict [] + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "message" , + M.call (| + M.get_name (| globals, "prepare_message" |), + make_list [ + M.get_name (| globals, "sender" |); + M.get_field (| M.get_name (| globals, "tx" |), "to" |); + M.get_field (| M.get_name (| globals, "tx" |), "value" |); + M.get_field (| M.get_name (| globals, "tx" |), "data" |); + M.get_name (| globals, "gas" |); + M.get_name (| globals, "env" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "output" , + M.call (| + M.get_name (| globals, "process_message_call" |), + make_list [ + M.get_name (| globals, "message" |); + M.get_name (| globals, "env" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "gas_used" , + BinOp.sub (| + M.get_field (| M.get_name (| globals, "tx" |), "gas" |), + M.get_field (| M.get_name (| globals, "output" |), "gas_left" |) + |) + |) in + let _ := M.assign_local (| + "gas_refund" , + M.call (| + M.get_name (| globals, "min" |), + make_list [ + BinOp.floor_div (| + M.get_name (| globals, "gas_used" |), + Constant.int 2 + |); + M.get_field (| M.get_name (| globals, "output" |), "refund_counter" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "gas_refund_amount" , + BinOp.mult (| + BinOp.add (| + M.get_field (| M.get_name (| globals, "output" |), "gas_left" |), + M.get_name (| globals, "gas_refund" |) + |), + M.get_field (| M.get_name (| globals, "tx" |), "gas_price" |) + |) + |) in + let _ := M.assign_local (| + "transaction_fee" , + BinOp.mult (| + BinOp.sub (| + BinOp.sub (| + M.get_field (| M.get_name (| globals, "tx" |), "gas" |), + M.get_field (| M.get_name (| globals, "output" |), "gas_left" |) + |), + M.get_name (| globals, "gas_refund" |) + |), + M.get_field (| M.get_name (| globals, "tx" |), "gas_price" |) + |) + |) in + let _ := M.assign_local (| + "total_gas_used" , + BinOp.sub (| + M.get_name (| globals, "gas_used" |), + M.get_name (| globals, "gas_refund" |) + |) + |) in + let _ := M.assign_local (| + "sender_balance_after_refund" , + BinOp.add (| + M.get_field (| M.call (| + M.get_name (| globals, "get_account" |), + make_list [ + M.get_field (| M.get_name (| globals, "env" |), "state" |); + M.get_name (| globals, "sender" |) + ], + make_dict [] + |), "balance" |), + M.get_name (| globals, "gas_refund_amount" |) + |) + |) in + let _ := M.call (| + M.get_name (| globals, "set_account_balance" |), + make_list [ + M.get_field (| M.get_name (| globals, "env" |), "state" |); + M.get_name (| globals, "sender" |); + M.get_name (| globals, "sender_balance_after_refund" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "coinbase_balance_after_mining_fee" , + BinOp.add (| + M.get_field (| M.call (| + M.get_name (| globals, "get_account" |), + make_list [ + M.get_field (| M.get_name (| globals, "env" |), "state" |); + M.get_field (| M.get_name (| globals, "env" |), "coinbase" |) + ], + make_dict [] + |), "balance" |), + M.get_name (| globals, "transaction_fee" |) + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.not_eq (| + M.get_name (| globals, "coinbase_balance_after_mining_fee" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, "set_account_balance" |), + make_list [ + M.get_field (| M.get_name (| globals, "env" |), "state" |); + M.get_field (| M.get_name (| globals, "env" |), "coinbase" |); + M.get_name (| globals, "coinbase_balance_after_mining_fee" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, "account_exists_and_is_empty" |), + make_list [ + M.get_field (| M.get_name (| globals, "env" |), "state" |); + M.get_field (| M.get_name (| globals, "env" |), "coinbase" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, "destroy_account" |), + make_list [ + M.get_field (| M.get_name (| globals, "env" |), "state" |); + M.get_field (| M.get_name (| globals, "env" |), "coinbase" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )) |) in + let _ := + M.for_ (| + M.get_name (| globals, "address" |), + M.get_field (| M.get_name (| globals, "output" |), "accounts_to_delete" |), + ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, "destroy_account" |), + make_list [ + M.get_field (| M.get_name (| globals, "env" |), "state" |); + M.get_name (| globals, "address" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := + M.for_ (| + M.get_name (| globals, "address" |), + M.get_field (| M.get_name (| globals, "output" |), "touched_accounts" |), + ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, "account_exists_and_is_empty" |), + make_list [ + M.get_field (| M.get_name (| globals, "env" |), "state" |); + M.get_name (| globals, "address" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, "destroy_account" |), + make_list [ + M.get_field (| M.get_name (| globals, "env" |), "state" |); + M.get_name (| globals, "address" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := M.return_ (| + make_tuple [ M.get_name (| globals, "total_gas_used" |); M.get_field (| M.get_name (| globals, "output" |), "logs" |); M.get_field (| M.get_name (| globals, "output" |), "error" |) ] + |) in + M.pure Constant.None_)). + +Definition validate_transaction : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "tx" ] |) in + let _ := Constant.str " + Verifies a transaction. + + The gas in a transaction gets used to pay for the intrinsic cost of + operations, therefore if there is insufficient gas then it would not + be possible to execute a transaction and it will be declared invalid. + + Additionally, the nonce of a transaction must not equal or exceed the + limit defined in `EIP-2681 `_. + In practice, defining the limit as ``2**64-1`` has no impact because + sending ``2**64-1`` transactions is improbable. It's not strictly + impossible though, ``2**64-1`` transactions is the entire capacity of the + Ethereum blockchain at 2022 gas limits for a little over 22 years. + + Parameters + ---------- + tx : + Transaction to validate. + + Returns + ------- + verified : `bool` + True if the transaction can be executed, or False otherwise. + " in + let _ := M.return_ (| + BoolOp.and (| + Compare.lt_e (| + M.call (| + M.get_name (| globals, "calculate_intrinsic_cost" |), + make_list [ + M.get_name (| globals, "tx" |) + ], + make_dict [] + |), + M.get_field (| M.get_name (| globals, "tx" |), "gas" |) + |), + ltac:(M.monadic ( + Compare.lt (| + M.get_field (| M.get_name (| globals, "tx" |), "nonce" |), + BinOp.sub (| + BinOp.pow (| + Constant.int 2, + Constant.int 64 + |), + Constant.int 1 + |) + |) + )) + |) + |) in + M.pure Constant.None_)). + +Definition calculate_intrinsic_cost : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "tx" ] |) in + let _ := Constant.str " + Calculates the gas that is charged before execution is started. + + The intrinsic cost of the transaction is charged before execution has + begun. Functions/operations in the EVM cost money to execute so this + intrinsic cost is for the operations that need to be paid for as part of + the transaction. Data transfer, for example, is part of this intrinsic + cost. It costs ether to send data over the wire and that ether is + accounted for in the intrinsic cost calculated in this function. This + intrinsic cost must be calculated and paid for before execution in order + for all operations to be implemented. + + Parameters + ---------- + tx : + Transaction to compute the intrinsic cost of. + + Returns + ------- + verified : `ethereum.base_types.Uint` + The intrinsic cost of the transaction. + " in + let _ := M.assign_local (| + "data_cost" , + Constant.int 0 + |) in + let _ := + M.for_ (| + M.get_name (| globals, "byte" |), + M.get_field (| M.get_name (| globals, "tx" |), "data" |), + ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, "byte" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_op_local (| + BinOp.add, + "data_cost", + M.get_name (| globals, "TX_DATA_COST_PER_ZERO" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_op_local (| + BinOp.add, + "data_cost", + M.get_name (| globals, "TX_DATA_COST_PER_NON_ZERO" |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_field (| M.get_name (| globals, "tx" |), "to" |), + M.call (| + M.get_name (| globals, "Bytes0" |), + make_list [ + Constant.bytes "" + ], + make_dict [] + |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "create_cost" , + M.get_name (| globals, "TX_CREATE_COST" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "create_cost" , + Constant.int 0 + |) in + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "access_list_cost" , + Constant.int 0 + |) in + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, "isinstance" |), + make_list [ + M.get_name (| globals, "tx" |); + M.get_name (| globals, "AccessListTransaction" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := + M.for_ (| + make_tuple [ M.get_name (| globals, "_address" |); M.get_name (| globals, "keys" |) ], + M.get_field (| M.get_name (| globals, "tx" |), "access_list" |), + ltac:(M.monadic ( + let _ := M.assign_op_local (| + BinOp.add, + "access_list_cost", + M.get_name (| globals, "TX_ACCESS_LIST_ADDRESS_COST" |) + |) in + let _ := M.assign_op_local (| + BinOp.add, + "access_list_cost", + BinOp.mult (| + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_name (| globals, "keys" |) + ], + make_dict [] + |), + M.get_name (| globals, "TX_ACCESS_LIST_STORAGE_KEY_COST" |) + |) + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + BinOp.add (| + BinOp.add (| + BinOp.add (| + M.get_name (| globals, "TX_BASE_COST" |), + M.get_name (| globals, "data_cost" |) + |), + M.get_name (| globals, "create_cost" |) + |), + M.get_name (| globals, "access_list_cost" |) + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Definition recover_sender : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "chain_id"; "tx" ] |) in + let _ := Constant.str " + Extracts the sender address from a transaction. + + The v, r, and s values are the three parts that make up the signature + of a transaction. In order to recover the sender of a transaction the two + components needed are the signature (``v``, ``r``, and ``s``) and the + signing hash of the transaction. The sender's public key can be obtained + with these two values and therefore the sender address can be retrieved. + + Parameters + ---------- + tx : + Transaction of interest. + chain_id : + ID of the executing chain. + + Returns + ------- + sender : `ethereum.fork_types.Address` + The address of the account that signed the transaction. + " in + let _ := M.assign (| + make_tuple [ M.get_name (| globals, "r" |); M.get_name (| globals, "s" |) ], + make_tuple [ M.get_field (| M.get_name (| globals, "tx" |), "r" |); M.get_field (| M.get_name (| globals, "tx" |), "s" |) ] + |) in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + BoolOp.and (| + Compare.lt (| + Constant.int 0, + M.get_name (| globals, "r" |) + |), + ltac:(M.monadic ( + Compare.lt (| + M.get_name (| globals, "r" |), + M.get_name (| globals, "SECP256K1N" |) + |) + )) + |); + M.get_name (| globals, "InvalidBlock" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + BoolOp.and (| + Compare.lt (| + Constant.int 0, + M.get_name (| globals, "s" |) + |), + ltac:(M.monadic ( + Compare.lt_e (| + M.get_name (| globals, "s" |), + BinOp.floor_div (| + M.get_name (| globals, "SECP256K1N" |), + Constant.int 2 + |) + |) + )) + |); + M.get_name (| globals, "InvalidBlock" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, "isinstance" |), + make_list [ + M.get_name (| globals, "tx" |); + M.get_name (| globals, "LegacyTransaction" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "v" , + M.get_field (| M.get_name (| globals, "tx" |), "v" |) + |) in + let _ := + (* if *) + M.if_then_else (| + BoolOp.or (| + Compare.eq (| + M.get_name (| globals, "v" |), + Constant.int 27 + |), + ltac:(M.monadic ( + Compare.eq (| + M.get_name (| globals, "v" |), + Constant.int 28 + |) + )) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "public_key" , + M.call (| + M.get_name (| globals, "secp256k1_recover" |), + make_list [ + M.get_name (| globals, "r" |); + M.get_name (| globals, "s" |); + BinOp.sub (| + M.get_name (| globals, "v" |), + Constant.int 27 + |); + M.call (| + M.get_name (| globals, "signing_hash_pre155" |), + make_list [ + M.get_name (| globals, "tx" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + BoolOp.or (| + Compare.eq (| + M.get_name (| globals, "v" |), + BinOp.add (| + Constant.int 35, + BinOp.mult (| + M.get_name (| globals, "chain_id" |), + Constant.int 2 + |) + |) + |), + ltac:(M.monadic ( + Compare.eq (| + M.get_name (| globals, "v" |), + BinOp.add (| + Constant.int 36, + BinOp.mult (| + M.get_name (| globals, "chain_id" |), + Constant.int 2 + |) + |) + |) + )) + |); + M.get_name (| globals, "InvalidBlock" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "public_key" , + M.call (| + M.get_name (| globals, "secp256k1_recover" |), + make_list [ + M.get_name (| globals, "r" |); + M.get_name (| globals, "s" |); + BinOp.sub (| + BinOp.sub (| + M.get_name (| globals, "v" |), + Constant.int 35 + |), + BinOp.mult (| + M.get_name (| globals, "chain_id" |), + Constant.int 2 + |) + |); + M.call (| + M.get_name (| globals, "signing_hash_155" |), + make_list [ + M.get_name (| globals, "tx" |); + M.get_name (| globals, "chain_id" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, "isinstance" |), + make_list [ + M.get_name (| globals, "tx" |); + M.get_name (| globals, "AccessListTransaction" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "public_key" , + M.call (| + M.get_name (| globals, "secp256k1_recover" |), + make_list [ + M.get_name (| globals, "r" |); + M.get_name (| globals, "s" |); + M.get_field (| M.get_name (| globals, "tx" |), "y_parity" |); + M.call (| + M.get_name (| globals, "signing_hash_2930" |), + make_list [ + M.get_name (| globals, "tx" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )) |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, "Address" |), + make_list [ + M.slice (| + M.call (| + M.get_name (| globals, "keccak256" |), + make_list [ + M.get_name (| globals, "public_key" |) + ], + make_dict [] + |), + Constant.int 12, + Constant.int 32, + Constant.None_ + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Definition signing_hash_pre155 : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "tx" ] |) in + let _ := Constant.str " + Compute the hash of a transaction used in a legacy (pre EIP 155) signature. + + Parameters + ---------- + tx : + Transaction of interest. + + Returns + ------- + hash : `ethereum.crypto.hash.Hash32` + Hash of the transaction. + " in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, "keccak256" |), + make_list [ + M.call (| + M.get_field (| M.get_name (| globals, "rlp" |), "encode" |), + make_list [ + make_tuple [ M.get_field (| M.get_name (| globals, "tx" |), "nonce" |); M.get_field (| M.get_name (| globals, "tx" |), "gas_price" |); M.get_field (| M.get_name (| globals, "tx" |), "gas" |); M.get_field (| M.get_name (| globals, "tx" |), "to" |); M.get_field (| M.get_name (| globals, "tx" |), "value" |); M.get_field (| M.get_name (| globals, "tx" |), "data" |) ] + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Definition signing_hash_155 : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "tx"; "chain_id" ] |) in + let _ := Constant.str " + Compute the hash of a transaction used in a EIP 155 signature. + + Parameters + ---------- + tx : + Transaction of interest. + chain_id : + The id of the current chain. + + Returns + ------- + hash : `ethereum.crypto.hash.Hash32` + Hash of the transaction. + " in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, "keccak256" |), + make_list [ + M.call (| + M.get_field (| M.get_name (| globals, "rlp" |), "encode" |), + make_list [ + make_tuple [ M.get_field (| M.get_name (| globals, "tx" |), "nonce" |); M.get_field (| M.get_name (| globals, "tx" |), "gas_price" |); M.get_field (| M.get_name (| globals, "tx" |), "gas" |); M.get_field (| M.get_name (| globals, "tx" |), "to" |); M.get_field (| M.get_name (| globals, "tx" |), "value" |); M.get_field (| M.get_name (| globals, "tx" |), "data" |); M.get_name (| globals, "chain_id" |); M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |); M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) ] + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Definition signing_hash_2930 : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "tx" ] |) in + let _ := Constant.str " + Compute the hash of a transaction used in a EIP 2930 signature. + + Parameters + ---------- + tx : + Transaction of interest. + + Returns + ------- + hash : `ethereum.crypto.hash.Hash32` + Hash of the transaction. + " in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, "keccak256" |), + make_list [ + BinOp.add (| + Constant.bytes "01", + M.call (| + M.get_field (| M.get_name (| globals, "rlp" |), "encode" |), + make_list [ + make_tuple [ M.get_field (| M.get_name (| globals, "tx" |), "chain_id" |); M.get_field (| M.get_name (| globals, "tx" |), "nonce" |); M.get_field (| M.get_name (| globals, "tx" |), "gas_price" |); M.get_field (| M.get_name (| globals, "tx" |), "gas" |); M.get_field (| M.get_name (| globals, "tx" |), "to" |); M.get_field (| M.get_name (| globals, "tx" |), "value" |); M.get_field (| M.get_name (| globals, "tx" |), "data" |); M.get_field (| M.get_name (| globals, "tx" |), "access_list" |) ] + ], + make_dict [] + |) + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Definition compute_header_hash : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "header" ] |) in + let _ := Constant.str " + Computes the hash of a block header. + + The header hash of a block is the canonical hash that is used to refer + to a specific block and completely distinguishes a block from another. + + ``keccak256`` is a function that produces a 256 bit hash of any input. + It also takes in any number of bytes as an input and produces a single + hash for them. A hash is a completely unique output for a single input. + So an input corresponds to one unique hash that can be used to identify + the input exactly. + + Prior to using the ``keccak256`` hash function, the header must be + encoded using the Recursive-Length Prefix. See :ref:`rlp`. + RLP encoding the header converts it into a space-efficient format that + allows for easy transfer of data between nodes. The purpose of RLP is to + encode arbitrarily nested arrays of binary data, and RLP is the primary + encoding method used to serialize objects in Ethereum's execution layer. + The only purpose of RLP is to encode structure; encoding specific data + types (e.g. strings, floats) is left up to higher-order protocols. + + Parameters + ---------- + header : + Header of interest. + + Returns + ------- + hash : `ethereum.crypto.hash.Hash32` + Hash of the header. + " in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, "keccak256" |), + make_list [ + M.call (| + M.get_field (| M.get_name (| globals, "rlp" |), "encode" |), + make_list [ + M.get_name (| globals, "header" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Definition check_gas_limit : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "gas_limit"; "parent_gas_limit" ] |) in + let _ := Constant.str " + Validates the gas limit for a block. + + The bounds of the gas limit, ``max_adjustment_delta``, is set as the + quotient of the parent block's gas limit and the + ``GAS_LIMIT_ADJUSTMENT_FACTOR``. Therefore, if the gas limit that is + passed through as a parameter is greater than or equal to the *sum* of + the parent's gas and the adjustment delta then the limit for gas is too + high and fails this function's check. Similarly, if the limit is less + than or equal to the *difference* of the parent's gas and the adjustment + delta *or* the predefined ``GAS_LIMIT_MINIMUM`` then this function's + check fails because the gas limit doesn't allow for a sufficient or + reasonable amount of gas to be used on a block. + + Parameters + ---------- + gas_limit : + Gas limit to validate. + + parent_gas_limit : + Gas limit of the parent block. + + Returns + ------- + check : `bool` + True if gas limit constraints are satisfied, False otherwise. + " in + let _ := M.assign_local (| + "max_adjustment_delta" , + BinOp.floor_div (| + M.get_name (| globals, "parent_gas_limit" |), + M.get_name (| globals, "GAS_LIMIT_ADJUSTMENT_FACTOR" |) + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.gt_e (| + M.get_name (| globals, "gas_limit" |), + BinOp.add (| + M.get_name (| globals, "parent_gas_limit" |), + M.get_name (| globals, "max_adjustment_delta" |) + |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + Constant.bool false + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + Compare.lt_e (| + M.get_name (| globals, "gas_limit" |), + BinOp.sub (| + M.get_name (| globals, "parent_gas_limit" |), + M.get_name (| globals, "max_adjustment_delta" |) + |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + Constant.bool false + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + Compare.lt (| + M.get_name (| globals, "gas_limit" |), + M.get_name (| globals, "GAS_LIMIT_MINIMUM" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + Constant.bool false + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.return_ (| + Constant.bool true + |) in + M.pure Constant.None_)). + +Definition calculate_block_difficulty : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "block_number"; "block_timestamp"; "parent_timestamp"; "parent_difficulty"; "parent_has_ommers" ] |) in + let _ := Constant.str " + Computes difficulty of a block using its header and parent header. + + The difficulty is determined by the time the block was created after its + parent. The ``offset`` is calculated using the parent block's difficulty, + ``parent_difficulty``, and the timestamp between blocks. This offset is + then added to the parent difficulty and is stored as the ``difficulty`` + variable. If the time between the block and its parent is too short, the + offset will result in a positive number thus making the sum of + ``parent_difficulty`` and ``offset`` to be a greater value in order to + avoid mass forking. But, if the time is long enough, then the offset + results in a negative value making the block less difficult than + its parent. + + The base standard for a block's difficulty is the predefined value + set for the genesis block since it has no parent. So, a block + can't be less difficult than the genesis block, therefore each block's + difficulty is set to the maximum value between the calculated + difficulty and the ``GENESIS_DIFFICULTY``. + + Parameters + ---------- + block_number : + Block number of the block. + block_timestamp : + Timestamp of the block. + parent_timestamp : + Timestamp of the parent block. + parent_difficulty : + difficulty of the parent block. + parent_has_ommers: + does the parent have ommers. + + Returns + ------- + difficulty : `ethereum.base_types.Uint` + Computed difficulty for a block. + " in + let _ := M.assign_local (| + "offset" , + BinOp.mult (| + BinOp.floor_div (| + M.call (| + M.get_name (| globals, "int" |), + make_list [ + M.get_name (| globals, "parent_difficulty" |) + ], + make_dict [] + |), + Constant.int 2048 + |), + M.call (| + M.get_name (| globals, "max" |), + make_list [ + BinOp.sub (| + (* if *) + M.if_then_else (| + M.get_name (| globals, "parent_has_ommers" |), + (* then *) + ltac:(M.monadic ( +Constant.int 2 + (* else *) + )), ltac:(M.monadic ( +Constant.int 1 + )) |), + BinOp.floor_div (| + M.call (| + M.get_name (| globals, "int" |), + make_list [ + BinOp.sub (| + M.get_name (| globals, "block_timestamp" |), + M.get_name (| globals, "parent_timestamp" |) + |) + ], + make_dict [] + |), + Constant.int 9 + |) + |); + UnOp.sub (| Constant.int 99 |) + ], + make_dict [] + |) + |) + |) in + let _ := M.assign_local (| + "difficulty" , + BinOp.add (| + M.call (| + M.get_name (| globals, "int" |), + make_list [ + M.get_name (| globals, "parent_difficulty" |) + ], + make_dict [] + |), + M.get_name (| globals, "offset" |) + |) + |) in + let _ := M.assign_local (| + "num_bomb_periods" , + BinOp.sub (| + BinOp.floor_div (| + BinOp.sub (| + M.call (| + M.get_name (| globals, "int" |), + make_list [ + M.get_name (| globals, "block_number" |) + ], + make_dict [] + |), + M.get_name (| globals, "BOMB_DELAY_BLOCKS" |) + |), + Constant.int 100000 + |), + Constant.int 2 + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.gt_e (| + M.get_name (| globals, "num_bomb_periods" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_op_local (| + BinOp.add, + "difficulty", + BinOp.pow (| + Constant.int 2, + M.get_name (| globals, "num_bomb_periods" |) + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, "max" |), + make_list [ + M.get_name (| globals, "difficulty" |); + M.get_name (| globals, "MINIMUM_DIFFICULTY" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). diff --git a/CoqOfPython/ethereum/berlin/fork_types.v b/CoqOfPython/ethereum/berlin/fork_types.v new file mode 100644 index 0000000..3502e2f --- /dev/null +++ b/CoqOfPython/ethereum/berlin/fork_types.v @@ -0,0 +1,98 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.berlin.fork_types". + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Types +^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Types re-used throughout the specification, which are specific to Ethereum. +". + +Axiom dataclasses_imports_dataclass : + IsImported globals "dataclasses" "dataclass". + +Axiom ethereum_imports_rlp : + IsImported globals "ethereum" "rlp". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_Bytes : + IsImported globals "ethereum.base_types" "Bytes". +Axiom ethereum_base_types_imports_Bytes20 : + IsImported globals "ethereum.base_types" "Bytes20". +Axiom ethereum_base_types_imports_Bytes256 : + IsImported globals "ethereum.base_types" "Bytes256". +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". +Axiom ethereum_base_types_imports_slotted_freezable : + IsImported globals "ethereum.base_types" "slotted_freezable". + +Axiom ethereum_crypto_hash_imports_Hash32 : + IsImported globals "ethereum.crypto.hash" "Hash32". +Axiom ethereum_crypto_hash_imports_keccak256 : + IsImported globals "ethereum.crypto.hash" "keccak256". + +Definition Address : Value.t := M.run ltac:(M.monadic ( + M.get_name (| globals, "Bytes20" |) +)). + +Definition Root : Value.t := M.run ltac:(M.monadic ( + M.get_name (| globals, "Hash32" |) +)). + +Definition Bloom : Value.t := M.run ltac:(M.monadic ( + M.get_name (| globals, "Bytes256" |) +)). + +Definition Account : Value.t := + builtins.make_klass + [] + [ + + ] + [ + + ]. + +Definition EMPTY_ACCOUNT : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Account" |), + make_list [], + make_dict [] + |) +)). + +Definition encode_account : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "raw_account_data"; "storage_root" ] |) in + let _ := Constant.str " + Encode `Account` dataclass. + + Storage is not stored in the `Account` dataclass, so `Accounts` cannot be + encoded with providing a storage root. + " in + let _ := M.return_ (| + M.call (| + M.get_field (| M.get_name (| globals, "rlp" |), "encode" |), + make_list [ + make_tuple [ M.get_field (| M.get_name (| globals, "raw_account_data" |), "nonce" |); M.get_field (| M.get_name (| globals, "raw_account_data" |), "balance" |); M.get_name (| globals, "storage_root" |); M.call (| + M.get_name (| globals, "keccak256" |), + make_list [ + M.get_field (| M.get_name (| globals, "raw_account_data" |), "code" |) + ], + make_dict [] + |) ] + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). diff --git a/CoqOfPython/ethereum/berlin/state.v b/CoqOfPython/ethereum/berlin/state.v new file mode 100644 index 0000000..58d88b0 --- /dev/null +++ b/CoqOfPython/ethereum/berlin/state.v @@ -0,0 +1,1279 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.berlin.state". + +Definition expr_1 : Value.t := + Constant.str " +State +^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +The state contains all information that is preserved between transactions. + +It consists of a main account trie and storage tries for each contract. + +There is a distinction between an account that does not exist and +`EMPTY_ACCOUNT`. +". + +Axiom dataclasses_imports_dataclass : + IsImported globals "dataclasses" "dataclass". +Axiom dataclasses_imports_field : + IsImported globals "dataclasses" "field". + +Axiom typing_imports_Callable : + IsImported globals "typing" "Callable". +Axiom typing_imports_Dict : + IsImported globals "typing" "Dict". +Axiom typing_imports_List : + IsImported globals "typing" "List". +Axiom typing_imports_Optional : + IsImported globals "typing" "Optional". +Axiom typing_imports_Set : + IsImported globals "typing" "Set". +Axiom typing_imports_Tuple : + IsImported globals "typing" "Tuple". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_Bytes : + IsImported globals "ethereum.base_types" "Bytes". +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". +Axiom ethereum_base_types_imports_modify : + IsImported globals "ethereum.base_types" "modify". + +Axiom ethereum_utils_ensure_imports_ensure : + IsImported globals "ethereum.utils.ensure" "ensure". + +Axiom ethereum_berlin_fork_types_imports_EMPTY_ACCOUNT : + IsImported globals "ethereum.berlin.fork_types" "EMPTY_ACCOUNT". +Axiom ethereum_berlin_fork_types_imports_Account : + IsImported globals "ethereum.berlin.fork_types" "Account". +Axiom ethereum_berlin_fork_types_imports_Address : + IsImported globals "ethereum.berlin.fork_types" "Address". +Axiom ethereum_berlin_fork_types_imports_Root : + IsImported globals "ethereum.berlin.fork_types" "Root". + +Axiom ethereum_berlin_trie_imports_EMPTY_TRIE_ROOT : + IsImported globals "ethereum.berlin.trie" "EMPTY_TRIE_ROOT". +Axiom ethereum_berlin_trie_imports_Trie : + IsImported globals "ethereum.berlin.trie" "Trie". +Axiom ethereum_berlin_trie_imports_copy_trie : + IsImported globals "ethereum.berlin.trie" "copy_trie". +Axiom ethereum_berlin_trie_imports_root : + IsImported globals "ethereum.berlin.trie" "root". +Axiom ethereum_berlin_trie_imports_trie_get : + IsImported globals "ethereum.berlin.trie" "trie_get". +Axiom ethereum_berlin_trie_imports_trie_set : + IsImported globals "ethereum.berlin.trie" "trie_set". + +Definition State : Value.t := + builtins.make_klass + [] + [ + + ] + [ + + ]. + +Definition close_state : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "state" ] |) in + let _ := Constant.str " + Free resources held by the state. Used by optimized implementations to + release file descriptors. + " in + let _ := M.delete (| M.get_field (| M.get_name (| globals, "state" |), "_main_trie" |) |) in + let _ := M.delete (| M.get_field (| M.get_name (| globals, "state" |), "_storage_tries" |) |) in + let _ := M.delete (| M.get_field (| M.get_name (| globals, "state" |), "_snapshots" |) |) in + let _ := M.delete (| M.get_field (| M.get_name (| globals, "state" |), "_created_accounts" |) |) in + M.pure Constant.None_)). + +Definition begin_transaction : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "state" ] |) in + let _ := Constant.str " + Start a state transaction. + + Transactions are entirely implicit and can be nested. It is not possible to + calculate the state root during a transaction. + + Parameters + ---------- + state : State + The state. + " in + let _ := M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, "state" |), "_snapshots" |), "append" |), + make_list [ + make_tuple [ M.call (| + M.get_name (| globals, "copy_trie" |), + make_list [ + M.get_field (| M.get_name (| globals, "state" |), "_main_trie" |) + ], + make_dict [] + |); Constant.str "(* At expr: unsupported node type: DictComp *)" ] + ], + make_dict [] + |) in + M.pure Constant.None_)). + +Definition commit_transaction : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "state" ] |) in + let _ := Constant.str " + Commit a state transaction. + + Parameters + ---------- + state : State + The state. + " in + let _ := M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, "state" |), "_snapshots" |), "pop" |), + make_list [], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + UnOp.not (| M.get_field (| M.get_name (| globals, "state" |), "_snapshots" |) |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, "state" |), "_created_accounts" |), "clear" |), + make_list [], + make_dict [] + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + M.pure Constant.None_)). + +Definition rollback_transaction : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "state" ] |) in + let _ := Constant.str " + Rollback a state transaction, resetting the state to the point when the + corresponding `start_transaction()` call was made. + + Parameters + ---------- + state : State + The state. + " in + let _ := M.assign (| + make_tuple [ M.get_field (| M.get_name (| globals, "state" |), "_main_trie" |); M.get_field (| M.get_name (| globals, "state" |), "_storage_tries" |) ], + M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, "state" |), "_snapshots" |), "pop" |), + make_list [], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + UnOp.not (| M.get_field (| M.get_name (| globals, "state" |), "_snapshots" |) |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, "state" |), "_created_accounts" |), "clear" |), + make_list [], + make_dict [] + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + M.pure Constant.None_)). + +Definition get_account : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "state"; "address" ] |) in + let _ := Constant.str " + Get the `Account` object at an address. Returns `EMPTY_ACCOUNT` if there + is no account at the address. + + Use `get_account_optional()` if you care about the difference between a + non-existent account and `EMPTY_ACCOUNT`. + + Parameters + ---------- + state: `State` + The state + address : `Address` + Address to lookup. + + Returns + ------- + account : `Account` + Account at address. + " in + let _ := M.assign_local (| + "account" , + M.call (| + M.get_name (| globals, "get_account_optional" |), + make_list [ + M.get_name (| globals, "state" |); + M.get_name (| globals, "address" |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, "isinstance" |), + make_list [ + M.get_name (| globals, "account" |); + M.get_name (| globals, "Account" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + M.get_name (| globals, "account" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.return_ (| + M.get_name (| globals, "EMPTY_ACCOUNT" |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_)). + +Definition get_account_optional : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "state"; "address" ] |) in + let _ := Constant.str " + Get the `Account` object at an address. Returns `None` (rather than + `EMPTY_ACCOUNT`) if there is no account at the address. + + Parameters + ---------- + state: `State` + The state + address : `Address` + Address to lookup. + + Returns + ------- + account : `Account` + Account at address. + " in + let _ := M.assign_local (| + "account" , + M.call (| + M.get_name (| globals, "trie_get" |), + make_list [ + M.get_field (| M.get_name (| globals, "state" |), "_main_trie" |); + M.get_name (| globals, "address" |) + ], + make_dict [] + |) + |) in + let _ := M.return_ (| + M.get_name (| globals, "account" |) + |) in + M.pure Constant.None_)). + +Definition set_account : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "state"; "address"; "account" ] |) in + let _ := Constant.str " + Set the `Account` object at an address. Setting to `None` deletes + the account (but not its storage, see `destroy_account()`). + + Parameters + ---------- + state: `State` + The state + address : `Address` + Address to set. + account : `Account` + Account to set at address. + " in + let _ := M.call (| + M.get_name (| globals, "trie_set" |), + make_list [ + M.get_field (| M.get_name (| globals, "state" |), "_main_trie" |); + M.get_name (| globals, "address" |); + M.get_name (| globals, "account" |) + ], + make_dict [] + |) in + M.pure Constant.None_)). + +Definition destroy_account : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "state"; "address" ] |) in + let _ := Constant.str " + Completely remove the account at `address` and all of its storage. + + This function is made available exclusively for the `SELFDESTRUCT` + opcode. It is expected that `SELFDESTRUCT` will be disabled in a future + hardfork and this function will be removed. + + Parameters + ---------- + state: `State` + The state + address : `Address` + Address of account to destroy. + " in + let _ := M.call (| + M.get_name (| globals, "destroy_storage" |), + make_list [ + M.get_name (| globals, "state" |); + M.get_name (| globals, "address" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "set_account" |), + make_list [ + M.get_name (| globals, "state" |); + M.get_name (| globals, "address" |); + Constant.None_ + ], + make_dict [] + |) in + M.pure Constant.None_)). + +Definition destroy_storage : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "state"; "address" ] |) in + let _ := Constant.str " + Completely remove the storage at `address`. + + Parameters + ---------- + state: `State` + The state + address : `Address` + Address of account whose storage is to be deleted. + " in + let _ := + (* if *) + M.if_then_else (| + Compare.in_ (| + M.get_name (| globals, "address" |), + M.get_field (| M.get_name (| globals, "state" |), "_storage_tries" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.delete (| M.get_subscript (| + M.get_field (| M.get_name (| globals, "state" |), "_storage_tries" |), + M.get_name (| globals, "address" |) + |) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + M.pure Constant.None_)). + +Definition mark_account_created : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "state"; "address" ] |) in + let _ := Constant.str " + Mark an account as having been created in the current transaction. + This information is used by `get_storage_original()` to handle an obscure + edgecase. + + The marker is not removed even if the account creation reverts. Since the + account cannot have had code prior to its creation and can't call + `get_storage_original()`, this is harmless. + + Parameters + ---------- + state: `State` + The state + address : `Address` + Address of the account that has been created. + " in + let _ := M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, "state" |), "_created_accounts" |), "add" |), + make_list [ + M.get_name (| globals, "address" |) + ], + make_dict [] + |) in + M.pure Constant.None_)). + +Definition get_storage : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "state"; "address"; "key" ] |) in + let _ := Constant.str " + Get a value at a storage key on an account. Returns `U256(0)` if the + storage key has not been set previously. + + Parameters + ---------- + state: `State` + The state + address : `Address` + Address of the account. + key : `Bytes` + Key to lookup. + + Returns + ------- + value : `U256` + Value at the key. + " in + let _ := M.assign_local (| + "trie" , + M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, "state" |), "_storage_tries" |), "get" |), + make_list [ + M.get_name (| globals, "address" |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.is (| + M.get_name (| globals, "trie" |), + Constant.None_ + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "value" , + M.call (| + M.get_name (| globals, "trie_get" |), + make_list [ + M.get_name (| globals, "trie" |); + M.get_name (| globals, "key" |) + ], + make_dict [] + |) + |) in + let _ := M.assert (| M.call (| + M.get_name (| globals, "isinstance" |), + make_list [ + M.get_name (| globals, "value" |); + M.get_name (| globals, "U256" |) + ], + make_dict [] + |) |) in + let _ := M.return_ (| + M.get_name (| globals, "value" |) + |) in + M.pure Constant.None_)). + +Definition set_storage : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "state"; "address"; "key"; "value" ] |) in + let _ := Constant.str " + Set a value at a storage key on an account. Setting to `U256(0)` deletes + the key. + + Parameters + ---------- + state: `State` + The state + address : `Address` + Address of the account. + key : `Bytes` + Key to set. + value : `U256` + Value to set at the key. + " in + let _ := M.assert (| Compare.is_not (| + M.call (| + M.get_name (| globals, "trie_get" |), + make_list [ + M.get_field (| M.get_name (| globals, "state" |), "_main_trie" |); + M.get_name (| globals, "address" |) + ], + make_dict [] + |), + Constant.None_ + |) |) in + let _ := M.assign_local (| + "trie" , + M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, "state" |), "_storage_tries" |), "get" |), + make_list [ + M.get_name (| globals, "address" |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.is (| + M.get_name (| globals, "trie" |), + Constant.None_ + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "trie" , + M.call (| + M.get_name (| globals, "Trie" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.assign (| + M.get_subscript (| + M.get_field (| M.get_name (| globals, "state" |), "_storage_tries" |), + M.get_name (| globals, "address" |) + |), + M.get_name (| globals, "trie" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.call (| + M.get_name (| globals, "trie_set" |), + make_list [ + M.get_name (| globals, "trie" |); + M.get_name (| globals, "key" |); + M.get_name (| globals, "value" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_field (| M.get_name (| globals, "trie" |), "_data" |), + Constant.str "(* At expr: unsupported node type: Dict *)" + |), + (* then *) + ltac:(M.monadic ( + let _ := M.delete (| M.get_subscript (| + M.get_field (| M.get_name (| globals, "state" |), "_storage_tries" |), + M.get_name (| globals, "address" |) + |) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + M.pure Constant.None_)). + +Definition storage_root : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "state"; "address" ] |) in + let _ := Constant.str " + Calculate the storage root of an account. + + Parameters + ---------- + state: + The state + address : + Address of the account. + + Returns + ------- + root : `Root` + Storage root of the account. + " in + let _ := M.assert (| UnOp.not (| M.get_field (| M.get_name (| globals, "state" |), "_snapshots" |) |) |) in + let _ := + (* if *) + M.if_then_else (| + Compare.in_ (| + M.get_name (| globals, "address" |), + M.get_field (| M.get_name (| globals, "state" |), "_storage_tries" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + M.call (| + M.get_name (| globals, "root" |), + make_list [ + M.get_subscript (| + M.get_field (| M.get_name (| globals, "state" |), "_storage_tries" |), + M.get_name (| globals, "address" |) + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.return_ (| + M.get_name (| globals, "EMPTY_TRIE_ROOT" |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_)). + +Definition state_root : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "state" ] |) in + let _ := Constant.str " + Calculate the state root. + + Parameters + ---------- + state: + The current state. + + Returns + ------- + root : `Root` + The state root. + " in + let _ := M.assert (| UnOp.not (| M.get_field (| M.get_name (| globals, "state" |), "_snapshots" |) |) |) in +(* At stmt: unsupported node type: FunctionDef *) + let _ := M.return_ (| + M.call (| + M.get_name (| globals, "root" |), + make_list [ + M.get_field (| M.get_name (| globals, "state" |), "_main_trie" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Definition account_exists : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "state"; "address" ] |) in + let _ := Constant.str " + Checks if an account exists in the state trie + + Parameters + ---------- + state: + The state + address: + Address of the account that needs to be checked. + + Returns + ------- + account_exists : `bool` + True if account exists in the state trie, False otherwise + " in + let _ := M.return_ (| + Compare.is_not (| + M.call (| + M.get_name (| globals, "get_account_optional" |), + make_list [ + M.get_name (| globals, "state" |); + M.get_name (| globals, "address" |) + ], + make_dict [] + |), + Constant.None_ + |) + |) in + M.pure Constant.None_)). + +Definition account_has_code_or_nonce : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "state"; "address" ] |) in + let _ := Constant.str " + Checks if an account has non zero nonce or non empty code + + Parameters + ---------- + state: + The state + address: + Address of the account that needs to be checked. + + Returns + ------- + has_code_or_nonce : `bool` + True if if an account has non zero nonce or non empty code, + False otherwise. + " in + let _ := M.assign_local (| + "account" , + M.call (| + M.get_name (| globals, "get_account" |), + make_list [ + M.get_name (| globals, "state" |); + M.get_name (| globals, "address" |) + ], + make_dict [] + |) + |) in + let _ := M.return_ (| + BoolOp.or (| + Compare.not_eq (| + M.get_field (| M.get_name (| globals, "account" |), "nonce" |), + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + |), + ltac:(M.monadic ( + Compare.not_eq (| + M.get_field (| M.get_name (| globals, "account" |), "code" |), + Constant.bytes "" + |) + )) + |) + |) in + M.pure Constant.None_)). + +Definition is_account_empty : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "state"; "address" ] |) in + let _ := Constant.str " + Checks if an account has zero nonce, empty code and zero balance. + + Parameters + ---------- + state: + The state + address: + Address of the account that needs to be checked. + + Returns + ------- + is_empty : `bool` + True if if an account has zero nonce, empty code and zero balance, + False otherwise. + " in + let _ := M.assign_local (| + "account" , + M.call (| + M.get_name (| globals, "get_account" |), + make_list [ + M.get_name (| globals, "state" |); + M.get_name (| globals, "address" |) + ], + make_dict [] + |) + |) in + let _ := M.return_ (| + BoolOp.and (| + Compare.eq (| + M.get_field (| M.get_name (| globals, "account" |), "nonce" |), + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + |), + ltac:(M.monadic ( + BoolOp.and (| + Compare.eq (| + M.get_field (| M.get_name (| globals, "account" |), "code" |), + Constant.bytes "" + |), + ltac:(M.monadic ( + Compare.eq (| + M.get_field (| M.get_name (| globals, "account" |), "balance" |), + Constant.int 0 + |) + )) + |) + )) + |) + |) in + M.pure Constant.None_)). + +Definition account_exists_and_is_empty : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "state"; "address" ] |) in + let _ := Constant.str " + Checks if an account exists and has zero nonce, empty code and zero + balance. + + Parameters + ---------- + state: + The state + address: + Address of the account that needs to be checked. + + Returns + ------- + exists_and_is_empty : `bool` + True if an account exists and has zero nonce, empty code and zero + balance, False otherwise. + " in + let _ := M.assign_local (| + "account" , + M.call (| + M.get_name (| globals, "get_account_optional" |), + make_list [ + M.get_name (| globals, "state" |); + M.get_name (| globals, "address" |) + ], + make_dict [] + |) + |) in + let _ := M.return_ (| + BoolOp.and (| + Compare.is_not (| + M.get_name (| globals, "account" |), + Constant.None_ + |), + ltac:(M.monadic ( + BoolOp.and (| + Compare.eq (| + M.get_field (| M.get_name (| globals, "account" |), "nonce" |), + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + |), + ltac:(M.monadic ( + BoolOp.and (| + Compare.eq (| + M.get_field (| M.get_name (| globals, "account" |), "code" |), + Constant.bytes "" + |), + ltac:(M.monadic ( + Compare.eq (| + M.get_field (| M.get_name (| globals, "account" |), "balance" |), + Constant.int 0 + |) + )) + |) + )) + |) + )) + |) + |) in + M.pure Constant.None_)). + +Definition is_account_alive : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "state"; "address" ] |) in + let _ := Constant.str " + Check whether is an account is both in the state and non empty. + + Parameters + ---------- + state: + The state + address: + Address of the account that needs to be checked. + + Returns + ------- + is_alive : `bool` + True if the account is alive. + " in + let _ := M.assign_local (| + "account" , + M.call (| + M.get_name (| globals, "get_account_optional" |), + make_list [ + M.get_name (| globals, "state" |); + M.get_name (| globals, "address" |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.is (| + M.get_name (| globals, "account" |), + Constant.None_ + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + Constant.bool false + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.return_ (| + UnOp.not (| BoolOp.and (| + Compare.eq (| + M.get_field (| M.get_name (| globals, "account" |), "nonce" |), + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + |), + ltac:(M.monadic ( + BoolOp.and (| + Compare.eq (| + M.get_field (| M.get_name (| globals, "account" |), "code" |), + Constant.bytes "" + |), + ltac:(M.monadic ( + Compare.eq (| + M.get_field (| M.get_name (| globals, "account" |), "balance" |), + Constant.int 0 + |) + )) + |) + )) + |) |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_)). + +Definition modify_state : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "state"; "address"; "f" ] |) in + let _ := Constant.str " + Modify an `Account` in the `State`. + " in + let _ := M.call (| + M.get_name (| globals, "set_account" |), + make_list [ + M.get_name (| globals, "state" |); + M.get_name (| globals, "address" |); + M.call (| + M.get_name (| globals, "modify" |), + make_list [ + M.call (| + M.get_name (| globals, "get_account" |), + make_list [ + M.get_name (| globals, "state" |); + M.get_name (| globals, "address" |) + ], + make_dict [] + |); + M.get_name (| globals, "f" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + M.pure Constant.None_)). + +Definition move_ether : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "state"; "sender_address"; "recipient_address"; "amount" ] |) in + let _ := Constant.str " + Move funds between accounts. + " in +(* At stmt: unsupported node type: FunctionDef *) +(* At stmt: unsupported node type: FunctionDef *) + let _ := M.call (| + M.get_name (| globals, "modify_state" |), + make_list [ + M.get_name (| globals, "state" |); + M.get_name (| globals, "sender_address" |); + M.get_name (| globals, "reduce_sender_balance" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "modify_state" |), + make_list [ + M.get_name (| globals, "state" |); + M.get_name (| globals, "recipient_address" |); + M.get_name (| globals, "increase_recipient_balance" |) + ], + make_dict [] + |) in + M.pure Constant.None_)). + +Definition set_account_balance : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "state"; "address"; "amount" ] |) in + let _ := Constant.str " + Sets the balance of an account. + + Parameters + ---------- + state: + The current state. + + address: + Address of the account whose nonce needs to be incremented. + + amount: + The amount that needs to set in balance. + " in +(* At stmt: unsupported node type: FunctionDef *) + let _ := M.call (| + M.get_name (| globals, "modify_state" |), + make_list [ + M.get_name (| globals, "state" |); + M.get_name (| globals, "address" |); + M.get_name (| globals, "set_balance" |) + ], + make_dict [] + |) in + M.pure Constant.None_)). + +Definition touch_account : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "state"; "address" ] |) in + let _ := Constant.str " + Initializes an account to state. + + Parameters + ---------- + state: + The current state. + + address: + The address of the account that need to initialised. + " in + let _ := + (* if *) + M.if_then_else (| + UnOp.not (| M.call (| + M.get_name (| globals, "account_exists" |), + make_list [ + M.get_name (| globals, "state" |); + M.get_name (| globals, "address" |) + ], + make_dict [] + |) |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, "set_account" |), + make_list [ + M.get_name (| globals, "state" |); + M.get_name (| globals, "address" |); + M.get_name (| globals, "EMPTY_ACCOUNT" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + M.pure Constant.None_)). + +Definition increment_nonce : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "state"; "address" ] |) in + let _ := Constant.str " + Increments the nonce of an account. + + Parameters + ---------- + state: + The current state. + + address: + Address of the account whose nonce needs to be incremented. + " in +(* At stmt: unsupported node type: FunctionDef *) + let _ := M.call (| + M.get_name (| globals, "modify_state" |), + make_list [ + M.get_name (| globals, "state" |); + M.get_name (| globals, "address" |); + M.get_name (| globals, "increase_nonce" |) + ], + make_dict [] + |) in + M.pure Constant.None_)). + +Definition set_code : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "state"; "address"; "code" ] |) in + let _ := Constant.str " + Sets Account code. + + Parameters + ---------- + state: + The current state. + + address: + Address of the account whose code needs to be update. + + code: + The bytecode that needs to be set. + " in +(* At stmt: unsupported node type: FunctionDef *) + let _ := M.call (| + M.get_name (| globals, "modify_state" |), + make_list [ + M.get_name (| globals, "state" |); + M.get_name (| globals, "address" |); + M.get_name (| globals, "write_code" |) + ], + make_dict [] + |) in + M.pure Constant.None_)). + +Definition create_ether : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "state"; "address"; "amount" ] |) in + let _ := Constant.str " + Add newly created ether to an account. + + Parameters + ---------- + state: + The current state. + address: + Address of the account to which ether is added. + amount: + The amount of ether to be added to the account of interest. + " in +(* At stmt: unsupported node type: FunctionDef *) + let _ := M.call (| + M.get_name (| globals, "modify_state" |), + make_list [ + M.get_name (| globals, "state" |); + M.get_name (| globals, "address" |); + M.get_name (| globals, "increase_balance" |) + ], + make_dict [] + |) in + M.pure Constant.None_)). + +Definition get_storage_original : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "state"; "address"; "key" ] |) in + let _ := Constant.str " + Get the original value in a storage slot i.e. the value before the current + transaction began. This function reads the value from the snapshots taken + before executing the transaction. + + Parameters + ---------- + state: + The current state. + address: + Address of the account to read the value from. + key: + Key of the storage slot. + " in + let _ := + (* if *) + M.if_then_else (| + Compare.in_ (| + M.get_name (| globals, "address" |), + M.get_field (| M.get_name (| globals, "state" |), "_created_accounts" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign (| + make_tuple [ M.get_name (| globals, "_" |); M.get_name (| globals, "original_trie" |) ], + M.get_subscript (| + M.get_field (| M.get_name (| globals, "state" |), "_snapshots" |), + Constant.int 0 + |) + |) in + let _ := M.assign_local (| + "original_account_trie" , + M.call (| + M.get_field (| M.get_name (| globals, "original_trie" |), "get" |), + make_list [ + M.get_name (| globals, "address" |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.is (| + M.get_name (| globals, "original_account_trie" |), + Constant.None_ + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "original_value" , + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "original_value" , + M.call (| + M.get_name (| globals, "trie_get" |), + make_list [ + M.get_name (| globals, "original_account_trie" |); + M.get_name (| globals, "key" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + )) |) in + let _ := M.assert (| M.call (| + M.get_name (| globals, "isinstance" |), + make_list [ + M.get_name (| globals, "original_value" |); + M.get_name (| globals, "U256" |) + ], + make_dict [] + |) |) in + let _ := M.return_ (| + M.get_name (| globals, "original_value" |) + |) in + M.pure Constant.None_)). diff --git a/CoqOfPython/ethereum/berlin/transactions.v b/CoqOfPython/ethereum/berlin/transactions.v new file mode 100644 index 0000000..bafffab --- /dev/null +++ b/CoqOfPython/ethereum/berlin/transactions.v @@ -0,0 +1,220 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.berlin.transactions". + +Definition expr_1 : Value.t := + Constant.str " +Transactions are atomic units of work created externally to Ethereum and +submitted to be executed. If Ethereum is viewed as a state machine, +transactions are the events that move between states. +". + +Axiom dataclasses_imports_dataclass : + IsImported globals "dataclasses" "dataclass". + +Axiom typing_imports_Tuple : + IsImported globals "typing" "Tuple". +Axiom typing_imports_Union : + IsImported globals "typing" "Union". + +Axiom ethereum_imports_rlp : + IsImported globals "ethereum" "rlp". + +Axiom ethereum_base_types_imports_U64 : + IsImported globals "ethereum.base_types" "U64". +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_Bytes : + IsImported globals "ethereum.base_types" "Bytes". +Axiom ethereum_base_types_imports_Bytes0 : + IsImported globals "ethereum.base_types" "Bytes0". +Axiom ethereum_base_types_imports_Bytes32 : + IsImported globals "ethereum.base_types" "Bytes32". +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". +Axiom ethereum_base_types_imports_slotted_freezable : + IsImported globals "ethereum.base_types" "slotted_freezable". + +Axiom ethereum_exceptions_imports_InvalidBlock : + IsImported globals "ethereum.exceptions" "InvalidBlock". + +Axiom ethereum_utils_ensure_imports_ensure : + IsImported globals "ethereum.utils.ensure" "ensure". + +Axiom ethereum_berlin_fork_types_imports_Address : + IsImported globals "ethereum.berlin.fork_types" "Address". + +Definition TX_BASE_COST : Value.t := M.run ltac:(M.monadic ( + Constant.int 21000 +)). + +Definition TX_DATA_COST_PER_NON_ZERO : Value.t := M.run ltac:(M.monadic ( + Constant.int 16 +)). + +Definition TX_DATA_COST_PER_ZERO : Value.t := M.run ltac:(M.monadic ( + Constant.int 4 +)). + +Definition TX_CREATE_COST : Value.t := M.run ltac:(M.monadic ( + Constant.int 32000 +)). + +Definition TX_ACCESS_LIST_ADDRESS_COST : Value.t := M.run ltac:(M.monadic ( + Constant.int 2400 +)). + +Definition TX_ACCESS_LIST_STORAGE_KEY_COST : Value.t := M.run ltac:(M.monadic ( + Constant.int 1900 +)). + +Definition LegacyTransaction : Value.t := + builtins.make_klass + [] + [ + + ] + [ + + ]. + +Definition AccessListTransaction : Value.t := + builtins.make_klass + [] + [ + + ] + [ + + ]. + +Definition Transaction : Value.t := M.run ltac:(M.monadic ( + M.get_subscript (| + M.get_name (| globals, "Union" |), + make_tuple [ M.get_name (| globals, "LegacyTransaction" |); M.get_name (| globals, "AccessListTransaction" |) ] + |) +)). + +Definition encode_transaction : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "tx" ] |) in + let _ := Constant.str " + Encode a transaction. Needed because non-legacy transactions aren't RLP. + " in + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, "isinstance" |), + make_list [ + M.get_name (| globals, "tx" |); + M.get_name (| globals, "LegacyTransaction" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + M.get_name (| globals, "tx" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, "isinstance" |), + make_list [ + M.get_name (| globals, "tx" |); + M.get_name (| globals, "AccessListTransaction" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + BinOp.add (| + Constant.bytes "01", + M.call (| + M.get_field (| M.get_name (| globals, "rlp" |), "encode" |), + make_list [ + M.get_name (| globals, "tx" |) + ], + make_dict [] + |) + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.raise (| Some (M.call (| + M.get_name (| globals, "Exception" |), + make_list [ + Constant.str "(* At expr: unsupported node type: JoinedStr *)" + ], + make_dict [] + |)) |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_)). + +Definition decode_transaction : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "tx" ] |) in + let _ := Constant.str " + Decode a transaction. Needed because non-legacy transactions aren't RLP. + " in + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, "isinstance" |), + make_list [ + M.get_name (| globals, "tx" |); + M.get_name (| globals, "Bytes" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + Compare.eq (| + M.get_subscript (| + M.get_name (| globals, "tx" |), + Constant.int 0 + |), + Constant.int 1 + |); + M.get_name (| globals, "InvalidBlock" |) + ], + make_dict [] + |) in + let _ := M.return_ (| + M.call (| + M.get_field (| M.get_name (| globals, "rlp" |), "decode_to" |), + make_list [ + M.get_name (| globals, "AccessListTransaction" |); + M.slice (| + M.get_name (| globals, "tx" |), + Constant.int 1, + Constant.None_, + Constant.None_ + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.return_ (| + M.get_name (| globals, "tx" |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_)). diff --git a/CoqOfPython/ethereum/berlin/trie.v b/CoqOfPython/ethereum/berlin/trie.v new file mode 100644 index 0000000..9dbed51 --- /dev/null +++ b/CoqOfPython/ethereum/berlin/trie.v @@ -0,0 +1,1595 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.berlin.trie". + +Definition expr_1 : Value.t := + Constant.str " +State Trie +^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +The state trie is the structure responsible for storing +`.fork_types.Account` objects. +". + +(* At top_level_stmt: unsupported node type: Import *) + +Axiom dataclasses_imports_dataclass : + IsImported globals "dataclasses" "dataclass". +Axiom dataclasses_imports_field : + IsImported globals "dataclasses" "field". + +Axiom typing_imports_Callable : + IsImported globals "typing" "Callable". +Axiom typing_imports_Dict : + IsImported globals "typing" "Dict". +Axiom typing_imports_Generic : + IsImported globals "typing" "Generic". +Axiom typing_imports_List : + IsImported globals "typing" "List". +Axiom typing_imports_Mapping : + IsImported globals "typing" "Mapping". +Axiom typing_imports_MutableMapping : + IsImported globals "typing" "MutableMapping". +Axiom typing_imports_Optional : + IsImported globals "typing" "Optional". +Axiom typing_imports_Sequence : + IsImported globals "typing" "Sequence". +Axiom typing_imports_TypeVar : + IsImported globals "typing" "TypeVar". +Axiom typing_imports_Union : + IsImported globals "typing" "Union". +Axiom typing_imports_cast : + IsImported globals "typing" "cast". + +Axiom ethereum_crypto_hash_imports_keccak256 : + IsImported globals "ethereum.crypto.hash" "keccak256". + +Axiom ethereum_muir_glacier_imports_trie : + IsImported globals "ethereum.muir_glacier" "trie". + +Axiom ethereum_utils_ensure_imports_ensure : + IsImported globals "ethereum.utils.ensure" "ensure". + +Axiom ethereum_utils_hexadecimal_imports_hex_to_bytes : + IsImported globals "ethereum.utils.hexadecimal" "hex_to_bytes". + +Axiom ethereum_imports_rlp : + IsImported globals "ethereum" "rlp". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_Bytes : + IsImported globals "ethereum.base_types" "Bytes". +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". +Axiom ethereum_base_types_imports_slotted_freezable : + IsImported globals "ethereum.base_types" "slotted_freezable". + +Axiom ethereum_berlin_blocks_imports_Receipt : + IsImported globals "ethereum.berlin.blocks" "Receipt". + +Axiom ethereum_berlin_fork_types_imports_Account : + IsImported globals "ethereum.berlin.fork_types" "Account". +Axiom ethereum_berlin_fork_types_imports_Address : + IsImported globals "ethereum.berlin.fork_types" "Address". +Axiom ethereum_berlin_fork_types_imports_Root : + IsImported globals "ethereum.berlin.fork_types" "Root". +Axiom ethereum_berlin_fork_types_imports_encode_account : + IsImported globals "ethereum.berlin.fork_types" "encode_account". + +Axiom ethereum_berlin_transactions_imports_LegacyTransaction : + IsImported globals "ethereum.berlin.transactions" "LegacyTransaction". + +Definition EMPTY_TRIE_ROOT : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Root" |), + make_list [ + M.call (| + M.get_name (| globals, "hex_to_bytes" |), + make_list [ + Constant.str "56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421" + ], + make_dict [] + |) + ], + make_dict [] + |) +)). + +Definition Node : Value.t := M.run ltac:(M.monadic ( + M.get_subscript (| + M.get_name (| globals, "Union" |), + make_tuple [ M.get_name (| globals, "Account" |); M.get_name (| globals, "Bytes" |); M.get_name (| globals, "LegacyTransaction" |); M.get_name (| globals, "Receipt" |); M.get_name (| globals, "Uint" |); M.get_name (| globals, "U256" |); Constant.None_ ] + |) +)). + +Definition K : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "TypeVar" |), + make_list [ + Constant.str "K" + ], + make_dict [] + |) +)). + +Definition V : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "TypeVar" |), + make_list [ + Constant.str "V"; + M.get_subscript (| + M.get_name (| globals, "Optional" |), + M.get_name (| globals, "Account" |) + |); + M.get_subscript (| + M.get_name (| globals, "Optional" |), + M.get_name (| globals, "Bytes" |) + |); + M.get_name (| globals, "Bytes" |); + M.get_subscript (| + M.get_name (| globals, "Optional" |), + M.get_subscript (| + M.get_name (| globals, "Union" |), + make_tuple [ M.get_name (| globals, "LegacyTransaction" |); M.get_name (| globals, "Bytes" |) ] + |) + |); + M.get_subscript (| + M.get_name (| globals, "Optional" |), + M.get_subscript (| + M.get_name (| globals, "Union" |), + make_tuple [ M.get_name (| globals, "Receipt" |); M.get_name (| globals, "Bytes" |) ] + |) + |); + M.get_name (| globals, "Uint" |); + M.get_name (| globals, "U256" |) + ], + make_dict [] + |) +)). + +Definition LeafNode : Value.t := + builtins.make_klass + [] + [ + + ] + [ + + ]. + +Definition ExtensionNode : Value.t := + builtins.make_klass + [] + [ + + ] + [ + + ]. + +Definition BranchNode : Value.t := + builtins.make_klass + [] + [ + + ] + [ + + ]. + +Definition InternalNode : Value.t := M.run ltac:(M.monadic ( + M.get_subscript (| + M.get_name (| globals, "Union" |), + make_tuple [ M.get_name (| globals, "LeafNode" |); M.get_name (| globals, "ExtensionNode" |); M.get_name (| globals, "BranchNode" |) ] + |) +)). + +Definition encode_internal_node : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "node" ] |) in + let _ := Constant.str " + Encodes a Merkle Trie node into its RLP form. The RLP will then be + serialized into a `Bytes` and hashed unless it is less that 32 bytes + when serialized. + + This function also accepts `None`, representing the absence of a node, + which is encoded to `b""""`. + + Parameters + ---------- + node : Optional[InternalNode] + The node to encode. + + Returns + ------- + encoded : `rlp.RLP` + The node encoded as RLP. + " in +(* At stmt: unsupported node type: AnnAssign *) + let _ := + (* if *) + M.if_then_else (| + Compare.is (| + M.get_name (| globals, "node" |), + Constant.None_ + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "unencoded" , + Constant.bytes "" + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, "isinstance" |), + make_list [ + M.get_name (| globals, "node" |); + M.get_name (| globals, "LeafNode" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "unencoded" , + make_tuple [ M.call (| + M.get_name (| globals, "nibble_list_to_compact" |), + make_list [ + M.get_field (| M.get_name (| globals, "node" |), "rest_of_key" |); + Constant.bool true + ], + make_dict [] + |); M.get_field (| M.get_name (| globals, "node" |), "value" |) ] + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, "isinstance" |), + make_list [ + M.get_name (| globals, "node" |); + M.get_name (| globals, "ExtensionNode" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "unencoded" , + make_tuple [ M.call (| + M.get_name (| globals, "nibble_list_to_compact" |), + make_list [ + M.get_field (| M.get_name (| globals, "node" |), "key_segment" |); + Constant.bool false + ], + make_dict [] + |); M.get_field (| M.get_name (| globals, "node" |), "subnode" |) ] + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, "isinstance" |), + make_list [ + M.get_name (| globals, "node" |); + M.get_name (| globals, "BranchNode" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "unencoded" , + BinOp.add (| + M.get_field (| M.get_name (| globals, "node" |), "subnodes" |), + make_list [ + M.get_field (| M.get_name (| globals, "node" |), "value" |) + ] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.raise (| Some (M.call (| + M.get_name (| globals, "AssertionError" |), + make_list [ + Constant.str "(* At expr: unsupported node type: JoinedStr *)" + ], + make_dict [] + |)) |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "encoded" , + M.call (| + M.get_field (| M.get_name (| globals, "rlp" |), "encode" |), + make_list [ + M.get_name (| globals, "unencoded" |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.lt (| + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_name (| globals, "encoded" |) + ], + make_dict [] + |), + Constant.int 32 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + M.get_name (| globals, "unencoded" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.return_ (| + M.call (| + M.get_name (| globals, "keccak256" |), + make_list [ + M.get_name (| globals, "encoded" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_)). + +Definition encode_node : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "node"; "storage_root" ] |) in + let _ := Constant.str " + Encode a Node for storage in the Merkle Trie. + + Currently mostly an unimplemented stub. + " in + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, "isinstance" |), + make_list [ + M.get_name (| globals, "node" |); + M.get_name (| globals, "Account" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assert (| Compare.is_not (| + M.get_name (| globals, "storage_root" |), + Constant.None_ + |) |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, "encode_account" |), + make_list [ + M.get_name (| globals, "node" |); + M.get_name (| globals, "storage_root" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, "isinstance" |), + make_list [ + M.get_name (| globals, "node" |); + make_tuple [ M.get_name (| globals, "LegacyTransaction" |); M.get_name (| globals, "Receipt" |); M.get_name (| globals, "U256" |) ] + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + M.call (| + M.get_field (| M.get_name (| globals, "rlp" |), "encode" |), + make_list [ + M.call (| + M.get_name (| globals, "cast" |), + make_list [ + M.get_field (| M.get_name (| globals, "rlp" |), "RLP" |); + M.get_name (| globals, "node" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, "isinstance" |), + make_list [ + M.get_name (| globals, "node" |); + M.get_name (| globals, "Bytes" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + M.get_name (| globals, "node" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.return_ (| + M.call (| + M.get_field (| M.get_name (| globals, "previous_trie" |), "encode_node" |), + make_list [ + M.get_name (| globals, "node" |); + M.get_name (| globals, "storage_root" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_)). + +Definition Trie : Value.t := + builtins.make_klass + [(* At base: unsupported node type: Subscript *)] + [ + + ] + [ + + ]. + +Definition copy_trie : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "trie" ] |) in + let _ := Constant.str " + Create a copy of `trie`. Since only frozen objects may be stored in tries, + the contents are reused. + + Parameters + ---------- + trie: `Trie` + Trie to copy. + + Returns + ------- + new_trie : `Trie[K, V]` + A copy of the trie. + " in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, "Trie" |), + make_list [ + M.get_field (| M.get_name (| globals, "trie" |), "secured" |); + M.get_field (| M.get_name (| globals, "trie" |), "default" |); + M.call (| + M.get_field (| M.get_name (| globals, "copy" |), "copy" |), + make_list [ + M.get_field (| M.get_name (| globals, "trie" |), "_data" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Definition trie_set : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "trie"; "key"; "value" ] |) in + let _ := Constant.str " + Stores an item in a Merkle Trie. + + This method deletes the key if `value == trie.default`, because the Merkle + Trie represents the default value by omitting it from the trie. + + Parameters + ---------- + trie: `Trie` + Trie to store in. + key : `Bytes` + Key to lookup. + value : `V` + Node to insert at `key`. + " in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, "value" |), + M.get_field (| M.get_name (| globals, "trie" |), "default" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + Compare.in_ (| + M.get_name (| globals, "key" |), + M.get_field (| M.get_name (| globals, "trie" |), "_data" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.delete (| M.get_subscript (| + M.get_field (| M.get_name (| globals, "trie" |), "_data" |), + M.get_name (| globals, "key" |) + |) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign (| + M.get_subscript (| + M.get_field (| M.get_name (| globals, "trie" |), "_data" |), + M.get_name (| globals, "key" |) + |), + M.get_name (| globals, "value" |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_)). + +Definition trie_get : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "trie"; "key" ] |) in + let _ := Constant.str " + Gets an item from the Merkle Trie. + + This method returns `trie.default` if the key is missing. + + Parameters + ---------- + trie: + Trie to lookup in. + key : + Key to lookup. + + Returns + ------- + node : `V` + Node at `key` in the trie. + " in + let _ := M.return_ (| + M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, "trie" |), "_data" |), "get" |), + make_list [ + M.get_name (| globals, "key" |); + M.get_field (| M.get_name (| globals, "trie" |), "default" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Definition common_prefix_length : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "a"; "b" ] |) in + let _ := Constant.str " + Find the longest common prefix of two sequences. + " in + let _ := + M.for_ (| + M.get_name (| globals, "i" |), + M.call (| + M.get_name (| globals, "range" |), + make_list [ + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_name (| globals, "a" |) + ], + make_dict [] + |) + ], + make_dict [] + |), + ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + BoolOp.or (| + Compare.gt_e (| + M.get_name (| globals, "i" |), + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_name (| globals, "b" |) + ], + make_dict [] + |) + |), + ltac:(M.monadic ( + Compare.not_eq (| + M.get_subscript (| + M.get_name (| globals, "a" |), + M.get_name (| globals, "i" |) + |), + M.get_subscript (| + M.get_name (| globals, "b" |), + M.get_name (| globals, "i" |) + |) + |) + )) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + M.get_name (| globals, "i" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_name (| globals, "a" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Definition nibble_list_to_compact : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "x"; "is_leaf" ] |) in + let _ := Constant.str " + Compresses nibble-list into a standard byte array with a flag. + + A nibble-list is a list of byte values no greater than `15`. The flag is + encoded in high nibble of the highest byte. The flag nibble can be broken + down into two two-bit flags. + + Highest nibble:: + + +---+---+----------+--------+ + | _ | _ | is_leaf | parity | + +---+---+----------+--------+ + 3 2 1 0 + + + The lowest bit of the nibble encodes the parity of the length of the + remaining nibbles -- `0` when even and `1` when odd. The second lowest bit + is used to distinguish leaf and extension nodes. The other two bits are not + used. + + Parameters + ---------- + x : + Array of nibbles. + is_leaf : + True if this is part of a leaf node, or false if it is an extension + node. + + Returns + ------- + compressed : `bytearray` + Compact byte array. + " in + let _ := M.assign_local (| + "compact" , + M.call (| + M.get_name (| globals, "bytearray" |), + make_list [], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + BinOp.mod_ (| + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_name (| globals, "x" |) + ], + make_dict [] + |), + Constant.int 2 + |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_field (| M.get_name (| globals, "compact" |), "append" |), + make_list [ + BinOp.mult (| + Constant.int 16, + BinOp.mult (| + Constant.int 2, + M.get_name (| globals, "is_leaf" |) + |) + |) + ], + make_dict [] + |) in + let _ := + M.for_ (| + M.get_name (| globals, "i" |), + M.call (| + M.get_name (| globals, "range" |), + make_list [ + Constant.int 0; + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_name (| globals, "x" |) + ], + make_dict [] + |); + Constant.int 2 + ], + make_dict [] + |), + ltac:(M.monadic ( + let _ := M.call (| + M.get_field (| M.get_name (| globals, "compact" |), "append" |), + make_list [ + BinOp.add (| + BinOp.mult (| + Constant.int 16, + M.get_subscript (| + M.get_name (| globals, "x" |), + M.get_name (| globals, "i" |) + |) + |), + M.get_subscript (| + M.get_name (| globals, "x" |), + BinOp.add (| + M.get_name (| globals, "i" |), + Constant.int 1 + |) + |) + |) + ], + make_dict [] + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.call (| + M.get_field (| M.get_name (| globals, "compact" |), "append" |), + make_list [ + BinOp.add (| + BinOp.mult (| + Constant.int 16, + BinOp.add (| + BinOp.mult (| + Constant.int 2, + M.get_name (| globals, "is_leaf" |) + |), + Constant.int 1 + |) + |), + M.get_subscript (| + M.get_name (| globals, "x" |), + Constant.int 0 + |) + |) + ], + make_dict [] + |) in + let _ := + M.for_ (| + M.get_name (| globals, "i" |), + M.call (| + M.get_name (| globals, "range" |), + make_list [ + Constant.int 1; + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_name (| globals, "x" |) + ], + make_dict [] + |); + Constant.int 2 + ], + make_dict [] + |), + ltac:(M.monadic ( + let _ := M.call (| + M.get_field (| M.get_name (| globals, "compact" |), "append" |), + make_list [ + BinOp.add (| + BinOp.mult (| + Constant.int 16, + M.get_subscript (| + M.get_name (| globals, "x" |), + M.get_name (| globals, "i" |) + |) + |), + M.get_subscript (| + M.get_name (| globals, "x" |), + BinOp.add (| + M.get_name (| globals, "i" |), + Constant.int 1 + |) + |) + |) + ], + make_dict [] + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + M.pure Constant.None_ + )) |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, "Bytes" |), + make_list [ + M.get_name (| globals, "compact" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Definition bytes_to_nibble_list : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "bytes_" ] |) in + let _ := Constant.str " + Converts a `Bytes` into to a sequence of nibbles (bytes with value < 16). + + Parameters + ---------- + bytes_: + The `Bytes` to convert. + + Returns + ------- + nibble_list : `Bytes` + The `Bytes` in nibble-list format. + " in + let _ := M.assign_local (| + "nibble_list" , + M.call (| + M.get_name (| globals, "bytearray" |), + make_list [ + BinOp.mult (| + Constant.int 2, + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_name (| globals, "bytes_" |) + ], + make_dict [] + |) + |) + ], + make_dict [] + |) + |) in + let _ := + M.for_ (| + make_tuple [ M.get_name (| globals, "byte_index" |); M.get_name (| globals, "byte" |) ], + M.call (| + M.get_name (| globals, "enumerate" |), + make_list [ + M.get_name (| globals, "bytes_" |) + ], + make_dict [] + |), + ltac:(M.monadic ( + let _ := M.assign (| + M.get_subscript (| + M.get_name (| globals, "nibble_list" |), + BinOp.mult (| + M.get_name (| globals, "byte_index" |), + Constant.int 2 + |) + |), + BinOp.r_shift (| + BinOp.bit_and (| + M.get_name (| globals, "byte" |), + Constant.int 240 + |), + Constant.int 4 + |) + |) in + let _ := M.assign (| + M.get_subscript (| + M.get_name (| globals, "nibble_list" |), + BinOp.add (| + BinOp.mult (| + M.get_name (| globals, "byte_index" |), + Constant.int 2 + |), + Constant.int 1 + |) + |), + BinOp.bit_and (| + M.get_name (| globals, "byte" |), + Constant.int 15 + |) + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, "Bytes" |), + make_list [ + M.get_name (| globals, "nibble_list" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Definition _prepare_trie : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "trie"; "get_storage_root" ] |) in + let _ := Constant.str " + Prepares the trie for root calculation. Removes values that are empty, + hashes the keys (if `secured == True`) and encodes all the nodes. + + Parameters + ---------- + trie : + The `Trie` to prepare. + get_storage_root : + Function to get the storage root of an account. Needed to encode + `Account` objects. + + Returns + ------- + out : `Mapping[ethereum.base_types.Bytes, Node]` + Object with keys mapped to nibble-byte form. + " in +(* At stmt: unsupported node type: AnnAssign *) + let _ := + M.for_ (| + make_tuple [ M.get_name (| globals, "preimage" |); M.get_name (| globals, "value" |) ], + M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, "trie" |), "_data" |), "items" |), + make_list [], + make_dict [] + |), + ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, "isinstance" |), + make_list [ + M.get_name (| globals, "value" |); + M.get_name (| globals, "Account" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assert (| Compare.is_not (| + M.get_name (| globals, "get_storage_root" |), + Constant.None_ + |) |) in + let _ := M.assign_local (| + "address" , + M.call (| + M.get_name (| globals, "Address" |), + make_list [ + M.get_name (| globals, "preimage" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "encoded_value" , + M.call (| + M.get_name (| globals, "encode_node" |), + make_list [ + M.get_name (| globals, "value" |); + M.call (| + M.get_name (| globals, "get_storage_root" |), + make_list [ + M.get_name (| globals, "address" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "encoded_value" , + M.call (| + M.get_name (| globals, "encode_node" |), + make_list [ + M.get_name (| globals, "value" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + )) |) in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + Compare.not_eq (| + M.get_name (| globals, "encoded_value" |), + Constant.bytes "" + |); + M.get_name (| globals, "AssertionError" |) + ], + make_dict [] + |) in +(* At stmt: unsupported node type: AnnAssign *) + let _ := + (* if *) + M.if_then_else (| + M.get_field (| M.get_name (| globals, "trie" |), "secured" |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "key" , + M.call (| + M.get_name (| globals, "keccak256" |), + make_list [ + M.get_name (| globals, "preimage" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "key" , + M.get_name (| globals, "preimage" |) + |) in + M.pure Constant.None_ + )) |) in + let _ := M.assign (| + M.get_subscript (| + M.get_name (| globals, "mapped" |), + M.call (| + M.get_name (| globals, "bytes_to_nibble_list" |), + make_list [ + M.get_name (| globals, "key" |) + ], + make_dict [] + |) + |), + M.get_name (| globals, "encoded_value" |) + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := M.return_ (| + M.get_name (| globals, "mapped" |) + |) in + M.pure Constant.None_)). + +Definition root : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "trie"; "get_storage_root" ] |) in + let _ := Constant.str " + Computes the root of a modified merkle patricia trie (MPT). + + Parameters + ---------- + trie : + `Trie` to get the root of. + get_storage_root : + Function to get the storage root of an account. Needed to encode + `Account` objects. + + + Returns + ------- + root : `eth1spec.fork_types.Root` + MPT root of the underlying key-value pairs. + " in + let _ := M.assign_local (| + "obj" , + M.call (| + M.get_name (| globals, "_prepare_trie" |), + make_list [ + M.get_name (| globals, "trie" |); + M.get_name (| globals, "get_storage_root" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "root_node" , + M.call (| + M.get_name (| globals, "encode_internal_node" |), + make_list [ + M.call (| + M.get_name (| globals, "patricialize" |), + make_list [ + M.get_name (| globals, "obj" |); + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.lt (| + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.call (| + M.get_field (| M.get_name (| globals, "rlp" |), "encode" |), + make_list [ + M.get_name (| globals, "root_node" |) + ], + make_dict [] + |) + ], + make_dict [] + |), + Constant.int 32 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + M.call (| + M.get_name (| globals, "keccak256" |), + make_list [ + M.call (| + M.get_field (| M.get_name (| globals, "rlp" |), "encode" |), + make_list [ + M.get_name (| globals, "root_node" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assert (| M.call (| + M.get_name (| globals, "isinstance" |), + make_list [ + M.get_name (| globals, "root_node" |); + M.get_name (| globals, "Bytes" |) + ], + make_dict [] + |) |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, "Root" |), + make_list [ + M.get_name (| globals, "root_node" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_)). + +Definition patricialize : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "obj"; "level" ] |) in + let _ := Constant.str " + Structural composition function. + + Used to recursively patricialize and merkleize a dictionary. Includes + memoization of the tree structure and hashes. + + Parameters + ---------- + obj : + Underlying trie key-value pairs, with keys in nibble-list format. + level : + Current trie level. + + Returns + ------- + node : `eth1spec.base_types.Bytes` + Root node of `obj`. + " in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_name (| globals, "obj" |) + ], + make_dict [] + |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + Constant.None_ + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "arbitrary_key" , + M.call (| + M.get_name (| globals, "next" |), + make_list [ + M.call (| + M.get_name (| globals, "iter" |), + make_list [ + M.get_name (| globals, "obj" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_name (| globals, "obj" |) + ], + make_dict [] + |), + Constant.int 1 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "leaf" , + M.call (| + M.get_name (| globals, "LeafNode" |), + make_list [ + M.slice (| + M.get_name (| globals, "arbitrary_key" |), + M.get_name (| globals, "level" |), + Constant.None_, + Constant.None_ + |); + M.get_subscript (| + M.get_name (| globals, "obj" |), + M.get_name (| globals, "arbitrary_key" |) + |) + ], + make_dict [] + |) + |) in + let _ := M.return_ (| + M.get_name (| globals, "leaf" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "substring" , + M.slice (| + M.get_name (| globals, "arbitrary_key" |), + M.get_name (| globals, "level" |), + Constant.None_, + Constant.None_ + |) + |) in + let _ := M.assign_local (| + "prefix_length" , + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_name (| globals, "substring" |) + ], + make_dict [] + |) + |) in + let _ := + M.for_ (| + M.get_name (| globals, "key" |), + M.get_name (| globals, "obj" |), + ltac:(M.monadic ( + let _ := M.assign_local (| + "prefix_length" , + M.call (| + M.get_name (| globals, "min" |), + make_list [ + M.get_name (| globals, "prefix_length" |); + M.call (| + M.get_name (| globals, "common_prefix_length" |), + make_list [ + M.get_name (| globals, "substring" |); + M.slice (| + M.get_name (| globals, "key" |), + M.get_name (| globals, "level" |), + Constant.None_, + Constant.None_ + |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, "prefix_length" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.break (| |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.gt (| + M.get_name (| globals, "prefix_length" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "prefix" , + M.slice (| + M.get_name (| globals, "arbitrary_key" |), + M.get_name (| globals, "level" |), + BinOp.add (| + M.get_name (| globals, "level" |), + M.get_name (| globals, "prefix_length" |) + |), + Constant.None_ + |) + |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, "ExtensionNode" |), + make_list [ + M.get_name (| globals, "prefix" |); + M.call (| + M.get_name (| globals, "encode_internal_node" |), + make_list [ + M.call (| + M.get_name (| globals, "patricialize" |), + make_list [ + M.get_name (| globals, "obj" |); + BinOp.add (| + M.get_name (| globals, "level" |), + M.get_name (| globals, "prefix_length" |) + |) + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in +(* At stmt: unsupported node type: AnnAssign *) + let _ := + M.for_ (| + M.get_name (| globals, "_" |), + M.call (| + M.get_name (| globals, "range" |), + make_list [ + Constant.int 16 + ], + make_dict [] + |), + ltac:(M.monadic ( + let _ := M.call (| + M.get_field (| M.get_name (| globals, "branches" |), "append" |), + make_list [ + Constant.str "(* At expr: unsupported node type: Dict *)" + ], + make_dict [] + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := M.assign_local (| + "value" , + Constant.bytes "" + |) in + let _ := + M.for_ (| + M.get_name (| globals, "key" |), + M.get_name (| globals, "obj" |), + ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_name (| globals, "key" |) + ], + make_dict [] + |), + M.get_name (| globals, "level" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, "isinstance" |), + make_list [ + M.get_subscript (| + M.get_name (| globals, "obj" |), + M.get_name (| globals, "key" |) + |); + make_tuple [ M.get_name (| globals, "Account" |); M.get_name (| globals, "Receipt" |); M.get_name (| globals, "Uint" |) ] + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, "AssertionError" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "value" , + M.get_subscript (| + M.get_name (| globals, "obj" |), + M.get_name (| globals, "key" |) + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign (| + M.get_subscript (| + M.get_subscript (| + M.get_name (| globals, "branches" |), + M.get_subscript (| + M.get_name (| globals, "key" |), + M.get_name (| globals, "level" |) + |) + |), + M.get_name (| globals, "key" |) + |), + M.get_subscript (| + M.get_name (| globals, "obj" |), + M.get_name (| globals, "key" |) + |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, "BranchNode" |), + make_list [ + Constant.str "(* At expr: unsupported node type: ListComp *)"; + M.get_name (| globals, "value" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). diff --git a/CoqOfPython/ethereum/berlin/utils/__init__.v b/CoqOfPython/ethereum/berlin/utils/__init__.v new file mode 100644 index 0000000..0c0263a --- /dev/null +++ b/CoqOfPython/ethereum/berlin/utils/__init__.v @@ -0,0 +1,8 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.berlin.utils.__init__". + +Definition expr_1 : Value.t := + Constant.str " +Utility functions unique to this particular fork. +". diff --git a/CoqOfPython/ethereum/berlin/utils/address.v b/CoqOfPython/ethereum/berlin/utils/address.v new file mode 100644 index 0000000..dd8319d --- /dev/null +++ b/CoqOfPython/ethereum/berlin/utils/address.v @@ -0,0 +1,227 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.berlin.utils.address". + +Definition expr_1 : Value.t := + Constant.str " +Hardfork Utility Functions For Addresses +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Address specific functions used in this berlin version of +specification. +". + +Axiom typing_imports_Union : + IsImported globals "typing" "Union". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_Bytes32 : + IsImported globals "ethereum.base_types" "Bytes32". +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". + +Axiom ethereum_crypto_hash_imports_keccak256 : + IsImported globals "ethereum.crypto.hash" "keccak256". + +Axiom ethereum_utils_byte_imports_left_pad_zero_bytes : + IsImported globals "ethereum.utils.byte" "left_pad_zero_bytes". + +Axiom ethereum_imports_rlp : + IsImported globals "ethereum" "rlp". + +Axiom ethereum_berlin_fork_types_imports_Address : + IsImported globals "ethereum.berlin.fork_types" "Address". + +Definition to_address : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "data" ] |) in + let _ := Constant.str " + Convert a Uint or U256 value to a valid address (20 bytes). + + Parameters + ---------- + data : + The string to be converted to bytes. + + Returns + ------- + address : `Address` + The obtained address. + " in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, "Address" |), + make_list [ + M.slice (| + M.call (| + M.get_field (| M.get_name (| globals, "data" |), "to_be_bytes32" |), + make_list [], + make_dict [] + |), + UnOp.sub (| Constant.int 20 |), + Constant.None_, + Constant.None_ + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Definition compute_contract_address : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "address"; "nonce" ] |) in + let _ := Constant.str " + Computes address of the new account that needs to be created. + + Parameters + ---------- + address : + The address of the account that wants to create the new account. + nonce : + The transaction count of the account that wants to create the new + account. + + Returns + ------- + address: `Address` + The computed address of the new account. + " in + let _ := M.assign_local (| + "computed_address" , + M.call (| + M.get_name (| globals, "keccak256" |), + make_list [ + M.call (| + M.get_field (| M.get_name (| globals, "rlp" |), "encode" |), + make_list [ + make_list [ + M.get_name (| globals, "address" |); + M.get_name (| globals, "nonce" |) + ] + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "canonical_address" , + M.slice (| + M.get_name (| globals, "computed_address" |), + UnOp.sub (| Constant.int 20 |), + Constant.None_, + Constant.None_ + |) + |) in + let _ := M.assign_local (| + "padded_address" , + M.call (| + M.get_name (| globals, "left_pad_zero_bytes" |), + make_list [ + M.get_name (| globals, "canonical_address" |); + Constant.int 20 + ], + make_dict [] + |) + |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, "Address" |), + make_list [ + M.get_name (| globals, "padded_address" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Definition compute_create2_contract_address : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "address"; "salt"; "call_data" ] |) in + let _ := Constant.str " + Computes address of the new account that needs to be created, which is + based on the sender address, salt and the call data as well. + + Parameters + ---------- + address : + The address of the account that wants to create the new account. + salt : + Address generation salt. + call_data : + The code of the new account which is to be created. + + Returns + ------- + address: `ethereum.berlin.fork_types.Address` + The computed address of the new account. + " in + let _ := M.assign_local (| + "preimage" , + BinOp.add (| + BinOp.add (| + BinOp.add (| + Constant.bytes "ff", + M.get_name (| globals, "address" |) + |), + M.get_name (| globals, "salt" |) + |), + M.call (| + M.get_name (| globals, "keccak256" |), + make_list [ + M.get_name (| globals, "call_data" |) + ], + make_dict [] + |) + |) + |) in + let _ := M.assign_local (| + "computed_address" , + M.call (| + M.get_name (| globals, "keccak256" |), + make_list [ + M.get_name (| globals, "preimage" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "canonical_address" , + M.slice (| + M.get_name (| globals, "computed_address" |), + UnOp.sub (| Constant.int 20 |), + Constant.None_, + Constant.None_ + |) + |) in + let _ := M.assign_local (| + "padded_address" , + M.call (| + M.get_name (| globals, "left_pad_zero_bytes" |), + make_list [ + M.get_name (| globals, "canonical_address" |); + Constant.int 20 + ], + make_dict [] + |) + |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, "Address" |), + make_list [ + M.get_name (| globals, "padded_address" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). diff --git a/CoqOfPython/ethereum/berlin/utils/hexadecimal.v b/CoqOfPython/ethereum/berlin/utils/hexadecimal.v new file mode 100644 index 0000000..4b247b7 --- /dev/null +++ b/CoqOfPython/ethereum/berlin/utils/hexadecimal.v @@ -0,0 +1,153 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.berlin.utils.hexadecimal". + +Definition expr_1 : Value.t := + Constant.str " +Utility Functions For Hexadecimal Strings +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Hexadecimal utility functions used in this specification, specific to +Berlin types. +". + +Axiom ethereum_utils_hexadecimal_imports_remove_hex_prefix : + IsImported globals "ethereum.utils.hexadecimal" "remove_hex_prefix". + +Axiom ethereum_berlin_fork_types_imports_Address : + IsImported globals "ethereum.berlin.fork_types" "Address". +Axiom ethereum_berlin_fork_types_imports_Bloom : + IsImported globals "ethereum.berlin.fork_types" "Bloom". +Axiom ethereum_berlin_fork_types_imports_Root : + IsImported globals "ethereum.berlin.fork_types" "Root". + +Definition hex_to_root : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "hex_string" ] |) in + let _ := Constant.str " + Convert hex string to trie root. + + Parameters + ---------- + hex_string : + The hexadecimal string to be converted to trie root. + + Returns + ------- + root : `Root` + Trie root obtained from the given hexadecimal string. + " in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, "Root" |), + make_list [ + M.call (| + M.get_field (| M.get_name (| globals, "bytes" |), "fromhex" |), + make_list [ + M.call (| + M.get_name (| globals, "remove_hex_prefix" |), + make_list [ + M.get_name (| globals, "hex_string" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Definition hex_to_bloom : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "hex_string" ] |) in + let _ := Constant.str " + Convert hex string to bloom. + + Parameters + ---------- + hex_string : + The hexadecimal string to be converted to bloom. + + Returns + ------- + bloom : `Bloom` + Bloom obtained from the given hexadecimal string. + " in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, "Bloom" |), + make_list [ + M.call (| + M.get_field (| M.get_name (| globals, "bytes" |), "fromhex" |), + make_list [ + M.call (| + M.get_name (| globals, "remove_hex_prefix" |), + make_list [ + M.get_name (| globals, "hex_string" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Definition hex_to_address : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "hex_string" ] |) in + let _ := Constant.str " + Convert hex string to Address (20 bytes). + + Parameters + ---------- + hex_string : + The hexadecimal string to be converted to Address. + + Returns + ------- + address : `Address` + The address obtained from the given hexadecimal string. + " in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, "Address" |), + make_list [ + M.call (| + M.get_field (| M.get_name (| globals, "bytes" |), "fromhex" |), + make_list [ + M.call (| + M.get_field (| M.call (| + M.get_name (| globals, "remove_hex_prefix" |), + make_list [ + M.get_name (| globals, "hex_string" |) + ], + make_dict [] + |), "rjust" |), + make_list [ + Constant.int 40; + Constant.str "0" + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). diff --git a/CoqOfPython/ethereum/berlin/utils/message.v b/CoqOfPython/ethereum/berlin/utils/message.v new file mode 100644 index 0000000..6ce9be0 --- /dev/null +++ b/CoqOfPython/ethereum/berlin/utils/message.v @@ -0,0 +1,266 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.berlin.utils.message". + +Definition expr_1 : Value.t := + Constant.str " +Hardfork Utility Functions For The Message Data-structure +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Message specific functions used in this berlin version of +specification. +". + +Axiom typing_imports_FrozenSet : + IsImported globals "typing" "FrozenSet". +Axiom typing_imports_Optional : + IsImported globals "typing" "Optional". +Axiom typing_imports_Tuple : + IsImported globals "typing" "Tuple". +Axiom typing_imports_Union : + IsImported globals "typing" "Union". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_Bytes : + IsImported globals "ethereum.base_types" "Bytes". +Axiom ethereum_base_types_imports_Bytes0 : + IsImported globals "ethereum.base_types" "Bytes0". +Axiom ethereum_base_types_imports_Bytes32 : + IsImported globals "ethereum.base_types" "Bytes32". +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". + +Axiom ethereum_berlin_fork_types_imports_Address : + IsImported globals "ethereum.berlin.fork_types" "Address". + +Axiom ethereum_berlin_state_imports_get_account : + IsImported globals "ethereum.berlin.state" "get_account". + +Axiom ethereum_berlin_vm_imports_Environment : + IsImported globals "ethereum.berlin.vm" "Environment". +Axiom ethereum_berlin_vm_imports_Message : + IsImported globals "ethereum.berlin.vm" "Message". + +Axiom ethereum_berlin_vm_precompiled_contracts_mapping_imports_PRE_COMPILED_CONTRACTS : + IsImported globals "ethereum.berlin.vm.precompiled_contracts.mapping" "PRE_COMPILED_CONTRACTS". + +Axiom ethereum_berlin_utils_address_imports_compute_contract_address : + IsImported globals "ethereum.berlin.utils.address" "compute_contract_address". + +Definition prepare_message : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "caller"; "target"; "value"; "data"; "gas"; "env"; "code_address"; "should_transfer_value"; "is_static"; "preaccessed_addresses"; "preaccessed_storage_keys" ] |) in + let _ := Constant.str " + Execute a transaction against the provided environment. + + Parameters + ---------- + caller : + Address which initiated the transaction + target : + Address whose code will be executed + value : + Value to be transferred. + data : + Array of bytes provided to the code in `target`. + gas : + Gas provided for the code in `target`. + env : + Environment for the Ethereum Virtual Machine. + code_address : + This is usually same as the `target` address except when an alternative + accounts code needs to be executed. + eg. `CALLCODE` calling a precompile. + should_transfer_value : + if True ETH should be transferred while executing a message call. + is_static: + if True then it prevents all state-changing operations from being + executed. + preaccessed_addresses: + Addresses that should be marked as accessed prior to the message call + preaccessed_storage_keys: + Storage keys that should be marked as accessed prior to the message + call + + Returns + ------- + message: `ethereum.berlin.vm.Message` + Items containing contract creation or message call specific data. + " in + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, "isinstance" |), + make_list [ + M.get_name (| globals, "target" |); + M.get_name (| globals, "Bytes0" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "current_target" , + M.call (| + M.get_name (| globals, "compute_contract_address" |), + make_list [ + M.get_name (| globals, "caller" |); + BinOp.sub (| + M.get_field (| M.call (| + M.get_name (| globals, "get_account" |), + make_list [ + M.get_field (| M.get_name (| globals, "env" |), "state" |); + M.get_name (| globals, "caller" |) + ], + make_dict [] + |), "nonce" |), + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 1 + ], + make_dict [] + |) + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "msg_data" , + M.call (| + M.get_name (| globals, "Bytes" |), + make_list [ + Constant.bytes "" + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "code" , + M.get_name (| globals, "data" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, "isinstance" |), + make_list [ + M.get_name (| globals, "target" |); + M.get_name (| globals, "Address" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "current_target" , + M.get_name (| globals, "target" |) + |) in + let _ := M.assign_local (| + "msg_data" , + M.get_name (| globals, "data" |) + |) in + let _ := M.assign_local (| + "code" , + M.get_field (| M.call (| + M.get_name (| globals, "get_account" |), + make_list [ + M.get_field (| M.get_name (| globals, "env" |), "state" |); + M.get_name (| globals, "target" |) + ], + make_dict [] + |), "code" |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.is (| + M.get_name (| globals, "code_address" |), + Constant.None_ + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "code_address" , + M.get_name (| globals, "target" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.raise (| Some (M.call (| + M.get_name (| globals, "AssertionError" |), + make_list [ + Constant.str "Target must be address or empty bytes" + ], + make_dict [] + |)) |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "accessed_addresses" , + M.call (| + M.get_name (| globals, "set" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_field (| M.get_name (| globals, "accessed_addresses" |), "add" |), + make_list [ + M.get_name (| globals, "current_target" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_field (| M.get_name (| globals, "accessed_addresses" |), "add" |), + make_list [ + M.get_name (| globals, "caller" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_field (| M.get_name (| globals, "accessed_addresses" |), "update" |), + make_list [ + M.call (| + M.get_field (| M.get_name (| globals, "PRE_COMPILED_CONTRACTS" |), "keys" |), + make_list [], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_field (| M.get_name (| globals, "accessed_addresses" |), "update" |), + make_list [ + M.get_name (| globals, "preaccessed_addresses" |) + ], + make_dict [] + |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, "Message" |), + make_list [], + make_dict [] + |) + |) in + M.pure Constant.None_)). diff --git a/CoqOfPython/ethereum/berlin/vm/__init__.v b/CoqOfPython/ethereum/berlin/vm/__init__.v new file mode 100644 index 0000000..fcd61d5 --- /dev/null +++ b/CoqOfPython/ethereum/berlin/vm/__init__.v @@ -0,0 +1,260 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.berlin.vm.__init__". + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +The abstract computer which runs the code stored in an +`.fork_types.Account`. +". + +Axiom dataclasses_imports_dataclass : + IsImported globals "dataclasses" "dataclass". + +Axiom typing_imports_List : + IsImported globals "typing" "List". +Axiom typing_imports_Optional : + IsImported globals "typing" "Optional". +Axiom typing_imports_Set : + IsImported globals "typing" "Set". +Axiom typing_imports_Tuple : + IsImported globals "typing" "Tuple". +Axiom typing_imports_Union : + IsImported globals "typing" "Union". + +Axiom ethereum_base_types_imports_U64 : + IsImported globals "ethereum.base_types" "U64". +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_Bytes : + IsImported globals "ethereum.base_types" "Bytes". +Axiom ethereum_base_types_imports_Bytes0 : + IsImported globals "ethereum.base_types" "Bytes0". +Axiom ethereum_base_types_imports_Bytes32 : + IsImported globals "ethereum.base_types" "Bytes32". +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". + +Axiom ethereum_crypto_hash_imports_Hash32 : + IsImported globals "ethereum.crypto.hash" "Hash32". + +Axiom ethereum_berlin_blocks_imports_Log : + IsImported globals "ethereum.berlin.blocks" "Log". + +Axiom ethereum_berlin_fork_types_imports_Address : + IsImported globals "ethereum.berlin.fork_types" "Address". + +Axiom ethereum_berlin_state_imports_State : + IsImported globals "ethereum.berlin.state" "State". +Axiom ethereum_berlin_state_imports_account_exists_and_is_empty : + IsImported globals "ethereum.berlin.state" "account_exists_and_is_empty". + +Axiom ethereum_berlin_vm_precompiled_contracts_imports_RIPEMD160_ADDRESS : + IsImported globals "ethereum.berlin.vm.precompiled_contracts" "RIPEMD160_ADDRESS". + +Definition __all__ : Value.t := M.run ltac:(M.monadic ( + make_tuple [ Constant.str "Environment"; Constant.str "Evm"; Constant.str "Message" ] +)). + +Definition Environment : Value.t := + builtins.make_klass + [] + [ + + ] + [ + + ]. + +Definition Message : Value.t := + builtins.make_klass + [] + [ + + ] + [ + + ]. + +Definition Evm : Value.t := + builtins.make_klass + [] + [ + + ] + [ + + ]. + +Definition incorporate_child_on_success : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm"; "child_evm" ] |) in + let _ := Constant.str " + Incorporate the state of a successful `child_evm` into the parent `evm`. + + Parameters + ---------- + evm : + The parent `EVM`. + child_evm : + The child evm to incorporate. + " in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "gas_left" |), + M.get_field (| M.get_name (| globals, "child_evm" |), "gas_left" |) + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "logs" |), + M.get_field (| M.get_name (| globals, "child_evm" |), "logs" |) + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "refund_counter" |), + M.get_field (| M.get_name (| globals, "child_evm" |), "refund_counter" |) + |) in + let _ := M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "accounts_to_delete" |), "update" |), + make_list [ + M.get_field (| M.get_name (| globals, "child_evm" |), "accounts_to_delete" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "touched_accounts" |), "update" |), + make_list [ + M.get_field (| M.get_name (| globals, "child_evm" |), "touched_accounts" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, "account_exists_and_is_empty" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "env" |), "state" |); + M.get_field (| M.get_field (| M.get_name (| globals, "child_evm" |), "message" |), "current_target" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "touched_accounts" |), "add" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "child_evm" |), "message" |), "current_target" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "accessed_addresses" |), "update" |), + make_list [ + M.get_field (| M.get_name (| globals, "child_evm" |), "accessed_addresses" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "accessed_storage_keys" |), "update" |), + make_list [ + M.get_field (| M.get_name (| globals, "child_evm" |), "accessed_storage_keys" |) + ], + make_dict [] + |) in + M.pure Constant.None_)). + +Definition incorporate_child_on_error : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm"; "child_evm" ] |) in + let _ := Constant.str " + Incorporate the state of an unsuccessful `child_evm` into the parent `evm`. + + Parameters + ---------- + evm : + The parent `EVM`. + child_evm : + The child evm to incorporate. + " in + let _ := + (* if *) + M.if_then_else (| + Compare.in_ (| + M.get_name (| globals, "RIPEMD160_ADDRESS" |), + M.get_field (| M.get_name (| globals, "child_evm" |), "touched_accounts" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "touched_accounts" |), "add" |), + make_list [ + M.get_name (| globals, "RIPEMD160_ADDRESS" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_field (| M.get_field (| M.get_name (| globals, "child_evm" |), "message" |), "current_target" |), + M.get_name (| globals, "RIPEMD160_ADDRESS" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, "account_exists_and_is_empty" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "env" |), "state" |); + M.get_field (| M.get_field (| M.get_name (| globals, "child_evm" |), "message" |), "current_target" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "touched_accounts" |), "add" |), + make_list [ + M.get_name (| globals, "RIPEMD160_ADDRESS" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "gas_left" |), + M.get_field (| M.get_name (| globals, "child_evm" |), "gas_left" |) + |) in + M.pure Constant.None_)). diff --git a/CoqOfPython/ethereum/berlin/vm/exceptions.v b/CoqOfPython/ethereum/berlin/vm/exceptions.v new file mode 100644 index 0000000..20acb2f --- /dev/null +++ b/CoqOfPython/ethereum/berlin/vm/exceptions.v @@ -0,0 +1,161 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.berlin.vm.exceptions". + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) Exceptions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Exceptions which cause the EVM to halt exceptionally. +". + +Axiom ethereum_exceptions_imports_EthereumException : + IsImported globals "ethereum.exceptions" "EthereumException". + +Definition ExceptionalHalt : Value.t := + builtins.make_klass + [(globals, "EthereumException")] + [ + + ] + [ + + ]. + +Definition Revert : Value.t := + builtins.make_klass + [(globals, "EthereumException")] + [ + + ] + [ + + ]. + +Definition StackUnderflowError : Value.t := + builtins.make_klass + [(globals, "ExceptionalHalt")] + [ + + ] + [ + + ]. + +Definition StackOverflowError : Value.t := + builtins.make_klass + [(globals, "ExceptionalHalt")] + [ + + ] + [ + + ]. + +Definition OutOfGasError : Value.t := + builtins.make_klass + [(globals, "ExceptionalHalt")] + [ + + ] + [ + + ]. + +Definition InvalidOpcode : Value.t := + builtins.make_klass + [(globals, "ExceptionalHalt")] + [ + + ] + [ + ( + "__init__", + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "self"; "code" ] |) in + let _ := M.call (| + M.get_field (| M.call (| + M.get_name (| globals, "super" |), + make_list [], + make_dict [] + |), "__init__" |), + make_list [ + M.get_name (| globals, "code" |) + ], + make_dict [] + |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, "self" |), "code" |), + M.get_name (| globals, "code" |) + |) in + M.pure Constant.None_)) + ) + ]. + +Definition InvalidJumpDestError : Value.t := + builtins.make_klass + [(globals, "ExceptionalHalt")] + [ + + ] + [ + + ]. + +Definition StackDepthLimitError : Value.t := + builtins.make_klass + [(globals, "ExceptionalHalt")] + [ + + ] + [ + + ]. + +Definition WriteInStaticContext : Value.t := + builtins.make_klass + [(globals, "ExceptionalHalt")] + [ + + ] + [ + + ]. + +Definition OutOfBoundsRead : Value.t := + builtins.make_klass + [(globals, "ExceptionalHalt")] + [ + + ] + [ + + ]. + +Definition InvalidParameter : Value.t := + builtins.make_klass + [(globals, "ExceptionalHalt")] + [ + + ] + [ + + ]. + +Definition AddressCollision : Value.t := + builtins.make_klass + [(globals, "ExceptionalHalt")] + [ + + ] + [ + + ]. diff --git a/CoqOfPython/ethereum/berlin/vm/gas.v b/CoqOfPython/ethereum/berlin/vm/gas.v new file mode 100644 index 0000000..febe9f3 --- /dev/null +++ b/CoqOfPython/ethereum/berlin/vm/gas.v @@ -0,0 +1,922 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.berlin.vm.gas". + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) Gas +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +EVM gas constants and calculators. +". + +Axiom dataclasses_imports_dataclass : + IsImported globals "dataclasses" "dataclass". + +Axiom typing_imports_List : + IsImported globals "typing" "List". +Axiom typing_imports_Tuple : + IsImported globals "typing" "Tuple". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". + +Axiom ethereum_trace_imports_GasAndRefund : + IsImported globals "ethereum.trace" "GasAndRefund". +Axiom ethereum_trace_imports_evm_trace : + IsImported globals "ethereum.trace" "evm_trace". + +Axiom ethereum_utils_numeric_imports_ceil32 : + IsImported globals "ethereum.utils.numeric" "ceil32". + +Axiom ethereum_berlin_vm_imports_Evm : + IsImported globals "ethereum.berlin.vm" "Evm". + +Axiom ethereum_berlin_vm_exceptions_imports_OutOfGasError : + IsImported globals "ethereum.berlin.vm.exceptions" "OutOfGasError". + +Definition GAS_JUMPDEST : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 1 + ], + make_dict [] + |) +)). + +Definition GAS_BASE : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 2 + ], + make_dict [] + |) +)). + +Definition GAS_VERY_LOW : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 3 + ], + make_dict [] + |) +)). + +Definition GAS_STORAGE_SET : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 20000 + ], + make_dict [] + |) +)). + +Definition GAS_STORAGE_UPDATE : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 5000 + ], + make_dict [] + |) +)). + +Definition GAS_STORAGE_CLEAR_REFUND : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 15000 + ], + make_dict [] + |) +)). + +Definition GAS_LOW : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 5 + ], + make_dict [] + |) +)). + +Definition GAS_MID : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 8 + ], + make_dict [] + |) +)). + +Definition GAS_HIGH : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 10 + ], + make_dict [] + |) +)). + +Definition GAS_EXPONENTIATION : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 10 + ], + make_dict [] + |) +)). + +Definition GAS_EXPONENTIATION_PER_BYTE : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 50 + ], + make_dict [] + |) +)). + +Definition GAS_MEMORY : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 3 + ], + make_dict [] + |) +)). + +Definition GAS_KECCAK256 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 30 + ], + make_dict [] + |) +)). + +Definition GAS_KECCAK256_WORD : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 6 + ], + make_dict [] + |) +)). + +Definition GAS_COPY : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 3 + ], + make_dict [] + |) +)). + +Definition GAS_BLOCK_HASH : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 20 + ], + make_dict [] + |) +)). + +Definition GAS_LOG : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 375 + ], + make_dict [] + |) +)). + +Definition GAS_LOG_DATA : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 8 + ], + make_dict [] + |) +)). + +Definition GAS_LOG_TOPIC : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 375 + ], + make_dict [] + |) +)). + +Definition GAS_CREATE : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 32000 + ], + make_dict [] + |) +)). + +Definition GAS_CODE_DEPOSIT : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 200 + ], + make_dict [] + |) +)). + +Definition GAS_ZERO : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) +)). + +Definition GAS_NEW_ACCOUNT : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 25000 + ], + make_dict [] + |) +)). + +Definition GAS_CALL_VALUE : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 9000 + ], + make_dict [] + |) +)). + +Definition GAS_CALL_STIPEND : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 2300 + ], + make_dict [] + |) +)). + +Definition GAS_SELF_DESTRUCT : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 5000 + ], + make_dict [] + |) +)). + +Definition GAS_SELF_DESTRUCT_NEW_ACCOUNT : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 25000 + ], + make_dict [] + |) +)). + +Definition REFUND_SELF_DESTRUCT : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 24000 + ], + make_dict [] + |) +)). + +Definition GAS_ECRECOVER : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 3000 + ], + make_dict [] + |) +)). + +Definition GAS_SHA256 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 60 + ], + make_dict [] + |) +)). + +Definition GAS_SHA256_WORD : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 12 + ], + make_dict [] + |) +)). + +Definition GAS_RIPEMD160 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 600 + ], + make_dict [] + |) +)). + +Definition GAS_RIPEMD160_WORD : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 120 + ], + make_dict [] + |) +)). + +Definition GAS_IDENTITY : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 15 + ], + make_dict [] + |) +)). + +Definition GAS_IDENTITY_WORD : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 3 + ], + make_dict [] + |) +)). + +Definition GAS_RETURN_DATA_COPY : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 3 + ], + make_dict [] + |) +)). + +Definition GAS_FAST_STEP : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 5 + ], + make_dict [] + |) +)). + +Definition GAS_BLAKE2_PER_ROUND : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 1 + ], + make_dict [] + |) +)). + +Definition GAS_COLD_SLOAD : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 2100 + ], + make_dict [] + |) +)). + +Definition GAS_COLD_ACCOUNT_ACCESS : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 2600 + ], + make_dict [] + |) +)). + +Definition GAS_WARM_ACCESS : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 100 + ], + make_dict [] + |) +)). + +Definition ExtendMemory : Value.t := + builtins.make_klass + [] + [ + + ] + [ + + ]. + +Definition MessageCallGas : Value.t := + builtins.make_klass + [] + [ + + ] + [ + + ]. + +Definition charge_gas : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm"; "amount" ] |) in + let _ := Constant.str " + Subtracts `amount` from `evm.gas_left`. + + Parameters + ---------- + evm : + The current EVM. + amount : + The amount of gas the current operation requires. + + " in + let _ := M.call (| + M.get_name (| globals, "evm_trace" |), + make_list [ + M.get_name (| globals, "evm" |); + M.call (| + M.get_name (| globals, "GasAndRefund" |), + make_list [ + M.get_name (| globals, "amount" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.lt (| + M.get_field (| M.get_name (| globals, "evm" |), "gas_left" |), + M.get_name (| globals, "amount" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, "OutOfGasError" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_op (| + BinOp.sub, + M.get_field (| M.get_name (| globals, "evm" |), "gas_left" |), + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + M.get_name (| globals, "amount" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_)). + +Definition calculate_memory_gas_cost : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "size_in_bytes" ] |) in + let _ := Constant.str " + Calculates the gas cost for allocating memory + to the smallest multiple of 32 bytes, + such that the allocated size is at least as big as the given size. + + Parameters + ---------- + size_in_bytes : + The size of the data in bytes. + + Returns + ------- + total_gas_cost : `ethereum.base_types.Uint` + The gas cost for storing data in memory. + " in + let _ := M.assign_local (| + "size_in_words" , + BinOp.floor_div (| + M.call (| + M.get_name (| globals, "ceil32" |), + make_list [ + M.get_name (| globals, "size_in_bytes" |) + ], + make_dict [] + |), + Constant.int 32 + |) + |) in + let _ := M.assign_local (| + "linear_cost" , + BinOp.mult (| + M.get_name (| globals, "size_in_words" |), + M.get_name (| globals, "GAS_MEMORY" |) + |) + |) in + let _ := M.assign_local (| + "quadratic_cost" , + BinOp.floor_div (| + BinOp.pow (| + M.get_name (| globals, "size_in_words" |), + Constant.int 2 + |), + Constant.int 512 + |) + |) in + let _ := M.assign_local (| + "total_gas_cost" , + BinOp.add (| + M.get_name (| globals, "linear_cost" |), + M.get_name (| globals, "quadratic_cost" |) + |) + |) in +(* At stmt: unsupported node type: Try *) + M.pure Constant.None_)). + +Definition calculate_gas_extend_memory : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "memory"; "extensions" ] |) in + let _ := Constant.str " + Calculates the gas amount to extend memory + + Parameters + ---------- + memory : + Memory contents of the EVM. + extensions: + List of extensions to be made to the memory. + Consists of a tuple of start position and size. + + Returns + ------- + extend_memory: `ExtendMemory` + " in + let _ := M.assign_local (| + "size_to_extend" , + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "to_be_paid" , + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "current_size" , + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_name (| globals, "memory" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := + M.for_ (| + make_tuple [ M.get_name (| globals, "start_position" |); M.get_name (| globals, "size" |) ], + M.get_name (| globals, "extensions" |), + ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, "size" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.continue (| |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "before_size" , + M.call (| + M.get_name (| globals, "ceil32" |), + make_list [ + M.get_name (| globals, "current_size" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "after_size" , + M.call (| + M.get_name (| globals, "ceil32" |), + make_list [ + BinOp.add (| + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.get_name (| globals, "start_position" |) + ], + make_dict [] + |), + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.get_name (| globals, "size" |) + ], + make_dict [] + |) + |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.lt_e (| + M.get_name (| globals, "after_size" |), + M.get_name (| globals, "before_size" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.continue (| |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_op_local (| + BinOp.add, + "size_to_extend", + BinOp.sub (| + M.get_name (| globals, "after_size" |), + M.get_name (| globals, "before_size" |) + |) + |) in + let _ := M.assign_local (| + "already_paid" , + M.call (| + M.get_name (| globals, "calculate_memory_gas_cost" |), + make_list [ + M.get_name (| globals, "before_size" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "total_cost" , + M.call (| + M.get_name (| globals, "calculate_memory_gas_cost" |), + make_list [ + M.get_name (| globals, "after_size" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_op_local (| + BinOp.add, + "to_be_paid", + BinOp.sub (| + M.get_name (| globals, "total_cost" |), + M.get_name (| globals, "already_paid" |) + |) + |) in + let _ := M.assign_local (| + "current_size" , + M.get_name (| globals, "after_size" |) + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, "ExtendMemory" |), + make_list [ + M.get_name (| globals, "to_be_paid" |); + M.get_name (| globals, "size_to_extend" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Definition calculate_message_call_gas : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "value"; "gas"; "gas_left"; "memory_cost"; "extra_gas"; "call_stipend" ] |) in + let _ := Constant.str " + Calculates the MessageCallGas (cost and stipend) for + executing call Opcodes. + + Parameters + ---------- + value: + The amount of `ETH` that needs to be transferred. + gas : + The amount of gas provided to the message-call. + gas_left : + The amount of gas left in the current frame. + memory_cost : + The amount needed to extend the memory in the current frame. + extra_gas : + The amount of gas needed for transferring value + creating a new + account inside a message call. + call_stipend : + The amount of stipend provided to a message call to execute code while + transferring value(ETH). + + Returns + ------- + message_call_gas: `MessageCallGas` + " in + let _ := M.assign_local (| + "call_stipend" , + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, "value" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( +M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + (* else *) + )), ltac:(M.monadic ( +M.get_name (| globals, "call_stipend" |) + )) |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.lt (| + M.get_name (| globals, "gas_left" |), + BinOp.add (| + M.get_name (| globals, "extra_gas" |), + M.get_name (| globals, "memory_cost" |) + |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + M.call (| + M.get_name (| globals, "MessageCallGas" |), + make_list [ + BinOp.add (| + M.get_name (| globals, "gas" |), + M.get_name (| globals, "extra_gas" |) + |); + BinOp.add (| + M.get_name (| globals, "gas" |), + M.get_name (| globals, "call_stipend" |) + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "gas" , + M.call (| + M.get_name (| globals, "min" |), + make_list [ + M.get_name (| globals, "gas" |); + M.call (| + M.get_name (| globals, "max_message_call_gas" |), + make_list [ + BinOp.sub (| + BinOp.sub (| + M.get_name (| globals, "gas_left" |), + M.get_name (| globals, "memory_cost" |) + |), + M.get_name (| globals, "extra_gas" |) + |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, "MessageCallGas" |), + make_list [ + BinOp.add (| + M.get_name (| globals, "gas" |), + M.get_name (| globals, "extra_gas" |) + |); + BinOp.add (| + M.get_name (| globals, "gas" |), + M.get_name (| globals, "call_stipend" |) + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Definition max_message_call_gas : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "gas" ] |) in + let _ := Constant.str " + Calculates the maximum gas that is allowed for making a message call + + Parameters + ---------- + gas : + The amount of gas provided to the message-call. + + Returns + ------- + max_allowed_message_call_gas: `ethereum.base_types.Uint` + The maximum gas allowed for making the message-call. + " in + let _ := M.return_ (| + BinOp.sub (| + M.get_name (| globals, "gas" |), + BinOp.floor_div (| + M.get_name (| globals, "gas" |), + Constant.int 64 + |) + |) + |) in + M.pure Constant.None_)). diff --git a/CoqOfPython/ethereum/berlin/vm/instructions/__init__.v b/CoqOfPython/ethereum/berlin/vm/instructions/__init__.v new file mode 100644 index 0000000..0eae3b0 --- /dev/null +++ b/CoqOfPython/ethereum/berlin/vm/instructions/__init__.v @@ -0,0 +1,74 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.berlin.vm.instructions.__init__". + +Definition expr_1 : Value.t := + Constant.str " +EVM Instruction Encoding (Opcodes) +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Machine readable representations of EVM instructions, and a mapping to their +implementations. +". + +(* At top_level_stmt: unsupported node type: Import *) + +Axiom typing_imports_Callable : + IsImported globals "typing" "Callable". +Axiom typing_imports_Dict : + IsImported globals "typing" "Dict". + +Axiom ethereum_berlin_vm_instructions_imports_arithmetic : + IsImported globals "ethereum.berlin.vm.instructions" "arithmetic". + +Axiom ethereum_berlin_vm_instructions_imports_bitwise : + IsImported globals "ethereum.berlin.vm.instructions" "bitwise". + +Axiom ethereum_berlin_vm_instructions_imports_block : + IsImported globals "ethereum.berlin.vm.instructions" "block". + +Axiom ethereum_berlin_vm_instructions_imports_comparison : + IsImported globals "ethereum.berlin.vm.instructions" "comparison". + +Axiom ethereum_berlin_vm_instructions_imports_control_flow : + IsImported globals "ethereum.berlin.vm.instructions" "control_flow". + +Axiom ethereum_berlin_vm_instructions_imports_environment : + IsImported globals "ethereum.berlin.vm.instructions" "environment". + +Axiom ethereum_berlin_vm_instructions_imports_keccak : + IsImported globals "ethereum.berlin.vm.instructions" "keccak". + +Axiom ethereum_berlin_vm_instructions_imports_log : + IsImported globals "ethereum.berlin.vm.instructions" "log". + +Axiom ethereum_berlin_vm_instructions_imports_memory : + IsImported globals "ethereum.berlin.vm.instructions" "memory". + +Axiom ethereum_berlin_vm_instructions_imports_stack : + IsImported globals "ethereum.berlin.vm.instructions" "stack". + +Axiom ethereum_berlin_vm_instructions_imports_storage : + IsImported globals "ethereum.berlin.vm.instructions" "storage". + +Axiom ethereum_berlin_vm_instructions_imports_system : + IsImported globals "ethereum.berlin.vm.instructions" "system". + +Definition Ops : Value.t := + builtins.make_klass + [(* At base: unsupported node type: Attribute *)] + [ + + ] + [ + + ]. + +(* At top_level_stmt: unsupported node type: AnnAssign *) diff --git a/CoqOfPython/ethereum/berlin/vm/instructions/arithmetic.v b/CoqOfPython/ethereum/berlin/vm/instructions/arithmetic.v new file mode 100644 index 0000000..ea8f027 --- /dev/null +++ b/CoqOfPython/ethereum/berlin/vm/instructions/arithmetic.v @@ -0,0 +1,1220 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.berlin.vm.instructions.arithmetic". + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) Arithmetic Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM Arithmetic instructions. +". + +Axiom ethereum_base_types_imports_U255_CEIL_VALUE : + IsImported globals "ethereum.base_types" "U255_CEIL_VALUE". +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_U256_CEIL_VALUE : + IsImported globals "ethereum.base_types" "U256_CEIL_VALUE". +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". + +Axiom ethereum_utils_numeric_imports_get_sign : + IsImported globals "ethereum.utils.numeric" "get_sign". + +Axiom ethereum_berlin_vm_imports_Evm : + IsImported globals "ethereum.berlin.vm" "Evm". + +Axiom ethereum_berlin_vm_gas_imports_GAS_EXPONENTIATION : + IsImported globals "ethereum.berlin.vm.gas" "GAS_EXPONENTIATION". +Axiom ethereum_berlin_vm_gas_imports_GAS_EXPONENTIATION_PER_BYTE : + IsImported globals "ethereum.berlin.vm.gas" "GAS_EXPONENTIATION_PER_BYTE". +Axiom ethereum_berlin_vm_gas_imports_GAS_LOW : + IsImported globals "ethereum.berlin.vm.gas" "GAS_LOW". +Axiom ethereum_berlin_vm_gas_imports_GAS_MID : + IsImported globals "ethereum.berlin.vm.gas" "GAS_MID". +Axiom ethereum_berlin_vm_gas_imports_GAS_VERY_LOW : + IsImported globals "ethereum.berlin.vm.gas" "GAS_VERY_LOW". +Axiom ethereum_berlin_vm_gas_imports_charge_gas : + IsImported globals "ethereum.berlin.vm.gas" "charge_gas". + +Axiom ethereum_berlin_vm_stack_imports_pop : + IsImported globals "ethereum.berlin.vm.stack" "pop". +Axiom ethereum_berlin_vm_stack_imports_push : + IsImported globals "ethereum.berlin.vm.stack" "push". + +Definition add : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Adds the top two elements of the stack together, and pushes the result back + on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "x" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "y" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_VERY_LOW" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "result" , + M.call (| + M.get_field (| M.get_name (| globals, "x" |), "wrapping_add" |), + make_list [ + M.get_name (| globals, "y" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.get_name (| globals, "result" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition sub : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Subtracts the top two elements of the stack, and pushes the result back + on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "x" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "y" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_VERY_LOW" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "result" , + M.call (| + M.get_field (| M.get_name (| globals, "x" |), "wrapping_sub" |), + make_list [ + M.get_name (| globals, "y" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.get_name (| globals, "result" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition mul : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Multiply the top two elements of the stack, and pushes the result back + on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "x" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "y" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_LOW" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "result" , + M.call (| + M.get_field (| M.get_name (| globals, "x" |), "wrapping_mul" |), + make_list [ + M.get_name (| globals, "y" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.get_name (| globals, "result" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition div : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Integer division of the top two elements of the stack. Pushes the result + back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "dividend" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "divisor" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_LOW" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, "divisor" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "quotient" , + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "quotient" , + BinOp.floor_div (| + M.get_name (| globals, "dividend" |), + M.get_name (| globals, "divisor" |) + |) + |) in + M.pure Constant.None_ + )) |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.get_name (| globals, "quotient" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition sdiv : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Signed integer division of the top two elements of the stack. Pushes the + result back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "dividend" , + M.call (| + M.get_field (| M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |), "to_signed" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "divisor" , + M.call (| + M.get_field (| M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |), "to_signed" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_LOW" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, "divisor" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "quotient" , + Constant.int 0 + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + BoolOp.and (| + Compare.eq (| + M.get_name (| globals, "dividend" |), + UnOp.sub (| M.get_name (| globals, "U255_CEIL_VALUE" |) |) + |), + ltac:(M.monadic ( + Compare.eq (| + M.get_name (| globals, "divisor" |), + UnOp.sub (| Constant.int 1 |) + |) + )) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "quotient" , + UnOp.sub (| M.get_name (| globals, "U255_CEIL_VALUE" |) |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "sign" , + M.call (| + M.get_name (| globals, "get_sign" |), + make_list [ + BinOp.mult (| + M.get_name (| globals, "dividend" |), + M.get_name (| globals, "divisor" |) + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "quotient" , + BinOp.mult (| + M.get_name (| globals, "sign" |), + BinOp.floor_div (| + M.call (| + M.get_name (| globals, "abs" |), + make_list [ + M.get_name (| globals, "dividend" |) + ], + make_dict [] + |), + M.call (| + M.get_name (| globals, "abs" |), + make_list [ + M.get_name (| globals, "divisor" |) + ], + make_dict [] + |) + |) + |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )) |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.call (| + M.get_field (| M.get_name (| globals, "U256" |), "from_signed" |), + make_list [ + M.get_name (| globals, "quotient" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition mod_ : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Modulo remainder of the top two elements of the stack. Pushes the result + back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "x" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "y" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_LOW" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, "y" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "remainder" , + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "remainder" , + BinOp.mod_ (| + M.get_name (| globals, "x" |), + M.get_name (| globals, "y" |) + |) + |) in + M.pure Constant.None_ + )) |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.get_name (| globals, "remainder" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition smod : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Signed modulo remainder of the top two elements of the stack. Pushes the + result back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "x" , + M.call (| + M.get_field (| M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |), "to_signed" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "y" , + M.call (| + M.get_field (| M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |), "to_signed" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_LOW" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, "y" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "remainder" , + Constant.int 0 + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "remainder" , + BinOp.mult (| + M.call (| + M.get_name (| globals, "get_sign" |), + make_list [ + M.get_name (| globals, "x" |) + ], + make_dict [] + |), + BinOp.mod_ (| + M.call (| + M.get_name (| globals, "abs" |), + make_list [ + M.get_name (| globals, "x" |) + ], + make_dict [] + |), + M.call (| + M.get_name (| globals, "abs" |), + make_list [ + M.get_name (| globals, "y" |) + ], + make_dict [] + |) + |) + |) + |) in + M.pure Constant.None_ + )) |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.call (| + M.get_field (| M.get_name (| globals, "U256" |), "from_signed" |), + make_list [ + M.get_name (| globals, "remainder" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition addmod : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Modulo addition of the top 2 elements with the 3rd element. Pushes the + result back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "x" , + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "y" , + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "z" , + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_MID" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, "z" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "result" , + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "result" , + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + BinOp.mod_ (| + BinOp.add (| + M.get_name (| globals, "x" |), + M.get_name (| globals, "y" |) + |), + M.get_name (| globals, "z" |) + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + )) |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.get_name (| globals, "result" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition mulmod : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Modulo multiplication of the top 2 elements with the 3rd element. Pushes + the result back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "x" , + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "y" , + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "z" , + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_MID" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, "z" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "result" , + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "result" , + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + BinOp.mod_ (| + BinOp.mult (| + M.get_name (| globals, "x" |), + M.get_name (| globals, "y" |) + |), + M.get_name (| globals, "z" |) + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + )) |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.get_name (| globals, "result" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition exp : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Exponential operation of the top 2 elements. Pushes the result back on + the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "base" , + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "exponent" , + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "exponent_bits" , + M.call (| + M.get_field (| M.get_name (| globals, "exponent" |), "bit_length" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "exponent_bytes" , + BinOp.floor_div (| + BinOp.add (| + M.get_name (| globals, "exponent_bits" |), + Constant.int 7 + |), + Constant.int 8 + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + BinOp.add (| + M.get_name (| globals, "GAS_EXPONENTIATION" |), + BinOp.mult (| + M.get_name (| globals, "GAS_EXPONENTIATION_PER_BYTE" |), + M.get_name (| globals, "exponent_bytes" |) + |) + |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "result" , + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + M.call (| + M.get_name (| globals, "pow" |), + make_list [ + M.get_name (| globals, "base" |); + M.get_name (| globals, "exponent" |); + M.get_name (| globals, "U256_CEIL_VALUE" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.get_name (| globals, "result" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition signextend : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Sign extend operation. In other words, extend a signed number which + fits in N bytes to 32 bytes. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "byte_num" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "value" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_LOW" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.gt (| + M.get_name (| globals, "byte_num" |), + Constant.int 31 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "result" , + M.get_name (| globals, "value" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "value_bytes" , + M.call (| + M.get_name (| globals, "bytes" |), + make_list [ + M.call (| + M.get_field (| M.get_name (| globals, "value" |), "to_be_bytes32" |), + make_list [], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "value_bytes" , + M.slice (| + M.get_name (| globals, "value_bytes" |), + BinOp.sub (| + Constant.int 31, + M.call (| + M.get_name (| globals, "int" |), + make_list [ + M.get_name (| globals, "byte_num" |) + ], + make_dict [] + |) + |), + Constant.None_, + Constant.None_ + |) + |) in + let _ := M.assign_local (| + "sign_bit" , + BinOp.r_shift (| + M.get_subscript (| + M.get_name (| globals, "value_bytes" |), + Constant.int 0 + |), + Constant.int 7 + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, "sign_bit" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "result" , + M.call (| + M.get_field (| M.get_name (| globals, "U256" |), "from_be_bytes" |), + make_list [ + M.get_name (| globals, "value_bytes" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "num_bytes_prepend" , + BinOp.sub (| + Constant.int 32, + BinOp.add (| + M.get_name (| globals, "byte_num" |), + Constant.int 1 + |) + |) + |) in + let _ := M.assign_local (| + "result" , + M.call (| + M.get_field (| M.get_name (| globals, "U256" |), "from_be_bytes" |), + make_list [ + BinOp.add (| + M.call (| + M.get_name (| globals, "bytearray" |), + make_list [ + BinOp.mult (| + make_list [ + Constant.int 255 + ], + M.get_name (| globals, "num_bytes_prepend" |) + |) + ], + make_dict [] + |), + M.get_name (| globals, "value_bytes" |) + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )) |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.get_name (| globals, "result" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). diff --git a/CoqOfPython/ethereum/berlin/vm/instructions/bitwise.v b/CoqOfPython/ethereum/berlin/vm/instructions/bitwise.v new file mode 100644 index 0000000..f18e7c2 --- /dev/null +++ b/CoqOfPython/ethereum/berlin/vm/instructions/bitwise.v @@ -0,0 +1,666 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.berlin.vm.instructions.bitwise". + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) Bitwise Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM bitwise instructions. +". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_U256_CEIL_VALUE : + IsImported globals "ethereum.base_types" "U256_CEIL_VALUE". + +Axiom ethereum_berlin_vm_imports_Evm : + IsImported globals "ethereum.berlin.vm" "Evm". + +Axiom ethereum_berlin_vm_gas_imports_GAS_VERY_LOW : + IsImported globals "ethereum.berlin.vm.gas" "GAS_VERY_LOW". +Axiom ethereum_berlin_vm_gas_imports_charge_gas : + IsImported globals "ethereum.berlin.vm.gas" "charge_gas". + +Axiom ethereum_berlin_vm_stack_imports_pop : + IsImported globals "ethereum.berlin.vm.stack" "pop". +Axiom ethereum_berlin_vm_stack_imports_push : + IsImported globals "ethereum.berlin.vm.stack" "push". + +Definition bitwise_and : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Bitwise AND operation of the top 2 elements of the stack. Pushes the + result back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "x" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "y" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_VERY_LOW" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + BinOp.bit_and (| + M.get_name (| globals, "x" |), + M.get_name (| globals, "y" |) + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition bitwise_or : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Bitwise OR operation of the top 2 elements of the stack. Pushes the + result back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "x" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "y" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_VERY_LOW" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + BinOp.bit_or (| + M.get_name (| globals, "x" |), + M.get_name (| globals, "y" |) + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition bitwise_xor : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Bitwise XOR operation of the top 2 elements of the stack. Pushes the + result back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "x" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "y" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_VERY_LOW" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + BinOp.bit_xor (| + M.get_name (| globals, "x" |), + M.get_name (| globals, "y" |) + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition bitwise_not : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Bitwise NOT operation of the top element of the stack. Pushes the + result back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "x" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_VERY_LOW" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + UnOp.invert (| M.get_name (| globals, "x" |) |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition get_byte : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + For a word (defined by next top element of the stack), retrieve the + Nth byte (0-indexed and defined by top element of stack) from the + left (most significant) to right (least significant). + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "byte_index" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "word" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_VERY_LOW" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.gt_e (| + M.get_name (| globals, "byte_index" |), + Constant.int 32 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "result" , + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "extra_bytes_to_right" , + BinOp.sub (| + Constant.int 31, + M.get_name (| globals, "byte_index" |) + |) + |) in + let _ := M.assign_local (| + "word" , + BinOp.r_shift (| + M.get_name (| globals, "word" |), + BinOp.mult (| + M.get_name (| globals, "extra_bytes_to_right" |), + Constant.int 8 + |) + |) + |) in + let _ := M.assign_local (| + "word" , + BinOp.bit_and (| + M.get_name (| globals, "word" |), + Constant.int 255 + |) + |) in + let _ := M.assign_local (| + "result" , + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + M.get_name (| globals, "word" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + )) |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.get_name (| globals, "result" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition bitwise_shl : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Logical shift left (SHL) operation of the top 2 elements of the stack. + Pushes the result back on the stack. + Parameters + ---------- + evm : + The current EVM frame. + " in + let _ := M.assign_local (| + "shift" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "value" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_VERY_LOW" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.lt (| + M.get_name (| globals, "shift" |), + Constant.int 256 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "result" , + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + BinOp.mod_ (| + BinOp.l_shift (| + M.get_name (| globals, "value" |), + M.get_name (| globals, "shift" |) + |), + M.get_name (| globals, "U256_CEIL_VALUE" |) + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "result" , + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + )) |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.get_name (| globals, "result" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition bitwise_shr : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Logical shift right (SHR) operation of the top 2 elements of the stack. + Pushes the result back on the stack. + Parameters + ---------- + evm : + The current EVM frame. + " in + let _ := M.assign_local (| + "shift" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "value" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_VERY_LOW" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.lt (| + M.get_name (| globals, "shift" |), + Constant.int 256 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "result" , + BinOp.r_shift (| + M.get_name (| globals, "value" |), + M.get_name (| globals, "shift" |) + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "result" , + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + )) |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.get_name (| globals, "result" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition bitwise_sar : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Arithmetic shift right (SAR) operation of the top 2 elements of the stack. + Pushes the result back on the stack. + Parameters + ---------- + evm : + The current EVM frame. + " in + let _ := M.assign_local (| + "shift" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "signed_value" , + M.call (| + M.get_field (| M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |), "to_signed" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_VERY_LOW" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.lt (| + M.get_name (| globals, "shift" |), + Constant.int 256 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "result" , + M.call (| + M.get_field (| M.get_name (| globals, "U256" |), "from_signed" |), + make_list [ + BinOp.r_shift (| + M.get_name (| globals, "signed_value" |), + M.get_name (| globals, "shift" |) + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + Compare.gt_e (| + M.get_name (| globals, "signed_value" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "result" , + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "result" , + M.get_field (| M.get_name (| globals, "U256" |), "MAX_VALUE" |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )) |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.get_name (| globals, "result" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). diff --git a/CoqOfPython/ethereum/berlin/vm/instructions/block.v b/CoqOfPython/ethereum/berlin/vm/instructions/block.v new file mode 100644 index 0000000..055cd5d --- /dev/null +++ b/CoqOfPython/ethereum/berlin/vm/instructions/block.v @@ -0,0 +1,390 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.berlin.vm.instructions.block". + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) Block Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM block instructions. +". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". + +Axiom ethereum_berlin_vm_imports_Evm : + IsImported globals "ethereum.berlin.vm" "Evm". + +Axiom ethereum_berlin_vm_gas_imports_GAS_BASE : + IsImported globals "ethereum.berlin.vm.gas" "GAS_BASE". +Axiom ethereum_berlin_vm_gas_imports_GAS_BLOCK_HASH : + IsImported globals "ethereum.berlin.vm.gas" "GAS_BLOCK_HASH". +Axiom ethereum_berlin_vm_gas_imports_charge_gas : + IsImported globals "ethereum.berlin.vm.gas" "charge_gas". + +Axiom ethereum_berlin_vm_stack_imports_pop : + IsImported globals "ethereum.berlin.vm.stack" "pop". +Axiom ethereum_berlin_vm_stack_imports_push : + IsImported globals "ethereum.berlin.vm.stack" "push". + +Definition block_hash : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Push the hash of one of the 256 most recent complete blocks onto the + stack. The block number to hash is present at the top of the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "block_number" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_BLOCK_HASH" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + BoolOp.or (| + Compare.lt_e (| + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "env" |), "number" |), + M.get_name (| globals, "block_number" |) + |), + ltac:(M.monadic ( + Compare.gt (| + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "env" |), "number" |), + BinOp.add (| + M.get_name (| globals, "block_number" |), + Constant.int 256 + |) + |) + )) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "hash" , + Constant.bytes "00" + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "hash" , + M.get_subscript (| + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "env" |), "block_hashes" |), + UnOp.sub (| BinOp.sub (| + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "env" |), "number" |), + M.get_name (| globals, "block_number" |) + |) |) + |) + |) in + M.pure Constant.None_ + )) |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.call (| + M.get_field (| M.get_name (| globals, "U256" |), "from_be_bytes" |), + make_list [ + M.get_name (| globals, "hash" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition coinbase : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Push the current block's beneficiary address (address of the block miner) + onto the stack. + + Here the current block refers to the block in which the currently + executing transaction/call resides. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_BASE" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.call (| + M.get_field (| M.get_name (| globals, "U256" |), "from_be_bytes" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "env" |), "coinbase" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition timestamp : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Push the current block's timestamp onto the stack. Here the timestamp + being referred is actually the unix timestamp in seconds. + + Here the current block refers to the block in which the currently + executing transaction/call resides. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_BASE" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "env" |), "time" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition number : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Push the current block's number onto the stack. + + Here the current block refers to the block in which the currently + executing transaction/call resides. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_BASE" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "env" |), "number" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition difficulty : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Push the current block's difficulty onto the stack. + + Here the current block refers to the block in which the currently + executing transaction/call resides. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_BASE" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "env" |), "difficulty" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition gas_limit : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Push the current block's gas limit onto the stack. + + Here the current block refers to the block in which the currently + executing transaction/call resides. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_BASE" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "env" |), "gas_limit" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition chain_id : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Push the chain id onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_BASE" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "env" |), "chain_id" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). diff --git a/CoqOfPython/ethereum/berlin/vm/instructions/comparison.v b/CoqOfPython/ethereum/berlin/vm/instructions/comparison.v new file mode 100644 index 0000000..6815b65 --- /dev/null +++ b/CoqOfPython/ethereum/berlin/vm/instructions/comparison.v @@ -0,0 +1,452 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.berlin.vm.instructions.comparison". + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) Comparison Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM Comparison instructions. +". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". + +Axiom ethereum_berlin_vm_imports_Evm : + IsImported globals "ethereum.berlin.vm" "Evm". + +Axiom ethereum_berlin_vm_gas_imports_GAS_VERY_LOW : + IsImported globals "ethereum.berlin.vm.gas" "GAS_VERY_LOW". +Axiom ethereum_berlin_vm_gas_imports_charge_gas : + IsImported globals "ethereum.berlin.vm.gas" "charge_gas". + +Axiom ethereum_berlin_vm_stack_imports_pop : + IsImported globals "ethereum.berlin.vm.stack" "pop". +Axiom ethereum_berlin_vm_stack_imports_push : + IsImported globals "ethereum.berlin.vm.stack" "push". + +Definition less_than : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Checks if the top element is less than the next top element. Pushes the + result back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "left" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "right" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_VERY_LOW" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "result" , + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Compare.lt (| + M.get_name (| globals, "left" |), + M.get_name (| globals, "right" |) + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.get_name (| globals, "result" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition signed_less_than : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Signed less-than comparison. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "left" , + M.call (| + M.get_field (| M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |), "to_signed" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "right" , + M.call (| + M.get_field (| M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |), "to_signed" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_VERY_LOW" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "result" , + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Compare.lt (| + M.get_name (| globals, "left" |), + M.get_name (| globals, "right" |) + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.get_name (| globals, "result" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition greater_than : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Checks if the top element is greater than the next top element. Pushes + the result back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "left" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "right" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_VERY_LOW" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "result" , + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Compare.gt (| + M.get_name (| globals, "left" |), + M.get_name (| globals, "right" |) + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.get_name (| globals, "result" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition signed_greater_than : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Signed greater-than comparison. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "left" , + M.call (| + M.get_field (| M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |), "to_signed" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "right" , + M.call (| + M.get_field (| M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |), "to_signed" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_VERY_LOW" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "result" , + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Compare.gt (| + M.get_name (| globals, "left" |), + M.get_name (| globals, "right" |) + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.get_name (| globals, "result" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition equal : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Checks if the top element is equal to the next top element. Pushes + the result back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "left" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "right" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_VERY_LOW" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "result" , + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Compare.eq (| + M.get_name (| globals, "left" |), + M.get_name (| globals, "right" |) + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.get_name (| globals, "result" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition is_zero : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Checks if the top element is equal to 0. Pushes the result back on the + stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "x" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_VERY_LOW" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "result" , + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Compare.eq (| + M.get_name (| globals, "x" |), + Constant.int 0 + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.get_name (| globals, "result" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). diff --git a/CoqOfPython/ethereum/berlin/vm/instructions/control_flow.v b/CoqOfPython/ethereum/berlin/vm/instructions/control_flow.v new file mode 100644 index 0000000..d084bbb --- /dev/null +++ b/CoqOfPython/ethereum/berlin/vm/instructions/control_flow.v @@ -0,0 +1,350 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.berlin.vm.instructions.control_flow". + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) Control Flow Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM control flow instructions. +". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". + +Axiom ethereum_berlin_vm_gas_imports_GAS_BASE : + IsImported globals "ethereum.berlin.vm.gas" "GAS_BASE". +Axiom ethereum_berlin_vm_gas_imports_GAS_HIGH : + IsImported globals "ethereum.berlin.vm.gas" "GAS_HIGH". +Axiom ethereum_berlin_vm_gas_imports_GAS_JUMPDEST : + IsImported globals "ethereum.berlin.vm.gas" "GAS_JUMPDEST". +Axiom ethereum_berlin_vm_gas_imports_GAS_MID : + IsImported globals "ethereum.berlin.vm.gas" "GAS_MID". +Axiom ethereum_berlin_vm_gas_imports_charge_gas : + IsImported globals "ethereum.berlin.vm.gas" "charge_gas". + +Axiom ethereum_berlin_vm_imports_Evm : + IsImported globals "ethereum.berlin.vm" "Evm". + +Axiom ethereum_berlin_vm_exceptions_imports_InvalidJumpDestError : + IsImported globals "ethereum.berlin.vm.exceptions" "InvalidJumpDestError". + +Axiom ethereum_berlin_vm_stack_imports_pop : + IsImported globals "ethereum.berlin.vm.stack" "pop". +Axiom ethereum_berlin_vm_stack_imports_push : + IsImported globals "ethereum.berlin.vm.stack" "push". + +Definition stop : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Stop further execution of EVM code. + + Parameters + ---------- + evm : + The current EVM frame. + " in + let _ := M.pass (| |) in + let _ := M.pass (| |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, "evm" |), "running" |), + Constant.bool false + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition jump : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Alter the program counter to the location specified by the top of the + stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "jump_dest" , + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_MID" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.not_in (| + M.get_name (| globals, "jump_dest" |), + M.get_field (| M.get_name (| globals, "evm" |), "valid_jump_destinations" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, "InvalidJumpDestError" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.get_name (| globals, "jump_dest" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Definition jumpi : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Alter the program counter to the specified location if and only if a + condition is true. If the condition is not true, then the program counter + would increase only by 1. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "jump_dest" , + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "conditional_value" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_HIGH" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, "conditional_value" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "destination" , + BinOp.add (| + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + Compare.not_in (| + M.get_name (| globals, "jump_dest" |), + M.get_field (| M.get_name (| globals, "evm" |), "valid_jump_destinations" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, "InvalidJumpDestError" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "destination" , + M.get_name (| globals, "jump_dest" |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )) |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.get_name (| globals, "destination" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Definition pc : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Push onto the stack the value of the program counter after reaching the + current instruction and without increasing it for the next instruction. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_BASE" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "pc" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition gas_left : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Push the amount of available gas (including the corresponding reduction + for the cost of this instruction) onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_BASE" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "gas_left" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition jumpdest : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Mark a valid destination for jumps. This is a noop, present only + to be used by `JUMP` and `JUMPI` opcodes to verify that their jump is + valid. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_JUMPDEST" |) + ], + make_dict [] + |) in + let _ := M.pass (| |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). diff --git a/CoqOfPython/ethereum/berlin/vm/instructions/environment.v b/CoqOfPython/ethereum/berlin/vm/instructions/environment.v new file mode 100644 index 0000000..973b275 --- /dev/null +++ b/CoqOfPython/ethereum/berlin/vm/instructions/environment.v @@ -0,0 +1,1487 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.berlin.vm.instructions.environment". + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) Environmental Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM environment related instructions. +". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". + +Axiom ethereum_crypto_hash_imports_keccak256 : + IsImported globals "ethereum.crypto.hash" "keccak256". + +Axiom ethereum_utils_ensure_imports_ensure : + IsImported globals "ethereum.utils.ensure" "ensure". + +Axiom ethereum_utils_numeric_imports_ceil32 : + IsImported globals "ethereum.utils.numeric" "ceil32". + +Axiom ethereum_berlin_fork_types_imports_EMPTY_ACCOUNT : + IsImported globals "ethereum.berlin.fork_types" "EMPTY_ACCOUNT". + +Axiom ethereum_berlin_state_imports_get_account : + IsImported globals "ethereum.berlin.state" "get_account". + +Axiom ethereum_berlin_utils_address_imports_to_address : + IsImported globals "ethereum.berlin.utils.address" "to_address". + +Axiom ethereum_berlin_vm_memory_imports_buffer_read : + IsImported globals "ethereum.berlin.vm.memory" "buffer_read". +Axiom ethereum_berlin_vm_memory_imports_memory_write : + IsImported globals "ethereum.berlin.vm.memory" "memory_write". + +Axiom ethereum_berlin_vm_imports_Evm : + IsImported globals "ethereum.berlin.vm" "Evm". + +Axiom ethereum_berlin_vm_exceptions_imports_OutOfBoundsRead : + IsImported globals "ethereum.berlin.vm.exceptions" "OutOfBoundsRead". + +Axiom ethereum_berlin_vm_gas_imports_GAS_BASE : + IsImported globals "ethereum.berlin.vm.gas" "GAS_BASE". +Axiom ethereum_berlin_vm_gas_imports_GAS_COLD_ACCOUNT_ACCESS : + IsImported globals "ethereum.berlin.vm.gas" "GAS_COLD_ACCOUNT_ACCESS". +Axiom ethereum_berlin_vm_gas_imports_GAS_COPY : + IsImported globals "ethereum.berlin.vm.gas" "GAS_COPY". +Axiom ethereum_berlin_vm_gas_imports_GAS_FAST_STEP : + IsImported globals "ethereum.berlin.vm.gas" "GAS_FAST_STEP". +Axiom ethereum_berlin_vm_gas_imports_GAS_RETURN_DATA_COPY : + IsImported globals "ethereum.berlin.vm.gas" "GAS_RETURN_DATA_COPY". +Axiom ethereum_berlin_vm_gas_imports_GAS_VERY_LOW : + IsImported globals "ethereum.berlin.vm.gas" "GAS_VERY_LOW". +Axiom ethereum_berlin_vm_gas_imports_GAS_WARM_ACCESS : + IsImported globals "ethereum.berlin.vm.gas" "GAS_WARM_ACCESS". +Axiom ethereum_berlin_vm_gas_imports_calculate_gas_extend_memory : + IsImported globals "ethereum.berlin.vm.gas" "calculate_gas_extend_memory". +Axiom ethereum_berlin_vm_gas_imports_charge_gas : + IsImported globals "ethereum.berlin.vm.gas" "charge_gas". + +Axiom ethereum_berlin_vm_stack_imports_pop : + IsImported globals "ethereum.berlin.vm.stack" "pop". +Axiom ethereum_berlin_vm_stack_imports_push : + IsImported globals "ethereum.berlin.vm.stack" "push". + +Definition address : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Pushes the address of the current executing account to the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_BASE" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.call (| + M.get_field (| M.get_name (| globals, "U256" |), "from_be_bytes" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "current_target" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition balance : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Pushes the balance of the given account onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "address" , + M.call (| + M.get_name (| globals, "to_address" |), + make_list [ + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.in_ (| + M.get_name (| globals, "address" |), + M.get_field (| M.get_name (| globals, "evm" |), "accessed_addresses" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_WARM_ACCESS" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "accessed_addresses" |), "add" |), + make_list [ + M.get_name (| globals, "address" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_COLD_ACCOUNT_ACCESS" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "balance" , + M.get_field (| M.call (| + M.get_name (| globals, "get_account" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "env" |), "state" |); + M.get_name (| globals, "address" |) + ], + make_dict [] + |), "balance" |) + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.get_name (| globals, "balance" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition origin : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Pushes the address of the original transaction sender to the stack. + The origin address can only be an EOA. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_BASE" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.call (| + M.get_field (| M.get_name (| globals, "U256" |), "from_be_bytes" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "env" |), "origin" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition caller : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Pushes the address of the caller onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_BASE" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.call (| + M.get_field (| M.get_name (| globals, "U256" |), "from_be_bytes" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "caller" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition callvalue : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Push the value (in wei) sent with the call onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_BASE" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "value" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition calldataload : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Push a word (32 bytes) of the input data belonging to the current + environment onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "start_index" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_VERY_LOW" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "value" , + M.call (| + M.get_name (| globals, "buffer_read" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "data" |); + M.get_name (| globals, "start_index" |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 32 + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.call (| + M.get_field (| M.get_name (| globals, "U256" |), "from_be_bytes" |), + make_list [ + M.get_name (| globals, "value" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition calldatasize : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Push the size of input data in current environment onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_BASE" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "data" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition calldatacopy : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Copy a portion of the input data in current environment to memory. + + This will also expand the memory, in case that the memory is insufficient + to store the data. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "memory_start_index" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "data_start_index" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "size" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "words" , + BinOp.floor_div (| + M.call (| + M.get_name (| globals, "ceil32" |), + make_list [ + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.get_name (| globals, "size" |) + ], + make_dict [] + |) + ], + make_dict [] + |), + Constant.int 32 + |) + |) in + let _ := M.assign_local (| + "copy_gas_cost" , + BinOp.mult (| + M.get_name (| globals, "GAS_COPY" |), + M.get_name (| globals, "words" |) + |) + |) in + let _ := M.assign_local (| + "extend_memory" , + M.call (| + M.get_name (| globals, "calculate_gas_extend_memory" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "memory" |); + make_list [ + make_tuple [ M.get_name (| globals, "memory_start_index" |); M.get_name (| globals, "size" |) ] + ] + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + BinOp.add (| + BinOp.add (| + M.get_name (| globals, "GAS_VERY_LOW" |), + M.get_name (| globals, "copy_gas_cost" |) + |), + M.get_field (| M.get_name (| globals, "extend_memory" |), "cost" |) + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "memory" |), + BinOp.mult (| + Constant.bytes "00", + M.get_field (| M.get_name (| globals, "extend_memory" |), "expand_by" |) + |) + |) in + let _ := M.assign_local (| + "value" , + M.call (| + M.get_name (| globals, "buffer_read" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "data" |); + M.get_name (| globals, "data_start_index" |); + M.get_name (| globals, "size" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "memory_write" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "memory" |); + M.get_name (| globals, "memory_start_index" |); + M.get_name (| globals, "value" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition codesize : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Push the size of code running in current environment onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_BASE" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "code" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition codecopy : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Copy a portion of the code in current environment to memory. + + This will also expand the memory, in case that the memory is insufficient + to store the data. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "memory_start_index" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "code_start_index" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "size" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "words" , + BinOp.floor_div (| + M.call (| + M.get_name (| globals, "ceil32" |), + make_list [ + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.get_name (| globals, "size" |) + ], + make_dict [] + |) + ], + make_dict [] + |), + Constant.int 32 + |) + |) in + let _ := M.assign_local (| + "copy_gas_cost" , + BinOp.mult (| + M.get_name (| globals, "GAS_COPY" |), + M.get_name (| globals, "words" |) + |) + |) in + let _ := M.assign_local (| + "extend_memory" , + M.call (| + M.get_name (| globals, "calculate_gas_extend_memory" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "memory" |); + make_list [ + make_tuple [ M.get_name (| globals, "memory_start_index" |); M.get_name (| globals, "size" |) ] + ] + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + BinOp.add (| + BinOp.add (| + M.get_name (| globals, "GAS_VERY_LOW" |), + M.get_name (| globals, "copy_gas_cost" |) + |), + M.get_field (| M.get_name (| globals, "extend_memory" |), "cost" |) + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "memory" |), + BinOp.mult (| + Constant.bytes "00", + M.get_field (| M.get_name (| globals, "extend_memory" |), "expand_by" |) + |) + |) in + let _ := M.assign_local (| + "value" , + M.call (| + M.get_name (| globals, "buffer_read" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "code" |); + M.get_name (| globals, "code_start_index" |); + M.get_name (| globals, "size" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "memory_write" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "memory" |); + M.get_name (| globals, "memory_start_index" |); + M.get_name (| globals, "value" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition gasprice : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Push the gas price used in current environment onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_BASE" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "env" |), "gas_price" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition extcodesize : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Push the code size of a given account onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "address" , + M.call (| + M.get_name (| globals, "to_address" |), + make_list [ + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.in_ (| + M.get_name (| globals, "address" |), + M.get_field (| M.get_name (| globals, "evm" |), "accessed_addresses" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_WARM_ACCESS" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "accessed_addresses" |), "add" |), + make_list [ + M.get_name (| globals, "address" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_COLD_ACCOUNT_ACCESS" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "codesize" , + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_field (| M.call (| + M.get_name (| globals, "get_account" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "env" |), "state" |); + M.get_name (| globals, "address" |) + ], + make_dict [] + |), "code" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.get_name (| globals, "codesize" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition extcodecopy : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Copy a portion of an account's code to memory. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "address" , + M.call (| + M.get_name (| globals, "to_address" |), + make_list [ + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_start_index" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "code_start_index" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "size" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "words" , + BinOp.floor_div (| + M.call (| + M.get_name (| globals, "ceil32" |), + make_list [ + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.get_name (| globals, "size" |) + ], + make_dict [] + |) + ], + make_dict [] + |), + Constant.int 32 + |) + |) in + let _ := M.assign_local (| + "copy_gas_cost" , + BinOp.mult (| + M.get_name (| globals, "GAS_COPY" |), + M.get_name (| globals, "words" |) + |) + |) in + let _ := M.assign_local (| + "extend_memory" , + M.call (| + M.get_name (| globals, "calculate_gas_extend_memory" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "memory" |); + make_list [ + make_tuple [ M.get_name (| globals, "memory_start_index" |); M.get_name (| globals, "size" |) ] + ] + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.in_ (| + M.get_name (| globals, "address" |), + M.get_field (| M.get_name (| globals, "evm" |), "accessed_addresses" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + BinOp.add (| + BinOp.add (| + M.get_name (| globals, "GAS_WARM_ACCESS" |), + M.get_name (| globals, "copy_gas_cost" |) + |), + M.get_field (| M.get_name (| globals, "extend_memory" |), "cost" |) + |) + ], + make_dict [] + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "accessed_addresses" |), "add" |), + make_list [ + M.get_name (| globals, "address" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + BinOp.add (| + BinOp.add (| + M.get_name (| globals, "GAS_COLD_ACCOUNT_ACCESS" |), + M.get_name (| globals, "copy_gas_cost" |) + |), + M.get_field (| M.get_name (| globals, "extend_memory" |), "cost" |) + |) + ], + make_dict [] + |) in + M.pure Constant.None_ + )) |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "memory" |), + BinOp.mult (| + Constant.bytes "00", + M.get_field (| M.get_name (| globals, "extend_memory" |), "expand_by" |) + |) + |) in + let _ := M.assign_local (| + "code" , + M.get_field (| M.call (| + M.get_name (| globals, "get_account" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "env" |), "state" |); + M.get_name (| globals, "address" |) + ], + make_dict [] + |), "code" |) + |) in + let _ := M.assign_local (| + "value" , + M.call (| + M.get_name (| globals, "buffer_read" |), + make_list [ + M.get_name (| globals, "code" |); + M.get_name (| globals, "code_start_index" |); + M.get_name (| globals, "size" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "memory_write" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "memory" |); + M.get_name (| globals, "memory_start_index" |); + M.get_name (| globals, "value" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition returndatasize : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Pushes the size of the return data buffer onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_BASE" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "return_data" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition returndatacopy : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Copies data from the return data buffer code to memory + + Parameters + ---------- + evm : + The current EVM frame. + " in + let _ := M.assign_local (| + "memory_start_index" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "return_data_start_position" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "size" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "words" , + BinOp.floor_div (| + M.call (| + M.get_name (| globals, "ceil32" |), + make_list [ + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.get_name (| globals, "size" |) + ], + make_dict [] + |) + ], + make_dict [] + |), + Constant.int 32 + |) + |) in + let _ := M.assign_local (| + "copy_gas_cost" , + BinOp.mult (| + M.get_name (| globals, "GAS_RETURN_DATA_COPY" |), + M.get_name (| globals, "words" |) + |) + |) in + let _ := M.assign_local (| + "extend_memory" , + M.call (| + M.get_name (| globals, "calculate_gas_extend_memory" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "memory" |); + make_list [ + make_tuple [ M.get_name (| globals, "memory_start_index" |); M.get_name (| globals, "size" |) ] + ] + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + BinOp.add (| + BinOp.add (| + M.get_name (| globals, "GAS_VERY_LOW" |), + M.get_name (| globals, "copy_gas_cost" |) + |), + M.get_field (| M.get_name (| globals, "extend_memory" |), "cost" |) + |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + Compare.lt_e (| + BinOp.add (| + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.get_name (| globals, "return_data_start_position" |) + ], + make_dict [] + |), + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.get_name (| globals, "size" |) + ], + make_dict [] + |) + |), + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "return_data" |) + ], + make_dict [] + |) + |); + M.get_name (| globals, "OutOfBoundsRead" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "memory" |), + BinOp.mult (| + Constant.bytes "00", + M.get_field (| M.get_name (| globals, "extend_memory" |), "expand_by" |) + |) + |) in + let _ := M.assign_local (| + "value" , + M.slice (| + M.get_field (| M.get_name (| globals, "evm" |), "return_data" |), + M.get_name (| globals, "return_data_start_position" |), + BinOp.add (| + M.get_name (| globals, "return_data_start_position" |), + M.get_name (| globals, "size" |) + |), + Constant.None_ + |) + |) in + let _ := M.call (| + M.get_name (| globals, "memory_write" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "memory" |); + M.get_name (| globals, "memory_start_index" |); + M.get_name (| globals, "value" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition extcodehash : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Returns the keccak256 hash of a contract’s bytecode + Parameters + ---------- + evm : + The current EVM frame. + " in + let _ := M.assign_local (| + "address" , + M.call (| + M.get_name (| globals, "to_address" |), + make_list [ + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.in_ (| + M.get_name (| globals, "address" |), + M.get_field (| M.get_name (| globals, "evm" |), "accessed_addresses" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_WARM_ACCESS" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "accessed_addresses" |), "add" |), + make_list [ + M.get_name (| globals, "address" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_COLD_ACCOUNT_ACCESS" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "account" , + M.call (| + M.get_name (| globals, "get_account" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "env" |), "state" |); + M.get_name (| globals, "address" |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, "account" |), + M.get_name (| globals, "EMPTY_ACCOUNT" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "codehash" , + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "codehash" , + M.call (| + M.get_field (| M.get_name (| globals, "U256" |), "from_be_bytes" |), + make_list [ + M.call (| + M.get_name (| globals, "keccak256" |), + make_list [ + M.get_field (| M.get_name (| globals, "account" |), "code" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + )) |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.get_name (| globals, "codehash" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition self_balance : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Pushes the balance of the current address to the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_FAST_STEP" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "balance" , + M.get_field (| M.call (| + M.get_name (| globals, "get_account" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "env" |), "state" |); + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "current_target" |) + ], + make_dict [] + |), "balance" |) + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.get_name (| globals, "balance" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). diff --git a/CoqOfPython/ethereum/berlin/vm/instructions/keccak.v b/CoqOfPython/ethereum/berlin/vm/instructions/keccak.v new file mode 100644 index 0000000..3adfdb0 --- /dev/null +++ b/CoqOfPython/ethereum/berlin/vm/instructions/keccak.v @@ -0,0 +1,188 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.berlin.vm.instructions.keccak". + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) Keccak Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM keccak instructions. +". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". + +Axiom ethereum_crypto_hash_imports_keccak256 : + IsImported globals "ethereum.crypto.hash" "keccak256". + +Axiom ethereum_utils_numeric_imports_ceil32 : + IsImported globals "ethereum.utils.numeric" "ceil32". + +Axiom ethereum_berlin_vm_imports_Evm : + IsImported globals "ethereum.berlin.vm" "Evm". + +Axiom ethereum_berlin_vm_gas_imports_GAS_KECCAK256 : + IsImported globals "ethereum.berlin.vm.gas" "GAS_KECCAK256". +Axiom ethereum_berlin_vm_gas_imports_GAS_KECCAK256_WORD : + IsImported globals "ethereum.berlin.vm.gas" "GAS_KECCAK256_WORD". +Axiom ethereum_berlin_vm_gas_imports_calculate_gas_extend_memory : + IsImported globals "ethereum.berlin.vm.gas" "calculate_gas_extend_memory". +Axiom ethereum_berlin_vm_gas_imports_charge_gas : + IsImported globals "ethereum.berlin.vm.gas" "charge_gas". + +Axiom ethereum_berlin_vm_memory_imports_memory_read_bytes : + IsImported globals "ethereum.berlin.vm.memory" "memory_read_bytes". + +Axiom ethereum_berlin_vm_stack_imports_pop : + IsImported globals "ethereum.berlin.vm.stack" "pop". +Axiom ethereum_berlin_vm_stack_imports_push : + IsImported globals "ethereum.berlin.vm.stack" "push". + +Definition keccak : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Pushes to the stack the Keccak-256 hash of a region of memory. + + This also expands the memory, in case the memory is insufficient to + access the data's memory location. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "memory_start_index" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "size" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "words" , + BinOp.floor_div (| + M.call (| + M.get_name (| globals, "ceil32" |), + make_list [ + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.get_name (| globals, "size" |) + ], + make_dict [] + |) + ], + make_dict [] + |), + Constant.int 32 + |) + |) in + let _ := M.assign_local (| + "word_gas_cost" , + BinOp.mult (| + M.get_name (| globals, "GAS_KECCAK256_WORD" |), + M.get_name (| globals, "words" |) + |) + |) in + let _ := M.assign_local (| + "extend_memory" , + M.call (| + M.get_name (| globals, "calculate_gas_extend_memory" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "memory" |); + make_list [ + make_tuple [ M.get_name (| globals, "memory_start_index" |); M.get_name (| globals, "size" |) ] + ] + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + BinOp.add (| + BinOp.add (| + M.get_name (| globals, "GAS_KECCAK256" |), + M.get_name (| globals, "word_gas_cost" |) + |), + M.get_field (| M.get_name (| globals, "extend_memory" |), "cost" |) + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "memory" |), + BinOp.mult (| + Constant.bytes "00", + M.get_field (| M.get_name (| globals, "extend_memory" |), "expand_by" |) + |) + |) in + let _ := M.assign_local (| + "data" , + M.call (| + M.get_name (| globals, "memory_read_bytes" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "memory" |); + M.get_name (| globals, "memory_start_index" |); + M.get_name (| globals, "size" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "hash" , + M.call (| + M.get_name (| globals, "keccak256" |), + make_list [ + M.get_name (| globals, "data" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.call (| + M.get_field (| M.get_name (| globals, "U256" |), "from_be_bytes" |), + make_list [ + M.get_name (| globals, "hash" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). diff --git a/CoqOfPython/ethereum/berlin/vm/instructions/log.v b/CoqOfPython/ethereum/berlin/vm/instructions/log.v new file mode 100644 index 0000000..3add2f4 --- /dev/null +++ b/CoqOfPython/ethereum/berlin/vm/instructions/log.v @@ -0,0 +1,256 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.berlin.vm.instructions.log". + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) Logging Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM logging instructions. +". + +Axiom functools_imports_partial : + IsImported globals "functools" "partial". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". + +Axiom ethereum_utils_ensure_imports_ensure : + IsImported globals "ethereum.utils.ensure" "ensure". + +Axiom ethereum_berlin_blocks_imports_Log : + IsImported globals "ethereum.berlin.blocks" "Log". + +Axiom ethereum_berlin_vm_imports_Evm : + IsImported globals "ethereum.berlin.vm" "Evm". + +Axiom ethereum_berlin_vm_exceptions_imports_WriteInStaticContext : + IsImported globals "ethereum.berlin.vm.exceptions" "WriteInStaticContext". + +Axiom ethereum_berlin_vm_gas_imports_GAS_LOG : + IsImported globals "ethereum.berlin.vm.gas" "GAS_LOG". +Axiom ethereum_berlin_vm_gas_imports_GAS_LOG_DATA : + IsImported globals "ethereum.berlin.vm.gas" "GAS_LOG_DATA". +Axiom ethereum_berlin_vm_gas_imports_GAS_LOG_TOPIC : + IsImported globals "ethereum.berlin.vm.gas" "GAS_LOG_TOPIC". +Axiom ethereum_berlin_vm_gas_imports_calculate_gas_extend_memory : + IsImported globals "ethereum.berlin.vm.gas" "calculate_gas_extend_memory". +Axiom ethereum_berlin_vm_gas_imports_charge_gas : + IsImported globals "ethereum.berlin.vm.gas" "charge_gas". + +Axiom ethereum_berlin_vm_memory_imports_memory_read_bytes : + IsImported globals "ethereum.berlin.vm.memory" "memory_read_bytes". + +Axiom ethereum_berlin_vm_stack_imports_pop : + IsImported globals "ethereum.berlin.vm.stack" "pop". + +Definition log_n : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm"; "num_topics" ] |) in + let _ := Constant.str " + Appends a log entry, having `num_topics` topics, to the evm logs. + + This will also expand the memory if the data (required by the log entry) + corresponding to the memory is not accessible. + + Parameters + ---------- + evm : + The current EVM frame. + num_topics : + The number of topics to be included in the log entry. + + " in + let _ := M.assign_local (| + "memory_start_index" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "size" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "topics" , + make_list [] + |) in + let _ := + M.for_ (| + M.get_name (| globals, "_" |), + M.call (| + M.get_name (| globals, "range" |), + make_list [ + M.get_name (| globals, "num_topics" |) + ], + make_dict [] + |), + ltac:(M.monadic ( + let _ := M.assign_local (| + "topic" , + M.call (| + M.get_field (| M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |), "to_be_bytes32" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_field (| M.get_name (| globals, "topics" |), "append" |), + make_list [ + M.get_name (| globals, "topic" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := M.assign_local (| + "extend_memory" , + M.call (| + M.get_name (| globals, "calculate_gas_extend_memory" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "memory" |); + make_list [ + make_tuple [ M.get_name (| globals, "memory_start_index" |); M.get_name (| globals, "size" |) ] + ] + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + BinOp.add (| + BinOp.add (| + BinOp.add (| + M.get_name (| globals, "GAS_LOG" |), + BinOp.mult (| + M.get_name (| globals, "GAS_LOG_DATA" |), + M.get_name (| globals, "size" |) + |) + |), + BinOp.mult (| + M.get_name (| globals, "GAS_LOG_TOPIC" |), + M.get_name (| globals, "num_topics" |) + |) + |), + M.get_field (| M.get_name (| globals, "extend_memory" |), "cost" |) + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "memory" |), + BinOp.mult (| + Constant.bytes "00", + M.get_field (| M.get_name (| globals, "extend_memory" |), "expand_by" |) + |) + |) in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + UnOp.not (| M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "is_static" |) |); + M.get_name (| globals, "WriteInStaticContext" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "log_entry" , + M.call (| + M.get_name (| globals, "Log" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, "evm" |), "logs" |), + BinOp.add (| + M.get_field (| M.get_name (| globals, "evm" |), "logs" |), + make_tuple [ M.get_name (| globals, "log_entry" |) ] + |) + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition log0 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "log_n" |) + ], + make_dict [] + |) +)). + +Definition log1 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "log_n" |) + ], + make_dict [] + |) +)). + +Definition log2 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "log_n" |) + ], + make_dict [] + |) +)). + +Definition log3 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "log_n" |) + ], + make_dict [] + |) +)). + +Definition log4 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "log_n" |) + ], + make_dict [] + |) +)). diff --git a/CoqOfPython/ethereum/berlin/vm/instructions/memory.v b/CoqOfPython/ethereum/berlin/vm/instructions/memory.v new file mode 100644 index 0000000..c93d543 --- /dev/null +++ b/CoqOfPython/ethereum/berlin/vm/instructions/memory.v @@ -0,0 +1,393 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.berlin.vm.instructions.memory". + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) Memory Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM Memory instructions. +". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_Bytes : + IsImported globals "ethereum.base_types" "Bytes". + +Axiom ethereum_berlin_vm_imports_Evm : + IsImported globals "ethereum.berlin.vm" "Evm". + +Axiom ethereum_berlin_vm_gas_imports_GAS_BASE : + IsImported globals "ethereum.berlin.vm.gas" "GAS_BASE". +Axiom ethereum_berlin_vm_gas_imports_GAS_VERY_LOW : + IsImported globals "ethereum.berlin.vm.gas" "GAS_VERY_LOW". +Axiom ethereum_berlin_vm_gas_imports_calculate_gas_extend_memory : + IsImported globals "ethereum.berlin.vm.gas" "calculate_gas_extend_memory". +Axiom ethereum_berlin_vm_gas_imports_charge_gas : + IsImported globals "ethereum.berlin.vm.gas" "charge_gas". + +Axiom ethereum_berlin_vm_memory_imports_memory_read_bytes : + IsImported globals "ethereum.berlin.vm.memory" "memory_read_bytes". +Axiom ethereum_berlin_vm_memory_imports_memory_write : + IsImported globals "ethereum.berlin.vm.memory" "memory_write". + +Axiom ethereum_berlin_vm_stack_imports_pop : + IsImported globals "ethereum.berlin.vm.stack" "pop". +Axiom ethereum_berlin_vm_stack_imports_push : + IsImported globals "ethereum.berlin.vm.stack" "push". + +Definition mstore : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Stores a word to memory. + This also expands the memory, if the memory is + insufficient to store the word. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "start_position" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "value" , + M.call (| + M.get_field (| M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |), "to_be_bytes32" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "extend_memory" , + M.call (| + M.get_name (| globals, "calculate_gas_extend_memory" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "memory" |); + make_list [ + make_tuple [ M.get_name (| globals, "start_position" |); M.call (| + M.get_name (| globals, "U256" |), + make_list [ + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_name (| globals, "value" |) + ], + make_dict [] + |) + ], + make_dict [] + |) ] + ] + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + BinOp.add (| + M.get_name (| globals, "GAS_VERY_LOW" |), + M.get_field (| M.get_name (| globals, "extend_memory" |), "cost" |) + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "memory" |), + BinOp.mult (| + Constant.bytes "00", + M.get_field (| M.get_name (| globals, "extend_memory" |), "expand_by" |) + |) + |) in + let _ := M.call (| + M.get_name (| globals, "memory_write" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "memory" |); + M.get_name (| globals, "start_position" |); + M.get_name (| globals, "value" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition mstore8 : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Stores a byte to memory. + This also expands the memory, if the memory is + insufficient to store the word. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "start_position" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "value" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "extend_memory" , + M.call (| + M.get_name (| globals, "calculate_gas_extend_memory" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "memory" |); + make_list [ + make_tuple [ M.get_name (| globals, "start_position" |); M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 1 + ], + make_dict [] + |) ] + ] + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + BinOp.add (| + M.get_name (| globals, "GAS_VERY_LOW" |), + M.get_field (| M.get_name (| globals, "extend_memory" |), "cost" |) + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "memory" |), + BinOp.mult (| + Constant.bytes "00", + M.get_field (| M.get_name (| globals, "extend_memory" |), "expand_by" |) + |) + |) in + let _ := M.assign_local (| + "normalized_bytes_value" , + M.call (| + M.get_name (| globals, "Bytes" |), + make_list [ + make_list [ + BinOp.bit_and (| + M.get_name (| globals, "value" |), + Constant.int 255 + |) + ] + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "memory_write" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "memory" |); + M.get_name (| globals, "start_position" |); + M.get_name (| globals, "normalized_bytes_value" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition mload : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Load word from memory. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "start_position" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "extend_memory" , + M.call (| + M.get_name (| globals, "calculate_gas_extend_memory" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "memory" |); + make_list [ + make_tuple [ M.get_name (| globals, "start_position" |); M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 32 + ], + make_dict [] + |) ] + ] + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + BinOp.add (| + M.get_name (| globals, "GAS_VERY_LOW" |), + M.get_field (| M.get_name (| globals, "extend_memory" |), "cost" |) + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "memory" |), + BinOp.mult (| + Constant.bytes "00", + M.get_field (| M.get_name (| globals, "extend_memory" |), "expand_by" |) + |) + |) in + let _ := M.assign_local (| + "value" , + M.call (| + M.get_field (| M.get_name (| globals, "U256" |), "from_be_bytes" |), + make_list [ + M.call (| + M.get_name (| globals, "memory_read_bytes" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "memory" |); + M.get_name (| globals, "start_position" |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 32 + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.get_name (| globals, "value" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition msize : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Push the size of active memory in bytes onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_BASE" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "memory" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). diff --git a/CoqOfPython/ethereum/berlin/vm/instructions/stack.v b/CoqOfPython/ethereum/berlin/vm/instructions/stack.v new file mode 100644 index 0000000..77860ad --- /dev/null +++ b/CoqOfPython/ethereum/berlin/vm/instructions/stack.v @@ -0,0 +1,947 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.berlin.vm.instructions.stack". + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) Stack Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM stack related instructions. +". + +Axiom functools_imports_partial : + IsImported globals "functools" "partial". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". + +Axiom ethereum_utils_ensure_imports_ensure : + IsImported globals "ethereum.utils.ensure" "ensure". + +Axiom ethereum_berlin_vm_imports_Evm : + IsImported globals "ethereum.berlin.vm" "Evm". +Axiom ethereum_berlin_vm_imports_stack : + IsImported globals "ethereum.berlin.vm" "stack". + +Axiom ethereum_berlin_vm_exceptions_imports_StackUnderflowError : + IsImported globals "ethereum.berlin.vm.exceptions" "StackUnderflowError". + +Axiom ethereum_berlin_vm_gas_imports_GAS_BASE : + IsImported globals "ethereum.berlin.vm.gas" "GAS_BASE". +Axiom ethereum_berlin_vm_gas_imports_GAS_VERY_LOW : + IsImported globals "ethereum.berlin.vm.gas" "GAS_VERY_LOW". +Axiom ethereum_berlin_vm_gas_imports_charge_gas : + IsImported globals "ethereum.berlin.vm.gas" "charge_gas". + +Axiom ethereum_berlin_vm_memory_imports_buffer_read : + IsImported globals "ethereum.berlin.vm.memory" "buffer_read". + +Definition pop : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Remove item from stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.call (| + M.get_field (| M.get_name (| globals, "stack" |), "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_BASE" |) + ], + make_dict [] + |) in + let _ := M.pass (| |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition push_n : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm"; "num_bytes" ] |) in + let _ := Constant.str " + Pushes a N-byte immediate onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + num_bytes : + The number of immediate bytes to be read from the code and pushed to + the stack. + + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_VERY_LOW" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "data_to_push" , + M.call (| + M.get_field (| M.get_name (| globals, "U256" |), "from_be_bytes" |), + make_list [ + M.call (| + M.get_name (| globals, "buffer_read" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "code" |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + BinOp.add (| + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) + ], + make_dict [] + |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + M.get_name (| globals, "num_bytes" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_field (| M.get_name (| globals, "stack" |), "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.get_name (| globals, "data_to_push" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + BinOp.add (| + Constant.int 1, + M.get_name (| globals, "num_bytes" |) + |) + |) in + M.pure Constant.None_)). + +Definition dup_n : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm"; "item_number" ] |) in + let _ := Constant.str " + Duplicate the Nth stack item (from top of the stack) to the top of stack. + + Parameters + ---------- + evm : + The current EVM frame. + + item_number : + The stack item number (0-indexed from top of stack) to be duplicated + to the top of stack. + + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_VERY_LOW" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + Compare.lt (| + M.get_name (| globals, "item_number" |), + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |); + M.get_name (| globals, "StackUnderflowError" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "data_to_duplicate" , + M.get_subscript (| + M.get_field (| M.get_name (| globals, "evm" |), "stack" |), + BinOp.sub (| + BinOp.sub (| + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |), + Constant.int 1 + |), + M.get_name (| globals, "item_number" |) + |) + |) + |) in + let _ := M.call (| + M.get_field (| M.get_name (| globals, "stack" |), "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.get_name (| globals, "data_to_duplicate" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition swap_n : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm"; "item_number" ] |) in + let _ := Constant.str " + Swap the top and the `item_number` element of the stack, where + the top of the stack is position zero. + + If `item_number` is zero, this function does nothing (which should not be + possible, since there is no `SWAP0` instruction). + + Parameters + ---------- + evm : + The current EVM frame. + + item_number : + The stack item number (0-indexed from top of stack) to be swapped + with the top of stack element. + + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_VERY_LOW" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + Compare.lt (| + M.get_name (| globals, "item_number" |), + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |); + M.get_name (| globals, "StackUnderflowError" |) + ], + make_dict [] + |) in + let _ := M.assign (| + make_tuple [ M.get_subscript (| + M.get_field (| M.get_name (| globals, "evm" |), "stack" |), + UnOp.sub (| Constant.int 1 |) + |); M.get_subscript (| + M.get_field (| M.get_name (| globals, "evm" |), "stack" |), + BinOp.sub (| + UnOp.sub (| Constant.int 1 |), + M.get_name (| globals, "item_number" |) + |) + |) ], + make_tuple [ M.get_subscript (| + M.get_field (| M.get_name (| globals, "evm" |), "stack" |), + BinOp.sub (| + UnOp.sub (| Constant.int 1 |), + M.get_name (| globals, "item_number" |) + |) + |); M.get_subscript (| + M.get_field (| M.get_name (| globals, "evm" |), "stack" |), + UnOp.sub (| Constant.int 1 |) + |) ] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition push1 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push2 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push3 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push4 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push5 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push6 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push7 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push8 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push9 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push10 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push11 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push12 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push13 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push14 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push15 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push16 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push17 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push18 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push19 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push20 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push21 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push22 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push23 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push24 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push25 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push26 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push27 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push28 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push29 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push30 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push31 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push32 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "push_n" |) + ], + make_dict [] + |) +)). + +Definition dup1 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "dup_n" |) + ], + make_dict [] + |) +)). + +Definition dup2 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "dup_n" |) + ], + make_dict [] + |) +)). + +Definition dup3 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "dup_n" |) + ], + make_dict [] + |) +)). + +Definition dup4 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "dup_n" |) + ], + make_dict [] + |) +)). + +Definition dup5 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "dup_n" |) + ], + make_dict [] + |) +)). + +Definition dup6 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "dup_n" |) + ], + make_dict [] + |) +)). + +Definition dup7 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "dup_n" |) + ], + make_dict [] + |) +)). + +Definition dup8 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "dup_n" |) + ], + make_dict [] + |) +)). + +Definition dup9 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "dup_n" |) + ], + make_dict [] + |) +)). + +Definition dup10 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "dup_n" |) + ], + make_dict [] + |) +)). + +Definition dup11 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "dup_n" |) + ], + make_dict [] + |) +)). + +Definition dup12 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "dup_n" |) + ], + make_dict [] + |) +)). + +Definition dup13 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "dup_n" |) + ], + make_dict [] + |) +)). + +Definition dup14 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "dup_n" |) + ], + make_dict [] + |) +)). + +Definition dup15 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "dup_n" |) + ], + make_dict [] + |) +)). + +Definition dup16 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "dup_n" |) + ], + make_dict [] + |) +)). + +Definition swap1 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "swap_n" |) + ], + make_dict [] + |) +)). + +Definition swap2 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "swap_n" |) + ], + make_dict [] + |) +)). + +Definition swap3 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "swap_n" |) + ], + make_dict [] + |) +)). + +Definition swap4 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "swap_n" |) + ], + make_dict [] + |) +)). + +Definition swap5 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "swap_n" |) + ], + make_dict [] + |) +)). + +Definition swap6 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "swap_n" |) + ], + make_dict [] + |) +)). + +Definition swap7 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "swap_n" |) + ], + make_dict [] + |) +)). + +Definition swap8 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "swap_n" |) + ], + make_dict [] + |) +)). + +Definition swap9 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "swap_n" |) + ], + make_dict [] + |) +)). + +Definition swap10 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "swap_n" |) + ], + make_dict [] + |) +)). + +Definition swap11 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "swap_n" |) + ], + make_dict [] + |) +)). + +Definition swap12 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "swap_n" |) + ], + make_dict [] + |) +)). + +Definition swap13 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "swap_n" |) + ], + make_dict [] + |) +)). + +Definition swap14 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "swap_n" |) + ], + make_dict [] + |) +)). + +Definition swap15 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "swap_n" |) + ], + make_dict [] + |) +)). + +Definition swap16 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "swap_n" |) + ], + make_dict [] + |) +)). diff --git a/CoqOfPython/ethereum/berlin/vm/instructions/storage.v b/CoqOfPython/ethereum/berlin/vm/instructions/storage.v new file mode 100644 index 0000000..8bf28fd --- /dev/null +++ b/CoqOfPython/ethereum/berlin/vm/instructions/storage.v @@ -0,0 +1,491 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.berlin.vm.instructions.storage". + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) Storage Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM storage related instructions. +". + +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". + +Axiom ethereum_utils_ensure_imports_ensure : + IsImported globals "ethereum.utils.ensure" "ensure". + +Axiom ethereum_berlin_state_imports_get_storage : + IsImported globals "ethereum.berlin.state" "get_storage". +Axiom ethereum_berlin_state_imports_get_storage_original : + IsImported globals "ethereum.berlin.state" "get_storage_original". +Axiom ethereum_berlin_state_imports_set_storage : + IsImported globals "ethereum.berlin.state" "set_storage". + +Axiom ethereum_berlin_vm_imports_Evm : + IsImported globals "ethereum.berlin.vm" "Evm". + +Axiom ethereum_berlin_vm_exceptions_imports_OutOfGasError : + IsImported globals "ethereum.berlin.vm.exceptions" "OutOfGasError". +Axiom ethereum_berlin_vm_exceptions_imports_WriteInStaticContext : + IsImported globals "ethereum.berlin.vm.exceptions" "WriteInStaticContext". + +Axiom ethereum_berlin_vm_gas_imports_GAS_CALL_STIPEND : + IsImported globals "ethereum.berlin.vm.gas" "GAS_CALL_STIPEND". +Axiom ethereum_berlin_vm_gas_imports_GAS_COLD_SLOAD : + IsImported globals "ethereum.berlin.vm.gas" "GAS_COLD_SLOAD". +Axiom ethereum_berlin_vm_gas_imports_GAS_STORAGE_CLEAR_REFUND : + IsImported globals "ethereum.berlin.vm.gas" "GAS_STORAGE_CLEAR_REFUND". +Axiom ethereum_berlin_vm_gas_imports_GAS_STORAGE_SET : + IsImported globals "ethereum.berlin.vm.gas" "GAS_STORAGE_SET". +Axiom ethereum_berlin_vm_gas_imports_GAS_STORAGE_UPDATE : + IsImported globals "ethereum.berlin.vm.gas" "GAS_STORAGE_UPDATE". +Axiom ethereum_berlin_vm_gas_imports_GAS_WARM_ACCESS : + IsImported globals "ethereum.berlin.vm.gas" "GAS_WARM_ACCESS". +Axiom ethereum_berlin_vm_gas_imports_charge_gas : + IsImported globals "ethereum.berlin.vm.gas" "charge_gas". + +Axiom ethereum_berlin_vm_stack_imports_pop : + IsImported globals "ethereum.berlin.vm.stack" "pop". +Axiom ethereum_berlin_vm_stack_imports_push : + IsImported globals "ethereum.berlin.vm.stack" "push". + +Definition sload : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Loads to the stack, the value corresponding to a certain key from the + storage of the current account. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "key" , + M.call (| + M.get_field (| M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |), "to_be_bytes32" |), + make_list [], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.in_ (| + make_tuple [ M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "current_target" |); M.get_name (| globals, "key" |) ], + M.get_field (| M.get_name (| globals, "evm" |), "accessed_storage_keys" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_WARM_ACCESS" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "accessed_storage_keys" |), "add" |), + make_list [ + make_tuple [ M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "current_target" |); M.get_name (| globals, "key" |) ] + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_COLD_SLOAD" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "value" , + M.call (| + M.get_name (| globals, "get_storage" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "env" |), "state" |); + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "current_target" |); + M.get_name (| globals, "key" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.get_name (| globals, "value" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition sstore : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Stores a value at a certain key in the current context's storage. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "key" , + M.call (| + M.get_field (| M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |), "to_be_bytes32" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "new_value" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + Compare.gt (| + M.get_field (| M.get_name (| globals, "evm" |), "gas_left" |), + M.get_name (| globals, "GAS_CALL_STIPEND" |) + |); + M.get_name (| globals, "OutOfGasError" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "original_value" , + M.call (| + M.get_name (| globals, "get_storage_original" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "env" |), "state" |); + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "current_target" |); + M.get_name (| globals, "key" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "current_value" , + M.call (| + M.get_name (| globals, "get_storage" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "env" |), "state" |); + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "current_target" |); + M.get_name (| globals, "key" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "gas_cost" , + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.not_in (| + make_tuple [ M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "current_target" |); M.get_name (| globals, "key" |) ], + M.get_field (| M.get_name (| globals, "evm" |), "accessed_storage_keys" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "accessed_storage_keys" |), "add" |), + make_list [ + make_tuple [ M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "current_target" |); M.get_name (| globals, "key" |) ] + ], + make_dict [] + |) in + let _ := M.assign_op_local (| + BinOp.add, + "gas_cost", + M.get_name (| globals, "GAS_COLD_SLOAD" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + BoolOp.and (| + Compare.eq (| + M.get_name (| globals, "original_value" |), + M.get_name (| globals, "current_value" |) + |), + ltac:(M.monadic ( + Compare.not_eq (| + M.get_name (| globals, "current_value" |), + M.get_name (| globals, "new_value" |) + |) + )) + |), + (* then *) + ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, "original_value" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_op_local (| + BinOp.add, + "gas_cost", + M.get_name (| globals, "GAS_STORAGE_SET" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_op_local (| + BinOp.add, + "gas_cost", + BinOp.sub (| + M.get_name (| globals, "GAS_STORAGE_UPDATE" |), + M.get_name (| globals, "GAS_COLD_SLOAD" |) + |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_op_local (| + BinOp.add, + "gas_cost", + M.get_name (| globals, "GAS_WARM_ACCESS" |) + |) in + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + Compare.not_eq (| + M.get_name (| globals, "current_value" |), + M.get_name (| globals, "new_value" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + BoolOp.and (| + Compare.not_eq (| + M.get_name (| globals, "original_value" |), + Constant.int 0 + |), + ltac:(M.monadic ( + BoolOp.and (| + Compare.not_eq (| + M.get_name (| globals, "current_value" |), + Constant.int 0 + |), + ltac:(M.monadic ( + Compare.eq (| + M.get_name (| globals, "new_value" |), + Constant.int 0 + |) + )) + |) + )) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "refund_counter" |), + M.call (| + M.get_name (| globals, "int" |), + make_list [ + M.get_name (| globals, "GAS_STORAGE_CLEAR_REFUND" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + BoolOp.and (| + Compare.not_eq (| + M.get_name (| globals, "original_value" |), + Constant.int 0 + |), + ltac:(M.monadic ( + Compare.eq (| + M.get_name (| globals, "current_value" |), + Constant.int 0 + |) + )) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_op (| + BinOp.sub, + M.get_field (| M.get_name (| globals, "evm" |), "refund_counter" |), + M.call (| + M.get_name (| globals, "int" |), + make_list [ + M.get_name (| globals, "GAS_STORAGE_CLEAR_REFUND" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, "original_value" |), + M.get_name (| globals, "new_value" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, "original_value" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "refund_counter" |), + M.call (| + M.get_name (| globals, "int" |), + make_list [ + BinOp.sub (| + M.get_name (| globals, "GAS_STORAGE_SET" |), + M.get_name (| globals, "GAS_WARM_ACCESS" |) + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "refund_counter" |), + M.call (| + M.get_name (| globals, "int" |), + make_list [ + BinOp.sub (| + BinOp.sub (| + M.get_name (| globals, "GAS_STORAGE_UPDATE" |), + M.get_name (| globals, "GAS_COLD_SLOAD" |) + |), + M.get_name (| globals, "GAS_WARM_ACCESS" |) + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "gas_cost" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + UnOp.not (| M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "is_static" |) |); + M.get_name (| globals, "WriteInStaticContext" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "set_storage" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "env" |), "state" |); + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "current_target" |); + M.get_name (| globals, "key" |); + M.get_name (| globals, "new_value" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). diff --git a/CoqOfPython/ethereum/berlin/vm/instructions/system.v b/CoqOfPython/ethereum/berlin/vm/instructions/system.v new file mode 100644 index 0000000..313e0af --- /dev/null +++ b/CoqOfPython/ethereum/berlin/vm/instructions/system.v @@ -0,0 +1,2268 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.berlin.vm.instructions.system". + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) System Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM system related instructions. +". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_Bytes0 : + IsImported globals "ethereum.base_types" "Bytes0". +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". + +Axiom ethereum_utils_ensure_imports_ensure : + IsImported globals "ethereum.utils.ensure" "ensure". + +Axiom ethereum_utils_numeric_imports_ceil32 : + IsImported globals "ethereum.utils.numeric" "ceil32". + +Axiom ethereum_berlin_fork_types_imports_Address : + IsImported globals "ethereum.berlin.fork_types" "Address". + +Axiom ethereum_berlin_state_imports_account_exists_and_is_empty : + IsImported globals "ethereum.berlin.state" "account_exists_and_is_empty". +Axiom ethereum_berlin_state_imports_account_has_code_or_nonce : + IsImported globals "ethereum.berlin.state" "account_has_code_or_nonce". +Axiom ethereum_berlin_state_imports_get_account : + IsImported globals "ethereum.berlin.state" "get_account". +Axiom ethereum_berlin_state_imports_increment_nonce : + IsImported globals "ethereum.berlin.state" "increment_nonce". +Axiom ethereum_berlin_state_imports_is_account_alive : + IsImported globals "ethereum.berlin.state" "is_account_alive". +Axiom ethereum_berlin_state_imports_set_account_balance : + IsImported globals "ethereum.berlin.state" "set_account_balance". + +Axiom ethereum_berlin_utils_address_imports_compute_contract_address : + IsImported globals "ethereum.berlin.utils.address" "compute_contract_address". +Axiom ethereum_berlin_utils_address_imports_compute_create2_contract_address : + IsImported globals "ethereum.berlin.utils.address" "compute_create2_contract_address". +Axiom ethereum_berlin_utils_address_imports_to_address : + IsImported globals "ethereum.berlin.utils.address" "to_address". + +Axiom ethereum_berlin_vm_imports_Evm : + IsImported globals "ethereum.berlin.vm" "Evm". +Axiom ethereum_berlin_vm_imports_Message : + IsImported globals "ethereum.berlin.vm" "Message". +Axiom ethereum_berlin_vm_imports_incorporate_child_on_error : + IsImported globals "ethereum.berlin.vm" "incorporate_child_on_error". +Axiom ethereum_berlin_vm_imports_incorporate_child_on_success : + IsImported globals "ethereum.berlin.vm" "incorporate_child_on_success". + +Axiom ethereum_berlin_vm_exceptions_imports_Revert : + IsImported globals "ethereum.berlin.vm.exceptions" "Revert". +Axiom ethereum_berlin_vm_exceptions_imports_WriteInStaticContext : + IsImported globals "ethereum.berlin.vm.exceptions" "WriteInStaticContext". + +Axiom ethereum_berlin_vm_gas_imports_GAS_CALL_VALUE : + IsImported globals "ethereum.berlin.vm.gas" "GAS_CALL_VALUE". +Axiom ethereum_berlin_vm_gas_imports_GAS_COLD_ACCOUNT_ACCESS : + IsImported globals "ethereum.berlin.vm.gas" "GAS_COLD_ACCOUNT_ACCESS". +Axiom ethereum_berlin_vm_gas_imports_GAS_CREATE : + IsImported globals "ethereum.berlin.vm.gas" "GAS_CREATE". +Axiom ethereum_berlin_vm_gas_imports_GAS_KECCAK256_WORD : + IsImported globals "ethereum.berlin.vm.gas" "GAS_KECCAK256_WORD". +Axiom ethereum_berlin_vm_gas_imports_GAS_NEW_ACCOUNT : + IsImported globals "ethereum.berlin.vm.gas" "GAS_NEW_ACCOUNT". +Axiom ethereum_berlin_vm_gas_imports_GAS_SELF_DESTRUCT : + IsImported globals "ethereum.berlin.vm.gas" "GAS_SELF_DESTRUCT". +Axiom ethereum_berlin_vm_gas_imports_GAS_SELF_DESTRUCT_NEW_ACCOUNT : + IsImported globals "ethereum.berlin.vm.gas" "GAS_SELF_DESTRUCT_NEW_ACCOUNT". +Axiom ethereum_berlin_vm_gas_imports_GAS_WARM_ACCESS : + IsImported globals "ethereum.berlin.vm.gas" "GAS_WARM_ACCESS". +Axiom ethereum_berlin_vm_gas_imports_GAS_ZERO : + IsImported globals "ethereum.berlin.vm.gas" "GAS_ZERO". +Axiom ethereum_berlin_vm_gas_imports_REFUND_SELF_DESTRUCT : + IsImported globals "ethereum.berlin.vm.gas" "REFUND_SELF_DESTRUCT". +Axiom ethereum_berlin_vm_gas_imports_calculate_gas_extend_memory : + IsImported globals "ethereum.berlin.vm.gas" "calculate_gas_extend_memory". +Axiom ethereum_berlin_vm_gas_imports_calculate_message_call_gas : + IsImported globals "ethereum.berlin.vm.gas" "calculate_message_call_gas". +Axiom ethereum_berlin_vm_gas_imports_charge_gas : + IsImported globals "ethereum.berlin.vm.gas" "charge_gas". +Axiom ethereum_berlin_vm_gas_imports_max_message_call_gas : + IsImported globals "ethereum.berlin.vm.gas" "max_message_call_gas". + +Axiom ethereum_berlin_vm_memory_imports_memory_read_bytes : + IsImported globals "ethereum.berlin.vm.memory" "memory_read_bytes". +Axiom ethereum_berlin_vm_memory_imports_memory_write : + IsImported globals "ethereum.berlin.vm.memory" "memory_write". + +Axiom ethereum_berlin_vm_stack_imports_pop : + IsImported globals "ethereum.berlin.vm.stack" "pop". +Axiom ethereum_berlin_vm_stack_imports_push : + IsImported globals "ethereum.berlin.vm.stack" "push". + +Definition generic_create : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm"; "endowment"; "contract_address"; "memory_start_position"; "memory_size" ] |) in + let _ := Constant.str " + Core logic used by the `CREATE*` family of opcodes. + " in +(* At stmt: unsupported node type: ImportFrom *) + let _ := M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "accessed_addresses" |), "add" |), + make_list [ + M.get_name (| globals, "contract_address" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "create_message_gas" , + M.call (| + M.get_name (| globals, "max_message_call_gas" |), + make_list [ + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "gas_left" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_op (| + BinOp.sub, + M.get_field (| M.get_name (| globals, "evm" |), "gas_left" |), + M.get_name (| globals, "create_message_gas" |) + |) in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + UnOp.not (| M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "is_static" |) |); + M.get_name (| globals, "WriteInStaticContext" |) + ], + make_dict [] + |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, "evm" |), "return_data" |), + Constant.bytes "" + |) in + let _ := M.assign_local (| + "sender_address" , + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "current_target" |) + |) in + let _ := M.assign_local (| + "sender" , + M.call (| + M.get_name (| globals, "get_account" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "env" |), "state" |); + M.get_name (| globals, "sender_address" |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + BoolOp.or (| + Compare.lt (| + M.get_field (| M.get_name (| globals, "sender" |), "balance" |), + M.get_name (| globals, "endowment" |) + |), + ltac:(M.monadic ( + BoolOp.or (| + Compare.eq (| + M.get_field (| M.get_name (| globals, "sender" |), "nonce" |), + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + BinOp.sub (| + BinOp.pow (| + Constant.int 2, + Constant.int 64 + |), + Constant.int 1 + |) + ], + make_dict [] + |) + |), + ltac:(M.monadic ( + Compare.gt (| + BinOp.add (| + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "depth" |), + Constant.int 1 + |), + M.get_name (| globals, "STACK_DEPTH_LIMIT" |) + |) + )) + |) + )) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "gas_left" |), + M.get_name (| globals, "create_message_gas" |) + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.return_ (| + Constant.None_ + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, "account_has_code_or_nonce" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "env" |), "state" |); + M.get_name (| globals, "contract_address" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, "increment_nonce" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "env" |), "state" |); + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "current_target" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.return_ (| + Constant.None_ + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "call_data" , + M.call (| + M.get_name (| globals, "memory_read_bytes" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "memory" |); + M.get_name (| globals, "memory_start_position" |); + M.get_name (| globals, "memory_size" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "increment_nonce" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "env" |), "state" |); + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "current_target" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "child_message" , + M.call (| + M.get_name (| globals, "Message" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "child_evm" , + M.call (| + M.get_name (| globals, "process_create_message" |), + make_list [ + M.get_name (| globals, "child_message" |); + M.get_field (| M.get_name (| globals, "evm" |), "env" |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + M.get_field (| M.get_name (| globals, "child_evm" |), "error" |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, "incorporate_child_on_error" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "child_evm" |) + ], + make_dict [] + |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, "evm" |), "return_data" |), + M.get_field (| M.get_name (| globals, "child_evm" |), "output" |) + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + ], + make_dict [] + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, "incorporate_child_on_success" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "child_evm" |) + ], + make_dict [] + |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, "evm" |), "return_data" |), + Constant.bytes "" + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.call (| + M.get_field (| M.get_name (| globals, "U256" |), "from_be_bytes" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "child_evm" |), "message" |), "current_target" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_)). + +Definition create : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Creates a new account with associated code. + + Parameters + ---------- + evm : + The current EVM frame. + " in + let _ := M.assign_local (| + "endowment" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_start_position" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_size" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "extend_memory" , + M.call (| + M.get_name (| globals, "calculate_gas_extend_memory" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "memory" |); + make_list [ + make_tuple [ M.get_name (| globals, "memory_start_position" |); M.get_name (| globals, "memory_size" |) ] + ] + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + BinOp.add (| + M.get_name (| globals, "GAS_CREATE" |), + M.get_field (| M.get_name (| globals, "extend_memory" |), "cost" |) + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "memory" |), + BinOp.mult (| + Constant.bytes "00", + M.get_field (| M.get_name (| globals, "extend_memory" |), "expand_by" |) + |) + |) in + let _ := M.assign_local (| + "contract_address" , + M.call (| + M.get_name (| globals, "compute_contract_address" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "current_target" |); + M.get_field (| M.call (| + M.get_name (| globals, "get_account" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "env" |), "state" |); + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "current_target" |) + ], + make_dict [] + |), "nonce" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "generic_create" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "endowment" |); + M.get_name (| globals, "contract_address" |); + M.get_name (| globals, "memory_start_position" |); + M.get_name (| globals, "memory_size" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition create2 : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Creates a new account with associated code. + + It's similar to CREATE opcode except that the address of new account + depends on the init_code instead of the nonce of sender. + + Parameters + ---------- + evm : + The current EVM frame. + " in + let _ := M.assign_local (| + "endowment" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_start_position" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_size" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "salt" , + M.call (| + M.get_field (| M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |), "to_be_bytes32" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "extend_memory" , + M.call (| + M.get_name (| globals, "calculate_gas_extend_memory" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "memory" |); + make_list [ + make_tuple [ M.get_name (| globals, "memory_start_position" |); M.get_name (| globals, "memory_size" |) ] + ] + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "call_data_words" , + BinOp.floor_div (| + M.call (| + M.get_name (| globals, "ceil32" |), + make_list [ + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.get_name (| globals, "memory_size" |) + ], + make_dict [] + |) + ], + make_dict [] + |), + Constant.int 32 + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + BinOp.add (| + BinOp.add (| + M.get_name (| globals, "GAS_CREATE" |), + BinOp.mult (| + M.get_name (| globals, "GAS_KECCAK256_WORD" |), + M.get_name (| globals, "call_data_words" |) + |) + |), + M.get_field (| M.get_name (| globals, "extend_memory" |), "cost" |) + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "memory" |), + BinOp.mult (| + Constant.bytes "00", + M.get_field (| M.get_name (| globals, "extend_memory" |), "expand_by" |) + |) + |) in + let _ := M.assign_local (| + "contract_address" , + M.call (| + M.get_name (| globals, "compute_create2_contract_address" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "current_target" |); + M.get_name (| globals, "salt" |); + M.call (| + M.get_name (| globals, "memory_read_bytes" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "memory" |); + M.get_name (| globals, "memory_start_position" |); + M.get_name (| globals, "memory_size" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "generic_create" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "endowment" |); + M.get_name (| globals, "contract_address" |); + M.get_name (| globals, "memory_start_position" |); + M.get_name (| globals, "memory_size" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition return_ : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Halts execution returning output data. + + Parameters + ---------- + evm : + The current EVM frame. + " in + let _ := M.assign_local (| + "memory_start_position" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_size" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "extend_memory" , + M.call (| + M.get_name (| globals, "calculate_gas_extend_memory" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "memory" |); + make_list [ + make_tuple [ M.get_name (| globals, "memory_start_position" |); M.get_name (| globals, "memory_size" |) ] + ] + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + BinOp.add (| + M.get_name (| globals, "GAS_ZERO" |), + M.get_field (| M.get_name (| globals, "extend_memory" |), "cost" |) + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "memory" |), + BinOp.mult (| + Constant.bytes "00", + M.get_field (| M.get_name (| globals, "extend_memory" |), "expand_by" |) + |) + |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, "evm" |), "output" |), + M.call (| + M.get_name (| globals, "memory_read_bytes" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "memory" |); + M.get_name (| globals, "memory_start_position" |); + M.get_name (| globals, "memory_size" |) + ], + make_dict [] + |) + |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, "evm" |), "running" |), + Constant.bool false + |) in + let _ := M.pass (| |) in + M.pure Constant.None_)). + +Definition generic_call : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm"; "gas"; "value"; "caller"; "to"; "code_address"; "should_transfer_value"; "is_staticcall"; "memory_input_start_position"; "memory_input_size"; "memory_output_start_position"; "memory_output_size" ] |) in + let _ := Constant.str " + Perform the core logic of the `CALL*` family of opcodes. + " in +(* At stmt: unsupported node type: ImportFrom *) + let _ := M.assign (| + M.get_field (| M.get_name (| globals, "evm" |), "return_data" |), + Constant.bytes "" + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.gt (| + BinOp.add (| + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "depth" |), + Constant.int 1 + |), + M.get_name (| globals, "STACK_DEPTH_LIMIT" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "gas_left" |), + M.get_name (| globals, "gas" |) + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.return_ (| + Constant.None_ + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "call_data" , + M.call (| + M.get_name (| globals, "memory_read_bytes" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "memory" |); + M.get_name (| globals, "memory_input_start_position" |); + M.get_name (| globals, "memory_input_size" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "code" , + M.get_field (| M.call (| + M.get_name (| globals, "get_account" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "env" |), "state" |); + M.get_name (| globals, "code_address" |) + ], + make_dict [] + |), "code" |) + |) in + let _ := M.assign_local (| + "child_message" , + M.call (| + M.get_name (| globals, "Message" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "child_evm" , + M.call (| + M.get_name (| globals, "process_message" |), + make_list [ + M.get_name (| globals, "child_message" |); + M.get_field (| M.get_name (| globals, "evm" |), "env" |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + M.get_field (| M.get_name (| globals, "child_evm" |), "error" |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, "incorporate_child_on_error" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "child_evm" |) + ], + make_dict [] + |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, "evm" |), "return_data" |), + M.get_field (| M.get_name (| globals, "child_evm" |), "output" |) + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + ], + make_dict [] + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, "incorporate_child_on_success" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "child_evm" |) + ], + make_dict [] + |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, "evm" |), "return_data" |), + M.get_field (| M.get_name (| globals, "child_evm" |), "output" |) + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 1 + ], + make_dict [] + |) + ], + make_dict [] + |) in + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "actual_output_size" , + M.call (| + M.get_name (| globals, "min" |), + make_list [ + M.get_name (| globals, "memory_output_size" |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_field (| M.get_name (| globals, "child_evm" |), "output" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "memory_write" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "memory" |); + M.get_name (| globals, "memory_output_start_position" |); + M.slice (| + M.get_field (| M.get_name (| globals, "child_evm" |), "output" |), + Constant.None_, + M.get_name (| globals, "actual_output_size" |), + Constant.None_ + |) + ], + make_dict [] + |) in + M.pure Constant.None_)). + +Definition call : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Message-call into an account. + + Parameters + ---------- + evm : + The current EVM frame. + " in + let _ := M.assign_local (| + "gas" , + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "to" , + M.call (| + M.get_name (| globals, "to_address" |), + make_list [ + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "value" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_input_start_position" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_input_size" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_output_start_position" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_output_size" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "extend_memory" , + M.call (| + M.get_name (| globals, "calculate_gas_extend_memory" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "memory" |); + make_list [ + make_tuple [ M.get_name (| globals, "memory_input_start_position" |); M.get_name (| globals, "memory_input_size" |) ]; + make_tuple [ M.get_name (| globals, "memory_output_start_position" |); M.get_name (| globals, "memory_output_size" |) ] + ] + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.in_ (| + M.get_name (| globals, "to" |), + M.get_field (| M.get_name (| globals, "evm" |), "accessed_addresses" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "access_gas_cost" , + M.get_name (| globals, "GAS_WARM_ACCESS" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "accessed_addresses" |), "add" |), + make_list [ + M.get_name (| globals, "to" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "access_gas_cost" , + M.get_name (| globals, "GAS_COLD_ACCOUNT_ACCESS" |) + |) in + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "create_gas_cost" , + (* if *) + M.if_then_else (| + BoolOp.or (| + M.call (| + M.get_name (| globals, "is_account_alive" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "env" |), "state" |); + M.get_name (| globals, "to" |) + ], + make_dict [] + |), + ltac:(M.monadic ( + Compare.eq (| + M.get_name (| globals, "value" |), + Constant.int 0 + |) + )) + |), + (* then *) + ltac:(M.monadic ( +M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + (* else *) + )), ltac:(M.monadic ( +M.get_name (| globals, "GAS_NEW_ACCOUNT" |) + )) |) + |) in + let _ := M.assign_local (| + "transfer_gas_cost" , + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, "value" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( +M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + (* else *) + )), ltac:(M.monadic ( +M.get_name (| globals, "GAS_CALL_VALUE" |) + )) |) + |) in + let _ := M.assign_local (| + "message_call_gas" , + M.call (| + M.get_name (| globals, "calculate_message_call_gas" |), + make_list [ + M.get_name (| globals, "value" |); + M.get_name (| globals, "gas" |); + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "gas_left" |) + ], + make_dict [] + |); + M.get_field (| M.get_name (| globals, "extend_memory" |), "cost" |); + BinOp.add (| + BinOp.add (| + M.get_name (| globals, "access_gas_cost" |), + M.get_name (| globals, "create_gas_cost" |) + |), + M.get_name (| globals, "transfer_gas_cost" |) + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + BinOp.add (| + M.get_field (| M.get_name (| globals, "message_call_gas" |), "cost" |), + M.get_field (| M.get_name (| globals, "extend_memory" |), "cost" |) + |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + BoolOp.or (| + UnOp.not (| M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "is_static" |) |), + ltac:(M.monadic ( + Compare.eq (| + M.get_name (| globals, "value" |), + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + |) + )) + |); + M.get_name (| globals, "WriteInStaticContext" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "memory" |), + BinOp.mult (| + Constant.bytes "00", + M.get_field (| M.get_name (| globals, "extend_memory" |), "expand_by" |) + |) + |) in + let _ := M.assign_local (| + "sender_balance" , + M.get_field (| M.call (| + M.get_name (| globals, "get_account" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "env" |), "state" |); + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "current_target" |) + ], + make_dict [] + |), "balance" |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.lt (| + M.get_name (| globals, "sender_balance" |), + M.get_name (| globals, "value" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, "evm" |), "return_data" |), + Constant.bytes "" + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "gas_left" |), + M.get_field (| M.get_name (| globals, "message_call_gas" |), "stipend" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, "generic_call" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_field (| M.get_name (| globals, "message_call_gas" |), "stipend" |); + M.get_name (| globals, "value" |); + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "current_target" |); + M.get_name (| globals, "to" |); + M.get_name (| globals, "to" |); + Constant.bool true; + Constant.bool false; + M.get_name (| globals, "memory_input_start_position" |); + M.get_name (| globals, "memory_input_size" |); + M.get_name (| globals, "memory_output_start_position" |); + M.get_name (| globals, "memory_output_size" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + )) |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition callcode : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Message-call into this account with alternative account’s code. + + Parameters + ---------- + evm : + The current EVM frame. + " in + let _ := M.assign_local (| + "gas" , + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "code_address" , + M.call (| + M.get_name (| globals, "to_address" |), + make_list [ + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "value" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_input_start_position" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_input_size" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_output_start_position" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_output_size" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "to" , + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "current_target" |) + |) in + let _ := M.assign_local (| + "extend_memory" , + M.call (| + M.get_name (| globals, "calculate_gas_extend_memory" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "memory" |); + make_list [ + make_tuple [ M.get_name (| globals, "memory_input_start_position" |); M.get_name (| globals, "memory_input_size" |) ]; + make_tuple [ M.get_name (| globals, "memory_output_start_position" |); M.get_name (| globals, "memory_output_size" |) ] + ] + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.in_ (| + M.get_name (| globals, "code_address" |), + M.get_field (| M.get_name (| globals, "evm" |), "accessed_addresses" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "access_gas_cost" , + M.get_name (| globals, "GAS_WARM_ACCESS" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "accessed_addresses" |), "add" |), + make_list [ + M.get_name (| globals, "code_address" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "access_gas_cost" , + M.get_name (| globals, "GAS_COLD_ACCOUNT_ACCESS" |) + |) in + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "transfer_gas_cost" , + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, "value" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( +M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + (* else *) + )), ltac:(M.monadic ( +M.get_name (| globals, "GAS_CALL_VALUE" |) + )) |) + |) in + let _ := M.assign_local (| + "message_call_gas" , + M.call (| + M.get_name (| globals, "calculate_message_call_gas" |), + make_list [ + M.get_name (| globals, "value" |); + M.get_name (| globals, "gas" |); + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "gas_left" |) + ], + make_dict [] + |); + M.get_field (| M.get_name (| globals, "extend_memory" |), "cost" |); + BinOp.add (| + M.get_name (| globals, "access_gas_cost" |), + M.get_name (| globals, "transfer_gas_cost" |) + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + BinOp.add (| + M.get_field (| M.get_name (| globals, "message_call_gas" |), "cost" |), + M.get_field (| M.get_name (| globals, "extend_memory" |), "cost" |) + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "memory" |), + BinOp.mult (| + Constant.bytes "00", + M.get_field (| M.get_name (| globals, "extend_memory" |), "expand_by" |) + |) + |) in + let _ := M.assign_local (| + "sender_balance" , + M.get_field (| M.call (| + M.get_name (| globals, "get_account" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "env" |), "state" |); + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "current_target" |) + ], + make_dict [] + |), "balance" |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.lt (| + M.get_name (| globals, "sender_balance" |), + M.get_name (| globals, "value" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, "evm" |), "return_data" |), + Constant.bytes "" + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "gas_left" |), + M.get_field (| M.get_name (| globals, "message_call_gas" |), "stipend" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, "generic_call" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_field (| M.get_name (| globals, "message_call_gas" |), "stipend" |); + M.get_name (| globals, "value" |); + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "current_target" |); + M.get_name (| globals, "to" |); + M.get_name (| globals, "code_address" |); + Constant.bool true; + Constant.bool false; + M.get_name (| globals, "memory_input_start_position" |); + M.get_name (| globals, "memory_input_size" |); + M.get_name (| globals, "memory_output_start_position" |); + M.get_name (| globals, "memory_output_size" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + )) |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition selfdestruct : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Halt execution and register account for later deletion. + + Parameters + ---------- + evm : + The current EVM frame. + " in + let _ := M.assign_local (| + "beneficiary" , + M.call (| + M.get_name (| globals, "to_address" |), + make_list [ + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "gas_cost" , + M.get_name (| globals, "GAS_SELF_DESTRUCT" |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.not_in (| + M.get_name (| globals, "beneficiary" |), + M.get_field (| M.get_name (| globals, "evm" |), "accessed_addresses" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "accessed_addresses" |), "add" |), + make_list [ + M.get_name (| globals, "beneficiary" |) + ], + make_dict [] + |) in + let _ := M.assign_op_local (| + BinOp.add, + "gas_cost", + M.get_name (| globals, "GAS_COLD_ACCOUNT_ACCESS" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + BoolOp.and (| + UnOp.not (| M.call (| + M.get_name (| globals, "is_account_alive" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "env" |), "state" |); + M.get_name (| globals, "beneficiary" |) + ], + make_dict [] + |) |), + ltac:(M.monadic ( + Compare.not_eq (| + M.get_field (| M.call (| + M.get_name (| globals, "get_account" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "env" |), "state" |); + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "current_target" |) + ], + make_dict [] + |), "balance" |), + Constant.int 0 + |) + )) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_op_local (| + BinOp.add, + "gas_cost", + M.get_name (| globals, "GAS_SELF_DESTRUCT_NEW_ACCOUNT" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "originator" , + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "current_target" |) + |) in + let _ := M.assign_local (| + "refunded_accounts" , + M.get_field (| M.get_name (| globals, "evm" |), "accounts_to_delete" |) + |) in + let _ := M.assign_local (| + "parent_evm" , + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "parent_evm" |) + |) in + let _ := + M.while (| + Compare.is_not (| + M.get_name (| globals, "parent_evm" |), + Constant.None_ + |), + ltac:(M.monadic ( + let _ := M.call (| + M.get_field (| M.get_name (| globals, "refunded_accounts" |), "update" |), + make_list [ + M.get_field (| M.get_name (| globals, "parent_evm" |), "accounts_to_delete" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "parent_evm" , + M.get_field (| M.get_field (| M.get_name (| globals, "parent_evm" |), "message" |), "parent_evm" |) + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.not_in (| + M.get_name (| globals, "originator" |), + M.get_name (| globals, "refunded_accounts" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "refund_counter" |), + M.get_name (| globals, "REFUND_SELF_DESTRUCT" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "gas_cost" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + UnOp.not (| M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "is_static" |) |); + M.get_name (| globals, "WriteInStaticContext" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "beneficiary_balance" , + M.get_field (| M.call (| + M.get_name (| globals, "get_account" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "env" |), "state" |); + M.get_name (| globals, "beneficiary" |) + ], + make_dict [] + |), "balance" |) + |) in + let _ := M.assign_local (| + "originator_balance" , + M.get_field (| M.call (| + M.get_name (| globals, "get_account" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "env" |), "state" |); + M.get_name (| globals, "originator" |) + ], + make_dict [] + |), "balance" |) + |) in + let _ := M.call (| + M.get_name (| globals, "set_account_balance" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "env" |), "state" |); + M.get_name (| globals, "beneficiary" |); + BinOp.add (| + M.get_name (| globals, "beneficiary_balance" |), + M.get_name (| globals, "originator_balance" |) + |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "set_account_balance" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "env" |), "state" |); + M.get_name (| globals, "originator" |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "accounts_to_delete" |), "add" |), + make_list [ + M.get_name (| globals, "originator" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, "account_exists_and_is_empty" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "env" |), "state" |); + M.get_name (| globals, "beneficiary" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "touched_accounts" |), "add" |), + make_list [ + M.get_name (| globals, "beneficiary" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, "evm" |), "running" |), + Constant.bool false + |) in + let _ := M.pass (| |) in + M.pure Constant.None_)). + +Definition delegatecall : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Message-call into an account. + + Parameters + ---------- + evm : + The current EVM frame. + " in + let _ := M.assign_local (| + "gas" , + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "code_address" , + M.call (| + M.get_name (| globals, "to_address" |), + make_list [ + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_input_start_position" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_input_size" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_output_start_position" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_output_size" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "extend_memory" , + M.call (| + M.get_name (| globals, "calculate_gas_extend_memory" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "memory" |); + make_list [ + make_tuple [ M.get_name (| globals, "memory_input_start_position" |); M.get_name (| globals, "memory_input_size" |) ]; + make_tuple [ M.get_name (| globals, "memory_output_start_position" |); M.get_name (| globals, "memory_output_size" |) ] + ] + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.in_ (| + M.get_name (| globals, "code_address" |), + M.get_field (| M.get_name (| globals, "evm" |), "accessed_addresses" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "access_gas_cost" , + M.get_name (| globals, "GAS_WARM_ACCESS" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "accessed_addresses" |), "add" |), + make_list [ + M.get_name (| globals, "code_address" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "access_gas_cost" , + M.get_name (| globals, "GAS_COLD_ACCOUNT_ACCESS" |) + |) in + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "message_call_gas" , + M.call (| + M.get_name (| globals, "calculate_message_call_gas" |), + make_list [ + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |); + M.get_name (| globals, "gas" |); + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "gas_left" |) + ], + make_dict [] + |); + M.get_field (| M.get_name (| globals, "extend_memory" |), "cost" |); + M.get_name (| globals, "access_gas_cost" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + BinOp.add (| + M.get_field (| M.get_name (| globals, "message_call_gas" |), "cost" |), + M.get_field (| M.get_name (| globals, "extend_memory" |), "cost" |) + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "memory" |), + BinOp.mult (| + Constant.bytes "00", + M.get_field (| M.get_name (| globals, "extend_memory" |), "expand_by" |) + |) + |) in + let _ := M.call (| + M.get_name (| globals, "generic_call" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_field (| M.get_name (| globals, "message_call_gas" |), "stipend" |); + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "value" |); + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "caller" |); + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "current_target" |); + M.get_name (| globals, "code_address" |); + Constant.bool false; + Constant.bool false; + M.get_name (| globals, "memory_input_start_position" |); + M.get_name (| globals, "memory_input_size" |); + M.get_name (| globals, "memory_output_start_position" |); + M.get_name (| globals, "memory_output_size" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition staticcall : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Message-call into an account. + + Parameters + ---------- + evm : + The current EVM frame. + " in + let _ := M.assign_local (| + "gas" , + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "to" , + M.call (| + M.get_name (| globals, "to_address" |), + make_list [ + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_input_start_position" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_input_size" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_output_start_position" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_output_size" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "extend_memory" , + M.call (| + M.get_name (| globals, "calculate_gas_extend_memory" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "memory" |); + make_list [ + make_tuple [ M.get_name (| globals, "memory_input_start_position" |); M.get_name (| globals, "memory_input_size" |) ]; + make_tuple [ M.get_name (| globals, "memory_output_start_position" |); M.get_name (| globals, "memory_output_size" |) ] + ] + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.in_ (| + M.get_name (| globals, "to" |), + M.get_field (| M.get_name (| globals, "evm" |), "accessed_addresses" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "access_gas_cost" , + M.get_name (| globals, "GAS_WARM_ACCESS" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "accessed_addresses" |), "add" |), + make_list [ + M.get_name (| globals, "to" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "access_gas_cost" , + M.get_name (| globals, "GAS_COLD_ACCOUNT_ACCESS" |) + |) in + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "message_call_gas" , + M.call (| + M.get_name (| globals, "calculate_message_call_gas" |), + make_list [ + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |); + M.get_name (| globals, "gas" |); + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "gas_left" |) + ], + make_dict [] + |); + M.get_field (| M.get_name (| globals, "extend_memory" |), "cost" |); + M.get_name (| globals, "access_gas_cost" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + BinOp.add (| + M.get_field (| M.get_name (| globals, "message_call_gas" |), "cost" |), + M.get_field (| M.get_name (| globals, "extend_memory" |), "cost" |) + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "memory" |), + BinOp.mult (| + Constant.bytes "00", + M.get_field (| M.get_name (| globals, "extend_memory" |), "expand_by" |) + |) + |) in + let _ := M.call (| + M.get_name (| globals, "generic_call" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_field (| M.get_name (| globals, "message_call_gas" |), "stipend" |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |); + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "current_target" |); + M.get_name (| globals, "to" |); + M.get_name (| globals, "to" |); + Constant.bool true; + Constant.bool true; + M.get_name (| globals, "memory_input_start_position" |); + M.get_name (| globals, "memory_input_size" |); + M.get_name (| globals, "memory_output_start_position" |); + M.get_name (| globals, "memory_output_size" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition revert : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Stop execution and revert state changes, without consuming all provided gas + and also has the ability to return a reason + Parameters + ---------- + evm : + The current EVM frame. + " in + let _ := M.assign_local (| + "memory_start_index" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "size" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "extend_memory" , + M.call (| + M.get_name (| globals, "calculate_gas_extend_memory" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "memory" |); + make_list [ + make_tuple [ M.get_name (| globals, "memory_start_index" |); M.get_name (| globals, "size" |) ] + ] + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_field (| M.get_name (| globals, "extend_memory" |), "cost" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "memory" |), + BinOp.mult (| + Constant.bytes "00", + M.get_field (| M.get_name (| globals, "extend_memory" |), "expand_by" |) + |) + |) in + let _ := M.assign_local (| + "output" , + M.call (| + M.get_name (| globals, "memory_read_bytes" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "memory" |); + M.get_name (| globals, "memory_start_index" |); + M.get_name (| globals, "size" |) + ], + make_dict [] + |) + |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, "evm" |), "output" |), + M.call (| + M.get_name (| globals, "bytes" |), + make_list [ + M.get_name (| globals, "output" |) + ], + make_dict [] + |) + |) in + let _ := M.raise (| Some (M.get_name (| globals, "Revert" |)) |) in + let _ := M.pass (| |) in + M.pure Constant.None_)). diff --git a/CoqOfPython/ethereum/berlin/vm/interpreter.v b/CoqOfPython/ethereum/berlin/vm/interpreter.v new file mode 100644 index 0000000..c0c52ad --- /dev/null +++ b/CoqOfPython/ethereum/berlin/vm/interpreter.v @@ -0,0 +1,673 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.berlin.vm.interpreter". + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) Interpreter +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +A straightforward interpreter that executes EVM code. +". + +Axiom dataclasses_imports_dataclass : + IsImported globals "dataclasses" "dataclass". + +Axiom typing_imports_Iterable : + IsImported globals "typing" "Iterable". +Axiom typing_imports_Optional : + IsImported globals "typing" "Optional". +Axiom typing_imports_Set : + IsImported globals "typing" "Set". +Axiom typing_imports_Tuple : + IsImported globals "typing" "Tuple". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_Bytes0 : + IsImported globals "ethereum.base_types" "Bytes0". +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". + +Axiom ethereum_trace_imports_EvmStop : + IsImported globals "ethereum.trace" "EvmStop". +Axiom ethereum_trace_imports_OpEnd : + IsImported globals "ethereum.trace" "OpEnd". +Axiom ethereum_trace_imports_OpException : + IsImported globals "ethereum.trace" "OpException". +Axiom ethereum_trace_imports_OpStart : + IsImported globals "ethereum.trace" "OpStart". +Axiom ethereum_trace_imports_PrecompileEnd : + IsImported globals "ethereum.trace" "PrecompileEnd". +Axiom ethereum_trace_imports_PrecompileStart : + IsImported globals "ethereum.trace" "PrecompileStart". +Axiom ethereum_trace_imports_TransactionEnd : + IsImported globals "ethereum.trace" "TransactionEnd". +Axiom ethereum_trace_imports_evm_trace : + IsImported globals "ethereum.trace" "evm_trace". + +Axiom ethereum_utils_ensure_imports_ensure : + IsImported globals "ethereum.utils.ensure" "ensure". + +Axiom ethereum_berlin_blocks_imports_Log : + IsImported globals "ethereum.berlin.blocks" "Log". + +Axiom ethereum_berlin_fork_types_imports_Address : + IsImported globals "ethereum.berlin.fork_types" "Address". + +Axiom ethereum_berlin_state_imports_account_exists_and_is_empty : + IsImported globals "ethereum.berlin.state" "account_exists_and_is_empty". +Axiom ethereum_berlin_state_imports_account_has_code_or_nonce : + IsImported globals "ethereum.berlin.state" "account_has_code_or_nonce". +Axiom ethereum_berlin_state_imports_begin_transaction : + IsImported globals "ethereum.berlin.state" "begin_transaction". +Axiom ethereum_berlin_state_imports_commit_transaction : + IsImported globals "ethereum.berlin.state" "commit_transaction". +Axiom ethereum_berlin_state_imports_destroy_storage : + IsImported globals "ethereum.berlin.state" "destroy_storage". +Axiom ethereum_berlin_state_imports_increment_nonce : + IsImported globals "ethereum.berlin.state" "increment_nonce". +Axiom ethereum_berlin_state_imports_mark_account_created : + IsImported globals "ethereum.berlin.state" "mark_account_created". +Axiom ethereum_berlin_state_imports_move_ether : + IsImported globals "ethereum.berlin.state" "move_ether". +Axiom ethereum_berlin_state_imports_rollback_transaction : + IsImported globals "ethereum.berlin.state" "rollback_transaction". +Axiom ethereum_berlin_state_imports_set_code : + IsImported globals "ethereum.berlin.state" "set_code". +Axiom ethereum_berlin_state_imports_touch_account : + IsImported globals "ethereum.berlin.state" "touch_account". + +Axiom ethereum_berlin_vm_imports_Message : + IsImported globals "ethereum.berlin.vm" "Message". + +Axiom ethereum_berlin_vm_gas_imports_GAS_CODE_DEPOSIT : + IsImported globals "ethereum.berlin.vm.gas" "GAS_CODE_DEPOSIT". +Axiom ethereum_berlin_vm_gas_imports_charge_gas : + IsImported globals "ethereum.berlin.vm.gas" "charge_gas". + +Axiom ethereum_berlin_vm_precompiled_contracts_mapping_imports_PRE_COMPILED_CONTRACTS : + IsImported globals "ethereum.berlin.vm.precompiled_contracts.mapping" "PRE_COMPILED_CONTRACTS". + +Axiom ethereum_berlin_vm_imports_Environment : + IsImported globals "ethereum.berlin.vm" "Environment". +Axiom ethereum_berlin_vm_imports_Evm : + IsImported globals "ethereum.berlin.vm" "Evm". + +Axiom ethereum_berlin_vm_exceptions_imports_AddressCollision : + IsImported globals "ethereum.berlin.vm.exceptions" "AddressCollision". +Axiom ethereum_berlin_vm_exceptions_imports_ExceptionalHalt : + IsImported globals "ethereum.berlin.vm.exceptions" "ExceptionalHalt". +Axiom ethereum_berlin_vm_exceptions_imports_InvalidOpcode : + IsImported globals "ethereum.berlin.vm.exceptions" "InvalidOpcode". +Axiom ethereum_berlin_vm_exceptions_imports_OutOfGasError : + IsImported globals "ethereum.berlin.vm.exceptions" "OutOfGasError". +Axiom ethereum_berlin_vm_exceptions_imports_Revert : + IsImported globals "ethereum.berlin.vm.exceptions" "Revert". +Axiom ethereum_berlin_vm_exceptions_imports_StackDepthLimitError : + IsImported globals "ethereum.berlin.vm.exceptions" "StackDepthLimitError". + +Axiom ethereum_berlin_vm_instructions_imports_Ops : + IsImported globals "ethereum.berlin.vm.instructions" "Ops". +Axiom ethereum_berlin_vm_instructions_imports_op_implementation : + IsImported globals "ethereum.berlin.vm.instructions" "op_implementation". + +Axiom ethereum_berlin_vm_runtime_imports_get_valid_jump_destinations : + IsImported globals "ethereum.berlin.vm.runtime" "get_valid_jump_destinations". + +Definition STACK_DEPTH_LIMIT : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 1024 + ], + make_dict [] + |) +)). + +Definition MAX_CODE_SIZE : Value.t := M.run ltac:(M.monadic ( + Constant.int 24576 +)). + +Definition MessageCallOutput : Value.t := + builtins.make_klass + [] + [ + + ] + [ + + ]. + +Definition process_message_call : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "message"; "env" ] |) in + let _ := Constant.str " + If `message.current` is empty then it creates a smart contract + else it executes a call from the `message.caller` to the `message.target`. + + Parameters + ---------- + message : + Transaction specific items. + + env : + External items required for EVM execution. + + Returns + ------- + output : `MessageCallOutput` + Output of the message call + " in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_field (| M.get_name (| globals, "message" |), "target" |), + M.call (| + M.get_name (| globals, "Bytes0" |), + make_list [ + Constant.bytes "" + ], + make_dict [] + |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "is_collision" , + M.call (| + M.get_name (| globals, "account_has_code_or_nonce" |), + make_list [ + M.get_field (| M.get_name (| globals, "env" |), "state" |); + M.get_field (| M.get_name (| globals, "message" |), "current_target" |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + M.get_name (| globals, "is_collision" |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + M.call (| + M.get_name (| globals, "MessageCallOutput" |), + make_list [ + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |); + M.call (| + M.get_name (| globals, "tuple" |), + make_list [], + make_dict [] + |); + M.call (| + M.get_name (| globals, "set" |), + make_list [], + make_dict [] + |); + M.call (| + M.get_name (| globals, "set" |), + make_list [], + make_dict [] + |); + M.call (| + M.get_name (| globals, "AddressCollision" |), + make_list [], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "evm" , + M.call (| + M.get_name (| globals, "process_create_message" |), + make_list [ + M.get_name (| globals, "message" |); + M.get_name (| globals, "env" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "evm" , + M.call (| + M.get_name (| globals, "process_message" |), + make_list [ + M.get_name (| globals, "message" |); + M.get_name (| globals, "env" |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, "account_exists_and_is_empty" |), + make_list [ + M.get_field (| M.get_name (| globals, "env" |), "state" |); + M.call (| + M.get_name (| globals, "Address" |), + make_list [ + M.get_field (| M.get_name (| globals, "message" |), "target" |) + ], + make_dict [] + |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "touched_accounts" |), "add" |), + make_list [ + M.call (| + M.get_name (| globals, "Address" |), + make_list [ + M.get_field (| M.get_name (| globals, "message" |), "target" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + M.get_field (| M.get_name (| globals, "evm" |), "error" |), + (* then *) + ltac:(M.monadic ( +(* At stmt: unsupported node type: AnnAssign *) + let _ := M.assign_local (| + "accounts_to_delete" , + M.call (| + M.get_name (| globals, "set" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "touched_accounts" , + M.call (| + M.get_name (| globals, "set" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "refund_counter" , + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "logs" , + M.get_field (| M.get_name (| globals, "evm" |), "logs" |) + |) in + let _ := M.assign_local (| + "accounts_to_delete" , + M.get_field (| M.get_name (| globals, "evm" |), "accounts_to_delete" |) + |) in + let _ := M.assign_local (| + "touched_accounts" , + M.get_field (| M.get_name (| globals, "evm" |), "touched_accounts" |) + |) in + let _ := M.assign_local (| + "refund_counter" , + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "refund_counter" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "tx_end" , + M.call (| + M.get_name (| globals, "TransactionEnd" |), + make_list [ + BinOp.sub (| + M.get_field (| M.get_name (| globals, "message" |), "gas" |), + M.get_field (| M.get_name (| globals, "evm" |), "gas_left" |) + |); + M.get_field (| M.get_name (| globals, "evm" |), "output" |); + M.get_field (| M.get_name (| globals, "evm" |), "error" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "evm_trace" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "tx_end" |) + ], + make_dict [] + |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, "MessageCallOutput" |), + make_list [], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Definition process_create_message : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "message"; "env" ] |) in + let _ := Constant.str " + Executes a call to create a smart contract. + + Parameters + ---------- + message : + Transaction specific items. + env : + External items required for EVM execution. + + Returns + ------- + evm: :py:class:`~ethereum.berlin.vm.Evm` + Items containing execution specific objects. + " in + let _ := M.call (| + M.get_name (| globals, "begin_transaction" |), + make_list [ + M.get_field (| M.get_name (| globals, "env" |), "state" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "destroy_storage" |), + make_list [ + M.get_field (| M.get_name (| globals, "env" |), "state" |); + M.get_field (| M.get_name (| globals, "message" |), "current_target" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "mark_account_created" |), + make_list [ + M.get_field (| M.get_name (| globals, "env" |), "state" |); + M.get_field (| M.get_name (| globals, "message" |), "current_target" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "increment_nonce" |), + make_list [ + M.get_field (| M.get_name (| globals, "env" |), "state" |); + M.get_field (| M.get_name (| globals, "message" |), "current_target" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "evm" , + M.call (| + M.get_name (| globals, "process_message" |), + make_list [ + M.get_name (| globals, "message" |); + M.get_name (| globals, "env" |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + UnOp.not (| M.get_field (| M.get_name (| globals, "evm" |), "error" |) |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "contract_code" , + M.get_field (| M.get_name (| globals, "evm" |), "output" |) + |) in + let _ := M.assign_local (| + "contract_code_gas" , + BinOp.mult (| + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_name (| globals, "contract_code" |) + ], + make_dict [] + |), + M.get_name (| globals, "GAS_CODE_DEPOSIT" |) + |) + |) in +(* At stmt: unsupported node type: Try *) + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, "rollback_transaction" |), + make_list [ + M.get_field (| M.get_name (| globals, "env" |), "state" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + )) |) in + let _ := M.return_ (| + M.get_name (| globals, "evm" |) + |) in + M.pure Constant.None_)). + +Definition process_message : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "message"; "env" ] |) in + let _ := Constant.str " + Executes a call to create a smart contract. + + Parameters + ---------- + message : + Transaction specific items. + env : + External items required for EVM execution. + + Returns + ------- + evm: :py:class:`~ethereum.berlin.vm.Evm` + Items containing execution specific objects + " in + let _ := + (* if *) + M.if_then_else (| + Compare.gt (| + M.get_field (| M.get_name (| globals, "message" |), "depth" |), + M.get_name (| globals, "STACK_DEPTH_LIMIT" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.call (| + M.get_name (| globals, "StackDepthLimitError" |), + make_list [ + Constant.str "Stack depth limit reached" + ], + make_dict [] + |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.call (| + M.get_name (| globals, "begin_transaction" |), + make_list [ + M.get_field (| M.get_name (| globals, "env" |), "state" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "touch_account" |), + make_list [ + M.get_field (| M.get_name (| globals, "env" |), "state" |); + M.get_field (| M.get_name (| globals, "message" |), "current_target" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + BoolOp.and (| + M.get_field (| M.get_name (| globals, "message" |), "should_transfer_value" |), + ltac:(M.monadic ( + Compare.not_eq (| + M.get_field (| M.get_name (| globals, "message" |), "value" |), + Constant.int 0 + |) + )) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, "move_ether" |), + make_list [ + M.get_field (| M.get_name (| globals, "env" |), "state" |); + M.get_field (| M.get_name (| globals, "message" |), "caller" |); + M.get_field (| M.get_name (| globals, "message" |), "current_target" |); + M.get_field (| M.get_name (| globals, "message" |), "value" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "evm" , + M.call (| + M.get_name (| globals, "execute_code" |), + make_list [ + M.get_name (| globals, "message" |); + M.get_name (| globals, "env" |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + M.get_field (| M.get_name (| globals, "evm" |), "error" |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, "rollback_transaction" |), + make_list [ + M.get_field (| M.get_name (| globals, "env" |), "state" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, "commit_transaction" |), + make_list [ + M.get_field (| M.get_name (| globals, "env" |), "state" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + )) |) in + let _ := M.return_ (| + M.get_name (| globals, "evm" |) + |) in + M.pure Constant.None_)). + +Definition execute_code : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "message"; "env" ] |) in + let _ := Constant.str " + Executes bytecode present in the `message`. + + Parameters + ---------- + message : + Transaction specific items. + env : + External items required for EVM execution. + + Returns + ------- + evm: `ethereum.vm.EVM` + Items containing execution specific objects + " in + let _ := M.assign_local (| + "code" , + M.get_field (| M.get_name (| globals, "message" |), "code" |) + |) in + let _ := M.assign_local (| + "valid_jump_destinations" , + M.call (| + M.get_name (| globals, "get_valid_jump_destinations" |), + make_list [ + M.get_name (| globals, "code" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "evm" , + M.call (| + M.get_name (| globals, "Evm" |), + make_list [], + make_dict [] + |) + |) in +(* At stmt: unsupported node type: Try *) + let _ := M.return_ (| + M.get_name (| globals, "evm" |) + |) in + M.pure Constant.None_)). diff --git a/CoqOfPython/ethereum/berlin/vm/memory.v b/CoqOfPython/ethereum/berlin/vm/memory.v new file mode 100644 index 0000000..62e26d1 --- /dev/null +++ b/CoqOfPython/ethereum/berlin/vm/memory.v @@ -0,0 +1,166 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.berlin.vm.memory". + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) Memory +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +EVM memory operations. +". + +Axiom ethereum_utils_byte_imports_right_pad_zero_bytes : + IsImported globals "ethereum.utils.byte" "right_pad_zero_bytes". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_Bytes : + IsImported globals "ethereum.base_types" "Bytes". +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". + +Definition memory_write : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "memory"; "start_position"; "value" ] |) in + let _ := Constant.str " + Writes to memory. + + Parameters + ---------- + memory : + Memory contents of the EVM. + start_position : + Starting pointer to the memory. + value : + Data to write to memory. + " in + let _ := M.assign (| + M.slice (| + M.get_name (| globals, "memory" |), + M.get_name (| globals, "start_position" |), + BinOp.add (| + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.get_name (| globals, "start_position" |) + ], + make_dict [] + |), + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_name (| globals, "value" |) + ], + make_dict [] + |) + |), + Constant.None_ + |), + M.get_name (| globals, "value" |) + |) in + M.pure Constant.None_)). + +Definition memory_read_bytes : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "memory"; "start_position"; "size" ] |) in + let _ := Constant.str " + Read bytes from memory. + + Parameters + ---------- + memory : + Memory contents of the EVM. + start_position : + Starting pointer to the memory. + size : + Size of the data that needs to be read from `start_position`. + + Returns + ------- + data_bytes : + Data read from memory. + " in + let _ := M.return_ (| + M.slice (| + M.get_name (| globals, "memory" |), + M.get_name (| globals, "start_position" |), + BinOp.add (| + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.get_name (| globals, "start_position" |) + ], + make_dict [] + |), + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.get_name (| globals, "size" |) + ], + make_dict [] + |) + |), + Constant.None_ + |) + |) in + M.pure Constant.None_)). + +Definition buffer_read : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "buffer"; "start_position"; "size" ] |) in + let _ := Constant.str " + Read bytes from a buffer. Padding with zeros if necessary. + + Parameters + ---------- + buffer : + Memory contents of the EVM. + start_position : + Starting pointer to the memory. + size : + Size of the data that needs to be read from `start_position`. + + Returns + ------- + data_bytes : + Data read from memory. + " in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, "right_pad_zero_bytes" |), + make_list [ + M.slice (| + M.get_name (| globals, "buffer" |), + M.get_name (| globals, "start_position" |), + BinOp.add (| + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.get_name (| globals, "start_position" |) + ], + make_dict [] + |), + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.get_name (| globals, "size" |) + ], + make_dict [] + |) + |), + Constant.None_ + |); + M.get_name (| globals, "size" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). diff --git a/CoqOfPython/ethereum/berlin/vm/precompiled_contracts/__init__.v b/CoqOfPython/ethereum/berlin/vm/precompiled_contracts/__init__.v new file mode 100644 index 0000000..311a52a --- /dev/null +++ b/CoqOfPython/ethereum/berlin/vm/precompiled_contracts/__init__.v @@ -0,0 +1,116 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.berlin.vm.precompiled_contracts.__init__". + +Definition expr_1 : Value.t := + Constant.str " +Precompiled Contract Addresses +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Addresses of precompiled contracts and mappings to their +implementations. +". + +Axiom ethereum_berlin_utils_hexadecimal_imports_hex_to_address : + IsImported globals "ethereum.berlin.utils.hexadecimal" "hex_to_address". + +Definition __all__ : Value.t := M.run ltac:(M.monadic ( + make_tuple [ Constant.str "ECRECOVER_ADDRESS"; Constant.str "SHA256_ADDRESS"; Constant.str "RIPEMD160_ADDRESS"; Constant.str "IDENTITY_ADDRESS"; Constant.str "MODEXP_ADDRESS"; Constant.str "ALT_BN128_ADD_ADDRESS"; Constant.str "ALT_BN128_MUL_ADDRESS"; Constant.str "ALT_BN128_PAIRING_CHECK_ADDRESS"; Constant.str "BLAKE2F_ADDRESS" ] +)). + +Definition ECRECOVER_ADDRESS : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "hex_to_address" |), + make_list [ + Constant.str "0x01" + ], + make_dict [] + |) +)). + +Definition SHA256_ADDRESS : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "hex_to_address" |), + make_list [ + Constant.str "0x02" + ], + make_dict [] + |) +)). + +Definition RIPEMD160_ADDRESS : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "hex_to_address" |), + make_list [ + Constant.str "0x03" + ], + make_dict [] + |) +)). + +Definition IDENTITY_ADDRESS : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "hex_to_address" |), + make_list [ + Constant.str "0x04" + ], + make_dict [] + |) +)). + +Definition MODEXP_ADDRESS : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "hex_to_address" |), + make_list [ + Constant.str "0x05" + ], + make_dict [] + |) +)). + +Definition ALT_BN128_ADD_ADDRESS : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "hex_to_address" |), + make_list [ + Constant.str "0x06" + ], + make_dict [] + |) +)). + +Definition ALT_BN128_MUL_ADDRESS : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "hex_to_address" |), + make_list [ + Constant.str "0x07" + ], + make_dict [] + |) +)). + +Definition ALT_BN128_PAIRING_CHECK_ADDRESS : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "hex_to_address" |), + make_list [ + Constant.str "0x08" + ], + make_dict [] + |) +)). + +Definition BLAKE2F_ADDRESS : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "hex_to_address" |), + make_list [ + Constant.str "0x09" + ], + make_dict [] + |) +)). diff --git a/CoqOfPython/ethereum/berlin/vm/precompiled_contracts/alt_bn128.v b/CoqOfPython/ethereum/berlin/vm/precompiled_contracts/alt_bn128.v new file mode 100644 index 0000000..8bfbd17 --- /dev/null +++ b/CoqOfPython/ethereum/berlin/vm/precompiled_contracts/alt_bn128.v @@ -0,0 +1,778 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.berlin.vm.precompiled_contracts.alt_bn128". + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) ALT_BN128 CONTRACTS +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementation of the ALT_BN128 precompiled contracts. +". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". + +Axiom ethereum_crypto_alt_bn128_imports_ALT_BN128_CURVE_ORDER : + IsImported globals "ethereum.crypto.alt_bn128" "ALT_BN128_CURVE_ORDER". +Axiom ethereum_crypto_alt_bn128_imports_ALT_BN128_PRIME : + IsImported globals "ethereum.crypto.alt_bn128" "ALT_BN128_PRIME". +Axiom ethereum_crypto_alt_bn128_imports_BNF : + IsImported globals "ethereum.crypto.alt_bn128" "BNF". +Axiom ethereum_crypto_alt_bn128_imports_BNF2 : + IsImported globals "ethereum.crypto.alt_bn128" "BNF2". +Axiom ethereum_crypto_alt_bn128_imports_BNF12 : + IsImported globals "ethereum.crypto.alt_bn128" "BNF12". +Axiom ethereum_crypto_alt_bn128_imports_BNP : + IsImported globals "ethereum.crypto.alt_bn128" "BNP". +Axiom ethereum_crypto_alt_bn128_imports_BNP2 : + IsImported globals "ethereum.crypto.alt_bn128" "BNP2". +Axiom ethereum_crypto_alt_bn128_imports_pairing : + IsImported globals "ethereum.crypto.alt_bn128" "pairing". + +Axiom ethereum_utils_ensure_imports_ensure : + IsImported globals "ethereum.utils.ensure" "ensure". + +Axiom ethereum_berlin_vm_imports_Evm : + IsImported globals "ethereum.berlin.vm" "Evm". + +Axiom ethereum_berlin_vm_gas_imports_charge_gas : + IsImported globals "ethereum.berlin.vm.gas" "charge_gas". + +Axiom ethereum_berlin_vm_memory_imports_buffer_read : + IsImported globals "ethereum.berlin.vm.memory" "buffer_read". + +Axiom ethereum_berlin_vm_exceptions_imports_OutOfGasError : + IsImported globals "ethereum.berlin.vm.exceptions" "OutOfGasError". + +Definition alt_bn128_add : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + The ALT_BN128 addition precompiled contract. + + Parameters + ---------- + evm : + The current EVM frame. + " in + let _ := M.assign_local (| + "data" , + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "data" |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 150 + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "x0_bytes" , + M.call (| + M.get_name (| globals, "buffer_read" |), + make_list [ + M.get_name (| globals, "data" |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 32 + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "x0_value" , + M.call (| + M.get_field (| M.get_name (| globals, "U256" |), "from_be_bytes" |), + make_list [ + M.get_name (| globals, "x0_bytes" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "y0_bytes" , + M.call (| + M.get_name (| globals, "buffer_read" |), + make_list [ + M.get_name (| globals, "data" |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 32 + ], + make_dict [] + |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 32 + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "y0_value" , + M.call (| + M.get_field (| M.get_name (| globals, "U256" |), "from_be_bytes" |), + make_list [ + M.get_name (| globals, "y0_bytes" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "x1_bytes" , + M.call (| + M.get_name (| globals, "buffer_read" |), + make_list [ + M.get_name (| globals, "data" |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 64 + ], + make_dict [] + |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 32 + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "x1_value" , + M.call (| + M.get_field (| M.get_name (| globals, "U256" |), "from_be_bytes" |), + make_list [ + M.get_name (| globals, "x1_bytes" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "y1_bytes" , + M.call (| + M.get_name (| globals, "buffer_read" |), + make_list [ + M.get_name (| globals, "data" |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 96 + ], + make_dict [] + |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 32 + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "y1_value" , + M.call (| + M.get_field (| M.get_name (| globals, "U256" |), "from_be_bytes" |), + make_list [ + M.get_name (| globals, "y1_bytes" |) + ], + make_dict [] + |) + |) in + let _ := + M.for_ (| + M.get_name (| globals, "i" |), + make_tuple [ M.get_name (| globals, "x0_value" |); M.get_name (| globals, "y0_value" |); M.get_name (| globals, "x1_value" |); M.get_name (| globals, "y1_value" |) ], + ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + Compare.gt_e (| + M.get_name (| globals, "i" |), + M.get_name (| globals, "ALT_BN128_PRIME" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, "OutOfGasError" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in +(* At stmt: unsupported node type: Try *) + let _ := M.assign_local (| + "p" , + BinOp.add (| + M.get_name (| globals, "p0" |), + M.get_name (| globals, "p1" |) + |) + |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, "evm" |), "output" |), + BinOp.add (| + M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, "p" |), "x" |), "to_be_bytes32" |), + make_list [], + make_dict [] + |), + M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, "p" |), "y" |), "to_be_bytes32" |), + make_list [], + make_dict [] + |) + |) + |) in + M.pure Constant.None_)). + +Definition alt_bn128_mul : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + The ALT_BN128 multiplication precompiled contract. + + Parameters + ---------- + evm : + The current EVM frame. + " in + let _ := M.assign_local (| + "data" , + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "data" |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 6000 + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "x0_bytes" , + M.call (| + M.get_name (| globals, "buffer_read" |), + make_list [ + M.get_name (| globals, "data" |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 32 + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "x0_value" , + M.call (| + M.get_field (| M.get_name (| globals, "U256" |), "from_be_bytes" |), + make_list [ + M.get_name (| globals, "x0_bytes" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "y0_bytes" , + M.call (| + M.get_name (| globals, "buffer_read" |), + make_list [ + M.get_name (| globals, "data" |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 32 + ], + make_dict [] + |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 32 + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "y0_value" , + M.call (| + M.get_field (| M.get_name (| globals, "U256" |), "from_be_bytes" |), + make_list [ + M.get_name (| globals, "y0_bytes" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "n" , + M.call (| + M.get_field (| M.get_name (| globals, "U256" |), "from_be_bytes" |), + make_list [ + M.call (| + M.get_name (| globals, "buffer_read" |), + make_list [ + M.get_name (| globals, "data" |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 64 + ], + make_dict [] + |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 32 + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := + M.for_ (| + M.get_name (| globals, "i" |), + make_tuple [ M.get_name (| globals, "x0_value" |); M.get_name (| globals, "y0_value" |) ], + ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + Compare.gt_e (| + M.get_name (| globals, "i" |), + M.get_name (| globals, "ALT_BN128_PRIME" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, "OutOfGasError" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in +(* At stmt: unsupported node type: Try *) + let _ := M.assign_local (| + "p" , + M.call (| + M.get_field (| M.get_name (| globals, "p0" |), "mul_by" |), + make_list [ + M.get_name (| globals, "n" |) + ], + make_dict [] + |) + |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, "evm" |), "output" |), + BinOp.add (| + M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, "p" |), "x" |), "to_be_bytes32" |), + make_list [], + make_dict [] + |), + M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, "p" |), "y" |), "to_be_bytes32" |), + make_list [], + make_dict [] + |) + |) + |) in + M.pure Constant.None_)). + +Definition alt_bn128_pairing_check : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + The ALT_BN128 pairing check precompiled contract. + + Parameters + ---------- + evm : + The current EVM frame. + " in + let _ := M.assign_local (| + "data" , + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "data" |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + BinOp.add (| + BinOp.mult (| + Constant.int 34000, + BinOp.floor_div (| + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_name (| globals, "data" |) + ], + make_dict [] + |), + Constant.int 192 + |) + |), + Constant.int 45000 + |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.not_eq (| + BinOp.mod_ (| + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_name (| globals, "data" |) + ], + make_dict [] + |), + Constant.int 192 + |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, "OutOfGasError" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "result" , + M.call (| + M.get_field (| M.get_name (| globals, "BNF12" |), "from_int" |), + make_list [ + Constant.int 1 + ], + make_dict [] + |) + |) in + let _ := + M.for_ (| + M.get_name (| globals, "i" |), + M.call (| + M.get_name (| globals, "range" |), + make_list [ + BinOp.floor_div (| + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_name (| globals, "data" |) + ], + make_dict [] + |), + Constant.int 192 + |) + ], + make_dict [] + |), + ltac:(M.monadic ( + let _ := M.assign_local (| + "values" , + make_list [] + |) in + let _ := + M.for_ (| + M.get_name (| globals, "j" |), + M.call (| + M.get_name (| globals, "range" |), + make_list [ + Constant.int 6 + ], + make_dict [] + |), + ltac:(M.monadic ( + let _ := M.assign_local (| + "value" , + M.call (| + M.get_field (| M.get_name (| globals, "U256" |), "from_be_bytes" |), + make_list [ + M.slice (| + M.get_name (| globals, "data" |), + BinOp.add (| + BinOp.mult (| + M.get_name (| globals, "i" |), + Constant.int 192 + |), + BinOp.mult (| + Constant.int 32, + M.get_name (| globals, "j" |) + |) + |), + BinOp.add (| + BinOp.mult (| + M.get_name (| globals, "i" |), + Constant.int 192 + |), + BinOp.mult (| + Constant.int 32, + BinOp.add (| + M.get_name (| globals, "j" |), + Constant.int 1 + |) + |) + |), + Constant.None_ + |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.gt_e (| + M.get_name (| globals, "value" |), + M.get_name (| globals, "ALT_BN128_PRIME" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, "OutOfGasError" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.call (| + M.get_field (| M.get_name (| globals, "values" |), "append" |), + make_list [ + M.call (| + M.get_name (| globals, "int" |), + make_list [ + M.get_name (| globals, "value" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in +(* At stmt: unsupported node type: Try *) + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + Compare.eq (| + M.call (| + M.get_field (| M.get_name (| globals, "p" |), "mul_by" |), + make_list [ + M.get_name (| globals, "ALT_BN128_CURVE_ORDER" |) + ], + make_dict [] + |), + M.call (| + M.get_field (| M.get_name (| globals, "BNP" |), "point_at_infinity" |), + make_list [], + make_dict [] + |) + |); + M.get_name (| globals, "OutOfGasError" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + Compare.eq (| + M.call (| + M.get_field (| M.get_name (| globals, "q" |), "mul_by" |), + make_list [ + M.get_name (| globals, "ALT_BN128_CURVE_ORDER" |) + ], + make_dict [] + |), + M.call (| + M.get_field (| M.get_name (| globals, "BNP2" |), "point_at_infinity" |), + make_list [], + make_dict [] + |) + |); + M.get_name (| globals, "OutOfGasError" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + BoolOp.and (| + Compare.not_eq (| + M.get_name (| globals, "p" |), + M.call (| + M.get_field (| M.get_name (| globals, "BNP" |), "point_at_infinity" |), + make_list [], + make_dict [] + |) + |), + ltac:(M.monadic ( + Compare.not_eq (| + M.get_name (| globals, "q" |), + M.call (| + M.get_field (| M.get_name (| globals, "BNP2" |), "point_at_infinity" |), + make_list [], + make_dict [] + |) + |) + )) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "result" , + BinOp.mult (| + M.get_name (| globals, "result" |), + M.call (| + M.get_name (| globals, "pairing" |), + make_list [ + M.get_name (| globals, "q" |); + M.get_name (| globals, "p" |) + ], + make_dict [] + |) + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, "result" |), + M.call (| + M.get_field (| M.get_name (| globals, "BNF12" |), "from_int" |), + make_list [ + Constant.int 1 + ], + make_dict [] + |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign (| + M.get_field (| M.get_name (| globals, "evm" |), "output" |), + M.call (| + M.get_field (| M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 1 + ], + make_dict [] + |), "to_be_bytes32" |), + make_list [], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign (| + M.get_field (| M.get_name (| globals, "evm" |), "output" |), + M.call (| + M.get_field (| M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |), "to_be_bytes32" |), + make_list [], + make_dict [] + |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_)). diff --git a/CoqOfPython/ethereum/berlin/vm/precompiled_contracts/blake2f.v b/CoqOfPython/ethereum/berlin/vm/precompiled_contracts/blake2f.v new file mode 100644 index 0000000..5afc3b4 --- /dev/null +++ b/CoqOfPython/ethereum/berlin/vm/precompiled_contracts/blake2f.v @@ -0,0 +1,127 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.berlin.vm.precompiled_contracts.blake2f". + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) Blake2 PRECOMPILED CONTRACT +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementation of the `Blake2` precompiled contract. +". + +Axiom ethereum_crypto_blake2_imports_Blake2b : + IsImported globals "ethereum.crypto.blake2" "Blake2b". + +Axiom ethereum_utils_ensure_imports_ensure : + IsImported globals "ethereum.utils.ensure" "ensure". + +Axiom ethereum_berlin_vm_imports_Evm : + IsImported globals "ethereum.berlin.vm" "Evm". + +Axiom ethereum_berlin_vm_gas_imports_GAS_BLAKE2_PER_ROUND : + IsImported globals "ethereum.berlin.vm.gas" "GAS_BLAKE2_PER_ROUND". +Axiom ethereum_berlin_vm_gas_imports_charge_gas : + IsImported globals "ethereum.berlin.vm.gas" "charge_gas". + +Axiom ethereum_berlin_vm_exceptions_imports_InvalidParameter : + IsImported globals "ethereum.berlin.vm.exceptions" "InvalidParameter". + +Definition blake2f : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Writes the Blake2 hash to output. + + Parameters + ---------- + evm : + The current EVM frame. + " in + let _ := M.assign_local (| + "data" , + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "data" |) + |) in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + Compare.eq (| + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_name (| globals, "data" |) + ], + make_dict [] + |), + Constant.int 213 + |); + M.get_name (| globals, "InvalidParameter" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "blake2b" , + M.call (| + M.get_name (| globals, "Blake2b" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.assign (| + make_tuple [ M.get_name (| globals, "rounds" |); M.get_name (| globals, "h" |); M.get_name (| globals, "m" |); M.get_name (| globals, "t_0" |); M.get_name (| globals, "t_1" |); M.get_name (| globals, "f" |) ], + M.call (| + M.get_field (| M.get_name (| globals, "blake2b" |), "get_blake2_parameters" |), + make_list [ + M.get_name (| globals, "data" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + BinOp.mult (| + M.get_name (| globals, "GAS_BLAKE2_PER_ROUND" |), + M.get_name (| globals, "rounds" |) + |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + Compare.in_ (| + M.get_name (| globals, "f" |), + make_list [ + Constant.int 0; + Constant.int 1 + ] + |); + M.get_name (| globals, "InvalidParameter" |) + ], + make_dict [] + |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, "evm" |), "output" |), + M.call (| + M.get_field (| M.get_name (| globals, "blake2b" |), "compress" |), + make_list [ + M.get_name (| globals, "rounds" |); + M.get_name (| globals, "h" |); + M.get_name (| globals, "m" |); + M.get_name (| globals, "t_0" |); + M.get_name (| globals, "t_1" |); + M.get_name (| globals, "f" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). diff --git a/CoqOfPython/ethereum/berlin/vm/precompiled_contracts/ecrecover.v b/CoqOfPython/ethereum/berlin/vm/precompiled_contracts/ecrecover.v new file mode 100644 index 0000000..9c5863b --- /dev/null +++ b/CoqOfPython/ethereum/berlin/vm/precompiled_contracts/ecrecover.v @@ -0,0 +1,301 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.berlin.vm.precompiled_contracts.ecrecover". + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) ECRECOVER PRECOMPILED CONTRACT +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementation of the ECRECOVER precompiled contract. +". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". + +Axiom ethereum_crypto_elliptic_curve_imports_SECP256K1N : + IsImported globals "ethereum.crypto.elliptic_curve" "SECP256K1N". +Axiom ethereum_crypto_elliptic_curve_imports_secp256k1_recover : + IsImported globals "ethereum.crypto.elliptic_curve" "secp256k1_recover". + +Axiom ethereum_crypto_hash_imports_Hash32 : + IsImported globals "ethereum.crypto.hash" "Hash32". +Axiom ethereum_crypto_hash_imports_keccak256 : + IsImported globals "ethereum.crypto.hash" "keccak256". + +Axiom ethereum_utils_byte_imports_left_pad_zero_bytes : + IsImported globals "ethereum.utils.byte" "left_pad_zero_bytes". + +Axiom ethereum_berlin_vm_imports_Evm : + IsImported globals "ethereum.berlin.vm" "Evm". + +Axiom ethereum_berlin_vm_gas_imports_GAS_ECRECOVER : + IsImported globals "ethereum.berlin.vm.gas" "GAS_ECRECOVER". +Axiom ethereum_berlin_vm_gas_imports_charge_gas : + IsImported globals "ethereum.berlin.vm.gas" "charge_gas". + +Axiom ethereum_berlin_vm_memory_imports_buffer_read : + IsImported globals "ethereum.berlin.vm.memory" "buffer_read". + +Definition ecrecover : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Decrypts the address using elliptic curve DSA recovery mechanism and writes + the address to output. + + Parameters + ---------- + evm : + The current EVM frame. + " in + let _ := M.assign_local (| + "data" , + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "data" |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_ECRECOVER" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "message_hash_bytes" , + M.call (| + M.get_name (| globals, "buffer_read" |), + make_list [ + M.get_name (| globals, "data" |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 32 + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "message_hash" , + M.call (| + M.get_name (| globals, "Hash32" |), + make_list [ + M.get_name (| globals, "message_hash_bytes" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "v" , + M.call (| + M.get_field (| M.get_name (| globals, "U256" |), "from_be_bytes" |), + make_list [ + M.call (| + M.get_name (| globals, "buffer_read" |), + make_list [ + M.get_name (| globals, "data" |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 32 + ], + make_dict [] + |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 32 + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "r" , + M.call (| + M.get_field (| M.get_name (| globals, "U256" |), "from_be_bytes" |), + make_list [ + M.call (| + M.get_name (| globals, "buffer_read" |), + make_list [ + M.get_name (| globals, "data" |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 64 + ], + make_dict [] + |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 32 + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "s" , + M.call (| + M.get_field (| M.get_name (| globals, "U256" |), "from_be_bytes" |), + make_list [ + M.call (| + M.get_name (| globals, "buffer_read" |), + make_list [ + M.get_name (| globals, "data" |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 96 + ], + make_dict [] + |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 32 + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + BoolOp.and (| + Compare.not_eq (| + M.get_name (| globals, "v" |), + Constant.int 27 + |), + ltac:(M.monadic ( + Compare.not_eq (| + M.get_name (| globals, "v" |), + Constant.int 28 + |) + )) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + Constant.None_ + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + BoolOp.or (| + Compare.gt_e (| + Constant.int 0, + M.get_name (| globals, "r" |) + |), + ltac:(M.monadic ( + Compare.gt_e (| + M.get_name (| globals, "r" |), + M.get_name (| globals, "SECP256K1N" |) + |) + )) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + Constant.None_ + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + BoolOp.or (| + Compare.gt_e (| + Constant.int 0, + M.get_name (| globals, "s" |) + |), + ltac:(M.monadic ( + Compare.gt_e (| + M.get_name (| globals, "s" |), + M.get_name (| globals, "SECP256K1N" |) + |) + )) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + Constant.None_ + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in +(* At stmt: unsupported node type: Try *) + let _ := M.assign_local (| + "address" , + M.slice (| + M.call (| + M.get_name (| globals, "keccak256" |), + make_list [ + M.get_name (| globals, "public_key" |) + ], + make_dict [] + |), + Constant.int 12, + Constant.int 32, + Constant.None_ + |) + |) in + let _ := M.assign_local (| + "padded_address" , + M.call (| + M.get_name (| globals, "left_pad_zero_bytes" |), + make_list [ + M.get_name (| globals, "address" |); + Constant.int 32 + ], + make_dict [] + |) + |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, "evm" |), "output" |), + M.get_name (| globals, "padded_address" |) + |) in + M.pure Constant.None_)). diff --git a/CoqOfPython/ethereum/berlin/vm/precompiled_contracts/identity.v b/CoqOfPython/ethereum/berlin/vm/precompiled_contracts/identity.v new file mode 100644 index 0000000..3663ec2 --- /dev/null +++ b/CoqOfPython/ethereum/berlin/vm/precompiled_contracts/identity.v @@ -0,0 +1,94 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.berlin.vm.precompiled_contracts.identity". + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) IDENTITY PRECOMPILED CONTRACT +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementation of the `IDENTITY` precompiled contract. +". + +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". + +Axiom ethereum_utils_numeric_imports_ceil32 : + IsImported globals "ethereum.utils.numeric" "ceil32". + +Axiom ethereum_berlin_vm_imports_Evm : + IsImported globals "ethereum.berlin.vm" "Evm". + +Axiom ethereum_berlin_vm_gas_imports_GAS_IDENTITY : + IsImported globals "ethereum.berlin.vm.gas" "GAS_IDENTITY". +Axiom ethereum_berlin_vm_gas_imports_GAS_IDENTITY_WORD : + IsImported globals "ethereum.berlin.vm.gas" "GAS_IDENTITY_WORD". +Axiom ethereum_berlin_vm_gas_imports_charge_gas : + IsImported globals "ethereum.berlin.vm.gas" "charge_gas". + +Definition identity : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Writes the message data to output. + + Parameters + ---------- + evm : + The current EVM frame. + " in + let _ := M.assign_local (| + "data" , + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "data" |) + |) in + let _ := M.assign_local (| + "word_count" , + BinOp.floor_div (| + M.call (| + M.get_name (| globals, "ceil32" |), + make_list [ + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_name (| globals, "data" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |), + Constant.int 32 + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + BinOp.add (| + M.get_name (| globals, "GAS_IDENTITY" |), + BinOp.mult (| + M.get_name (| globals, "GAS_IDENTITY_WORD" |), + M.get_name (| globals, "word_count" |) + |) + |) + ], + make_dict [] + |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, "evm" |), "output" |), + M.get_name (| globals, "data" |) + |) in + M.pure Constant.None_)). diff --git a/CoqOfPython/ethereum/berlin/vm/precompiled_contracts/mapping.v b/CoqOfPython/ethereum/berlin/vm/precompiled_contracts/mapping.v new file mode 100644 index 0000000..14f0d14 --- /dev/null +++ b/CoqOfPython/ethereum/berlin/vm/precompiled_contracts/mapping.v @@ -0,0 +1,72 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.berlin.vm.precompiled_contracts.mapping". + +Definition expr_1 : Value.t := + Constant.str " +Precompiled Contract Addresses +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Mapping of precompiled contracts their implementations. +". + +Axiom typing_imports_Callable : + IsImported globals "typing" "Callable". +Axiom typing_imports_Dict : + IsImported globals "typing" "Dict". + +Axiom ethereum_berlin_fork_types_imports_Address : + IsImported globals "ethereum.berlin.fork_types" "Address". + +Axiom ethereum_berlin_vm_precompiled_contracts_imports_ALT_BN128_ADD_ADDRESS : + IsImported globals "ethereum.berlin.vm.precompiled_contracts" "ALT_BN128_ADD_ADDRESS". +Axiom ethereum_berlin_vm_precompiled_contracts_imports_ALT_BN128_MUL_ADDRESS : + IsImported globals "ethereum.berlin.vm.precompiled_contracts" "ALT_BN128_MUL_ADDRESS". +Axiom ethereum_berlin_vm_precompiled_contracts_imports_ALT_BN128_PAIRING_CHECK_ADDRESS : + IsImported globals "ethereum.berlin.vm.precompiled_contracts" "ALT_BN128_PAIRING_CHECK_ADDRESS". +Axiom ethereum_berlin_vm_precompiled_contracts_imports_BLAKE2F_ADDRESS : + IsImported globals "ethereum.berlin.vm.precompiled_contracts" "BLAKE2F_ADDRESS". +Axiom ethereum_berlin_vm_precompiled_contracts_imports_ECRECOVER_ADDRESS : + IsImported globals "ethereum.berlin.vm.precompiled_contracts" "ECRECOVER_ADDRESS". +Axiom ethereum_berlin_vm_precompiled_contracts_imports_IDENTITY_ADDRESS : + IsImported globals "ethereum.berlin.vm.precompiled_contracts" "IDENTITY_ADDRESS". +Axiom ethereum_berlin_vm_precompiled_contracts_imports_MODEXP_ADDRESS : + IsImported globals "ethereum.berlin.vm.precompiled_contracts" "MODEXP_ADDRESS". +Axiom ethereum_berlin_vm_precompiled_contracts_imports_RIPEMD160_ADDRESS : + IsImported globals "ethereum.berlin.vm.precompiled_contracts" "RIPEMD160_ADDRESS". +Axiom ethereum_berlin_vm_precompiled_contracts_imports_SHA256_ADDRESS : + IsImported globals "ethereum.berlin.vm.precompiled_contracts" "SHA256_ADDRESS". + +Axiom ethereum_berlin_vm_precompiled_contracts_alt_bn128_imports_alt_bn128_add : + IsImported globals "ethereum.berlin.vm.precompiled_contracts.alt_bn128" "alt_bn128_add". +Axiom ethereum_berlin_vm_precompiled_contracts_alt_bn128_imports_alt_bn128_mul : + IsImported globals "ethereum.berlin.vm.precompiled_contracts.alt_bn128" "alt_bn128_mul". +Axiom ethereum_berlin_vm_precompiled_contracts_alt_bn128_imports_alt_bn128_pairing_check : + IsImported globals "ethereum.berlin.vm.precompiled_contracts.alt_bn128" "alt_bn128_pairing_check". + +Axiom ethereum_berlin_vm_precompiled_contracts_blake2f_imports_blake2f : + IsImported globals "ethereum.berlin.vm.precompiled_contracts.blake2f" "blake2f". + +Axiom ethereum_berlin_vm_precompiled_contracts_ecrecover_imports_ecrecover : + IsImported globals "ethereum.berlin.vm.precompiled_contracts.ecrecover" "ecrecover". + +Axiom ethereum_berlin_vm_precompiled_contracts_identity_imports_identity : + IsImported globals "ethereum.berlin.vm.precompiled_contracts.identity" "identity". + +Axiom ethereum_berlin_vm_precompiled_contracts_modexp_imports_modexp : + IsImported globals "ethereum.berlin.vm.precompiled_contracts.modexp" "modexp". + +Axiom ethereum_berlin_vm_precompiled_contracts_ripemd160_imports_ripemd160 : + IsImported globals "ethereum.berlin.vm.precompiled_contracts.ripemd160" "ripemd160". + +Axiom ethereum_berlin_vm_precompiled_contracts_sha256_imports_sha256 : + IsImported globals "ethereum.berlin.vm.precompiled_contracts.sha256" "sha256". + +(* At top_level_stmt: unsupported node type: AnnAssign *) diff --git a/CoqOfPython/ethereum/berlin/vm/precompiled_contracts/modexp.v b/CoqOfPython/ethereum/berlin/vm/precompiled_contracts/modexp.v new file mode 100644 index 0000000..aa24c23 --- /dev/null +++ b/CoqOfPython/ethereum/berlin/vm/precompiled_contracts/modexp.v @@ -0,0 +1,676 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.berlin.vm.precompiled_contracts.modexp". + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) MODEXP PRECOMPILED CONTRACT +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementation of the `MODEXP` precompiled contract. +". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_Bytes : + IsImported globals "ethereum.base_types" "Bytes". +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". + +Axiom ethereum_berlin_vm_imports_Evm : + IsImported globals "ethereum.berlin.vm" "Evm". + +Axiom ethereum_berlin_vm_gas_imports_charge_gas : + IsImported globals "ethereum.berlin.vm.gas" "charge_gas". + +Axiom ethereum_berlin_vm_memory_imports_buffer_read : + IsImported globals "ethereum.berlin.vm.memory" "buffer_read". + +Definition GQUADDIVISOR : Value.t := M.run ltac:(M.monadic ( + Constant.int 3 +)). + +Definition modexp : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Calculates `(base**exp) % modulus` for arbitrary sized `base`, `exp` and. + `modulus`. The return value is the same length as the modulus. + " in + let _ := M.assign_local (| + "data" , + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "data" |) + |) in + let _ := M.assign_local (| + "base_length" , + M.call (| + M.get_field (| M.get_name (| globals, "U256" |), "from_be_bytes" |), + make_list [ + M.call (| + M.get_name (| globals, "buffer_read" |), + make_list [ + M.get_name (| globals, "data" |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 32 + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "exp_length" , + M.call (| + M.get_field (| M.get_name (| globals, "U256" |), "from_be_bytes" |), + make_list [ + M.call (| + M.get_name (| globals, "buffer_read" |), + make_list [ + M.get_name (| globals, "data" |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 32 + ], + make_dict [] + |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 32 + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "modulus_length" , + M.call (| + M.get_field (| M.get_name (| globals, "U256" |), "from_be_bytes" |), + make_list [ + M.call (| + M.get_name (| globals, "buffer_read" |), + make_list [ + M.get_name (| globals, "data" |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 64 + ], + make_dict [] + |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 32 + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "exp_start" , + BinOp.add (| + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 96 + ], + make_dict [] + |), + M.get_name (| globals, "base_length" |) + |) + |) in + let _ := M.assign_local (| + "exp_head" , + M.call (| + M.get_field (| M.get_name (| globals, "Uint" |), "from_be_bytes" |), + make_list [ + M.call (| + M.get_name (| globals, "buffer_read" |), + make_list [ + M.get_name (| globals, "data" |); + M.get_name (| globals, "exp_start" |); + M.call (| + M.get_name (| globals, "min" |), + make_list [ + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 32 + ], + make_dict [] + |); + M.get_name (| globals, "exp_length" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.call (| + M.get_name (| globals, "gas_cost" |), + make_list [ + M.get_name (| globals, "base_length" |); + M.get_name (| globals, "modulus_length" |); + M.get_name (| globals, "exp_length" |); + M.get_name (| globals, "exp_head" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + BoolOp.and (| + Compare.eq (| + M.get_name (| globals, "base_length" |), + Constant.int 0 + |), + ltac:(M.monadic ( + Compare.eq (| + M.get_name (| globals, "modulus_length" |), + Constant.int 0 + |) + )) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign (| + M.get_field (| M.get_name (| globals, "evm" |), "output" |), + M.call (| + M.get_name (| globals, "Bytes" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.return_ (| + Constant.None_ + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "base" , + M.call (| + M.get_field (| M.get_name (| globals, "Uint" |), "from_be_bytes" |), + make_list [ + M.call (| + M.get_name (| globals, "buffer_read" |), + make_list [ + M.get_name (| globals, "data" |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 96 + ], + make_dict [] + |); + M.get_name (| globals, "base_length" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "exp" , + M.call (| + M.get_field (| M.get_name (| globals, "Uint" |), "from_be_bytes" |), + make_list [ + M.call (| + M.get_name (| globals, "buffer_read" |), + make_list [ + M.get_name (| globals, "data" |); + M.get_name (| globals, "exp_start" |); + M.get_name (| globals, "exp_length" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "modulus_start" , + BinOp.add (| + M.get_name (| globals, "exp_start" |), + M.get_name (| globals, "exp_length" |) + |) + |) in + let _ := M.assign_local (| + "modulus" , + M.call (| + M.get_field (| M.get_name (| globals, "Uint" |), "from_be_bytes" |), + make_list [ + M.call (| + M.get_name (| globals, "buffer_read" |), + make_list [ + M.get_name (| globals, "data" |); + M.get_name (| globals, "modulus_start" |); + M.get_name (| globals, "modulus_length" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, "modulus" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign (| + M.get_field (| M.get_name (| globals, "evm" |), "output" |), + BinOp.mult (| + M.call (| + M.get_name (| globals, "Bytes" |), + make_list [ + Constant.bytes "00" + ], + make_dict [] + |), + M.get_name (| globals, "modulus_length" |) + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign (| + M.get_field (| M.get_name (| globals, "evm" |), "output" |), + M.call (| + M.get_field (| M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, "pow" |), + make_list [ + M.get_name (| globals, "base" |); + M.get_name (| globals, "exp" |); + M.get_name (| globals, "modulus" |) + ], + make_dict [] + |) + ], + make_dict [] + |), "to_bytes" |), + make_list [ + M.get_name (| globals, "modulus_length" |); + Constant.str "big" + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_)). + +Definition complexity : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "base_length"; "modulus_length" ] |) in + let _ := Constant.str " + Estimate the complexity of performing a modular exponentiation. + + Parameters + ---------- + + base_length : + Length of the array representing the base integer. + + modulus_length : + Length of the array representing the modulus integer. + + Returns + ------- + + complexity : `Uint` + Complexity of performing the operation. + " in + let _ := M.assign_local (| + "max_length" , + M.call (| + M.get_name (| globals, "max" |), + make_list [ + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.get_name (| globals, "base_length" |) + ], + make_dict [] + |); + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.get_name (| globals, "modulus_length" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "words" , + BinOp.floor_div (| + BinOp.add (| + M.get_name (| globals, "max_length" |), + Constant.int 7 + |), + Constant.int 8 + |) + |) in + let _ := M.return_ (| + BinOp.pow (| + M.get_name (| globals, "words" |), + Constant.int 2 + |) + |) in + M.pure Constant.None_)). + +Definition iterations : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "exponent_length"; "exponent_head" ] |) in + let _ := Constant.str " + Calculate the number of iterations required to perform a modular + exponentiation. + + Parameters + ---------- + + exponent_length : + Length of the array representing the exponent integer. + + exponent_head : + First 32 bytes of the exponent (with leading zero padding if it is + shorter than 32 bytes), as an unsigned integer. + + Returns + ------- + + iterations : `Uint` + Number of iterations. + " in + let _ := + (* if *) + M.if_then_else (| + BoolOp.and (| + Compare.lt_e (| + M.get_name (| globals, "exponent_length" |), + Constant.int 32 + |), + ltac:(M.monadic ( + Compare.eq (| + M.get_name (| globals, "exponent_head" |), + Constant.int 0 + |) + )) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "count" , + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + Compare.lt_e (| + M.get_name (| globals, "exponent_length" |), + Constant.int 32 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "bit_length" , + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.call (| + M.get_field (| M.get_name (| globals, "exponent_head" |), "bit_length" |), + make_list [], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.gt (| + M.get_name (| globals, "bit_length" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_op_local (| + BinOp.sub, + "bit_length", + Constant.int 1 + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "count" , + M.get_name (| globals, "bit_length" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "length_part" , + BinOp.mult (| + Constant.int 8, + BinOp.sub (| + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.get_name (| globals, "exponent_length" |) + ], + make_dict [] + |), + Constant.int 32 + |) + |) + |) in + let _ := M.assign_local (| + "bits_part" , + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.call (| + M.get_field (| M.get_name (| globals, "exponent_head" |), "bit_length" |), + make_list [], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.gt (| + M.get_name (| globals, "bits_part" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_op_local (| + BinOp.sub, + "bits_part", + Constant.int 1 + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "count" , + BinOp.add (| + M.get_name (| globals, "length_part" |), + M.get_name (| globals, "bits_part" |) + |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )) |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, "max" |), + make_list [ + M.get_name (| globals, "count" |); + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 1 + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Definition gas_cost : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "base_length"; "modulus_length"; "exponent_length"; "exponent_head" ] |) in + let _ := Constant.str " + Calculate the gas cost of performing a modular exponentiation. + + Parameters + ---------- + + base_length : + Length of the array representing the base integer. + + modulus_length : + Length of the array representing the modulus integer. + + exponent_length : + Length of the array representing the exponent integer. + + exponent_head : + First 32 bytes of the exponent (with leading zero padding if it is + shorter than 32 bytes), as an unsigned integer. + + Returns + ------- + + gas_cost : `Uint` + Gas required for performing the operation. + " in + let _ := M.assign_local (| + "multiplication_complexity" , + M.call (| + M.get_name (| globals, "complexity" |), + make_list [ + M.get_name (| globals, "base_length" |); + M.get_name (| globals, "modulus_length" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "iteration_count" , + M.call (| + M.get_name (| globals, "iterations" |), + make_list [ + M.get_name (| globals, "exponent_length" |); + M.get_name (| globals, "exponent_head" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "cost" , + BinOp.mult (| + M.get_name (| globals, "multiplication_complexity" |), + M.get_name (| globals, "iteration_count" |) + |) + |) in + let _ := M.assign_op_local (| + BinOp.floor_div, + "cost", + M.get_name (| globals, "GQUADDIVISOR" |) + |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, "max" |), + make_list [ + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 200 + ], + make_dict [] + |); + M.get_name (| globals, "cost" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). diff --git a/CoqOfPython/ethereum/berlin/vm/precompiled_contracts/ripemd160.v b/CoqOfPython/ethereum/berlin/vm/precompiled_contracts/ripemd160.v new file mode 100644 index 0000000..a699925 --- /dev/null +++ b/CoqOfPython/ethereum/berlin/vm/precompiled_contracts/ripemd160.v @@ -0,0 +1,125 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.berlin.vm.precompiled_contracts.ripemd160". + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) RIPEMD160 PRECOMPILED CONTRACT +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementation of the `RIPEMD160` precompiled contract. +". + +(* At top_level_stmt: unsupported node type: Import *) + +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". + +Axiom ethereum_utils_byte_imports_left_pad_zero_bytes : + IsImported globals "ethereum.utils.byte" "left_pad_zero_bytes". + +Axiom ethereum_utils_numeric_imports_ceil32 : + IsImported globals "ethereum.utils.numeric" "ceil32". + +Axiom ethereum_berlin_vm_imports_Evm : + IsImported globals "ethereum.berlin.vm" "Evm". + +Axiom ethereum_berlin_vm_gas_imports_GAS_RIPEMD160 : + IsImported globals "ethereum.berlin.vm.gas" "GAS_RIPEMD160". +Axiom ethereum_berlin_vm_gas_imports_GAS_RIPEMD160_WORD : + IsImported globals "ethereum.berlin.vm.gas" "GAS_RIPEMD160_WORD". +Axiom ethereum_berlin_vm_gas_imports_charge_gas : + IsImported globals "ethereum.berlin.vm.gas" "charge_gas". + +Definition ripemd160 : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Writes the ripemd160 hash to output. + + Parameters + ---------- + evm : + The current EVM frame. + " in + let _ := M.assign_local (| + "data" , + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "data" |) + |) in + let _ := M.assign_local (| + "word_count" , + BinOp.floor_div (| + M.call (| + M.get_name (| globals, "ceil32" |), + make_list [ + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_name (| globals, "data" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |), + Constant.int 32 + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + BinOp.add (| + M.get_name (| globals, "GAS_RIPEMD160" |), + BinOp.mult (| + M.get_name (| globals, "GAS_RIPEMD160_WORD" |), + M.get_name (| globals, "word_count" |) + |) + |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "hash_bytes" , + M.call (| + M.get_field (| M.call (| + M.get_field (| M.get_name (| globals, "hashlib" |), "new" |), + make_list [ + Constant.str "ripemd160"; + M.get_name (| globals, "data" |) + ], + make_dict [] + |), "digest" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "padded_hash" , + M.call (| + M.get_name (| globals, "left_pad_zero_bytes" |), + make_list [ + M.get_name (| globals, "hash_bytes" |); + Constant.int 32 + ], + make_dict [] + |) + |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, "evm" |), "output" |), + M.get_name (| globals, "padded_hash" |) + |) in + M.pure Constant.None_)). diff --git a/CoqOfPython/ethereum/berlin/vm/precompiled_contracts/sha256.v b/CoqOfPython/ethereum/berlin/vm/precompiled_contracts/sha256.v new file mode 100644 index 0000000..b3c060c --- /dev/null +++ b/CoqOfPython/ethereum/berlin/vm/precompiled_contracts/sha256.v @@ -0,0 +1,106 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.berlin.vm.precompiled_contracts.sha256". + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) SHA256 PRECOMPILED CONTRACT +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementation of the `SHA256` precompiled contract. +". + +(* At top_level_stmt: unsupported node type: Import *) + +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". + +Axiom ethereum_utils_numeric_imports_ceil32 : + IsImported globals "ethereum.utils.numeric" "ceil32". + +Axiom ethereum_berlin_vm_imports_Evm : + IsImported globals "ethereum.berlin.vm" "Evm". + +Axiom ethereum_berlin_vm_gas_imports_GAS_SHA256 : + IsImported globals "ethereum.berlin.vm.gas" "GAS_SHA256". +Axiom ethereum_berlin_vm_gas_imports_GAS_SHA256_WORD : + IsImported globals "ethereum.berlin.vm.gas" "GAS_SHA256_WORD". +Axiom ethereum_berlin_vm_gas_imports_charge_gas : + IsImported globals "ethereum.berlin.vm.gas" "charge_gas". + +Definition sha256 : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Writes the sha256 hash to output. + + Parameters + ---------- + evm : + The current EVM frame. + " in + let _ := M.assign_local (| + "data" , + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "data" |) + |) in + let _ := M.assign_local (| + "word_count" , + BinOp.floor_div (| + M.call (| + M.get_name (| globals, "ceil32" |), + make_list [ + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_name (| globals, "data" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |), + Constant.int 32 + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + BinOp.add (| + M.get_name (| globals, "GAS_SHA256" |), + BinOp.mult (| + M.get_name (| globals, "GAS_SHA256_WORD" |), + M.get_name (| globals, "word_count" |) + |) + |) + ], + make_dict [] + |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, "evm" |), "output" |), + M.call (| + M.get_field (| M.call (| + M.get_field (| M.get_name (| globals, "hashlib" |), "sha256" |), + make_list [ + M.get_name (| globals, "data" |) + ], + make_dict [] + |), "digest" |), + make_list [], + make_dict [] + |) + |) in + M.pure Constant.None_)). diff --git a/CoqOfPython/ethereum/berlin/vm/runtime.v b/CoqOfPython/ethereum/berlin/vm/runtime.v new file mode 100644 index 0000000..03bc450 --- /dev/null +++ b/CoqOfPython/ethereum/berlin/vm/runtime.v @@ -0,0 +1,157 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.berlin.vm.runtime". + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) Runtime Operations +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Runtime related operations used while executing EVM code. +". + +Axiom typing_imports_Set : + IsImported globals "typing" "Set". + +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". + +Axiom ethereum_berlin_vm_instructions_imports_Ops : + IsImported globals "ethereum.berlin.vm.instructions" "Ops". + +Definition get_valid_jump_destinations : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "code" ] |) in + let _ := Constant.str " + Analyze the evm code to obtain the set of valid jump destinations. + + Valid jump destinations are defined as follows: + * The jump destination is less than the length of the code. + * The jump destination should have the `JUMPDEST` opcode (0x5B). + * The jump destination shouldn't be part of the data corresponding to + `PUSH-N` opcodes. + + Note - Jump destinations are 0-indexed. + + Parameters + ---------- + code : + The EVM code which is to be executed. + + Returns + ------- + valid_jump_destinations: `Set[Uint]` + The set of valid jump destinations in the code. + " in + let _ := M.assign_local (| + "valid_jump_destinations" , + M.call (| + M.get_name (| globals, "set" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "pc" , + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + |) in + let _ := + M.while (| + Compare.lt (| + M.get_name (| globals, "pc" |), + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_name (| globals, "code" |) + ], + make_dict [] + |) + |), + ltac:(M.monadic ( +(* At stmt: unsupported node type: Try *) + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, "current_opcode" |), + M.get_field (| M.get_name (| globals, "Ops" |), "JUMPDEST" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_field (| M.get_name (| globals, "valid_jump_destinations" |), "add" |), + make_list [ + M.get_name (| globals, "pc" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + BoolOp.and (| + Compare.lt_e (| + M.get_field (| M.get_field (| M.get_name (| globals, "Ops" |), "PUSH1" |), "value" |), + M.get_field (| M.get_name (| globals, "current_opcode" |), "value" |) + |), + ltac:(M.monadic ( + Compare.lt_e (| + M.get_field (| M.get_name (| globals, "current_opcode" |), "value" |), + M.get_field (| M.get_field (| M.get_name (| globals, "Ops" |), "PUSH32" |), "value" |) + |) + )) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "push_data_size" , + BinOp.add (| + BinOp.sub (| + M.get_field (| M.get_name (| globals, "current_opcode" |), "value" |), + M.get_field (| M.get_field (| M.get_name (| globals, "Ops" |), "PUSH1" |), "value" |) + |), + Constant.int 1 + |) + |) in + let _ := M.assign_op_local (| + BinOp.add, + "pc", + M.get_name (| globals, "push_data_size" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )) |) in + let _ := M.assign_op_local (| + BinOp.add, + "pc", + Constant.int 1 + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := M.return_ (| + M.get_name (| globals, "valid_jump_destinations" |) + |) in + M.pure Constant.None_)). diff --git a/CoqOfPython/ethereum/berlin/vm/stack.v b/CoqOfPython/ethereum/berlin/vm/stack.v new file mode 100644 index 0000000..812da9c --- /dev/null +++ b/CoqOfPython/ethereum/berlin/vm/stack.v @@ -0,0 +1,123 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.berlin.vm.stack". + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) Stack +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementation of the stack operators for the EVM. +". + +Axiom typing_imports_List : + IsImported globals "typing" "List". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". + +Axiom ethereum_berlin_vm_exceptions_imports_StackOverflowError : + IsImported globals "ethereum.berlin.vm.exceptions" "StackOverflowError". +Axiom ethereum_berlin_vm_exceptions_imports_StackUnderflowError : + IsImported globals "ethereum.berlin.vm.exceptions" "StackUnderflowError". + +Definition pop : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "stack" ] |) in + let _ := Constant.str " + Pops the top item off of `stack`. + + Parameters + ---------- + stack : + EVM stack. + + Returns + ------- + value : `U256` + The top element on the stack. + + " in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_name (| globals, "stack" |) + ], + make_dict [] + |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, "StackUnderflowError" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.return_ (| + M.call (| + M.get_field (| M.get_name (| globals, "stack" |), "pop" |), + make_list [], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Definition push : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "stack"; "value" ] |) in + let _ := Constant.str " + Pushes `value` onto `stack`. + + Parameters + ---------- + stack : + EVM stack. + + value : + Item to be pushed onto `stack`. + + " in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_name (| globals, "stack" |) + ], + make_dict [] + |), + Constant.int 1024 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, "StackOverflowError" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.return_ (| + M.call (| + M.get_field (| M.get_name (| globals, "stack" |), "append" |), + make_list [ + M.get_name (| globals, "value" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). diff --git a/CoqOfPython/ethereum/byzantium/__init__.v b/CoqOfPython/ethereum/byzantium/__init__.v new file mode 100644 index 0000000..2dfebd4 --- /dev/null +++ b/CoqOfPython/ethereum/byzantium/__init__.v @@ -0,0 +1,23 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.byzantium.__init__". + +Definition expr_1 : Value.t := + Constant.str " +The Byzantium fork reduces the mining rewards, delays the difficulty bomb, +lets contracts make non-state-changing calls to other contracts, and adds +cryptographic primitives for layer 2 scaling. +". + +Axiom ethereum_fork_criteria_imports_ByBlockNumber : + IsImported globals "ethereum.fork_criteria" "ByBlockNumber". + +Definition FORK_CRITERIA : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "ByBlockNumber" |), + make_list [ + Constant.int 4370000 + ], + make_dict [] + |) +)). diff --git a/CoqOfPython/ethereum/byzantium/blocks.v b/CoqOfPython/ethereum/byzantium/blocks.v new file mode 100644 index 0000000..93405c6 --- /dev/null +++ b/CoqOfPython/ethereum/byzantium/blocks.v @@ -0,0 +1,87 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.byzantium.blocks". + +Definition expr_1 : Value.t := + Constant.str " +A `Block` is a single link in the chain that is Ethereum. Each `Block` contains +a `Header` and zero or more transactions. Each `Header` contains associated +metadata like the block number, parent block hash, and how much gas was +consumed by its transactions. + +Together, these blocks form a cryptographically secure journal recording the +history of all state transitions that have happened since the genesis of the +chain. +". + +Axiom dataclasses_imports_dataclass : + IsImported globals "dataclasses" "dataclass". + +Axiom typing_imports_Tuple : + IsImported globals "typing" "Tuple". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_Bytes : + IsImported globals "ethereum.base_types" "Bytes". +Axiom ethereum_base_types_imports_Bytes8 : + IsImported globals "ethereum.base_types" "Bytes8". +Axiom ethereum_base_types_imports_Bytes32 : + IsImported globals "ethereum.base_types" "Bytes32". +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". +Axiom ethereum_base_types_imports_slotted_freezable : + IsImported globals "ethereum.base_types" "slotted_freezable". + +Axiom ethereum_crypto_hash_imports_Hash32 : + IsImported globals "ethereum.crypto.hash" "Hash32". + +Axiom ethereum_byzantium_fork_types_imports_Address : + IsImported globals "ethereum.byzantium.fork_types" "Address". +Axiom ethereum_byzantium_fork_types_imports_Bloom : + IsImported globals "ethereum.byzantium.fork_types" "Bloom". +Axiom ethereum_byzantium_fork_types_imports_Root : + IsImported globals "ethereum.byzantium.fork_types" "Root". + +Axiom ethereum_byzantium_transactions_imports_Transaction : + IsImported globals "ethereum.byzantium.transactions" "Transaction". + +Definition Header : Value.t := + builtins.make_klass + [] + [ + + ] + [ + + ]. + +Definition Block : Value.t := + builtins.make_klass + [] + [ + + ] + [ + + ]. + +Definition Log : Value.t := + builtins.make_klass + [] + [ + + ] + [ + + ]. + +Definition Receipt : Value.t := + builtins.make_klass + [] + [ + + ] + [ + + ]. diff --git a/CoqOfPython/ethereum/byzantium/bloom.v b/CoqOfPython/ethereum/byzantium/bloom.v new file mode 100644 index 0000000..4b8bc45 --- /dev/null +++ b/CoqOfPython/ethereum/byzantium/bloom.v @@ -0,0 +1,207 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.byzantium.bloom". + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Logs Bloom +^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +This modules defines functions for calculating bloom filters of logs. For the +general theory of bloom filters see e.g. `Wikipedia +`_. Bloom filters are used to allow +for efficient searching of logs by address and/or topic, by rapidly +eliminating blocks and receipts from their search. +". + +Axiom typing_imports_Tuple : + IsImported globals "typing" "Tuple". + +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". + +Axiom ethereum_crypto_hash_imports_keccak256 : + IsImported globals "ethereum.crypto.hash" "keccak256". + +Axiom ethereum_byzantium_blocks_imports_Log : + IsImported globals "ethereum.byzantium.blocks" "Log". + +Axiom ethereum_byzantium_fork_types_imports_Bloom : + IsImported globals "ethereum.byzantium.fork_types" "Bloom". + +Definition add_to_bloom : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "bloom"; "bloom_entry" ] |) in + let _ := Constant.str " + Add a bloom entry to the bloom filter (`bloom`). + + The number of hash functions used is 3. They are calculated by taking the + least significant 11 bits from the first 3 16-bit words of the + `keccak_256()` hash of `bloom_entry`. + + Parameters + ---------- + bloom : + The bloom filter. + bloom_entry : + An entry which is to be added to bloom filter. + " in + let _ := M.assign_local (| + "hash" , + M.call (| + M.get_name (| globals, "keccak256" |), + make_list [ + M.get_name (| globals, "bloom_entry" |) + ], + make_dict [] + |) + |) in + let _ := + M.for_ (| + M.get_name (| globals, "idx" |), + make_tuple [ Constant.int 0; Constant.int 2; Constant.int 4 ], + ltac:(M.monadic ( + let _ := M.assign_local (| + "bit_to_set" , + BinOp.bit_and (| + M.call (| + M.get_field (| M.get_name (| globals, "Uint" |), "from_be_bytes" |), + make_list [ + M.slice (| + M.get_name (| globals, "hash" |), + M.get_name (| globals, "idx" |), + BinOp.add (| + M.get_name (| globals, "idx" |), + Constant.int 2 + |), + Constant.None_ + |) + ], + make_dict [] + |), + Constant.int 2047 + |) + |) in + let _ := M.assign_local (| + "bit_index" , + BinOp.sub (| + Constant.int 2047, + M.get_name (| globals, "bit_to_set" |) + |) + |) in + let _ := M.assign_local (| + "byte_index" , + BinOp.floor_div (| + M.get_name (| globals, "bit_index" |), + Constant.int 8 + |) + |) in + let _ := M.assign_local (| + "bit_value" , + BinOp.l_shift (| + Constant.int 1, + BinOp.sub (| + Constant.int 7, + BinOp.mod_ (| + M.get_name (| globals, "bit_index" |), + Constant.int 8 + |) + |) + |) + |) in + let _ := M.assign (| + M.get_subscript (| + M.get_name (| globals, "bloom" |), + M.get_name (| globals, "byte_index" |) + |), + BinOp.bit_or (| + M.get_subscript (| + M.get_name (| globals, "bloom" |), + M.get_name (| globals, "byte_index" |) + |), + M.get_name (| globals, "bit_value" |) + |) + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + M.pure Constant.None_)). + +Definition logs_bloom : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "logs" ] |) in + let _ := Constant.str " + Obtain the logs bloom from a list of log entries. + + The address and each topic of a log are added to the bloom filter. + + Parameters + ---------- + logs : + List of logs for which the logs bloom is to be obtained. + + Returns + ------- + logs_bloom : `Bloom` + The logs bloom obtained which is 256 bytes with some bits set as per + the caller address and the log topics. + " in +(* At stmt: unsupported node type: AnnAssign *) + let _ := + M.for_ (| + M.get_name (| globals, "log" |), + M.get_name (| globals, "logs" |), + ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, "add_to_bloom" |), + make_list [ + M.get_name (| globals, "bloom" |); + M.get_field (| M.get_name (| globals, "log" |), "address" |) + ], + make_dict [] + |) in + let _ := + M.for_ (| + M.get_name (| globals, "topic" |), + M.get_field (| M.get_name (| globals, "log" |), "topics" |), + ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, "add_to_bloom" |), + make_list [ + M.get_name (| globals, "bloom" |); + M.get_name (| globals, "topic" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, "Bloom" |), + make_list [ + M.get_name (| globals, "bloom" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). diff --git a/CoqOfPython/ethereum/byzantium/fork.v b/CoqOfPython/ethereum/byzantium/fork.v new file mode 100644 index 0000000..87d1e53 --- /dev/null +++ b/CoqOfPython/ethereum/byzantium/fork.v @@ -0,0 +1,2655 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.byzantium.fork". + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Specification +^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Entry point for the Ethereum specification. +". + +Axiom dataclasses_imports_dataclass : + IsImported globals "dataclasses" "dataclass". + +Axiom typing_imports_List : + IsImported globals "typing" "List". +Axiom typing_imports_Optional : + IsImported globals "typing" "Optional". +Axiom typing_imports_Set : + IsImported globals "typing" "Set". +Axiom typing_imports_Tuple : + IsImported globals "typing" "Tuple". + +Axiom ethereum_base_types_imports_Bytes0 : + IsImported globals "ethereum.base_types" "Bytes0". + +Axiom ethereum_crypto_elliptic_curve_imports_SECP256K1N : + IsImported globals "ethereum.crypto.elliptic_curve" "SECP256K1N". +Axiom ethereum_crypto_elliptic_curve_imports_secp256k1_recover : + IsImported globals "ethereum.crypto.elliptic_curve" "secp256k1_recover". + +Axiom ethereum_crypto_hash_imports_Hash32 : + IsImported globals "ethereum.crypto.hash" "Hash32". +Axiom ethereum_crypto_hash_imports_keccak256 : + IsImported globals "ethereum.crypto.hash" "keccak256". + +Axiom ethereum_ethash_imports_dataset_size : + IsImported globals "ethereum.ethash" "dataset_size". +Axiom ethereum_ethash_imports_generate_cache : + IsImported globals "ethereum.ethash" "generate_cache". +Axiom ethereum_ethash_imports_hashimoto_light : + IsImported globals "ethereum.ethash" "hashimoto_light". + +Axiom ethereum_exceptions_imports_InvalidBlock : + IsImported globals "ethereum.exceptions" "InvalidBlock". + +Axiom ethereum_utils_ensure_imports_ensure : + IsImported globals "ethereum.utils.ensure" "ensure". + +Axiom ethereum_imports_rlp : + IsImported globals "ethereum" "rlp". + +Axiom ethereum_base_types_imports_U64 : + IsImported globals "ethereum.base_types" "U64". +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_U256_CEIL_VALUE : + IsImported globals "ethereum.base_types" "U256_CEIL_VALUE". +Axiom ethereum_base_types_imports_Bytes : + IsImported globals "ethereum.base_types" "Bytes". +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". + +Axiom ethereum_byzantium_imports_vm : + IsImported globals "ethereum.byzantium" "vm". + +Axiom ethereum_byzantium_blocks_imports_Block : + IsImported globals "ethereum.byzantium.blocks" "Block". +Axiom ethereum_byzantium_blocks_imports_Header : + IsImported globals "ethereum.byzantium.blocks" "Header". +Axiom ethereum_byzantium_blocks_imports_Log : + IsImported globals "ethereum.byzantium.blocks" "Log". +Axiom ethereum_byzantium_blocks_imports_Receipt : + IsImported globals "ethereum.byzantium.blocks" "Receipt". + +Axiom ethereum_byzantium_bloom_imports_logs_bloom : + IsImported globals "ethereum.byzantium.bloom" "logs_bloom". + +Axiom ethereum_byzantium_fork_types_imports_Address : + IsImported globals "ethereum.byzantium.fork_types" "Address". +Axiom ethereum_byzantium_fork_types_imports_Bloom : + IsImported globals "ethereum.byzantium.fork_types" "Bloom". +Axiom ethereum_byzantium_fork_types_imports_Root : + IsImported globals "ethereum.byzantium.fork_types" "Root". + +Axiom ethereum_byzantium_state_imports_State : + IsImported globals "ethereum.byzantium.state" "State". +Axiom ethereum_byzantium_state_imports_account_exists_and_is_empty : + IsImported globals "ethereum.byzantium.state" "account_exists_and_is_empty". +Axiom ethereum_byzantium_state_imports_create_ether : + IsImported globals "ethereum.byzantium.state" "create_ether". +Axiom ethereum_byzantium_state_imports_destroy_account : + IsImported globals "ethereum.byzantium.state" "destroy_account". +Axiom ethereum_byzantium_state_imports_get_account : + IsImported globals "ethereum.byzantium.state" "get_account". +Axiom ethereum_byzantium_state_imports_increment_nonce : + IsImported globals "ethereum.byzantium.state" "increment_nonce". +Axiom ethereum_byzantium_state_imports_set_account_balance : + IsImported globals "ethereum.byzantium.state" "set_account_balance". +Axiom ethereum_byzantium_state_imports_state_root : + IsImported globals "ethereum.byzantium.state" "state_root". + +Axiom ethereum_byzantium_transactions_imports_TX_BASE_COST : + IsImported globals "ethereum.byzantium.transactions" "TX_BASE_COST". +Axiom ethereum_byzantium_transactions_imports_TX_CREATE_COST : + IsImported globals "ethereum.byzantium.transactions" "TX_CREATE_COST". +Axiom ethereum_byzantium_transactions_imports_TX_DATA_COST_PER_NON_ZERO : + IsImported globals "ethereum.byzantium.transactions" "TX_DATA_COST_PER_NON_ZERO". +Axiom ethereum_byzantium_transactions_imports_TX_DATA_COST_PER_ZERO : + IsImported globals "ethereum.byzantium.transactions" "TX_DATA_COST_PER_ZERO". +Axiom ethereum_byzantium_transactions_imports_Transaction : + IsImported globals "ethereum.byzantium.transactions" "Transaction". + +Axiom ethereum_byzantium_trie_imports_Trie : + IsImported globals "ethereum.byzantium.trie" "Trie". +Axiom ethereum_byzantium_trie_imports_root : + IsImported globals "ethereum.byzantium.trie" "root". +Axiom ethereum_byzantium_trie_imports_trie_set : + IsImported globals "ethereum.byzantium.trie" "trie_set". + +Axiom ethereum_byzantium_utils_message_imports_prepare_message : + IsImported globals "ethereum.byzantium.utils.message" "prepare_message". + +Axiom ethereum_byzantium_vm_interpreter_imports_process_message_call : + IsImported globals "ethereum.byzantium.vm.interpreter" "process_message_call". + +Definition BLOCK_REWARD : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + BinOp.mult (| + Constant.int 3, + BinOp.pow (| + Constant.int 10, + Constant.int 18 + |) + |) + ], + make_dict [] + |) +)). + +Definition GAS_LIMIT_ADJUSTMENT_FACTOR : Value.t := M.run ltac:(M.monadic ( + Constant.int 1024 +)). + +Definition GAS_LIMIT_MINIMUM : Value.t := M.run ltac:(M.monadic ( + Constant.int 5000 +)). + +Definition MINIMUM_DIFFICULTY : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 131072 + ], + make_dict [] + |) +)). + +Definition MAX_OMMER_DEPTH : Value.t := M.run ltac:(M.monadic ( + Constant.int 6 +)). + +Definition BOMB_DELAY_BLOCKS : Value.t := M.run ltac:(M.monadic ( + Constant.int 3000000 +)). + +Definition EMPTY_OMMER_HASH : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "keccak256" |), + make_list [ + M.call (| + M.get_field (| M.get_name (| globals, "rlp" |), "encode" |), + make_list [ + make_list [] + ], + make_dict [] + |) + ], + make_dict [] + |) +)). + +Definition BlockChain : Value.t := + builtins.make_klass + [] + [ + + ] + [ + + ]. + +Definition apply_fork : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "old" ] |) in + let _ := Constant.str " + Transforms the state from the previous hard fork (`old`) into the block + chain object for this hard fork and returns it. + + When forks need to implement an irregular state transition, this function + is used to handle the irregularity. See the :ref:`DAO Fork ` for + an example. + + Parameters + ---------- + old : + Previous block chain object. + + Returns + ------- + new : `BlockChain` + Upgraded block chain object for this hard fork. + " in + let _ := M.return_ (| + M.get_name (| globals, "old" |) + |) in + M.pure Constant.None_)). + +Definition get_last_256_block_hashes : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "chain" ] |) in + let _ := Constant.str " + Obtain the list of hashes of the previous 256 blocks in order of + increasing block number. + + This function will return less hashes for the first 256 blocks. + + The ``BLOCKHASH`` opcode needs to access the latest hashes on the chain, + therefore this function retrieves them. + + Parameters + ---------- + chain : + History and current state. + + Returns + ------- + recent_block_hashes : `List[Hash32]` + Hashes of the recent 256 blocks in order of increasing block number. + " in + let _ := M.assign_local (| + "recent_blocks" , + M.slice (| + M.get_field (| M.get_name (| globals, "chain" |), "blocks" |), + UnOp.sub (| Constant.int 255 |), + Constant.None_, + Constant.None_ + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_name (| globals, "recent_blocks" |) + ], + make_dict [] + |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + make_list [] + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "recent_block_hashes" , + make_list [] + |) in + let _ := + M.for_ (| + M.get_name (| globals, "block" |), + M.get_name (| globals, "recent_blocks" |), + ltac:(M.monadic ( + let _ := M.assign_local (| + "prev_block_hash" , + M.get_field (| M.get_field (| M.get_name (| globals, "block" |), "header" |), "parent_hash" |) + |) in + let _ := M.call (| + M.get_field (| M.get_name (| globals, "recent_block_hashes" |), "append" |), + make_list [ + M.get_name (| globals, "prev_block_hash" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := M.assign_local (| + "most_recent_block_hash" , + M.call (| + M.get_name (| globals, "keccak256" |), + make_list [ + M.call (| + M.get_field (| M.get_name (| globals, "rlp" |), "encode" |), + make_list [ + M.get_field (| M.get_subscript (| + M.get_name (| globals, "recent_blocks" |), + UnOp.sub (| Constant.int 1 |) + |), "header" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_field (| M.get_name (| globals, "recent_block_hashes" |), "append" |), + make_list [ + M.get_name (| globals, "most_recent_block_hash" |) + ], + make_dict [] + |) in + let _ := M.return_ (| + M.get_name (| globals, "recent_block_hashes" |) + |) in + M.pure Constant.None_)). + +Definition state_transition : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "chain"; "block" ] |) in + let _ := Constant.str " + Attempts to apply a block to an existing block chain. + + All parts of the block's contents need to be verified before being added + to the chain. Blocks are verified by ensuring that the contents of the + block make logical sense with the contents of the parent block. The + information in the block's header must also match the corresponding + information in the block. + + To implement Ethereum, in theory clients are only required to store the + most recent 255 blocks of the chain since as far as execution is + concerned, only those blocks are accessed. Practically, however, clients + should store more blocks to handle reorgs. + + Parameters + ---------- + chain : + History and current state. + block : + Block to apply to `chain`. + " in + let _ := M.assign_local (| + "parent_header" , + M.get_field (| M.get_subscript (| + M.get_field (| M.get_name (| globals, "chain" |), "blocks" |), + UnOp.sub (| Constant.int 1 |) + |), "header" |) + |) in + let _ := M.call (| + M.get_name (| globals, "validate_header" |), + make_list [ + M.get_field (| M.get_name (| globals, "block" |), "header" |); + M.get_name (| globals, "parent_header" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "validate_ommers" |), + make_list [ + M.get_field (| M.get_name (| globals, "block" |), "ommers" |); + M.get_field (| M.get_name (| globals, "block" |), "header" |); + M.get_name (| globals, "chain" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "apply_body_output" , + M.call (| + M.get_name (| globals, "apply_body" |), + make_list [ + M.get_field (| M.get_name (| globals, "chain" |), "state" |); + M.call (| + M.get_name (| globals, "get_last_256_block_hashes" |), + make_list [ + M.get_name (| globals, "chain" |) + ], + make_dict [] + |); + M.get_field (| M.get_field (| M.get_name (| globals, "block" |), "header" |), "coinbase" |); + M.get_field (| M.get_field (| M.get_name (| globals, "block" |), "header" |), "number" |); + M.get_field (| M.get_field (| M.get_name (| globals, "block" |), "header" |), "gas_limit" |); + M.get_field (| M.get_field (| M.get_name (| globals, "block" |), "header" |), "timestamp" |); + M.get_field (| M.get_field (| M.get_name (| globals, "block" |), "header" |), "difficulty" |); + M.get_field (| M.get_name (| globals, "block" |), "transactions" |); + M.get_field (| M.get_name (| globals, "block" |), "ommers" |); + M.get_field (| M.get_name (| globals, "chain" |), "chain_id" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + Compare.eq (| + M.get_field (| M.get_name (| globals, "apply_body_output" |), "block_gas_used" |), + M.get_field (| M.get_field (| M.get_name (| globals, "block" |), "header" |), "gas_used" |) + |); + M.get_name (| globals, "InvalidBlock" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + Compare.eq (| + M.get_field (| M.get_name (| globals, "apply_body_output" |), "transactions_root" |), + M.get_field (| M.get_field (| M.get_name (| globals, "block" |), "header" |), "transactions_root" |) + |); + M.get_name (| globals, "InvalidBlock" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + Compare.eq (| + M.get_field (| M.get_name (| globals, "apply_body_output" |), "state_root" |), + M.get_field (| M.get_field (| M.get_name (| globals, "block" |), "header" |), "state_root" |) + |); + M.get_name (| globals, "InvalidBlock" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + Compare.eq (| + M.get_field (| M.get_name (| globals, "apply_body_output" |), "receipt_root" |), + M.get_field (| M.get_field (| M.get_name (| globals, "block" |), "header" |), "receipt_root" |) + |); + M.get_name (| globals, "InvalidBlock" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + Compare.eq (| + M.get_field (| M.get_name (| globals, "apply_body_output" |), "block_logs_bloom" |), + M.get_field (| M.get_field (| M.get_name (| globals, "block" |), "header" |), "bloom" |) + |); + M.get_name (| globals, "InvalidBlock" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, "chain" |), "blocks" |), "append" |), + make_list [ + M.get_name (| globals, "block" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.gt (| + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_field (| M.get_name (| globals, "chain" |), "blocks" |) + ], + make_dict [] + |), + Constant.int 255 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign (| + M.get_field (| M.get_name (| globals, "chain" |), "blocks" |), + M.slice (| + M.get_field (| M.get_name (| globals, "chain" |), "blocks" |), + UnOp.sub (| Constant.int 255 |), + Constant.None_, + Constant.None_ + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + M.pure Constant.None_)). + +Definition validate_header : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "header"; "parent_header" ] |) in + let _ := Constant.str " + Verifies a block header. + + In order to consider a block's header valid, the logic for the + quantities in the header should match the logic for the block itself. + For example the header timestamp should be greater than the block's parent + timestamp because the block was created *after* the parent block. + Additionally, the block's number should be directly following the parent + block's number since it is the next block in the sequence. + + Parameters + ---------- + header : + Header to check for correctness. + parent_header : + Parent Header of the header to check for correctness + " in + let _ := M.assign_local (| + "parent_has_ommers" , + Compare.not_eq (| + M.get_field (| M.get_name (| globals, "parent_header" |), "ommers_hash" |), + M.get_name (| globals, "EMPTY_OMMER_HASH" |) + |) + |) in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + Compare.gt (| + M.get_field (| M.get_name (| globals, "header" |), "timestamp" |), + M.get_field (| M.get_name (| globals, "parent_header" |), "timestamp" |) + |); + M.get_name (| globals, "InvalidBlock" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + Compare.eq (| + M.get_field (| M.get_name (| globals, "header" |), "number" |), + BinOp.add (| + M.get_field (| M.get_name (| globals, "parent_header" |), "number" |), + Constant.int 1 + |) + |); + M.get_name (| globals, "InvalidBlock" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + M.call (| + M.get_name (| globals, "check_gas_limit" |), + make_list [ + M.get_field (| M.get_name (| globals, "header" |), "gas_limit" |); + M.get_field (| M.get_name (| globals, "parent_header" |), "gas_limit" |) + ], + make_dict [] + |); + M.get_name (| globals, "InvalidBlock" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + Compare.lt_e (| + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_field (| M.get_name (| globals, "header" |), "extra_data" |) + ], + make_dict [] + |), + Constant.int 32 + |); + M.get_name (| globals, "InvalidBlock" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "block_difficulty" , + M.call (| + M.get_name (| globals, "calculate_block_difficulty" |), + make_list [ + M.get_field (| M.get_name (| globals, "header" |), "number" |); + M.get_field (| M.get_name (| globals, "header" |), "timestamp" |); + M.get_field (| M.get_name (| globals, "parent_header" |), "timestamp" |); + M.get_field (| M.get_name (| globals, "parent_header" |), "difficulty" |); + M.get_name (| globals, "parent_has_ommers" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + Compare.eq (| + M.get_field (| M.get_name (| globals, "header" |), "difficulty" |), + M.get_name (| globals, "block_difficulty" |) + |); + M.get_name (| globals, "InvalidBlock" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "block_parent_hash" , + M.call (| + M.get_name (| globals, "keccak256" |), + make_list [ + M.call (| + M.get_field (| M.get_name (| globals, "rlp" |), "encode" |), + make_list [ + M.get_name (| globals, "parent_header" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + Compare.eq (| + M.get_field (| M.get_name (| globals, "header" |), "parent_hash" |), + M.get_name (| globals, "block_parent_hash" |) + |); + M.get_name (| globals, "InvalidBlock" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "validate_proof_of_work" |), + make_list [ + M.get_name (| globals, "header" |) + ], + make_dict [] + |) in + M.pure Constant.None_)). + +Definition generate_header_hash_for_pow : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "header" ] |) in + let _ := Constant.str " + Generate rlp hash of the header which is to be used for Proof-of-Work + verification. + + In other words, the PoW artefacts `mix_digest` and `nonce` are ignored + while calculating this hash. + + A particular PoW is valid for a single hash, that hash is computed by + this function. The `nonce` and `mix_digest` are omitted from this hash + because they are being changed by miners in their search for a sufficient + proof-of-work. + + Parameters + ---------- + header : + The header object for which the hash is to be generated. + + Returns + ------- + hash : `Hash32` + The PoW valid rlp hash of the passed in header. + " in + let _ := M.assign_local (| + "header_data_without_pow_artefacts" , + make_list [ + M.get_field (| M.get_name (| globals, "header" |), "parent_hash" |); + M.get_field (| M.get_name (| globals, "header" |), "ommers_hash" |); + M.get_field (| M.get_name (| globals, "header" |), "coinbase" |); + M.get_field (| M.get_name (| globals, "header" |), "state_root" |); + M.get_field (| M.get_name (| globals, "header" |), "transactions_root" |); + M.get_field (| M.get_name (| globals, "header" |), "receipt_root" |); + M.get_field (| M.get_name (| globals, "header" |), "bloom" |); + M.get_field (| M.get_name (| globals, "header" |), "difficulty" |); + M.get_field (| M.get_name (| globals, "header" |), "number" |); + M.get_field (| M.get_name (| globals, "header" |), "gas_limit" |); + M.get_field (| M.get_name (| globals, "header" |), "gas_used" |); + M.get_field (| M.get_name (| globals, "header" |), "timestamp" |); + M.get_field (| M.get_name (| globals, "header" |), "extra_data" |) + ] + |) in + let _ := M.return_ (| + M.call (| + M.get_field (| M.get_name (| globals, "rlp" |), "rlp_hash" |), + make_list [ + M.get_name (| globals, "header_data_without_pow_artefacts" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Definition validate_proof_of_work : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "header" ] |) in + let _ := Constant.str " + Validates the Proof of Work constraints. + + In order to verify that a miner's proof-of-work is valid for a block, a + ``mix-digest`` and ``result`` are calculated using the ``hashimoto_light`` + hash function. The mix digest is a hash of the header and the nonce that + is passed through and it confirms whether or not proof-of-work was done + on the correct block. The result is the actual hash value of the block. + + Parameters + ---------- + header : + Header of interest. + " in + let _ := M.assign_local (| + "header_hash" , + M.call (| + M.get_name (| globals, "generate_header_hash_for_pow" |), + make_list [ + M.get_name (| globals, "header" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "cache" , + M.call (| + M.get_name (| globals, "generate_cache" |), + make_list [ + M.get_field (| M.get_name (| globals, "header" |), "number" |) + ], + make_dict [] + |) + |) in + let _ := M.assign (| + make_tuple [ M.get_name (| globals, "mix_digest" |); M.get_name (| globals, "result" |) ], + M.call (| + M.get_name (| globals, "hashimoto_light" |), + make_list [ + M.get_name (| globals, "header_hash" |); + M.get_field (| M.get_name (| globals, "header" |), "nonce" |); + M.get_name (| globals, "cache" |); + M.call (| + M.get_name (| globals, "dataset_size" |), + make_list [ + M.get_field (| M.get_name (| globals, "header" |), "number" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + Compare.eq (| + M.get_name (| globals, "mix_digest" |), + M.get_field (| M.get_name (| globals, "header" |), "mix_digest" |) + |); + M.get_name (| globals, "InvalidBlock" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + Compare.lt_e (| + M.call (| + M.get_field (| M.get_name (| globals, "Uint" |), "from_be_bytes" |), + make_list [ + M.get_name (| globals, "result" |) + ], + make_dict [] + |), + BinOp.floor_div (| + M.get_name (| globals, "U256_CEIL_VALUE" |), + M.get_field (| M.get_name (| globals, "header" |), "difficulty" |) + |) + |); + M.get_name (| globals, "InvalidBlock" |) + ], + make_dict [] + |) in + M.pure Constant.None_)). + +Definition check_transaction : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "tx"; "gas_available"; "chain_id" ] |) in + let _ := Constant.str " + Check if the transaction is includable in the block. + + Parameters + ---------- + tx : + The transaction. + gas_available : + The gas remaining in the block. + chain_id : + The ID of the current chain. + + Returns + ------- + sender_address : + The sender of the transaction. + + Raises + ------ + InvalidBlock : + If the transaction is not includable. + " in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + Compare.lt_e (| + M.get_field (| M.get_name (| globals, "tx" |), "gas" |), + M.get_name (| globals, "gas_available" |) + |); + M.get_name (| globals, "InvalidBlock" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "sender_address" , + M.call (| + M.get_name (| globals, "recover_sender" |), + make_list [ + M.get_name (| globals, "chain_id" |); + M.get_name (| globals, "tx" |) + ], + make_dict [] + |) + |) in + let _ := M.return_ (| + M.get_name (| globals, "sender_address" |) + |) in + M.pure Constant.None_)). + +Definition make_receipt : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "tx"; "error"; "cumulative_gas_used"; "logs" ] |) in + let _ := Constant.str " + Make the receipt for a transaction that was executed. + + Parameters + ---------- + tx : + The executed transaction. + error : + Error in the top level frame of the transaction, if any. + cumulative_gas_used : + The total gas used so far in the block after the transaction was + executed. + logs : + The logs produced by the transaction. + + Returns + ------- + receipt : + The receipt for the transaction. + " in + let _ := M.assign_local (| + "receipt" , + M.call (| + M.get_name (| globals, "Receipt" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.return_ (| + M.get_name (| globals, "receipt" |) + |) in + M.pure Constant.None_)). + +Definition ApplyBodyOutput : Value.t := + builtins.make_klass + [] + [ + + ] + [ + + ]. + +Definition apply_body : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "state"; "block_hashes"; "coinbase"; "block_number"; "block_gas_limit"; "block_time"; "block_difficulty"; "transactions"; "ommers"; "chain_id" ] |) in + let _ := Constant.str " + Executes a block. + + Many of the contents of a block are stored in data structures called + tries. There is a transactions trie which is similar to a ledger of the + transactions stored in the current block. There is also a receipts trie + which stores the results of executing a transaction, like the post state + and gas used. This function creates and executes the block that is to be + added to the chain. + + Parameters + ---------- + state : + Current account state. + block_hashes : + List of hashes of the previous 256 blocks in the order of + increasing block number. + coinbase : + Address of account which receives block reward and transaction fees. + block_number : + Position of the block within the chain. + block_gas_limit : + Initial amount of gas available for execution in this block. + block_time : + Time the block was produced, measured in seconds since the epoch. + block_difficulty : + Difficulty of the block. + transactions : + Transactions included in the block. + ommers : + Headers of ancestor blocks which are not direct parents (formerly + uncles.) + chain_id : + ID of the executing chain. + + Returns + ------- + apply_body_output : `ApplyBodyOutput` + Output of applying the block body to the state. + " in + let _ := M.assign_local (| + "gas_available" , + M.get_name (| globals, "block_gas_limit" |) + |) in +(* At stmt: unsupported node type: AnnAssign *) +(* At stmt: unsupported node type: AnnAssign *) +(* At stmt: unsupported node type: AnnAssign *) + let _ := + M.for_ (| + make_tuple [ M.get_name (| globals, "i" |); M.get_name (| globals, "tx" |) ], + M.call (| + M.get_name (| globals, "enumerate" |), + make_list [ + M.get_name (| globals, "transactions" |) + ], + make_dict [] + |), + ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, "trie_set" |), + make_list [ + M.get_name (| globals, "transactions_trie" |); + M.call (| + M.get_field (| M.get_name (| globals, "rlp" |), "encode" |), + make_list [ + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.get_name (| globals, "i" |) + ], + make_dict [] + |) + ], + make_dict [] + |); + M.get_name (| globals, "tx" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "sender_address" , + M.call (| + M.get_name (| globals, "check_transaction" |), + make_list [ + M.get_name (| globals, "tx" |); + M.get_name (| globals, "gas_available" |); + M.get_name (| globals, "chain_id" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "env" , + M.call (| + M.get_field (| M.get_name (| globals, "vm" |), "Environment" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.assign (| + make_tuple [ M.get_name (| globals, "gas_used" |); M.get_name (| globals, "logs" |); M.get_name (| globals, "error" |) ], + M.call (| + M.get_name (| globals, "process_transaction" |), + make_list [ + M.get_name (| globals, "env" |); + M.get_name (| globals, "tx" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_op_local (| + BinOp.sub, + "gas_available", + M.get_name (| globals, "gas_used" |) + |) in + let _ := M.assign_local (| + "receipt" , + M.call (| + M.get_name (| globals, "make_receipt" |), + make_list [ + M.get_name (| globals, "tx" |); + M.get_name (| globals, "error" |); + BinOp.sub (| + M.get_name (| globals, "block_gas_limit" |), + M.get_name (| globals, "gas_available" |) + |); + M.get_name (| globals, "logs" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "trie_set" |), + make_list [ + M.get_name (| globals, "receipts_trie" |); + M.call (| + M.get_field (| M.get_name (| globals, "rlp" |), "encode" |), + make_list [ + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.get_name (| globals, "i" |) + ], + make_dict [] + |) + ], + make_dict [] + |); + M.get_name (| globals, "receipt" |) + ], + make_dict [] + |) in + let _ := M.assign_op_local (| + BinOp.add, + "block_logs", + M.get_name (| globals, "logs" |) + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := M.call (| + M.get_name (| globals, "pay_rewards" |), + make_list [ + M.get_name (| globals, "state" |); + M.get_name (| globals, "block_number" |); + M.get_name (| globals, "coinbase" |); + M.get_name (| globals, "ommers" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "block_gas_used" , + BinOp.sub (| + M.get_name (| globals, "block_gas_limit" |), + M.get_name (| globals, "gas_available" |) + |) + |) in + let _ := M.assign_local (| + "block_logs_bloom" , + M.call (| + M.get_name (| globals, "logs_bloom" |), + make_list [ + M.get_name (| globals, "block_logs" |) + ], + make_dict [] + |) + |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, "ApplyBodyOutput" |), + make_list [ + M.get_name (| globals, "block_gas_used" |); + M.call (| + M.get_name (| globals, "root" |), + make_list [ + M.get_name (| globals, "transactions_trie" |) + ], + make_dict [] + |); + M.call (| + M.get_name (| globals, "root" |), + make_list [ + M.get_name (| globals, "receipts_trie" |) + ], + make_dict [] + |); + M.get_name (| globals, "block_logs_bloom" |); + M.call (| + M.get_name (| globals, "state_root" |), + make_list [ + M.get_name (| globals, "state" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Definition validate_ommers : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "ommers"; "block_header"; "chain" ] |) in + let _ := Constant.str " + Validates the ommers mentioned in the block. + + An ommer block is a block that wasn't canonically added to the + blockchain because it wasn't validated as fast as the canonical block + but was mined at the same time. + + To be considered valid, the ommers must adhere to the rules defined in + the Ethereum protocol. The maximum amount of ommers is 2 per block and + there cannot be duplicate ommers in a block. Many of the other ommer + constraints are listed in the in-line comments of this function. + + Parameters + ---------- + ommers : + List of ommers mentioned in the current block. + block_header: + The header of current block. + chain : + History and current state. + " in + let _ := M.assign_local (| + "block_hash" , + M.call (| + M.get_field (| M.get_name (| globals, "rlp" |), "rlp_hash" |), + make_list [ + M.get_name (| globals, "block_header" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + Compare.eq (| + M.call (| + M.get_field (| M.get_name (| globals, "rlp" |), "rlp_hash" |), + make_list [ + M.get_name (| globals, "ommers" |) + ], + make_dict [] + |), + M.get_field (| M.get_name (| globals, "block_header" |), "ommers_hash" |) + |); + M.get_name (| globals, "InvalidBlock" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_name (| globals, "ommers" |) + ], + make_dict [] + |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + Constant.None_ + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + M.for_ (| + M.get_name (| globals, "ommer" |), + M.get_name (| globals, "ommers" |), + ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + BoolOp.and (| + Compare.lt_e (| + Constant.int 1, + M.get_field (| M.get_name (| globals, "ommer" |), "number" |) + |), + ltac:(M.monadic ( + Compare.lt (| + M.get_field (| M.get_name (| globals, "ommer" |), "number" |), + M.get_field (| M.get_name (| globals, "block_header" |), "number" |) + |) + )) + |); + M.get_name (| globals, "InvalidBlock" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "ommer_parent_header" , + M.get_field (| M.get_subscript (| + M.get_field (| M.get_name (| globals, "chain" |), "blocks" |), + BinOp.sub (| + UnOp.sub (| BinOp.sub (| + M.get_field (| M.get_name (| globals, "block_header" |), "number" |), + M.get_field (| M.get_name (| globals, "ommer" |), "number" |) + |) |), + Constant.int 1 + |) + |), "header" |) + |) in + let _ := M.call (| + M.get_name (| globals, "validate_header" |), + make_list [ + M.get_name (| globals, "ommer" |); + M.get_name (| globals, "ommer_parent_header" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + Compare.lt_e (| + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_name (| globals, "ommers" |) + ], + make_dict [] + |), + Constant.int 2 + |); + M.get_name (| globals, "InvalidBlock" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "ommers_hashes" , + Constant.str "(* At expr: unsupported node type: ListComp *)" + |) in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + Compare.eq (| + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_name (| globals, "ommers_hashes" |) + ], + make_dict [] + |), + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.call (| + M.get_name (| globals, "set" |), + make_list [ + M.get_name (| globals, "ommers_hashes" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |); + M.get_name (| globals, "InvalidBlock" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "recent_canonical_blocks" , + M.slice (| + M.get_field (| M.get_name (| globals, "chain" |), "blocks" |), + UnOp.sub (| BinOp.add (| + M.get_name (| globals, "MAX_OMMER_DEPTH" |), + Constant.int 1 + |) |), + Constant.None_, + Constant.None_ + |) + |) in + let _ := M.assign_local (| + "recent_canonical_block_hashes" , + Constant.str "(* At expr: unsupported node type: SetComp *)" + |) in +(* At stmt: unsupported node type: AnnAssign *) + let _ := + M.for_ (| + M.get_name (| globals, "block" |), + M.get_name (| globals, "recent_canonical_blocks" |), + ltac:(M.monadic ( + let _ := M.assign_local (| + "recent_ommers_hashes" , + M.call (| + M.get_field (| M.get_name (| globals, "recent_ommers_hashes" |), "union" |), + make_list [ + Constant.str "(* At expr: unsupported node type: SetComp *)" + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := + M.for_ (| + make_tuple [ M.get_name (| globals, "ommer_index" |); M.get_name (| globals, "ommer" |) ], + M.call (| + M.get_name (| globals, "enumerate" |), + make_list [ + M.get_name (| globals, "ommers" |) + ], + make_dict [] + |), + ltac:(M.monadic ( + let _ := M.assign_local (| + "ommer_hash" , + M.get_subscript (| + M.get_name (| globals, "ommers_hashes" |), + M.get_name (| globals, "ommer_index" |) + |) + |) in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + Compare.not_eq (| + M.get_name (| globals, "ommer_hash" |), + M.get_name (| globals, "block_hash" |) + |); + M.get_name (| globals, "InvalidBlock" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + Compare.not_in (| + M.get_name (| globals, "ommer_hash" |), + M.get_name (| globals, "recent_canonical_block_hashes" |) + |); + M.get_name (| globals, "InvalidBlock" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + Compare.not_in (| + M.get_name (| globals, "ommer_hash" |), + M.get_name (| globals, "recent_ommers_hashes" |) + |); + M.get_name (| globals, "InvalidBlock" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "ommer_age" , + BinOp.sub (| + M.get_field (| M.get_name (| globals, "block_header" |), "number" |), + M.get_field (| M.get_name (| globals, "ommer" |), "number" |) + |) + |) in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + BoolOp.and (| + Compare.lt_e (| + Constant.int 1, + M.get_name (| globals, "ommer_age" |) + |), + ltac:(M.monadic ( + Compare.lt_e (| + M.get_name (| globals, "ommer_age" |), + M.get_name (| globals, "MAX_OMMER_DEPTH" |) + |) + )) + |); + M.get_name (| globals, "InvalidBlock" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + Compare.in_ (| + M.get_field (| M.get_name (| globals, "ommer" |), "parent_hash" |), + M.get_name (| globals, "recent_canonical_block_hashes" |) + |); + M.get_name (| globals, "InvalidBlock" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + Compare.not_eq (| + M.get_field (| M.get_name (| globals, "ommer" |), "parent_hash" |), + M.get_field (| M.get_name (| globals, "block_header" |), "parent_hash" |) + |); + M.get_name (| globals, "InvalidBlock" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + M.pure Constant.None_)). + +Definition pay_rewards : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "state"; "block_number"; "coinbase"; "ommers" ] |) in + let _ := Constant.str " + Pay rewards to the block miner as well as the ommers miners. + + The miner of the canonical block is rewarded with the predetermined + block reward, ``BLOCK_REWARD``, plus a variable award based off of the + number of ommer blocks that were mined around the same time, and included + in the canonical block's header. An ommer block is a block that wasn't + added to the canonical blockchain because it wasn't validated as fast as + the accepted block but was mined at the same time. Although not all blocks + that are mined are added to the canonical chain, miners are still paid a + reward for their efforts. This reward is called an ommer reward and is + calculated based on the number associated with the ommer block that they + mined. + + Parameters + ---------- + state : + Current account state. + block_number : + Position of the block within the chain. + coinbase : + Address of account which receives block reward and transaction fees. + ommers : + List of ommers mentioned in the current block. + " in + let _ := M.assign_local (| + "miner_reward" , + BinOp.add (| + M.get_name (| globals, "BLOCK_REWARD" |), + BinOp.mult (| + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_name (| globals, "ommers" |) + ], + make_dict [] + |), + BinOp.floor_div (| + M.get_name (| globals, "BLOCK_REWARD" |), + Constant.int 32 + |) + |) + |) + |) in + let _ := M.call (| + M.get_name (| globals, "create_ether" |), + make_list [ + M.get_name (| globals, "state" |); + M.get_name (| globals, "coinbase" |); + M.get_name (| globals, "miner_reward" |) + ], + make_dict [] + |) in + let _ := + M.for_ (| + M.get_name (| globals, "ommer" |), + M.get_name (| globals, "ommers" |), + ltac:(M.monadic ( + let _ := M.assign_local (| + "ommer_age" , + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + BinOp.sub (| + M.get_name (| globals, "block_number" |), + M.get_field (| M.get_name (| globals, "ommer" |), "number" |) + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "ommer_miner_reward" , + BinOp.floor_div (| + BinOp.mult (| + BinOp.sub (| + Constant.int 8, + M.get_name (| globals, "ommer_age" |) + |), + M.get_name (| globals, "BLOCK_REWARD" |) + |), + Constant.int 8 + |) + |) in + let _ := M.call (| + M.get_name (| globals, "create_ether" |), + make_list [ + M.get_name (| globals, "state" |); + M.get_field (| M.get_name (| globals, "ommer" |), "coinbase" |); + M.get_name (| globals, "ommer_miner_reward" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + M.pure Constant.None_)). + +Definition process_transaction : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "env"; "tx" ] |) in + let _ := Constant.str " + Execute a transaction against the provided environment. + + This function processes the actions needed to execute a transaction. + It decrements the sender's account after calculating the gas fee and + refunds them the proper amount after execution. Calling contracts, + deploying code, and incrementing nonces are all examples of actions that + happen within this function or from a call made within this function. + + Accounts that are marked for deletion are processed and destroyed after + execution. + + Parameters + ---------- + env : + Environment for the Ethereum Virtual Machine. + tx : + Transaction to execute. + + Returns + ------- + gas_left : `ethereum.base_types.U256` + Remaining gas after execution. + logs : `Tuple[ethereum.blocks.Log, ...]` + Logs generated during execution. + " in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + M.call (| + M.get_name (| globals, "validate_transaction" |), + make_list [ + M.get_name (| globals, "tx" |) + ], + make_dict [] + |); + M.get_name (| globals, "InvalidBlock" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "sender" , + M.get_field (| M.get_name (| globals, "env" |), "origin" |) + |) in + let _ := M.assign_local (| + "sender_account" , + M.call (| + M.get_name (| globals, "get_account" |), + make_list [ + M.get_field (| M.get_name (| globals, "env" |), "state" |); + M.get_name (| globals, "sender" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "gas_fee" , + BinOp.mult (| + M.get_field (| M.get_name (| globals, "tx" |), "gas" |), + M.get_field (| M.get_name (| globals, "tx" |), "gas_price" |) + |) + |) in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + Compare.eq (| + M.get_field (| M.get_name (| globals, "sender_account" |), "nonce" |), + M.get_field (| M.get_name (| globals, "tx" |), "nonce" |) + |); + M.get_name (| globals, "InvalidBlock" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + Compare.gt_e (| + M.get_field (| M.get_name (| globals, "sender_account" |), "balance" |), + BinOp.add (| + M.get_name (| globals, "gas_fee" |), + M.get_field (| M.get_name (| globals, "tx" |), "value" |) + |) + |); + M.get_name (| globals, "InvalidBlock" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + Compare.eq (| + M.get_field (| M.get_name (| globals, "sender_account" |), "code" |), + M.call (| + M.get_name (| globals, "bytearray" |), + make_list [], + make_dict [] + |) + |); + M.get_name (| globals, "InvalidBlock" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "gas" , + BinOp.sub (| + M.get_field (| M.get_name (| globals, "tx" |), "gas" |), + M.call (| + M.get_name (| globals, "calculate_intrinsic_cost" |), + make_list [ + M.get_name (| globals, "tx" |) + ], + make_dict [] + |) + |) + |) in + let _ := M.call (| + M.get_name (| globals, "increment_nonce" |), + make_list [ + M.get_field (| M.get_name (| globals, "env" |), "state" |); + M.get_name (| globals, "sender" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "sender_balance_after_gas_fee" , + BinOp.sub (| + M.get_field (| M.get_name (| globals, "sender_account" |), "balance" |), + M.get_name (| globals, "gas_fee" |) + |) + |) in + let _ := M.call (| + M.get_name (| globals, "set_account_balance" |), + make_list [ + M.get_field (| M.get_name (| globals, "env" |), "state" |); + M.get_name (| globals, "sender" |); + M.get_name (| globals, "sender_balance_after_gas_fee" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "message" , + M.call (| + M.get_name (| globals, "prepare_message" |), + make_list [ + M.get_name (| globals, "sender" |); + M.get_field (| M.get_name (| globals, "tx" |), "to" |); + M.get_field (| M.get_name (| globals, "tx" |), "value" |); + M.get_field (| M.get_name (| globals, "tx" |), "data" |); + M.get_name (| globals, "gas" |); + M.get_name (| globals, "env" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "output" , + M.call (| + M.get_name (| globals, "process_message_call" |), + make_list [ + M.get_name (| globals, "message" |); + M.get_name (| globals, "env" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "gas_used" , + BinOp.sub (| + M.get_field (| M.get_name (| globals, "tx" |), "gas" |), + M.get_field (| M.get_name (| globals, "output" |), "gas_left" |) + |) + |) in + let _ := M.assign_local (| + "gas_refund" , + M.call (| + M.get_name (| globals, "min" |), + make_list [ + BinOp.floor_div (| + M.get_name (| globals, "gas_used" |), + Constant.int 2 + |); + M.get_field (| M.get_name (| globals, "output" |), "refund_counter" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "gas_refund_amount" , + BinOp.mult (| + BinOp.add (| + M.get_field (| M.get_name (| globals, "output" |), "gas_left" |), + M.get_name (| globals, "gas_refund" |) + |), + M.get_field (| M.get_name (| globals, "tx" |), "gas_price" |) + |) + |) in + let _ := M.assign_local (| + "transaction_fee" , + BinOp.mult (| + BinOp.sub (| + BinOp.sub (| + M.get_field (| M.get_name (| globals, "tx" |), "gas" |), + M.get_field (| M.get_name (| globals, "output" |), "gas_left" |) + |), + M.get_name (| globals, "gas_refund" |) + |), + M.get_field (| M.get_name (| globals, "tx" |), "gas_price" |) + |) + |) in + let _ := M.assign_local (| + "total_gas_used" , + BinOp.sub (| + M.get_name (| globals, "gas_used" |), + M.get_name (| globals, "gas_refund" |) + |) + |) in + let _ := M.assign_local (| + "sender_balance_after_refund" , + BinOp.add (| + M.get_field (| M.call (| + M.get_name (| globals, "get_account" |), + make_list [ + M.get_field (| M.get_name (| globals, "env" |), "state" |); + M.get_name (| globals, "sender" |) + ], + make_dict [] + |), "balance" |), + M.get_name (| globals, "gas_refund_amount" |) + |) + |) in + let _ := M.call (| + M.get_name (| globals, "set_account_balance" |), + make_list [ + M.get_field (| M.get_name (| globals, "env" |), "state" |); + M.get_name (| globals, "sender" |); + M.get_name (| globals, "sender_balance_after_refund" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "coinbase_balance_after_mining_fee" , + BinOp.add (| + M.get_field (| M.call (| + M.get_name (| globals, "get_account" |), + make_list [ + M.get_field (| M.get_name (| globals, "env" |), "state" |); + M.get_field (| M.get_name (| globals, "env" |), "coinbase" |) + ], + make_dict [] + |), "balance" |), + M.get_name (| globals, "transaction_fee" |) + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.not_eq (| + M.get_name (| globals, "coinbase_balance_after_mining_fee" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, "set_account_balance" |), + make_list [ + M.get_field (| M.get_name (| globals, "env" |), "state" |); + M.get_field (| M.get_name (| globals, "env" |), "coinbase" |); + M.get_name (| globals, "coinbase_balance_after_mining_fee" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, "account_exists_and_is_empty" |), + make_list [ + M.get_field (| M.get_name (| globals, "env" |), "state" |); + M.get_field (| M.get_name (| globals, "env" |), "coinbase" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, "destroy_account" |), + make_list [ + M.get_field (| M.get_name (| globals, "env" |), "state" |); + M.get_field (| M.get_name (| globals, "env" |), "coinbase" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )) |) in + let _ := + M.for_ (| + M.get_name (| globals, "address" |), + M.get_field (| M.get_name (| globals, "output" |), "accounts_to_delete" |), + ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, "destroy_account" |), + make_list [ + M.get_field (| M.get_name (| globals, "env" |), "state" |); + M.get_name (| globals, "address" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := + M.for_ (| + M.get_name (| globals, "address" |), + M.get_field (| M.get_name (| globals, "output" |), "touched_accounts" |), + ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, "account_exists_and_is_empty" |), + make_list [ + M.get_field (| M.get_name (| globals, "env" |), "state" |); + M.get_name (| globals, "address" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, "destroy_account" |), + make_list [ + M.get_field (| M.get_name (| globals, "env" |), "state" |); + M.get_name (| globals, "address" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := M.return_ (| + make_tuple [ M.get_name (| globals, "total_gas_used" |); M.get_field (| M.get_name (| globals, "output" |), "logs" |); M.get_field (| M.get_name (| globals, "output" |), "error" |) ] + |) in + M.pure Constant.None_)). + +Definition validate_transaction : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "tx" ] |) in + let _ := Constant.str " + Verifies a transaction. + + The gas in a transaction gets used to pay for the intrinsic cost of + operations, therefore if there is insufficient gas then it would not + be possible to execute a transaction and it will be declared invalid. + + Additionally, the nonce of a transaction must not equal or exceed the + limit defined in `EIP-2681 `_. + In practice, defining the limit as ``2**64-1`` has no impact because + sending ``2**64-1`` transactions is improbable. It's not strictly + impossible though, ``2**64-1`` transactions is the entire capacity of the + Ethereum blockchain at 2022 gas limits for a little over 22 years. + + Parameters + ---------- + tx : + Transaction to validate. + + Returns + ------- + verified : `bool` + True if the transaction can be executed, or False otherwise. + " in + let _ := M.return_ (| + BoolOp.and (| + Compare.lt_e (| + M.call (| + M.get_name (| globals, "calculate_intrinsic_cost" |), + make_list [ + M.get_name (| globals, "tx" |) + ], + make_dict [] + |), + M.get_field (| M.get_name (| globals, "tx" |), "gas" |) + |), + ltac:(M.monadic ( + Compare.lt (| + M.get_field (| M.get_name (| globals, "tx" |), "nonce" |), + BinOp.sub (| + BinOp.pow (| + Constant.int 2, + Constant.int 64 + |), + Constant.int 1 + |) + |) + )) + |) + |) in + M.pure Constant.None_)). + +Definition calculate_intrinsic_cost : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "tx" ] |) in + let _ := Constant.str " + Calculates the gas that is charged before execution is started. + + The intrinsic cost of the transaction is charged before execution has + begun. Functions/operations in the EVM cost money to execute so this + intrinsic cost is for the operations that need to be paid for as part of + the transaction. Data transfer, for example, is part of this intrinsic + cost. It costs ether to send data over the wire and that ether is + accounted for in the intrinsic cost calculated in this function. This + intrinsic cost must be calculated and paid for before execution in order + for all operations to be implemented. + + Parameters + ---------- + tx : + Transaction to compute the intrinsic cost of. + + Returns + ------- + verified : `ethereum.base_types.Uint` + The intrinsic cost of the transaction. + " in + let _ := M.assign_local (| + "data_cost" , + Constant.int 0 + |) in + let _ := + M.for_ (| + M.get_name (| globals, "byte" |), + M.get_field (| M.get_name (| globals, "tx" |), "data" |), + ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, "byte" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_op_local (| + BinOp.add, + "data_cost", + M.get_name (| globals, "TX_DATA_COST_PER_ZERO" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_op_local (| + BinOp.add, + "data_cost", + M.get_name (| globals, "TX_DATA_COST_PER_NON_ZERO" |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_field (| M.get_name (| globals, "tx" |), "to" |), + M.call (| + M.get_name (| globals, "Bytes0" |), + make_list [ + Constant.bytes "" + ], + make_dict [] + |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "create_cost" , + M.get_name (| globals, "TX_CREATE_COST" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "create_cost" , + Constant.int 0 + |) in + M.pure Constant.None_ + )) |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + BinOp.add (| + BinOp.add (| + M.get_name (| globals, "TX_BASE_COST" |), + M.get_name (| globals, "data_cost" |) + |), + M.get_name (| globals, "create_cost" |) + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Definition recover_sender : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "chain_id"; "tx" ] |) in + let _ := Constant.str " + Extracts the sender address from a transaction. + + The v, r, and s values are the three parts that make up the signature + of a transaction. In order to recover the sender of a transaction the two + components needed are the signature (``v``, ``r``, and ``s``) and the + signing hash of the transaction. The sender's public key can be obtained + with these two values and therefore the sender address can be retrieved. + + Parameters + ---------- + tx : + Transaction of interest. + chain_id : + ID of the executing chain. + + Returns + ------- + sender : `ethereum.fork_types.Address` + The address of the account that signed the transaction. + " in + let _ := M.assign (| + make_tuple [ M.get_name (| globals, "v" |); M.get_name (| globals, "r" |); M.get_name (| globals, "s" |) ], + make_tuple [ M.get_field (| M.get_name (| globals, "tx" |), "v" |); M.get_field (| M.get_name (| globals, "tx" |), "r" |); M.get_field (| M.get_name (| globals, "tx" |), "s" |) ] + |) in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + BoolOp.and (| + Compare.lt (| + Constant.int 0, + M.get_name (| globals, "r" |) + |), + ltac:(M.monadic ( + Compare.lt (| + M.get_name (| globals, "r" |), + M.get_name (| globals, "SECP256K1N" |) + |) + )) + |); + M.get_name (| globals, "InvalidBlock" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + BoolOp.and (| + Compare.lt (| + Constant.int 0, + M.get_name (| globals, "s" |) + |), + ltac:(M.monadic ( + Compare.lt_e (| + M.get_name (| globals, "s" |), + BinOp.floor_div (| + M.get_name (| globals, "SECP256K1N" |), + Constant.int 2 + |) + |) + )) + |); + M.get_name (| globals, "InvalidBlock" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + BoolOp.or (| + Compare.eq (| + M.get_name (| globals, "v" |), + Constant.int 27 + |), + ltac:(M.monadic ( + Compare.eq (| + M.get_name (| globals, "v" |), + Constant.int 28 + |) + )) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "public_key" , + M.call (| + M.get_name (| globals, "secp256k1_recover" |), + make_list [ + M.get_name (| globals, "r" |); + M.get_name (| globals, "s" |); + BinOp.sub (| + M.get_name (| globals, "v" |), + Constant.int 27 + |); + M.call (| + M.get_name (| globals, "signing_hash_pre155" |), + make_list [ + M.get_name (| globals, "tx" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + BoolOp.or (| + Compare.eq (| + M.get_name (| globals, "v" |), + BinOp.add (| + Constant.int 35, + BinOp.mult (| + M.get_name (| globals, "chain_id" |), + Constant.int 2 + |) + |) + |), + ltac:(M.monadic ( + Compare.eq (| + M.get_name (| globals, "v" |), + BinOp.add (| + Constant.int 36, + BinOp.mult (| + M.get_name (| globals, "chain_id" |), + Constant.int 2 + |) + |) + |) + )) + |); + M.get_name (| globals, "InvalidBlock" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "public_key" , + M.call (| + M.get_name (| globals, "secp256k1_recover" |), + make_list [ + M.get_name (| globals, "r" |); + M.get_name (| globals, "s" |); + BinOp.sub (| + BinOp.sub (| + M.get_name (| globals, "v" |), + Constant.int 35 + |), + BinOp.mult (| + M.get_name (| globals, "chain_id" |), + Constant.int 2 + |) + |); + M.call (| + M.get_name (| globals, "signing_hash_155" |), + make_list [ + M.get_name (| globals, "tx" |); + M.get_name (| globals, "chain_id" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + )) |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, "Address" |), + make_list [ + M.slice (| + M.call (| + M.get_name (| globals, "keccak256" |), + make_list [ + M.get_name (| globals, "public_key" |) + ], + make_dict [] + |), + Constant.int 12, + Constant.int 32, + Constant.None_ + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Definition signing_hash_pre155 : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "tx" ] |) in + let _ := Constant.str " + Compute the hash of a transaction used in a legacy (pre EIP 155) signature. + + Parameters + ---------- + tx : + Transaction of interest. + + Returns + ------- + hash : `ethereum.crypto.hash.Hash32` + Hash of the transaction. + " in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, "keccak256" |), + make_list [ + M.call (| + M.get_field (| M.get_name (| globals, "rlp" |), "encode" |), + make_list [ + make_tuple [ M.get_field (| M.get_name (| globals, "tx" |), "nonce" |); M.get_field (| M.get_name (| globals, "tx" |), "gas_price" |); M.get_field (| M.get_name (| globals, "tx" |), "gas" |); M.get_field (| M.get_name (| globals, "tx" |), "to" |); M.get_field (| M.get_name (| globals, "tx" |), "value" |); M.get_field (| M.get_name (| globals, "tx" |), "data" |) ] + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Definition signing_hash_155 : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "tx"; "chain_id" ] |) in + let _ := Constant.str " + Compute the hash of a transaction used in a EIP 155 signature. + + Parameters + ---------- + tx : + Transaction of interest. + chain_id : + The id of the current chain. + + Returns + ------- + hash : `ethereum.crypto.hash.Hash32` + Hash of the transaction. + " in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, "keccak256" |), + make_list [ + M.call (| + M.get_field (| M.get_name (| globals, "rlp" |), "encode" |), + make_list [ + make_tuple [ M.get_field (| M.get_name (| globals, "tx" |), "nonce" |); M.get_field (| M.get_name (| globals, "tx" |), "gas_price" |); M.get_field (| M.get_name (| globals, "tx" |), "gas" |); M.get_field (| M.get_name (| globals, "tx" |), "to" |); M.get_field (| M.get_name (| globals, "tx" |), "value" |); M.get_field (| M.get_name (| globals, "tx" |), "data" |); M.get_name (| globals, "chain_id" |); M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |); M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) ] + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Definition compute_header_hash : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "header" ] |) in + let _ := Constant.str " + Computes the hash of a block header. + + The header hash of a block is the canonical hash that is used to refer + to a specific block and completely distinguishes a block from another. + + ``keccak256`` is a function that produces a 256 bit hash of any input. + It also takes in any number of bytes as an input and produces a single + hash for them. A hash is a completely unique output for a single input. + So an input corresponds to one unique hash that can be used to identify + the input exactly. + + Prior to using the ``keccak256`` hash function, the header must be + encoded using the Recursive-Length Prefix. See :ref:`rlp`. + RLP encoding the header converts it into a space-efficient format that + allows for easy transfer of data between nodes. The purpose of RLP is to + encode arbitrarily nested arrays of binary data, and RLP is the primary + encoding method used to serialize objects in Ethereum's execution layer. + The only purpose of RLP is to encode structure; encoding specific data + types (e.g. strings, floats) is left up to higher-order protocols. + + Parameters + ---------- + header : + Header of interest. + + Returns + ------- + hash : `ethereum.crypto.hash.Hash32` + Hash of the header. + " in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, "keccak256" |), + make_list [ + M.call (| + M.get_field (| M.get_name (| globals, "rlp" |), "encode" |), + make_list [ + M.get_name (| globals, "header" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Definition check_gas_limit : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "gas_limit"; "parent_gas_limit" ] |) in + let _ := Constant.str " + Validates the gas limit for a block. + + The bounds of the gas limit, ``max_adjustment_delta``, is set as the + quotient of the parent block's gas limit and the + ``GAS_LIMIT_ADJUSTMENT_FACTOR``. Therefore, if the gas limit that is + passed through as a parameter is greater than or equal to the *sum* of + the parent's gas and the adjustment delta then the limit for gas is too + high and fails this function's check. Similarly, if the limit is less + than or equal to the *difference* of the parent's gas and the adjustment + delta *or* the predefined ``GAS_LIMIT_MINIMUM`` then this function's + check fails because the gas limit doesn't allow for a sufficient or + reasonable amount of gas to be used on a block. + + Parameters + ---------- + gas_limit : + Gas limit to validate. + + parent_gas_limit : + Gas limit of the parent block. + + Returns + ------- + check : `bool` + True if gas limit constraints are satisfied, False otherwise. + " in + let _ := M.assign_local (| + "max_adjustment_delta" , + BinOp.floor_div (| + M.get_name (| globals, "parent_gas_limit" |), + M.get_name (| globals, "GAS_LIMIT_ADJUSTMENT_FACTOR" |) + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.gt_e (| + M.get_name (| globals, "gas_limit" |), + BinOp.add (| + M.get_name (| globals, "parent_gas_limit" |), + M.get_name (| globals, "max_adjustment_delta" |) + |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + Constant.bool false + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + Compare.lt_e (| + M.get_name (| globals, "gas_limit" |), + BinOp.sub (| + M.get_name (| globals, "parent_gas_limit" |), + M.get_name (| globals, "max_adjustment_delta" |) + |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + Constant.bool false + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + Compare.lt (| + M.get_name (| globals, "gas_limit" |), + M.get_name (| globals, "GAS_LIMIT_MINIMUM" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + Constant.bool false + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.return_ (| + Constant.bool true + |) in + M.pure Constant.None_)). + +Definition calculate_block_difficulty : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "block_number"; "block_timestamp"; "parent_timestamp"; "parent_difficulty"; "parent_has_ommers" ] |) in + let _ := Constant.str " + Computes difficulty of a block using its header and parent header. + + The difficulty is determined by the time the block was created after its + parent. The ``offset`` is calculated using the parent block's difficulty, + ``parent_difficulty``, and the timestamp between blocks. This offset is + then added to the parent difficulty and is stored as the ``difficulty`` + variable. If the time between the block and its parent is too short, the + offset will result in a positive number thus making the sum of + ``parent_difficulty`` and ``offset`` to be a greater value in order to + avoid mass forking. But, if the time is long enough, then the offset + results in a negative value making the block less difficult than + its parent. + + The base standard for a block's difficulty is the predefined value + set for the genesis block since it has no parent. So, a block + can't be less difficult than the genesis block, therefore each block's + difficulty is set to the maximum value between the calculated + difficulty and the ``GENESIS_DIFFICULTY``. + + Parameters + ---------- + block_number : + Block number of the block. + block_timestamp : + Timestamp of the block. + parent_timestamp : + Timestamp of the parent block. + parent_difficulty : + difficulty of the parent block. + parent_has_ommers: + does the parent have ommers. + + Returns + ------- + difficulty : `ethereum.base_types.Uint` + Computed difficulty for a block. + " in + let _ := M.assign_local (| + "offset" , + BinOp.mult (| + BinOp.floor_div (| + M.call (| + M.get_name (| globals, "int" |), + make_list [ + M.get_name (| globals, "parent_difficulty" |) + ], + make_dict [] + |), + Constant.int 2048 + |), + M.call (| + M.get_name (| globals, "max" |), + make_list [ + BinOp.sub (| + (* if *) + M.if_then_else (| + M.get_name (| globals, "parent_has_ommers" |), + (* then *) + ltac:(M.monadic ( +Constant.int 2 + (* else *) + )), ltac:(M.monadic ( +Constant.int 1 + )) |), + BinOp.floor_div (| + M.call (| + M.get_name (| globals, "int" |), + make_list [ + BinOp.sub (| + M.get_name (| globals, "block_timestamp" |), + M.get_name (| globals, "parent_timestamp" |) + |) + ], + make_dict [] + |), + Constant.int 9 + |) + |); + UnOp.sub (| Constant.int 99 |) + ], + make_dict [] + |) + |) + |) in + let _ := M.assign_local (| + "difficulty" , + BinOp.add (| + M.call (| + M.get_name (| globals, "int" |), + make_list [ + M.get_name (| globals, "parent_difficulty" |) + ], + make_dict [] + |), + M.get_name (| globals, "offset" |) + |) + |) in + let _ := M.assign_local (| + "num_bomb_periods" , + BinOp.sub (| + BinOp.floor_div (| + BinOp.sub (| + M.call (| + M.get_name (| globals, "int" |), + make_list [ + M.get_name (| globals, "block_number" |) + ], + make_dict [] + |), + M.get_name (| globals, "BOMB_DELAY_BLOCKS" |) + |), + Constant.int 100000 + |), + Constant.int 2 + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.gt_e (| + M.get_name (| globals, "num_bomb_periods" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_op_local (| + BinOp.add, + "difficulty", + BinOp.pow (| + Constant.int 2, + M.get_name (| globals, "num_bomb_periods" |) + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, "max" |), + make_list [ + M.get_name (| globals, "difficulty" |); + M.get_name (| globals, "MINIMUM_DIFFICULTY" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). diff --git a/CoqOfPython/ethereum/byzantium/fork_types.v b/CoqOfPython/ethereum/byzantium/fork_types.v new file mode 100644 index 0000000..b564ee7 --- /dev/null +++ b/CoqOfPython/ethereum/byzantium/fork_types.v @@ -0,0 +1,98 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.byzantium.fork_types". + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Types +^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Types re-used throughout the specification, which are specific to Ethereum. +". + +Axiom dataclasses_imports_dataclass : + IsImported globals "dataclasses" "dataclass". + +Axiom ethereum_imports_rlp : + IsImported globals "ethereum" "rlp". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_Bytes : + IsImported globals "ethereum.base_types" "Bytes". +Axiom ethereum_base_types_imports_Bytes20 : + IsImported globals "ethereum.base_types" "Bytes20". +Axiom ethereum_base_types_imports_Bytes256 : + IsImported globals "ethereum.base_types" "Bytes256". +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". +Axiom ethereum_base_types_imports_slotted_freezable : + IsImported globals "ethereum.base_types" "slotted_freezable". + +Axiom ethereum_crypto_hash_imports_Hash32 : + IsImported globals "ethereum.crypto.hash" "Hash32". +Axiom ethereum_crypto_hash_imports_keccak256 : + IsImported globals "ethereum.crypto.hash" "keccak256". + +Definition Address : Value.t := M.run ltac:(M.monadic ( + M.get_name (| globals, "Bytes20" |) +)). + +Definition Root : Value.t := M.run ltac:(M.monadic ( + M.get_name (| globals, "Hash32" |) +)). + +Definition Bloom : Value.t := M.run ltac:(M.monadic ( + M.get_name (| globals, "Bytes256" |) +)). + +Definition Account : Value.t := + builtins.make_klass + [] + [ + + ] + [ + + ]. + +Definition EMPTY_ACCOUNT : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Account" |), + make_list [], + make_dict [] + |) +)). + +Definition encode_account : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "raw_account_data"; "storage_root" ] |) in + let _ := Constant.str " + Encode `Account` dataclass. + + Storage is not stored in the `Account` dataclass, so `Accounts` cannot be + encoded with providing a storage root. + " in + let _ := M.return_ (| + M.call (| + M.get_field (| M.get_name (| globals, "rlp" |), "encode" |), + make_list [ + make_tuple [ M.get_field (| M.get_name (| globals, "raw_account_data" |), "nonce" |); M.get_field (| M.get_name (| globals, "raw_account_data" |), "balance" |); M.get_name (| globals, "storage_root" |); M.call (| + M.get_name (| globals, "keccak256" |), + make_list [ + M.get_field (| M.get_name (| globals, "raw_account_data" |), "code" |) + ], + make_dict [] + |) ] + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). diff --git a/CoqOfPython/ethereum/byzantium/state.v b/CoqOfPython/ethereum/byzantium/state.v new file mode 100644 index 0000000..525fbd8 --- /dev/null +++ b/CoqOfPython/ethereum/byzantium/state.v @@ -0,0 +1,1111 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.byzantium.state". + +Definition expr_1 : Value.t := + Constant.str " +State +^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +The state contains all information that is preserved between transactions. + +It consists of a main account trie and storage tries for each contract. + +There is a distinction between an account that does not exist and +`EMPTY_ACCOUNT`. +". + +Axiom dataclasses_imports_dataclass : + IsImported globals "dataclasses" "dataclass". +Axiom dataclasses_imports_field : + IsImported globals "dataclasses" "field". + +Axiom typing_imports_Callable : + IsImported globals "typing" "Callable". +Axiom typing_imports_Dict : + IsImported globals "typing" "Dict". +Axiom typing_imports_List : + IsImported globals "typing" "List". +Axiom typing_imports_Optional : + IsImported globals "typing" "Optional". +Axiom typing_imports_Tuple : + IsImported globals "typing" "Tuple". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_Bytes : + IsImported globals "ethereum.base_types" "Bytes". +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". +Axiom ethereum_base_types_imports_modify : + IsImported globals "ethereum.base_types" "modify". + +Axiom ethereum_utils_ensure_imports_ensure : + IsImported globals "ethereum.utils.ensure" "ensure". + +Axiom ethereum_byzantium_fork_types_imports_EMPTY_ACCOUNT : + IsImported globals "ethereum.byzantium.fork_types" "EMPTY_ACCOUNT". +Axiom ethereum_byzantium_fork_types_imports_Account : + IsImported globals "ethereum.byzantium.fork_types" "Account". +Axiom ethereum_byzantium_fork_types_imports_Address : + IsImported globals "ethereum.byzantium.fork_types" "Address". +Axiom ethereum_byzantium_fork_types_imports_Root : + IsImported globals "ethereum.byzantium.fork_types" "Root". + +Axiom ethereum_byzantium_trie_imports_EMPTY_TRIE_ROOT : + IsImported globals "ethereum.byzantium.trie" "EMPTY_TRIE_ROOT". +Axiom ethereum_byzantium_trie_imports_Trie : + IsImported globals "ethereum.byzantium.trie" "Trie". +Axiom ethereum_byzantium_trie_imports_copy_trie : + IsImported globals "ethereum.byzantium.trie" "copy_trie". +Axiom ethereum_byzantium_trie_imports_root : + IsImported globals "ethereum.byzantium.trie" "root". +Axiom ethereum_byzantium_trie_imports_trie_get : + IsImported globals "ethereum.byzantium.trie" "trie_get". +Axiom ethereum_byzantium_trie_imports_trie_set : + IsImported globals "ethereum.byzantium.trie" "trie_set". + +Definition State : Value.t := + builtins.make_klass + [] + [ + + ] + [ + + ]. + +Definition close_state : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "state" ] |) in + let _ := Constant.str " + Free resources held by the state. Used by optimized implementations to + release file descriptors. + " in + let _ := M.delete (| M.get_field (| M.get_name (| globals, "state" |), "_main_trie" |) |) in + let _ := M.delete (| M.get_field (| M.get_name (| globals, "state" |), "_storage_tries" |) |) in + let _ := M.delete (| M.get_field (| M.get_name (| globals, "state" |), "_snapshots" |) |) in + M.pure Constant.None_)). + +Definition begin_transaction : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "state" ] |) in + let _ := Constant.str " + Start a state transaction. + + Transactions are entirely implicit and can be nested. It is not possible to + calculate the state root during a transaction. + + Parameters + ---------- + state : State + The state. + " in + let _ := M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, "state" |), "_snapshots" |), "append" |), + make_list [ + make_tuple [ M.call (| + M.get_name (| globals, "copy_trie" |), + make_list [ + M.get_field (| M.get_name (| globals, "state" |), "_main_trie" |) + ], + make_dict [] + |); Constant.str "(* At expr: unsupported node type: DictComp *)" ] + ], + make_dict [] + |) in + M.pure Constant.None_)). + +Definition commit_transaction : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "state" ] |) in + let _ := Constant.str " + Commit a state transaction. + + Parameters + ---------- + state : State + The state. + " in + let _ := M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, "state" |), "_snapshots" |), "pop" |), + make_list [], + make_dict [] + |) in + M.pure Constant.None_)). + +Definition rollback_transaction : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "state" ] |) in + let _ := Constant.str " + Rollback a state transaction, resetting the state to the point when the + corresponding `start_transaction()` call was made. + + Parameters + ---------- + state : State + The state. + " in + let _ := M.assign (| + make_tuple [ M.get_field (| M.get_name (| globals, "state" |), "_main_trie" |); M.get_field (| M.get_name (| globals, "state" |), "_storage_tries" |) ], + M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, "state" |), "_snapshots" |), "pop" |), + make_list [], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Definition get_account : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "state"; "address" ] |) in + let _ := Constant.str " + Get the `Account` object at an address. Returns `EMPTY_ACCOUNT` if there + is no account at the address. + + Use `get_account_optional()` if you care about the difference between a + non-existent account and `EMPTY_ACCOUNT`. + + Parameters + ---------- + state: `State` + The state + address : `Address` + Address to lookup. + + Returns + ------- + account : `Account` + Account at address. + " in + let _ := M.assign_local (| + "account" , + M.call (| + M.get_name (| globals, "get_account_optional" |), + make_list [ + M.get_name (| globals, "state" |); + M.get_name (| globals, "address" |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, "isinstance" |), + make_list [ + M.get_name (| globals, "account" |); + M.get_name (| globals, "Account" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + M.get_name (| globals, "account" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.return_ (| + M.get_name (| globals, "EMPTY_ACCOUNT" |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_)). + +Definition get_account_optional : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "state"; "address" ] |) in + let _ := Constant.str " + Get the `Account` object at an address. Returns `None` (rather than + `EMPTY_ACCOUNT`) if there is no account at the address. + + Parameters + ---------- + state: `State` + The state + address : `Address` + Address to lookup. + + Returns + ------- + account : `Account` + Account at address. + " in + let _ := M.assign_local (| + "account" , + M.call (| + M.get_name (| globals, "trie_get" |), + make_list [ + M.get_field (| M.get_name (| globals, "state" |), "_main_trie" |); + M.get_name (| globals, "address" |) + ], + make_dict [] + |) + |) in + let _ := M.return_ (| + M.get_name (| globals, "account" |) + |) in + M.pure Constant.None_)). + +Definition set_account : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "state"; "address"; "account" ] |) in + let _ := Constant.str " + Set the `Account` object at an address. Setting to `None` deletes + the account (but not its storage, see `destroy_account()`). + + Parameters + ---------- + state: `State` + The state + address : `Address` + Address to set. + account : `Account` + Account to set at address. + " in + let _ := M.call (| + M.get_name (| globals, "trie_set" |), + make_list [ + M.get_field (| M.get_name (| globals, "state" |), "_main_trie" |); + M.get_name (| globals, "address" |); + M.get_name (| globals, "account" |) + ], + make_dict [] + |) in + M.pure Constant.None_)). + +Definition destroy_account : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "state"; "address" ] |) in + let _ := Constant.str " + Completely remove the account at `address` and all of its storage. + + This function is made available exclusively for the `SELFDESTRUCT` + opcode. It is expected that `SELFDESTRUCT` will be disabled in a future + hardfork and this function will be removed. + + Parameters + ---------- + state: `State` + The state + address : `Address` + Address of account to destroy. + " in + let _ := M.call (| + M.get_name (| globals, "destroy_storage" |), + make_list [ + M.get_name (| globals, "state" |); + M.get_name (| globals, "address" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "set_account" |), + make_list [ + M.get_name (| globals, "state" |); + M.get_name (| globals, "address" |); + Constant.None_ + ], + make_dict [] + |) in + M.pure Constant.None_)). + +Definition destroy_storage : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "state"; "address" ] |) in + let _ := Constant.str " + Completely remove the storage at `address`. + + Parameters + ---------- + state: `State` + The state + address : `Address` + Address of account whose storage is to be deleted. + " in + let _ := + (* if *) + M.if_then_else (| + Compare.in_ (| + M.get_name (| globals, "address" |), + M.get_field (| M.get_name (| globals, "state" |), "_storage_tries" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.delete (| M.get_subscript (| + M.get_field (| M.get_name (| globals, "state" |), "_storage_tries" |), + M.get_name (| globals, "address" |) + |) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + M.pure Constant.None_)). + +Definition get_storage : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "state"; "address"; "key" ] |) in + let _ := Constant.str " + Get a value at a storage key on an account. Returns `U256(0)` if the + storage key has not been set previously. + + Parameters + ---------- + state: `State` + The state + address : `Address` + Address of the account. + key : `Bytes` + Key to lookup. + + Returns + ------- + value : `U256` + Value at the key. + " in + let _ := M.assign_local (| + "trie" , + M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, "state" |), "_storage_tries" |), "get" |), + make_list [ + M.get_name (| globals, "address" |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.is (| + M.get_name (| globals, "trie" |), + Constant.None_ + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "value" , + M.call (| + M.get_name (| globals, "trie_get" |), + make_list [ + M.get_name (| globals, "trie" |); + M.get_name (| globals, "key" |) + ], + make_dict [] + |) + |) in + let _ := M.assert (| M.call (| + M.get_name (| globals, "isinstance" |), + make_list [ + M.get_name (| globals, "value" |); + M.get_name (| globals, "U256" |) + ], + make_dict [] + |) |) in + let _ := M.return_ (| + M.get_name (| globals, "value" |) + |) in + M.pure Constant.None_)). + +Definition set_storage : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "state"; "address"; "key"; "value" ] |) in + let _ := Constant.str " + Set a value at a storage key on an account. Setting to `U256(0)` deletes + the key. + + Parameters + ---------- + state: `State` + The state + address : `Address` + Address of the account. + key : `Bytes` + Key to set. + value : `U256` + Value to set at the key. + " in + let _ := M.assert (| Compare.is_not (| + M.call (| + M.get_name (| globals, "trie_get" |), + make_list [ + M.get_field (| M.get_name (| globals, "state" |), "_main_trie" |); + M.get_name (| globals, "address" |) + ], + make_dict [] + |), + Constant.None_ + |) |) in + let _ := M.assign_local (| + "trie" , + M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, "state" |), "_storage_tries" |), "get" |), + make_list [ + M.get_name (| globals, "address" |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.is (| + M.get_name (| globals, "trie" |), + Constant.None_ + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "trie" , + M.call (| + M.get_name (| globals, "Trie" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.assign (| + M.get_subscript (| + M.get_field (| M.get_name (| globals, "state" |), "_storage_tries" |), + M.get_name (| globals, "address" |) + |), + M.get_name (| globals, "trie" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.call (| + M.get_name (| globals, "trie_set" |), + make_list [ + M.get_name (| globals, "trie" |); + M.get_name (| globals, "key" |); + M.get_name (| globals, "value" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_field (| M.get_name (| globals, "trie" |), "_data" |), + Constant.str "(* At expr: unsupported node type: Dict *)" + |), + (* then *) + ltac:(M.monadic ( + let _ := M.delete (| M.get_subscript (| + M.get_field (| M.get_name (| globals, "state" |), "_storage_tries" |), + M.get_name (| globals, "address" |) + |) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + M.pure Constant.None_)). + +Definition storage_root : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "state"; "address" ] |) in + let _ := Constant.str " + Calculate the storage root of an account. + + Parameters + ---------- + state: + The state + address : + Address of the account. + + Returns + ------- + root : `Root` + Storage root of the account. + " in + let _ := M.assert (| UnOp.not (| M.get_field (| M.get_name (| globals, "state" |), "_snapshots" |) |) |) in + let _ := + (* if *) + M.if_then_else (| + Compare.in_ (| + M.get_name (| globals, "address" |), + M.get_field (| M.get_name (| globals, "state" |), "_storage_tries" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + M.call (| + M.get_name (| globals, "root" |), + make_list [ + M.get_subscript (| + M.get_field (| M.get_name (| globals, "state" |), "_storage_tries" |), + M.get_name (| globals, "address" |) + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.return_ (| + M.get_name (| globals, "EMPTY_TRIE_ROOT" |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_)). + +Definition state_root : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "state" ] |) in + let _ := Constant.str " + Calculate the state root. + + Parameters + ---------- + state: + The current state. + + Returns + ------- + root : `Root` + The state root. + " in + let _ := M.assert (| UnOp.not (| M.get_field (| M.get_name (| globals, "state" |), "_snapshots" |) |) |) in +(* At stmt: unsupported node type: FunctionDef *) + let _ := M.return_ (| + M.call (| + M.get_name (| globals, "root" |), + make_list [ + M.get_field (| M.get_name (| globals, "state" |), "_main_trie" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Definition account_exists : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "state"; "address" ] |) in + let _ := Constant.str " + Checks if an account exists in the state trie + + Parameters + ---------- + state: + The state + address: + Address of the account that needs to be checked. + + Returns + ------- + account_exists : `bool` + True if account exists in the state trie, False otherwise + " in + let _ := M.return_ (| + Compare.is_not (| + M.call (| + M.get_name (| globals, "get_account_optional" |), + make_list [ + M.get_name (| globals, "state" |); + M.get_name (| globals, "address" |) + ], + make_dict [] + |), + Constant.None_ + |) + |) in + M.pure Constant.None_)). + +Definition account_has_code_or_nonce : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "state"; "address" ] |) in + let _ := Constant.str " + Checks if an account has non zero nonce or non empty code + + Parameters + ---------- + state: + The state + address: + Address of the account that needs to be checked. + + Returns + ------- + has_code_or_nonce : `bool` + True if if an account has non zero nonce or non empty code, + False otherwise. + " in + let _ := M.assign_local (| + "account" , + M.call (| + M.get_name (| globals, "get_account" |), + make_list [ + M.get_name (| globals, "state" |); + M.get_name (| globals, "address" |) + ], + make_dict [] + |) + |) in + let _ := M.return_ (| + BoolOp.or (| + Compare.not_eq (| + M.get_field (| M.get_name (| globals, "account" |), "nonce" |), + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + |), + ltac:(M.monadic ( + Compare.not_eq (| + M.get_field (| M.get_name (| globals, "account" |), "code" |), + Constant.bytes "" + |) + )) + |) + |) in + M.pure Constant.None_)). + +Definition is_account_empty : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "state"; "address" ] |) in + let _ := Constant.str " + Checks if an account has zero nonce, empty code and zero balance. + + Parameters + ---------- + state: + The state + address: + Address of the account that needs to be checked. + + Returns + ------- + is_empty : `bool` + True if if an account has zero nonce, empty code and zero balance, + False otherwise. + " in + let _ := M.assign_local (| + "account" , + M.call (| + M.get_name (| globals, "get_account" |), + make_list [ + M.get_name (| globals, "state" |); + M.get_name (| globals, "address" |) + ], + make_dict [] + |) + |) in + let _ := M.return_ (| + BoolOp.and (| + Compare.eq (| + M.get_field (| M.get_name (| globals, "account" |), "nonce" |), + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + |), + ltac:(M.monadic ( + BoolOp.and (| + Compare.eq (| + M.get_field (| M.get_name (| globals, "account" |), "code" |), + Constant.bytes "" + |), + ltac:(M.monadic ( + Compare.eq (| + M.get_field (| M.get_name (| globals, "account" |), "balance" |), + Constant.int 0 + |) + )) + |) + )) + |) + |) in + M.pure Constant.None_)). + +Definition account_exists_and_is_empty : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "state"; "address" ] |) in + let _ := Constant.str " + Checks if an account exists and has zero nonce, empty code and zero + balance. + + Parameters + ---------- + state: + The state + address: + Address of the account that needs to be checked. + + Returns + ------- + exists_and_is_empty : `bool` + True if an account exists and has zero nonce, empty code and zero + balance, False otherwise. + " in + let _ := M.assign_local (| + "account" , + M.call (| + M.get_name (| globals, "get_account_optional" |), + make_list [ + M.get_name (| globals, "state" |); + M.get_name (| globals, "address" |) + ], + make_dict [] + |) + |) in + let _ := M.return_ (| + BoolOp.and (| + Compare.is_not (| + M.get_name (| globals, "account" |), + Constant.None_ + |), + ltac:(M.monadic ( + BoolOp.and (| + Compare.eq (| + M.get_field (| M.get_name (| globals, "account" |), "nonce" |), + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + |), + ltac:(M.monadic ( + BoolOp.and (| + Compare.eq (| + M.get_field (| M.get_name (| globals, "account" |), "code" |), + Constant.bytes "" + |), + ltac:(M.monadic ( + Compare.eq (| + M.get_field (| M.get_name (| globals, "account" |), "balance" |), + Constant.int 0 + |) + )) + |) + )) + |) + )) + |) + |) in + M.pure Constant.None_)). + +Definition is_account_alive : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "state"; "address" ] |) in + let _ := Constant.str " + Check whether is an account is both in the state and non empty. + + Parameters + ---------- + state: + The state + address: + Address of the account that needs to be checked. + + Returns + ------- + is_alive : `bool` + True if the account is alive. + " in + let _ := M.assign_local (| + "account" , + M.call (| + M.get_name (| globals, "get_account_optional" |), + make_list [ + M.get_name (| globals, "state" |); + M.get_name (| globals, "address" |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.is (| + M.get_name (| globals, "account" |), + Constant.None_ + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + Constant.bool false + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.return_ (| + UnOp.not (| BoolOp.and (| + Compare.eq (| + M.get_field (| M.get_name (| globals, "account" |), "nonce" |), + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + |), + ltac:(M.monadic ( + BoolOp.and (| + Compare.eq (| + M.get_field (| M.get_name (| globals, "account" |), "code" |), + Constant.bytes "" + |), + ltac:(M.monadic ( + Compare.eq (| + M.get_field (| M.get_name (| globals, "account" |), "balance" |), + Constant.int 0 + |) + )) + |) + )) + |) |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_)). + +Definition modify_state : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "state"; "address"; "f" ] |) in + let _ := Constant.str " + Modify an `Account` in the `State`. + " in + let _ := M.call (| + M.get_name (| globals, "set_account" |), + make_list [ + M.get_name (| globals, "state" |); + M.get_name (| globals, "address" |); + M.call (| + M.get_name (| globals, "modify" |), + make_list [ + M.call (| + M.get_name (| globals, "get_account" |), + make_list [ + M.get_name (| globals, "state" |); + M.get_name (| globals, "address" |) + ], + make_dict [] + |); + M.get_name (| globals, "f" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + M.pure Constant.None_)). + +Definition move_ether : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "state"; "sender_address"; "recipient_address"; "amount" ] |) in + let _ := Constant.str " + Move funds between accounts. + " in +(* At stmt: unsupported node type: FunctionDef *) +(* At stmt: unsupported node type: FunctionDef *) + let _ := M.call (| + M.get_name (| globals, "modify_state" |), + make_list [ + M.get_name (| globals, "state" |); + M.get_name (| globals, "sender_address" |); + M.get_name (| globals, "reduce_sender_balance" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "modify_state" |), + make_list [ + M.get_name (| globals, "state" |); + M.get_name (| globals, "recipient_address" |); + M.get_name (| globals, "increase_recipient_balance" |) + ], + make_dict [] + |) in + M.pure Constant.None_)). + +Definition set_account_balance : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "state"; "address"; "amount" ] |) in + let _ := Constant.str " + Sets the balance of an account. + + Parameters + ---------- + state: + The current state. + + address: + Address of the account whose nonce needs to be incremented. + + amount: + The amount that needs to set in balance. + " in +(* At stmt: unsupported node type: FunctionDef *) + let _ := M.call (| + M.get_name (| globals, "modify_state" |), + make_list [ + M.get_name (| globals, "state" |); + M.get_name (| globals, "address" |); + M.get_name (| globals, "set_balance" |) + ], + make_dict [] + |) in + M.pure Constant.None_)). + +Definition touch_account : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "state"; "address" ] |) in + let _ := Constant.str " + Initializes an account to state. + + Parameters + ---------- + state: + The current state. + + address: + The address of the account that need to initialised. + " in + let _ := + (* if *) + M.if_then_else (| + UnOp.not (| M.call (| + M.get_name (| globals, "account_exists" |), + make_list [ + M.get_name (| globals, "state" |); + M.get_name (| globals, "address" |) + ], + make_dict [] + |) |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, "set_account" |), + make_list [ + M.get_name (| globals, "state" |); + M.get_name (| globals, "address" |); + M.get_name (| globals, "EMPTY_ACCOUNT" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + M.pure Constant.None_)). + +Definition increment_nonce : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "state"; "address" ] |) in + let _ := Constant.str " + Increments the nonce of an account. + + Parameters + ---------- + state: + The current state. + + address: + Address of the account whose nonce needs to be incremented. + " in +(* At stmt: unsupported node type: FunctionDef *) + let _ := M.call (| + M.get_name (| globals, "modify_state" |), + make_list [ + M.get_name (| globals, "state" |); + M.get_name (| globals, "address" |); + M.get_name (| globals, "increase_nonce" |) + ], + make_dict [] + |) in + M.pure Constant.None_)). + +Definition set_code : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "state"; "address"; "code" ] |) in + let _ := Constant.str " + Sets Account code. + + Parameters + ---------- + state: + The current state. + + address: + Address of the account whose code needs to be update. + + code: + The bytecode that needs to be set. + " in +(* At stmt: unsupported node type: FunctionDef *) + let _ := M.call (| + M.get_name (| globals, "modify_state" |), + make_list [ + M.get_name (| globals, "state" |); + M.get_name (| globals, "address" |); + M.get_name (| globals, "write_code" |) + ], + make_dict [] + |) in + M.pure Constant.None_)). + +Definition create_ether : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "state"; "address"; "amount" ] |) in + let _ := Constant.str " + Add newly created ether to an account. + + Parameters + ---------- + state: + The current state. + address: + Address of the account to which ether is added. + amount: + The amount of ether to be added to the account of interest. + " in +(* At stmt: unsupported node type: FunctionDef *) + let _ := M.call (| + M.get_name (| globals, "modify_state" |), + make_list [ + M.get_name (| globals, "state" |); + M.get_name (| globals, "address" |); + M.get_name (| globals, "increase_balance" |) + ], + make_dict [] + |) in + M.pure Constant.None_)). diff --git a/CoqOfPython/ethereum/byzantium/transactions.v b/CoqOfPython/ethereum/byzantium/transactions.v new file mode 100644 index 0000000..d474dfc --- /dev/null +++ b/CoqOfPython/ethereum/byzantium/transactions.v @@ -0,0 +1,56 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.byzantium.transactions". + +Definition expr_1 : Value.t := + Constant.str " +Transactions are atomic units of work created externally to Ethereum and +submitted to be executed. If Ethereum is viewed as a state machine, +transactions are the events that move between states. +". + +Axiom dataclasses_imports_dataclass : + IsImported globals "dataclasses" "dataclass". + +Axiom typing_imports_Union : + IsImported globals "typing" "Union". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_Bytes : + IsImported globals "ethereum.base_types" "Bytes". +Axiom ethereum_base_types_imports_Bytes0 : + IsImported globals "ethereum.base_types" "Bytes0". +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". +Axiom ethereum_base_types_imports_slotted_freezable : + IsImported globals "ethereum.base_types" "slotted_freezable". + +Axiom ethereum_byzantium_fork_types_imports_Address : + IsImported globals "ethereum.byzantium.fork_types" "Address". + +Definition TX_BASE_COST : Value.t := M.run ltac:(M.monadic ( + Constant.int 21000 +)). + +Definition TX_DATA_COST_PER_NON_ZERO : Value.t := M.run ltac:(M.monadic ( + Constant.int 68 +)). + +Definition TX_DATA_COST_PER_ZERO : Value.t := M.run ltac:(M.monadic ( + Constant.int 4 +)). + +Definition TX_CREATE_COST : Value.t := M.run ltac:(M.monadic ( + Constant.int 32000 +)). + +Definition Transaction : Value.t := + builtins.make_klass + [] + [ + + ] + [ + + ]. diff --git a/CoqOfPython/ethereum/byzantium/trie.v b/CoqOfPython/ethereum/byzantium/trie.v new file mode 100644 index 0000000..4999d6e --- /dev/null +++ b/CoqOfPython/ethereum/byzantium/trie.v @@ -0,0 +1,1589 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.byzantium.trie". + +Definition expr_1 : Value.t := + Constant.str " +State Trie +^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +The state trie is the structure responsible for storing +`.fork_types.Account` objects. +". + +(* At top_level_stmt: unsupported node type: Import *) + +Axiom dataclasses_imports_dataclass : + IsImported globals "dataclasses" "dataclass". +Axiom dataclasses_imports_field : + IsImported globals "dataclasses" "field". + +Axiom typing_imports_Callable : + IsImported globals "typing" "Callable". +Axiom typing_imports_Dict : + IsImported globals "typing" "Dict". +Axiom typing_imports_Generic : + IsImported globals "typing" "Generic". +Axiom typing_imports_List : + IsImported globals "typing" "List". +Axiom typing_imports_Mapping : + IsImported globals "typing" "Mapping". +Axiom typing_imports_MutableMapping : + IsImported globals "typing" "MutableMapping". +Axiom typing_imports_Optional : + IsImported globals "typing" "Optional". +Axiom typing_imports_Sequence : + IsImported globals "typing" "Sequence". +Axiom typing_imports_TypeVar : + IsImported globals "typing" "TypeVar". +Axiom typing_imports_Union : + IsImported globals "typing" "Union". +Axiom typing_imports_cast : + IsImported globals "typing" "cast". + +Axiom ethereum_crypto_hash_imports_keccak256 : + IsImported globals "ethereum.crypto.hash" "keccak256". + +Axiom ethereum_spurious_dragon_imports_trie : + IsImported globals "ethereum.spurious_dragon" "trie". + +Axiom ethereum_utils_ensure_imports_ensure : + IsImported globals "ethereum.utils.ensure" "ensure". + +Axiom ethereum_utils_hexadecimal_imports_hex_to_bytes : + IsImported globals "ethereum.utils.hexadecimal" "hex_to_bytes". + +Axiom ethereum_imports_rlp : + IsImported globals "ethereum" "rlp". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_Bytes : + IsImported globals "ethereum.base_types" "Bytes". +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". +Axiom ethereum_base_types_imports_slotted_freezable : + IsImported globals "ethereum.base_types" "slotted_freezable". + +Axiom ethereum_byzantium_blocks_imports_Receipt : + IsImported globals "ethereum.byzantium.blocks" "Receipt". + +Axiom ethereum_byzantium_fork_types_imports_Account : + IsImported globals "ethereum.byzantium.fork_types" "Account". +Axiom ethereum_byzantium_fork_types_imports_Address : + IsImported globals "ethereum.byzantium.fork_types" "Address". +Axiom ethereum_byzantium_fork_types_imports_Root : + IsImported globals "ethereum.byzantium.fork_types" "Root". +Axiom ethereum_byzantium_fork_types_imports_encode_account : + IsImported globals "ethereum.byzantium.fork_types" "encode_account". + +Axiom ethereum_byzantium_transactions_imports_Transaction : + IsImported globals "ethereum.byzantium.transactions" "Transaction". + +Definition EMPTY_TRIE_ROOT : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Root" |), + make_list [ + M.call (| + M.get_name (| globals, "hex_to_bytes" |), + make_list [ + Constant.str "56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421" + ], + make_dict [] + |) + ], + make_dict [] + |) +)). + +Definition Node : Value.t := M.run ltac:(M.monadic ( + M.get_subscript (| + M.get_name (| globals, "Union" |), + make_tuple [ M.get_name (| globals, "Account" |); M.get_name (| globals, "Bytes" |); M.get_name (| globals, "Transaction" |); M.get_name (| globals, "Receipt" |); M.get_name (| globals, "Uint" |); M.get_name (| globals, "U256" |); Constant.None_ ] + |) +)). + +Definition K : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "TypeVar" |), + make_list [ + Constant.str "K" + ], + make_dict [] + |) +)). + +Definition V : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "TypeVar" |), + make_list [ + Constant.str "V"; + M.get_subscript (| + M.get_name (| globals, "Optional" |), + M.get_name (| globals, "Account" |) + |); + M.get_subscript (| + M.get_name (| globals, "Optional" |), + M.get_name (| globals, "Bytes" |) + |); + M.get_name (| globals, "Bytes" |); + M.get_subscript (| + M.get_name (| globals, "Optional" |), + M.get_name (| globals, "Transaction" |) + |); + M.get_subscript (| + M.get_name (| globals, "Optional" |), + M.get_name (| globals, "Receipt" |) + |); + M.get_name (| globals, "Uint" |); + M.get_name (| globals, "U256" |) + ], + make_dict [] + |) +)). + +Definition LeafNode : Value.t := + builtins.make_klass + [] + [ + + ] + [ + + ]. + +Definition ExtensionNode : Value.t := + builtins.make_klass + [] + [ + + ] + [ + + ]. + +Definition BranchNode : Value.t := + builtins.make_klass + [] + [ + + ] + [ + + ]. + +Definition InternalNode : Value.t := M.run ltac:(M.monadic ( + M.get_subscript (| + M.get_name (| globals, "Union" |), + make_tuple [ M.get_name (| globals, "LeafNode" |); M.get_name (| globals, "ExtensionNode" |); M.get_name (| globals, "BranchNode" |) ] + |) +)). + +Definition encode_internal_node : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "node" ] |) in + let _ := Constant.str " + Encodes a Merkle Trie node into its RLP form. The RLP will then be + serialized into a `Bytes` and hashed unless it is less that 32 bytes + when serialized. + + This function also accepts `None`, representing the absence of a node, + which is encoded to `b""""`. + + Parameters + ---------- + node : Optional[InternalNode] + The node to encode. + + Returns + ------- + encoded : `rlp.RLP` + The node encoded as RLP. + " in +(* At stmt: unsupported node type: AnnAssign *) + let _ := + (* if *) + M.if_then_else (| + Compare.is (| + M.get_name (| globals, "node" |), + Constant.None_ + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "unencoded" , + Constant.bytes "" + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, "isinstance" |), + make_list [ + M.get_name (| globals, "node" |); + M.get_name (| globals, "LeafNode" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "unencoded" , + make_tuple [ M.call (| + M.get_name (| globals, "nibble_list_to_compact" |), + make_list [ + M.get_field (| M.get_name (| globals, "node" |), "rest_of_key" |); + Constant.bool true + ], + make_dict [] + |); M.get_field (| M.get_name (| globals, "node" |), "value" |) ] + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, "isinstance" |), + make_list [ + M.get_name (| globals, "node" |); + M.get_name (| globals, "ExtensionNode" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "unencoded" , + make_tuple [ M.call (| + M.get_name (| globals, "nibble_list_to_compact" |), + make_list [ + M.get_field (| M.get_name (| globals, "node" |), "key_segment" |); + Constant.bool false + ], + make_dict [] + |); M.get_field (| M.get_name (| globals, "node" |), "subnode" |) ] + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, "isinstance" |), + make_list [ + M.get_name (| globals, "node" |); + M.get_name (| globals, "BranchNode" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "unencoded" , + BinOp.add (| + M.get_field (| M.get_name (| globals, "node" |), "subnodes" |), + make_list [ + M.get_field (| M.get_name (| globals, "node" |), "value" |) + ] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.raise (| Some (M.call (| + M.get_name (| globals, "AssertionError" |), + make_list [ + Constant.str "(* At expr: unsupported node type: JoinedStr *)" + ], + make_dict [] + |)) |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "encoded" , + M.call (| + M.get_field (| M.get_name (| globals, "rlp" |), "encode" |), + make_list [ + M.get_name (| globals, "unencoded" |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.lt (| + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_name (| globals, "encoded" |) + ], + make_dict [] + |), + Constant.int 32 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + M.get_name (| globals, "unencoded" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.return_ (| + M.call (| + M.get_name (| globals, "keccak256" |), + make_list [ + M.get_name (| globals, "encoded" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_)). + +Definition encode_node : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "node"; "storage_root" ] |) in + let _ := Constant.str " + Encode a Node for storage in the Merkle Trie. + + Currently mostly an unimplemented stub. + " in + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, "isinstance" |), + make_list [ + M.get_name (| globals, "node" |); + M.get_name (| globals, "Account" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assert (| Compare.is_not (| + M.get_name (| globals, "storage_root" |), + Constant.None_ + |) |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, "encode_account" |), + make_list [ + M.get_name (| globals, "node" |); + M.get_name (| globals, "storage_root" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, "isinstance" |), + make_list [ + M.get_name (| globals, "node" |); + make_tuple [ M.get_name (| globals, "Transaction" |); M.get_name (| globals, "Receipt" |); M.get_name (| globals, "U256" |) ] + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + M.call (| + M.get_field (| M.get_name (| globals, "rlp" |), "encode" |), + make_list [ + M.call (| + M.get_name (| globals, "cast" |), + make_list [ + M.get_field (| M.get_name (| globals, "rlp" |), "RLP" |); + M.get_name (| globals, "node" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, "isinstance" |), + make_list [ + M.get_name (| globals, "node" |); + M.get_name (| globals, "Bytes" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + M.get_name (| globals, "node" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.return_ (| + M.call (| + M.get_field (| M.get_name (| globals, "previous_trie" |), "encode_node" |), + make_list [ + M.get_name (| globals, "node" |); + M.get_name (| globals, "storage_root" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_)). + +Definition Trie : Value.t := + builtins.make_klass + [(* At base: unsupported node type: Subscript *)] + [ + + ] + [ + + ]. + +Definition copy_trie : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "trie" ] |) in + let _ := Constant.str " + Create a copy of `trie`. Since only frozen objects may be stored in tries, + the contents are reused. + + Parameters + ---------- + trie: `Trie` + Trie to copy. + + Returns + ------- + new_trie : `Trie[K, V]` + A copy of the trie. + " in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, "Trie" |), + make_list [ + M.get_field (| M.get_name (| globals, "trie" |), "secured" |); + M.get_field (| M.get_name (| globals, "trie" |), "default" |); + M.call (| + M.get_field (| M.get_name (| globals, "copy" |), "copy" |), + make_list [ + M.get_field (| M.get_name (| globals, "trie" |), "_data" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Definition trie_set : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "trie"; "key"; "value" ] |) in + let _ := Constant.str " + Stores an item in a Merkle Trie. + + This method deletes the key if `value == trie.default`, because the Merkle + Trie represents the default value by omitting it from the trie. + + Parameters + ---------- + trie: `Trie` + Trie to store in. + key : `Bytes` + Key to lookup. + value : `V` + Node to insert at `key`. + " in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, "value" |), + M.get_field (| M.get_name (| globals, "trie" |), "default" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + Compare.in_ (| + M.get_name (| globals, "key" |), + M.get_field (| M.get_name (| globals, "trie" |), "_data" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.delete (| M.get_subscript (| + M.get_field (| M.get_name (| globals, "trie" |), "_data" |), + M.get_name (| globals, "key" |) + |) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign (| + M.get_subscript (| + M.get_field (| M.get_name (| globals, "trie" |), "_data" |), + M.get_name (| globals, "key" |) + |), + M.get_name (| globals, "value" |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_)). + +Definition trie_get : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "trie"; "key" ] |) in + let _ := Constant.str " + Gets an item from the Merkle Trie. + + This method returns `trie.default` if the key is missing. + + Parameters + ---------- + trie: + Trie to lookup in. + key : + Key to lookup. + + Returns + ------- + node : `V` + Node at `key` in the trie. + " in + let _ := M.return_ (| + M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, "trie" |), "_data" |), "get" |), + make_list [ + M.get_name (| globals, "key" |); + M.get_field (| M.get_name (| globals, "trie" |), "default" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Definition common_prefix_length : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "a"; "b" ] |) in + let _ := Constant.str " + Find the longest common prefix of two sequences. + " in + let _ := + M.for_ (| + M.get_name (| globals, "i" |), + M.call (| + M.get_name (| globals, "range" |), + make_list [ + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_name (| globals, "a" |) + ], + make_dict [] + |) + ], + make_dict [] + |), + ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + BoolOp.or (| + Compare.gt_e (| + M.get_name (| globals, "i" |), + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_name (| globals, "b" |) + ], + make_dict [] + |) + |), + ltac:(M.monadic ( + Compare.not_eq (| + M.get_subscript (| + M.get_name (| globals, "a" |), + M.get_name (| globals, "i" |) + |), + M.get_subscript (| + M.get_name (| globals, "b" |), + M.get_name (| globals, "i" |) + |) + |) + )) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + M.get_name (| globals, "i" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_name (| globals, "a" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Definition nibble_list_to_compact : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "x"; "is_leaf" ] |) in + let _ := Constant.str " + Compresses nibble-list into a standard byte array with a flag. + + A nibble-list is a list of byte values no greater than `15`. The flag is + encoded in high nibble of the highest byte. The flag nibble can be broken + down into two two-bit flags. + + Highest nibble:: + + +---+---+----------+--------+ + | _ | _ | is_leaf | parity | + +---+---+----------+--------+ + 3 2 1 0 + + + The lowest bit of the nibble encodes the parity of the length of the + remaining nibbles -- `0` when even and `1` when odd. The second lowest bit + is used to distinguish leaf and extension nodes. The other two bits are not + used. + + Parameters + ---------- + x : + Array of nibbles. + is_leaf : + True if this is part of a leaf node, or false if it is an extension + node. + + Returns + ------- + compressed : `bytearray` + Compact byte array. + " in + let _ := M.assign_local (| + "compact" , + M.call (| + M.get_name (| globals, "bytearray" |), + make_list [], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + BinOp.mod_ (| + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_name (| globals, "x" |) + ], + make_dict [] + |), + Constant.int 2 + |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_field (| M.get_name (| globals, "compact" |), "append" |), + make_list [ + BinOp.mult (| + Constant.int 16, + BinOp.mult (| + Constant.int 2, + M.get_name (| globals, "is_leaf" |) + |) + |) + ], + make_dict [] + |) in + let _ := + M.for_ (| + M.get_name (| globals, "i" |), + M.call (| + M.get_name (| globals, "range" |), + make_list [ + Constant.int 0; + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_name (| globals, "x" |) + ], + make_dict [] + |); + Constant.int 2 + ], + make_dict [] + |), + ltac:(M.monadic ( + let _ := M.call (| + M.get_field (| M.get_name (| globals, "compact" |), "append" |), + make_list [ + BinOp.add (| + BinOp.mult (| + Constant.int 16, + M.get_subscript (| + M.get_name (| globals, "x" |), + M.get_name (| globals, "i" |) + |) + |), + M.get_subscript (| + M.get_name (| globals, "x" |), + BinOp.add (| + M.get_name (| globals, "i" |), + Constant.int 1 + |) + |) + |) + ], + make_dict [] + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.call (| + M.get_field (| M.get_name (| globals, "compact" |), "append" |), + make_list [ + BinOp.add (| + BinOp.mult (| + Constant.int 16, + BinOp.add (| + BinOp.mult (| + Constant.int 2, + M.get_name (| globals, "is_leaf" |) + |), + Constant.int 1 + |) + |), + M.get_subscript (| + M.get_name (| globals, "x" |), + Constant.int 0 + |) + |) + ], + make_dict [] + |) in + let _ := + M.for_ (| + M.get_name (| globals, "i" |), + M.call (| + M.get_name (| globals, "range" |), + make_list [ + Constant.int 1; + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_name (| globals, "x" |) + ], + make_dict [] + |); + Constant.int 2 + ], + make_dict [] + |), + ltac:(M.monadic ( + let _ := M.call (| + M.get_field (| M.get_name (| globals, "compact" |), "append" |), + make_list [ + BinOp.add (| + BinOp.mult (| + Constant.int 16, + M.get_subscript (| + M.get_name (| globals, "x" |), + M.get_name (| globals, "i" |) + |) + |), + M.get_subscript (| + M.get_name (| globals, "x" |), + BinOp.add (| + M.get_name (| globals, "i" |), + Constant.int 1 + |) + |) + |) + ], + make_dict [] + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + M.pure Constant.None_ + )) |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, "Bytes" |), + make_list [ + M.get_name (| globals, "compact" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Definition bytes_to_nibble_list : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "bytes_" ] |) in + let _ := Constant.str " + Converts a `Bytes` into to a sequence of nibbles (bytes with value < 16). + + Parameters + ---------- + bytes_: + The `Bytes` to convert. + + Returns + ------- + nibble_list : `Bytes` + The `Bytes` in nibble-list format. + " in + let _ := M.assign_local (| + "nibble_list" , + M.call (| + M.get_name (| globals, "bytearray" |), + make_list [ + BinOp.mult (| + Constant.int 2, + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_name (| globals, "bytes_" |) + ], + make_dict [] + |) + |) + ], + make_dict [] + |) + |) in + let _ := + M.for_ (| + make_tuple [ M.get_name (| globals, "byte_index" |); M.get_name (| globals, "byte" |) ], + M.call (| + M.get_name (| globals, "enumerate" |), + make_list [ + M.get_name (| globals, "bytes_" |) + ], + make_dict [] + |), + ltac:(M.monadic ( + let _ := M.assign (| + M.get_subscript (| + M.get_name (| globals, "nibble_list" |), + BinOp.mult (| + M.get_name (| globals, "byte_index" |), + Constant.int 2 + |) + |), + BinOp.r_shift (| + BinOp.bit_and (| + M.get_name (| globals, "byte" |), + Constant.int 240 + |), + Constant.int 4 + |) + |) in + let _ := M.assign (| + M.get_subscript (| + M.get_name (| globals, "nibble_list" |), + BinOp.add (| + BinOp.mult (| + M.get_name (| globals, "byte_index" |), + Constant.int 2 + |), + Constant.int 1 + |) + |), + BinOp.bit_and (| + M.get_name (| globals, "byte" |), + Constant.int 15 + |) + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, "Bytes" |), + make_list [ + M.get_name (| globals, "nibble_list" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Definition _prepare_trie : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "trie"; "get_storage_root" ] |) in + let _ := Constant.str " + Prepares the trie for root calculation. Removes values that are empty, + hashes the keys (if `secured == True`) and encodes all the nodes. + + Parameters + ---------- + trie : + The `Trie` to prepare. + get_storage_root : + Function to get the storage root of an account. Needed to encode + `Account` objects. + + Returns + ------- + out : `Mapping[ethereum.base_types.Bytes, Node]` + Object with keys mapped to nibble-byte form. + " in +(* At stmt: unsupported node type: AnnAssign *) + let _ := + M.for_ (| + make_tuple [ M.get_name (| globals, "preimage" |); M.get_name (| globals, "value" |) ], + M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, "trie" |), "_data" |), "items" |), + make_list [], + make_dict [] + |), + ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, "isinstance" |), + make_list [ + M.get_name (| globals, "value" |); + M.get_name (| globals, "Account" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assert (| Compare.is_not (| + M.get_name (| globals, "get_storage_root" |), + Constant.None_ + |) |) in + let _ := M.assign_local (| + "address" , + M.call (| + M.get_name (| globals, "Address" |), + make_list [ + M.get_name (| globals, "preimage" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "encoded_value" , + M.call (| + M.get_name (| globals, "encode_node" |), + make_list [ + M.get_name (| globals, "value" |); + M.call (| + M.get_name (| globals, "get_storage_root" |), + make_list [ + M.get_name (| globals, "address" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "encoded_value" , + M.call (| + M.get_name (| globals, "encode_node" |), + make_list [ + M.get_name (| globals, "value" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + )) |) in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + Compare.not_eq (| + M.get_name (| globals, "encoded_value" |), + Constant.bytes "" + |); + M.get_name (| globals, "AssertionError" |) + ], + make_dict [] + |) in +(* At stmt: unsupported node type: AnnAssign *) + let _ := + (* if *) + M.if_then_else (| + M.get_field (| M.get_name (| globals, "trie" |), "secured" |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "key" , + M.call (| + M.get_name (| globals, "keccak256" |), + make_list [ + M.get_name (| globals, "preimage" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "key" , + M.get_name (| globals, "preimage" |) + |) in + M.pure Constant.None_ + )) |) in + let _ := M.assign (| + M.get_subscript (| + M.get_name (| globals, "mapped" |), + M.call (| + M.get_name (| globals, "bytes_to_nibble_list" |), + make_list [ + M.get_name (| globals, "key" |) + ], + make_dict [] + |) + |), + M.get_name (| globals, "encoded_value" |) + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := M.return_ (| + M.get_name (| globals, "mapped" |) + |) in + M.pure Constant.None_)). + +Definition root : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "trie"; "get_storage_root" ] |) in + let _ := Constant.str " + Computes the root of a modified merkle patricia trie (MPT). + + Parameters + ---------- + trie : + `Trie` to get the root of. + get_storage_root : + Function to get the storage root of an account. Needed to encode + `Account` objects. + + + Returns + ------- + root : `.fork_types.Root` + MPT root of the underlying key-value pairs. + " in + let _ := M.assign_local (| + "obj" , + M.call (| + M.get_name (| globals, "_prepare_trie" |), + make_list [ + M.get_name (| globals, "trie" |); + M.get_name (| globals, "get_storage_root" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "root_node" , + M.call (| + M.get_name (| globals, "encode_internal_node" |), + make_list [ + M.call (| + M.get_name (| globals, "patricialize" |), + make_list [ + M.get_name (| globals, "obj" |); + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.lt (| + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.call (| + M.get_field (| M.get_name (| globals, "rlp" |), "encode" |), + make_list [ + M.get_name (| globals, "root_node" |) + ], + make_dict [] + |) + ], + make_dict [] + |), + Constant.int 32 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + M.call (| + M.get_name (| globals, "keccak256" |), + make_list [ + M.call (| + M.get_field (| M.get_name (| globals, "rlp" |), "encode" |), + make_list [ + M.get_name (| globals, "root_node" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assert (| M.call (| + M.get_name (| globals, "isinstance" |), + make_list [ + M.get_name (| globals, "root_node" |); + M.get_name (| globals, "Bytes" |) + ], + make_dict [] + |) |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, "Root" |), + make_list [ + M.get_name (| globals, "root_node" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_)). + +Definition patricialize : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "obj"; "level" ] |) in + let _ := Constant.str " + Structural composition function. + + Used to recursively patricialize and merkleize a dictionary. Includes + memoization of the tree structure and hashes. + + Parameters + ---------- + obj : + Underlying trie key-value pairs, with keys in nibble-list format. + level : + Current trie level. + + Returns + ------- + node : `ethereum.base_types.Bytes` + Root node of `obj`. + " in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_name (| globals, "obj" |) + ], + make_dict [] + |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + Constant.None_ + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "arbitrary_key" , + M.call (| + M.get_name (| globals, "next" |), + make_list [ + M.call (| + M.get_name (| globals, "iter" |), + make_list [ + M.get_name (| globals, "obj" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_name (| globals, "obj" |) + ], + make_dict [] + |), + Constant.int 1 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "leaf" , + M.call (| + M.get_name (| globals, "LeafNode" |), + make_list [ + M.slice (| + M.get_name (| globals, "arbitrary_key" |), + M.get_name (| globals, "level" |), + Constant.None_, + Constant.None_ + |); + M.get_subscript (| + M.get_name (| globals, "obj" |), + M.get_name (| globals, "arbitrary_key" |) + |) + ], + make_dict [] + |) + |) in + let _ := M.return_ (| + M.get_name (| globals, "leaf" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "substring" , + M.slice (| + M.get_name (| globals, "arbitrary_key" |), + M.get_name (| globals, "level" |), + Constant.None_, + Constant.None_ + |) + |) in + let _ := M.assign_local (| + "prefix_length" , + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_name (| globals, "substring" |) + ], + make_dict [] + |) + |) in + let _ := + M.for_ (| + M.get_name (| globals, "key" |), + M.get_name (| globals, "obj" |), + ltac:(M.monadic ( + let _ := M.assign_local (| + "prefix_length" , + M.call (| + M.get_name (| globals, "min" |), + make_list [ + M.get_name (| globals, "prefix_length" |); + M.call (| + M.get_name (| globals, "common_prefix_length" |), + make_list [ + M.get_name (| globals, "substring" |); + M.slice (| + M.get_name (| globals, "key" |), + M.get_name (| globals, "level" |), + Constant.None_, + Constant.None_ + |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, "prefix_length" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.break (| |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.gt (| + M.get_name (| globals, "prefix_length" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "prefix" , + M.slice (| + M.get_name (| globals, "arbitrary_key" |), + M.get_name (| globals, "level" |), + BinOp.add (| + M.get_name (| globals, "level" |), + M.get_name (| globals, "prefix_length" |) + |), + Constant.None_ + |) + |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, "ExtensionNode" |), + make_list [ + M.get_name (| globals, "prefix" |); + M.call (| + M.get_name (| globals, "encode_internal_node" |), + make_list [ + M.call (| + M.get_name (| globals, "patricialize" |), + make_list [ + M.get_name (| globals, "obj" |); + BinOp.add (| + M.get_name (| globals, "level" |), + M.get_name (| globals, "prefix_length" |) + |) + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in +(* At stmt: unsupported node type: AnnAssign *) + let _ := + M.for_ (| + M.get_name (| globals, "_" |), + M.call (| + M.get_name (| globals, "range" |), + make_list [ + Constant.int 16 + ], + make_dict [] + |), + ltac:(M.monadic ( + let _ := M.call (| + M.get_field (| M.get_name (| globals, "branches" |), "append" |), + make_list [ + Constant.str "(* At expr: unsupported node type: Dict *)" + ], + make_dict [] + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := M.assign_local (| + "value" , + Constant.bytes "" + |) in + let _ := + M.for_ (| + M.get_name (| globals, "key" |), + M.get_name (| globals, "obj" |), + ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_name (| globals, "key" |) + ], + make_dict [] + |), + M.get_name (| globals, "level" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, "isinstance" |), + make_list [ + M.get_subscript (| + M.get_name (| globals, "obj" |), + M.get_name (| globals, "key" |) + |); + make_tuple [ M.get_name (| globals, "Account" |); M.get_name (| globals, "Receipt" |); M.get_name (| globals, "Uint" |) ] + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, "AssertionError" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "value" , + M.get_subscript (| + M.get_name (| globals, "obj" |), + M.get_name (| globals, "key" |) + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign (| + M.get_subscript (| + M.get_subscript (| + M.get_name (| globals, "branches" |), + M.get_subscript (| + M.get_name (| globals, "key" |), + M.get_name (| globals, "level" |) + |) + |), + M.get_name (| globals, "key" |) + |), + M.get_subscript (| + M.get_name (| globals, "obj" |), + M.get_name (| globals, "key" |) + |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, "BranchNode" |), + make_list [ + Constant.str "(* At expr: unsupported node type: ListComp *)"; + M.get_name (| globals, "value" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). diff --git a/CoqOfPython/ethereum/byzantium/utils/__init__.v b/CoqOfPython/ethereum/byzantium/utils/__init__.v new file mode 100644 index 0000000..418c984 --- /dev/null +++ b/CoqOfPython/ethereum/byzantium/utils/__init__.v @@ -0,0 +1,8 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.byzantium.utils.__init__". + +Definition expr_1 : Value.t := + Constant.str " +Utility functions unique to this particular fork. +". diff --git a/CoqOfPython/ethereum/byzantium/utils/address.v b/CoqOfPython/ethereum/byzantium/utils/address.v new file mode 100644 index 0000000..f8a4ecd --- /dev/null +++ b/CoqOfPython/ethereum/byzantium/utils/address.v @@ -0,0 +1,144 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.byzantium.utils.address". + +Definition expr_1 : Value.t := + Constant.str " +Hardfork Utility Functions For Addresses +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Address specific functions used in this byzantium version of +specification. +". + +Axiom typing_imports_Union : + IsImported globals "typing" "Union". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". + +Axiom ethereum_crypto_hash_imports_keccak256 : + IsImported globals "ethereum.crypto.hash" "keccak256". + +Axiom ethereum_utils_byte_imports_left_pad_zero_bytes : + IsImported globals "ethereum.utils.byte" "left_pad_zero_bytes". + +Axiom ethereum_imports_rlp : + IsImported globals "ethereum" "rlp". + +Axiom ethereum_byzantium_fork_types_imports_Address : + IsImported globals "ethereum.byzantium.fork_types" "Address". + +Definition to_address : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "data" ] |) in + let _ := Constant.str " + Convert a Uint or U256 value to a valid address (20 bytes). + + Parameters + ---------- + data : + The string to be converted to bytes. + + Returns + ------- + address : `Address` + The obtained address. + " in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, "Address" |), + make_list [ + M.slice (| + M.call (| + M.get_field (| M.get_name (| globals, "data" |), "to_be_bytes32" |), + make_list [], + make_dict [] + |), + UnOp.sub (| Constant.int 20 |), + Constant.None_, + Constant.None_ + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Definition compute_contract_address : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "address"; "nonce" ] |) in + let _ := Constant.str " + Computes address of the new account that needs to be created. + + Parameters + ---------- + address : + The address of the account that wants to create the new account. + nonce : + The transaction count of the account that wants to create the new + account. + + Returns + ------- + address: `ethereum.byzantium.fork_types.Address` + The computed address of the new account. + " in + let _ := M.assign_local (| + "computed_address" , + M.call (| + M.get_name (| globals, "keccak256" |), + make_list [ + M.call (| + M.get_field (| M.get_name (| globals, "rlp" |), "encode" |), + make_list [ + make_list [ + M.get_name (| globals, "address" |); + M.get_name (| globals, "nonce" |) + ] + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "canonical_address" , + M.slice (| + M.get_name (| globals, "computed_address" |), + UnOp.sub (| Constant.int 20 |), + Constant.None_, + Constant.None_ + |) + |) in + let _ := M.assign_local (| + "padded_address" , + M.call (| + M.get_name (| globals, "left_pad_zero_bytes" |), + make_list [ + M.get_name (| globals, "canonical_address" |); + Constant.int 20 + ], + make_dict [] + |) + |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, "Address" |), + make_list [ + M.get_name (| globals, "padded_address" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). diff --git a/CoqOfPython/ethereum/byzantium/utils/hexadecimal.v b/CoqOfPython/ethereum/byzantium/utils/hexadecimal.v new file mode 100644 index 0000000..5540c16 --- /dev/null +++ b/CoqOfPython/ethereum/byzantium/utils/hexadecimal.v @@ -0,0 +1,153 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.byzantium.utils.hexadecimal". + +Definition expr_1 : Value.t := + Constant.str " +Utility Functions For Hexadecimal Strings +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Hexadecimal utility functions used in this specification, specific to +Byzantium types. +". + +Axiom ethereum_utils_hexadecimal_imports_remove_hex_prefix : + IsImported globals "ethereum.utils.hexadecimal" "remove_hex_prefix". + +Axiom ethereum_byzantium_fork_types_imports_Address : + IsImported globals "ethereum.byzantium.fork_types" "Address". +Axiom ethereum_byzantium_fork_types_imports_Bloom : + IsImported globals "ethereum.byzantium.fork_types" "Bloom". +Axiom ethereum_byzantium_fork_types_imports_Root : + IsImported globals "ethereum.byzantium.fork_types" "Root". + +Definition hex_to_root : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "hex_string" ] |) in + let _ := Constant.str " + Convert hex string to trie root. + + Parameters + ---------- + hex_string : + The hexadecimal string to be converted to trie root. + + Returns + ------- + root : `Root` + Trie root obtained from the given hexadecimal string. + " in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, "Root" |), + make_list [ + M.call (| + M.get_field (| M.get_name (| globals, "bytes" |), "fromhex" |), + make_list [ + M.call (| + M.get_name (| globals, "remove_hex_prefix" |), + make_list [ + M.get_name (| globals, "hex_string" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Definition hex_to_bloom : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "hex_string" ] |) in + let _ := Constant.str " + Convert hex string to bloom. + + Parameters + ---------- + hex_string : + The hexadecimal string to be converted to bloom. + + Returns + ------- + bloom : `Bloom` + Bloom obtained from the given hexadecimal string. + " in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, "Bloom" |), + make_list [ + M.call (| + M.get_field (| M.get_name (| globals, "bytes" |), "fromhex" |), + make_list [ + M.call (| + M.get_name (| globals, "remove_hex_prefix" |), + make_list [ + M.get_name (| globals, "hex_string" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Definition hex_to_address : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "hex_string" ] |) in + let _ := Constant.str " + Convert hex string to Address (20 bytes). + + Parameters + ---------- + hex_string : + The hexadecimal string to be converted to Address. + + Returns + ------- + address : `Address` + The address obtained from the given hexadecimal string. + " in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, "Address" |), + make_list [ + M.call (| + M.get_field (| M.get_name (| globals, "bytes" |), "fromhex" |), + make_list [ + M.call (| + M.get_field (| M.call (| + M.get_name (| globals, "remove_hex_prefix" |), + make_list [ + M.get_name (| globals, "hex_string" |) + ], + make_dict [] + |), "rjust" |), + make_list [ + Constant.int 40; + Constant.str "0" + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). diff --git a/CoqOfPython/ethereum/byzantium/utils/message.v b/CoqOfPython/ethereum/byzantium/utils/message.v new file mode 100644 index 0000000..c60fbeb --- /dev/null +++ b/CoqOfPython/ethereum/byzantium/utils/message.v @@ -0,0 +1,212 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.byzantium.utils.message". + +Definition expr_1 : Value.t := + Constant.str " +Hardfork Utility Functions For The Message Data-structure +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Message specific functions used in this byzantium version of +specification. +". + +Axiom typing_imports_Optional : + IsImported globals "typing" "Optional". +Axiom typing_imports_Union : + IsImported globals "typing" "Union". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_Bytes : + IsImported globals "ethereum.base_types" "Bytes". +Axiom ethereum_base_types_imports_Bytes0 : + IsImported globals "ethereum.base_types" "Bytes0". +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". + +Axiom ethereum_byzantium_fork_types_imports_Address : + IsImported globals "ethereum.byzantium.fork_types" "Address". + +Axiom ethereum_byzantium_state_imports_get_account : + IsImported globals "ethereum.byzantium.state" "get_account". + +Axiom ethereum_byzantium_vm_imports_Environment : + IsImported globals "ethereum.byzantium.vm" "Environment". +Axiom ethereum_byzantium_vm_imports_Message : + IsImported globals "ethereum.byzantium.vm" "Message". + +Axiom ethereum_byzantium_utils_address_imports_compute_contract_address : + IsImported globals "ethereum.byzantium.utils.address" "compute_contract_address". + +Definition prepare_message : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "caller"; "target"; "value"; "data"; "gas"; "env"; "code_address"; "should_transfer_value"; "is_static" ] |) in + let _ := Constant.str " + Execute a transaction against the provided environment. + + Parameters + ---------- + caller : + Address which initiated the transaction + target : + Address whose code will be executed + value : + Value to be transferred. + data : + Array of bytes provided to the code in `target`. + gas : + Gas provided for the code in `target`. + env : + Environment for the Ethereum Virtual Machine. + code_address : + This is usually same as the `target` address except when an alternative + accounts code needs to be executed. + eg. `CALLCODE` calling a precompile. + should_transfer_value : + if True ETH should be transferred while executing a message call. + is_static: + if True then it prevents all state-changing operations from being + executed. + + Returns + ------- + message: `ethereum.byzantium.vm.Message` + Items containing contract creation or message call specific data. + " in + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, "isinstance" |), + make_list [ + M.get_name (| globals, "target" |); + M.get_name (| globals, "Bytes0" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "current_target" , + M.call (| + M.get_name (| globals, "compute_contract_address" |), + make_list [ + M.get_name (| globals, "caller" |); + BinOp.sub (| + M.get_field (| M.call (| + M.get_name (| globals, "get_account" |), + make_list [ + M.get_field (| M.get_name (| globals, "env" |), "state" |); + M.get_name (| globals, "caller" |) + ], + make_dict [] + |), "nonce" |), + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 1 + ], + make_dict [] + |) + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "msg_data" , + M.call (| + M.get_name (| globals, "Bytes" |), + make_list [ + Constant.bytes "" + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "code" , + M.get_name (| globals, "data" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, "isinstance" |), + make_list [ + M.get_name (| globals, "target" |); + M.get_name (| globals, "Address" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "current_target" , + M.get_name (| globals, "target" |) + |) in + let _ := M.assign_local (| + "msg_data" , + M.get_name (| globals, "data" |) + |) in + let _ := M.assign_local (| + "code" , + M.get_field (| M.call (| + M.get_name (| globals, "get_account" |), + make_list [ + M.get_field (| M.get_name (| globals, "env" |), "state" |); + M.get_name (| globals, "target" |) + ], + make_dict [] + |), "code" |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.is (| + M.get_name (| globals, "code_address" |), + Constant.None_ + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "code_address" , + M.get_name (| globals, "target" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.raise (| Some (M.call (| + M.get_name (| globals, "AssertionError" |), + make_list [ + Constant.str "Target must be address or empty bytes" + ], + make_dict [] + |)) |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )) |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, "Message" |), + make_list [], + make_dict [] + |) + |) in + M.pure Constant.None_)). diff --git a/CoqOfPython/ethereum/byzantium/vm/__init__.v b/CoqOfPython/ethereum/byzantium/vm/__init__.v new file mode 100644 index 0000000..b02d05c --- /dev/null +++ b/CoqOfPython/ethereum/byzantium/vm/__init__.v @@ -0,0 +1,242 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.byzantium.vm.__init__". + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +The abstract computer which runs the code stored in an +`.fork_types.Account`. +". + +Axiom dataclasses_imports_dataclass : + IsImported globals "dataclasses" "dataclass". + +Axiom typing_imports_List : + IsImported globals "typing" "List". +Axiom typing_imports_Optional : + IsImported globals "typing" "Optional". +Axiom typing_imports_Set : + IsImported globals "typing" "Set". +Axiom typing_imports_Tuple : + IsImported globals "typing" "Tuple". +Axiom typing_imports_Union : + IsImported globals "typing" "Union". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_Bytes : + IsImported globals "ethereum.base_types" "Bytes". +Axiom ethereum_base_types_imports_Bytes0 : + IsImported globals "ethereum.base_types" "Bytes0". +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". + +Axiom ethereum_crypto_hash_imports_Hash32 : + IsImported globals "ethereum.crypto.hash" "Hash32". + +Axiom ethereum_byzantium_blocks_imports_Log : + IsImported globals "ethereum.byzantium.blocks" "Log". + +Axiom ethereum_byzantium_fork_types_imports_Address : + IsImported globals "ethereum.byzantium.fork_types" "Address". + +Axiom ethereum_byzantium_state_imports_State : + IsImported globals "ethereum.byzantium.state" "State". +Axiom ethereum_byzantium_state_imports_account_exists_and_is_empty : + IsImported globals "ethereum.byzantium.state" "account_exists_and_is_empty". + +Axiom ethereum_byzantium_vm_precompiled_contracts_imports_RIPEMD160_ADDRESS : + IsImported globals "ethereum.byzantium.vm.precompiled_contracts" "RIPEMD160_ADDRESS". + +Definition __all__ : Value.t := M.run ltac:(M.monadic ( + make_tuple [ Constant.str "Environment"; Constant.str "Evm"; Constant.str "Message" ] +)). + +Definition Environment : Value.t := + builtins.make_klass + [] + [ + + ] + [ + + ]. + +Definition Message : Value.t := + builtins.make_klass + [] + [ + + ] + [ + + ]. + +Definition Evm : Value.t := + builtins.make_klass + [] + [ + + ] + [ + + ]. + +Definition incorporate_child_on_success : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm"; "child_evm" ] |) in + let _ := Constant.str " + Incorporate the state of a successful `child_evm` into the parent `evm`. + + Parameters + ---------- + evm : + The parent `EVM`. + child_evm : + The child evm to incorporate. + " in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "gas_left" |), + M.get_field (| M.get_name (| globals, "child_evm" |), "gas_left" |) + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "logs" |), + M.get_field (| M.get_name (| globals, "child_evm" |), "logs" |) + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "refund_counter" |), + M.get_field (| M.get_name (| globals, "child_evm" |), "refund_counter" |) + |) in + let _ := M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "accounts_to_delete" |), "update" |), + make_list [ + M.get_field (| M.get_name (| globals, "child_evm" |), "accounts_to_delete" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "touched_accounts" |), "update" |), + make_list [ + M.get_field (| M.get_name (| globals, "child_evm" |), "touched_accounts" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, "account_exists_and_is_empty" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "env" |), "state" |); + M.get_field (| M.get_field (| M.get_name (| globals, "child_evm" |), "message" |), "current_target" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "touched_accounts" |), "add" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "child_evm" |), "message" |), "current_target" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + M.pure Constant.None_)). + +Definition incorporate_child_on_error : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm"; "child_evm" ] |) in + let _ := Constant.str " + Incorporate the state of an unsuccessful `child_evm` into the parent `evm`. + + Parameters + ---------- + evm : + The parent `EVM`. + child_evm : + The child evm to incorporate. + " in + let _ := + (* if *) + M.if_then_else (| + Compare.in_ (| + M.get_name (| globals, "RIPEMD160_ADDRESS" |), + M.get_field (| M.get_name (| globals, "child_evm" |), "touched_accounts" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "touched_accounts" |), "add" |), + make_list [ + M.get_name (| globals, "RIPEMD160_ADDRESS" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_field (| M.get_field (| M.get_name (| globals, "child_evm" |), "message" |), "current_target" |), + M.get_name (| globals, "RIPEMD160_ADDRESS" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, "account_exists_and_is_empty" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "env" |), "state" |); + M.get_field (| M.get_field (| M.get_name (| globals, "child_evm" |), "message" |), "current_target" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "touched_accounts" |), "add" |), + make_list [ + M.get_name (| globals, "RIPEMD160_ADDRESS" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "gas_left" |), + M.get_field (| M.get_name (| globals, "child_evm" |), "gas_left" |) + |) in + M.pure Constant.None_)). diff --git a/CoqOfPython/ethereum/byzantium/vm/exceptions.v b/CoqOfPython/ethereum/byzantium/vm/exceptions.v new file mode 100644 index 0000000..7375e6c --- /dev/null +++ b/CoqOfPython/ethereum/byzantium/vm/exceptions.v @@ -0,0 +1,151 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.byzantium.vm.exceptions". + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) Exceptions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Exceptions which cause the EVM to halt exceptionally. +". + +Axiom ethereum_exceptions_imports_EthereumException : + IsImported globals "ethereum.exceptions" "EthereumException". + +Definition ExceptionalHalt : Value.t := + builtins.make_klass + [(globals, "EthereumException")] + [ + + ] + [ + + ]. + +Definition Revert : Value.t := + builtins.make_klass + [(globals, "EthereumException")] + [ + + ] + [ + + ]. + +Definition StackUnderflowError : Value.t := + builtins.make_klass + [(globals, "ExceptionalHalt")] + [ + + ] + [ + + ]. + +Definition StackOverflowError : Value.t := + builtins.make_klass + [(globals, "ExceptionalHalt")] + [ + + ] + [ + + ]. + +Definition OutOfGasError : Value.t := + builtins.make_klass + [(globals, "ExceptionalHalt")] + [ + + ] + [ + + ]. + +Definition InvalidOpcode : Value.t := + builtins.make_klass + [(globals, "ExceptionalHalt")] + [ + + ] + [ + ( + "__init__", + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "self"; "code" ] |) in + let _ := M.call (| + M.get_field (| M.call (| + M.get_name (| globals, "super" |), + make_list [], + make_dict [] + |), "__init__" |), + make_list [ + M.get_name (| globals, "code" |) + ], + make_dict [] + |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, "self" |), "code" |), + M.get_name (| globals, "code" |) + |) in + M.pure Constant.None_)) + ) + ]. + +Definition InvalidJumpDestError : Value.t := + builtins.make_klass + [(globals, "ExceptionalHalt")] + [ + + ] + [ + + ]. + +Definition StackDepthLimitError : Value.t := + builtins.make_klass + [(globals, "ExceptionalHalt")] + [ + + ] + [ + + ]. + +Definition WriteInStaticContext : Value.t := + builtins.make_klass + [(globals, "ExceptionalHalt")] + [ + + ] + [ + + ]. + +Definition OutOfBoundsRead : Value.t := + builtins.make_klass + [(globals, "ExceptionalHalt")] + [ + + ] + [ + + ]. + +Definition AddressCollision : Value.t := + builtins.make_klass + [(globals, "ExceptionalHalt")] + [ + + ] + [ + + ]. diff --git a/CoqOfPython/ethereum/byzantium/vm/gas.v b/CoqOfPython/ethereum/byzantium/vm/gas.v new file mode 100644 index 0000000..bd2fb66 --- /dev/null +++ b/CoqOfPython/ethereum/byzantium/vm/gas.v @@ -0,0 +1,912 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.byzantium.vm.gas". + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) Gas +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +EVM gas constants and calculators. +". + +Axiom dataclasses_imports_dataclass : + IsImported globals "dataclasses" "dataclass". + +Axiom typing_imports_List : + IsImported globals "typing" "List". +Axiom typing_imports_Tuple : + IsImported globals "typing" "Tuple". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". + +Axiom ethereum_trace_imports_GasAndRefund : + IsImported globals "ethereum.trace" "GasAndRefund". +Axiom ethereum_trace_imports_evm_trace : + IsImported globals "ethereum.trace" "evm_trace". + +Axiom ethereum_utils_numeric_imports_ceil32 : + IsImported globals "ethereum.utils.numeric" "ceil32". + +Axiom ethereum_byzantium_vm_imports_Evm : + IsImported globals "ethereum.byzantium.vm" "Evm". + +Axiom ethereum_byzantium_vm_exceptions_imports_OutOfGasError : + IsImported globals "ethereum.byzantium.vm.exceptions" "OutOfGasError". + +Definition GAS_JUMPDEST : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 1 + ], + make_dict [] + |) +)). + +Definition GAS_BASE : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 2 + ], + make_dict [] + |) +)). + +Definition GAS_VERY_LOW : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 3 + ], + make_dict [] + |) +)). + +Definition GAS_SLOAD : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 200 + ], + make_dict [] + |) +)). + +Definition GAS_STORAGE_SET : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 20000 + ], + make_dict [] + |) +)). + +Definition GAS_STORAGE_UPDATE : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 5000 + ], + make_dict [] + |) +)). + +Definition GAS_STORAGE_CLEAR_REFUND : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 15000 + ], + make_dict [] + |) +)). + +Definition GAS_LOW : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 5 + ], + make_dict [] + |) +)). + +Definition GAS_MID : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 8 + ], + make_dict [] + |) +)). + +Definition GAS_HIGH : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 10 + ], + make_dict [] + |) +)). + +Definition GAS_EXPONENTIATION : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 10 + ], + make_dict [] + |) +)). + +Definition GAS_EXPONENTIATION_PER_BYTE : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 50 + ], + make_dict [] + |) +)). + +Definition GAS_MEMORY : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 3 + ], + make_dict [] + |) +)). + +Definition GAS_KECCAK256 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 30 + ], + make_dict [] + |) +)). + +Definition GAS_KECCAK256_WORD : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 6 + ], + make_dict [] + |) +)). + +Definition GAS_COPY : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 3 + ], + make_dict [] + |) +)). + +Definition GAS_BLOCK_HASH : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 20 + ], + make_dict [] + |) +)). + +Definition GAS_EXTERNAL : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 700 + ], + make_dict [] + |) +)). + +Definition GAS_BALANCE : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 400 + ], + make_dict [] + |) +)). + +Definition GAS_LOG : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 375 + ], + make_dict [] + |) +)). + +Definition GAS_LOG_DATA : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 8 + ], + make_dict [] + |) +)). + +Definition GAS_LOG_TOPIC : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 375 + ], + make_dict [] + |) +)). + +Definition GAS_CREATE : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 32000 + ], + make_dict [] + |) +)). + +Definition GAS_CODE_DEPOSIT : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 200 + ], + make_dict [] + |) +)). + +Definition GAS_ZERO : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) +)). + +Definition GAS_CALL : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 700 + ], + make_dict [] + |) +)). + +Definition GAS_NEW_ACCOUNT : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 25000 + ], + make_dict [] + |) +)). + +Definition GAS_CALL_VALUE : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 9000 + ], + make_dict [] + |) +)). + +Definition GAS_CALL_STIPEND : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 2300 + ], + make_dict [] + |) +)). + +Definition GAS_SELF_DESTRUCT : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 5000 + ], + make_dict [] + |) +)). + +Definition GAS_SELF_DESTRUCT_NEW_ACCOUNT : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 25000 + ], + make_dict [] + |) +)). + +Definition REFUND_SELF_DESTRUCT : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 24000 + ], + make_dict [] + |) +)). + +Definition GAS_ECRECOVER : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 3000 + ], + make_dict [] + |) +)). + +Definition GAS_SHA256 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 60 + ], + make_dict [] + |) +)). + +Definition GAS_SHA256_WORD : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 12 + ], + make_dict [] + |) +)). + +Definition GAS_RIPEMD160 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 600 + ], + make_dict [] + |) +)). + +Definition GAS_RIPEMD160_WORD : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 120 + ], + make_dict [] + |) +)). + +Definition GAS_IDENTITY : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 15 + ], + make_dict [] + |) +)). + +Definition GAS_IDENTITY_WORD : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 3 + ], + make_dict [] + |) +)). + +Definition GAS_RETURN_DATA_COPY : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 3 + ], + make_dict [] + |) +)). + +Definition ExtendMemory : Value.t := + builtins.make_klass + [] + [ + + ] + [ + + ]. + +Definition MessageCallGas : Value.t := + builtins.make_klass + [] + [ + + ] + [ + + ]. + +Definition charge_gas : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm"; "amount" ] |) in + let _ := Constant.str " + Subtracts `amount` from `evm.gas_left`. + + Parameters + ---------- + evm : + The current EVM. + amount : + The amount of gas the current operation requires. + + " in + let _ := M.call (| + M.get_name (| globals, "evm_trace" |), + make_list [ + M.get_name (| globals, "evm" |); + M.call (| + M.get_name (| globals, "GasAndRefund" |), + make_list [ + M.get_name (| globals, "amount" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.lt (| + M.get_field (| M.get_name (| globals, "evm" |), "gas_left" |), + M.get_name (| globals, "amount" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, "OutOfGasError" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_op (| + BinOp.sub, + M.get_field (| M.get_name (| globals, "evm" |), "gas_left" |), + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + M.get_name (| globals, "amount" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_)). + +Definition calculate_memory_gas_cost : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "size_in_bytes" ] |) in + let _ := Constant.str " + Calculates the gas cost for allocating memory + to the smallest multiple of 32 bytes, + such that the allocated size is at least as big as the given size. + + Parameters + ---------- + size_in_bytes : + The size of the data in bytes. + + Returns + ------- + total_gas_cost : `ethereum.base_types.Uint` + The gas cost for storing data in memory. + " in + let _ := M.assign_local (| + "size_in_words" , + BinOp.floor_div (| + M.call (| + M.get_name (| globals, "ceil32" |), + make_list [ + M.get_name (| globals, "size_in_bytes" |) + ], + make_dict [] + |), + Constant.int 32 + |) + |) in + let _ := M.assign_local (| + "linear_cost" , + BinOp.mult (| + M.get_name (| globals, "size_in_words" |), + M.get_name (| globals, "GAS_MEMORY" |) + |) + |) in + let _ := M.assign_local (| + "quadratic_cost" , + BinOp.floor_div (| + BinOp.pow (| + M.get_name (| globals, "size_in_words" |), + Constant.int 2 + |), + Constant.int 512 + |) + |) in + let _ := M.assign_local (| + "total_gas_cost" , + BinOp.add (| + M.get_name (| globals, "linear_cost" |), + M.get_name (| globals, "quadratic_cost" |) + |) + |) in +(* At stmt: unsupported node type: Try *) + M.pure Constant.None_)). + +Definition calculate_gas_extend_memory : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "memory"; "extensions" ] |) in + let _ := Constant.str " + Calculates the gas amount to extend memory + + Parameters + ---------- + memory : + Memory contents of the EVM. + extensions: + List of extensions to be made to the memory. + Consists of a tuple of start position and size. + + Returns + ------- + extend_memory: `ExtendMemory` + " in + let _ := M.assign_local (| + "size_to_extend" , + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "to_be_paid" , + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "current_size" , + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_name (| globals, "memory" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := + M.for_ (| + make_tuple [ M.get_name (| globals, "start_position" |); M.get_name (| globals, "size" |) ], + M.get_name (| globals, "extensions" |), + ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, "size" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.continue (| |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "before_size" , + M.call (| + M.get_name (| globals, "ceil32" |), + make_list [ + M.get_name (| globals, "current_size" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "after_size" , + M.call (| + M.get_name (| globals, "ceil32" |), + make_list [ + BinOp.add (| + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.get_name (| globals, "start_position" |) + ], + make_dict [] + |), + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.get_name (| globals, "size" |) + ], + make_dict [] + |) + |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.lt_e (| + M.get_name (| globals, "after_size" |), + M.get_name (| globals, "before_size" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.continue (| |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_op_local (| + BinOp.add, + "size_to_extend", + BinOp.sub (| + M.get_name (| globals, "after_size" |), + M.get_name (| globals, "before_size" |) + |) + |) in + let _ := M.assign_local (| + "already_paid" , + M.call (| + M.get_name (| globals, "calculate_memory_gas_cost" |), + make_list [ + M.get_name (| globals, "before_size" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "total_cost" , + M.call (| + M.get_name (| globals, "calculate_memory_gas_cost" |), + make_list [ + M.get_name (| globals, "after_size" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_op_local (| + BinOp.add, + "to_be_paid", + BinOp.sub (| + M.get_name (| globals, "total_cost" |), + M.get_name (| globals, "already_paid" |) + |) + |) in + let _ := M.assign_local (| + "current_size" , + M.get_name (| globals, "after_size" |) + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, "ExtendMemory" |), + make_list [ + M.get_name (| globals, "to_be_paid" |); + M.get_name (| globals, "size_to_extend" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Definition calculate_message_call_gas : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "value"; "gas"; "gas_left"; "memory_cost"; "extra_gas"; "call_stipend" ] |) in + let _ := Constant.str " + Calculates the MessageCallGas (cost and stipend) for + executing call Opcodes. + + Parameters + ---------- + value: + The amount of `ETH` that needs to be transferred. + gas : + The amount of gas provided to the message-call. + gas_left : + The amount of gas left in the current frame. + memory_cost : + The amount needed to extend the memory in the current frame. + extra_gas : + The amount of gas needed for transferring value + creating a new + account inside a message call. + call_stipend : + The amount of stipend provided to a message call to execute code while + transferring value(ETH). + + Returns + ------- + message_call_gas: `MessageCallGas` + " in + let _ := M.assign_local (| + "call_stipend" , + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, "value" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( +M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + (* else *) + )), ltac:(M.monadic ( +M.get_name (| globals, "call_stipend" |) + )) |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.lt (| + M.get_name (| globals, "gas_left" |), + BinOp.add (| + M.get_name (| globals, "extra_gas" |), + M.get_name (| globals, "memory_cost" |) + |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + M.call (| + M.get_name (| globals, "MessageCallGas" |), + make_list [ + BinOp.add (| + M.get_name (| globals, "gas" |), + M.get_name (| globals, "extra_gas" |) + |); + BinOp.add (| + M.get_name (| globals, "gas" |), + M.get_name (| globals, "call_stipend" |) + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "gas" , + M.call (| + M.get_name (| globals, "min" |), + make_list [ + M.get_name (| globals, "gas" |); + M.call (| + M.get_name (| globals, "max_message_call_gas" |), + make_list [ + BinOp.sub (| + BinOp.sub (| + M.get_name (| globals, "gas_left" |), + M.get_name (| globals, "memory_cost" |) + |), + M.get_name (| globals, "extra_gas" |) + |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, "MessageCallGas" |), + make_list [ + BinOp.add (| + M.get_name (| globals, "gas" |), + M.get_name (| globals, "extra_gas" |) + |); + BinOp.add (| + M.get_name (| globals, "gas" |), + M.get_name (| globals, "call_stipend" |) + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Definition max_message_call_gas : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "gas" ] |) in + let _ := Constant.str " + Calculates the maximum gas that is allowed for making a message call + + Parameters + ---------- + gas : + The amount of gas provided to the message-call. + + Returns + ------- + max_allowed_message_call_gas: `ethereum.base_types.Uint` + The maximum gas allowed for making the message-call. + " in + let _ := M.return_ (| + BinOp.sub (| + M.get_name (| globals, "gas" |), + BinOp.floor_div (| + M.get_name (| globals, "gas" |), + Constant.int 64 + |) + |) + |) in + M.pure Constant.None_)). diff --git a/CoqOfPython/ethereum/byzantium/vm/instructions/__init__.v b/CoqOfPython/ethereum/byzantium/vm/instructions/__init__.v new file mode 100644 index 0000000..f76e351 --- /dev/null +++ b/CoqOfPython/ethereum/byzantium/vm/instructions/__init__.v @@ -0,0 +1,74 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.byzantium.vm.instructions.__init__". + +Definition expr_1 : Value.t := + Constant.str " +EVM Instruction Encoding (Opcodes) +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Machine readable representations of EVM instructions, and a mapping to their +implementations. +". + +(* At top_level_stmt: unsupported node type: Import *) + +Axiom typing_imports_Callable : + IsImported globals "typing" "Callable". +Axiom typing_imports_Dict : + IsImported globals "typing" "Dict". + +Axiom ethereum_byzantium_vm_instructions_imports_arithmetic : + IsImported globals "ethereum.byzantium.vm.instructions" "arithmetic". + +Axiom ethereum_byzantium_vm_instructions_imports_bitwise : + IsImported globals "ethereum.byzantium.vm.instructions" "bitwise". + +Axiom ethereum_byzantium_vm_instructions_imports_block : + IsImported globals "ethereum.byzantium.vm.instructions" "block". + +Axiom ethereum_byzantium_vm_instructions_imports_comparison : + IsImported globals "ethereum.byzantium.vm.instructions" "comparison". + +Axiom ethereum_byzantium_vm_instructions_imports_control_flow : + IsImported globals "ethereum.byzantium.vm.instructions" "control_flow". + +Axiom ethereum_byzantium_vm_instructions_imports_environment : + IsImported globals "ethereum.byzantium.vm.instructions" "environment". + +Axiom ethereum_byzantium_vm_instructions_imports_keccak : + IsImported globals "ethereum.byzantium.vm.instructions" "keccak". + +Axiom ethereum_byzantium_vm_instructions_imports_log : + IsImported globals "ethereum.byzantium.vm.instructions" "log". + +Axiom ethereum_byzantium_vm_instructions_imports_memory : + IsImported globals "ethereum.byzantium.vm.instructions" "memory". + +Axiom ethereum_byzantium_vm_instructions_imports_stack : + IsImported globals "ethereum.byzantium.vm.instructions" "stack". + +Axiom ethereum_byzantium_vm_instructions_imports_storage : + IsImported globals "ethereum.byzantium.vm.instructions" "storage". + +Axiom ethereum_byzantium_vm_instructions_imports_system : + IsImported globals "ethereum.byzantium.vm.instructions" "system". + +Definition Ops : Value.t := + builtins.make_klass + [(* At base: unsupported node type: Attribute *)] + [ + + ] + [ + + ]. + +(* At top_level_stmt: unsupported node type: AnnAssign *) diff --git a/CoqOfPython/ethereum/byzantium/vm/instructions/arithmetic.v b/CoqOfPython/ethereum/byzantium/vm/instructions/arithmetic.v new file mode 100644 index 0000000..554d565 --- /dev/null +++ b/CoqOfPython/ethereum/byzantium/vm/instructions/arithmetic.v @@ -0,0 +1,1220 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.byzantium.vm.instructions.arithmetic". + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) Arithmetic Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM Arithmetic instructions. +". + +Axiom ethereum_base_types_imports_U255_CEIL_VALUE : + IsImported globals "ethereum.base_types" "U255_CEIL_VALUE". +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_U256_CEIL_VALUE : + IsImported globals "ethereum.base_types" "U256_CEIL_VALUE". +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". + +Axiom ethereum_utils_numeric_imports_get_sign : + IsImported globals "ethereum.utils.numeric" "get_sign". + +Axiom ethereum_byzantium_vm_imports_Evm : + IsImported globals "ethereum.byzantium.vm" "Evm". + +Axiom ethereum_byzantium_vm_gas_imports_GAS_EXPONENTIATION : + IsImported globals "ethereum.byzantium.vm.gas" "GAS_EXPONENTIATION". +Axiom ethereum_byzantium_vm_gas_imports_GAS_EXPONENTIATION_PER_BYTE : + IsImported globals "ethereum.byzantium.vm.gas" "GAS_EXPONENTIATION_PER_BYTE". +Axiom ethereum_byzantium_vm_gas_imports_GAS_LOW : + IsImported globals "ethereum.byzantium.vm.gas" "GAS_LOW". +Axiom ethereum_byzantium_vm_gas_imports_GAS_MID : + IsImported globals "ethereum.byzantium.vm.gas" "GAS_MID". +Axiom ethereum_byzantium_vm_gas_imports_GAS_VERY_LOW : + IsImported globals "ethereum.byzantium.vm.gas" "GAS_VERY_LOW". +Axiom ethereum_byzantium_vm_gas_imports_charge_gas : + IsImported globals "ethereum.byzantium.vm.gas" "charge_gas". + +Axiom ethereum_byzantium_vm_stack_imports_pop : + IsImported globals "ethereum.byzantium.vm.stack" "pop". +Axiom ethereum_byzantium_vm_stack_imports_push : + IsImported globals "ethereum.byzantium.vm.stack" "push". + +Definition add : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Adds the top two elements of the stack together, and pushes the result back + on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "x" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "y" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_VERY_LOW" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "result" , + M.call (| + M.get_field (| M.get_name (| globals, "x" |), "wrapping_add" |), + make_list [ + M.get_name (| globals, "y" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.get_name (| globals, "result" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition sub : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Subtracts the top two elements of the stack, and pushes the result back + on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "x" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "y" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_VERY_LOW" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "result" , + M.call (| + M.get_field (| M.get_name (| globals, "x" |), "wrapping_sub" |), + make_list [ + M.get_name (| globals, "y" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.get_name (| globals, "result" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition mul : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Multiply the top two elements of the stack, and pushes the result back + on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "x" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "y" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_LOW" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "result" , + M.call (| + M.get_field (| M.get_name (| globals, "x" |), "wrapping_mul" |), + make_list [ + M.get_name (| globals, "y" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.get_name (| globals, "result" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition div : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Integer division of the top two elements of the stack. Pushes the result + back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "dividend" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "divisor" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_LOW" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, "divisor" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "quotient" , + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "quotient" , + BinOp.floor_div (| + M.get_name (| globals, "dividend" |), + M.get_name (| globals, "divisor" |) + |) + |) in + M.pure Constant.None_ + )) |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.get_name (| globals, "quotient" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition sdiv : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Signed integer division of the top two elements of the stack. Pushes the + result back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "dividend" , + M.call (| + M.get_field (| M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |), "to_signed" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "divisor" , + M.call (| + M.get_field (| M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |), "to_signed" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_LOW" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, "divisor" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "quotient" , + Constant.int 0 + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + BoolOp.and (| + Compare.eq (| + M.get_name (| globals, "dividend" |), + UnOp.sub (| M.get_name (| globals, "U255_CEIL_VALUE" |) |) + |), + ltac:(M.monadic ( + Compare.eq (| + M.get_name (| globals, "divisor" |), + UnOp.sub (| Constant.int 1 |) + |) + )) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "quotient" , + UnOp.sub (| M.get_name (| globals, "U255_CEIL_VALUE" |) |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "sign" , + M.call (| + M.get_name (| globals, "get_sign" |), + make_list [ + BinOp.mult (| + M.get_name (| globals, "dividend" |), + M.get_name (| globals, "divisor" |) + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "quotient" , + BinOp.mult (| + M.get_name (| globals, "sign" |), + BinOp.floor_div (| + M.call (| + M.get_name (| globals, "abs" |), + make_list [ + M.get_name (| globals, "dividend" |) + ], + make_dict [] + |), + M.call (| + M.get_name (| globals, "abs" |), + make_list [ + M.get_name (| globals, "divisor" |) + ], + make_dict [] + |) + |) + |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )) |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.call (| + M.get_field (| M.get_name (| globals, "U256" |), "from_signed" |), + make_list [ + M.get_name (| globals, "quotient" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition mod_ : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Modulo remainder of the top two elements of the stack. Pushes the result + back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "x" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "y" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_LOW" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, "y" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "remainder" , + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "remainder" , + BinOp.mod_ (| + M.get_name (| globals, "x" |), + M.get_name (| globals, "y" |) + |) + |) in + M.pure Constant.None_ + )) |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.get_name (| globals, "remainder" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition smod : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Signed modulo remainder of the top two elements of the stack. Pushes the + result back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "x" , + M.call (| + M.get_field (| M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |), "to_signed" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "y" , + M.call (| + M.get_field (| M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |), "to_signed" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_LOW" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, "y" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "remainder" , + Constant.int 0 + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "remainder" , + BinOp.mult (| + M.call (| + M.get_name (| globals, "get_sign" |), + make_list [ + M.get_name (| globals, "x" |) + ], + make_dict [] + |), + BinOp.mod_ (| + M.call (| + M.get_name (| globals, "abs" |), + make_list [ + M.get_name (| globals, "x" |) + ], + make_dict [] + |), + M.call (| + M.get_name (| globals, "abs" |), + make_list [ + M.get_name (| globals, "y" |) + ], + make_dict [] + |) + |) + |) + |) in + M.pure Constant.None_ + )) |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.call (| + M.get_field (| M.get_name (| globals, "U256" |), "from_signed" |), + make_list [ + M.get_name (| globals, "remainder" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition addmod : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Modulo addition of the top 2 elements with the 3rd element. Pushes the + result back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "x" , + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "y" , + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "z" , + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_MID" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, "z" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "result" , + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "result" , + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + BinOp.mod_ (| + BinOp.add (| + M.get_name (| globals, "x" |), + M.get_name (| globals, "y" |) + |), + M.get_name (| globals, "z" |) + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + )) |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.get_name (| globals, "result" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition mulmod : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Modulo multiplication of the top 2 elements with the 3rd element. Pushes + the result back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "x" , + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "y" , + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "z" , + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_MID" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, "z" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "result" , + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "result" , + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + BinOp.mod_ (| + BinOp.mult (| + M.get_name (| globals, "x" |), + M.get_name (| globals, "y" |) + |), + M.get_name (| globals, "z" |) + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + )) |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.get_name (| globals, "result" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition exp : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Exponential operation of the top 2 elements. Pushes the result back on + the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "base" , + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "exponent" , + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "exponent_bits" , + M.call (| + M.get_field (| M.get_name (| globals, "exponent" |), "bit_length" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "exponent_bytes" , + BinOp.floor_div (| + BinOp.add (| + M.get_name (| globals, "exponent_bits" |), + Constant.int 7 + |), + Constant.int 8 + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + BinOp.add (| + M.get_name (| globals, "GAS_EXPONENTIATION" |), + BinOp.mult (| + M.get_name (| globals, "GAS_EXPONENTIATION_PER_BYTE" |), + M.get_name (| globals, "exponent_bytes" |) + |) + |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "result" , + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + M.call (| + M.get_name (| globals, "pow" |), + make_list [ + M.get_name (| globals, "base" |); + M.get_name (| globals, "exponent" |); + M.get_name (| globals, "U256_CEIL_VALUE" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.get_name (| globals, "result" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition signextend : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Sign extend operation. In other words, extend a signed number which + fits in N bytes to 32 bytes. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "byte_num" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "value" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_LOW" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.gt (| + M.get_name (| globals, "byte_num" |), + Constant.int 31 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "result" , + M.get_name (| globals, "value" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "value_bytes" , + M.call (| + M.get_name (| globals, "bytes" |), + make_list [ + M.call (| + M.get_field (| M.get_name (| globals, "value" |), "to_be_bytes32" |), + make_list [], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "value_bytes" , + M.slice (| + M.get_name (| globals, "value_bytes" |), + BinOp.sub (| + Constant.int 31, + M.call (| + M.get_name (| globals, "int" |), + make_list [ + M.get_name (| globals, "byte_num" |) + ], + make_dict [] + |) + |), + Constant.None_, + Constant.None_ + |) + |) in + let _ := M.assign_local (| + "sign_bit" , + BinOp.r_shift (| + M.get_subscript (| + M.get_name (| globals, "value_bytes" |), + Constant.int 0 + |), + Constant.int 7 + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, "sign_bit" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "result" , + M.call (| + M.get_field (| M.get_name (| globals, "U256" |), "from_be_bytes" |), + make_list [ + M.get_name (| globals, "value_bytes" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "num_bytes_prepend" , + BinOp.sub (| + Constant.int 32, + BinOp.add (| + M.get_name (| globals, "byte_num" |), + Constant.int 1 + |) + |) + |) in + let _ := M.assign_local (| + "result" , + M.call (| + M.get_field (| M.get_name (| globals, "U256" |), "from_be_bytes" |), + make_list [ + BinOp.add (| + M.call (| + M.get_name (| globals, "bytearray" |), + make_list [ + BinOp.mult (| + make_list [ + Constant.int 255 + ], + M.get_name (| globals, "num_bytes_prepend" |) + |) + ], + make_dict [] + |), + M.get_name (| globals, "value_bytes" |) + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )) |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.get_name (| globals, "result" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). diff --git a/CoqOfPython/ethereum/byzantium/vm/instructions/bitwise.v b/CoqOfPython/ethereum/byzantium/vm/instructions/bitwise.v new file mode 100644 index 0000000..78deb13 --- /dev/null +++ b/CoqOfPython/ethereum/byzantium/vm/instructions/bitwise.v @@ -0,0 +1,372 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.byzantium.vm.instructions.bitwise". + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) Bitwise Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM bitwise instructions. +". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". + +Axiom ethereum_byzantium_vm_imports_Evm : + IsImported globals "ethereum.byzantium.vm" "Evm". + +Axiom ethereum_byzantium_vm_gas_imports_GAS_VERY_LOW : + IsImported globals "ethereum.byzantium.vm.gas" "GAS_VERY_LOW". +Axiom ethereum_byzantium_vm_gas_imports_charge_gas : + IsImported globals "ethereum.byzantium.vm.gas" "charge_gas". + +Axiom ethereum_byzantium_vm_stack_imports_pop : + IsImported globals "ethereum.byzantium.vm.stack" "pop". +Axiom ethereum_byzantium_vm_stack_imports_push : + IsImported globals "ethereum.byzantium.vm.stack" "push". + +Definition bitwise_and : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Bitwise AND operation of the top 2 elements of the stack. Pushes the + result back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "x" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "y" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_VERY_LOW" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + BinOp.bit_and (| + M.get_name (| globals, "x" |), + M.get_name (| globals, "y" |) + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition bitwise_or : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Bitwise OR operation of the top 2 elements of the stack. Pushes the + result back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "x" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "y" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_VERY_LOW" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + BinOp.bit_or (| + M.get_name (| globals, "x" |), + M.get_name (| globals, "y" |) + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition bitwise_xor : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Bitwise XOR operation of the top 2 elements of the stack. Pushes the + result back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "x" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "y" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_VERY_LOW" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + BinOp.bit_xor (| + M.get_name (| globals, "x" |), + M.get_name (| globals, "y" |) + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition bitwise_not : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Bitwise NOT operation of the top element of the stack. Pushes the + result back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "x" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_VERY_LOW" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + UnOp.invert (| M.get_name (| globals, "x" |) |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition get_byte : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + For a word (defined by next top element of the stack), retrieve the + Nth byte (0-indexed and defined by top element of stack) from the + left (most significant) to right (least significant). + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "byte_index" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "word" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_VERY_LOW" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.gt_e (| + M.get_name (| globals, "byte_index" |), + Constant.int 32 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "result" , + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "extra_bytes_to_right" , + BinOp.sub (| + Constant.int 31, + M.get_name (| globals, "byte_index" |) + |) + |) in + let _ := M.assign_local (| + "word" , + BinOp.r_shift (| + M.get_name (| globals, "word" |), + BinOp.mult (| + M.get_name (| globals, "extra_bytes_to_right" |), + Constant.int 8 + |) + |) + |) in + let _ := M.assign_local (| + "word" , + BinOp.bit_and (| + M.get_name (| globals, "word" |), + Constant.int 255 + |) + |) in + let _ := M.assign_local (| + "result" , + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + M.get_name (| globals, "word" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + )) |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.get_name (| globals, "result" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). diff --git a/CoqOfPython/ethereum/byzantium/vm/instructions/block.v b/CoqOfPython/ethereum/byzantium/vm/instructions/block.v new file mode 100644 index 0000000..deb5d8d --- /dev/null +++ b/CoqOfPython/ethereum/byzantium/vm/instructions/block.v @@ -0,0 +1,348 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.byzantium.vm.instructions.block". + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) Block Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM block instructions. +". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". + +Axiom ethereum_byzantium_vm_imports_Evm : + IsImported globals "ethereum.byzantium.vm" "Evm". + +Axiom ethereum_byzantium_vm_gas_imports_GAS_BASE : + IsImported globals "ethereum.byzantium.vm.gas" "GAS_BASE". +Axiom ethereum_byzantium_vm_gas_imports_GAS_BLOCK_HASH : + IsImported globals "ethereum.byzantium.vm.gas" "GAS_BLOCK_HASH". +Axiom ethereum_byzantium_vm_gas_imports_charge_gas : + IsImported globals "ethereum.byzantium.vm.gas" "charge_gas". + +Axiom ethereum_byzantium_vm_stack_imports_pop : + IsImported globals "ethereum.byzantium.vm.stack" "pop". +Axiom ethereum_byzantium_vm_stack_imports_push : + IsImported globals "ethereum.byzantium.vm.stack" "push". + +Definition block_hash : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Push the hash of one of the 256 most recent complete blocks onto the + stack. The block number to hash is present at the top of the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "block_number" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_BLOCK_HASH" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + BoolOp.or (| + Compare.lt_e (| + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "env" |), "number" |), + M.get_name (| globals, "block_number" |) + |), + ltac:(M.monadic ( + Compare.gt (| + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "env" |), "number" |), + BinOp.add (| + M.get_name (| globals, "block_number" |), + Constant.int 256 + |) + |) + )) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "hash" , + Constant.bytes "00" + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "hash" , + M.get_subscript (| + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "env" |), "block_hashes" |), + UnOp.sub (| BinOp.sub (| + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "env" |), "number" |), + M.get_name (| globals, "block_number" |) + |) |) + |) + |) in + M.pure Constant.None_ + )) |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.call (| + M.get_field (| M.get_name (| globals, "U256" |), "from_be_bytes" |), + make_list [ + M.get_name (| globals, "hash" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition coinbase : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Push the current block's beneficiary address (address of the block miner) + onto the stack. + + Here the current block refers to the block in which the currently + executing transaction/call resides. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_BASE" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.call (| + M.get_field (| M.get_name (| globals, "U256" |), "from_be_bytes" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "env" |), "coinbase" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition timestamp : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Push the current block's timestamp onto the stack. Here the timestamp + being referred is actually the unix timestamp in seconds. + + Here the current block refers to the block in which the currently + executing transaction/call resides. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_BASE" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "env" |), "time" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition number : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Push the current block's number onto the stack. + + Here the current block refers to the block in which the currently + executing transaction/call resides. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_BASE" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "env" |), "number" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition difficulty : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Push the current block's difficulty onto the stack. + + Here the current block refers to the block in which the currently + executing transaction/call resides. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_BASE" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "env" |), "difficulty" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition gas_limit : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Push the current block's gas limit onto the stack. + + Here the current block refers to the block in which the currently + executing transaction/call resides. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_BASE" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "env" |), "gas_limit" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). diff --git a/CoqOfPython/ethereum/byzantium/vm/instructions/comparison.v b/CoqOfPython/ethereum/byzantium/vm/instructions/comparison.v new file mode 100644 index 0000000..b282bad --- /dev/null +++ b/CoqOfPython/ethereum/byzantium/vm/instructions/comparison.v @@ -0,0 +1,452 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.byzantium.vm.instructions.comparison". + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) Comparison Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM Comparison instructions. +". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". + +Axiom ethereum_byzantium_vm_imports_Evm : + IsImported globals "ethereum.byzantium.vm" "Evm". + +Axiom ethereum_byzantium_vm_gas_imports_GAS_VERY_LOW : + IsImported globals "ethereum.byzantium.vm.gas" "GAS_VERY_LOW". +Axiom ethereum_byzantium_vm_gas_imports_charge_gas : + IsImported globals "ethereum.byzantium.vm.gas" "charge_gas". + +Axiom ethereum_byzantium_vm_stack_imports_pop : + IsImported globals "ethereum.byzantium.vm.stack" "pop". +Axiom ethereum_byzantium_vm_stack_imports_push : + IsImported globals "ethereum.byzantium.vm.stack" "push". + +Definition less_than : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Checks if the top element is less than the next top element. Pushes the + result back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "left" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "right" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_VERY_LOW" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "result" , + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Compare.lt (| + M.get_name (| globals, "left" |), + M.get_name (| globals, "right" |) + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.get_name (| globals, "result" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition signed_less_than : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Signed less-than comparison. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "left" , + M.call (| + M.get_field (| M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |), "to_signed" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "right" , + M.call (| + M.get_field (| M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |), "to_signed" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_VERY_LOW" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "result" , + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Compare.lt (| + M.get_name (| globals, "left" |), + M.get_name (| globals, "right" |) + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.get_name (| globals, "result" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition greater_than : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Checks if the top element is greater than the next top element. Pushes + the result back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "left" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "right" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_VERY_LOW" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "result" , + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Compare.gt (| + M.get_name (| globals, "left" |), + M.get_name (| globals, "right" |) + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.get_name (| globals, "result" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition signed_greater_than : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Signed greater-than comparison. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "left" , + M.call (| + M.get_field (| M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |), "to_signed" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "right" , + M.call (| + M.get_field (| M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |), "to_signed" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_VERY_LOW" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "result" , + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Compare.gt (| + M.get_name (| globals, "left" |), + M.get_name (| globals, "right" |) + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.get_name (| globals, "result" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition equal : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Checks if the top element is equal to the next top element. Pushes + the result back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "left" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "right" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_VERY_LOW" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "result" , + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Compare.eq (| + M.get_name (| globals, "left" |), + M.get_name (| globals, "right" |) + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.get_name (| globals, "result" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition is_zero : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Checks if the top element is equal to 0. Pushes the result back on the + stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "x" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_VERY_LOW" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "result" , + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Compare.eq (| + M.get_name (| globals, "x" |), + Constant.int 0 + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.get_name (| globals, "result" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). diff --git a/CoqOfPython/ethereum/byzantium/vm/instructions/control_flow.v b/CoqOfPython/ethereum/byzantium/vm/instructions/control_flow.v new file mode 100644 index 0000000..01a71f7 --- /dev/null +++ b/CoqOfPython/ethereum/byzantium/vm/instructions/control_flow.v @@ -0,0 +1,350 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.byzantium.vm.instructions.control_flow". + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) Control Flow Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM control flow instructions. +". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". + +Axiom ethereum_byzantium_vm_gas_imports_GAS_BASE : + IsImported globals "ethereum.byzantium.vm.gas" "GAS_BASE". +Axiom ethereum_byzantium_vm_gas_imports_GAS_HIGH : + IsImported globals "ethereum.byzantium.vm.gas" "GAS_HIGH". +Axiom ethereum_byzantium_vm_gas_imports_GAS_JUMPDEST : + IsImported globals "ethereum.byzantium.vm.gas" "GAS_JUMPDEST". +Axiom ethereum_byzantium_vm_gas_imports_GAS_MID : + IsImported globals "ethereum.byzantium.vm.gas" "GAS_MID". +Axiom ethereum_byzantium_vm_gas_imports_charge_gas : + IsImported globals "ethereum.byzantium.vm.gas" "charge_gas". + +Axiom ethereum_byzantium_vm_imports_Evm : + IsImported globals "ethereum.byzantium.vm" "Evm". + +Axiom ethereum_byzantium_vm_exceptions_imports_InvalidJumpDestError : + IsImported globals "ethereum.byzantium.vm.exceptions" "InvalidJumpDestError". + +Axiom ethereum_byzantium_vm_stack_imports_pop : + IsImported globals "ethereum.byzantium.vm.stack" "pop". +Axiom ethereum_byzantium_vm_stack_imports_push : + IsImported globals "ethereum.byzantium.vm.stack" "push". + +Definition stop : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Stop further execution of EVM code. + + Parameters + ---------- + evm : + The current EVM frame. + " in + let _ := M.pass (| |) in + let _ := M.pass (| |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, "evm" |), "running" |), + Constant.bool false + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition jump : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Alter the program counter to the location specified by the top of the + stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "jump_dest" , + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_MID" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.not_in (| + M.get_name (| globals, "jump_dest" |), + M.get_field (| M.get_name (| globals, "evm" |), "valid_jump_destinations" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, "InvalidJumpDestError" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.get_name (| globals, "jump_dest" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Definition jumpi : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Alter the program counter to the specified location if and only if a + condition is true. If the condition is not true, then the program counter + would increase only by 1. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "jump_dest" , + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "conditional_value" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_HIGH" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, "conditional_value" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "destination" , + BinOp.add (| + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + Compare.not_in (| + M.get_name (| globals, "jump_dest" |), + M.get_field (| M.get_name (| globals, "evm" |), "valid_jump_destinations" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, "InvalidJumpDestError" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "destination" , + M.get_name (| globals, "jump_dest" |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )) |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.get_name (| globals, "destination" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Definition pc : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Push onto the stack the value of the program counter after reaching the + current instruction and without increasing it for the next instruction. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_BASE" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "pc" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition gas_left : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Push the amount of available gas (including the corresponding reduction + for the cost of this instruction) onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_BASE" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "gas_left" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition jumpdest : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Mark a valid destination for jumps. This is a noop, present only + to be used by `JUMP` and `JUMPI` opcodes to verify that their jump is + valid. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_JUMPDEST" |) + ], + make_dict [] + |) in + let _ := M.pass (| |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). diff --git a/CoqOfPython/ethereum/byzantium/vm/instructions/environment.v b/CoqOfPython/ethereum/byzantium/vm/instructions/environment.v new file mode 100644 index 0000000..150687d --- /dev/null +++ b/CoqOfPython/ethereum/byzantium/vm/instructions/environment.v @@ -0,0 +1,1210 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.byzantium.vm.instructions.environment". + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) Environmental Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM environment related instructions. +". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". + +Axiom ethereum_utils_ensure_imports_ensure : + IsImported globals "ethereum.utils.ensure" "ensure". + +Axiom ethereum_utils_numeric_imports_ceil32 : + IsImported globals "ethereum.utils.numeric" "ceil32". + +Axiom ethereum_byzantium_state_imports_get_account : + IsImported globals "ethereum.byzantium.state" "get_account". + +Axiom ethereum_byzantium_utils_address_imports_to_address : + IsImported globals "ethereum.byzantium.utils.address" "to_address". + +Axiom ethereum_byzantium_vm_memory_imports_buffer_read : + IsImported globals "ethereum.byzantium.vm.memory" "buffer_read". +Axiom ethereum_byzantium_vm_memory_imports_memory_write : + IsImported globals "ethereum.byzantium.vm.memory" "memory_write". + +Axiom ethereum_byzantium_vm_imports_Evm : + IsImported globals "ethereum.byzantium.vm" "Evm". + +Axiom ethereum_byzantium_vm_exceptions_imports_OutOfBoundsRead : + IsImported globals "ethereum.byzantium.vm.exceptions" "OutOfBoundsRead". + +Axiom ethereum_byzantium_vm_gas_imports_GAS_BALANCE : + IsImported globals "ethereum.byzantium.vm.gas" "GAS_BALANCE". +Axiom ethereum_byzantium_vm_gas_imports_GAS_BASE : + IsImported globals "ethereum.byzantium.vm.gas" "GAS_BASE". +Axiom ethereum_byzantium_vm_gas_imports_GAS_COPY : + IsImported globals "ethereum.byzantium.vm.gas" "GAS_COPY". +Axiom ethereum_byzantium_vm_gas_imports_GAS_EXTERNAL : + IsImported globals "ethereum.byzantium.vm.gas" "GAS_EXTERNAL". +Axiom ethereum_byzantium_vm_gas_imports_GAS_RETURN_DATA_COPY : + IsImported globals "ethereum.byzantium.vm.gas" "GAS_RETURN_DATA_COPY". +Axiom ethereum_byzantium_vm_gas_imports_GAS_VERY_LOW : + IsImported globals "ethereum.byzantium.vm.gas" "GAS_VERY_LOW". +Axiom ethereum_byzantium_vm_gas_imports_calculate_gas_extend_memory : + IsImported globals "ethereum.byzantium.vm.gas" "calculate_gas_extend_memory". +Axiom ethereum_byzantium_vm_gas_imports_charge_gas : + IsImported globals "ethereum.byzantium.vm.gas" "charge_gas". + +Axiom ethereum_byzantium_vm_stack_imports_pop : + IsImported globals "ethereum.byzantium.vm.stack" "pop". +Axiom ethereum_byzantium_vm_stack_imports_push : + IsImported globals "ethereum.byzantium.vm.stack" "push". + +Definition address : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Pushes the address of the current executing account to the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_BASE" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.call (| + M.get_field (| M.get_name (| globals, "U256" |), "from_be_bytes" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "current_target" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition balance : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Pushes the balance of the given account onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "address" , + M.call (| + M.get_name (| globals, "to_address" |), + make_list [ + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_BALANCE" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "balance" , + M.get_field (| M.call (| + M.get_name (| globals, "get_account" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "env" |), "state" |); + M.get_name (| globals, "address" |) + ], + make_dict [] + |), "balance" |) + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.get_name (| globals, "balance" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition origin : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Pushes the address of the original transaction sender to the stack. + The origin address can only be an EOA. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_BASE" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.call (| + M.get_field (| M.get_name (| globals, "U256" |), "from_be_bytes" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "env" |), "origin" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition caller : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Pushes the address of the caller onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_BASE" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.call (| + M.get_field (| M.get_name (| globals, "U256" |), "from_be_bytes" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "caller" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition callvalue : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Push the value (in wei) sent with the call onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_BASE" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "value" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition calldataload : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Push a word (32 bytes) of the input data belonging to the current + environment onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "start_index" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_VERY_LOW" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "value" , + M.call (| + M.get_name (| globals, "buffer_read" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "data" |); + M.get_name (| globals, "start_index" |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 32 + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.call (| + M.get_field (| M.get_name (| globals, "U256" |), "from_be_bytes" |), + make_list [ + M.get_name (| globals, "value" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition calldatasize : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Push the size of input data in current environment onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_BASE" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "data" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition calldatacopy : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Copy a portion of the input data in current environment to memory. + + This will also expand the memory, in case that the memory is insufficient + to store the data. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "memory_start_index" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "data_start_index" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "size" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "words" , + BinOp.floor_div (| + M.call (| + M.get_name (| globals, "ceil32" |), + make_list [ + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.get_name (| globals, "size" |) + ], + make_dict [] + |) + ], + make_dict [] + |), + Constant.int 32 + |) + |) in + let _ := M.assign_local (| + "copy_gas_cost" , + BinOp.mult (| + M.get_name (| globals, "GAS_COPY" |), + M.get_name (| globals, "words" |) + |) + |) in + let _ := M.assign_local (| + "extend_memory" , + M.call (| + M.get_name (| globals, "calculate_gas_extend_memory" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "memory" |); + make_list [ + make_tuple [ M.get_name (| globals, "memory_start_index" |); M.get_name (| globals, "size" |) ] + ] + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + BinOp.add (| + BinOp.add (| + M.get_name (| globals, "GAS_VERY_LOW" |), + M.get_name (| globals, "copy_gas_cost" |) + |), + M.get_field (| M.get_name (| globals, "extend_memory" |), "cost" |) + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "memory" |), + BinOp.mult (| + Constant.bytes "00", + M.get_field (| M.get_name (| globals, "extend_memory" |), "expand_by" |) + |) + |) in + let _ := M.assign_local (| + "value" , + M.call (| + M.get_name (| globals, "buffer_read" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "data" |); + M.get_name (| globals, "data_start_index" |); + M.get_name (| globals, "size" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "memory_write" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "memory" |); + M.get_name (| globals, "memory_start_index" |); + M.get_name (| globals, "value" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition codesize : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Push the size of code running in current environment onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_BASE" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "code" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition codecopy : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Copy a portion of the code in current environment to memory. + + This will also expand the memory, in case that the memory is insufficient + to store the data. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "memory_start_index" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "code_start_index" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "size" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "words" , + BinOp.floor_div (| + M.call (| + M.get_name (| globals, "ceil32" |), + make_list [ + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.get_name (| globals, "size" |) + ], + make_dict [] + |) + ], + make_dict [] + |), + Constant.int 32 + |) + |) in + let _ := M.assign_local (| + "copy_gas_cost" , + BinOp.mult (| + M.get_name (| globals, "GAS_COPY" |), + M.get_name (| globals, "words" |) + |) + |) in + let _ := M.assign_local (| + "extend_memory" , + M.call (| + M.get_name (| globals, "calculate_gas_extend_memory" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "memory" |); + make_list [ + make_tuple [ M.get_name (| globals, "memory_start_index" |); M.get_name (| globals, "size" |) ] + ] + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + BinOp.add (| + BinOp.add (| + M.get_name (| globals, "GAS_VERY_LOW" |), + M.get_name (| globals, "copy_gas_cost" |) + |), + M.get_field (| M.get_name (| globals, "extend_memory" |), "cost" |) + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "memory" |), + BinOp.mult (| + Constant.bytes "00", + M.get_field (| M.get_name (| globals, "extend_memory" |), "expand_by" |) + |) + |) in + let _ := M.assign_local (| + "value" , + M.call (| + M.get_name (| globals, "buffer_read" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "code" |); + M.get_name (| globals, "code_start_index" |); + M.get_name (| globals, "size" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "memory_write" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "memory" |); + M.get_name (| globals, "memory_start_index" |); + M.get_name (| globals, "value" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition gasprice : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Push the gas price used in current environment onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_BASE" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "env" |), "gas_price" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition extcodesize : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Push the code size of a given account onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "address" , + M.call (| + M.get_name (| globals, "to_address" |), + make_list [ + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_EXTERNAL" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "codesize" , + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_field (| M.call (| + M.get_name (| globals, "get_account" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "env" |), "state" |); + M.get_name (| globals, "address" |) + ], + make_dict [] + |), "code" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.get_name (| globals, "codesize" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition extcodecopy : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Copy a portion of an account's code to memory. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "address" , + M.call (| + M.get_name (| globals, "to_address" |), + make_list [ + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_start_index" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "code_start_index" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "size" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "words" , + BinOp.floor_div (| + M.call (| + M.get_name (| globals, "ceil32" |), + make_list [ + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.get_name (| globals, "size" |) + ], + make_dict [] + |) + ], + make_dict [] + |), + Constant.int 32 + |) + |) in + let _ := M.assign_local (| + "copy_gas_cost" , + BinOp.mult (| + M.get_name (| globals, "GAS_COPY" |), + M.get_name (| globals, "words" |) + |) + |) in + let _ := M.assign_local (| + "extend_memory" , + M.call (| + M.get_name (| globals, "calculate_gas_extend_memory" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "memory" |); + make_list [ + make_tuple [ M.get_name (| globals, "memory_start_index" |); M.get_name (| globals, "size" |) ] + ] + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + BinOp.add (| + BinOp.add (| + M.get_name (| globals, "GAS_EXTERNAL" |), + M.get_name (| globals, "copy_gas_cost" |) + |), + M.get_field (| M.get_name (| globals, "extend_memory" |), "cost" |) + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "memory" |), + BinOp.mult (| + Constant.bytes "00", + M.get_field (| M.get_name (| globals, "extend_memory" |), "expand_by" |) + |) + |) in + let _ := M.assign_local (| + "code" , + M.get_field (| M.call (| + M.get_name (| globals, "get_account" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "env" |), "state" |); + M.get_name (| globals, "address" |) + ], + make_dict [] + |), "code" |) + |) in + let _ := M.assign_local (| + "value" , + M.call (| + M.get_name (| globals, "buffer_read" |), + make_list [ + M.get_name (| globals, "code" |); + M.get_name (| globals, "code_start_index" |); + M.get_name (| globals, "size" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "memory_write" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "memory" |); + M.get_name (| globals, "memory_start_index" |); + M.get_name (| globals, "value" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition returndatasize : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Pushes the size of the return data buffer onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_BASE" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "return_data" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition returndatacopy : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Copies data from the return data buffer code to memory + + Parameters + ---------- + evm : + The current EVM frame. + " in + let _ := M.assign_local (| + "memory_start_index" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "return_data_start_position" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "size" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "words" , + BinOp.floor_div (| + M.call (| + M.get_name (| globals, "ceil32" |), + make_list [ + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.get_name (| globals, "size" |) + ], + make_dict [] + |) + ], + make_dict [] + |), + Constant.int 32 + |) + |) in + let _ := M.assign_local (| + "copy_gas_cost" , + BinOp.mult (| + M.get_name (| globals, "GAS_RETURN_DATA_COPY" |), + M.get_name (| globals, "words" |) + |) + |) in + let _ := M.assign_local (| + "extend_memory" , + M.call (| + M.get_name (| globals, "calculate_gas_extend_memory" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "memory" |); + make_list [ + make_tuple [ M.get_name (| globals, "memory_start_index" |); M.get_name (| globals, "size" |) ] + ] + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + BinOp.add (| + BinOp.add (| + M.get_name (| globals, "GAS_VERY_LOW" |), + M.get_name (| globals, "copy_gas_cost" |) + |), + M.get_field (| M.get_name (| globals, "extend_memory" |), "cost" |) + |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + Compare.lt_e (| + BinOp.add (| + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.get_name (| globals, "return_data_start_position" |) + ], + make_dict [] + |), + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.get_name (| globals, "size" |) + ], + make_dict [] + |) + |), + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "return_data" |) + ], + make_dict [] + |) + |); + M.get_name (| globals, "OutOfBoundsRead" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "memory" |), + BinOp.mult (| + Constant.bytes "00", + M.get_field (| M.get_name (| globals, "extend_memory" |), "expand_by" |) + |) + |) in + let _ := M.assign_local (| + "value" , + M.slice (| + M.get_field (| M.get_name (| globals, "evm" |), "return_data" |), + M.get_name (| globals, "return_data_start_position" |), + BinOp.add (| + M.get_name (| globals, "return_data_start_position" |), + M.get_name (| globals, "size" |) + |), + Constant.None_ + |) + |) in + let _ := M.call (| + M.get_name (| globals, "memory_write" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "memory" |); + M.get_name (| globals, "memory_start_index" |); + M.get_name (| globals, "value" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). diff --git a/CoqOfPython/ethereum/byzantium/vm/instructions/keccak.v b/CoqOfPython/ethereum/byzantium/vm/instructions/keccak.v new file mode 100644 index 0000000..c54b6cc --- /dev/null +++ b/CoqOfPython/ethereum/byzantium/vm/instructions/keccak.v @@ -0,0 +1,188 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.byzantium.vm.instructions.keccak". + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) Keccak Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM keccak instructions. +". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". + +Axiom ethereum_crypto_hash_imports_keccak256 : + IsImported globals "ethereum.crypto.hash" "keccak256". + +Axiom ethereum_utils_numeric_imports_ceil32 : + IsImported globals "ethereum.utils.numeric" "ceil32". + +Axiom ethereum_byzantium_vm_imports_Evm : + IsImported globals "ethereum.byzantium.vm" "Evm". + +Axiom ethereum_byzantium_vm_gas_imports_GAS_KECCAK256 : + IsImported globals "ethereum.byzantium.vm.gas" "GAS_KECCAK256". +Axiom ethereum_byzantium_vm_gas_imports_GAS_KECCAK256_WORD : + IsImported globals "ethereum.byzantium.vm.gas" "GAS_KECCAK256_WORD". +Axiom ethereum_byzantium_vm_gas_imports_calculate_gas_extend_memory : + IsImported globals "ethereum.byzantium.vm.gas" "calculate_gas_extend_memory". +Axiom ethereum_byzantium_vm_gas_imports_charge_gas : + IsImported globals "ethereum.byzantium.vm.gas" "charge_gas". + +Axiom ethereum_byzantium_vm_memory_imports_memory_read_bytes : + IsImported globals "ethereum.byzantium.vm.memory" "memory_read_bytes". + +Axiom ethereum_byzantium_vm_stack_imports_pop : + IsImported globals "ethereum.byzantium.vm.stack" "pop". +Axiom ethereum_byzantium_vm_stack_imports_push : + IsImported globals "ethereum.byzantium.vm.stack" "push". + +Definition keccak : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Pushes to the stack the Keccak-256 hash of a region of memory. + + This also expands the memory, in case the memory is insufficient to + access the data's memory location. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "memory_start_index" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "size" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "words" , + BinOp.floor_div (| + M.call (| + M.get_name (| globals, "ceil32" |), + make_list [ + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.get_name (| globals, "size" |) + ], + make_dict [] + |) + ], + make_dict [] + |), + Constant.int 32 + |) + |) in + let _ := M.assign_local (| + "word_gas_cost" , + BinOp.mult (| + M.get_name (| globals, "GAS_KECCAK256_WORD" |), + M.get_name (| globals, "words" |) + |) + |) in + let _ := M.assign_local (| + "extend_memory" , + M.call (| + M.get_name (| globals, "calculate_gas_extend_memory" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "memory" |); + make_list [ + make_tuple [ M.get_name (| globals, "memory_start_index" |); M.get_name (| globals, "size" |) ] + ] + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + BinOp.add (| + BinOp.add (| + M.get_name (| globals, "GAS_KECCAK256" |), + M.get_name (| globals, "word_gas_cost" |) + |), + M.get_field (| M.get_name (| globals, "extend_memory" |), "cost" |) + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "memory" |), + BinOp.mult (| + Constant.bytes "00", + M.get_field (| M.get_name (| globals, "extend_memory" |), "expand_by" |) + |) + |) in + let _ := M.assign_local (| + "data" , + M.call (| + M.get_name (| globals, "memory_read_bytes" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "memory" |); + M.get_name (| globals, "memory_start_index" |); + M.get_name (| globals, "size" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "hash" , + M.call (| + M.get_name (| globals, "keccak256" |), + make_list [ + M.get_name (| globals, "data" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.call (| + M.get_field (| M.get_name (| globals, "U256" |), "from_be_bytes" |), + make_list [ + M.get_name (| globals, "hash" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). diff --git a/CoqOfPython/ethereum/byzantium/vm/instructions/log.v b/CoqOfPython/ethereum/byzantium/vm/instructions/log.v new file mode 100644 index 0000000..4f0424b --- /dev/null +++ b/CoqOfPython/ethereum/byzantium/vm/instructions/log.v @@ -0,0 +1,256 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.byzantium.vm.instructions.log". + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) Logging Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM logging instructions. +". + +Axiom functools_imports_partial : + IsImported globals "functools" "partial". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". + +Axiom ethereum_utils_ensure_imports_ensure : + IsImported globals "ethereum.utils.ensure" "ensure". + +Axiom ethereum_byzantium_blocks_imports_Log : + IsImported globals "ethereum.byzantium.blocks" "Log". + +Axiom ethereum_byzantium_vm_imports_Evm : + IsImported globals "ethereum.byzantium.vm" "Evm". + +Axiom ethereum_byzantium_vm_exceptions_imports_WriteInStaticContext : + IsImported globals "ethereum.byzantium.vm.exceptions" "WriteInStaticContext". + +Axiom ethereum_byzantium_vm_gas_imports_GAS_LOG : + IsImported globals "ethereum.byzantium.vm.gas" "GAS_LOG". +Axiom ethereum_byzantium_vm_gas_imports_GAS_LOG_DATA : + IsImported globals "ethereum.byzantium.vm.gas" "GAS_LOG_DATA". +Axiom ethereum_byzantium_vm_gas_imports_GAS_LOG_TOPIC : + IsImported globals "ethereum.byzantium.vm.gas" "GAS_LOG_TOPIC". +Axiom ethereum_byzantium_vm_gas_imports_calculate_gas_extend_memory : + IsImported globals "ethereum.byzantium.vm.gas" "calculate_gas_extend_memory". +Axiom ethereum_byzantium_vm_gas_imports_charge_gas : + IsImported globals "ethereum.byzantium.vm.gas" "charge_gas". + +Axiom ethereum_byzantium_vm_memory_imports_memory_read_bytes : + IsImported globals "ethereum.byzantium.vm.memory" "memory_read_bytes". + +Axiom ethereum_byzantium_vm_stack_imports_pop : + IsImported globals "ethereum.byzantium.vm.stack" "pop". + +Definition log_n : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm"; "num_topics" ] |) in + let _ := Constant.str " + Appends a log entry, having `num_topics` topics, to the evm logs. + + This will also expand the memory if the data (required by the log entry) + corresponding to the memory is not accessible. + + Parameters + ---------- + evm : + The current EVM frame. + num_topics : + The number of topics to be included in the log entry. + + " in + let _ := M.assign_local (| + "memory_start_index" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "size" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "topics" , + make_list [] + |) in + let _ := + M.for_ (| + M.get_name (| globals, "_" |), + M.call (| + M.get_name (| globals, "range" |), + make_list [ + M.get_name (| globals, "num_topics" |) + ], + make_dict [] + |), + ltac:(M.monadic ( + let _ := M.assign_local (| + "topic" , + M.call (| + M.get_field (| M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |), "to_be_bytes32" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_field (| M.get_name (| globals, "topics" |), "append" |), + make_list [ + M.get_name (| globals, "topic" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := M.assign_local (| + "extend_memory" , + M.call (| + M.get_name (| globals, "calculate_gas_extend_memory" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "memory" |); + make_list [ + make_tuple [ M.get_name (| globals, "memory_start_index" |); M.get_name (| globals, "size" |) ] + ] + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + BinOp.add (| + BinOp.add (| + BinOp.add (| + M.get_name (| globals, "GAS_LOG" |), + BinOp.mult (| + M.get_name (| globals, "GAS_LOG_DATA" |), + M.get_name (| globals, "size" |) + |) + |), + BinOp.mult (| + M.get_name (| globals, "GAS_LOG_TOPIC" |), + M.get_name (| globals, "num_topics" |) + |) + |), + M.get_field (| M.get_name (| globals, "extend_memory" |), "cost" |) + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "memory" |), + BinOp.mult (| + Constant.bytes "00", + M.get_field (| M.get_name (| globals, "extend_memory" |), "expand_by" |) + |) + |) in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + UnOp.not (| M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "is_static" |) |); + M.get_name (| globals, "WriteInStaticContext" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "log_entry" , + M.call (| + M.get_name (| globals, "Log" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, "evm" |), "logs" |), + BinOp.add (| + M.get_field (| M.get_name (| globals, "evm" |), "logs" |), + make_tuple [ M.get_name (| globals, "log_entry" |) ] + |) + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition log0 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "log_n" |) + ], + make_dict [] + |) +)). + +Definition log1 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "log_n" |) + ], + make_dict [] + |) +)). + +Definition log2 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "log_n" |) + ], + make_dict [] + |) +)). + +Definition log3 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "log_n" |) + ], + make_dict [] + |) +)). + +Definition log4 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "log_n" |) + ], + make_dict [] + |) +)). diff --git a/CoqOfPython/ethereum/byzantium/vm/instructions/memory.v b/CoqOfPython/ethereum/byzantium/vm/instructions/memory.v new file mode 100644 index 0000000..ff2aeb3 --- /dev/null +++ b/CoqOfPython/ethereum/byzantium/vm/instructions/memory.v @@ -0,0 +1,393 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.byzantium.vm.instructions.memory". + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) Memory Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM Memory instructions. +". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_Bytes : + IsImported globals "ethereum.base_types" "Bytes". + +Axiom ethereum_byzantium_vm_imports_Evm : + IsImported globals "ethereum.byzantium.vm" "Evm". + +Axiom ethereum_byzantium_vm_gas_imports_GAS_BASE : + IsImported globals "ethereum.byzantium.vm.gas" "GAS_BASE". +Axiom ethereum_byzantium_vm_gas_imports_GAS_VERY_LOW : + IsImported globals "ethereum.byzantium.vm.gas" "GAS_VERY_LOW". +Axiom ethereum_byzantium_vm_gas_imports_calculate_gas_extend_memory : + IsImported globals "ethereum.byzantium.vm.gas" "calculate_gas_extend_memory". +Axiom ethereum_byzantium_vm_gas_imports_charge_gas : + IsImported globals "ethereum.byzantium.vm.gas" "charge_gas". + +Axiom ethereum_byzantium_vm_memory_imports_memory_read_bytes : + IsImported globals "ethereum.byzantium.vm.memory" "memory_read_bytes". +Axiom ethereum_byzantium_vm_memory_imports_memory_write : + IsImported globals "ethereum.byzantium.vm.memory" "memory_write". + +Axiom ethereum_byzantium_vm_stack_imports_pop : + IsImported globals "ethereum.byzantium.vm.stack" "pop". +Axiom ethereum_byzantium_vm_stack_imports_push : + IsImported globals "ethereum.byzantium.vm.stack" "push". + +Definition mstore : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Stores a word to memory. + This also expands the memory, if the memory is + insufficient to store the word. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "start_position" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "value" , + M.call (| + M.get_field (| M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |), "to_be_bytes32" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "extend_memory" , + M.call (| + M.get_name (| globals, "calculate_gas_extend_memory" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "memory" |); + make_list [ + make_tuple [ M.get_name (| globals, "start_position" |); M.call (| + M.get_name (| globals, "U256" |), + make_list [ + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_name (| globals, "value" |) + ], + make_dict [] + |) + ], + make_dict [] + |) ] + ] + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + BinOp.add (| + M.get_name (| globals, "GAS_VERY_LOW" |), + M.get_field (| M.get_name (| globals, "extend_memory" |), "cost" |) + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "memory" |), + BinOp.mult (| + Constant.bytes "00", + M.get_field (| M.get_name (| globals, "extend_memory" |), "expand_by" |) + |) + |) in + let _ := M.call (| + M.get_name (| globals, "memory_write" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "memory" |); + M.get_name (| globals, "start_position" |); + M.get_name (| globals, "value" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition mstore8 : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Stores a byte to memory. + This also expands the memory, if the memory is + insufficient to store the word. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "start_position" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "value" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "extend_memory" , + M.call (| + M.get_name (| globals, "calculate_gas_extend_memory" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "memory" |); + make_list [ + make_tuple [ M.get_name (| globals, "start_position" |); M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 1 + ], + make_dict [] + |) ] + ] + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + BinOp.add (| + M.get_name (| globals, "GAS_VERY_LOW" |), + M.get_field (| M.get_name (| globals, "extend_memory" |), "cost" |) + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "memory" |), + BinOp.mult (| + Constant.bytes "00", + M.get_field (| M.get_name (| globals, "extend_memory" |), "expand_by" |) + |) + |) in + let _ := M.assign_local (| + "normalized_bytes_value" , + M.call (| + M.get_name (| globals, "Bytes" |), + make_list [ + make_list [ + BinOp.bit_and (| + M.get_name (| globals, "value" |), + Constant.int 255 + |) + ] + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "memory_write" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "memory" |); + M.get_name (| globals, "start_position" |); + M.get_name (| globals, "normalized_bytes_value" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition mload : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Load word from memory. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "start_position" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "extend_memory" , + M.call (| + M.get_name (| globals, "calculate_gas_extend_memory" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "memory" |); + make_list [ + make_tuple [ M.get_name (| globals, "start_position" |); M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 32 + ], + make_dict [] + |) ] + ] + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + BinOp.add (| + M.get_name (| globals, "GAS_VERY_LOW" |), + M.get_field (| M.get_name (| globals, "extend_memory" |), "cost" |) + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "memory" |), + BinOp.mult (| + Constant.bytes "00", + M.get_field (| M.get_name (| globals, "extend_memory" |), "expand_by" |) + |) + |) in + let _ := M.assign_local (| + "value" , + M.call (| + M.get_field (| M.get_name (| globals, "U256" |), "from_be_bytes" |), + make_list [ + M.call (| + M.get_name (| globals, "memory_read_bytes" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "memory" |); + M.get_name (| globals, "start_position" |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 32 + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.get_name (| globals, "value" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition msize : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Push the size of active memory in bytes onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_BASE" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "memory" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). diff --git a/CoqOfPython/ethereum/byzantium/vm/instructions/stack.v b/CoqOfPython/ethereum/byzantium/vm/instructions/stack.v new file mode 100644 index 0000000..2b2ad26 --- /dev/null +++ b/CoqOfPython/ethereum/byzantium/vm/instructions/stack.v @@ -0,0 +1,947 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.byzantium.vm.instructions.stack". + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) Stack Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM stack related instructions. +". + +Axiom functools_imports_partial : + IsImported globals "functools" "partial". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". + +Axiom ethereum_utils_ensure_imports_ensure : + IsImported globals "ethereum.utils.ensure" "ensure". + +Axiom ethereum_byzantium_vm_imports_Evm : + IsImported globals "ethereum.byzantium.vm" "Evm". +Axiom ethereum_byzantium_vm_imports_stack : + IsImported globals "ethereum.byzantium.vm" "stack". + +Axiom ethereum_byzantium_vm_exceptions_imports_StackUnderflowError : + IsImported globals "ethereum.byzantium.vm.exceptions" "StackUnderflowError". + +Axiom ethereum_byzantium_vm_gas_imports_GAS_BASE : + IsImported globals "ethereum.byzantium.vm.gas" "GAS_BASE". +Axiom ethereum_byzantium_vm_gas_imports_GAS_VERY_LOW : + IsImported globals "ethereum.byzantium.vm.gas" "GAS_VERY_LOW". +Axiom ethereum_byzantium_vm_gas_imports_charge_gas : + IsImported globals "ethereum.byzantium.vm.gas" "charge_gas". + +Axiom ethereum_byzantium_vm_memory_imports_buffer_read : + IsImported globals "ethereum.byzantium.vm.memory" "buffer_read". + +Definition pop : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Remove item from stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.call (| + M.get_field (| M.get_name (| globals, "stack" |), "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_BASE" |) + ], + make_dict [] + |) in + let _ := M.pass (| |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition push_n : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm"; "num_bytes" ] |) in + let _ := Constant.str " + Pushes a N-byte immediate onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + num_bytes : + The number of immediate bytes to be read from the code and pushed to + the stack. + + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_VERY_LOW" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "data_to_push" , + M.call (| + M.get_field (| M.get_name (| globals, "U256" |), "from_be_bytes" |), + make_list [ + M.call (| + M.get_name (| globals, "buffer_read" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "code" |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + BinOp.add (| + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) + ], + make_dict [] + |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + M.get_name (| globals, "num_bytes" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_field (| M.get_name (| globals, "stack" |), "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.get_name (| globals, "data_to_push" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + BinOp.add (| + Constant.int 1, + M.get_name (| globals, "num_bytes" |) + |) + |) in + M.pure Constant.None_)). + +Definition dup_n : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm"; "item_number" ] |) in + let _ := Constant.str " + Duplicate the Nth stack item (from top of the stack) to the top of stack. + + Parameters + ---------- + evm : + The current EVM frame. + + item_number : + The stack item number (0-indexed from top of stack) to be duplicated + to the top of stack. + + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_VERY_LOW" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + Compare.lt (| + M.get_name (| globals, "item_number" |), + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |); + M.get_name (| globals, "StackUnderflowError" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "data_to_duplicate" , + M.get_subscript (| + M.get_field (| M.get_name (| globals, "evm" |), "stack" |), + BinOp.sub (| + BinOp.sub (| + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |), + Constant.int 1 + |), + M.get_name (| globals, "item_number" |) + |) + |) + |) in + let _ := M.call (| + M.get_field (| M.get_name (| globals, "stack" |), "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.get_name (| globals, "data_to_duplicate" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition swap_n : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm"; "item_number" ] |) in + let _ := Constant.str " + Swap the top and the `item_number` element of the stack, where + the top of the stack is position zero. + + If `item_number` is zero, this function does nothing (which should not be + possible, since there is no `SWAP0` instruction). + + Parameters + ---------- + evm : + The current EVM frame. + + item_number : + The stack item number (0-indexed from top of stack) to be swapped + with the top of stack element. + + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_VERY_LOW" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + Compare.lt (| + M.get_name (| globals, "item_number" |), + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |); + M.get_name (| globals, "StackUnderflowError" |) + ], + make_dict [] + |) in + let _ := M.assign (| + make_tuple [ M.get_subscript (| + M.get_field (| M.get_name (| globals, "evm" |), "stack" |), + UnOp.sub (| Constant.int 1 |) + |); M.get_subscript (| + M.get_field (| M.get_name (| globals, "evm" |), "stack" |), + BinOp.sub (| + UnOp.sub (| Constant.int 1 |), + M.get_name (| globals, "item_number" |) + |) + |) ], + make_tuple [ M.get_subscript (| + M.get_field (| M.get_name (| globals, "evm" |), "stack" |), + BinOp.sub (| + UnOp.sub (| Constant.int 1 |), + M.get_name (| globals, "item_number" |) + |) + |); M.get_subscript (| + M.get_field (| M.get_name (| globals, "evm" |), "stack" |), + UnOp.sub (| Constant.int 1 |) + |) ] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition push1 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push2 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push3 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push4 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push5 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push6 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push7 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push8 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push9 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push10 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push11 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push12 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push13 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push14 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push15 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push16 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push17 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push18 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push19 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push20 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push21 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push22 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push23 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push24 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push25 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push26 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push27 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push28 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push29 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push30 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push31 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push32 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "push_n" |) + ], + make_dict [] + |) +)). + +Definition dup1 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "dup_n" |) + ], + make_dict [] + |) +)). + +Definition dup2 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "dup_n" |) + ], + make_dict [] + |) +)). + +Definition dup3 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "dup_n" |) + ], + make_dict [] + |) +)). + +Definition dup4 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "dup_n" |) + ], + make_dict [] + |) +)). + +Definition dup5 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "dup_n" |) + ], + make_dict [] + |) +)). + +Definition dup6 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "dup_n" |) + ], + make_dict [] + |) +)). + +Definition dup7 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "dup_n" |) + ], + make_dict [] + |) +)). + +Definition dup8 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "dup_n" |) + ], + make_dict [] + |) +)). + +Definition dup9 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "dup_n" |) + ], + make_dict [] + |) +)). + +Definition dup10 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "dup_n" |) + ], + make_dict [] + |) +)). + +Definition dup11 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "dup_n" |) + ], + make_dict [] + |) +)). + +Definition dup12 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "dup_n" |) + ], + make_dict [] + |) +)). + +Definition dup13 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "dup_n" |) + ], + make_dict [] + |) +)). + +Definition dup14 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "dup_n" |) + ], + make_dict [] + |) +)). + +Definition dup15 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "dup_n" |) + ], + make_dict [] + |) +)). + +Definition dup16 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "dup_n" |) + ], + make_dict [] + |) +)). + +Definition swap1 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "swap_n" |) + ], + make_dict [] + |) +)). + +Definition swap2 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "swap_n" |) + ], + make_dict [] + |) +)). + +Definition swap3 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "swap_n" |) + ], + make_dict [] + |) +)). + +Definition swap4 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "swap_n" |) + ], + make_dict [] + |) +)). + +Definition swap5 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "swap_n" |) + ], + make_dict [] + |) +)). + +Definition swap6 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "swap_n" |) + ], + make_dict [] + |) +)). + +Definition swap7 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "swap_n" |) + ], + make_dict [] + |) +)). + +Definition swap8 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "swap_n" |) + ], + make_dict [] + |) +)). + +Definition swap9 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "swap_n" |) + ], + make_dict [] + |) +)). + +Definition swap10 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "swap_n" |) + ], + make_dict [] + |) +)). + +Definition swap11 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "swap_n" |) + ], + make_dict [] + |) +)). + +Definition swap12 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "swap_n" |) + ], + make_dict [] + |) +)). + +Definition swap13 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "swap_n" |) + ], + make_dict [] + |) +)). + +Definition swap14 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "swap_n" |) + ], + make_dict [] + |) +)). + +Definition swap15 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "swap_n" |) + ], + make_dict [] + |) +)). + +Definition swap16 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "swap_n" |) + ], + make_dict [] + |) +)). diff --git a/CoqOfPython/ethereum/byzantium/vm/instructions/storage.v b/CoqOfPython/ethereum/byzantium/vm/instructions/storage.v new file mode 100644 index 0000000..64a99f4 --- /dev/null +++ b/CoqOfPython/ethereum/byzantium/vm/instructions/storage.v @@ -0,0 +1,248 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.byzantium.vm.instructions.storage". + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) Storage Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM storage related instructions. +". + +Axiom ethereum_utils_ensure_imports_ensure : + IsImported globals "ethereum.utils.ensure" "ensure". + +Axiom ethereum_byzantium_state_imports_get_storage : + IsImported globals "ethereum.byzantium.state" "get_storage". +Axiom ethereum_byzantium_state_imports_set_storage : + IsImported globals "ethereum.byzantium.state" "set_storage". + +Axiom ethereum_byzantium_vm_imports_Evm : + IsImported globals "ethereum.byzantium.vm" "Evm". + +Axiom ethereum_byzantium_vm_exceptions_imports_WriteInStaticContext : + IsImported globals "ethereum.byzantium.vm.exceptions" "WriteInStaticContext". + +Axiom ethereum_byzantium_vm_gas_imports_GAS_SLOAD : + IsImported globals "ethereum.byzantium.vm.gas" "GAS_SLOAD". +Axiom ethereum_byzantium_vm_gas_imports_GAS_STORAGE_CLEAR_REFUND : + IsImported globals "ethereum.byzantium.vm.gas" "GAS_STORAGE_CLEAR_REFUND". +Axiom ethereum_byzantium_vm_gas_imports_GAS_STORAGE_SET : + IsImported globals "ethereum.byzantium.vm.gas" "GAS_STORAGE_SET". +Axiom ethereum_byzantium_vm_gas_imports_GAS_STORAGE_UPDATE : + IsImported globals "ethereum.byzantium.vm.gas" "GAS_STORAGE_UPDATE". +Axiom ethereum_byzantium_vm_gas_imports_charge_gas : + IsImported globals "ethereum.byzantium.vm.gas" "charge_gas". + +Axiom ethereum_byzantium_vm_stack_imports_pop : + IsImported globals "ethereum.byzantium.vm.stack" "pop". +Axiom ethereum_byzantium_vm_stack_imports_push : + IsImported globals "ethereum.byzantium.vm.stack" "push". + +Definition sload : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Loads to the stack, the value corresponding to a certain key from the + storage of the current account. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "key" , + M.call (| + M.get_field (| M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |), "to_be_bytes32" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_SLOAD" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "value" , + M.call (| + M.get_name (| globals, "get_storage" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "env" |), "state" |); + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "current_target" |); + M.get_name (| globals, "key" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.get_name (| globals, "value" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition sstore : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Stores a value at a certain key in the current context's storage. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "key" , + M.call (| + M.get_field (| M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |), "to_be_bytes32" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "new_value" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "current_value" , + M.call (| + M.get_name (| globals, "get_storage" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "env" |), "state" |); + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "current_target" |); + M.get_name (| globals, "key" |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + BoolOp.and (| + Compare.not_eq (| + M.get_name (| globals, "new_value" |), + Constant.int 0 + |), + ltac:(M.monadic ( + Compare.eq (| + M.get_name (| globals, "current_value" |), + Constant.int 0 + |) + )) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "gas_cost" , + M.get_name (| globals, "GAS_STORAGE_SET" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "gas_cost" , + M.get_name (| globals, "GAS_STORAGE_UPDATE" |) + |) in + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + BoolOp.and (| + Compare.eq (| + M.get_name (| globals, "new_value" |), + Constant.int 0 + |), + ltac:(M.monadic ( + Compare.not_eq (| + M.get_name (| globals, "current_value" |), + Constant.int 0 + |) + )) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "refund_counter" |), + M.get_name (| globals, "GAS_STORAGE_CLEAR_REFUND" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "gas_cost" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + UnOp.not (| M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "is_static" |) |); + M.get_name (| globals, "WriteInStaticContext" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "set_storage" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "env" |), "state" |); + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "current_target" |); + M.get_name (| globals, "key" |); + M.get_name (| globals, "new_value" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). diff --git a/CoqOfPython/ethereum/byzantium/vm/instructions/system.v b/CoqOfPython/ethereum/byzantium/vm/instructions/system.v new file mode 100644 index 0000000..e75fc6e --- /dev/null +++ b/CoqOfPython/ethereum/byzantium/vm/instructions/system.v @@ -0,0 +1,1932 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.byzantium.vm.instructions.system". + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) System Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM system related instructions. +". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_Bytes0 : + IsImported globals "ethereum.base_types" "Bytes0". +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". + +Axiom ethereum_utils_ensure_imports_ensure : + IsImported globals "ethereum.utils.ensure" "ensure". + +Axiom ethereum_byzantium_fork_types_imports_Address : + IsImported globals "ethereum.byzantium.fork_types" "Address". + +Axiom ethereum_byzantium_state_imports_account_exists_and_is_empty : + IsImported globals "ethereum.byzantium.state" "account_exists_and_is_empty". +Axiom ethereum_byzantium_state_imports_account_has_code_or_nonce : + IsImported globals "ethereum.byzantium.state" "account_has_code_or_nonce". +Axiom ethereum_byzantium_state_imports_get_account : + IsImported globals "ethereum.byzantium.state" "get_account". +Axiom ethereum_byzantium_state_imports_increment_nonce : + IsImported globals "ethereum.byzantium.state" "increment_nonce". +Axiom ethereum_byzantium_state_imports_is_account_alive : + IsImported globals "ethereum.byzantium.state" "is_account_alive". +Axiom ethereum_byzantium_state_imports_set_account_balance : + IsImported globals "ethereum.byzantium.state" "set_account_balance". + +Axiom ethereum_byzantium_utils_address_imports_compute_contract_address : + IsImported globals "ethereum.byzantium.utils.address" "compute_contract_address". +Axiom ethereum_byzantium_utils_address_imports_to_address : + IsImported globals "ethereum.byzantium.utils.address" "to_address". + +Axiom ethereum_byzantium_vm_imports_Evm : + IsImported globals "ethereum.byzantium.vm" "Evm". +Axiom ethereum_byzantium_vm_imports_Message : + IsImported globals "ethereum.byzantium.vm" "Message". +Axiom ethereum_byzantium_vm_imports_incorporate_child_on_error : + IsImported globals "ethereum.byzantium.vm" "incorporate_child_on_error". +Axiom ethereum_byzantium_vm_imports_incorporate_child_on_success : + IsImported globals "ethereum.byzantium.vm" "incorporate_child_on_success". + +Axiom ethereum_byzantium_vm_exceptions_imports_Revert : + IsImported globals "ethereum.byzantium.vm.exceptions" "Revert". +Axiom ethereum_byzantium_vm_exceptions_imports_WriteInStaticContext : + IsImported globals "ethereum.byzantium.vm.exceptions" "WriteInStaticContext". + +Axiom ethereum_byzantium_vm_gas_imports_GAS_CALL : + IsImported globals "ethereum.byzantium.vm.gas" "GAS_CALL". +Axiom ethereum_byzantium_vm_gas_imports_GAS_CALL_VALUE : + IsImported globals "ethereum.byzantium.vm.gas" "GAS_CALL_VALUE". +Axiom ethereum_byzantium_vm_gas_imports_GAS_CREATE : + IsImported globals "ethereum.byzantium.vm.gas" "GAS_CREATE". +Axiom ethereum_byzantium_vm_gas_imports_GAS_NEW_ACCOUNT : + IsImported globals "ethereum.byzantium.vm.gas" "GAS_NEW_ACCOUNT". +Axiom ethereum_byzantium_vm_gas_imports_GAS_SELF_DESTRUCT : + IsImported globals "ethereum.byzantium.vm.gas" "GAS_SELF_DESTRUCT". +Axiom ethereum_byzantium_vm_gas_imports_GAS_SELF_DESTRUCT_NEW_ACCOUNT : + IsImported globals "ethereum.byzantium.vm.gas" "GAS_SELF_DESTRUCT_NEW_ACCOUNT". +Axiom ethereum_byzantium_vm_gas_imports_GAS_ZERO : + IsImported globals "ethereum.byzantium.vm.gas" "GAS_ZERO". +Axiom ethereum_byzantium_vm_gas_imports_REFUND_SELF_DESTRUCT : + IsImported globals "ethereum.byzantium.vm.gas" "REFUND_SELF_DESTRUCT". +Axiom ethereum_byzantium_vm_gas_imports_calculate_gas_extend_memory : + IsImported globals "ethereum.byzantium.vm.gas" "calculate_gas_extend_memory". +Axiom ethereum_byzantium_vm_gas_imports_calculate_message_call_gas : + IsImported globals "ethereum.byzantium.vm.gas" "calculate_message_call_gas". +Axiom ethereum_byzantium_vm_gas_imports_charge_gas : + IsImported globals "ethereum.byzantium.vm.gas" "charge_gas". +Axiom ethereum_byzantium_vm_gas_imports_max_message_call_gas : + IsImported globals "ethereum.byzantium.vm.gas" "max_message_call_gas". + +Axiom ethereum_byzantium_vm_memory_imports_memory_read_bytes : + IsImported globals "ethereum.byzantium.vm.memory" "memory_read_bytes". +Axiom ethereum_byzantium_vm_memory_imports_memory_write : + IsImported globals "ethereum.byzantium.vm.memory" "memory_write". + +Axiom ethereum_byzantium_vm_stack_imports_pop : + IsImported globals "ethereum.byzantium.vm.stack" "pop". +Axiom ethereum_byzantium_vm_stack_imports_push : + IsImported globals "ethereum.byzantium.vm.stack" "push". + +Definition create : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Creates a new account with associated code. + + Parameters + ---------- + evm : + The current EVM frame. + " in +(* At stmt: unsupported node type: ImportFrom *) + let _ := M.assign_local (| + "endowment" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_start_position" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_size" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "extend_memory" , + M.call (| + M.get_name (| globals, "calculate_gas_extend_memory" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "memory" |); + make_list [ + make_tuple [ M.get_name (| globals, "memory_start_position" |); M.get_name (| globals, "memory_size" |) ] + ] + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + BinOp.add (| + M.get_name (| globals, "GAS_CREATE" |), + M.get_field (| M.get_name (| globals, "extend_memory" |), "cost" |) + |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "create_message_gas" , + M.call (| + M.get_name (| globals, "max_message_call_gas" |), + make_list [ + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "gas_left" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_op (| + BinOp.sub, + M.get_field (| M.get_name (| globals, "evm" |), "gas_left" |), + M.get_name (| globals, "create_message_gas" |) + |) in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + UnOp.not (| M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "is_static" |) |); + M.get_name (| globals, "WriteInStaticContext" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "memory" |), + BinOp.mult (| + Constant.bytes "00", + M.get_field (| M.get_name (| globals, "extend_memory" |), "expand_by" |) + |) + |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, "evm" |), "return_data" |), + Constant.bytes "" + |) in + let _ := M.assign_local (| + "sender_address" , + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "current_target" |) + |) in + let _ := M.assign_local (| + "sender" , + M.call (| + M.get_name (| globals, "get_account" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "env" |), "state" |); + M.get_name (| globals, "sender_address" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "contract_address" , + M.call (| + M.get_name (| globals, "compute_contract_address" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "current_target" |); + M.get_field (| M.call (| + M.get_name (| globals, "get_account" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "env" |), "state" |); + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "current_target" |) + ], + make_dict [] + |), "nonce" |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + BoolOp.or (| + Compare.lt (| + M.get_field (| M.get_name (| globals, "sender" |), "balance" |), + M.get_name (| globals, "endowment" |) + |), + ltac:(M.monadic ( + BoolOp.or (| + Compare.eq (| + M.get_field (| M.get_name (| globals, "sender" |), "nonce" |), + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + BinOp.sub (| + BinOp.pow (| + Constant.int 2, + Constant.int 64 + |), + Constant.int 1 + |) + ], + make_dict [] + |) + |), + ltac:(M.monadic ( + Compare.gt (| + BinOp.add (| + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "depth" |), + Constant.int 1 + |), + M.get_name (| globals, "STACK_DEPTH_LIMIT" |) + |) + )) + |) + )) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "gas_left" |), + M.get_name (| globals, "create_message_gas" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, "account_has_code_or_nonce" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "env" |), "state" |); + M.get_name (| globals, "contract_address" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, "increment_nonce" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "env" |), "state" |); + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "current_target" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + ], + make_dict [] + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "call_data" , + M.call (| + M.get_name (| globals, "memory_read_bytes" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "memory" |); + M.get_name (| globals, "memory_start_position" |); + M.get_name (| globals, "memory_size" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "increment_nonce" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "env" |), "state" |); + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "current_target" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "child_message" , + M.call (| + M.get_name (| globals, "Message" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "child_evm" , + M.call (| + M.get_name (| globals, "process_create_message" |), + make_list [ + M.get_name (| globals, "child_message" |); + M.get_field (| M.get_name (| globals, "evm" |), "env" |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + M.get_field (| M.get_name (| globals, "child_evm" |), "error" |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, "incorporate_child_on_error" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "child_evm" |) + ], + make_dict [] + |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, "evm" |), "return_data" |), + M.get_field (| M.get_name (| globals, "child_evm" |), "output" |) + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + ], + make_dict [] + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, "incorporate_child_on_success" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "child_evm" |) + ], + make_dict [] + |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, "evm" |), "return_data" |), + Constant.bytes "" + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.call (| + M.get_field (| M.get_name (| globals, "U256" |), "from_be_bytes" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "child_evm" |), "message" |), "current_target" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )) |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition return_ : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Halts execution returning output data. + + Parameters + ---------- + evm : + The current EVM frame. + " in + let _ := M.assign_local (| + "memory_start_position" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_size" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "extend_memory" , + M.call (| + M.get_name (| globals, "calculate_gas_extend_memory" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "memory" |); + make_list [ + make_tuple [ M.get_name (| globals, "memory_start_position" |); M.get_name (| globals, "memory_size" |) ] + ] + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + BinOp.add (| + M.get_name (| globals, "GAS_ZERO" |), + M.get_field (| M.get_name (| globals, "extend_memory" |), "cost" |) + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "memory" |), + BinOp.mult (| + Constant.bytes "00", + M.get_field (| M.get_name (| globals, "extend_memory" |), "expand_by" |) + |) + |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, "evm" |), "output" |), + M.call (| + M.get_name (| globals, "memory_read_bytes" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "memory" |); + M.get_name (| globals, "memory_start_position" |); + M.get_name (| globals, "memory_size" |) + ], + make_dict [] + |) + |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, "evm" |), "running" |), + Constant.bool false + |) in + let _ := M.pass (| |) in + M.pure Constant.None_)). + +Definition generic_call : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm"; "gas"; "value"; "caller"; "to"; "code_address"; "should_transfer_value"; "is_staticcall"; "memory_input_start_position"; "memory_input_size"; "memory_output_start_position"; "memory_output_size" ] |) in + let _ := Constant.str " + Perform the core logic of the `CALL*` family of opcodes. + " in +(* At stmt: unsupported node type: ImportFrom *) + let _ := M.assign (| + M.get_field (| M.get_name (| globals, "evm" |), "return_data" |), + Constant.bytes "" + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.gt (| + BinOp.add (| + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "depth" |), + Constant.int 1 + |), + M.get_name (| globals, "STACK_DEPTH_LIMIT" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "gas_left" |), + M.get_name (| globals, "gas" |) + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.return_ (| + Constant.None_ + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "call_data" , + M.call (| + M.get_name (| globals, "memory_read_bytes" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "memory" |); + M.get_name (| globals, "memory_input_start_position" |); + M.get_name (| globals, "memory_input_size" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "code" , + M.get_field (| M.call (| + M.get_name (| globals, "get_account" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "env" |), "state" |); + M.get_name (| globals, "code_address" |) + ], + make_dict [] + |), "code" |) + |) in + let _ := M.assign_local (| + "child_message" , + M.call (| + M.get_name (| globals, "Message" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "child_evm" , + M.call (| + M.get_name (| globals, "process_message" |), + make_list [ + M.get_name (| globals, "child_message" |); + M.get_field (| M.get_name (| globals, "evm" |), "env" |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + M.get_field (| M.get_name (| globals, "child_evm" |), "error" |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, "incorporate_child_on_error" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "child_evm" |) + ], + make_dict [] + |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, "evm" |), "return_data" |), + M.get_field (| M.get_name (| globals, "child_evm" |), "output" |) + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + ], + make_dict [] + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, "incorporate_child_on_success" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "child_evm" |) + ], + make_dict [] + |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, "evm" |), "return_data" |), + M.get_field (| M.get_name (| globals, "child_evm" |), "output" |) + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 1 + ], + make_dict [] + |) + ], + make_dict [] + |) in + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "actual_output_size" , + M.call (| + M.get_name (| globals, "min" |), + make_list [ + M.get_name (| globals, "memory_output_size" |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_field (| M.get_name (| globals, "child_evm" |), "output" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "memory_write" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "memory" |); + M.get_name (| globals, "memory_output_start_position" |); + M.slice (| + M.get_field (| M.get_name (| globals, "child_evm" |), "output" |), + Constant.None_, + M.get_name (| globals, "actual_output_size" |), + Constant.None_ + |) + ], + make_dict [] + |) in + M.pure Constant.None_)). + +Definition call : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Message-call into an account. + + Parameters + ---------- + evm : + The current EVM frame. + " in + let _ := M.assign_local (| + "gas" , + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "to" , + M.call (| + M.get_name (| globals, "to_address" |), + make_list [ + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "value" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_input_start_position" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_input_size" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_output_start_position" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_output_size" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "extend_memory" , + M.call (| + M.get_name (| globals, "calculate_gas_extend_memory" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "memory" |); + make_list [ + make_tuple [ M.get_name (| globals, "memory_input_start_position" |); M.get_name (| globals, "memory_input_size" |) ]; + make_tuple [ M.get_name (| globals, "memory_output_start_position" |); M.get_name (| globals, "memory_output_size" |) ] + ] + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "create_gas_cost" , + (* if *) + M.if_then_else (| + BoolOp.or (| + Compare.eq (| + M.get_name (| globals, "value" |), + Constant.int 0 + |), + ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "is_account_alive" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "env" |), "state" |); + M.get_name (| globals, "to" |) + ], + make_dict [] + |) + )) + |), + (* then *) + ltac:(M.monadic ( +M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + (* else *) + )), ltac:(M.monadic ( +M.get_name (| globals, "GAS_NEW_ACCOUNT" |) + )) |) + |) in + let _ := M.assign_local (| + "transfer_gas_cost" , + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, "value" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( +M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + (* else *) + )), ltac:(M.monadic ( +M.get_name (| globals, "GAS_CALL_VALUE" |) + )) |) + |) in + let _ := M.assign_local (| + "message_call_gas" , + M.call (| + M.get_name (| globals, "calculate_message_call_gas" |), + make_list [ + M.get_name (| globals, "value" |); + M.get_name (| globals, "gas" |); + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "gas_left" |) + ], + make_dict [] + |); + M.get_field (| M.get_name (| globals, "extend_memory" |), "cost" |); + BinOp.add (| + BinOp.add (| + M.get_name (| globals, "GAS_CALL" |), + M.get_name (| globals, "create_gas_cost" |) + |), + M.get_name (| globals, "transfer_gas_cost" |) + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + BinOp.add (| + M.get_field (| M.get_name (| globals, "message_call_gas" |), "cost" |), + M.get_field (| M.get_name (| globals, "extend_memory" |), "cost" |) + |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + BoolOp.or (| + UnOp.not (| M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "is_static" |) |), + ltac:(M.monadic ( + Compare.eq (| + M.get_name (| globals, "value" |), + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + |) + )) + |); + M.get_name (| globals, "WriteInStaticContext" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "memory" |), + BinOp.mult (| + Constant.bytes "00", + M.get_field (| M.get_name (| globals, "extend_memory" |), "expand_by" |) + |) + |) in + let _ := M.assign_local (| + "sender_balance" , + M.get_field (| M.call (| + M.get_name (| globals, "get_account" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "env" |), "state" |); + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "current_target" |) + ], + make_dict [] + |), "balance" |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.lt (| + M.get_name (| globals, "sender_balance" |), + M.get_name (| globals, "value" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, "evm" |), "return_data" |), + Constant.bytes "" + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "gas_left" |), + M.get_field (| M.get_name (| globals, "message_call_gas" |), "stipend" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, "generic_call" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_field (| M.get_name (| globals, "message_call_gas" |), "stipend" |); + M.get_name (| globals, "value" |); + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "current_target" |); + M.get_name (| globals, "to" |); + M.get_name (| globals, "to" |); + Constant.bool true; + Constant.bool false; + M.get_name (| globals, "memory_input_start_position" |); + M.get_name (| globals, "memory_input_size" |); + M.get_name (| globals, "memory_output_start_position" |); + M.get_name (| globals, "memory_output_size" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + )) |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition callcode : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Message-call into this account with alternative account’s code. + + Parameters + ---------- + evm : + The current EVM frame. + " in + let _ := M.assign_local (| + "gas" , + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "code_address" , + M.call (| + M.get_name (| globals, "to_address" |), + make_list [ + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "value" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_input_start_position" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_input_size" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_output_start_position" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_output_size" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "to" , + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "current_target" |) + |) in + let _ := M.assign_local (| + "extend_memory" , + M.call (| + M.get_name (| globals, "calculate_gas_extend_memory" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "memory" |); + make_list [ + make_tuple [ M.get_name (| globals, "memory_input_start_position" |); M.get_name (| globals, "memory_input_size" |) ]; + make_tuple [ M.get_name (| globals, "memory_output_start_position" |); M.get_name (| globals, "memory_output_size" |) ] + ] + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "transfer_gas_cost" , + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, "value" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( +M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + (* else *) + )), ltac:(M.monadic ( +M.get_name (| globals, "GAS_CALL_VALUE" |) + )) |) + |) in + let _ := M.assign_local (| + "message_call_gas" , + M.call (| + M.get_name (| globals, "calculate_message_call_gas" |), + make_list [ + M.get_name (| globals, "value" |); + M.get_name (| globals, "gas" |); + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "gas_left" |) + ], + make_dict [] + |); + M.get_field (| M.get_name (| globals, "extend_memory" |), "cost" |); + BinOp.add (| + M.get_name (| globals, "GAS_CALL" |), + M.get_name (| globals, "transfer_gas_cost" |) + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + BinOp.add (| + M.get_field (| M.get_name (| globals, "message_call_gas" |), "cost" |), + M.get_field (| M.get_name (| globals, "extend_memory" |), "cost" |) + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "memory" |), + BinOp.mult (| + Constant.bytes "00", + M.get_field (| M.get_name (| globals, "extend_memory" |), "expand_by" |) + |) + |) in + let _ := M.assign_local (| + "sender_balance" , + M.get_field (| M.call (| + M.get_name (| globals, "get_account" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "env" |), "state" |); + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "current_target" |) + ], + make_dict [] + |), "balance" |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.lt (| + M.get_name (| globals, "sender_balance" |), + M.get_name (| globals, "value" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, "evm" |), "return_data" |), + Constant.bytes "" + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "gas_left" |), + M.get_field (| M.get_name (| globals, "message_call_gas" |), "stipend" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, "generic_call" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_field (| M.get_name (| globals, "message_call_gas" |), "stipend" |); + M.get_name (| globals, "value" |); + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "current_target" |); + M.get_name (| globals, "to" |); + M.get_name (| globals, "code_address" |); + Constant.bool true; + Constant.bool false; + M.get_name (| globals, "memory_input_start_position" |); + M.get_name (| globals, "memory_input_size" |); + M.get_name (| globals, "memory_output_start_position" |); + M.get_name (| globals, "memory_output_size" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + )) |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition selfdestruct : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Halt execution and register account for later deletion. + + Parameters + ---------- + evm : + The current EVM frame. + " in + let _ := M.assign_local (| + "beneficiary" , + M.call (| + M.get_name (| globals, "to_address" |), + make_list [ + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "gas_cost" , + M.get_name (| globals, "GAS_SELF_DESTRUCT" |) + |) in + let _ := + (* if *) + M.if_then_else (| + BoolOp.and (| + UnOp.not (| M.call (| + M.get_name (| globals, "is_account_alive" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "env" |), "state" |); + M.get_name (| globals, "beneficiary" |) + ], + make_dict [] + |) |), + ltac:(M.monadic ( + Compare.not_eq (| + M.get_field (| M.call (| + M.get_name (| globals, "get_account" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "env" |), "state" |); + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "current_target" |) + ], + make_dict [] + |), "balance" |), + Constant.int 0 + |) + )) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_op_local (| + BinOp.add, + "gas_cost", + M.get_name (| globals, "GAS_SELF_DESTRUCT_NEW_ACCOUNT" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "originator" , + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "current_target" |) + |) in + let _ := M.assign_local (| + "refunded_accounts" , + M.get_field (| M.get_name (| globals, "evm" |), "accounts_to_delete" |) + |) in + let _ := M.assign_local (| + "parent_evm" , + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "parent_evm" |) + |) in + let _ := + M.while (| + Compare.is_not (| + M.get_name (| globals, "parent_evm" |), + Constant.None_ + |), + ltac:(M.monadic ( + let _ := M.call (| + M.get_field (| M.get_name (| globals, "refunded_accounts" |), "update" |), + make_list [ + M.get_field (| M.get_name (| globals, "parent_evm" |), "accounts_to_delete" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "parent_evm" , + M.get_field (| M.get_field (| M.get_name (| globals, "parent_evm" |), "message" |), "parent_evm" |) + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.not_in (| + M.get_name (| globals, "originator" |), + M.get_name (| globals, "refunded_accounts" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "refund_counter" |), + M.get_name (| globals, "REFUND_SELF_DESTRUCT" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "gas_cost" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + UnOp.not (| M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "is_static" |) |); + M.get_name (| globals, "WriteInStaticContext" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "beneficiary_balance" , + M.get_field (| M.call (| + M.get_name (| globals, "get_account" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "env" |), "state" |); + M.get_name (| globals, "beneficiary" |) + ], + make_dict [] + |), "balance" |) + |) in + let _ := M.assign_local (| + "originator_balance" , + M.get_field (| M.call (| + M.get_name (| globals, "get_account" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "env" |), "state" |); + M.get_name (| globals, "originator" |) + ], + make_dict [] + |), "balance" |) + |) in + let _ := M.call (| + M.get_name (| globals, "set_account_balance" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "env" |), "state" |); + M.get_name (| globals, "beneficiary" |); + BinOp.add (| + M.get_name (| globals, "beneficiary_balance" |), + M.get_name (| globals, "originator_balance" |) + |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "set_account_balance" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "env" |), "state" |); + M.get_name (| globals, "originator" |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "accounts_to_delete" |), "add" |), + make_list [ + M.get_name (| globals, "originator" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, "account_exists_and_is_empty" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "env" |), "state" |); + M.get_name (| globals, "beneficiary" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "touched_accounts" |), "add" |), + make_list [ + M.get_name (| globals, "beneficiary" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, "evm" |), "running" |), + Constant.bool false + |) in + let _ := M.pass (| |) in + M.pure Constant.None_)). + +Definition delegatecall : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Message-call into an account. + + Parameters + ---------- + evm : + The current EVM frame. + " in + let _ := M.assign_local (| + "gas" , + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "code_address" , + M.call (| + M.get_name (| globals, "to_address" |), + make_list [ + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_input_start_position" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_input_size" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_output_start_position" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_output_size" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "extend_memory" , + M.call (| + M.get_name (| globals, "calculate_gas_extend_memory" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "memory" |); + make_list [ + make_tuple [ M.get_name (| globals, "memory_input_start_position" |); M.get_name (| globals, "memory_input_size" |) ]; + make_tuple [ M.get_name (| globals, "memory_output_start_position" |); M.get_name (| globals, "memory_output_size" |) ] + ] + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "message_call_gas" , + M.call (| + M.get_name (| globals, "calculate_message_call_gas" |), + make_list [ + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |); + M.get_name (| globals, "gas" |); + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "gas_left" |) + ], + make_dict [] + |); + M.get_field (| M.get_name (| globals, "extend_memory" |), "cost" |); + M.get_name (| globals, "GAS_CALL" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + BinOp.add (| + M.get_field (| M.get_name (| globals, "message_call_gas" |), "cost" |), + M.get_field (| M.get_name (| globals, "extend_memory" |), "cost" |) + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "memory" |), + BinOp.mult (| + Constant.bytes "00", + M.get_field (| M.get_name (| globals, "extend_memory" |), "expand_by" |) + |) + |) in + let _ := M.call (| + M.get_name (| globals, "generic_call" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_field (| M.get_name (| globals, "message_call_gas" |), "stipend" |); + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "value" |); + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "caller" |); + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "current_target" |); + M.get_name (| globals, "code_address" |); + Constant.bool false; + Constant.bool false; + M.get_name (| globals, "memory_input_start_position" |); + M.get_name (| globals, "memory_input_size" |); + M.get_name (| globals, "memory_output_start_position" |); + M.get_name (| globals, "memory_output_size" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition staticcall : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Message-call into an account. + + Parameters + ---------- + evm : + The current EVM frame. + " in + let _ := M.assign_local (| + "gas" , + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "to" , + M.call (| + M.get_name (| globals, "to_address" |), + make_list [ + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_input_start_position" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_input_size" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_output_start_position" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_output_size" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "extend_memory" , + M.call (| + M.get_name (| globals, "calculate_gas_extend_memory" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "memory" |); + make_list [ + make_tuple [ M.get_name (| globals, "memory_input_start_position" |); M.get_name (| globals, "memory_input_size" |) ]; + make_tuple [ M.get_name (| globals, "memory_output_start_position" |); M.get_name (| globals, "memory_output_size" |) ] + ] + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "message_call_gas" , + M.call (| + M.get_name (| globals, "calculate_message_call_gas" |), + make_list [ + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |); + M.get_name (| globals, "gas" |); + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "gas_left" |) + ], + make_dict [] + |); + M.get_field (| M.get_name (| globals, "extend_memory" |), "cost" |); + M.get_name (| globals, "GAS_CALL" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + BinOp.add (| + M.get_field (| M.get_name (| globals, "message_call_gas" |), "cost" |), + M.get_field (| M.get_name (| globals, "extend_memory" |), "cost" |) + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "memory" |), + BinOp.mult (| + Constant.bytes "00", + M.get_field (| M.get_name (| globals, "extend_memory" |), "expand_by" |) + |) + |) in + let _ := M.call (| + M.get_name (| globals, "generic_call" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_field (| M.get_name (| globals, "message_call_gas" |), "stipend" |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |); + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "current_target" |); + M.get_name (| globals, "to" |); + M.get_name (| globals, "to" |); + Constant.bool true; + Constant.bool true; + M.get_name (| globals, "memory_input_start_position" |); + M.get_name (| globals, "memory_input_size" |); + M.get_name (| globals, "memory_output_start_position" |); + M.get_name (| globals, "memory_output_size" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition revert : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Stop execution and revert state changes, without consuming all provided gas + and also has the ability to return a reason + Parameters + ---------- + evm : + The current EVM frame. + " in + let _ := M.assign_local (| + "memory_start_index" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "size" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "extend_memory" , + M.call (| + M.get_name (| globals, "calculate_gas_extend_memory" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "memory" |); + make_list [ + make_tuple [ M.get_name (| globals, "memory_start_index" |); M.get_name (| globals, "size" |) ] + ] + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_field (| M.get_name (| globals, "extend_memory" |), "cost" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "memory" |), + BinOp.mult (| + Constant.bytes "00", + M.get_field (| M.get_name (| globals, "extend_memory" |), "expand_by" |) + |) + |) in + let _ := M.assign_local (| + "output" , + M.call (| + M.get_name (| globals, "memory_read_bytes" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "memory" |); + M.get_name (| globals, "memory_start_index" |); + M.get_name (| globals, "size" |) + ], + make_dict [] + |) + |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, "evm" |), "output" |), + M.call (| + M.get_name (| globals, "bytes" |), + make_list [ + M.get_name (| globals, "output" |) + ], + make_dict [] + |) + |) in + let _ := M.raise (| Some (M.get_name (| globals, "Revert" |)) |) in + let _ := M.pass (| |) in + M.pure Constant.None_)). diff --git a/CoqOfPython/ethereum/byzantium/vm/interpreter.v b/CoqOfPython/ethereum/byzantium/vm/interpreter.v new file mode 100644 index 0000000..53559db --- /dev/null +++ b/CoqOfPython/ethereum/byzantium/vm/interpreter.v @@ -0,0 +1,657 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.byzantium.vm.interpreter". + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) Interpreter +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +A straightforward interpreter that executes EVM code. +". + +Axiom dataclasses_imports_dataclass : + IsImported globals "dataclasses" "dataclass". + +Axiom typing_imports_Iterable : + IsImported globals "typing" "Iterable". +Axiom typing_imports_Optional : + IsImported globals "typing" "Optional". +Axiom typing_imports_Set : + IsImported globals "typing" "Set". +Axiom typing_imports_Tuple : + IsImported globals "typing" "Tuple". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_Bytes0 : + IsImported globals "ethereum.base_types" "Bytes0". +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". + +Axiom ethereum_trace_imports_EvmStop : + IsImported globals "ethereum.trace" "EvmStop". +Axiom ethereum_trace_imports_OpEnd : + IsImported globals "ethereum.trace" "OpEnd". +Axiom ethereum_trace_imports_OpException : + IsImported globals "ethereum.trace" "OpException". +Axiom ethereum_trace_imports_OpStart : + IsImported globals "ethereum.trace" "OpStart". +Axiom ethereum_trace_imports_PrecompileEnd : + IsImported globals "ethereum.trace" "PrecompileEnd". +Axiom ethereum_trace_imports_PrecompileStart : + IsImported globals "ethereum.trace" "PrecompileStart". +Axiom ethereum_trace_imports_TransactionEnd : + IsImported globals "ethereum.trace" "TransactionEnd". +Axiom ethereum_trace_imports_evm_trace : + IsImported globals "ethereum.trace" "evm_trace". + +Axiom ethereum_utils_ensure_imports_ensure : + IsImported globals "ethereum.utils.ensure" "ensure". + +Axiom ethereum_byzantium_blocks_imports_Log : + IsImported globals "ethereum.byzantium.blocks" "Log". + +Axiom ethereum_byzantium_fork_types_imports_Address : + IsImported globals "ethereum.byzantium.fork_types" "Address". + +Axiom ethereum_byzantium_state_imports_account_exists_and_is_empty : + IsImported globals "ethereum.byzantium.state" "account_exists_and_is_empty". +Axiom ethereum_byzantium_state_imports_account_has_code_or_nonce : + IsImported globals "ethereum.byzantium.state" "account_has_code_or_nonce". +Axiom ethereum_byzantium_state_imports_begin_transaction : + IsImported globals "ethereum.byzantium.state" "begin_transaction". +Axiom ethereum_byzantium_state_imports_commit_transaction : + IsImported globals "ethereum.byzantium.state" "commit_transaction". +Axiom ethereum_byzantium_state_imports_destroy_storage : + IsImported globals "ethereum.byzantium.state" "destroy_storage". +Axiom ethereum_byzantium_state_imports_increment_nonce : + IsImported globals "ethereum.byzantium.state" "increment_nonce". +Axiom ethereum_byzantium_state_imports_move_ether : + IsImported globals "ethereum.byzantium.state" "move_ether". +Axiom ethereum_byzantium_state_imports_rollback_transaction : + IsImported globals "ethereum.byzantium.state" "rollback_transaction". +Axiom ethereum_byzantium_state_imports_set_code : + IsImported globals "ethereum.byzantium.state" "set_code". +Axiom ethereum_byzantium_state_imports_touch_account : + IsImported globals "ethereum.byzantium.state" "touch_account". + +Axiom ethereum_byzantium_vm_imports_Message : + IsImported globals "ethereum.byzantium.vm" "Message". + +Axiom ethereum_byzantium_vm_gas_imports_GAS_CODE_DEPOSIT : + IsImported globals "ethereum.byzantium.vm.gas" "GAS_CODE_DEPOSIT". +Axiom ethereum_byzantium_vm_gas_imports_charge_gas : + IsImported globals "ethereum.byzantium.vm.gas" "charge_gas". + +Axiom ethereum_byzantium_vm_precompiled_contracts_mapping_imports_PRE_COMPILED_CONTRACTS : + IsImported globals "ethereum.byzantium.vm.precompiled_contracts.mapping" "PRE_COMPILED_CONTRACTS". + +Axiom ethereum_byzantium_vm_imports_Environment : + IsImported globals "ethereum.byzantium.vm" "Environment". +Axiom ethereum_byzantium_vm_imports_Evm : + IsImported globals "ethereum.byzantium.vm" "Evm". + +Axiom ethereum_byzantium_vm_exceptions_imports_AddressCollision : + IsImported globals "ethereum.byzantium.vm.exceptions" "AddressCollision". +Axiom ethereum_byzantium_vm_exceptions_imports_ExceptionalHalt : + IsImported globals "ethereum.byzantium.vm.exceptions" "ExceptionalHalt". +Axiom ethereum_byzantium_vm_exceptions_imports_InvalidOpcode : + IsImported globals "ethereum.byzantium.vm.exceptions" "InvalidOpcode". +Axiom ethereum_byzantium_vm_exceptions_imports_OutOfGasError : + IsImported globals "ethereum.byzantium.vm.exceptions" "OutOfGasError". +Axiom ethereum_byzantium_vm_exceptions_imports_Revert : + IsImported globals "ethereum.byzantium.vm.exceptions" "Revert". +Axiom ethereum_byzantium_vm_exceptions_imports_StackDepthLimitError : + IsImported globals "ethereum.byzantium.vm.exceptions" "StackDepthLimitError". + +Axiom ethereum_byzantium_vm_instructions_imports_Ops : + IsImported globals "ethereum.byzantium.vm.instructions" "Ops". +Axiom ethereum_byzantium_vm_instructions_imports_op_implementation : + IsImported globals "ethereum.byzantium.vm.instructions" "op_implementation". + +Axiom ethereum_byzantium_vm_runtime_imports_get_valid_jump_destinations : + IsImported globals "ethereum.byzantium.vm.runtime" "get_valid_jump_destinations". + +Definition STACK_DEPTH_LIMIT : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 1024 + ], + make_dict [] + |) +)). + +Definition MAX_CODE_SIZE : Value.t := M.run ltac:(M.monadic ( + Constant.int 24576 +)). + +Definition MessageCallOutput : Value.t := + builtins.make_klass + [] + [ + + ] + [ + + ]. + +Definition process_message_call : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "message"; "env" ] |) in + let _ := Constant.str " + If `message.current` is empty then it creates a smart contract + else it executes a call from the `message.caller` to the `message.target`. + + Parameters + ---------- + message : + Transaction specific items. + + env : + External items required for EVM execution. + + Returns + ------- + output : `MessageCallOutput` + Output of the message call + " in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_field (| M.get_name (| globals, "message" |), "target" |), + M.call (| + M.get_name (| globals, "Bytes0" |), + make_list [ + Constant.bytes "" + ], + make_dict [] + |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "is_collision" , + M.call (| + M.get_name (| globals, "account_has_code_or_nonce" |), + make_list [ + M.get_field (| M.get_name (| globals, "env" |), "state" |); + M.get_field (| M.get_name (| globals, "message" |), "current_target" |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + M.get_name (| globals, "is_collision" |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + M.call (| + M.get_name (| globals, "MessageCallOutput" |), + make_list [ + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |); + M.call (| + M.get_name (| globals, "tuple" |), + make_list [], + make_dict [] + |); + M.call (| + M.get_name (| globals, "set" |), + make_list [], + make_dict [] + |); + M.call (| + M.get_name (| globals, "set" |), + make_list [], + make_dict [] + |); + M.call (| + M.get_name (| globals, "AddressCollision" |), + make_list [], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "evm" , + M.call (| + M.get_name (| globals, "process_create_message" |), + make_list [ + M.get_name (| globals, "message" |); + M.get_name (| globals, "env" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "evm" , + M.call (| + M.get_name (| globals, "process_message" |), + make_list [ + M.get_name (| globals, "message" |); + M.get_name (| globals, "env" |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, "account_exists_and_is_empty" |), + make_list [ + M.get_field (| M.get_name (| globals, "env" |), "state" |); + M.call (| + M.get_name (| globals, "Address" |), + make_list [ + M.get_field (| M.get_name (| globals, "message" |), "target" |) + ], + make_dict [] + |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "touched_accounts" |), "add" |), + make_list [ + M.call (| + M.get_name (| globals, "Address" |), + make_list [ + M.get_field (| M.get_name (| globals, "message" |), "target" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + M.get_field (| M.get_name (| globals, "evm" |), "error" |), + (* then *) + ltac:(M.monadic ( +(* At stmt: unsupported node type: AnnAssign *) + let _ := M.assign_local (| + "accounts_to_delete" , + M.call (| + M.get_name (| globals, "set" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "touched_accounts" , + M.call (| + M.get_name (| globals, "set" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "refund_counter" , + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "logs" , + M.get_field (| M.get_name (| globals, "evm" |), "logs" |) + |) in + let _ := M.assign_local (| + "accounts_to_delete" , + M.get_field (| M.get_name (| globals, "evm" |), "accounts_to_delete" |) + |) in + let _ := M.assign_local (| + "touched_accounts" , + M.get_field (| M.get_name (| globals, "evm" |), "touched_accounts" |) + |) in + let _ := M.assign_local (| + "refund_counter" , + M.get_field (| M.get_name (| globals, "evm" |), "refund_counter" |) + |) in + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "tx_end" , + M.call (| + M.get_name (| globals, "TransactionEnd" |), + make_list [ + BinOp.sub (| + M.get_field (| M.get_name (| globals, "message" |), "gas" |), + M.get_field (| M.get_name (| globals, "evm" |), "gas_left" |) + |); + M.get_field (| M.get_name (| globals, "evm" |), "output" |); + M.get_field (| M.get_name (| globals, "evm" |), "error" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "evm_trace" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "tx_end" |) + ], + make_dict [] + |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, "MessageCallOutput" |), + make_list [], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Definition process_create_message : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "message"; "env" ] |) in + let _ := Constant.str " + Executes a call to create a smart contract. + + Parameters + ---------- + message : + Transaction specific items. + env : + External items required for EVM execution. + + Returns + ------- + evm: :py:class:`~ethereum.byzantium.vm.Evm` + Items containing execution specific objects. + " in + let _ := M.call (| + M.get_name (| globals, "begin_transaction" |), + make_list [ + M.get_field (| M.get_name (| globals, "env" |), "state" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "destroy_storage" |), + make_list [ + M.get_field (| M.get_name (| globals, "env" |), "state" |); + M.get_field (| M.get_name (| globals, "message" |), "current_target" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "increment_nonce" |), + make_list [ + M.get_field (| M.get_name (| globals, "env" |), "state" |); + M.get_field (| M.get_name (| globals, "message" |), "current_target" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "evm" , + M.call (| + M.get_name (| globals, "process_message" |), + make_list [ + M.get_name (| globals, "message" |); + M.get_name (| globals, "env" |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + UnOp.not (| M.get_field (| M.get_name (| globals, "evm" |), "error" |) |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "contract_code" , + M.get_field (| M.get_name (| globals, "evm" |), "output" |) + |) in + let _ := M.assign_local (| + "contract_code_gas" , + BinOp.mult (| + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_name (| globals, "contract_code" |) + ], + make_dict [] + |), + M.get_name (| globals, "GAS_CODE_DEPOSIT" |) + |) + |) in +(* At stmt: unsupported node type: Try *) + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, "rollback_transaction" |), + make_list [ + M.get_field (| M.get_name (| globals, "env" |), "state" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + )) |) in + let _ := M.return_ (| + M.get_name (| globals, "evm" |) + |) in + M.pure Constant.None_)). + +Definition process_message : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "message"; "env" ] |) in + let _ := Constant.str " + Executes a call to create a smart contract. + + Parameters + ---------- + message : + Transaction specific items. + env : + External items required for EVM execution. + + Returns + ------- + evm: :py:class:`~ethereum.byzantium.vm.Evm` + Items containing execution specific objects + " in + let _ := + (* if *) + M.if_then_else (| + Compare.gt (| + M.get_field (| M.get_name (| globals, "message" |), "depth" |), + M.get_name (| globals, "STACK_DEPTH_LIMIT" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.call (| + M.get_name (| globals, "StackDepthLimitError" |), + make_list [ + Constant.str "Stack depth limit reached" + ], + make_dict [] + |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.call (| + M.get_name (| globals, "begin_transaction" |), + make_list [ + M.get_field (| M.get_name (| globals, "env" |), "state" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "touch_account" |), + make_list [ + M.get_field (| M.get_name (| globals, "env" |), "state" |); + M.get_field (| M.get_name (| globals, "message" |), "current_target" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + BoolOp.and (| + M.get_field (| M.get_name (| globals, "message" |), "should_transfer_value" |), + ltac:(M.monadic ( + Compare.not_eq (| + M.get_field (| M.get_name (| globals, "message" |), "value" |), + Constant.int 0 + |) + )) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, "move_ether" |), + make_list [ + M.get_field (| M.get_name (| globals, "env" |), "state" |); + M.get_field (| M.get_name (| globals, "message" |), "caller" |); + M.get_field (| M.get_name (| globals, "message" |), "current_target" |); + M.get_field (| M.get_name (| globals, "message" |), "value" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "evm" , + M.call (| + M.get_name (| globals, "execute_code" |), + make_list [ + M.get_name (| globals, "message" |); + M.get_name (| globals, "env" |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + M.get_field (| M.get_name (| globals, "evm" |), "error" |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, "rollback_transaction" |), + make_list [ + M.get_field (| M.get_name (| globals, "env" |), "state" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, "commit_transaction" |), + make_list [ + M.get_field (| M.get_name (| globals, "env" |), "state" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + )) |) in + let _ := M.return_ (| + M.get_name (| globals, "evm" |) + |) in + M.pure Constant.None_)). + +Definition execute_code : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "message"; "env" ] |) in + let _ := Constant.str " + Executes bytecode present in the `message`. + + Parameters + ---------- + message : + Transaction specific items. + env : + External items required for EVM execution. + + Returns + ------- + evm: `ethereum.vm.EVM` + Items containing execution specific objects + " in + let _ := M.assign_local (| + "code" , + M.get_field (| M.get_name (| globals, "message" |), "code" |) + |) in + let _ := M.assign_local (| + "valid_jump_destinations" , + M.call (| + M.get_name (| globals, "get_valid_jump_destinations" |), + make_list [ + M.get_name (| globals, "code" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "evm" , + M.call (| + M.get_name (| globals, "Evm" |), + make_list [], + make_dict [] + |) + |) in +(* At stmt: unsupported node type: Try *) + let _ := M.return_ (| + M.get_name (| globals, "evm" |) + |) in + M.pure Constant.None_)). diff --git a/CoqOfPython/ethereum/byzantium/vm/memory.v b/CoqOfPython/ethereum/byzantium/vm/memory.v new file mode 100644 index 0000000..148e6c5 --- /dev/null +++ b/CoqOfPython/ethereum/byzantium/vm/memory.v @@ -0,0 +1,166 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.byzantium.vm.memory". + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) Memory +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +EVM memory operations. +". + +Axiom ethereum_utils_byte_imports_right_pad_zero_bytes : + IsImported globals "ethereum.utils.byte" "right_pad_zero_bytes". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_Bytes : + IsImported globals "ethereum.base_types" "Bytes". +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". + +Definition memory_write : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "memory"; "start_position"; "value" ] |) in + let _ := Constant.str " + Writes to memory. + + Parameters + ---------- + memory : + Memory contents of the EVM. + start_position : + Starting pointer to the memory. + value : + Data to write to memory. + " in + let _ := M.assign (| + M.slice (| + M.get_name (| globals, "memory" |), + M.get_name (| globals, "start_position" |), + BinOp.add (| + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.get_name (| globals, "start_position" |) + ], + make_dict [] + |), + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_name (| globals, "value" |) + ], + make_dict [] + |) + |), + Constant.None_ + |), + M.get_name (| globals, "value" |) + |) in + M.pure Constant.None_)). + +Definition memory_read_bytes : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "memory"; "start_position"; "size" ] |) in + let _ := Constant.str " + Read bytes from memory. + + Parameters + ---------- + memory : + Memory contents of the EVM. + start_position : + Starting pointer to the memory. + size : + Size of the data that needs to be read from `start_position`. + + Returns + ------- + data_bytes : + Data read from memory. + " in + let _ := M.return_ (| + M.slice (| + M.get_name (| globals, "memory" |), + M.get_name (| globals, "start_position" |), + BinOp.add (| + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.get_name (| globals, "start_position" |) + ], + make_dict [] + |), + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.get_name (| globals, "size" |) + ], + make_dict [] + |) + |), + Constant.None_ + |) + |) in + M.pure Constant.None_)). + +Definition buffer_read : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "buffer"; "start_position"; "size" ] |) in + let _ := Constant.str " + Read bytes from a buffer. Padding with zeros if necessary. + + Parameters + ---------- + buffer : + Memory contents of the EVM. + start_position : + Starting pointer to the memory. + size : + Size of the data that needs to be read from `start_position`. + + Returns + ------- + data_bytes : + Data read from memory. + " in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, "right_pad_zero_bytes" |), + make_list [ + M.slice (| + M.get_name (| globals, "buffer" |), + M.get_name (| globals, "start_position" |), + BinOp.add (| + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.get_name (| globals, "start_position" |) + ], + make_dict [] + |), + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.get_name (| globals, "size" |) + ], + make_dict [] + |) + |), + Constant.None_ + |); + M.get_name (| globals, "size" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). diff --git a/CoqOfPython/ethereum/byzantium/vm/precompiled_contracts/__init__.v b/CoqOfPython/ethereum/byzantium/vm/precompiled_contracts/__init__.v new file mode 100644 index 0000000..d82e958 --- /dev/null +++ b/CoqOfPython/ethereum/byzantium/vm/precompiled_contracts/__init__.v @@ -0,0 +1,106 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.byzantium.vm.precompiled_contracts.__init__". + +Definition expr_1 : Value.t := + Constant.str " +Precompiled Contract Addresses +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Addresses of precompiled contracts and mappings to their +implementations. +". + +Axiom ethereum_byzantium_utils_hexadecimal_imports_hex_to_address : + IsImported globals "ethereum.byzantium.utils.hexadecimal" "hex_to_address". + +Definition __all__ : Value.t := M.run ltac:(M.monadic ( + make_tuple [ Constant.str "ECRECOVER_ADDRESS"; Constant.str "SHA256_ADDRESS"; Constant.str "RIPEMD160_ADDRESS"; Constant.str "IDENTITY_ADDRESS"; Constant.str "MODEXP_ADDRESS"; Constant.str "ALT_BN128_ADD_ADDRESS"; Constant.str "ALT_BN128_MUL_ADDRESS"; Constant.str "ALT_BN128_PAIRING_CHECK_ADDRESS"; Constant.str "BLAKE2F_ADDRESS" ] +)). + +Definition ECRECOVER_ADDRESS : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "hex_to_address" |), + make_list [ + Constant.str "0x01" + ], + make_dict [] + |) +)). + +Definition SHA256_ADDRESS : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "hex_to_address" |), + make_list [ + Constant.str "0x02" + ], + make_dict [] + |) +)). + +Definition RIPEMD160_ADDRESS : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "hex_to_address" |), + make_list [ + Constant.str "0x03" + ], + make_dict [] + |) +)). + +Definition IDENTITY_ADDRESS : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "hex_to_address" |), + make_list [ + Constant.str "0x04" + ], + make_dict [] + |) +)). + +Definition MODEXP_ADDRESS : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "hex_to_address" |), + make_list [ + Constant.str "0x05" + ], + make_dict [] + |) +)). + +Definition ALT_BN128_ADD_ADDRESS : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "hex_to_address" |), + make_list [ + Constant.str "0x06" + ], + make_dict [] + |) +)). + +Definition ALT_BN128_MUL_ADDRESS : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "hex_to_address" |), + make_list [ + Constant.str "0x07" + ], + make_dict [] + |) +)). + +Definition ALT_BN128_PAIRING_CHECK_ADDRESS : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "hex_to_address" |), + make_list [ + Constant.str "0x08" + ], + make_dict [] + |) +)). diff --git a/CoqOfPython/ethereum/byzantium/vm/precompiled_contracts/alt_bn128.v b/CoqOfPython/ethereum/byzantium/vm/precompiled_contracts/alt_bn128.v new file mode 100644 index 0000000..01b9f2c --- /dev/null +++ b/CoqOfPython/ethereum/byzantium/vm/precompiled_contracts/alt_bn128.v @@ -0,0 +1,778 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.byzantium.vm.precompiled_contracts.alt_bn128". + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) ALT_BN128 CONTRACTS +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementation of the ALT_BN128 precompiled contracts. +". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". + +Axiom ethereum_crypto_alt_bn128_imports_ALT_BN128_CURVE_ORDER : + IsImported globals "ethereum.crypto.alt_bn128" "ALT_BN128_CURVE_ORDER". +Axiom ethereum_crypto_alt_bn128_imports_ALT_BN128_PRIME : + IsImported globals "ethereum.crypto.alt_bn128" "ALT_BN128_PRIME". +Axiom ethereum_crypto_alt_bn128_imports_BNF : + IsImported globals "ethereum.crypto.alt_bn128" "BNF". +Axiom ethereum_crypto_alt_bn128_imports_BNF2 : + IsImported globals "ethereum.crypto.alt_bn128" "BNF2". +Axiom ethereum_crypto_alt_bn128_imports_BNF12 : + IsImported globals "ethereum.crypto.alt_bn128" "BNF12". +Axiom ethereum_crypto_alt_bn128_imports_BNP : + IsImported globals "ethereum.crypto.alt_bn128" "BNP". +Axiom ethereum_crypto_alt_bn128_imports_BNP2 : + IsImported globals "ethereum.crypto.alt_bn128" "BNP2". +Axiom ethereum_crypto_alt_bn128_imports_pairing : + IsImported globals "ethereum.crypto.alt_bn128" "pairing". + +Axiom ethereum_utils_ensure_imports_ensure : + IsImported globals "ethereum.utils.ensure" "ensure". + +Axiom ethereum_byzantium_vm_imports_Evm : + IsImported globals "ethereum.byzantium.vm" "Evm". + +Axiom ethereum_byzantium_vm_gas_imports_charge_gas : + IsImported globals "ethereum.byzantium.vm.gas" "charge_gas". + +Axiom ethereum_byzantium_vm_memory_imports_buffer_read : + IsImported globals "ethereum.byzantium.vm.memory" "buffer_read". + +Axiom ethereum_byzantium_vm_exceptions_imports_OutOfGasError : + IsImported globals "ethereum.byzantium.vm.exceptions" "OutOfGasError". + +Definition alt_bn128_add : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + The ALT_BN128 addition precompiled contract. + + Parameters + ---------- + evm : + The current EVM frame. + " in + let _ := M.assign_local (| + "data" , + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "data" |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 500 + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "x0_bytes" , + M.call (| + M.get_name (| globals, "buffer_read" |), + make_list [ + M.get_name (| globals, "data" |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 32 + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "x0_value" , + M.call (| + M.get_field (| M.get_name (| globals, "U256" |), "from_be_bytes" |), + make_list [ + M.get_name (| globals, "x0_bytes" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "y0_bytes" , + M.call (| + M.get_name (| globals, "buffer_read" |), + make_list [ + M.get_name (| globals, "data" |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 32 + ], + make_dict [] + |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 32 + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "y0_value" , + M.call (| + M.get_field (| M.get_name (| globals, "U256" |), "from_be_bytes" |), + make_list [ + M.get_name (| globals, "y0_bytes" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "x1_bytes" , + M.call (| + M.get_name (| globals, "buffer_read" |), + make_list [ + M.get_name (| globals, "data" |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 64 + ], + make_dict [] + |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 32 + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "x1_value" , + M.call (| + M.get_field (| M.get_name (| globals, "U256" |), "from_be_bytes" |), + make_list [ + M.get_name (| globals, "x1_bytes" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "y1_bytes" , + M.call (| + M.get_name (| globals, "buffer_read" |), + make_list [ + M.get_name (| globals, "data" |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 96 + ], + make_dict [] + |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 32 + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "y1_value" , + M.call (| + M.get_field (| M.get_name (| globals, "U256" |), "from_be_bytes" |), + make_list [ + M.get_name (| globals, "y1_bytes" |) + ], + make_dict [] + |) + |) in + let _ := + M.for_ (| + M.get_name (| globals, "i" |), + make_tuple [ M.get_name (| globals, "x0_value" |); M.get_name (| globals, "y0_value" |); M.get_name (| globals, "x1_value" |); M.get_name (| globals, "y1_value" |) ], + ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + Compare.gt_e (| + M.get_name (| globals, "i" |), + M.get_name (| globals, "ALT_BN128_PRIME" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, "OutOfGasError" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in +(* At stmt: unsupported node type: Try *) + let _ := M.assign_local (| + "p" , + BinOp.add (| + M.get_name (| globals, "p0" |), + M.get_name (| globals, "p1" |) + |) + |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, "evm" |), "output" |), + BinOp.add (| + M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, "p" |), "x" |), "to_be_bytes32" |), + make_list [], + make_dict [] + |), + M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, "p" |), "y" |), "to_be_bytes32" |), + make_list [], + make_dict [] + |) + |) + |) in + M.pure Constant.None_)). + +Definition alt_bn128_mul : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + The ALT_BN128 multiplication precompiled contract. + + Parameters + ---------- + evm : + The current EVM frame. + " in + let _ := M.assign_local (| + "data" , + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "data" |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 40000 + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "x0_bytes" , + M.call (| + M.get_name (| globals, "buffer_read" |), + make_list [ + M.get_name (| globals, "data" |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 32 + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "x0_value" , + M.call (| + M.get_field (| M.get_name (| globals, "U256" |), "from_be_bytes" |), + make_list [ + M.get_name (| globals, "x0_bytes" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "y0_bytes" , + M.call (| + M.get_name (| globals, "buffer_read" |), + make_list [ + M.get_name (| globals, "data" |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 32 + ], + make_dict [] + |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 32 + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "y0_value" , + M.call (| + M.get_field (| M.get_name (| globals, "U256" |), "from_be_bytes" |), + make_list [ + M.get_name (| globals, "y0_bytes" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "n" , + M.call (| + M.get_field (| M.get_name (| globals, "U256" |), "from_be_bytes" |), + make_list [ + M.call (| + M.get_name (| globals, "buffer_read" |), + make_list [ + M.get_name (| globals, "data" |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 64 + ], + make_dict [] + |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 32 + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := + M.for_ (| + M.get_name (| globals, "i" |), + make_tuple [ M.get_name (| globals, "x0_value" |); M.get_name (| globals, "y0_value" |) ], + ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + Compare.gt_e (| + M.get_name (| globals, "i" |), + M.get_name (| globals, "ALT_BN128_PRIME" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, "OutOfGasError" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in +(* At stmt: unsupported node type: Try *) + let _ := M.assign_local (| + "p" , + M.call (| + M.get_field (| M.get_name (| globals, "p0" |), "mul_by" |), + make_list [ + M.get_name (| globals, "n" |) + ], + make_dict [] + |) + |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, "evm" |), "output" |), + BinOp.add (| + M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, "p" |), "x" |), "to_be_bytes32" |), + make_list [], + make_dict [] + |), + M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, "p" |), "y" |), "to_be_bytes32" |), + make_list [], + make_dict [] + |) + |) + |) in + M.pure Constant.None_)). + +Definition alt_bn128_pairing_check : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + The ALT_BN128 pairing check precompiled contract. + + Parameters + ---------- + evm : + The current EVM frame. + " in + let _ := M.assign_local (| + "data" , + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "data" |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + BinOp.add (| + BinOp.mult (| + Constant.int 80000, + BinOp.floor_div (| + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_name (| globals, "data" |) + ], + make_dict [] + |), + Constant.int 192 + |) + |), + Constant.int 100000 + |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.not_eq (| + BinOp.mod_ (| + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_name (| globals, "data" |) + ], + make_dict [] + |), + Constant.int 192 + |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, "OutOfGasError" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "result" , + M.call (| + M.get_field (| M.get_name (| globals, "BNF12" |), "from_int" |), + make_list [ + Constant.int 1 + ], + make_dict [] + |) + |) in + let _ := + M.for_ (| + M.get_name (| globals, "i" |), + M.call (| + M.get_name (| globals, "range" |), + make_list [ + BinOp.floor_div (| + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_name (| globals, "data" |) + ], + make_dict [] + |), + Constant.int 192 + |) + ], + make_dict [] + |), + ltac:(M.monadic ( + let _ := M.assign_local (| + "values" , + make_list [] + |) in + let _ := + M.for_ (| + M.get_name (| globals, "j" |), + M.call (| + M.get_name (| globals, "range" |), + make_list [ + Constant.int 6 + ], + make_dict [] + |), + ltac:(M.monadic ( + let _ := M.assign_local (| + "value" , + M.call (| + M.get_field (| M.get_name (| globals, "U256" |), "from_be_bytes" |), + make_list [ + M.slice (| + M.get_name (| globals, "data" |), + BinOp.add (| + BinOp.mult (| + M.get_name (| globals, "i" |), + Constant.int 192 + |), + BinOp.mult (| + Constant.int 32, + M.get_name (| globals, "j" |) + |) + |), + BinOp.add (| + BinOp.mult (| + M.get_name (| globals, "i" |), + Constant.int 192 + |), + BinOp.mult (| + Constant.int 32, + BinOp.add (| + M.get_name (| globals, "j" |), + Constant.int 1 + |) + |) + |), + Constant.None_ + |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.gt_e (| + M.get_name (| globals, "value" |), + M.get_name (| globals, "ALT_BN128_PRIME" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, "OutOfGasError" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.call (| + M.get_field (| M.get_name (| globals, "values" |), "append" |), + make_list [ + M.call (| + M.get_name (| globals, "int" |), + make_list [ + M.get_name (| globals, "value" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in +(* At stmt: unsupported node type: Try *) + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + Compare.eq (| + M.call (| + M.get_field (| M.get_name (| globals, "p" |), "mul_by" |), + make_list [ + M.get_name (| globals, "ALT_BN128_CURVE_ORDER" |) + ], + make_dict [] + |), + M.call (| + M.get_field (| M.get_name (| globals, "BNP" |), "point_at_infinity" |), + make_list [], + make_dict [] + |) + |); + M.get_name (| globals, "OutOfGasError" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + Compare.eq (| + M.call (| + M.get_field (| M.get_name (| globals, "q" |), "mul_by" |), + make_list [ + M.get_name (| globals, "ALT_BN128_CURVE_ORDER" |) + ], + make_dict [] + |), + M.call (| + M.get_field (| M.get_name (| globals, "BNP2" |), "point_at_infinity" |), + make_list [], + make_dict [] + |) + |); + M.get_name (| globals, "OutOfGasError" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + BoolOp.and (| + Compare.not_eq (| + M.get_name (| globals, "p" |), + M.call (| + M.get_field (| M.get_name (| globals, "BNP" |), "point_at_infinity" |), + make_list [], + make_dict [] + |) + |), + ltac:(M.monadic ( + Compare.not_eq (| + M.get_name (| globals, "q" |), + M.call (| + M.get_field (| M.get_name (| globals, "BNP2" |), "point_at_infinity" |), + make_list [], + make_dict [] + |) + |) + )) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "result" , + BinOp.mult (| + M.get_name (| globals, "result" |), + M.call (| + M.get_name (| globals, "pairing" |), + make_list [ + M.get_name (| globals, "q" |); + M.get_name (| globals, "p" |) + ], + make_dict [] + |) + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, "result" |), + M.call (| + M.get_field (| M.get_name (| globals, "BNF12" |), "from_int" |), + make_list [ + Constant.int 1 + ], + make_dict [] + |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign (| + M.get_field (| M.get_name (| globals, "evm" |), "output" |), + M.call (| + M.get_field (| M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 1 + ], + make_dict [] + |), "to_be_bytes32" |), + make_list [], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign (| + M.get_field (| M.get_name (| globals, "evm" |), "output" |), + M.call (| + M.get_field (| M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |), "to_be_bytes32" |), + make_list [], + make_dict [] + |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_)). diff --git a/CoqOfPython/ethereum/byzantium/vm/precompiled_contracts/ecrecover.v b/CoqOfPython/ethereum/byzantium/vm/precompiled_contracts/ecrecover.v new file mode 100644 index 0000000..6daeeb3 --- /dev/null +++ b/CoqOfPython/ethereum/byzantium/vm/precompiled_contracts/ecrecover.v @@ -0,0 +1,301 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.byzantium.vm.precompiled_contracts.ecrecover". + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) ECRECOVER PRECOMPILED CONTRACT +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementation of the ECRECOVER precompiled contract. +". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". + +Axiom ethereum_crypto_elliptic_curve_imports_SECP256K1N : + IsImported globals "ethereum.crypto.elliptic_curve" "SECP256K1N". +Axiom ethereum_crypto_elliptic_curve_imports_secp256k1_recover : + IsImported globals "ethereum.crypto.elliptic_curve" "secp256k1_recover". + +Axiom ethereum_crypto_hash_imports_Hash32 : + IsImported globals "ethereum.crypto.hash" "Hash32". +Axiom ethereum_crypto_hash_imports_keccak256 : + IsImported globals "ethereum.crypto.hash" "keccak256". + +Axiom ethereum_utils_byte_imports_left_pad_zero_bytes : + IsImported globals "ethereum.utils.byte" "left_pad_zero_bytes". + +Axiom ethereum_byzantium_vm_imports_Evm : + IsImported globals "ethereum.byzantium.vm" "Evm". + +Axiom ethereum_byzantium_vm_gas_imports_GAS_ECRECOVER : + IsImported globals "ethereum.byzantium.vm.gas" "GAS_ECRECOVER". +Axiom ethereum_byzantium_vm_gas_imports_charge_gas : + IsImported globals "ethereum.byzantium.vm.gas" "charge_gas". + +Axiom ethereum_byzantium_vm_memory_imports_buffer_read : + IsImported globals "ethereum.byzantium.vm.memory" "buffer_read". + +Definition ecrecover : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Decrypts the address using elliptic curve DSA recovery mechanism and writes + the address to output. + + Parameters + ---------- + evm : + The current EVM frame. + " in + let _ := M.assign_local (| + "data" , + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "data" |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_ECRECOVER" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "message_hash_bytes" , + M.call (| + M.get_name (| globals, "buffer_read" |), + make_list [ + M.get_name (| globals, "data" |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 32 + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "message_hash" , + M.call (| + M.get_name (| globals, "Hash32" |), + make_list [ + M.get_name (| globals, "message_hash_bytes" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "v" , + M.call (| + M.get_field (| M.get_name (| globals, "U256" |), "from_be_bytes" |), + make_list [ + M.call (| + M.get_name (| globals, "buffer_read" |), + make_list [ + M.get_name (| globals, "data" |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 32 + ], + make_dict [] + |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 32 + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "r" , + M.call (| + M.get_field (| M.get_name (| globals, "U256" |), "from_be_bytes" |), + make_list [ + M.call (| + M.get_name (| globals, "buffer_read" |), + make_list [ + M.get_name (| globals, "data" |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 64 + ], + make_dict [] + |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 32 + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "s" , + M.call (| + M.get_field (| M.get_name (| globals, "U256" |), "from_be_bytes" |), + make_list [ + M.call (| + M.get_name (| globals, "buffer_read" |), + make_list [ + M.get_name (| globals, "data" |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 96 + ], + make_dict [] + |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 32 + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + BoolOp.and (| + Compare.not_eq (| + M.get_name (| globals, "v" |), + Constant.int 27 + |), + ltac:(M.monadic ( + Compare.not_eq (| + M.get_name (| globals, "v" |), + Constant.int 28 + |) + )) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + Constant.None_ + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + BoolOp.or (| + Compare.gt_e (| + Constant.int 0, + M.get_name (| globals, "r" |) + |), + ltac:(M.monadic ( + Compare.gt_e (| + M.get_name (| globals, "r" |), + M.get_name (| globals, "SECP256K1N" |) + |) + )) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + Constant.None_ + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + BoolOp.or (| + Compare.gt_e (| + Constant.int 0, + M.get_name (| globals, "s" |) + |), + ltac:(M.monadic ( + Compare.gt_e (| + M.get_name (| globals, "s" |), + M.get_name (| globals, "SECP256K1N" |) + |) + )) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + Constant.None_ + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in +(* At stmt: unsupported node type: Try *) + let _ := M.assign_local (| + "address" , + M.slice (| + M.call (| + M.get_name (| globals, "keccak256" |), + make_list [ + M.get_name (| globals, "public_key" |) + ], + make_dict [] + |), + Constant.int 12, + Constant.int 32, + Constant.None_ + |) + |) in + let _ := M.assign_local (| + "padded_address" , + M.call (| + M.get_name (| globals, "left_pad_zero_bytes" |), + make_list [ + M.get_name (| globals, "address" |); + Constant.int 32 + ], + make_dict [] + |) + |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, "evm" |), "output" |), + M.get_name (| globals, "padded_address" |) + |) in + M.pure Constant.None_)). diff --git a/CoqOfPython/ethereum/byzantium/vm/precompiled_contracts/identity.v b/CoqOfPython/ethereum/byzantium/vm/precompiled_contracts/identity.v new file mode 100644 index 0000000..7f914dd --- /dev/null +++ b/CoqOfPython/ethereum/byzantium/vm/precompiled_contracts/identity.v @@ -0,0 +1,94 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.byzantium.vm.precompiled_contracts.identity". + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) IDENTITY PRECOMPILED CONTRACT +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementation of the `IDENTITY` precompiled contract. +". + +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". + +Axiom ethereum_utils_numeric_imports_ceil32 : + IsImported globals "ethereum.utils.numeric" "ceil32". + +Axiom ethereum_byzantium_vm_imports_Evm : + IsImported globals "ethereum.byzantium.vm" "Evm". + +Axiom ethereum_byzantium_vm_gas_imports_GAS_IDENTITY : + IsImported globals "ethereum.byzantium.vm.gas" "GAS_IDENTITY". +Axiom ethereum_byzantium_vm_gas_imports_GAS_IDENTITY_WORD : + IsImported globals "ethereum.byzantium.vm.gas" "GAS_IDENTITY_WORD". +Axiom ethereum_byzantium_vm_gas_imports_charge_gas : + IsImported globals "ethereum.byzantium.vm.gas" "charge_gas". + +Definition identity : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Writes the message data to output. + + Parameters + ---------- + evm : + The current EVM frame. + " in + let _ := M.assign_local (| + "data" , + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "data" |) + |) in + let _ := M.assign_local (| + "word_count" , + BinOp.floor_div (| + M.call (| + M.get_name (| globals, "ceil32" |), + make_list [ + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_name (| globals, "data" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |), + Constant.int 32 + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + BinOp.add (| + M.get_name (| globals, "GAS_IDENTITY" |), + BinOp.mult (| + M.get_name (| globals, "GAS_IDENTITY_WORD" |), + M.get_name (| globals, "word_count" |) + |) + |) + ], + make_dict [] + |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, "evm" |), "output" |), + M.get_name (| globals, "data" |) + |) in + M.pure Constant.None_)). diff --git a/CoqOfPython/ethereum/byzantium/vm/precompiled_contracts/mapping.v b/CoqOfPython/ethereum/byzantium/vm/precompiled_contracts/mapping.v new file mode 100644 index 0000000..7088817 --- /dev/null +++ b/CoqOfPython/ethereum/byzantium/vm/precompiled_contracts/mapping.v @@ -0,0 +1,67 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.byzantium.vm.precompiled_contracts.mapping". + +Definition expr_1 : Value.t := + Constant.str " +Precompiled Contract Addresses +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Mapping of precompiled contracts their implementations. +". + +Axiom typing_imports_Callable : + IsImported globals "typing" "Callable". +Axiom typing_imports_Dict : + IsImported globals "typing" "Dict". + +Axiom ethereum_byzantium_fork_types_imports_Address : + IsImported globals "ethereum.byzantium.fork_types" "Address". + +Axiom ethereum_byzantium_vm_precompiled_contracts_imports_ALT_BN128_ADD_ADDRESS : + IsImported globals "ethereum.byzantium.vm.precompiled_contracts" "ALT_BN128_ADD_ADDRESS". +Axiom ethereum_byzantium_vm_precompiled_contracts_imports_ALT_BN128_MUL_ADDRESS : + IsImported globals "ethereum.byzantium.vm.precompiled_contracts" "ALT_BN128_MUL_ADDRESS". +Axiom ethereum_byzantium_vm_precompiled_contracts_imports_ALT_BN128_PAIRING_CHECK_ADDRESS : + IsImported globals "ethereum.byzantium.vm.precompiled_contracts" "ALT_BN128_PAIRING_CHECK_ADDRESS". +Axiom ethereum_byzantium_vm_precompiled_contracts_imports_ECRECOVER_ADDRESS : + IsImported globals "ethereum.byzantium.vm.precompiled_contracts" "ECRECOVER_ADDRESS". +Axiom ethereum_byzantium_vm_precompiled_contracts_imports_IDENTITY_ADDRESS : + IsImported globals "ethereum.byzantium.vm.precompiled_contracts" "IDENTITY_ADDRESS". +Axiom ethereum_byzantium_vm_precompiled_contracts_imports_MODEXP_ADDRESS : + IsImported globals "ethereum.byzantium.vm.precompiled_contracts" "MODEXP_ADDRESS". +Axiom ethereum_byzantium_vm_precompiled_contracts_imports_RIPEMD160_ADDRESS : + IsImported globals "ethereum.byzantium.vm.precompiled_contracts" "RIPEMD160_ADDRESS". +Axiom ethereum_byzantium_vm_precompiled_contracts_imports_SHA256_ADDRESS : + IsImported globals "ethereum.byzantium.vm.precompiled_contracts" "SHA256_ADDRESS". + +Axiom ethereum_byzantium_vm_precompiled_contracts_alt_bn128_imports_alt_bn128_add : + IsImported globals "ethereum.byzantium.vm.precompiled_contracts.alt_bn128" "alt_bn128_add". +Axiom ethereum_byzantium_vm_precompiled_contracts_alt_bn128_imports_alt_bn128_mul : + IsImported globals "ethereum.byzantium.vm.precompiled_contracts.alt_bn128" "alt_bn128_mul". +Axiom ethereum_byzantium_vm_precompiled_contracts_alt_bn128_imports_alt_bn128_pairing_check : + IsImported globals "ethereum.byzantium.vm.precompiled_contracts.alt_bn128" "alt_bn128_pairing_check". + +Axiom ethereum_byzantium_vm_precompiled_contracts_ecrecover_imports_ecrecover : + IsImported globals "ethereum.byzantium.vm.precompiled_contracts.ecrecover" "ecrecover". + +Axiom ethereum_byzantium_vm_precompiled_contracts_identity_imports_identity : + IsImported globals "ethereum.byzantium.vm.precompiled_contracts.identity" "identity". + +Axiom ethereum_byzantium_vm_precompiled_contracts_modexp_imports_modexp : + IsImported globals "ethereum.byzantium.vm.precompiled_contracts.modexp" "modexp". + +Axiom ethereum_byzantium_vm_precompiled_contracts_ripemd160_imports_ripemd160 : + IsImported globals "ethereum.byzantium.vm.precompiled_contracts.ripemd160" "ripemd160". + +Axiom ethereum_byzantium_vm_precompiled_contracts_sha256_imports_sha256 : + IsImported globals "ethereum.byzantium.vm.precompiled_contracts.sha256" "sha256". + +(* At top_level_stmt: unsupported node type: AnnAssign *) diff --git a/CoqOfPython/ethereum/byzantium/vm/precompiled_contracts/modexp.v b/CoqOfPython/ethereum/byzantium/vm/precompiled_contracts/modexp.v new file mode 100644 index 0000000..d8d7f8d --- /dev/null +++ b/CoqOfPython/ethereum/byzantium/vm/precompiled_contracts/modexp.v @@ -0,0 +1,544 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.byzantium.vm.precompiled_contracts.modexp". + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) MODEXP PRECOMPILED CONTRACT +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementation of the `MODEXP` precompiled contract. +". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_Bytes : + IsImported globals "ethereum.base_types" "Bytes". +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". + +Axiom ethereum_byzantium_vm_imports_Evm : + IsImported globals "ethereum.byzantium.vm" "Evm". + +Axiom ethereum_byzantium_vm_gas_imports_charge_gas : + IsImported globals "ethereum.byzantium.vm.gas" "charge_gas". + +Axiom ethereum_byzantium_vm_memory_imports_buffer_read : + IsImported globals "ethereum.byzantium.vm.memory" "buffer_read". + +Definition GQUADDIVISOR : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 20 + ], + make_dict [] + |) +)). + +Definition modexp : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Calculates `(base**exp) % modulus` for arbitrary sized `base`, `exp` and. + `modulus`. The return value is the same length as the modulus. + " in + let _ := M.assign_local (| + "data" , + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "data" |) + |) in + let _ := M.assign_local (| + "base_length" , + M.call (| + M.get_field (| M.get_name (| globals, "U256" |), "from_be_bytes" |), + make_list [ + M.call (| + M.get_name (| globals, "buffer_read" |), + make_list [ + M.get_name (| globals, "data" |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 32 + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "exp_length" , + M.call (| + M.get_field (| M.get_name (| globals, "U256" |), "from_be_bytes" |), + make_list [ + M.call (| + M.get_name (| globals, "buffer_read" |), + make_list [ + M.get_name (| globals, "data" |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 32 + ], + make_dict [] + |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 32 + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "modulus_length" , + M.call (| + M.get_field (| M.get_name (| globals, "U256" |), "from_be_bytes" |), + make_list [ + M.call (| + M.get_name (| globals, "buffer_read" |), + make_list [ + M.get_name (| globals, "data" |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 64 + ], + make_dict [] + |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 32 + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "exp_start" , + BinOp.add (| + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 96 + ], + make_dict [] + |), + M.get_name (| globals, "base_length" |) + |) + |) in + let _ := M.assign_local (| + "exp_head" , + M.call (| + M.get_field (| M.get_name (| globals, "U256" |), "from_be_bytes" |), + make_list [ + M.call (| + M.get_name (| globals, "buffer_read" |), + make_list [ + M.get_name (| globals, "data" |); + M.get_name (| globals, "exp_start" |); + M.call (| + M.get_name (| globals, "min" |), + make_list [ + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 32 + ], + make_dict [] + |); + M.get_name (| globals, "exp_length" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.lt (| + M.get_name (| globals, "exp_length" |), + Constant.int 32 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "adjusted_exp_length" , + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, "max" |), + make_list [ + Constant.int 0; + BinOp.sub (| + M.call (| + M.get_field (| M.get_name (| globals, "exp_head" |), "bit_length" |), + make_list [], + make_dict [] + |), + Constant.int 1 + |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "adjusted_exp_length" , + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + BinOp.add (| + BinOp.mult (| + Constant.int 8, + BinOp.sub (| + M.call (| + M.get_name (| globals, "int" |), + make_list [ + M.get_name (| globals, "exp_length" |) + ], + make_dict [] + |), + Constant.int 32 + |) + |), + M.call (| + M.get_name (| globals, "max" |), + make_list [ + Constant.int 0; + BinOp.sub (| + M.call (| + M.get_field (| M.get_name (| globals, "exp_head" |), "bit_length" |), + make_list [], + make_dict [] + |), + Constant.int 1 + |) + ], + make_dict [] + |) + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + )) |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + BinOp.floor_div (| + BinOp.mult (| + M.call (| + M.get_name (| globals, "get_mult_complexity" |), + make_list [ + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, "max" |), + make_list [ + M.get_name (| globals, "base_length" |); + M.get_name (| globals, "modulus_length" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |), + M.call (| + M.get_name (| globals, "max" |), + make_list [ + M.get_name (| globals, "adjusted_exp_length" |); + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 1 + ], + make_dict [] + |) + ], + make_dict [] + |) + |), + M.get_name (| globals, "GQUADDIVISOR" |) + |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + BoolOp.and (| + Compare.eq (| + M.get_name (| globals, "base_length" |), + Constant.int 0 + |), + ltac:(M.monadic ( + Compare.eq (| + M.get_name (| globals, "modulus_length" |), + Constant.int 0 + |) + )) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign (| + M.get_field (| M.get_name (| globals, "evm" |), "output" |), + M.call (| + M.get_name (| globals, "Bytes" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.return_ (| + Constant.None_ + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "base" , + M.call (| + M.get_field (| M.get_name (| globals, "Uint" |), "from_be_bytes" |), + make_list [ + M.call (| + M.get_name (| globals, "buffer_read" |), + make_list [ + M.get_name (| globals, "data" |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 96 + ], + make_dict [] + |); + M.get_name (| globals, "base_length" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "exp" , + M.call (| + M.get_field (| M.get_name (| globals, "Uint" |), "from_be_bytes" |), + make_list [ + M.call (| + M.get_name (| globals, "buffer_read" |), + make_list [ + M.get_name (| globals, "data" |); + M.get_name (| globals, "exp_start" |); + M.get_name (| globals, "exp_length" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "modulus_start" , + BinOp.add (| + M.get_name (| globals, "exp_start" |), + M.get_name (| globals, "exp_length" |) + |) + |) in + let _ := M.assign_local (| + "modulus" , + M.call (| + M.get_field (| M.get_name (| globals, "Uint" |), "from_be_bytes" |), + make_list [ + M.call (| + M.get_name (| globals, "buffer_read" |), + make_list [ + M.get_name (| globals, "data" |); + M.get_name (| globals, "modulus_start" |); + M.get_name (| globals, "modulus_length" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, "modulus" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign (| + M.get_field (| M.get_name (| globals, "evm" |), "output" |), + BinOp.mult (| + M.call (| + M.get_name (| globals, "Bytes" |), + make_list [ + Constant.bytes "00" + ], + make_dict [] + |), + M.get_name (| globals, "modulus_length" |) + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign (| + M.get_field (| M.get_name (| globals, "evm" |), "output" |), + M.call (| + M.get_field (| M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, "pow" |), + make_list [ + M.get_name (| globals, "base" |); + M.get_name (| globals, "exp" |); + M.get_name (| globals, "modulus" |) + ], + make_dict [] + |) + ], + make_dict [] + |), "to_bytes" |), + make_list [ + M.get_name (| globals, "modulus_length" |); + Constant.str "big" + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_)). + +Definition get_mult_complexity : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "x" ] |) in + let _ := Constant.str " + Estimate the complexity of performing Karatsuba multiplication. + " in + let _ := + (* if *) + M.if_then_else (| + Compare.lt_e (| + M.get_name (| globals, "x" |), + Constant.int 64 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + BinOp.pow (| + M.get_name (| globals, "x" |), + Constant.int 2 + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + Compare.lt_e (| + M.get_name (| globals, "x" |), + Constant.int 1024 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + BinOp.sub (| + BinOp.add (| + BinOp.floor_div (| + BinOp.pow (| + M.get_name (| globals, "x" |), + Constant.int 2 + |), + Constant.int 4 + |), + BinOp.mult (| + Constant.int 96, + M.get_name (| globals, "x" |) + |) + |), + Constant.int 3072 + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.return_ (| + BinOp.sub (| + BinOp.add (| + BinOp.floor_div (| + BinOp.pow (| + M.get_name (| globals, "x" |), + Constant.int 2 + |), + Constant.int 16 + |), + BinOp.mult (| + Constant.int 480, + M.get_name (| globals, "x" |) + |) + |), + Constant.int 199680 + |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_)). diff --git a/CoqOfPython/ethereum/byzantium/vm/precompiled_contracts/ripemd160.v b/CoqOfPython/ethereum/byzantium/vm/precompiled_contracts/ripemd160.v new file mode 100644 index 0000000..dcf5699 --- /dev/null +++ b/CoqOfPython/ethereum/byzantium/vm/precompiled_contracts/ripemd160.v @@ -0,0 +1,125 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.byzantium.vm.precompiled_contracts.ripemd160". + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) RIPEMD160 PRECOMPILED CONTRACT +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementation of the `RIPEMD160` precompiled contract. +". + +(* At top_level_stmt: unsupported node type: Import *) + +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". + +Axiom ethereum_utils_byte_imports_left_pad_zero_bytes : + IsImported globals "ethereum.utils.byte" "left_pad_zero_bytes". + +Axiom ethereum_utils_numeric_imports_ceil32 : + IsImported globals "ethereum.utils.numeric" "ceil32". + +Axiom ethereum_byzantium_vm_imports_Evm : + IsImported globals "ethereum.byzantium.vm" "Evm". + +Axiom ethereum_byzantium_vm_gas_imports_GAS_RIPEMD160 : + IsImported globals "ethereum.byzantium.vm.gas" "GAS_RIPEMD160". +Axiom ethereum_byzantium_vm_gas_imports_GAS_RIPEMD160_WORD : + IsImported globals "ethereum.byzantium.vm.gas" "GAS_RIPEMD160_WORD". +Axiom ethereum_byzantium_vm_gas_imports_charge_gas : + IsImported globals "ethereum.byzantium.vm.gas" "charge_gas". + +Definition ripemd160 : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Writes the ripemd160 hash to output. + + Parameters + ---------- + evm : + The current EVM frame. + " in + let _ := M.assign_local (| + "data" , + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "data" |) + |) in + let _ := M.assign_local (| + "word_count" , + BinOp.floor_div (| + M.call (| + M.get_name (| globals, "ceil32" |), + make_list [ + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_name (| globals, "data" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |), + Constant.int 32 + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + BinOp.add (| + M.get_name (| globals, "GAS_RIPEMD160" |), + BinOp.mult (| + M.get_name (| globals, "GAS_RIPEMD160_WORD" |), + M.get_name (| globals, "word_count" |) + |) + |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "hash_bytes" , + M.call (| + M.get_field (| M.call (| + M.get_field (| M.get_name (| globals, "hashlib" |), "new" |), + make_list [ + Constant.str "ripemd160"; + M.get_name (| globals, "data" |) + ], + make_dict [] + |), "digest" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "padded_hash" , + M.call (| + M.get_name (| globals, "left_pad_zero_bytes" |), + make_list [ + M.get_name (| globals, "hash_bytes" |); + Constant.int 32 + ], + make_dict [] + |) + |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, "evm" |), "output" |), + M.get_name (| globals, "padded_hash" |) + |) in + M.pure Constant.None_)). diff --git a/CoqOfPython/ethereum/byzantium/vm/precompiled_contracts/sha256.v b/CoqOfPython/ethereum/byzantium/vm/precompiled_contracts/sha256.v new file mode 100644 index 0000000..3059153 --- /dev/null +++ b/CoqOfPython/ethereum/byzantium/vm/precompiled_contracts/sha256.v @@ -0,0 +1,106 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.byzantium.vm.precompiled_contracts.sha256". + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) SHA256 PRECOMPILED CONTRACT +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementation of the `SHA256` precompiled contract. +". + +(* At top_level_stmt: unsupported node type: Import *) + +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". + +Axiom ethereum_utils_numeric_imports_ceil32 : + IsImported globals "ethereum.utils.numeric" "ceil32". + +Axiom ethereum_byzantium_vm_imports_Evm : + IsImported globals "ethereum.byzantium.vm" "Evm". + +Axiom ethereum_byzantium_vm_gas_imports_GAS_SHA256 : + IsImported globals "ethereum.byzantium.vm.gas" "GAS_SHA256". +Axiom ethereum_byzantium_vm_gas_imports_GAS_SHA256_WORD : + IsImported globals "ethereum.byzantium.vm.gas" "GAS_SHA256_WORD". +Axiom ethereum_byzantium_vm_gas_imports_charge_gas : + IsImported globals "ethereum.byzantium.vm.gas" "charge_gas". + +Definition sha256 : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Writes the sha256 hash to output. + + Parameters + ---------- + evm : + The current EVM frame. + " in + let _ := M.assign_local (| + "data" , + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "data" |) + |) in + let _ := M.assign_local (| + "word_count" , + BinOp.floor_div (| + M.call (| + M.get_name (| globals, "ceil32" |), + make_list [ + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_name (| globals, "data" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |), + Constant.int 32 + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + BinOp.add (| + M.get_name (| globals, "GAS_SHA256" |), + BinOp.mult (| + M.get_name (| globals, "GAS_SHA256_WORD" |), + M.get_name (| globals, "word_count" |) + |) + |) + ], + make_dict [] + |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, "evm" |), "output" |), + M.call (| + M.get_field (| M.call (| + M.get_field (| M.get_name (| globals, "hashlib" |), "sha256" |), + make_list [ + M.get_name (| globals, "data" |) + ], + make_dict [] + |), "digest" |), + make_list [], + make_dict [] + |) + |) in + M.pure Constant.None_)). diff --git a/CoqOfPython/ethereum/byzantium/vm/runtime.v b/CoqOfPython/ethereum/byzantium/vm/runtime.v new file mode 100644 index 0000000..0417135 --- /dev/null +++ b/CoqOfPython/ethereum/byzantium/vm/runtime.v @@ -0,0 +1,157 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.byzantium.vm.runtime". + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) Runtime Operations +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Runtime related operations used while executing EVM code. +". + +Axiom typing_imports_Set : + IsImported globals "typing" "Set". + +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". + +Axiom ethereum_byzantium_vm_instructions_imports_Ops : + IsImported globals "ethereum.byzantium.vm.instructions" "Ops". + +Definition get_valid_jump_destinations : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "code" ] |) in + let _ := Constant.str " + Analyze the evm code to obtain the set of valid jump destinations. + + Valid jump destinations are defined as follows: + * The jump destination is less than the length of the code. + * The jump destination should have the `JUMPDEST` opcode (0x5B). + * The jump destination shouldn't be part of the data corresponding to + `PUSH-N` opcodes. + + Note - Jump destinations are 0-indexed. + + Parameters + ---------- + code : + The EVM code which is to be executed. + + Returns + ------- + valid_jump_destinations: `Set[Uint]` + The set of valid jump destinations in the code. + " in + let _ := M.assign_local (| + "valid_jump_destinations" , + M.call (| + M.get_name (| globals, "set" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "pc" , + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + |) in + let _ := + M.while (| + Compare.lt (| + M.get_name (| globals, "pc" |), + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_name (| globals, "code" |) + ], + make_dict [] + |) + |), + ltac:(M.monadic ( +(* At stmt: unsupported node type: Try *) + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, "current_opcode" |), + M.get_field (| M.get_name (| globals, "Ops" |), "JUMPDEST" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_field (| M.get_name (| globals, "valid_jump_destinations" |), "add" |), + make_list [ + M.get_name (| globals, "pc" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + BoolOp.and (| + Compare.lt_e (| + M.get_field (| M.get_field (| M.get_name (| globals, "Ops" |), "PUSH1" |), "value" |), + M.get_field (| M.get_name (| globals, "current_opcode" |), "value" |) + |), + ltac:(M.monadic ( + Compare.lt_e (| + M.get_field (| M.get_name (| globals, "current_opcode" |), "value" |), + M.get_field (| M.get_field (| M.get_name (| globals, "Ops" |), "PUSH32" |), "value" |) + |) + )) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "push_data_size" , + BinOp.add (| + BinOp.sub (| + M.get_field (| M.get_name (| globals, "current_opcode" |), "value" |), + M.get_field (| M.get_field (| M.get_name (| globals, "Ops" |), "PUSH1" |), "value" |) + |), + Constant.int 1 + |) + |) in + let _ := M.assign_op_local (| + BinOp.add, + "pc", + M.get_name (| globals, "push_data_size" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )) |) in + let _ := M.assign_op_local (| + BinOp.add, + "pc", + Constant.int 1 + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := M.return_ (| + M.get_name (| globals, "valid_jump_destinations" |) + |) in + M.pure Constant.None_)). diff --git a/CoqOfPython/ethereum/byzantium/vm/stack.v b/CoqOfPython/ethereum/byzantium/vm/stack.v new file mode 100644 index 0000000..e9c738b --- /dev/null +++ b/CoqOfPython/ethereum/byzantium/vm/stack.v @@ -0,0 +1,123 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.byzantium.vm.stack". + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) Stack +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementation of the stack operators for the EVM. +". + +Axiom typing_imports_List : + IsImported globals "typing" "List". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". + +Axiom ethereum_byzantium_vm_exceptions_imports_StackOverflowError : + IsImported globals "ethereum.byzantium.vm.exceptions" "StackOverflowError". +Axiom ethereum_byzantium_vm_exceptions_imports_StackUnderflowError : + IsImported globals "ethereum.byzantium.vm.exceptions" "StackUnderflowError". + +Definition pop : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "stack" ] |) in + let _ := Constant.str " + Pops the top item off of `stack`. + + Parameters + ---------- + stack : + EVM stack. + + Returns + ------- + value : `U256` + The top element on the stack. + + " in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_name (| globals, "stack" |) + ], + make_dict [] + |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, "StackUnderflowError" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.return_ (| + M.call (| + M.get_field (| M.get_name (| globals, "stack" |), "pop" |), + make_list [], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Definition push : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "stack"; "value" ] |) in + let _ := Constant.str " + Pushes `value` onto `stack`. + + Parameters + ---------- + stack : + EVM stack. + + value : + Item to be pushed onto `stack`. + + " in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_name (| globals, "stack" |) + ], + make_dict [] + |), + Constant.int 1024 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, "StackOverflowError" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.return_ (| + M.call (| + M.get_field (| M.get_name (| globals, "stack" |), "append" |), + make_list [ + M.get_name (| globals, "value" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). diff --git a/CoqOfPython/ethereum/cancun/__init__.v b/CoqOfPython/ethereum/cancun/__init__.v new file mode 100644 index 0000000..2ad1a6a --- /dev/null +++ b/CoqOfPython/ethereum/cancun/__init__.v @@ -0,0 +1,24 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.cancun.__init__". + +Definition expr_1 : Value.t := + Constant.str " +The Cancun fork introduces transient storage, exposes beacon chain roots, +introduces a new blob-carrying transaction type, adds a memory copying +instruction, limits self-destruct to only work for contracts created in the +same transaction, and adds an instruction to read the blob base fee. +". + +Axiom ethereum_fork_criteria_imports_ByTimestamp : + IsImported globals "ethereum.fork_criteria" "ByTimestamp". + +Definition FORK_CRITERIA : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "ByTimestamp" |), + make_list [ + Constant.int 1710338135 + ], + make_dict [] + |) +)). diff --git a/CoqOfPython/ethereum/cancun/blocks.v b/CoqOfPython/ethereum/cancun/blocks.v new file mode 100644 index 0000000..540810b --- /dev/null +++ b/CoqOfPython/ethereum/cancun/blocks.v @@ -0,0 +1,101 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.cancun.blocks". + +Definition expr_1 : Value.t := + Constant.str " +A `Block` is a single link in the chain that is Ethereum. Each `Block` contains +a `Header` and zero or more transactions. Each `Header` contains associated +metadata like the block number, parent block hash, and how much gas was +consumed by its transactions. + +Together, these blocks form a cryptographically secure journal recording the +history of all state transitions that have happened since the genesis of the +chain. +". + +Axiom dataclasses_imports_dataclass : + IsImported globals "dataclasses" "dataclass". + +Axiom typing_imports_Tuple : + IsImported globals "typing" "Tuple". +Axiom typing_imports_Union : + IsImported globals "typing" "Union". + +Axiom ethereum_base_types_imports_U64 : + IsImported globals "ethereum.base_types" "U64". +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_Bytes : + IsImported globals "ethereum.base_types" "Bytes". +Axiom ethereum_base_types_imports_Bytes8 : + IsImported globals "ethereum.base_types" "Bytes8". +Axiom ethereum_base_types_imports_Bytes32 : + IsImported globals "ethereum.base_types" "Bytes32". +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". +Axiom ethereum_base_types_imports_slotted_freezable : + IsImported globals "ethereum.base_types" "slotted_freezable". + +Axiom ethereum_crypto_hash_imports_Hash32 : + IsImported globals "ethereum.crypto.hash" "Hash32". + +Axiom ethereum_cancun_fork_types_imports_Address : + IsImported globals "ethereum.cancun.fork_types" "Address". +Axiom ethereum_cancun_fork_types_imports_Bloom : + IsImported globals "ethereum.cancun.fork_types" "Bloom". +Axiom ethereum_cancun_fork_types_imports_Root : + IsImported globals "ethereum.cancun.fork_types" "Root". + +Axiom ethereum_cancun_transactions_imports_LegacyTransaction : + IsImported globals "ethereum.cancun.transactions" "LegacyTransaction". + +Definition Withdrawal : Value.t := + builtins.make_klass + [] + [ + + ] + [ + + ]. + +Definition Header : Value.t := + builtins.make_klass + [] + [ + + ] + [ + + ]. + +Definition Block : Value.t := + builtins.make_klass + [] + [ + + ] + [ + + ]. + +Definition Log : Value.t := + builtins.make_klass + [] + [ + + ] + [ + + ]. + +Definition Receipt : Value.t := + builtins.make_klass + [] + [ + + ] + [ + + ]. diff --git a/CoqOfPython/ethereum/cancun/bloom.v b/CoqOfPython/ethereum/cancun/bloom.v new file mode 100644 index 0000000..8795d1e --- /dev/null +++ b/CoqOfPython/ethereum/cancun/bloom.v @@ -0,0 +1,207 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.cancun.bloom". + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Logs Bloom +^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +This modules defines functions for calculating bloom filters of logs. For the +general theory of bloom filters see e.g. `Wikipedia +`_. Bloom filters are used to allow +for efficient searching of logs by address and/or topic, by rapidly +eliminating blocks and receipts from their search. +". + +Axiom typing_imports_Tuple : + IsImported globals "typing" "Tuple". + +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". + +Axiom ethereum_crypto_hash_imports_keccak256 : + IsImported globals "ethereum.crypto.hash" "keccak256". + +Axiom ethereum_cancun_blocks_imports_Log : + IsImported globals "ethereum.cancun.blocks" "Log". + +Axiom ethereum_cancun_fork_types_imports_Bloom : + IsImported globals "ethereum.cancun.fork_types" "Bloom". + +Definition add_to_bloom : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "bloom"; "bloom_entry" ] |) in + let _ := Constant.str " + Add a bloom entry to the bloom filter (`bloom`). + + The number of hash functions used is 3. They are calculated by taking the + least significant 11 bits from the first 3 16-bit words of the + `keccak_256()` hash of `bloom_entry`. + + Parameters + ---------- + bloom : + The bloom filter. + bloom_entry : + An entry which is to be added to bloom filter. + " in + let _ := M.assign_local (| + "hash" , + M.call (| + M.get_name (| globals, "keccak256" |), + make_list [ + M.get_name (| globals, "bloom_entry" |) + ], + make_dict [] + |) + |) in + let _ := + M.for_ (| + M.get_name (| globals, "idx" |), + make_tuple [ Constant.int 0; Constant.int 2; Constant.int 4 ], + ltac:(M.monadic ( + let _ := M.assign_local (| + "bit_to_set" , + BinOp.bit_and (| + M.call (| + M.get_field (| M.get_name (| globals, "Uint" |), "from_be_bytes" |), + make_list [ + M.slice (| + M.get_name (| globals, "hash" |), + M.get_name (| globals, "idx" |), + BinOp.add (| + M.get_name (| globals, "idx" |), + Constant.int 2 + |), + Constant.None_ + |) + ], + make_dict [] + |), + Constant.int 2047 + |) + |) in + let _ := M.assign_local (| + "bit_index" , + BinOp.sub (| + Constant.int 2047, + M.get_name (| globals, "bit_to_set" |) + |) + |) in + let _ := M.assign_local (| + "byte_index" , + BinOp.floor_div (| + M.get_name (| globals, "bit_index" |), + Constant.int 8 + |) + |) in + let _ := M.assign_local (| + "bit_value" , + BinOp.l_shift (| + Constant.int 1, + BinOp.sub (| + Constant.int 7, + BinOp.mod_ (| + M.get_name (| globals, "bit_index" |), + Constant.int 8 + |) + |) + |) + |) in + let _ := M.assign (| + M.get_subscript (| + M.get_name (| globals, "bloom" |), + M.get_name (| globals, "byte_index" |) + |), + BinOp.bit_or (| + M.get_subscript (| + M.get_name (| globals, "bloom" |), + M.get_name (| globals, "byte_index" |) + |), + M.get_name (| globals, "bit_value" |) + |) + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + M.pure Constant.None_)). + +Definition logs_bloom : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "logs" ] |) in + let _ := Constant.str " + Obtain the logs bloom from a list of log entries. + + The address and each topic of a log are added to the bloom filter. + + Parameters + ---------- + logs : + List of logs for which the logs bloom is to be obtained. + + Returns + ------- + logs_bloom : `Bloom` + The logs bloom obtained which is 256 bytes with some bits set as per + the caller address and the log topics. + " in +(* At stmt: unsupported node type: AnnAssign *) + let _ := + M.for_ (| + M.get_name (| globals, "log" |), + M.get_name (| globals, "logs" |), + ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, "add_to_bloom" |), + make_list [ + M.get_name (| globals, "bloom" |); + M.get_field (| M.get_name (| globals, "log" |), "address" |) + ], + make_dict [] + |) in + let _ := + M.for_ (| + M.get_name (| globals, "topic" |), + M.get_field (| M.get_name (| globals, "log" |), "topics" |), + ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, "add_to_bloom" |), + make_list [ + M.get_name (| globals, "bloom" |); + M.get_name (| globals, "topic" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, "Bloom" |), + make_list [ + M.get_name (| globals, "bloom" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). diff --git a/CoqOfPython/ethereum/cancun/fork.v b/CoqOfPython/ethereum/cancun/fork.v new file mode 100644 index 0000000..678991e --- /dev/null +++ b/CoqOfPython/ethereum/cancun/fork.v @@ -0,0 +1,3161 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.cancun.fork". + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Specification +^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Entry point for the Ethereum specification. +". + +Axiom dataclasses_imports_dataclass : + IsImported globals "dataclasses" "dataclass". + +Axiom typing_imports_List : + IsImported globals "typing" "List". +Axiom typing_imports_Optional : + IsImported globals "typing" "Optional". +Axiom typing_imports_Tuple : + IsImported globals "typing" "Tuple". +Axiom typing_imports_Union : + IsImported globals "typing" "Union". + +Axiom ethereum_base_types_imports_Bytes0 : + IsImported globals "ethereum.base_types" "Bytes0". +Axiom ethereum_base_types_imports_Bytes32 : + IsImported globals "ethereum.base_types" "Bytes32". + +Axiom ethereum_crypto_elliptic_curve_imports_SECP256K1N : + IsImported globals "ethereum.crypto.elliptic_curve" "SECP256K1N". +Axiom ethereum_crypto_elliptic_curve_imports_secp256k1_recover : + IsImported globals "ethereum.crypto.elliptic_curve" "secp256k1_recover". + +Axiom ethereum_crypto_hash_imports_Hash32 : + IsImported globals "ethereum.crypto.hash" "Hash32". +Axiom ethereum_crypto_hash_imports_keccak256 : + IsImported globals "ethereum.crypto.hash" "keccak256". + +Axiom ethereum_exceptions_imports_InvalidBlock : + IsImported globals "ethereum.exceptions" "InvalidBlock". + +Axiom ethereum_utils_ensure_imports_ensure : + IsImported globals "ethereum.utils.ensure" "ensure". + +Axiom ethereum_imports_rlp : + IsImported globals "ethereum" "rlp". + +Axiom ethereum_base_types_imports_U64 : + IsImported globals "ethereum.base_types" "U64". +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_Bytes : + IsImported globals "ethereum.base_types" "Bytes". +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". + +Axiom ethereum_cancun_imports_vm : + IsImported globals "ethereum.cancun" "vm". + +Axiom ethereum_cancun_blocks_imports_Block : + IsImported globals "ethereum.cancun.blocks" "Block". +Axiom ethereum_cancun_blocks_imports_Header : + IsImported globals "ethereum.cancun.blocks" "Header". +Axiom ethereum_cancun_blocks_imports_Log : + IsImported globals "ethereum.cancun.blocks" "Log". +Axiom ethereum_cancun_blocks_imports_Receipt : + IsImported globals "ethereum.cancun.blocks" "Receipt". +Axiom ethereum_cancun_blocks_imports_Withdrawal : + IsImported globals "ethereum.cancun.blocks" "Withdrawal". + +Axiom ethereum_cancun_bloom_imports_logs_bloom : + IsImported globals "ethereum.cancun.bloom" "logs_bloom". + +Axiom ethereum_cancun_fork_types_imports_Address : + IsImported globals "ethereum.cancun.fork_types" "Address". +Axiom ethereum_cancun_fork_types_imports_Bloom : + IsImported globals "ethereum.cancun.fork_types" "Bloom". +Axiom ethereum_cancun_fork_types_imports_Root : + IsImported globals "ethereum.cancun.fork_types" "Root". +Axiom ethereum_cancun_fork_types_imports_VersionedHash : + IsImported globals "ethereum.cancun.fork_types" "VersionedHash". + +Axiom ethereum_cancun_state_imports_State : + IsImported globals "ethereum.cancun.state" "State". +Axiom ethereum_cancun_state_imports_TransientStorage : + IsImported globals "ethereum.cancun.state" "TransientStorage". +Axiom ethereum_cancun_state_imports_account_exists_and_is_empty : + IsImported globals "ethereum.cancun.state" "account_exists_and_is_empty". +Axiom ethereum_cancun_state_imports_destroy_account : + IsImported globals "ethereum.cancun.state" "destroy_account". +Axiom ethereum_cancun_state_imports_destroy_touched_empty_accounts : + IsImported globals "ethereum.cancun.state" "destroy_touched_empty_accounts". +Axiom ethereum_cancun_state_imports_get_account : + IsImported globals "ethereum.cancun.state" "get_account". +Axiom ethereum_cancun_state_imports_increment_nonce : + IsImported globals "ethereum.cancun.state" "increment_nonce". +Axiom ethereum_cancun_state_imports_process_withdrawal : + IsImported globals "ethereum.cancun.state" "process_withdrawal". +Axiom ethereum_cancun_state_imports_set_account_balance : + IsImported globals "ethereum.cancun.state" "set_account_balance". +Axiom ethereum_cancun_state_imports_state_root : + IsImported globals "ethereum.cancun.state" "state_root". + +Axiom ethereum_cancun_transactions_imports_TX_ACCESS_LIST_ADDRESS_COST : + IsImported globals "ethereum.cancun.transactions" "TX_ACCESS_LIST_ADDRESS_COST". +Axiom ethereum_cancun_transactions_imports_TX_ACCESS_LIST_STORAGE_KEY_COST : + IsImported globals "ethereum.cancun.transactions" "TX_ACCESS_LIST_STORAGE_KEY_COST". +Axiom ethereum_cancun_transactions_imports_TX_BASE_COST : + IsImported globals "ethereum.cancun.transactions" "TX_BASE_COST". +Axiom ethereum_cancun_transactions_imports_TX_CREATE_COST : + IsImported globals "ethereum.cancun.transactions" "TX_CREATE_COST". +Axiom ethereum_cancun_transactions_imports_TX_DATA_COST_PER_NON_ZERO : + IsImported globals "ethereum.cancun.transactions" "TX_DATA_COST_PER_NON_ZERO". +Axiom ethereum_cancun_transactions_imports_TX_DATA_COST_PER_ZERO : + IsImported globals "ethereum.cancun.transactions" "TX_DATA_COST_PER_ZERO". +Axiom ethereum_cancun_transactions_imports_AccessListTransaction : + IsImported globals "ethereum.cancun.transactions" "AccessListTransaction". +Axiom ethereum_cancun_transactions_imports_BlobTransaction : + IsImported globals "ethereum.cancun.transactions" "BlobTransaction". +Axiom ethereum_cancun_transactions_imports_FeeMarketTransaction : + IsImported globals "ethereum.cancun.transactions" "FeeMarketTransaction". +Axiom ethereum_cancun_transactions_imports_LegacyTransaction : + IsImported globals "ethereum.cancun.transactions" "LegacyTransaction". +Axiom ethereum_cancun_transactions_imports_Transaction : + IsImported globals "ethereum.cancun.transactions" "Transaction". +Axiom ethereum_cancun_transactions_imports_decode_transaction : + IsImported globals "ethereum.cancun.transactions" "decode_transaction". +Axiom ethereum_cancun_transactions_imports_encode_transaction : + IsImported globals "ethereum.cancun.transactions" "encode_transaction". + +Axiom ethereum_cancun_trie_imports_Trie : + IsImported globals "ethereum.cancun.trie" "Trie". +Axiom ethereum_cancun_trie_imports_root : + IsImported globals "ethereum.cancun.trie" "root". +Axiom ethereum_cancun_trie_imports_trie_set : + IsImported globals "ethereum.cancun.trie" "trie_set". + +Axiom ethereum_cancun_utils_hexadecimal_imports_hex_to_address : + IsImported globals "ethereum.cancun.utils.hexadecimal" "hex_to_address". + +Axiom ethereum_cancun_utils_message_imports_prepare_message : + IsImported globals "ethereum.cancun.utils.message" "prepare_message". + +Axiom ethereum_cancun_vm_imports_Message : + IsImported globals "ethereum.cancun.vm" "Message". + +Axiom ethereum_cancun_vm_gas_imports_calculate_blob_gas_price : + IsImported globals "ethereum.cancun.vm.gas" "calculate_blob_gas_price". +Axiom ethereum_cancun_vm_gas_imports_calculate_data_fee : + IsImported globals "ethereum.cancun.vm.gas" "calculate_data_fee". +Axiom ethereum_cancun_vm_gas_imports_calculate_excess_blob_gas : + IsImported globals "ethereum.cancun.vm.gas" "calculate_excess_blob_gas". +Axiom ethereum_cancun_vm_gas_imports_calculate_total_blob_gas : + IsImported globals "ethereum.cancun.vm.gas" "calculate_total_blob_gas". +Axiom ethereum_cancun_vm_gas_imports_init_code_cost : + IsImported globals "ethereum.cancun.vm.gas" "init_code_cost". + +Axiom ethereum_cancun_vm_interpreter_imports_MAX_CODE_SIZE : + IsImported globals "ethereum.cancun.vm.interpreter" "MAX_CODE_SIZE". +Axiom ethereum_cancun_vm_interpreter_imports_process_message_call : + IsImported globals "ethereum.cancun.vm.interpreter" "process_message_call". + +Definition BASE_FEE_MAX_CHANGE_DENOMINATOR : Value.t := M.run ltac:(M.monadic ( + Constant.int 8 +)). + +Definition ELASTICITY_MULTIPLIER : Value.t := M.run ltac:(M.monadic ( + Constant.int 2 +)). + +Definition GAS_LIMIT_ADJUSTMENT_FACTOR : Value.t := M.run ltac:(M.monadic ( + Constant.int 1024 +)). + +Definition GAS_LIMIT_MINIMUM : Value.t := M.run ltac:(M.monadic ( + Constant.int 5000 +)). + +Definition EMPTY_OMMER_HASH : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "keccak256" |), + make_list [ + M.call (| + M.get_field (| M.get_name (| globals, "rlp" |), "encode" |), + make_list [ + make_list [] + ], + make_dict [] + |) + ], + make_dict [] + |) +)). + +Definition SYSTEM_ADDRESS : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "hex_to_address" |), + make_list [ + Constant.str "0xfffffffffffffffffffffffffffffffffffffffe" + ], + make_dict [] + |) +)). + +Definition BEACON_ROOTS_ADDRESS : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "hex_to_address" |), + make_list [ + Constant.str "0x000F3df6D732807Ef1319fB7B8bB8522d0Beac02" + ], + make_dict [] + |) +)). + +Definition SYSTEM_TRANSACTION_GAS : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 30000000 + ], + make_dict [] + |) +)). + +Definition MAX_BLOB_GAS_PER_BLOCK : Value.t := M.run ltac:(M.monadic ( + Constant.int 786432 +)). + +Definition VERSIONED_HASH_VERSION_KZG : Value.t := M.run ltac:(M.monadic ( + Constant.bytes "01" +)). + +Definition BlockChain : Value.t := + builtins.make_klass + [] + [ + + ] + [ + + ]. + +Definition apply_fork : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "old" ] |) in + let _ := Constant.str " + Transforms the state from the previous hard fork (`old`) into the block + chain object for this hard fork and returns it. + + When forks need to implement an irregular state transition, this function + is used to handle the irregularity. See the :ref:`DAO Fork ` for + an example. + + Parameters + ---------- + old : + Previous block chain object. + + Returns + ------- + new : `BlockChain` + Upgraded block chain object for this hard fork. + " in + let _ := M.return_ (| + M.get_name (| globals, "old" |) + |) in + M.pure Constant.None_)). + +Definition get_last_256_block_hashes : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "chain" ] |) in + let _ := Constant.str " + Obtain the list of hashes of the previous 256 blocks in order of + increasing block number. + + This function will return less hashes for the first 256 blocks. + + The ``BLOCKHASH`` opcode needs to access the latest hashes on the chain, + therefore this function retrieves them. + + Parameters + ---------- + chain : + History and current state. + + Returns + ------- + recent_block_hashes : `List[Hash32]` + Hashes of the recent 256 blocks in order of increasing block number. + " in + let _ := M.assign_local (| + "recent_blocks" , + M.slice (| + M.get_field (| M.get_name (| globals, "chain" |), "blocks" |), + UnOp.sub (| Constant.int 255 |), + Constant.None_, + Constant.None_ + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_name (| globals, "recent_blocks" |) + ], + make_dict [] + |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + make_list [] + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "recent_block_hashes" , + make_list [] + |) in + let _ := + M.for_ (| + M.get_name (| globals, "block" |), + M.get_name (| globals, "recent_blocks" |), + ltac:(M.monadic ( + let _ := M.assign_local (| + "prev_block_hash" , + M.get_field (| M.get_field (| M.get_name (| globals, "block" |), "header" |), "parent_hash" |) + |) in + let _ := M.call (| + M.get_field (| M.get_name (| globals, "recent_block_hashes" |), "append" |), + make_list [ + M.get_name (| globals, "prev_block_hash" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := M.assign_local (| + "most_recent_block_hash" , + M.call (| + M.get_name (| globals, "keccak256" |), + make_list [ + M.call (| + M.get_field (| M.get_name (| globals, "rlp" |), "encode" |), + make_list [ + M.get_field (| M.get_subscript (| + M.get_name (| globals, "recent_blocks" |), + UnOp.sub (| Constant.int 1 |) + |), "header" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_field (| M.get_name (| globals, "recent_block_hashes" |), "append" |), + make_list [ + M.get_name (| globals, "most_recent_block_hash" |) + ], + make_dict [] + |) in + let _ := M.return_ (| + M.get_name (| globals, "recent_block_hashes" |) + |) in + M.pure Constant.None_)). + +Definition state_transition : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "chain"; "block" ] |) in + let _ := Constant.str " + Attempts to apply a block to an existing block chain. + + All parts of the block's contents need to be verified before being added + to the chain. Blocks are verified by ensuring that the contents of the + block make logical sense with the contents of the parent block. The + information in the block's header must also match the corresponding + information in the block. + + To implement Ethereum, in theory clients are only required to store the + most recent 255 blocks of the chain since as far as execution is + concerned, only those blocks are accessed. Practically, however, clients + should store more blocks to handle reorgs. + + Parameters + ---------- + chain : + History and current state. + block : + Block to apply to `chain`. + " in + let _ := M.assign_local (| + "parent_header" , + M.get_field (| M.get_subscript (| + M.get_field (| M.get_name (| globals, "chain" |), "blocks" |), + UnOp.sub (| Constant.int 1 |) + |), "header" |) + |) in + let _ := M.assign_local (| + "excess_blob_gas" , + M.call (| + M.get_name (| globals, "calculate_excess_blob_gas" |), + make_list [ + M.get_name (| globals, "parent_header" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + Compare.eq (| + M.get_field (| M.get_field (| M.get_name (| globals, "block" |), "header" |), "excess_blob_gas" |), + M.get_name (| globals, "excess_blob_gas" |) + |); + M.get_name (| globals, "InvalidBlock" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "validate_header" |), + make_list [ + M.get_field (| M.get_name (| globals, "block" |), "header" |); + M.get_name (| globals, "parent_header" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + Compare.eq (| + M.get_field (| M.get_name (| globals, "block" |), "ommers" |), + make_tuple [ ] + |); + M.get_name (| globals, "InvalidBlock" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "apply_body_output" , + M.call (| + M.get_name (| globals, "apply_body" |), + make_list [ + M.get_field (| M.get_name (| globals, "chain" |), "state" |); + M.call (| + M.get_name (| globals, "get_last_256_block_hashes" |), + make_list [ + M.get_name (| globals, "chain" |) + ], + make_dict [] + |); + M.get_field (| M.get_field (| M.get_name (| globals, "block" |), "header" |), "coinbase" |); + M.get_field (| M.get_field (| M.get_name (| globals, "block" |), "header" |), "number" |); + M.get_field (| M.get_field (| M.get_name (| globals, "block" |), "header" |), "base_fee_per_gas" |); + M.get_field (| M.get_field (| M.get_name (| globals, "block" |), "header" |), "gas_limit" |); + M.get_field (| M.get_field (| M.get_name (| globals, "block" |), "header" |), "timestamp" |); + M.get_field (| M.get_field (| M.get_name (| globals, "block" |), "header" |), "prev_randao" |); + M.get_field (| M.get_name (| globals, "block" |), "transactions" |); + M.get_field (| M.get_name (| globals, "chain" |), "chain_id" |); + M.get_field (| M.get_name (| globals, "block" |), "withdrawals" |); + M.get_field (| M.get_field (| M.get_name (| globals, "block" |), "header" |), "parent_beacon_block_root" |); + M.get_name (| globals, "excess_blob_gas" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + Compare.eq (| + M.get_field (| M.get_name (| globals, "apply_body_output" |), "block_gas_used" |), + M.get_field (| M.get_field (| M.get_name (| globals, "block" |), "header" |), "gas_used" |) + |); + M.get_name (| globals, "InvalidBlock" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + Compare.eq (| + M.get_field (| M.get_name (| globals, "apply_body_output" |), "transactions_root" |), + M.get_field (| M.get_field (| M.get_name (| globals, "block" |), "header" |), "transactions_root" |) + |); + M.get_name (| globals, "InvalidBlock" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + Compare.eq (| + M.get_field (| M.get_name (| globals, "apply_body_output" |), "state_root" |), + M.get_field (| M.get_field (| M.get_name (| globals, "block" |), "header" |), "state_root" |) + |); + M.get_name (| globals, "InvalidBlock" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + Compare.eq (| + M.get_field (| M.get_name (| globals, "apply_body_output" |), "receipt_root" |), + M.get_field (| M.get_field (| M.get_name (| globals, "block" |), "header" |), "receipt_root" |) + |); + M.get_name (| globals, "InvalidBlock" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + Compare.eq (| + M.get_field (| M.get_name (| globals, "apply_body_output" |), "block_logs_bloom" |), + M.get_field (| M.get_field (| M.get_name (| globals, "block" |), "header" |), "bloom" |) + |); + M.get_name (| globals, "InvalidBlock" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + Compare.eq (| + M.get_field (| M.get_name (| globals, "apply_body_output" |), "withdrawals_root" |), + M.get_field (| M.get_field (| M.get_name (| globals, "block" |), "header" |), "withdrawals_root" |) + |); + M.get_name (| globals, "InvalidBlock" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + Compare.eq (| + M.get_field (| M.get_name (| globals, "apply_body_output" |), "blob_gas_used" |), + M.get_field (| M.get_field (| M.get_name (| globals, "block" |), "header" |), "blob_gas_used" |) + |); + M.get_name (| globals, "InvalidBlock" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, "chain" |), "blocks" |), "append" |), + make_list [ + M.get_name (| globals, "block" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.gt (| + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_field (| M.get_name (| globals, "chain" |), "blocks" |) + ], + make_dict [] + |), + Constant.int 255 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign (| + M.get_field (| M.get_name (| globals, "chain" |), "blocks" |), + M.slice (| + M.get_field (| M.get_name (| globals, "chain" |), "blocks" |), + UnOp.sub (| Constant.int 255 |), + Constant.None_, + Constant.None_ + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + M.pure Constant.None_)). + +Definition calculate_base_fee_per_gas : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "block_gas_limit"; "parent_gas_limit"; "parent_gas_used"; "parent_base_fee_per_gas" ] |) in + let _ := Constant.str " + Calculates the base fee per gas for the block. + + Parameters + ---------- + block_gas_limit : + Gas limit of the block for which the base fee is being calculated. + parent_gas_limit : + Gas limit of the parent block. + parent_gas_used : + Gas used in the parent block. + parent_base_fee_per_gas : + Base fee per gas of the parent block. + + Returns + ------- + base_fee_per_gas : `Uint` + Base fee per gas for the block. + " in + let _ := M.assign_local (| + "parent_gas_target" , + BinOp.floor_div (| + M.get_name (| globals, "parent_gas_limit" |), + M.get_name (| globals, "ELASTICITY_MULTIPLIER" |) + |) + |) in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + M.call (| + M.get_name (| globals, "check_gas_limit" |), + make_list [ + M.get_name (| globals, "block_gas_limit" |); + M.get_name (| globals, "parent_gas_limit" |) + ], + make_dict [] + |); + M.get_name (| globals, "InvalidBlock" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, "parent_gas_used" |), + M.get_name (| globals, "parent_gas_target" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "expected_base_fee_per_gas" , + M.get_name (| globals, "parent_base_fee_per_gas" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + Compare.gt (| + M.get_name (| globals, "parent_gas_used" |), + M.get_name (| globals, "parent_gas_target" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "gas_used_delta" , + BinOp.sub (| + M.get_name (| globals, "parent_gas_used" |), + M.get_name (| globals, "parent_gas_target" |) + |) + |) in + let _ := M.assign_local (| + "parent_fee_gas_delta" , + BinOp.mult (| + M.get_name (| globals, "parent_base_fee_per_gas" |), + M.get_name (| globals, "gas_used_delta" |) + |) + |) in + let _ := M.assign_local (| + "target_fee_gas_delta" , + BinOp.floor_div (| + M.get_name (| globals, "parent_fee_gas_delta" |), + M.get_name (| globals, "parent_gas_target" |) + |) + |) in + let _ := M.assign_local (| + "base_fee_per_gas_delta" , + M.call (| + M.get_name (| globals, "max" |), + make_list [ + BinOp.floor_div (| + M.get_name (| globals, "target_fee_gas_delta" |), + M.get_name (| globals, "BASE_FEE_MAX_CHANGE_DENOMINATOR" |) + |); + Constant.int 1 + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "expected_base_fee_per_gas" , + BinOp.add (| + M.get_name (| globals, "parent_base_fee_per_gas" |), + M.get_name (| globals, "base_fee_per_gas_delta" |) + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "gas_used_delta" , + BinOp.sub (| + M.get_name (| globals, "parent_gas_target" |), + M.get_name (| globals, "parent_gas_used" |) + |) + |) in + let _ := M.assign_local (| + "parent_fee_gas_delta" , + BinOp.mult (| + M.get_name (| globals, "parent_base_fee_per_gas" |), + M.get_name (| globals, "gas_used_delta" |) + |) + |) in + let _ := M.assign_local (| + "target_fee_gas_delta" , + BinOp.floor_div (| + M.get_name (| globals, "parent_fee_gas_delta" |), + M.get_name (| globals, "parent_gas_target" |) + |) + |) in + let _ := M.assign_local (| + "base_fee_per_gas_delta" , + BinOp.floor_div (| + M.get_name (| globals, "target_fee_gas_delta" |), + M.get_name (| globals, "BASE_FEE_MAX_CHANGE_DENOMINATOR" |) + |) + |) in + let _ := M.assign_local (| + "expected_base_fee_per_gas" , + BinOp.sub (| + M.get_name (| globals, "parent_base_fee_per_gas" |), + M.get_name (| globals, "base_fee_per_gas_delta" |) + |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )) |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.get_name (| globals, "expected_base_fee_per_gas" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Definition validate_header : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "header"; "parent_header" ] |) in + let _ := Constant.str " + Verifies a block header. + + In order to consider a block's header valid, the logic for the + quantities in the header should match the logic for the block itself. + For example the header timestamp should be greater than the block's parent + timestamp because the block was created *after* the parent block. + Additionally, the block's number should be directly following the parent + block's number since it is the next block in the sequence. + + Parameters + ---------- + header : + Header to check for correctness. + parent_header : + Parent Header of the header to check for correctness + " in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + Compare.lt_e (| + M.get_field (| M.get_name (| globals, "header" |), "gas_used" |), + M.get_field (| M.get_name (| globals, "header" |), "gas_limit" |) + |); + M.get_name (| globals, "InvalidBlock" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "expected_base_fee_per_gas" , + M.call (| + M.get_name (| globals, "calculate_base_fee_per_gas" |), + make_list [ + M.get_field (| M.get_name (| globals, "header" |), "gas_limit" |); + M.get_field (| M.get_name (| globals, "parent_header" |), "gas_limit" |); + M.get_field (| M.get_name (| globals, "parent_header" |), "gas_used" |); + M.get_field (| M.get_name (| globals, "parent_header" |), "base_fee_per_gas" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + Compare.eq (| + M.get_name (| globals, "expected_base_fee_per_gas" |), + M.get_field (| M.get_name (| globals, "header" |), "base_fee_per_gas" |) + |); + M.get_name (| globals, "InvalidBlock" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + Compare.gt (| + M.get_field (| M.get_name (| globals, "header" |), "timestamp" |), + M.get_field (| M.get_name (| globals, "parent_header" |), "timestamp" |) + |); + M.get_name (| globals, "InvalidBlock" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + Compare.eq (| + M.get_field (| M.get_name (| globals, "header" |), "number" |), + BinOp.add (| + M.get_field (| M.get_name (| globals, "parent_header" |), "number" |), + Constant.int 1 + |) + |); + M.get_name (| globals, "InvalidBlock" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + Compare.lt_e (| + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_field (| M.get_name (| globals, "header" |), "extra_data" |) + ], + make_dict [] + |), + Constant.int 32 + |); + M.get_name (| globals, "InvalidBlock" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + Compare.eq (| + M.get_field (| M.get_name (| globals, "header" |), "difficulty" |), + Constant.int 0 + |); + M.get_name (| globals, "InvalidBlock" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + Compare.eq (| + M.get_field (| M.get_name (| globals, "header" |), "nonce" |), + Constant.bytes "0000000000000000" + |); + M.get_name (| globals, "InvalidBlock" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + Compare.eq (| + M.get_field (| M.get_name (| globals, "header" |), "ommers_hash" |), + M.get_name (| globals, "EMPTY_OMMER_HASH" |) + |); + M.get_name (| globals, "InvalidBlock" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "block_parent_hash" , + M.call (| + M.get_name (| globals, "keccak256" |), + make_list [ + M.call (| + M.get_field (| M.get_name (| globals, "rlp" |), "encode" |), + make_list [ + M.get_name (| globals, "parent_header" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + Compare.eq (| + M.get_field (| M.get_name (| globals, "header" |), "parent_hash" |), + M.get_name (| globals, "block_parent_hash" |) + |); + M.get_name (| globals, "InvalidBlock" |) + ], + make_dict [] + |) in + M.pure Constant.None_)). + +Definition check_transaction : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "state"; "tx"; "gas_available"; "chain_id"; "base_fee_per_gas"; "excess_blob_gas" ] |) in + let _ := Constant.str " + Check if the transaction is includable in the block. + + Parameters + ---------- + state : + Current state. + tx : + The transaction. + gas_available : + The gas remaining in the block. + chain_id : + The ID of the current chain. + base_fee_per_gas : + The block base fee. + excess_blob_gas : + The excess blob gas. + + Returns + ------- + sender_address : + The sender of the transaction. + effective_gas_price : + The price to charge for gas when the transaction is executed. + blob_versioned_hashes : + The blob versioned hashes of the transaction. + + Raises + ------ + InvalidBlock : + If the transaction is not includable. + " in + let _ := + (* if *) + M.if_then_else (| + Compare.gt (| + M.call (| + M.get_name (| globals, "calculate_intrinsic_cost" |), + make_list [ + M.get_name (| globals, "tx" |) + ], + make_dict [] + |), + M.get_field (| M.get_name (| globals, "tx" |), "gas" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, "InvalidBlock" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + Compare.gt_e (| + M.get_field (| M.get_name (| globals, "tx" |), "nonce" |), + BinOp.sub (| + BinOp.pow (| + Constant.int 2, + Constant.int 64 + |), + Constant.int 1 + |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, "InvalidBlock" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + BoolOp.and (| + Compare.eq (| + M.get_field (| M.get_name (| globals, "tx" |), "to" |), + M.call (| + M.get_name (| globals, "Bytes0" |), + make_list [ + Constant.bytes "" + ], + make_dict [] + |) + |), + ltac:(M.monadic ( + Compare.gt (| + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_field (| M.get_name (| globals, "tx" |), "data" |) + ], + make_dict [] + |), + BinOp.mult (| + Constant.int 2, + M.get_name (| globals, "MAX_CODE_SIZE" |) + |) + |) + )) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, "InvalidBlock" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + Compare.gt (| + M.get_field (| M.get_name (| globals, "tx" |), "gas" |), + M.get_name (| globals, "gas_available" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, "InvalidBlock" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "sender" , + M.call (| + M.get_name (| globals, "recover_sender" |), + make_list [ + M.get_name (| globals, "chain_id" |); + M.get_name (| globals, "tx" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "sender_account" , + M.call (| + M.get_name (| globals, "get_account" |), + make_list [ + M.get_name (| globals, "state" |); + M.get_name (| globals, "sender" |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, "isinstance" |), + make_list [ + M.get_name (| globals, "tx" |); + make_tuple [ M.get_name (| globals, "FeeMarketTransaction" |); M.get_name (| globals, "BlobTransaction" |) ] + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + Compare.lt (| + M.get_field (| M.get_name (| globals, "tx" |), "max_fee_per_gas" |), + M.get_field (| M.get_name (| globals, "tx" |), "max_priority_fee_per_gas" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, "InvalidBlock" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + Compare.lt (| + M.get_field (| M.get_name (| globals, "tx" |), "max_fee_per_gas" |), + M.get_name (| globals, "base_fee_per_gas" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, "InvalidBlock" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "priority_fee_per_gas" , + M.call (| + M.get_name (| globals, "min" |), + make_list [ + M.get_field (| M.get_name (| globals, "tx" |), "max_priority_fee_per_gas" |); + BinOp.sub (| + M.get_field (| M.get_name (| globals, "tx" |), "max_fee_per_gas" |), + M.get_name (| globals, "base_fee_per_gas" |) + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "effective_gas_price" , + BinOp.add (| + M.get_name (| globals, "priority_fee_per_gas" |), + M.get_name (| globals, "base_fee_per_gas" |) + |) + |) in + let _ := M.assign_local (| + "max_gas_fee" , + BinOp.mult (| + M.get_field (| M.get_name (| globals, "tx" |), "gas" |), + M.get_field (| M.get_name (| globals, "tx" |), "max_fee_per_gas" |) + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + Compare.lt (| + M.get_field (| M.get_name (| globals, "tx" |), "gas_price" |), + M.get_name (| globals, "base_fee_per_gas" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, "InvalidBlock" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "effective_gas_price" , + M.get_field (| M.get_name (| globals, "tx" |), "gas_price" |) + |) in + let _ := M.assign_local (| + "max_gas_fee" , + BinOp.mult (| + M.get_field (| M.get_name (| globals, "tx" |), "gas" |), + M.get_field (| M.get_name (| globals, "tx" |), "gas_price" |) + |) + |) in + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, "isinstance" |), + make_list [ + M.get_name (| globals, "tx" |); + M.get_name (| globals, "BlobTransaction" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + UnOp.not (| M.call (| + M.get_name (| globals, "isinstance" |), + make_list [ + M.get_field (| M.get_name (| globals, "tx" |), "to" |); + M.get_name (| globals, "Address" |) + ], + make_dict [] + |) |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, "InvalidBlock" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_field (| M.get_name (| globals, "tx" |), "blob_versioned_hashes" |) + ], + make_dict [] + |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, "InvalidBlock" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + M.for_ (| + M.get_name (| globals, "blob_versioned_hash" |), + M.get_field (| M.get_name (| globals, "tx" |), "blob_versioned_hashes" |), + ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + Compare.not_eq (| + M.slice (| + M.get_name (| globals, "blob_versioned_hash" |), + Constant.int 0, + Constant.int 1, + Constant.None_ + |), + M.get_name (| globals, "VERSIONED_HASH_VERSION_KZG" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, "InvalidBlock" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.lt (| + M.get_field (| M.get_name (| globals, "tx" |), "max_fee_per_blob_gas" |), + M.call (| + M.get_name (| globals, "calculate_blob_gas_price" |), + make_list [ + M.get_name (| globals, "excess_blob_gas" |) + ], + make_dict [] + |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, "InvalidBlock" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_op_local (| + BinOp.add, + "max_gas_fee", + BinOp.mult (| + M.call (| + M.get_name (| globals, "calculate_total_blob_gas" |), + make_list [ + M.get_name (| globals, "tx" |) + ], + make_dict [] + |), + M.get_field (| M.get_name (| globals, "tx" |), "max_fee_per_blob_gas" |) + |) + |) in + let _ := M.assign_local (| + "blob_versioned_hashes" , + M.get_field (| M.get_name (| globals, "tx" |), "blob_versioned_hashes" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "blob_versioned_hashes" , + make_tuple [ ] + |) in + M.pure Constant.None_ + )) |) in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + Compare.eq (| + M.get_field (| M.get_name (| globals, "sender_account" |), "nonce" |), + M.get_field (| M.get_name (| globals, "tx" |), "nonce" |) + |); + M.get_name (| globals, "InvalidBlock" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + Compare.gt_e (| + M.get_field (| M.get_name (| globals, "sender_account" |), "balance" |), + BinOp.add (| + M.get_name (| globals, "max_gas_fee" |), + M.get_field (| M.get_name (| globals, "tx" |), "value" |) + |) + |); + M.get_name (| globals, "InvalidBlock" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + Compare.eq (| + M.get_field (| M.get_name (| globals, "sender_account" |), "code" |), + M.call (| + M.get_name (| globals, "bytearray" |), + make_list [], + make_dict [] + |) + |); + M.get_name (| globals, "InvalidBlock" |) + ], + make_dict [] + |) in + let _ := M.return_ (| + make_tuple [ M.get_name (| globals, "sender" |); M.get_name (| globals, "effective_gas_price" |); M.get_name (| globals, "blob_versioned_hashes" |) ] + |) in + M.pure Constant.None_)). + +Definition make_receipt : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "tx"; "error"; "cumulative_gas_used"; "logs" ] |) in + let _ := Constant.str " + Make the receipt for a transaction that was executed. + + Parameters + ---------- + tx : + The executed transaction. + error : + Error in the top level frame of the transaction, if any. + cumulative_gas_used : + The total gas used so far in the block after the transaction was + executed. + logs : + The logs produced by the transaction. + + Returns + ------- + receipt : + The receipt for the transaction. + " in + let _ := M.assign_local (| + "receipt" , + M.call (| + M.get_name (| globals, "Receipt" |), + make_list [], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, "isinstance" |), + make_list [ + M.get_name (| globals, "tx" |); + M.get_name (| globals, "AccessListTransaction" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + BinOp.add (| + Constant.bytes "01", + M.call (| + M.get_field (| M.get_name (| globals, "rlp" |), "encode" |), + make_list [ + M.get_name (| globals, "receipt" |) + ], + make_dict [] + |) + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, "isinstance" |), + make_list [ + M.get_name (| globals, "tx" |); + M.get_name (| globals, "FeeMarketTransaction" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + BinOp.add (| + Constant.bytes "02", + M.call (| + M.get_field (| M.get_name (| globals, "rlp" |), "encode" |), + make_list [ + M.get_name (| globals, "receipt" |) + ], + make_dict [] + |) + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, "isinstance" |), + make_list [ + M.get_name (| globals, "tx" |); + M.get_name (| globals, "BlobTransaction" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + BinOp.add (| + Constant.bytes "03", + M.call (| + M.get_field (| M.get_name (| globals, "rlp" |), "encode" |), + make_list [ + M.get_name (| globals, "receipt" |) + ], + make_dict [] + |) + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.return_ (| + M.get_name (| globals, "receipt" |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_)). + +Definition ApplyBodyOutput : Value.t := + builtins.make_klass + [] + [ + + ] + [ + + ]. + +Definition apply_body : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "state"; "block_hashes"; "coinbase"; "block_number"; "base_fee_per_gas"; "block_gas_limit"; "block_time"; "prev_randao"; "transactions"; "chain_id"; "withdrawals"; "parent_beacon_block_root"; "excess_blob_gas" ] |) in + let _ := Constant.str " + Executes a block. + + Many of the contents of a block are stored in data structures called + tries. There is a transactions trie which is similar to a ledger of the + transactions stored in the current block. There is also a receipts trie + which stores the results of executing a transaction, like the post state + and gas used. This function creates and executes the block that is to be + added to the chain. + + Parameters + ---------- + state : + Current account state. + block_hashes : + List of hashes of the previous 256 blocks in the order of + increasing block number. + coinbase : + Address of account which receives block reward and transaction fees. + block_number : + Position of the block within the chain. + base_fee_per_gas : + Base fee per gas of within the block. + block_gas_limit : + Initial amount of gas available for execution in this block. + block_time : + Time the block was produced, measured in seconds since the epoch. + prev_randao : + The previous randao from the beacon chain. + transactions : + Transactions included in the block. + ommers : + Headers of ancestor blocks which are not direct parents (formerly + uncles.) + chain_id : + ID of the executing chain. + withdrawals : + Withdrawals to be processed in the current block. + parent_beacon_block_root : + The root of the beacon block from the parent block. + excess_blob_gas : + Excess blob gas calculated from the previous block. + + Returns + ------- + apply_body_output : `ApplyBodyOutput` + Output of applying the block body to the state. + " in + let _ := M.assign_local (| + "blob_gas_used" , + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "gas_available" , + M.get_name (| globals, "block_gas_limit" |) + |) in +(* At stmt: unsupported node type: AnnAssign *) +(* At stmt: unsupported node type: AnnAssign *) +(* At stmt: unsupported node type: AnnAssign *) +(* At stmt: unsupported node type: AnnAssign *) + let _ := M.assign_local (| + "beacon_block_roots_contract_code" , + M.get_field (| M.call (| + M.get_name (| globals, "get_account" |), + make_list [ + M.get_name (| globals, "state" |); + M.get_name (| globals, "BEACON_ROOTS_ADDRESS" |) + ], + make_dict [] + |), "code" |) + |) in + let _ := M.assign_local (| + "system_tx_message" , + M.call (| + M.get_name (| globals, "Message" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "system_tx_env" , + M.call (| + M.get_field (| M.get_name (| globals, "vm" |), "Environment" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "system_tx_output" , + M.call (| + M.get_name (| globals, "process_message_call" |), + make_list [ + M.get_name (| globals, "system_tx_message" |); + M.get_name (| globals, "system_tx_env" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "destroy_touched_empty_accounts" |), + make_list [ + M.get_field (| M.get_name (| globals, "system_tx_env" |), "state" |); + M.get_field (| M.get_name (| globals, "system_tx_output" |), "touched_accounts" |) + ], + make_dict [] + |) in + let _ := + M.for_ (| + make_tuple [ M.get_name (| globals, "i" |); M.get_name (| globals, "tx" |) ], + M.call (| + M.get_name (| globals, "enumerate" |), + make_list [ + M.call (| + M.get_name (| globals, "map" |), + make_list [ + M.get_name (| globals, "decode_transaction" |); + M.get_name (| globals, "transactions" |) + ], + make_dict [] + |) + ], + make_dict [] + |), + ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, "trie_set" |), + make_list [ + M.get_name (| globals, "transactions_trie" |); + M.call (| + M.get_field (| M.get_name (| globals, "rlp" |), "encode" |), + make_list [ + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.get_name (| globals, "i" |) + ], + make_dict [] + |) + ], + make_dict [] + |); + M.call (| + M.get_name (| globals, "encode_transaction" |), + make_list [ + M.get_name (| globals, "tx" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign (| + make_tuple [ M.get_name (| globals, "sender_address" |); M.get_name (| globals, "effective_gas_price" |); M.get_name (| globals, "blob_versioned_hashes" |) ], + M.call (| + M.get_name (| globals, "check_transaction" |), + make_list [ + M.get_name (| globals, "state" |); + M.get_name (| globals, "tx" |); + M.get_name (| globals, "gas_available" |); + M.get_name (| globals, "chain_id" |); + M.get_name (| globals, "base_fee_per_gas" |); + M.get_name (| globals, "excess_blob_gas" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "env" , + M.call (| + M.get_field (| M.get_name (| globals, "vm" |), "Environment" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.assign (| + make_tuple [ M.get_name (| globals, "gas_used" |); M.get_name (| globals, "logs" |); M.get_name (| globals, "error" |) ], + M.call (| + M.get_name (| globals, "process_transaction" |), + make_list [ + M.get_name (| globals, "env" |); + M.get_name (| globals, "tx" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_op_local (| + BinOp.sub, + "gas_available", + M.get_name (| globals, "gas_used" |) + |) in + let _ := M.assign_local (| + "receipt" , + M.call (| + M.get_name (| globals, "make_receipt" |), + make_list [ + M.get_name (| globals, "tx" |); + M.get_name (| globals, "error" |); + BinOp.sub (| + M.get_name (| globals, "block_gas_limit" |), + M.get_name (| globals, "gas_available" |) + |); + M.get_name (| globals, "logs" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "trie_set" |), + make_list [ + M.get_name (| globals, "receipts_trie" |); + M.call (| + M.get_field (| M.get_name (| globals, "rlp" |), "encode" |), + make_list [ + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.get_name (| globals, "i" |) + ], + make_dict [] + |) + ], + make_dict [] + |); + M.get_name (| globals, "receipt" |) + ], + make_dict [] + |) in + let _ := M.assign_op_local (| + BinOp.add, + "block_logs", + M.get_name (| globals, "logs" |) + |) in + let _ := M.assign_op_local (| + BinOp.add, + "blob_gas_used", + M.call (| + M.get_name (| globals, "calculate_total_blob_gas" |), + make_list [ + M.get_name (| globals, "tx" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + Compare.lt_e (| + M.get_name (| globals, "blob_gas_used" |), + M.get_name (| globals, "MAX_BLOB_GAS_PER_BLOCK" |) + |); + M.get_name (| globals, "InvalidBlock" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "block_gas_used" , + BinOp.sub (| + M.get_name (| globals, "block_gas_limit" |), + M.get_name (| globals, "gas_available" |) + |) + |) in + let _ := M.assign_local (| + "block_logs_bloom" , + M.call (| + M.get_name (| globals, "logs_bloom" |), + make_list [ + M.get_name (| globals, "block_logs" |) + ], + make_dict [] + |) + |) in + let _ := + M.for_ (| + make_tuple [ M.get_name (| globals, "i" |); M.get_name (| globals, "wd" |) ], + M.call (| + M.get_name (| globals, "enumerate" |), + make_list [ + M.get_name (| globals, "withdrawals" |) + ], + make_dict [] + |), + ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, "trie_set" |), + make_list [ + M.get_name (| globals, "withdrawals_trie" |); + M.call (| + M.get_field (| M.get_name (| globals, "rlp" |), "encode" |), + make_list [ + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.get_name (| globals, "i" |) + ], + make_dict [] + |) + ], + make_dict [] + |); + M.call (| + M.get_field (| M.get_name (| globals, "rlp" |), "encode" |), + make_list [ + M.get_name (| globals, "wd" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "process_withdrawal" |), + make_list [ + M.get_name (| globals, "state" |); + M.get_name (| globals, "wd" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, "account_exists_and_is_empty" |), + make_list [ + M.get_name (| globals, "state" |); + M.get_field (| M.get_name (| globals, "wd" |), "address" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, "destroy_account" |), + make_list [ + M.get_name (| globals, "state" |); + M.get_field (| M.get_name (| globals, "wd" |), "address" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, "ApplyBodyOutput" |), + make_list [ + M.get_name (| globals, "block_gas_used" |); + M.call (| + M.get_name (| globals, "root" |), + make_list [ + M.get_name (| globals, "transactions_trie" |) + ], + make_dict [] + |); + M.call (| + M.get_name (| globals, "root" |), + make_list [ + M.get_name (| globals, "receipts_trie" |) + ], + make_dict [] + |); + M.get_name (| globals, "block_logs_bloom" |); + M.call (| + M.get_name (| globals, "state_root" |), + make_list [ + M.get_name (| globals, "state" |) + ], + make_dict [] + |); + M.call (| + M.get_name (| globals, "root" |), + make_list [ + M.get_name (| globals, "withdrawals_trie" |) + ], + make_dict [] + |); + M.get_name (| globals, "blob_gas_used" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Definition process_transaction : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "env"; "tx" ] |) in + let _ := Constant.str " + Execute a transaction against the provided environment. + + This function processes the actions needed to execute a transaction. + It decrements the sender's account after calculating the gas fee and + refunds them the proper amount after execution. Calling contracts, + deploying code, and incrementing nonces are all examples of actions that + happen within this function or from a call made within this function. + + Accounts that are marked for deletion are processed and destroyed after + execution. + + Parameters + ---------- + env : + Environment for the Ethereum Virtual Machine. + tx : + Transaction to execute. + + Returns + ------- + gas_left : `ethereum.base_types.U256` + Remaining gas after execution. + logs : `Tuple[ethereum.blocks.Log, ...]` + Logs generated during execution. + " in + let _ := M.assign_local (| + "sender" , + M.get_field (| M.get_name (| globals, "env" |), "origin" |) + |) in + let _ := M.assign_local (| + "sender_account" , + M.call (| + M.get_name (| globals, "get_account" |), + make_list [ + M.get_field (| M.get_name (| globals, "env" |), "state" |); + M.get_name (| globals, "sender" |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, "isinstance" |), + make_list [ + M.get_name (| globals, "tx" |); + M.get_name (| globals, "BlobTransaction" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "blob_gas_fee" , + M.call (| + M.get_name (| globals, "calculate_data_fee" |), + make_list [ + M.get_field (| M.get_name (| globals, "env" |), "excess_blob_gas" |); + M.get_name (| globals, "tx" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "blob_gas_fee" , + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "effective_gas_fee" , + BinOp.mult (| + M.get_field (| M.get_name (| globals, "tx" |), "gas" |), + M.get_field (| M.get_name (| globals, "env" |), "gas_price" |) + |) + |) in + let _ := M.assign_local (| + "gas" , + BinOp.sub (| + M.get_field (| M.get_name (| globals, "tx" |), "gas" |), + M.call (| + M.get_name (| globals, "calculate_intrinsic_cost" |), + make_list [ + M.get_name (| globals, "tx" |) + ], + make_dict [] + |) + |) + |) in + let _ := M.call (| + M.get_name (| globals, "increment_nonce" |), + make_list [ + M.get_field (| M.get_name (| globals, "env" |), "state" |); + M.get_name (| globals, "sender" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "sender_balance_after_gas_fee" , + BinOp.sub (| + BinOp.sub (| + M.get_field (| M.get_name (| globals, "sender_account" |), "balance" |), + M.get_name (| globals, "effective_gas_fee" |) + |), + M.get_name (| globals, "blob_gas_fee" |) + |) + |) in + let _ := M.call (| + M.get_name (| globals, "set_account_balance" |), + make_list [ + M.get_field (| M.get_name (| globals, "env" |), "state" |); + M.get_name (| globals, "sender" |); + M.get_name (| globals, "sender_balance_after_gas_fee" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "preaccessed_addresses" , + M.call (| + M.get_name (| globals, "set" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "preaccessed_storage_keys" , + M.call (| + M.get_name (| globals, "set" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_field (| M.get_name (| globals, "preaccessed_addresses" |), "add" |), + make_list [ + M.get_field (| M.get_name (| globals, "env" |), "coinbase" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, "isinstance" |), + make_list [ + M.get_name (| globals, "tx" |); + make_tuple [ M.get_name (| globals, "AccessListTransaction" |); M.get_name (| globals, "FeeMarketTransaction" |); M.get_name (| globals, "BlobTransaction" |) ] + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := + M.for_ (| + make_tuple [ M.get_name (| globals, "address" |); M.get_name (| globals, "keys" |) ], + M.get_field (| M.get_name (| globals, "tx" |), "access_list" |), + ltac:(M.monadic ( + let _ := M.call (| + M.get_field (| M.get_name (| globals, "preaccessed_addresses" |), "add" |), + make_list [ + M.get_name (| globals, "address" |) + ], + make_dict [] + |) in + let _ := + M.for_ (| + M.get_name (| globals, "key" |), + M.get_name (| globals, "keys" |), + ltac:(M.monadic ( + let _ := M.call (| + M.get_field (| M.get_name (| globals, "preaccessed_storage_keys" |), "add" |), + make_list [ + make_tuple [ M.get_name (| globals, "address" |); M.get_name (| globals, "key" |) ] + ], + make_dict [] + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "message" , + M.call (| + M.get_name (| globals, "prepare_message" |), + make_list [ + M.get_name (| globals, "sender" |); + M.get_field (| M.get_name (| globals, "tx" |), "to" |); + M.get_field (| M.get_name (| globals, "tx" |), "value" |); + M.get_field (| M.get_name (| globals, "tx" |), "data" |); + M.get_name (| globals, "gas" |); + M.get_name (| globals, "env" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "output" , + M.call (| + M.get_name (| globals, "process_message_call" |), + make_list [ + M.get_name (| globals, "message" |); + M.get_name (| globals, "env" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "gas_used" , + BinOp.sub (| + M.get_field (| M.get_name (| globals, "tx" |), "gas" |), + M.get_field (| M.get_name (| globals, "output" |), "gas_left" |) + |) + |) in + let _ := M.assign_local (| + "gas_refund" , + M.call (| + M.get_name (| globals, "min" |), + make_list [ + BinOp.floor_div (| + M.get_name (| globals, "gas_used" |), + Constant.int 5 + |); + M.get_field (| M.get_name (| globals, "output" |), "refund_counter" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "gas_refund_amount" , + BinOp.mult (| + BinOp.add (| + M.get_field (| M.get_name (| globals, "output" |), "gas_left" |), + M.get_name (| globals, "gas_refund" |) + |), + M.get_field (| M.get_name (| globals, "env" |), "gas_price" |) + |) + |) in + let _ := M.assign_local (| + "priority_fee_per_gas" , + BinOp.sub (| + M.get_field (| M.get_name (| globals, "env" |), "gas_price" |), + M.get_field (| M.get_name (| globals, "env" |), "base_fee_per_gas" |) + |) + |) in + let _ := M.assign_local (| + "transaction_fee" , + BinOp.mult (| + BinOp.sub (| + BinOp.sub (| + M.get_field (| M.get_name (| globals, "tx" |), "gas" |), + M.get_field (| M.get_name (| globals, "output" |), "gas_left" |) + |), + M.get_name (| globals, "gas_refund" |) + |), + M.get_name (| globals, "priority_fee_per_gas" |) + |) + |) in + let _ := M.assign_local (| + "total_gas_used" , + BinOp.sub (| + M.get_name (| globals, "gas_used" |), + M.get_name (| globals, "gas_refund" |) + |) + |) in + let _ := M.assign_local (| + "sender_balance_after_refund" , + BinOp.add (| + M.get_field (| M.call (| + M.get_name (| globals, "get_account" |), + make_list [ + M.get_field (| M.get_name (| globals, "env" |), "state" |); + M.get_name (| globals, "sender" |) + ], + make_dict [] + |), "balance" |), + M.get_name (| globals, "gas_refund_amount" |) + |) + |) in + let _ := M.call (| + M.get_name (| globals, "set_account_balance" |), + make_list [ + M.get_field (| M.get_name (| globals, "env" |), "state" |); + M.get_name (| globals, "sender" |); + M.get_name (| globals, "sender_balance_after_refund" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "coinbase_balance_after_mining_fee" , + BinOp.add (| + M.get_field (| M.call (| + M.get_name (| globals, "get_account" |), + make_list [ + M.get_field (| M.get_name (| globals, "env" |), "state" |); + M.get_field (| M.get_name (| globals, "env" |), "coinbase" |) + ], + make_dict [] + |), "balance" |), + M.get_name (| globals, "transaction_fee" |) + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.not_eq (| + M.get_name (| globals, "coinbase_balance_after_mining_fee" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, "set_account_balance" |), + make_list [ + M.get_field (| M.get_name (| globals, "env" |), "state" |); + M.get_field (| M.get_name (| globals, "env" |), "coinbase" |); + M.get_name (| globals, "coinbase_balance_after_mining_fee" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, "account_exists_and_is_empty" |), + make_list [ + M.get_field (| M.get_name (| globals, "env" |), "state" |); + M.get_field (| M.get_name (| globals, "env" |), "coinbase" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, "destroy_account" |), + make_list [ + M.get_field (| M.get_name (| globals, "env" |), "state" |); + M.get_field (| M.get_name (| globals, "env" |), "coinbase" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )) |) in + let _ := + M.for_ (| + M.get_name (| globals, "address" |), + M.get_field (| M.get_name (| globals, "output" |), "accounts_to_delete" |), + ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, "destroy_account" |), + make_list [ + M.get_field (| M.get_name (| globals, "env" |), "state" |); + M.get_name (| globals, "address" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := M.call (| + M.get_name (| globals, "destroy_touched_empty_accounts" |), + make_list [ + M.get_field (| M.get_name (| globals, "env" |), "state" |); + M.get_field (| M.get_name (| globals, "output" |), "touched_accounts" |) + ], + make_dict [] + |) in + let _ := M.return_ (| + make_tuple [ M.get_name (| globals, "total_gas_used" |); M.get_field (| M.get_name (| globals, "output" |), "logs" |); M.get_field (| M.get_name (| globals, "output" |), "error" |) ] + |) in + M.pure Constant.None_)). + +Definition calculate_intrinsic_cost : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "tx" ] |) in + let _ := Constant.str " + Calculates the gas that is charged before execution is started. + + The intrinsic cost of the transaction is charged before execution has + begun. Functions/operations in the EVM cost money to execute so this + intrinsic cost is for the operations that need to be paid for as part of + the transaction. Data transfer, for example, is part of this intrinsic + cost. It costs ether to send data over the wire and that ether is + accounted for in the intrinsic cost calculated in this function. This + intrinsic cost must be calculated and paid for before execution in order + for all operations to be implemented. + + Parameters + ---------- + tx : + Transaction to compute the intrinsic cost of. + + Returns + ------- + verified : `ethereum.base_types.Uint` + The intrinsic cost of the transaction. + " in + let _ := M.assign_local (| + "data_cost" , + Constant.int 0 + |) in + let _ := + M.for_ (| + M.get_name (| globals, "byte" |), + M.get_field (| M.get_name (| globals, "tx" |), "data" |), + ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, "byte" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_op_local (| + BinOp.add, + "data_cost", + M.get_name (| globals, "TX_DATA_COST_PER_ZERO" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_op_local (| + BinOp.add, + "data_cost", + M.get_name (| globals, "TX_DATA_COST_PER_NON_ZERO" |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_field (| M.get_name (| globals, "tx" |), "to" |), + M.call (| + M.get_name (| globals, "Bytes0" |), + make_list [ + Constant.bytes "" + ], + make_dict [] + |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "create_cost" , + BinOp.add (| + M.get_name (| globals, "TX_CREATE_COST" |), + M.call (| + M.get_name (| globals, "int" |), + make_list [ + M.call (| + M.get_name (| globals, "init_code_cost" |), + make_list [ + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_field (| M.get_name (| globals, "tx" |), "data" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "create_cost" , + Constant.int 0 + |) in + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "access_list_cost" , + Constant.int 0 + |) in + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, "isinstance" |), + make_list [ + M.get_name (| globals, "tx" |); + make_tuple [ M.get_name (| globals, "AccessListTransaction" |); M.get_name (| globals, "FeeMarketTransaction" |); M.get_name (| globals, "BlobTransaction" |) ] + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := + M.for_ (| + make_tuple [ M.get_name (| globals, "_address" |); M.get_name (| globals, "keys" |) ], + M.get_field (| M.get_name (| globals, "tx" |), "access_list" |), + ltac:(M.monadic ( + let _ := M.assign_op_local (| + BinOp.add, + "access_list_cost", + M.get_name (| globals, "TX_ACCESS_LIST_ADDRESS_COST" |) + |) in + let _ := M.assign_op_local (| + BinOp.add, + "access_list_cost", + BinOp.mult (| + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_name (| globals, "keys" |) + ], + make_dict [] + |), + M.get_name (| globals, "TX_ACCESS_LIST_STORAGE_KEY_COST" |) + |) + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + BinOp.add (| + BinOp.add (| + BinOp.add (| + M.get_name (| globals, "TX_BASE_COST" |), + M.get_name (| globals, "data_cost" |) + |), + M.get_name (| globals, "create_cost" |) + |), + M.get_name (| globals, "access_list_cost" |) + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Definition recover_sender : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "chain_id"; "tx" ] |) in + let _ := Constant.str " + Extracts the sender address from a transaction. + + The v, r, and s values are the three parts that make up the signature + of a transaction. In order to recover the sender of a transaction the two + components needed are the signature (``v``, ``r``, and ``s``) and the + signing hash of the transaction. The sender's public key can be obtained + with these two values and therefore the sender address can be retrieved. + + Parameters + ---------- + tx : + Transaction of interest. + chain_id : + ID of the executing chain. + + Returns + ------- + sender : `ethereum.fork_types.Address` + The address of the account that signed the transaction. + " in + let _ := M.assign (| + make_tuple [ M.get_name (| globals, "r" |); M.get_name (| globals, "s" |) ], + make_tuple [ M.get_field (| M.get_name (| globals, "tx" |), "r" |); M.get_field (| M.get_name (| globals, "tx" |), "s" |) ] + |) in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + BoolOp.and (| + Compare.lt (| + Constant.int 0, + M.get_name (| globals, "r" |) + |), + ltac:(M.monadic ( + Compare.lt (| + M.get_name (| globals, "r" |), + M.get_name (| globals, "SECP256K1N" |) + |) + )) + |); + M.get_name (| globals, "InvalidBlock" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + BoolOp.and (| + Compare.lt (| + Constant.int 0, + M.get_name (| globals, "s" |) + |), + ltac:(M.monadic ( + Compare.lt_e (| + M.get_name (| globals, "s" |), + BinOp.floor_div (| + M.get_name (| globals, "SECP256K1N" |), + Constant.int 2 + |) + |) + )) + |); + M.get_name (| globals, "InvalidBlock" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, "isinstance" |), + make_list [ + M.get_name (| globals, "tx" |); + M.get_name (| globals, "LegacyTransaction" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "v" , + M.get_field (| M.get_name (| globals, "tx" |), "v" |) + |) in + let _ := + (* if *) + M.if_then_else (| + BoolOp.or (| + Compare.eq (| + M.get_name (| globals, "v" |), + Constant.int 27 + |), + ltac:(M.monadic ( + Compare.eq (| + M.get_name (| globals, "v" |), + Constant.int 28 + |) + )) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "public_key" , + M.call (| + M.get_name (| globals, "secp256k1_recover" |), + make_list [ + M.get_name (| globals, "r" |); + M.get_name (| globals, "s" |); + BinOp.sub (| + M.get_name (| globals, "v" |), + Constant.int 27 + |); + M.call (| + M.get_name (| globals, "signing_hash_pre155" |), + make_list [ + M.get_name (| globals, "tx" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + BoolOp.or (| + Compare.eq (| + M.get_name (| globals, "v" |), + BinOp.add (| + Constant.int 35, + BinOp.mult (| + M.get_name (| globals, "chain_id" |), + Constant.int 2 + |) + |) + |), + ltac:(M.monadic ( + Compare.eq (| + M.get_name (| globals, "v" |), + BinOp.add (| + Constant.int 36, + BinOp.mult (| + M.get_name (| globals, "chain_id" |), + Constant.int 2 + |) + |) + |) + )) + |); + M.get_name (| globals, "InvalidBlock" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "public_key" , + M.call (| + M.get_name (| globals, "secp256k1_recover" |), + make_list [ + M.get_name (| globals, "r" |); + M.get_name (| globals, "s" |); + BinOp.sub (| + BinOp.sub (| + M.get_name (| globals, "v" |), + Constant.int 35 + |), + BinOp.mult (| + M.get_name (| globals, "chain_id" |), + Constant.int 2 + |) + |); + M.call (| + M.get_name (| globals, "signing_hash_155" |), + make_list [ + M.get_name (| globals, "tx" |); + M.get_name (| globals, "chain_id" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, "isinstance" |), + make_list [ + M.get_name (| globals, "tx" |); + M.get_name (| globals, "AccessListTransaction" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "public_key" , + M.call (| + M.get_name (| globals, "secp256k1_recover" |), + make_list [ + M.get_name (| globals, "r" |); + M.get_name (| globals, "s" |); + M.get_field (| M.get_name (| globals, "tx" |), "y_parity" |); + M.call (| + M.get_name (| globals, "signing_hash_2930" |), + make_list [ + M.get_name (| globals, "tx" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, "isinstance" |), + make_list [ + M.get_name (| globals, "tx" |); + M.get_name (| globals, "FeeMarketTransaction" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "public_key" , + M.call (| + M.get_name (| globals, "secp256k1_recover" |), + make_list [ + M.get_name (| globals, "r" |); + M.get_name (| globals, "s" |); + M.get_field (| M.get_name (| globals, "tx" |), "y_parity" |); + M.call (| + M.get_name (| globals, "signing_hash_1559" |), + make_list [ + M.get_name (| globals, "tx" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, "isinstance" |), + make_list [ + M.get_name (| globals, "tx" |); + M.get_name (| globals, "BlobTransaction" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "public_key" , + M.call (| + M.get_name (| globals, "secp256k1_recover" |), + make_list [ + M.get_name (| globals, "r" |); + M.get_name (| globals, "s" |); + M.get_field (| M.get_name (| globals, "tx" |), "y_parity" |); + M.call (| + M.get_name (| globals, "signing_hash_4844" |), + make_list [ + M.get_name (| globals, "tx" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )) |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, "Address" |), + make_list [ + M.slice (| + M.call (| + M.get_name (| globals, "keccak256" |), + make_list [ + M.get_name (| globals, "public_key" |) + ], + make_dict [] + |), + Constant.int 12, + Constant.int 32, + Constant.None_ + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Definition signing_hash_pre155 : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "tx" ] |) in + let _ := Constant.str " + Compute the hash of a transaction used in a legacy (pre EIP 155) signature. + + Parameters + ---------- + tx : + Transaction of interest. + + Returns + ------- + hash : `ethereum.crypto.hash.Hash32` + Hash of the transaction. + " in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, "keccak256" |), + make_list [ + M.call (| + M.get_field (| M.get_name (| globals, "rlp" |), "encode" |), + make_list [ + make_tuple [ M.get_field (| M.get_name (| globals, "tx" |), "nonce" |); M.get_field (| M.get_name (| globals, "tx" |), "gas_price" |); M.get_field (| M.get_name (| globals, "tx" |), "gas" |); M.get_field (| M.get_name (| globals, "tx" |), "to" |); M.get_field (| M.get_name (| globals, "tx" |), "value" |); M.get_field (| M.get_name (| globals, "tx" |), "data" |) ] + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Definition signing_hash_155 : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "tx"; "chain_id" ] |) in + let _ := Constant.str " + Compute the hash of a transaction used in a EIP 155 signature. + + Parameters + ---------- + tx : + Transaction of interest. + chain_id : + The id of the current chain. + + Returns + ------- + hash : `ethereum.crypto.hash.Hash32` + Hash of the transaction. + " in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, "keccak256" |), + make_list [ + M.call (| + M.get_field (| M.get_name (| globals, "rlp" |), "encode" |), + make_list [ + make_tuple [ M.get_field (| M.get_name (| globals, "tx" |), "nonce" |); M.get_field (| M.get_name (| globals, "tx" |), "gas_price" |); M.get_field (| M.get_name (| globals, "tx" |), "gas" |); M.get_field (| M.get_name (| globals, "tx" |), "to" |); M.get_field (| M.get_name (| globals, "tx" |), "value" |); M.get_field (| M.get_name (| globals, "tx" |), "data" |); M.get_name (| globals, "chain_id" |); M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |); M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) ] + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Definition signing_hash_2930 : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "tx" ] |) in + let _ := Constant.str " + Compute the hash of a transaction used in a EIP 2930 signature. + + Parameters + ---------- + tx : + Transaction of interest. + + Returns + ------- + hash : `ethereum.crypto.hash.Hash32` + Hash of the transaction. + " in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, "keccak256" |), + make_list [ + BinOp.add (| + Constant.bytes "01", + M.call (| + M.get_field (| M.get_name (| globals, "rlp" |), "encode" |), + make_list [ + make_tuple [ M.get_field (| M.get_name (| globals, "tx" |), "chain_id" |); M.get_field (| M.get_name (| globals, "tx" |), "nonce" |); M.get_field (| M.get_name (| globals, "tx" |), "gas_price" |); M.get_field (| M.get_name (| globals, "tx" |), "gas" |); M.get_field (| M.get_name (| globals, "tx" |), "to" |); M.get_field (| M.get_name (| globals, "tx" |), "value" |); M.get_field (| M.get_name (| globals, "tx" |), "data" |); M.get_field (| M.get_name (| globals, "tx" |), "access_list" |) ] + ], + make_dict [] + |) + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Definition signing_hash_1559 : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "tx" ] |) in + let _ := Constant.str " + Compute the hash of a transaction used in a EIP 1559 signature. + + Parameters + ---------- + tx : + Transaction of interest. + + Returns + ------- + hash : `ethereum.crypto.hash.Hash32` + Hash of the transaction. + " in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, "keccak256" |), + make_list [ + BinOp.add (| + Constant.bytes "02", + M.call (| + M.get_field (| M.get_name (| globals, "rlp" |), "encode" |), + make_list [ + make_tuple [ M.get_field (| M.get_name (| globals, "tx" |), "chain_id" |); M.get_field (| M.get_name (| globals, "tx" |), "nonce" |); M.get_field (| M.get_name (| globals, "tx" |), "max_priority_fee_per_gas" |); M.get_field (| M.get_name (| globals, "tx" |), "max_fee_per_gas" |); M.get_field (| M.get_name (| globals, "tx" |), "gas" |); M.get_field (| M.get_name (| globals, "tx" |), "to" |); M.get_field (| M.get_name (| globals, "tx" |), "value" |); M.get_field (| M.get_name (| globals, "tx" |), "data" |); M.get_field (| M.get_name (| globals, "tx" |), "access_list" |) ] + ], + make_dict [] + |) + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Definition signing_hash_4844 : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "tx" ] |) in + let _ := Constant.str " + Compute the hash of a transaction used in a EIP-4844 signature. + + Parameters + ---------- + tx : + Transaction of interest. + + Returns + ------- + hash : `ethereum.crypto.hash.Hash32` + Hash of the transaction. + " in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, "keccak256" |), + make_list [ + BinOp.add (| + Constant.bytes "03", + M.call (| + M.get_field (| M.get_name (| globals, "rlp" |), "encode" |), + make_list [ + make_tuple [ M.get_field (| M.get_name (| globals, "tx" |), "chain_id" |); M.get_field (| M.get_name (| globals, "tx" |), "nonce" |); M.get_field (| M.get_name (| globals, "tx" |), "max_priority_fee_per_gas" |); M.get_field (| M.get_name (| globals, "tx" |), "max_fee_per_gas" |); M.get_field (| M.get_name (| globals, "tx" |), "gas" |); M.get_field (| M.get_name (| globals, "tx" |), "to" |); M.get_field (| M.get_name (| globals, "tx" |), "value" |); M.get_field (| M.get_name (| globals, "tx" |), "data" |); M.get_field (| M.get_name (| globals, "tx" |), "access_list" |); M.get_field (| M.get_name (| globals, "tx" |), "max_fee_per_blob_gas" |); M.get_field (| M.get_name (| globals, "tx" |), "blob_versioned_hashes" |) ] + ], + make_dict [] + |) + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Definition compute_header_hash : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "header" ] |) in + let _ := Constant.str " + Computes the hash of a block header. + + The header hash of a block is the canonical hash that is used to refer + to a specific block and completely distinguishes a block from another. + + ``keccak256`` is a function that produces a 256 bit hash of any input. + It also takes in any number of bytes as an input and produces a single + hash for them. A hash is a completely unique output for a single input. + So an input corresponds to one unique hash that can be used to identify + the input exactly. + + Prior to using the ``keccak256`` hash function, the header must be + encoded using the Recursive-Length Prefix. See :ref:`rlp`. + RLP encoding the header converts it into a space-efficient format that + allows for easy transfer of data between nodes. The purpose of RLP is to + encode arbitrarily nested arrays of binary data, and RLP is the primary + encoding method used to serialize objects in Ethereum's execution layer. + The only purpose of RLP is to encode structure; encoding specific data + types (e.g. strings, floats) is left up to higher-order protocols. + + Parameters + ---------- + header : + Header of interest. + + Returns + ------- + hash : `ethereum.crypto.hash.Hash32` + Hash of the header. + " in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, "keccak256" |), + make_list [ + M.call (| + M.get_field (| M.get_name (| globals, "rlp" |), "encode" |), + make_list [ + M.get_name (| globals, "header" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Definition check_gas_limit : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "gas_limit"; "parent_gas_limit" ] |) in + let _ := Constant.str " + Validates the gas limit for a block. + + The bounds of the gas limit, ``max_adjustment_delta``, is set as the + quotient of the parent block's gas limit and the + ``GAS_LIMIT_ADJUSTMENT_FACTOR``. Therefore, if the gas limit that is + passed through as a parameter is greater than or equal to the *sum* of + the parent's gas and the adjustment delta then the limit for gas is too + high and fails this function's check. Similarly, if the limit is less + than or equal to the *difference* of the parent's gas and the adjustment + delta *or* the predefined ``GAS_LIMIT_MINIMUM`` then this function's + check fails because the gas limit doesn't allow for a sufficient or + reasonable amount of gas to be used on a block. + + Parameters + ---------- + gas_limit : + Gas limit to validate. + + parent_gas_limit : + Gas limit of the parent block. + + Returns + ------- + check : `bool` + True if gas limit constraints are satisfied, False otherwise. + " in + let _ := M.assign_local (| + "max_adjustment_delta" , + BinOp.floor_div (| + M.get_name (| globals, "parent_gas_limit" |), + M.get_name (| globals, "GAS_LIMIT_ADJUSTMENT_FACTOR" |) + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.gt_e (| + M.get_name (| globals, "gas_limit" |), + BinOp.add (| + M.get_name (| globals, "parent_gas_limit" |), + M.get_name (| globals, "max_adjustment_delta" |) + |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + Constant.bool false + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + Compare.lt_e (| + M.get_name (| globals, "gas_limit" |), + BinOp.sub (| + M.get_name (| globals, "parent_gas_limit" |), + M.get_name (| globals, "max_adjustment_delta" |) + |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + Constant.bool false + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + Compare.lt (| + M.get_name (| globals, "gas_limit" |), + M.get_name (| globals, "GAS_LIMIT_MINIMUM" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + Constant.bool false + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.return_ (| + Constant.bool true + |) in + M.pure Constant.None_)). diff --git a/CoqOfPython/ethereum/cancun/fork_types.v b/CoqOfPython/ethereum/cancun/fork_types.v new file mode 100644 index 0000000..dd0de4b --- /dev/null +++ b/CoqOfPython/ethereum/cancun/fork_types.v @@ -0,0 +1,102 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.cancun.fork_types". + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Types +^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Types re-used throughout the specification, which are specific to Ethereum. +". + +Axiom dataclasses_imports_dataclass : + IsImported globals "dataclasses" "dataclass". + +Axiom ethereum_imports_rlp : + IsImported globals "ethereum" "rlp". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_Bytes : + IsImported globals "ethereum.base_types" "Bytes". +Axiom ethereum_base_types_imports_Bytes20 : + IsImported globals "ethereum.base_types" "Bytes20". +Axiom ethereum_base_types_imports_Bytes256 : + IsImported globals "ethereum.base_types" "Bytes256". +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". +Axiom ethereum_base_types_imports_slotted_freezable : + IsImported globals "ethereum.base_types" "slotted_freezable". + +Axiom ethereum_crypto_hash_imports_Hash32 : + IsImported globals "ethereum.crypto.hash" "Hash32". +Axiom ethereum_crypto_hash_imports_keccak256 : + IsImported globals "ethereum.crypto.hash" "keccak256". + +Definition Address : Value.t := M.run ltac:(M.monadic ( + M.get_name (| globals, "Bytes20" |) +)). + +Definition Root : Value.t := M.run ltac:(M.monadic ( + M.get_name (| globals, "Hash32" |) +)). + +Definition VersionedHash : Value.t := M.run ltac:(M.monadic ( + M.get_name (| globals, "Hash32" |) +)). + +Definition Bloom : Value.t := M.run ltac:(M.monadic ( + M.get_name (| globals, "Bytes256" |) +)). + +Definition Account : Value.t := + builtins.make_klass + [] + [ + + ] + [ + + ]. + +Definition EMPTY_ACCOUNT : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Account" |), + make_list [], + make_dict [] + |) +)). + +Definition encode_account : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "raw_account_data"; "storage_root" ] |) in + let _ := Constant.str " + Encode `Account` dataclass. + + Storage is not stored in the `Account` dataclass, so `Accounts` cannot be + encoded with providing a storage root. + " in + let _ := M.return_ (| + M.call (| + M.get_field (| M.get_name (| globals, "rlp" |), "encode" |), + make_list [ + make_tuple [ M.get_field (| M.get_name (| globals, "raw_account_data" |), "nonce" |); M.get_field (| M.get_name (| globals, "raw_account_data" |), "balance" |); M.get_name (| globals, "storage_root" |); M.call (| + M.get_name (| globals, "keccak256" |), + make_list [ + M.get_field (| M.get_name (| globals, "raw_account_data" |), "code" |) + ], + make_dict [] + |) ] + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). diff --git a/CoqOfPython/ethereum/cancun/state.v b/CoqOfPython/ethereum/cancun/state.v new file mode 100644 index 0000000..897c75a --- /dev/null +++ b/CoqOfPython/ethereum/cancun/state.v @@ -0,0 +1,1523 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.cancun.state". + +Definition expr_1 : Value.t := + Constant.str " +State +^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +The state contains all information that is preserved between transactions. + +It consists of a main account trie and storage tries for each contract. + +There is a distinction between an account that does not exist and +`EMPTY_ACCOUNT`. +". + +Axiom dataclasses_imports_dataclass : + IsImported globals "dataclasses" "dataclass". +Axiom dataclasses_imports_field : + IsImported globals "dataclasses" "field". + +Axiom typing_imports_Callable : + IsImported globals "typing" "Callable". +Axiom typing_imports_Dict : + IsImported globals "typing" "Dict". +Axiom typing_imports_Iterable : + IsImported globals "typing" "Iterable". +Axiom typing_imports_List : + IsImported globals "typing" "List". +Axiom typing_imports_Optional : + IsImported globals "typing" "Optional". +Axiom typing_imports_Set : + IsImported globals "typing" "Set". +Axiom typing_imports_Tuple : + IsImported globals "typing" "Tuple". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_Bytes : + IsImported globals "ethereum.base_types" "Bytes". +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". +Axiom ethereum_base_types_imports_modify : + IsImported globals "ethereum.base_types" "modify". + +Axiom ethereum_utils_ensure_imports_ensure : + IsImported globals "ethereum.utils.ensure" "ensure". + +Axiom ethereum_cancun_blocks_imports_Withdrawal : + IsImported globals "ethereum.cancun.blocks" "Withdrawal". + +Axiom ethereum_cancun_fork_types_imports_EMPTY_ACCOUNT : + IsImported globals "ethereum.cancun.fork_types" "EMPTY_ACCOUNT". +Axiom ethereum_cancun_fork_types_imports_Account : + IsImported globals "ethereum.cancun.fork_types" "Account". +Axiom ethereum_cancun_fork_types_imports_Address : + IsImported globals "ethereum.cancun.fork_types" "Address". +Axiom ethereum_cancun_fork_types_imports_Root : + IsImported globals "ethereum.cancun.fork_types" "Root". + +Axiom ethereum_cancun_trie_imports_EMPTY_TRIE_ROOT : + IsImported globals "ethereum.cancun.trie" "EMPTY_TRIE_ROOT". +Axiom ethereum_cancun_trie_imports_Trie : + IsImported globals "ethereum.cancun.trie" "Trie". +Axiom ethereum_cancun_trie_imports_copy_trie : + IsImported globals "ethereum.cancun.trie" "copy_trie". +Axiom ethereum_cancun_trie_imports_root : + IsImported globals "ethereum.cancun.trie" "root". +Axiom ethereum_cancun_trie_imports_trie_get : + IsImported globals "ethereum.cancun.trie" "trie_get". +Axiom ethereum_cancun_trie_imports_trie_set : + IsImported globals "ethereum.cancun.trie" "trie_set". + +Definition State : Value.t := + builtins.make_klass + [] + [ + + ] + [ + + ]. + +Definition TransientStorage : Value.t := + builtins.make_klass + [] + [ + + ] + [ + + ]. + +Definition close_state : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "state" ] |) in + let _ := Constant.str " + Free resources held by the state. Used by optimized implementations to + release file descriptors. + " in + let _ := M.delete (| M.get_field (| M.get_name (| globals, "state" |), "_main_trie" |) |) in + let _ := M.delete (| M.get_field (| M.get_name (| globals, "state" |), "_storage_tries" |) |) in + let _ := M.delete (| M.get_field (| M.get_name (| globals, "state" |), "_snapshots" |) |) in + let _ := M.delete (| M.get_field (| M.get_name (| globals, "state" |), "created_accounts" |) |) in + M.pure Constant.None_)). + +Definition begin_transaction : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "state"; "transient_storage" ] |) in + let _ := Constant.str " + Start a state transaction. + + Transactions are entirely implicit and can be nested. It is not possible to + calculate the state root during a transaction. + + Parameters + ---------- + state : State + The state. + transient_storage : TransientStorage + The transient storage of the transaction. + " in + let _ := M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, "state" |), "_snapshots" |), "append" |), + make_list [ + make_tuple [ M.call (| + M.get_name (| globals, "copy_trie" |), + make_list [ + M.get_field (| M.get_name (| globals, "state" |), "_main_trie" |) + ], + make_dict [] + |); Constant.str "(* At expr: unsupported node type: DictComp *)" ] + ], + make_dict [] + |) in + let _ := M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, "transient_storage" |), "_snapshots" |), "append" |), + make_list [ + Constant.str "(* At expr: unsupported node type: DictComp *)" + ], + make_dict [] + |) in + M.pure Constant.None_)). + +Definition commit_transaction : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "state"; "transient_storage" ] |) in + let _ := Constant.str " + Commit a state transaction. + + Parameters + ---------- + state : State + The state. + transient_storage : TransientStorage + The transient storage of the transaction. + " in + let _ := M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, "state" |), "_snapshots" |), "pop" |), + make_list [], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + UnOp.not (| M.get_field (| M.get_name (| globals, "state" |), "_snapshots" |) |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, "state" |), "created_accounts" |), "clear" |), + make_list [], + make_dict [] + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, "transient_storage" |), "_snapshots" |), "pop" |), + make_list [], + make_dict [] + |) in + M.pure Constant.None_)). + +Definition rollback_transaction : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "state"; "transient_storage" ] |) in + let _ := Constant.str " + Rollback a state transaction, resetting the state to the point when the + corresponding `start_transaction()` call was made. + + Parameters + ---------- + state : State + The state. + transient_storage : TransientStorage + The transient storage of the transaction. + " in + let _ := M.assign (| + make_tuple [ M.get_field (| M.get_name (| globals, "state" |), "_main_trie" |); M.get_field (| M.get_name (| globals, "state" |), "_storage_tries" |) ], + M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, "state" |), "_snapshots" |), "pop" |), + make_list [], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + UnOp.not (| M.get_field (| M.get_name (| globals, "state" |), "_snapshots" |) |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, "state" |), "created_accounts" |), "clear" |), + make_list [], + make_dict [] + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, "transient_storage" |), "_tries" |), + M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, "transient_storage" |), "_snapshots" |), "pop" |), + make_list [], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Definition get_account : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "state"; "address" ] |) in + let _ := Constant.str " + Get the `Account` object at an address. Returns `EMPTY_ACCOUNT` if there + is no account at the address. + + Use `get_account_optional()` if you care about the difference between a + non-existent account and `EMPTY_ACCOUNT`. + + Parameters + ---------- + state: `State` + The state + address : `Address` + Address to lookup. + + Returns + ------- + account : `Account` + Account at address. + " in + let _ := M.assign_local (| + "account" , + M.call (| + M.get_name (| globals, "get_account_optional" |), + make_list [ + M.get_name (| globals, "state" |); + M.get_name (| globals, "address" |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, "isinstance" |), + make_list [ + M.get_name (| globals, "account" |); + M.get_name (| globals, "Account" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + M.get_name (| globals, "account" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.return_ (| + M.get_name (| globals, "EMPTY_ACCOUNT" |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_)). + +Definition get_account_optional : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "state"; "address" ] |) in + let _ := Constant.str " + Get the `Account` object at an address. Returns `None` (rather than + `EMPTY_ACCOUNT`) if there is no account at the address. + + Parameters + ---------- + state: `State` + The state + address : `Address` + Address to lookup. + + Returns + ------- + account : `Account` + Account at address. + " in + let _ := M.assign_local (| + "account" , + M.call (| + M.get_name (| globals, "trie_get" |), + make_list [ + M.get_field (| M.get_name (| globals, "state" |), "_main_trie" |); + M.get_name (| globals, "address" |) + ], + make_dict [] + |) + |) in + let _ := M.return_ (| + M.get_name (| globals, "account" |) + |) in + M.pure Constant.None_)). + +Definition set_account : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "state"; "address"; "account" ] |) in + let _ := Constant.str " + Set the `Account` object at an address. Setting to `None` deletes + the account (but not its storage, see `destroy_account()`). + + Parameters + ---------- + state: `State` + The state + address : `Address` + Address to set. + account : `Account` + Account to set at address. + " in + let _ := M.call (| + M.get_name (| globals, "trie_set" |), + make_list [ + M.get_field (| M.get_name (| globals, "state" |), "_main_trie" |); + M.get_name (| globals, "address" |); + M.get_name (| globals, "account" |) + ], + make_dict [] + |) in + M.pure Constant.None_)). + +Definition destroy_account : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "state"; "address" ] |) in + let _ := Constant.str " + Completely remove the account at `address` and all of its storage. + + This function is made available exclusively for the `SELFDESTRUCT` + opcode. It is expected that `SELFDESTRUCT` will be disabled in a future + hardfork and this function will be removed. + + Parameters + ---------- + state: `State` + The state + address : `Address` + Address of account to destroy. + " in + let _ := M.call (| + M.get_name (| globals, "destroy_storage" |), + make_list [ + M.get_name (| globals, "state" |); + M.get_name (| globals, "address" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "set_account" |), + make_list [ + M.get_name (| globals, "state" |); + M.get_name (| globals, "address" |); + Constant.None_ + ], + make_dict [] + |) in + M.pure Constant.None_)). + +Definition destroy_storage : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "state"; "address" ] |) in + let _ := Constant.str " + Completely remove the storage at `address`. + + Parameters + ---------- + state: `State` + The state + address : `Address` + Address of account whose storage is to be deleted. + " in + let _ := + (* if *) + M.if_then_else (| + Compare.in_ (| + M.get_name (| globals, "address" |), + M.get_field (| M.get_name (| globals, "state" |), "_storage_tries" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.delete (| M.get_subscript (| + M.get_field (| M.get_name (| globals, "state" |), "_storage_tries" |), + M.get_name (| globals, "address" |) + |) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + M.pure Constant.None_)). + +Definition mark_account_created : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "state"; "address" ] |) in + let _ := Constant.str " + Mark an account as having been created in the current transaction. + This information is used by `get_storage_original()` to handle an obscure + edgecase. + + The marker is not removed even if the account creation reverts. Since the + account cannot have had code prior to its creation and can't call + `get_storage_original()`, this is harmless. + + Parameters + ---------- + state: `State` + The state + address : `Address` + Address of the account that has been created. + " in + let _ := M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, "state" |), "created_accounts" |), "add" |), + make_list [ + M.get_name (| globals, "address" |) + ], + make_dict [] + |) in + M.pure Constant.None_)). + +Definition get_storage : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "state"; "address"; "key" ] |) in + let _ := Constant.str " + Get a value at a storage key on an account. Returns `U256(0)` if the + storage key has not been set previously. + + Parameters + ---------- + state: `State` + The state + address : `Address` + Address of the account. + key : `Bytes` + Key to lookup. + + Returns + ------- + value : `U256` + Value at the key. + " in + let _ := M.assign_local (| + "trie" , + M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, "state" |), "_storage_tries" |), "get" |), + make_list [ + M.get_name (| globals, "address" |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.is (| + M.get_name (| globals, "trie" |), + Constant.None_ + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "value" , + M.call (| + M.get_name (| globals, "trie_get" |), + make_list [ + M.get_name (| globals, "trie" |); + M.get_name (| globals, "key" |) + ], + make_dict [] + |) + |) in + let _ := M.assert (| M.call (| + M.get_name (| globals, "isinstance" |), + make_list [ + M.get_name (| globals, "value" |); + M.get_name (| globals, "U256" |) + ], + make_dict [] + |) |) in + let _ := M.return_ (| + M.get_name (| globals, "value" |) + |) in + M.pure Constant.None_)). + +Definition set_storage : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "state"; "address"; "key"; "value" ] |) in + let _ := Constant.str " + Set a value at a storage key on an account. Setting to `U256(0)` deletes + the key. + + Parameters + ---------- + state: `State` + The state + address : `Address` + Address of the account. + key : `Bytes` + Key to set. + value : `U256` + Value to set at the key. + " in + let _ := M.assert (| Compare.is_not (| + M.call (| + M.get_name (| globals, "trie_get" |), + make_list [ + M.get_field (| M.get_name (| globals, "state" |), "_main_trie" |); + M.get_name (| globals, "address" |) + ], + make_dict [] + |), + Constant.None_ + |) |) in + let _ := M.assign_local (| + "trie" , + M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, "state" |), "_storage_tries" |), "get" |), + make_list [ + M.get_name (| globals, "address" |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.is (| + M.get_name (| globals, "trie" |), + Constant.None_ + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "trie" , + M.call (| + M.get_name (| globals, "Trie" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.assign (| + M.get_subscript (| + M.get_field (| M.get_name (| globals, "state" |), "_storage_tries" |), + M.get_name (| globals, "address" |) + |), + M.get_name (| globals, "trie" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.call (| + M.get_name (| globals, "trie_set" |), + make_list [ + M.get_name (| globals, "trie" |); + M.get_name (| globals, "key" |); + M.get_name (| globals, "value" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_field (| M.get_name (| globals, "trie" |), "_data" |), + Constant.str "(* At expr: unsupported node type: Dict *)" + |), + (* then *) + ltac:(M.monadic ( + let _ := M.delete (| M.get_subscript (| + M.get_field (| M.get_name (| globals, "state" |), "_storage_tries" |), + M.get_name (| globals, "address" |) + |) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + M.pure Constant.None_)). + +Definition storage_root : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "state"; "address" ] |) in + let _ := Constant.str " + Calculate the storage root of an account. + + Parameters + ---------- + state: + The state + address : + Address of the account. + + Returns + ------- + root : `Root` + Storage root of the account. + " in + let _ := M.assert (| UnOp.not (| M.get_field (| M.get_name (| globals, "state" |), "_snapshots" |) |) |) in + let _ := + (* if *) + M.if_then_else (| + Compare.in_ (| + M.get_name (| globals, "address" |), + M.get_field (| M.get_name (| globals, "state" |), "_storage_tries" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + M.call (| + M.get_name (| globals, "root" |), + make_list [ + M.get_subscript (| + M.get_field (| M.get_name (| globals, "state" |), "_storage_tries" |), + M.get_name (| globals, "address" |) + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.return_ (| + M.get_name (| globals, "EMPTY_TRIE_ROOT" |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_)). + +Definition state_root : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "state" ] |) in + let _ := Constant.str " + Calculate the state root. + + Parameters + ---------- + state: + The current state. + + Returns + ------- + root : `Root` + The state root. + " in + let _ := M.assert (| UnOp.not (| M.get_field (| M.get_name (| globals, "state" |), "_snapshots" |) |) |) in +(* At stmt: unsupported node type: FunctionDef *) + let _ := M.return_ (| + M.call (| + M.get_name (| globals, "root" |), + make_list [ + M.get_field (| M.get_name (| globals, "state" |), "_main_trie" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Definition account_exists : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "state"; "address" ] |) in + let _ := Constant.str " + Checks if an account exists in the state trie + + Parameters + ---------- + state: + The state + address: + Address of the account that needs to be checked. + + Returns + ------- + account_exists : `bool` + True if account exists in the state trie, False otherwise + " in + let _ := M.return_ (| + Compare.is_not (| + M.call (| + M.get_name (| globals, "get_account_optional" |), + make_list [ + M.get_name (| globals, "state" |); + M.get_name (| globals, "address" |) + ], + make_dict [] + |), + Constant.None_ + |) + |) in + M.pure Constant.None_)). + +Definition account_has_code_or_nonce : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "state"; "address" ] |) in + let _ := Constant.str " + Checks if an account has non zero nonce or non empty code + + Parameters + ---------- + state: + The state + address: + Address of the account that needs to be checked. + + Returns + ------- + has_code_or_nonce : `bool` + True if if an account has non zero nonce or non empty code, + False otherwise. + " in + let _ := M.assign_local (| + "account" , + M.call (| + M.get_name (| globals, "get_account" |), + make_list [ + M.get_name (| globals, "state" |); + M.get_name (| globals, "address" |) + ], + make_dict [] + |) + |) in + let _ := M.return_ (| + BoolOp.or (| + Compare.not_eq (| + M.get_field (| M.get_name (| globals, "account" |), "nonce" |), + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + |), + ltac:(M.monadic ( + Compare.not_eq (| + M.get_field (| M.get_name (| globals, "account" |), "code" |), + Constant.bytes "" + |) + )) + |) + |) in + M.pure Constant.None_)). + +Definition is_account_empty : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "state"; "address" ] |) in + let _ := Constant.str " + Checks if an account has zero nonce, empty code and zero balance. + + Parameters + ---------- + state: + The state + address: + Address of the account that needs to be checked. + + Returns + ------- + is_empty : `bool` + True if if an account has zero nonce, empty code and zero balance, + False otherwise. + " in + let _ := M.assign_local (| + "account" , + M.call (| + M.get_name (| globals, "get_account" |), + make_list [ + M.get_name (| globals, "state" |); + M.get_name (| globals, "address" |) + ], + make_dict [] + |) + |) in + let _ := M.return_ (| + BoolOp.and (| + Compare.eq (| + M.get_field (| M.get_name (| globals, "account" |), "nonce" |), + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + |), + ltac:(M.monadic ( + BoolOp.and (| + Compare.eq (| + M.get_field (| M.get_name (| globals, "account" |), "code" |), + Constant.bytes "" + |), + ltac:(M.monadic ( + Compare.eq (| + M.get_field (| M.get_name (| globals, "account" |), "balance" |), + Constant.int 0 + |) + )) + |) + )) + |) + |) in + M.pure Constant.None_)). + +Definition account_exists_and_is_empty : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "state"; "address" ] |) in + let _ := Constant.str " + Checks if an account exists and has zero nonce, empty code and zero + balance. + + Parameters + ---------- + state: + The state + address: + Address of the account that needs to be checked. + + Returns + ------- + exists_and_is_empty : `bool` + True if an account exists and has zero nonce, empty code and zero + balance, False otherwise. + " in + let _ := M.assign_local (| + "account" , + M.call (| + M.get_name (| globals, "get_account_optional" |), + make_list [ + M.get_name (| globals, "state" |); + M.get_name (| globals, "address" |) + ], + make_dict [] + |) + |) in + let _ := M.return_ (| + BoolOp.and (| + Compare.is_not (| + M.get_name (| globals, "account" |), + Constant.None_ + |), + ltac:(M.monadic ( + BoolOp.and (| + Compare.eq (| + M.get_field (| M.get_name (| globals, "account" |), "nonce" |), + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + |), + ltac:(M.monadic ( + BoolOp.and (| + Compare.eq (| + M.get_field (| M.get_name (| globals, "account" |), "code" |), + Constant.bytes "" + |), + ltac:(M.monadic ( + Compare.eq (| + M.get_field (| M.get_name (| globals, "account" |), "balance" |), + Constant.int 0 + |) + )) + |) + )) + |) + )) + |) + |) in + M.pure Constant.None_)). + +Definition is_account_alive : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "state"; "address" ] |) in + let _ := Constant.str " + Check whether is an account is both in the state and non empty. + + Parameters + ---------- + state: + The state + address: + Address of the account that needs to be checked. + + Returns + ------- + is_alive : `bool` + True if the account is alive. + " in + let _ := M.assign_local (| + "account" , + M.call (| + M.get_name (| globals, "get_account_optional" |), + make_list [ + M.get_name (| globals, "state" |); + M.get_name (| globals, "address" |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.is (| + M.get_name (| globals, "account" |), + Constant.None_ + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + Constant.bool false + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.return_ (| + UnOp.not (| BoolOp.and (| + Compare.eq (| + M.get_field (| M.get_name (| globals, "account" |), "nonce" |), + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + |), + ltac:(M.monadic ( + BoolOp.and (| + Compare.eq (| + M.get_field (| M.get_name (| globals, "account" |), "code" |), + Constant.bytes "" + |), + ltac:(M.monadic ( + Compare.eq (| + M.get_field (| M.get_name (| globals, "account" |), "balance" |), + Constant.int 0 + |) + )) + |) + )) + |) |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_)). + +Definition modify_state : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "state"; "address"; "f" ] |) in + let _ := Constant.str " + Modify an `Account` in the `State`. + " in + let _ := M.call (| + M.get_name (| globals, "set_account" |), + make_list [ + M.get_name (| globals, "state" |); + M.get_name (| globals, "address" |); + M.call (| + M.get_name (| globals, "modify" |), + make_list [ + M.call (| + M.get_name (| globals, "get_account" |), + make_list [ + M.get_name (| globals, "state" |); + M.get_name (| globals, "address" |) + ], + make_dict [] + |); + M.get_name (| globals, "f" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + M.pure Constant.None_)). + +Definition move_ether : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "state"; "sender_address"; "recipient_address"; "amount" ] |) in + let _ := Constant.str " + Move funds between accounts. + " in +(* At stmt: unsupported node type: FunctionDef *) +(* At stmt: unsupported node type: FunctionDef *) + let _ := M.call (| + M.get_name (| globals, "modify_state" |), + make_list [ + M.get_name (| globals, "state" |); + M.get_name (| globals, "sender_address" |); + M.get_name (| globals, "reduce_sender_balance" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "modify_state" |), + make_list [ + M.get_name (| globals, "state" |); + M.get_name (| globals, "recipient_address" |); + M.get_name (| globals, "increase_recipient_balance" |) + ], + make_dict [] + |) in + M.pure Constant.None_)). + +Definition process_withdrawal : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "state"; "wd" ] |) in + let _ := Constant.str " + Increase the balance of the withdrawing account. + " in +(* At stmt: unsupported node type: FunctionDef *) + let _ := M.call (| + M.get_name (| globals, "modify_state" |), + make_list [ + M.get_name (| globals, "state" |); + M.get_field (| M.get_name (| globals, "wd" |), "address" |); + M.get_name (| globals, "increase_recipient_balance" |) + ], + make_dict [] + |) in + M.pure Constant.None_)). + +Definition set_account_balance : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "state"; "address"; "amount" ] |) in + let _ := Constant.str " + Sets the balance of an account. + + Parameters + ---------- + state: + The current state. + + address: + Address of the account whose nonce needs to be incremented. + + amount: + The amount that needs to set in balance. + " in +(* At stmt: unsupported node type: FunctionDef *) + let _ := M.call (| + M.get_name (| globals, "modify_state" |), + make_list [ + M.get_name (| globals, "state" |); + M.get_name (| globals, "address" |); + M.get_name (| globals, "set_balance" |) + ], + make_dict [] + |) in + M.pure Constant.None_)). + +Definition touch_account : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "state"; "address" ] |) in + let _ := Constant.str " + Initializes an account to state. + + Parameters + ---------- + state: + The current state. + + address: + The address of the account that need to initialised. + " in + let _ := + (* if *) + M.if_then_else (| + UnOp.not (| M.call (| + M.get_name (| globals, "account_exists" |), + make_list [ + M.get_name (| globals, "state" |); + M.get_name (| globals, "address" |) + ], + make_dict [] + |) |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, "set_account" |), + make_list [ + M.get_name (| globals, "state" |); + M.get_name (| globals, "address" |); + M.get_name (| globals, "EMPTY_ACCOUNT" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + M.pure Constant.None_)). + +Definition increment_nonce : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "state"; "address" ] |) in + let _ := Constant.str " + Increments the nonce of an account. + + Parameters + ---------- + state: + The current state. + + address: + Address of the account whose nonce needs to be incremented. + " in +(* At stmt: unsupported node type: FunctionDef *) + let _ := M.call (| + M.get_name (| globals, "modify_state" |), + make_list [ + M.get_name (| globals, "state" |); + M.get_name (| globals, "address" |); + M.get_name (| globals, "increase_nonce" |) + ], + make_dict [] + |) in + M.pure Constant.None_)). + +Definition set_code : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "state"; "address"; "code" ] |) in + let _ := Constant.str " + Sets Account code. + + Parameters + ---------- + state: + The current state. + + address: + Address of the account whose code needs to be update. + + code: + The bytecode that needs to be set. + " in +(* At stmt: unsupported node type: FunctionDef *) + let _ := M.call (| + M.get_name (| globals, "modify_state" |), + make_list [ + M.get_name (| globals, "state" |); + M.get_name (| globals, "address" |); + M.get_name (| globals, "write_code" |) + ], + make_dict [] + |) in + M.pure Constant.None_)). + +Definition get_storage_original : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "state"; "address"; "key" ] |) in + let _ := Constant.str " + Get the original value in a storage slot i.e. the value before the current + transaction began. This function reads the value from the snapshots taken + before executing the transaction. + + Parameters + ---------- + state: + The current state. + address: + Address of the account to read the value from. + key: + Key of the storage slot. + " in + let _ := + (* if *) + M.if_then_else (| + Compare.in_ (| + M.get_name (| globals, "address" |), + M.get_field (| M.get_name (| globals, "state" |), "created_accounts" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign (| + make_tuple [ M.get_name (| globals, "_" |); M.get_name (| globals, "original_trie" |) ], + M.get_subscript (| + M.get_field (| M.get_name (| globals, "state" |), "_snapshots" |), + Constant.int 0 + |) + |) in + let _ := M.assign_local (| + "original_account_trie" , + M.call (| + M.get_field (| M.get_name (| globals, "original_trie" |), "get" |), + make_list [ + M.get_name (| globals, "address" |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.is (| + M.get_name (| globals, "original_account_trie" |), + Constant.None_ + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "original_value" , + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "original_value" , + M.call (| + M.get_name (| globals, "trie_get" |), + make_list [ + M.get_name (| globals, "original_account_trie" |); + M.get_name (| globals, "key" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + )) |) in + let _ := M.assert (| M.call (| + M.get_name (| globals, "isinstance" |), + make_list [ + M.get_name (| globals, "original_value" |); + M.get_name (| globals, "U256" |) + ], + make_dict [] + |) |) in + let _ := M.return_ (| + M.get_name (| globals, "original_value" |) + |) in + M.pure Constant.None_)). + +Definition get_transient_storage : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "transient_storage"; "address"; "key" ] |) in + let _ := Constant.str " + Get a value at a storage key on an account from transient storage. + Returns `U256(0)` if the storage key has not been set previously. + Parameters + ---------- + transient_storage: `TransientStorage` + The transient storage + address : `Address` + Address of the account. + key : `Bytes` + Key to lookup. + Returns + ------- + value : `U256` + Value at the key. + " in + let _ := M.assign_local (| + "trie" , + M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, "transient_storage" |), "_tries" |), "get" |), + make_list [ + M.get_name (| globals, "address" |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.is (| + M.get_name (| globals, "trie" |), + Constant.None_ + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "value" , + M.call (| + M.get_name (| globals, "trie_get" |), + make_list [ + M.get_name (| globals, "trie" |); + M.get_name (| globals, "key" |) + ], + make_dict [] + |) + |) in + let _ := M.assert (| M.call (| + M.get_name (| globals, "isinstance" |), + make_list [ + M.get_name (| globals, "value" |); + M.get_name (| globals, "U256" |) + ], + make_dict [] + |) |) in + let _ := M.return_ (| + M.get_name (| globals, "value" |) + |) in + M.pure Constant.None_)). + +Definition set_transient_storage : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "transient_storage"; "address"; "key"; "value" ] |) in + let _ := Constant.str " + Set a value at a storage key on an account. Setting to `U256(0)` deletes + the key. + Parameters + ---------- + transient_storage: `TransientStorage` + The transient storage + address : `Address` + Address of the account. + key : `Bytes` + Key to set. + value : `U256` + Value to set at the key. + " in + let _ := M.assign_local (| + "trie" , + M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, "transient_storage" |), "_tries" |), "get" |), + make_list [ + M.get_name (| globals, "address" |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.is (| + M.get_name (| globals, "trie" |), + Constant.None_ + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "trie" , + M.call (| + M.get_name (| globals, "Trie" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.assign (| + M.get_subscript (| + M.get_field (| M.get_name (| globals, "transient_storage" |), "_tries" |), + M.get_name (| globals, "address" |) + |), + M.get_name (| globals, "trie" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.call (| + M.get_name (| globals, "trie_set" |), + make_list [ + M.get_name (| globals, "trie" |); + M.get_name (| globals, "key" |); + M.get_name (| globals, "value" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_field (| M.get_name (| globals, "trie" |), "_data" |), + Constant.str "(* At expr: unsupported node type: Dict *)" + |), + (* then *) + ltac:(M.monadic ( + let _ := M.delete (| M.get_subscript (| + M.get_field (| M.get_name (| globals, "transient_storage" |), "_tries" |), + M.get_name (| globals, "address" |) + |) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + M.pure Constant.None_)). + +Definition destroy_touched_empty_accounts : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "state"; "touched_accounts" ] |) in + let _ := Constant.str " + Destroy all touched accounts that are empty. + Parameters + ---------- + state: `State` + The current state. + touched_accounts: `Iterable[Address]` + All the accounts that have been touched in the current transaction. + " in + let _ := + M.for_ (| + M.get_name (| globals, "address" |), + M.get_name (| globals, "touched_accounts" |), + ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, "account_exists_and_is_empty" |), + make_list [ + M.get_name (| globals, "state" |); + M.get_name (| globals, "address" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, "destroy_account" |), + make_list [ + M.get_name (| globals, "state" |); + M.get_name (| globals, "address" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + M.pure Constant.None_)). diff --git a/CoqOfPython/ethereum/cancun/transactions.v b/CoqOfPython/ethereum/cancun/transactions.v new file mode 100644 index 0000000..e5e186a --- /dev/null +++ b/CoqOfPython/ethereum/cancun/transactions.v @@ -0,0 +1,367 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.cancun.transactions". + +Definition expr_1 : Value.t := + Constant.str " +Transactions are atomic units of work created externally to Ethereum and +submitted to be executed. If Ethereum is viewed as a state machine, +transactions are the events that move between states. +". + +Axiom dataclasses_imports_dataclass : + IsImported globals "dataclasses" "dataclass". + +Axiom typing_imports_Tuple : + IsImported globals "typing" "Tuple". +Axiom typing_imports_Union : + IsImported globals "typing" "Union". + +Axiom ethereum_imports_rlp : + IsImported globals "ethereum" "rlp". + +Axiom ethereum_base_types_imports_U64 : + IsImported globals "ethereum.base_types" "U64". +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_Bytes : + IsImported globals "ethereum.base_types" "Bytes". +Axiom ethereum_base_types_imports_Bytes0 : + IsImported globals "ethereum.base_types" "Bytes0". +Axiom ethereum_base_types_imports_Bytes32 : + IsImported globals "ethereum.base_types" "Bytes32". +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". +Axiom ethereum_base_types_imports_slotted_freezable : + IsImported globals "ethereum.base_types" "slotted_freezable". + +Axiom ethereum_exceptions_imports_InvalidBlock : + IsImported globals "ethereum.exceptions" "InvalidBlock". + +Axiom ethereum_cancun_fork_types_imports_Address : + IsImported globals "ethereum.cancun.fork_types" "Address". +Axiom ethereum_cancun_fork_types_imports_VersionedHash : + IsImported globals "ethereum.cancun.fork_types" "VersionedHash". + +Definition TX_BASE_COST : Value.t := M.run ltac:(M.monadic ( + Constant.int 21000 +)). + +Definition TX_DATA_COST_PER_NON_ZERO : Value.t := M.run ltac:(M.monadic ( + Constant.int 16 +)). + +Definition TX_DATA_COST_PER_ZERO : Value.t := M.run ltac:(M.monadic ( + Constant.int 4 +)). + +Definition TX_CREATE_COST : Value.t := M.run ltac:(M.monadic ( + Constant.int 32000 +)). + +Definition TX_ACCESS_LIST_ADDRESS_COST : Value.t := M.run ltac:(M.monadic ( + Constant.int 2400 +)). + +Definition TX_ACCESS_LIST_STORAGE_KEY_COST : Value.t := M.run ltac:(M.monadic ( + Constant.int 1900 +)). + +Definition LegacyTransaction : Value.t := + builtins.make_klass + [] + [ + + ] + [ + + ]. + +Definition AccessListTransaction : Value.t := + builtins.make_klass + [] + [ + + ] + [ + + ]. + +Definition FeeMarketTransaction : Value.t := + builtins.make_klass + [] + [ + + ] + [ + + ]. + +Definition BlobTransaction : Value.t := + builtins.make_klass + [] + [ + + ] + [ + + ]. + +Definition Transaction : Value.t := M.run ltac:(M.monadic ( + M.get_subscript (| + M.get_name (| globals, "Union" |), + make_tuple [ M.get_name (| globals, "LegacyTransaction" |); M.get_name (| globals, "AccessListTransaction" |); M.get_name (| globals, "FeeMarketTransaction" |); M.get_name (| globals, "BlobTransaction" |) ] + |) +)). + +Definition encode_transaction : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "tx" ] |) in + let _ := Constant.str " + Encode a transaction. Needed because non-legacy transactions aren't RLP. + " in + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, "isinstance" |), + make_list [ + M.get_name (| globals, "tx" |); + M.get_name (| globals, "LegacyTransaction" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + M.get_name (| globals, "tx" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, "isinstance" |), + make_list [ + M.get_name (| globals, "tx" |); + M.get_name (| globals, "AccessListTransaction" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + BinOp.add (| + Constant.bytes "01", + M.call (| + M.get_field (| M.get_name (| globals, "rlp" |), "encode" |), + make_list [ + M.get_name (| globals, "tx" |) + ], + make_dict [] + |) + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, "isinstance" |), + make_list [ + M.get_name (| globals, "tx" |); + M.get_name (| globals, "FeeMarketTransaction" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + BinOp.add (| + Constant.bytes "02", + M.call (| + M.get_field (| M.get_name (| globals, "rlp" |), "encode" |), + make_list [ + M.get_name (| globals, "tx" |) + ], + make_dict [] + |) + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, "isinstance" |), + make_list [ + M.get_name (| globals, "tx" |); + M.get_name (| globals, "BlobTransaction" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + BinOp.add (| + Constant.bytes "03", + M.call (| + M.get_field (| M.get_name (| globals, "rlp" |), "encode" |), + make_list [ + M.get_name (| globals, "tx" |) + ], + make_dict [] + |) + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.raise (| Some (M.call (| + M.get_name (| globals, "Exception" |), + make_list [ + Constant.str "(* At expr: unsupported node type: JoinedStr *)" + ], + make_dict [] + |)) |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_)). + +Definition decode_transaction : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "tx" ] |) in + let _ := Constant.str " + Decode a transaction. Needed because non-legacy transactions aren't RLP. + " in + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, "isinstance" |), + make_list [ + M.get_name (| globals, "tx" |); + M.get_name (| globals, "Bytes" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_subscript (| + M.get_name (| globals, "tx" |), + Constant.int 0 + |), + Constant.int 1 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + M.call (| + M.get_field (| M.get_name (| globals, "rlp" |), "decode_to" |), + make_list [ + M.get_name (| globals, "AccessListTransaction" |); + M.slice (| + M.get_name (| globals, "tx" |), + Constant.int 1, + Constant.None_, + Constant.None_ + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_subscript (| + M.get_name (| globals, "tx" |), + Constant.int 0 + |), + Constant.int 2 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + M.call (| + M.get_field (| M.get_name (| globals, "rlp" |), "decode_to" |), + make_list [ + M.get_name (| globals, "FeeMarketTransaction" |); + M.slice (| + M.get_name (| globals, "tx" |), + Constant.int 1, + Constant.None_, + Constant.None_ + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_subscript (| + M.get_name (| globals, "tx" |), + Constant.int 0 + |), + Constant.int 3 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + M.call (| + M.get_field (| M.get_name (| globals, "rlp" |), "decode_to" |), + make_list [ + M.get_name (| globals, "BlobTransaction" |); + M.slice (| + M.get_name (| globals, "tx" |), + Constant.int 1, + Constant.None_, + Constant.None_ + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, "InvalidBlock" |)) |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.return_ (| + M.get_name (| globals, "tx" |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_)). diff --git a/CoqOfPython/ethereum/cancun/trie.v b/CoqOfPython/ethereum/cancun/trie.v new file mode 100644 index 0000000..ef7de86 --- /dev/null +++ b/CoqOfPython/ethereum/cancun/trie.v @@ -0,0 +1,1604 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.cancun.trie". + +Definition expr_1 : Value.t := + Constant.str " +State Trie +^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +The state trie is the structure responsible for storing +`.fork_types.Account` objects. +". + +(* At top_level_stmt: unsupported node type: Import *) + +Axiom dataclasses_imports_dataclass : + IsImported globals "dataclasses" "dataclass". +Axiom dataclasses_imports_field : + IsImported globals "dataclasses" "field". + +Axiom typing_imports_Callable : + IsImported globals "typing" "Callable". +Axiom typing_imports_Dict : + IsImported globals "typing" "Dict". +Axiom typing_imports_Generic : + IsImported globals "typing" "Generic". +Axiom typing_imports_List : + IsImported globals "typing" "List". +Axiom typing_imports_Mapping : + IsImported globals "typing" "Mapping". +Axiom typing_imports_MutableMapping : + IsImported globals "typing" "MutableMapping". +Axiom typing_imports_Optional : + IsImported globals "typing" "Optional". +Axiom typing_imports_Sequence : + IsImported globals "typing" "Sequence". +Axiom typing_imports_TypeVar : + IsImported globals "typing" "TypeVar". +Axiom typing_imports_Union : + IsImported globals "typing" "Union". +Axiom typing_imports_cast : + IsImported globals "typing" "cast". + +Axiom ethereum_crypto_hash_imports_keccak256 : + IsImported globals "ethereum.crypto.hash" "keccak256". + +Axiom ethereum_shanghai_imports_trie : + IsImported globals "ethereum.shanghai" "trie". + +Axiom ethereum_utils_ensure_imports_ensure : + IsImported globals "ethereum.utils.ensure" "ensure". + +Axiom ethereum_utils_hexadecimal_imports_hex_to_bytes : + IsImported globals "ethereum.utils.hexadecimal" "hex_to_bytes". + +Axiom ethereum_imports_rlp : + IsImported globals "ethereum" "rlp". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_Bytes : + IsImported globals "ethereum.base_types" "Bytes". +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". +Axiom ethereum_base_types_imports_slotted_freezable : + IsImported globals "ethereum.base_types" "slotted_freezable". + +Axiom ethereum_cancun_blocks_imports_Receipt : + IsImported globals "ethereum.cancun.blocks" "Receipt". +Axiom ethereum_cancun_blocks_imports_Withdrawal : + IsImported globals "ethereum.cancun.blocks" "Withdrawal". + +Axiom ethereum_cancun_fork_types_imports_Account : + IsImported globals "ethereum.cancun.fork_types" "Account". +Axiom ethereum_cancun_fork_types_imports_Address : + IsImported globals "ethereum.cancun.fork_types" "Address". +Axiom ethereum_cancun_fork_types_imports_Root : + IsImported globals "ethereum.cancun.fork_types" "Root". +Axiom ethereum_cancun_fork_types_imports_encode_account : + IsImported globals "ethereum.cancun.fork_types" "encode_account". + +Axiom ethereum_cancun_transactions_imports_LegacyTransaction : + IsImported globals "ethereum.cancun.transactions" "LegacyTransaction". + +Definition EMPTY_TRIE_ROOT : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Root" |), + make_list [ + M.call (| + M.get_name (| globals, "hex_to_bytes" |), + make_list [ + Constant.str "56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421" + ], + make_dict [] + |) + ], + make_dict [] + |) +)). + +Definition Node : Value.t := M.run ltac:(M.monadic ( + M.get_subscript (| + M.get_name (| globals, "Union" |), + make_tuple [ M.get_name (| globals, "Account" |); M.get_name (| globals, "Bytes" |); M.get_name (| globals, "LegacyTransaction" |); M.get_name (| globals, "Receipt" |); M.get_name (| globals, "Uint" |); M.get_name (| globals, "U256" |); M.get_name (| globals, "Withdrawal" |); Constant.None_ ] + |) +)). + +Definition K : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "TypeVar" |), + make_list [ + Constant.str "K" + ], + make_dict [] + |) +)). + +Definition V : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "TypeVar" |), + make_list [ + Constant.str "V"; + M.get_subscript (| + M.get_name (| globals, "Optional" |), + M.get_name (| globals, "Account" |) + |); + M.get_subscript (| + M.get_name (| globals, "Optional" |), + M.get_name (| globals, "Bytes" |) + |); + M.get_name (| globals, "Bytes" |); + M.get_subscript (| + M.get_name (| globals, "Optional" |), + M.get_subscript (| + M.get_name (| globals, "Union" |), + make_tuple [ M.get_name (| globals, "LegacyTransaction" |); M.get_name (| globals, "Bytes" |) ] + |) + |); + M.get_subscript (| + M.get_name (| globals, "Optional" |), + M.get_subscript (| + M.get_name (| globals, "Union" |), + make_tuple [ M.get_name (| globals, "Receipt" |); M.get_name (| globals, "Bytes" |) ] + |) + |); + M.get_subscript (| + M.get_name (| globals, "Optional" |), + M.get_subscript (| + M.get_name (| globals, "Union" |), + make_tuple [ M.get_name (| globals, "Withdrawal" |); M.get_name (| globals, "Bytes" |) ] + |) + |); + M.get_name (| globals, "Uint" |); + M.get_name (| globals, "U256" |) + ], + make_dict [] + |) +)). + +Definition LeafNode : Value.t := + builtins.make_klass + [] + [ + + ] + [ + + ]. + +Definition ExtensionNode : Value.t := + builtins.make_klass + [] + [ + + ] + [ + + ]. + +Definition BranchNode : Value.t := + builtins.make_klass + [] + [ + + ] + [ + + ]. + +Definition InternalNode : Value.t := M.run ltac:(M.monadic ( + M.get_subscript (| + M.get_name (| globals, "Union" |), + make_tuple [ M.get_name (| globals, "LeafNode" |); M.get_name (| globals, "ExtensionNode" |); M.get_name (| globals, "BranchNode" |) ] + |) +)). + +Definition encode_internal_node : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "node" ] |) in + let _ := Constant.str " + Encodes a Merkle Trie node into its RLP form. The RLP will then be + serialized into a `Bytes` and hashed unless it is less that 32 bytes + when serialized. + + This function also accepts `None`, representing the absence of a node, + which is encoded to `b""""`. + + Parameters + ---------- + node : Optional[InternalNode] + The node to encode. + + Returns + ------- + encoded : `rlp.RLP` + The node encoded as RLP. + " in +(* At stmt: unsupported node type: AnnAssign *) + let _ := + (* if *) + M.if_then_else (| + Compare.is (| + M.get_name (| globals, "node" |), + Constant.None_ + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "unencoded" , + Constant.bytes "" + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, "isinstance" |), + make_list [ + M.get_name (| globals, "node" |); + M.get_name (| globals, "LeafNode" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "unencoded" , + make_tuple [ M.call (| + M.get_name (| globals, "nibble_list_to_compact" |), + make_list [ + M.get_field (| M.get_name (| globals, "node" |), "rest_of_key" |); + Constant.bool true + ], + make_dict [] + |); M.get_field (| M.get_name (| globals, "node" |), "value" |) ] + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, "isinstance" |), + make_list [ + M.get_name (| globals, "node" |); + M.get_name (| globals, "ExtensionNode" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "unencoded" , + make_tuple [ M.call (| + M.get_name (| globals, "nibble_list_to_compact" |), + make_list [ + M.get_field (| M.get_name (| globals, "node" |), "key_segment" |); + Constant.bool false + ], + make_dict [] + |); M.get_field (| M.get_name (| globals, "node" |), "subnode" |) ] + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, "isinstance" |), + make_list [ + M.get_name (| globals, "node" |); + M.get_name (| globals, "BranchNode" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "unencoded" , + BinOp.add (| + M.get_field (| M.get_name (| globals, "node" |), "subnodes" |), + make_list [ + M.get_field (| M.get_name (| globals, "node" |), "value" |) + ] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.raise (| Some (M.call (| + M.get_name (| globals, "AssertionError" |), + make_list [ + Constant.str "(* At expr: unsupported node type: JoinedStr *)" + ], + make_dict [] + |)) |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "encoded" , + M.call (| + M.get_field (| M.get_name (| globals, "rlp" |), "encode" |), + make_list [ + M.get_name (| globals, "unencoded" |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.lt (| + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_name (| globals, "encoded" |) + ], + make_dict [] + |), + Constant.int 32 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + M.get_name (| globals, "unencoded" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.return_ (| + M.call (| + M.get_name (| globals, "keccak256" |), + make_list [ + M.get_name (| globals, "encoded" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_)). + +Definition encode_node : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "node"; "storage_root" ] |) in + let _ := Constant.str " + Encode a Node for storage in the Merkle Trie. + + Currently mostly an unimplemented stub. + " in + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, "isinstance" |), + make_list [ + M.get_name (| globals, "node" |); + M.get_name (| globals, "Account" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assert (| Compare.is_not (| + M.get_name (| globals, "storage_root" |), + Constant.None_ + |) |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, "encode_account" |), + make_list [ + M.get_name (| globals, "node" |); + M.get_name (| globals, "storage_root" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, "isinstance" |), + make_list [ + M.get_name (| globals, "node" |); + make_tuple [ M.get_name (| globals, "LegacyTransaction" |); M.get_name (| globals, "Receipt" |); M.get_name (| globals, "Withdrawal" |); M.get_name (| globals, "U256" |) ] + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + M.call (| + M.get_field (| M.get_name (| globals, "rlp" |), "encode" |), + make_list [ + M.call (| + M.get_name (| globals, "cast" |), + make_list [ + M.get_field (| M.get_name (| globals, "rlp" |), "RLP" |); + M.get_name (| globals, "node" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, "isinstance" |), + make_list [ + M.get_name (| globals, "node" |); + M.get_name (| globals, "Bytes" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + M.get_name (| globals, "node" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.return_ (| + M.call (| + M.get_field (| M.get_name (| globals, "previous_trie" |), "encode_node" |), + make_list [ + M.get_name (| globals, "node" |); + M.get_name (| globals, "storage_root" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_)). + +Definition Trie : Value.t := + builtins.make_klass + [(* At base: unsupported node type: Subscript *)] + [ + + ] + [ + + ]. + +Definition copy_trie : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "trie" ] |) in + let _ := Constant.str " + Create a copy of `trie`. Since only frozen objects may be stored in tries, + the contents are reused. + + Parameters + ---------- + trie: `Trie` + Trie to copy. + + Returns + ------- + new_trie : `Trie[K, V]` + A copy of the trie. + " in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, "Trie" |), + make_list [ + M.get_field (| M.get_name (| globals, "trie" |), "secured" |); + M.get_field (| M.get_name (| globals, "trie" |), "default" |); + M.call (| + M.get_field (| M.get_name (| globals, "copy" |), "copy" |), + make_list [ + M.get_field (| M.get_name (| globals, "trie" |), "_data" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Definition trie_set : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "trie"; "key"; "value" ] |) in + let _ := Constant.str " + Stores an item in a Merkle Trie. + + This method deletes the key if `value == trie.default`, because the Merkle + Trie represents the default value by omitting it from the trie. + + Parameters + ---------- + trie: `Trie` + Trie to store in. + key : `Bytes` + Key to lookup. + value : `V` + Node to insert at `key`. + " in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, "value" |), + M.get_field (| M.get_name (| globals, "trie" |), "default" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + Compare.in_ (| + M.get_name (| globals, "key" |), + M.get_field (| M.get_name (| globals, "trie" |), "_data" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.delete (| M.get_subscript (| + M.get_field (| M.get_name (| globals, "trie" |), "_data" |), + M.get_name (| globals, "key" |) + |) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign (| + M.get_subscript (| + M.get_field (| M.get_name (| globals, "trie" |), "_data" |), + M.get_name (| globals, "key" |) + |), + M.get_name (| globals, "value" |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_)). + +Definition trie_get : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "trie"; "key" ] |) in + let _ := Constant.str " + Gets an item from the Merkle Trie. + + This method returns `trie.default` if the key is missing. + + Parameters + ---------- + trie: + Trie to lookup in. + key : + Key to lookup. + + Returns + ------- + node : `V` + Node at `key` in the trie. + " in + let _ := M.return_ (| + M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, "trie" |), "_data" |), "get" |), + make_list [ + M.get_name (| globals, "key" |); + M.get_field (| M.get_name (| globals, "trie" |), "default" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Definition common_prefix_length : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "a"; "b" ] |) in + let _ := Constant.str " + Find the longest common prefix of two sequences. + " in + let _ := + M.for_ (| + M.get_name (| globals, "i" |), + M.call (| + M.get_name (| globals, "range" |), + make_list [ + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_name (| globals, "a" |) + ], + make_dict [] + |) + ], + make_dict [] + |), + ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + BoolOp.or (| + Compare.gt_e (| + M.get_name (| globals, "i" |), + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_name (| globals, "b" |) + ], + make_dict [] + |) + |), + ltac:(M.monadic ( + Compare.not_eq (| + M.get_subscript (| + M.get_name (| globals, "a" |), + M.get_name (| globals, "i" |) + |), + M.get_subscript (| + M.get_name (| globals, "b" |), + M.get_name (| globals, "i" |) + |) + |) + )) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + M.get_name (| globals, "i" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_name (| globals, "a" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Definition nibble_list_to_compact : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "x"; "is_leaf" ] |) in + let _ := Constant.str " + Compresses nibble-list into a standard byte array with a flag. + + A nibble-list is a list of byte values no greater than `15`. The flag is + encoded in high nibble of the highest byte. The flag nibble can be broken + down into two two-bit flags. + + Highest nibble:: + + +---+---+----------+--------+ + | _ | _ | is_leaf | parity | + +---+---+----------+--------+ + 3 2 1 0 + + + The lowest bit of the nibble encodes the parity of the length of the + remaining nibbles -- `0` when even and `1` when odd. The second lowest bit + is used to distinguish leaf and extension nodes. The other two bits are not + used. + + Parameters + ---------- + x : + Array of nibbles. + is_leaf : + True if this is part of a leaf node, or false if it is an extension + node. + + Returns + ------- + compressed : `bytearray` + Compact byte array. + " in + let _ := M.assign_local (| + "compact" , + M.call (| + M.get_name (| globals, "bytearray" |), + make_list [], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + BinOp.mod_ (| + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_name (| globals, "x" |) + ], + make_dict [] + |), + Constant.int 2 + |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_field (| M.get_name (| globals, "compact" |), "append" |), + make_list [ + BinOp.mult (| + Constant.int 16, + BinOp.mult (| + Constant.int 2, + M.get_name (| globals, "is_leaf" |) + |) + |) + ], + make_dict [] + |) in + let _ := + M.for_ (| + M.get_name (| globals, "i" |), + M.call (| + M.get_name (| globals, "range" |), + make_list [ + Constant.int 0; + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_name (| globals, "x" |) + ], + make_dict [] + |); + Constant.int 2 + ], + make_dict [] + |), + ltac:(M.monadic ( + let _ := M.call (| + M.get_field (| M.get_name (| globals, "compact" |), "append" |), + make_list [ + BinOp.add (| + BinOp.mult (| + Constant.int 16, + M.get_subscript (| + M.get_name (| globals, "x" |), + M.get_name (| globals, "i" |) + |) + |), + M.get_subscript (| + M.get_name (| globals, "x" |), + BinOp.add (| + M.get_name (| globals, "i" |), + Constant.int 1 + |) + |) + |) + ], + make_dict [] + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.call (| + M.get_field (| M.get_name (| globals, "compact" |), "append" |), + make_list [ + BinOp.add (| + BinOp.mult (| + Constant.int 16, + BinOp.add (| + BinOp.mult (| + Constant.int 2, + M.get_name (| globals, "is_leaf" |) + |), + Constant.int 1 + |) + |), + M.get_subscript (| + M.get_name (| globals, "x" |), + Constant.int 0 + |) + |) + ], + make_dict [] + |) in + let _ := + M.for_ (| + M.get_name (| globals, "i" |), + M.call (| + M.get_name (| globals, "range" |), + make_list [ + Constant.int 1; + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_name (| globals, "x" |) + ], + make_dict [] + |); + Constant.int 2 + ], + make_dict [] + |), + ltac:(M.monadic ( + let _ := M.call (| + M.get_field (| M.get_name (| globals, "compact" |), "append" |), + make_list [ + BinOp.add (| + BinOp.mult (| + Constant.int 16, + M.get_subscript (| + M.get_name (| globals, "x" |), + M.get_name (| globals, "i" |) + |) + |), + M.get_subscript (| + M.get_name (| globals, "x" |), + BinOp.add (| + M.get_name (| globals, "i" |), + Constant.int 1 + |) + |) + |) + ], + make_dict [] + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + M.pure Constant.None_ + )) |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, "Bytes" |), + make_list [ + M.get_name (| globals, "compact" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Definition bytes_to_nibble_list : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "bytes_" ] |) in + let _ := Constant.str " + Converts a `Bytes` into to a sequence of nibbles (bytes with value < 16). + + Parameters + ---------- + bytes_: + The `Bytes` to convert. + + Returns + ------- + nibble_list : `Bytes` + The `Bytes` in nibble-list format. + " in + let _ := M.assign_local (| + "nibble_list" , + M.call (| + M.get_name (| globals, "bytearray" |), + make_list [ + BinOp.mult (| + Constant.int 2, + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_name (| globals, "bytes_" |) + ], + make_dict [] + |) + |) + ], + make_dict [] + |) + |) in + let _ := + M.for_ (| + make_tuple [ M.get_name (| globals, "byte_index" |); M.get_name (| globals, "byte" |) ], + M.call (| + M.get_name (| globals, "enumerate" |), + make_list [ + M.get_name (| globals, "bytes_" |) + ], + make_dict [] + |), + ltac:(M.monadic ( + let _ := M.assign (| + M.get_subscript (| + M.get_name (| globals, "nibble_list" |), + BinOp.mult (| + M.get_name (| globals, "byte_index" |), + Constant.int 2 + |) + |), + BinOp.r_shift (| + BinOp.bit_and (| + M.get_name (| globals, "byte" |), + Constant.int 240 + |), + Constant.int 4 + |) + |) in + let _ := M.assign (| + M.get_subscript (| + M.get_name (| globals, "nibble_list" |), + BinOp.add (| + BinOp.mult (| + M.get_name (| globals, "byte_index" |), + Constant.int 2 + |), + Constant.int 1 + |) + |), + BinOp.bit_and (| + M.get_name (| globals, "byte" |), + Constant.int 15 + |) + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, "Bytes" |), + make_list [ + M.get_name (| globals, "nibble_list" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Definition _prepare_trie : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "trie"; "get_storage_root" ] |) in + let _ := Constant.str " + Prepares the trie for root calculation. Removes values that are empty, + hashes the keys (if `secured == True`) and encodes all the nodes. + + Parameters + ---------- + trie : + The `Trie` to prepare. + get_storage_root : + Function to get the storage root of an account. Needed to encode + `Account` objects. + + Returns + ------- + out : `Mapping[ethereum.base_types.Bytes, Node]` + Object with keys mapped to nibble-byte form. + " in +(* At stmt: unsupported node type: AnnAssign *) + let _ := + M.for_ (| + make_tuple [ M.get_name (| globals, "preimage" |); M.get_name (| globals, "value" |) ], + M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, "trie" |), "_data" |), "items" |), + make_list [], + make_dict [] + |), + ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, "isinstance" |), + make_list [ + M.get_name (| globals, "value" |); + M.get_name (| globals, "Account" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assert (| Compare.is_not (| + M.get_name (| globals, "get_storage_root" |), + Constant.None_ + |) |) in + let _ := M.assign_local (| + "address" , + M.call (| + M.get_name (| globals, "Address" |), + make_list [ + M.get_name (| globals, "preimage" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "encoded_value" , + M.call (| + M.get_name (| globals, "encode_node" |), + make_list [ + M.get_name (| globals, "value" |); + M.call (| + M.get_name (| globals, "get_storage_root" |), + make_list [ + M.get_name (| globals, "address" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "encoded_value" , + M.call (| + M.get_name (| globals, "encode_node" |), + make_list [ + M.get_name (| globals, "value" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + )) |) in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + Compare.not_eq (| + M.get_name (| globals, "encoded_value" |), + Constant.bytes "" + |); + M.get_name (| globals, "AssertionError" |) + ], + make_dict [] + |) in +(* At stmt: unsupported node type: AnnAssign *) + let _ := + (* if *) + M.if_then_else (| + M.get_field (| M.get_name (| globals, "trie" |), "secured" |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "key" , + M.call (| + M.get_name (| globals, "keccak256" |), + make_list [ + M.get_name (| globals, "preimage" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "key" , + M.get_name (| globals, "preimage" |) + |) in + M.pure Constant.None_ + )) |) in + let _ := M.assign (| + M.get_subscript (| + M.get_name (| globals, "mapped" |), + M.call (| + M.get_name (| globals, "bytes_to_nibble_list" |), + make_list [ + M.get_name (| globals, "key" |) + ], + make_dict [] + |) + |), + M.get_name (| globals, "encoded_value" |) + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := M.return_ (| + M.get_name (| globals, "mapped" |) + |) in + M.pure Constant.None_)). + +Definition root : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "trie"; "get_storage_root" ] |) in + let _ := Constant.str " + Computes the root of a modified merkle patricia trie (MPT). + + Parameters + ---------- + trie : + `Trie` to get the root of. + get_storage_root : + Function to get the storage root of an account. Needed to encode + `Account` objects. + + + Returns + ------- + root : `.fork_types.Root` + MPT root of the underlying key-value pairs. + " in + let _ := M.assign_local (| + "obj" , + M.call (| + M.get_name (| globals, "_prepare_trie" |), + make_list [ + M.get_name (| globals, "trie" |); + M.get_name (| globals, "get_storage_root" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "root_node" , + M.call (| + M.get_name (| globals, "encode_internal_node" |), + make_list [ + M.call (| + M.get_name (| globals, "patricialize" |), + make_list [ + M.get_name (| globals, "obj" |); + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.lt (| + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.call (| + M.get_field (| M.get_name (| globals, "rlp" |), "encode" |), + make_list [ + M.get_name (| globals, "root_node" |) + ], + make_dict [] + |) + ], + make_dict [] + |), + Constant.int 32 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + M.call (| + M.get_name (| globals, "keccak256" |), + make_list [ + M.call (| + M.get_field (| M.get_name (| globals, "rlp" |), "encode" |), + make_list [ + M.get_name (| globals, "root_node" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assert (| M.call (| + M.get_name (| globals, "isinstance" |), + make_list [ + M.get_name (| globals, "root_node" |); + M.get_name (| globals, "Bytes" |) + ], + make_dict [] + |) |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, "Root" |), + make_list [ + M.get_name (| globals, "root_node" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_)). + +Definition patricialize : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "obj"; "level" ] |) in + let _ := Constant.str " + Structural composition function. + + Used to recursively patricialize and merkleize a dictionary. Includes + memoization of the tree structure and hashes. + + Parameters + ---------- + obj : + Underlying trie key-value pairs, with keys in nibble-list format. + level : + Current trie level. + + Returns + ------- + node : `ethereum.base_types.Bytes` + Root node of `obj`. + " in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_name (| globals, "obj" |) + ], + make_dict [] + |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + Constant.None_ + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "arbitrary_key" , + M.call (| + M.get_name (| globals, "next" |), + make_list [ + M.call (| + M.get_name (| globals, "iter" |), + make_list [ + M.get_name (| globals, "obj" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_name (| globals, "obj" |) + ], + make_dict [] + |), + Constant.int 1 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "leaf" , + M.call (| + M.get_name (| globals, "LeafNode" |), + make_list [ + M.slice (| + M.get_name (| globals, "arbitrary_key" |), + M.get_name (| globals, "level" |), + Constant.None_, + Constant.None_ + |); + M.get_subscript (| + M.get_name (| globals, "obj" |), + M.get_name (| globals, "arbitrary_key" |) + |) + ], + make_dict [] + |) + |) in + let _ := M.return_ (| + M.get_name (| globals, "leaf" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "substring" , + M.slice (| + M.get_name (| globals, "arbitrary_key" |), + M.get_name (| globals, "level" |), + Constant.None_, + Constant.None_ + |) + |) in + let _ := M.assign_local (| + "prefix_length" , + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_name (| globals, "substring" |) + ], + make_dict [] + |) + |) in + let _ := + M.for_ (| + M.get_name (| globals, "key" |), + M.get_name (| globals, "obj" |), + ltac:(M.monadic ( + let _ := M.assign_local (| + "prefix_length" , + M.call (| + M.get_name (| globals, "min" |), + make_list [ + M.get_name (| globals, "prefix_length" |); + M.call (| + M.get_name (| globals, "common_prefix_length" |), + make_list [ + M.get_name (| globals, "substring" |); + M.slice (| + M.get_name (| globals, "key" |), + M.get_name (| globals, "level" |), + Constant.None_, + Constant.None_ + |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, "prefix_length" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.break (| |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.gt (| + M.get_name (| globals, "prefix_length" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "prefix" , + M.slice (| + M.get_name (| globals, "arbitrary_key" |), + M.get_name (| globals, "level" |), + BinOp.add (| + M.get_name (| globals, "level" |), + M.get_name (| globals, "prefix_length" |) + |), + Constant.None_ + |) + |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, "ExtensionNode" |), + make_list [ + M.get_name (| globals, "prefix" |); + M.call (| + M.get_name (| globals, "encode_internal_node" |), + make_list [ + M.call (| + M.get_name (| globals, "patricialize" |), + make_list [ + M.get_name (| globals, "obj" |); + BinOp.add (| + M.get_name (| globals, "level" |), + M.get_name (| globals, "prefix_length" |) + |) + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in +(* At stmt: unsupported node type: AnnAssign *) + let _ := + M.for_ (| + M.get_name (| globals, "_" |), + M.call (| + M.get_name (| globals, "range" |), + make_list [ + Constant.int 16 + ], + make_dict [] + |), + ltac:(M.monadic ( + let _ := M.call (| + M.get_field (| M.get_name (| globals, "branches" |), "append" |), + make_list [ + Constant.str "(* At expr: unsupported node type: Dict *)" + ], + make_dict [] + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := M.assign_local (| + "value" , + Constant.bytes "" + |) in + let _ := + M.for_ (| + M.get_name (| globals, "key" |), + M.get_name (| globals, "obj" |), + ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_name (| globals, "key" |) + ], + make_dict [] + |), + M.get_name (| globals, "level" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, "isinstance" |), + make_list [ + M.get_subscript (| + M.get_name (| globals, "obj" |), + M.get_name (| globals, "key" |) + |); + make_tuple [ M.get_name (| globals, "Account" |); M.get_name (| globals, "Receipt" |); M.get_name (| globals, "Uint" |) ] + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, "AssertionError" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "value" , + M.get_subscript (| + M.get_name (| globals, "obj" |), + M.get_name (| globals, "key" |) + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign (| + M.get_subscript (| + M.get_subscript (| + M.get_name (| globals, "branches" |), + M.get_subscript (| + M.get_name (| globals, "key" |), + M.get_name (| globals, "level" |) + |) + |), + M.get_name (| globals, "key" |) + |), + M.get_subscript (| + M.get_name (| globals, "obj" |), + M.get_name (| globals, "key" |) + |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, "BranchNode" |), + make_list [ + Constant.str "(* At expr: unsupported node type: ListComp *)"; + M.get_name (| globals, "value" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). diff --git a/CoqOfPython/ethereum/cancun/utils/__init__.v b/CoqOfPython/ethereum/cancun/utils/__init__.v new file mode 100644 index 0000000..3e26e47 --- /dev/null +++ b/CoqOfPython/ethereum/cancun/utils/__init__.v @@ -0,0 +1,8 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.cancun.utils.__init__". + +Definition expr_1 : Value.t := + Constant.str " +Utility functions unique to this particular fork. +". diff --git a/CoqOfPython/ethereum/cancun/utils/address.v b/CoqOfPython/ethereum/cancun/utils/address.v new file mode 100644 index 0000000..c9e2edc --- /dev/null +++ b/CoqOfPython/ethereum/cancun/utils/address.v @@ -0,0 +1,227 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.cancun.utils.address". + +Definition expr_1 : Value.t := + Constant.str " +Hardfork Utility Functions For Addresses +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Address specific functions used in this cancun version of +specification. +". + +Axiom typing_imports_Union : + IsImported globals "typing" "Union". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_Bytes32 : + IsImported globals "ethereum.base_types" "Bytes32". +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". + +Axiom ethereum_crypto_hash_imports_keccak256 : + IsImported globals "ethereum.crypto.hash" "keccak256". + +Axiom ethereum_utils_byte_imports_left_pad_zero_bytes : + IsImported globals "ethereum.utils.byte" "left_pad_zero_bytes". + +Axiom ethereum_imports_rlp : + IsImported globals "ethereum" "rlp". + +Axiom ethereum_cancun_fork_types_imports_Address : + IsImported globals "ethereum.cancun.fork_types" "Address". + +Definition to_address : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "data" ] |) in + let _ := Constant.str " + Convert a Uint or U256 value to a valid address (20 bytes). + + Parameters + ---------- + data : + The string to be converted to bytes. + + Returns + ------- + address : `Address` + The obtained address. + " in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, "Address" |), + make_list [ + M.slice (| + M.call (| + M.get_field (| M.get_name (| globals, "data" |), "to_be_bytes32" |), + make_list [], + make_dict [] + |), + UnOp.sub (| Constant.int 20 |), + Constant.None_, + Constant.None_ + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Definition compute_contract_address : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "address"; "nonce" ] |) in + let _ := Constant.str " + Computes address of the new account that needs to be created. + + Parameters + ---------- + address : + The address of the account that wants to create the new account. + nonce : + The transaction count of the account that wants to create the new + account. + + Returns + ------- + address: `Address` + The computed address of the new account. + " in + let _ := M.assign_local (| + "computed_address" , + M.call (| + M.get_name (| globals, "keccak256" |), + make_list [ + M.call (| + M.get_field (| M.get_name (| globals, "rlp" |), "encode" |), + make_list [ + make_list [ + M.get_name (| globals, "address" |); + M.get_name (| globals, "nonce" |) + ] + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "canonical_address" , + M.slice (| + M.get_name (| globals, "computed_address" |), + UnOp.sub (| Constant.int 20 |), + Constant.None_, + Constant.None_ + |) + |) in + let _ := M.assign_local (| + "padded_address" , + M.call (| + M.get_name (| globals, "left_pad_zero_bytes" |), + make_list [ + M.get_name (| globals, "canonical_address" |); + Constant.int 20 + ], + make_dict [] + |) + |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, "Address" |), + make_list [ + M.get_name (| globals, "padded_address" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Definition compute_create2_contract_address : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "address"; "salt"; "call_data" ] |) in + let _ := Constant.str " + Computes address of the new account that needs to be created, which is + based on the sender address, salt and the call data as well. + + Parameters + ---------- + address : + The address of the account that wants to create the new account. + salt : + Address generation salt. + call_data : + The code of the new account which is to be created. + + Returns + ------- + address: `ethereum.cancun.fork_types.Address` + The computed address of the new account. + " in + let _ := M.assign_local (| + "preimage" , + BinOp.add (| + BinOp.add (| + BinOp.add (| + Constant.bytes "ff", + M.get_name (| globals, "address" |) + |), + M.get_name (| globals, "salt" |) + |), + M.call (| + M.get_name (| globals, "keccak256" |), + make_list [ + M.get_name (| globals, "call_data" |) + ], + make_dict [] + |) + |) + |) in + let _ := M.assign_local (| + "computed_address" , + M.call (| + M.get_name (| globals, "keccak256" |), + make_list [ + M.get_name (| globals, "preimage" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "canonical_address" , + M.slice (| + M.get_name (| globals, "computed_address" |), + UnOp.sub (| Constant.int 20 |), + Constant.None_, + Constant.None_ + |) + |) in + let _ := M.assign_local (| + "padded_address" , + M.call (| + M.get_name (| globals, "left_pad_zero_bytes" |), + make_list [ + M.get_name (| globals, "canonical_address" |); + Constant.int 20 + ], + make_dict [] + |) + |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, "Address" |), + make_list [ + M.get_name (| globals, "padded_address" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). diff --git a/CoqOfPython/ethereum/cancun/utils/hexadecimal.v b/CoqOfPython/ethereum/cancun/utils/hexadecimal.v new file mode 100644 index 0000000..8834108 --- /dev/null +++ b/CoqOfPython/ethereum/cancun/utils/hexadecimal.v @@ -0,0 +1,153 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.cancun.utils.hexadecimal". + +Definition expr_1 : Value.t := + Constant.str " +Utility Functions For Hexadecimal Strings +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Hexadecimal utility functions used in this specification, specific to +Cancun types. +". + +Axiom ethereum_utils_hexadecimal_imports_remove_hex_prefix : + IsImported globals "ethereum.utils.hexadecimal" "remove_hex_prefix". + +Axiom ethereum_cancun_fork_types_imports_Address : + IsImported globals "ethereum.cancun.fork_types" "Address". +Axiom ethereum_cancun_fork_types_imports_Bloom : + IsImported globals "ethereum.cancun.fork_types" "Bloom". +Axiom ethereum_cancun_fork_types_imports_Root : + IsImported globals "ethereum.cancun.fork_types" "Root". + +Definition hex_to_root : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "hex_string" ] |) in + let _ := Constant.str " + Convert hex string to trie root. + + Parameters + ---------- + hex_string : + The hexadecimal string to be converted to trie root. + + Returns + ------- + root : `Root` + Trie root obtained from the given hexadecimal string. + " in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, "Root" |), + make_list [ + M.call (| + M.get_field (| M.get_name (| globals, "bytes" |), "fromhex" |), + make_list [ + M.call (| + M.get_name (| globals, "remove_hex_prefix" |), + make_list [ + M.get_name (| globals, "hex_string" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Definition hex_to_bloom : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "hex_string" ] |) in + let _ := Constant.str " + Convert hex string to bloom. + + Parameters + ---------- + hex_string : + The hexadecimal string to be converted to bloom. + + Returns + ------- + bloom : `Bloom` + Bloom obtained from the given hexadecimal string. + " in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, "Bloom" |), + make_list [ + M.call (| + M.get_field (| M.get_name (| globals, "bytes" |), "fromhex" |), + make_list [ + M.call (| + M.get_name (| globals, "remove_hex_prefix" |), + make_list [ + M.get_name (| globals, "hex_string" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Definition hex_to_address : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "hex_string" ] |) in + let _ := Constant.str " + Convert hex string to Address (20 bytes). + + Parameters + ---------- + hex_string : + The hexadecimal string to be converted to Address. + + Returns + ------- + address : `Address` + The address obtained from the given hexadecimal string. + " in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, "Address" |), + make_list [ + M.call (| + M.get_field (| M.get_name (| globals, "bytes" |), "fromhex" |), + make_list [ + M.call (| + M.get_field (| M.call (| + M.get_name (| globals, "remove_hex_prefix" |), + make_list [ + M.get_name (| globals, "hex_string" |) + ], + make_dict [] + |), "rjust" |), + make_list [ + Constant.int 40; + Constant.str "0" + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). diff --git a/CoqOfPython/ethereum/cancun/utils/message.v b/CoqOfPython/ethereum/cancun/utils/message.v new file mode 100644 index 0000000..e62d563 --- /dev/null +++ b/CoqOfPython/ethereum/cancun/utils/message.v @@ -0,0 +1,266 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.cancun.utils.message". + +Definition expr_1 : Value.t := + Constant.str " +Hardfork Utility Functions For The Message Data-structure +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Message specific functions used in this cancun version of +specification. +". + +Axiom typing_imports_FrozenSet : + IsImported globals "typing" "FrozenSet". +Axiom typing_imports_Optional : + IsImported globals "typing" "Optional". +Axiom typing_imports_Tuple : + IsImported globals "typing" "Tuple". +Axiom typing_imports_Union : + IsImported globals "typing" "Union". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_Bytes : + IsImported globals "ethereum.base_types" "Bytes". +Axiom ethereum_base_types_imports_Bytes0 : + IsImported globals "ethereum.base_types" "Bytes0". +Axiom ethereum_base_types_imports_Bytes32 : + IsImported globals "ethereum.base_types" "Bytes32". +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". + +Axiom ethereum_cancun_fork_types_imports_Address : + IsImported globals "ethereum.cancun.fork_types" "Address". + +Axiom ethereum_cancun_state_imports_get_account : + IsImported globals "ethereum.cancun.state" "get_account". + +Axiom ethereum_cancun_vm_imports_Environment : + IsImported globals "ethereum.cancun.vm" "Environment". +Axiom ethereum_cancun_vm_imports_Message : + IsImported globals "ethereum.cancun.vm" "Message". + +Axiom ethereum_cancun_vm_precompiled_contracts_mapping_imports_PRE_COMPILED_CONTRACTS : + IsImported globals "ethereum.cancun.vm.precompiled_contracts.mapping" "PRE_COMPILED_CONTRACTS". + +Axiom ethereum_cancun_utils_address_imports_compute_contract_address : + IsImported globals "ethereum.cancun.utils.address" "compute_contract_address". + +Definition prepare_message : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "caller"; "target"; "value"; "data"; "gas"; "env"; "code_address"; "should_transfer_value"; "is_static"; "preaccessed_addresses"; "preaccessed_storage_keys" ] |) in + let _ := Constant.str " + Execute a transaction against the provided environment. + + Parameters + ---------- + caller : + Address which initiated the transaction + target : + Address whose code will be executed + value : + Value to be transferred. + data : + Array of bytes provided to the code in `target`. + gas : + Gas provided for the code in `target`. + env : + Environment for the Ethereum Virtual Machine. + code_address : + This is usually same as the `target` address except when an alternative + accounts code needs to be executed. + eg. `CALLCODE` calling a precompile. + should_transfer_value : + if True ETH should be transferred while executing a message call. + is_static: + if True then it prevents all state-changing operations from being + executed. + preaccessed_addresses: + Addresses that should be marked as accessed prior to the message call + preaccessed_storage_keys: + Storage keys that should be marked as accessed prior to the message + call + + Returns + ------- + message: `ethereum.cancun.vm.Message` + Items containing contract creation or message call specific data. + " in + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, "isinstance" |), + make_list [ + M.get_name (| globals, "target" |); + M.get_name (| globals, "Bytes0" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "current_target" , + M.call (| + M.get_name (| globals, "compute_contract_address" |), + make_list [ + M.get_name (| globals, "caller" |); + BinOp.sub (| + M.get_field (| M.call (| + M.get_name (| globals, "get_account" |), + make_list [ + M.get_field (| M.get_name (| globals, "env" |), "state" |); + M.get_name (| globals, "caller" |) + ], + make_dict [] + |), "nonce" |), + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 1 + ], + make_dict [] + |) + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "msg_data" , + M.call (| + M.get_name (| globals, "Bytes" |), + make_list [ + Constant.bytes "" + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "code" , + M.get_name (| globals, "data" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, "isinstance" |), + make_list [ + M.get_name (| globals, "target" |); + M.get_name (| globals, "Address" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "current_target" , + M.get_name (| globals, "target" |) + |) in + let _ := M.assign_local (| + "msg_data" , + M.get_name (| globals, "data" |) + |) in + let _ := M.assign_local (| + "code" , + M.get_field (| M.call (| + M.get_name (| globals, "get_account" |), + make_list [ + M.get_field (| M.get_name (| globals, "env" |), "state" |); + M.get_name (| globals, "target" |) + ], + make_dict [] + |), "code" |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.is (| + M.get_name (| globals, "code_address" |), + Constant.None_ + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "code_address" , + M.get_name (| globals, "target" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.raise (| Some (M.call (| + M.get_name (| globals, "AssertionError" |), + make_list [ + Constant.str "Target must be address or empty bytes" + ], + make_dict [] + |)) |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "accessed_addresses" , + M.call (| + M.get_name (| globals, "set" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_field (| M.get_name (| globals, "accessed_addresses" |), "add" |), + make_list [ + M.get_name (| globals, "current_target" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_field (| M.get_name (| globals, "accessed_addresses" |), "add" |), + make_list [ + M.get_name (| globals, "caller" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_field (| M.get_name (| globals, "accessed_addresses" |), "update" |), + make_list [ + M.call (| + M.get_field (| M.get_name (| globals, "PRE_COMPILED_CONTRACTS" |), "keys" |), + make_list [], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_field (| M.get_name (| globals, "accessed_addresses" |), "update" |), + make_list [ + M.get_name (| globals, "preaccessed_addresses" |) + ], + make_dict [] + |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, "Message" |), + make_list [], + make_dict [] + |) + |) in + M.pure Constant.None_)). diff --git a/CoqOfPython/ethereum/cancun/vm/__init__.v b/CoqOfPython/ethereum/cancun/vm/__init__.v new file mode 100644 index 0000000..5efb61d --- /dev/null +++ b/CoqOfPython/ethereum/cancun/vm/__init__.v @@ -0,0 +1,264 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.cancun.vm.__init__". + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +The abstract computer which runs the code stored in an +`.fork_types.Account`. +". + +Axiom dataclasses_imports_dataclass : + IsImported globals "dataclasses" "dataclass". + +Axiom typing_imports_List : + IsImported globals "typing" "List". +Axiom typing_imports_Optional : + IsImported globals "typing" "Optional". +Axiom typing_imports_Set : + IsImported globals "typing" "Set". +Axiom typing_imports_Tuple : + IsImported globals "typing" "Tuple". +Axiom typing_imports_Union : + IsImported globals "typing" "Union". + +Axiom ethereum_base_types_imports_U64 : + IsImported globals "ethereum.base_types" "U64". +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_Bytes : + IsImported globals "ethereum.base_types" "Bytes". +Axiom ethereum_base_types_imports_Bytes0 : + IsImported globals "ethereum.base_types" "Bytes0". +Axiom ethereum_base_types_imports_Bytes32 : + IsImported globals "ethereum.base_types" "Bytes32". +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". + +Axiom ethereum_crypto_hash_imports_Hash32 : + IsImported globals "ethereum.crypto.hash" "Hash32". + +Axiom ethereum_cancun_blocks_imports_Log : + IsImported globals "ethereum.cancun.blocks" "Log". + +Axiom ethereum_cancun_fork_types_imports_Address : + IsImported globals "ethereum.cancun.fork_types" "Address". +Axiom ethereum_cancun_fork_types_imports_VersionedHash : + IsImported globals "ethereum.cancun.fork_types" "VersionedHash". + +Axiom ethereum_cancun_state_imports_State : + IsImported globals "ethereum.cancun.state" "State". +Axiom ethereum_cancun_state_imports_TransientStorage : + IsImported globals "ethereum.cancun.state" "TransientStorage". +Axiom ethereum_cancun_state_imports_account_exists_and_is_empty : + IsImported globals "ethereum.cancun.state" "account_exists_and_is_empty". + +Axiom ethereum_cancun_vm_precompiled_contracts_imports_RIPEMD160_ADDRESS : + IsImported globals "ethereum.cancun.vm.precompiled_contracts" "RIPEMD160_ADDRESS". + +Definition __all__ : Value.t := M.run ltac:(M.monadic ( + make_tuple [ Constant.str "Environment"; Constant.str "Evm"; Constant.str "Message" ] +)). + +Definition Environment : Value.t := + builtins.make_klass + [] + [ + + ] + [ + + ]. + +Definition Message : Value.t := + builtins.make_klass + [] + [ + + ] + [ + + ]. + +Definition Evm : Value.t := + builtins.make_klass + [] + [ + + ] + [ + + ]. + +Definition incorporate_child_on_success : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm"; "child_evm" ] |) in + let _ := Constant.str " + Incorporate the state of a successful `child_evm` into the parent `evm`. + + Parameters + ---------- + evm : + The parent `EVM`. + child_evm : + The child evm to incorporate. + " in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "gas_left" |), + M.get_field (| M.get_name (| globals, "child_evm" |), "gas_left" |) + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "logs" |), + M.get_field (| M.get_name (| globals, "child_evm" |), "logs" |) + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "refund_counter" |), + M.get_field (| M.get_name (| globals, "child_evm" |), "refund_counter" |) + |) in + let _ := M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "accounts_to_delete" |), "update" |), + make_list [ + M.get_field (| M.get_name (| globals, "child_evm" |), "accounts_to_delete" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "touched_accounts" |), "update" |), + make_list [ + M.get_field (| M.get_name (| globals, "child_evm" |), "touched_accounts" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, "account_exists_and_is_empty" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "env" |), "state" |); + M.get_field (| M.get_field (| M.get_name (| globals, "child_evm" |), "message" |), "current_target" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "touched_accounts" |), "add" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "child_evm" |), "message" |), "current_target" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "accessed_addresses" |), "update" |), + make_list [ + M.get_field (| M.get_name (| globals, "child_evm" |), "accessed_addresses" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "accessed_storage_keys" |), "update" |), + make_list [ + M.get_field (| M.get_name (| globals, "child_evm" |), "accessed_storage_keys" |) + ], + make_dict [] + |) in + M.pure Constant.None_)). + +Definition incorporate_child_on_error : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm"; "child_evm" ] |) in + let _ := Constant.str " + Incorporate the state of an unsuccessful `child_evm` into the parent `evm`. + + Parameters + ---------- + evm : + The parent `EVM`. + child_evm : + The child evm to incorporate. + " in + let _ := + (* if *) + M.if_then_else (| + Compare.in_ (| + M.get_name (| globals, "RIPEMD160_ADDRESS" |), + M.get_field (| M.get_name (| globals, "child_evm" |), "touched_accounts" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "touched_accounts" |), "add" |), + make_list [ + M.get_name (| globals, "RIPEMD160_ADDRESS" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_field (| M.get_field (| M.get_name (| globals, "child_evm" |), "message" |), "current_target" |), + M.get_name (| globals, "RIPEMD160_ADDRESS" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, "account_exists_and_is_empty" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "env" |), "state" |); + M.get_field (| M.get_field (| M.get_name (| globals, "child_evm" |), "message" |), "current_target" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "touched_accounts" |), "add" |), + make_list [ + M.get_name (| globals, "RIPEMD160_ADDRESS" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "gas_left" |), + M.get_field (| M.get_name (| globals, "child_evm" |), "gas_left" |) + |) in + M.pure Constant.None_)). diff --git a/CoqOfPython/ethereum/cancun/vm/exceptions.v b/CoqOfPython/ethereum/cancun/vm/exceptions.v new file mode 100644 index 0000000..42aba40 --- /dev/null +++ b/CoqOfPython/ethereum/cancun/vm/exceptions.v @@ -0,0 +1,181 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.cancun.vm.exceptions". + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) Exceptions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Exceptions which cause the EVM to halt exceptionally. +". + +Axiom ethereum_exceptions_imports_EthereumException : + IsImported globals "ethereum.exceptions" "EthereumException". + +Definition ExceptionalHalt : Value.t := + builtins.make_klass + [(globals, "EthereumException")] + [ + + ] + [ + + ]. + +Definition Revert : Value.t := + builtins.make_klass + [(globals, "EthereumException")] + [ + + ] + [ + + ]. + +Definition StackUnderflowError : Value.t := + builtins.make_klass + [(globals, "ExceptionalHalt")] + [ + + ] + [ + + ]. + +Definition StackOverflowError : Value.t := + builtins.make_klass + [(globals, "ExceptionalHalt")] + [ + + ] + [ + + ]. + +Definition OutOfGasError : Value.t := + builtins.make_klass + [(globals, "ExceptionalHalt")] + [ + + ] + [ + + ]. + +Definition InvalidOpcode : Value.t := + builtins.make_klass + [(globals, "ExceptionalHalt")] + [ + + ] + [ + ( + "__init__", + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "self"; "code" ] |) in + let _ := M.call (| + M.get_field (| M.call (| + M.get_name (| globals, "super" |), + make_list [], + make_dict [] + |), "__init__" |), + make_list [ + M.get_name (| globals, "code" |) + ], + make_dict [] + |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, "self" |), "code" |), + M.get_name (| globals, "code" |) + |) in + M.pure Constant.None_)) + ) + ]. + +Definition InvalidJumpDestError : Value.t := + builtins.make_klass + [(globals, "ExceptionalHalt")] + [ + + ] + [ + + ]. + +Definition StackDepthLimitError : Value.t := + builtins.make_klass + [(globals, "ExceptionalHalt")] + [ + + ] + [ + + ]. + +Definition WriteInStaticContext : Value.t := + builtins.make_klass + [(globals, "ExceptionalHalt")] + [ + + ] + [ + + ]. + +Definition OutOfBoundsRead : Value.t := + builtins.make_klass + [(globals, "ExceptionalHalt")] + [ + + ] + [ + + ]. + +Definition InvalidParameter : Value.t := + builtins.make_klass + [(globals, "ExceptionalHalt")] + [ + + ] + [ + + ]. + +Definition InvalidContractPrefix : Value.t := + builtins.make_klass + [(globals, "ExceptionalHalt")] + [ + + ] + [ + + ]. + +Definition AddressCollision : Value.t := + builtins.make_klass + [(globals, "ExceptionalHalt")] + [ + + ] + [ + + ]. + +Definition KZGProofError : Value.t := + builtins.make_klass + [(globals, "ExceptionalHalt")] + [ + + ] + [ + + ]. diff --git a/CoqOfPython/ethereum/cancun/vm/gas.v b/CoqOfPython/ethereum/cancun/vm/gas.v new file mode 100644 index 0000000..8e04e69 --- /dev/null +++ b/CoqOfPython/ethereum/cancun/vm/gas.v @@ -0,0 +1,1211 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.cancun.vm.gas". + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) Gas +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +EVM gas constants and calculators. +". + +Axiom dataclasses_imports_dataclass : + IsImported globals "dataclasses" "dataclass". + +Axiom typing_imports_List : + IsImported globals "typing" "List". +Axiom typing_imports_Tuple : + IsImported globals "typing" "Tuple". + +Axiom ethereum_base_types_imports_U64 : + IsImported globals "ethereum.base_types" "U64". +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". + +Axiom ethereum_trace_imports_GasAndRefund : + IsImported globals "ethereum.trace" "GasAndRefund". +Axiom ethereum_trace_imports_evm_trace : + IsImported globals "ethereum.trace" "evm_trace". + +Axiom ethereum_utils_numeric_imports_ceil32 : + IsImported globals "ethereum.utils.numeric" "ceil32". +Axiom ethereum_utils_numeric_imports_taylor_exponential : + IsImported globals "ethereum.utils.numeric" "taylor_exponential". + +Axiom ethereum_cancun_blocks_imports_Header : + IsImported globals "ethereum.cancun.blocks" "Header". + +Axiom ethereum_cancun_transactions_imports_BlobTransaction : + IsImported globals "ethereum.cancun.transactions" "BlobTransaction". +Axiom ethereum_cancun_transactions_imports_Transaction : + IsImported globals "ethereum.cancun.transactions" "Transaction". + +Axiom ethereum_cancun_vm_imports_Evm : + IsImported globals "ethereum.cancun.vm" "Evm". + +Axiom ethereum_cancun_vm_exceptions_imports_OutOfGasError : + IsImported globals "ethereum.cancun.vm.exceptions" "OutOfGasError". + +Definition GAS_JUMPDEST : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 1 + ], + make_dict [] + |) +)). + +Definition GAS_BASE : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 2 + ], + make_dict [] + |) +)). + +Definition GAS_VERY_LOW : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 3 + ], + make_dict [] + |) +)). + +Definition GAS_STORAGE_SET : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 20000 + ], + make_dict [] + |) +)). + +Definition GAS_STORAGE_UPDATE : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 5000 + ], + make_dict [] + |) +)). + +Definition GAS_STORAGE_CLEAR_REFUND : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 4800 + ], + make_dict [] + |) +)). + +Definition GAS_LOW : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 5 + ], + make_dict [] + |) +)). + +Definition GAS_MID : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 8 + ], + make_dict [] + |) +)). + +Definition GAS_HIGH : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 10 + ], + make_dict [] + |) +)). + +Definition GAS_EXPONENTIATION : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 10 + ], + make_dict [] + |) +)). + +Definition GAS_EXPONENTIATION_PER_BYTE : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 50 + ], + make_dict [] + |) +)). + +Definition GAS_MEMORY : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 3 + ], + make_dict [] + |) +)). + +Definition GAS_KECCAK256 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 30 + ], + make_dict [] + |) +)). + +Definition GAS_KECCAK256_WORD : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 6 + ], + make_dict [] + |) +)). + +Definition GAS_COPY : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 3 + ], + make_dict [] + |) +)). + +Definition GAS_BLOCK_HASH : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 20 + ], + make_dict [] + |) +)). + +Definition GAS_LOG : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 375 + ], + make_dict [] + |) +)). + +Definition GAS_LOG_DATA : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 8 + ], + make_dict [] + |) +)). + +Definition GAS_LOG_TOPIC : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 375 + ], + make_dict [] + |) +)). + +Definition GAS_CREATE : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 32000 + ], + make_dict [] + |) +)). + +Definition GAS_CODE_DEPOSIT : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 200 + ], + make_dict [] + |) +)). + +Definition GAS_ZERO : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) +)). + +Definition GAS_NEW_ACCOUNT : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 25000 + ], + make_dict [] + |) +)). + +Definition GAS_CALL_VALUE : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 9000 + ], + make_dict [] + |) +)). + +Definition GAS_CALL_STIPEND : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 2300 + ], + make_dict [] + |) +)). + +Definition GAS_SELF_DESTRUCT : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 5000 + ], + make_dict [] + |) +)). + +Definition GAS_SELF_DESTRUCT_NEW_ACCOUNT : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 25000 + ], + make_dict [] + |) +)). + +Definition GAS_ECRECOVER : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 3000 + ], + make_dict [] + |) +)). + +Definition GAS_SHA256 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 60 + ], + make_dict [] + |) +)). + +Definition GAS_SHA256_WORD : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 12 + ], + make_dict [] + |) +)). + +Definition GAS_RIPEMD160 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 600 + ], + make_dict [] + |) +)). + +Definition GAS_RIPEMD160_WORD : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 120 + ], + make_dict [] + |) +)). + +Definition GAS_IDENTITY : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 15 + ], + make_dict [] + |) +)). + +Definition GAS_IDENTITY_WORD : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 3 + ], + make_dict [] + |) +)). + +Definition GAS_RETURN_DATA_COPY : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 3 + ], + make_dict [] + |) +)). + +Definition GAS_FAST_STEP : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 5 + ], + make_dict [] + |) +)). + +Definition GAS_BLAKE2_PER_ROUND : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 1 + ], + make_dict [] + |) +)). + +Definition GAS_COLD_SLOAD : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 2100 + ], + make_dict [] + |) +)). + +Definition GAS_COLD_ACCOUNT_ACCESS : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 2600 + ], + make_dict [] + |) +)). + +Definition GAS_WARM_ACCESS : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 100 + ], + make_dict [] + |) +)). + +Definition GAS_INIT_CODE_WORD_COST : Value.t := M.run ltac:(M.monadic ( + Constant.int 2 +)). + +Definition GAS_BLOBHASH_OPCODE : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 3 + ], + make_dict [] + |) +)). + +Definition GAS_POINT_EVALUATION : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 50000 + ], + make_dict [] + |) +)). + +Definition TARGET_BLOB_GAS_PER_BLOCK : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "U64" |), + make_list [ + Constant.int 393216 + ], + make_dict [] + |) +)). + +Definition GAS_PER_BLOB : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + BinOp.pow (| + Constant.int 2, + Constant.int 17 + |) + ], + make_dict [] + |) +)). + +Definition MIN_BLOB_GASPRICE : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 1 + ], + make_dict [] + |) +)). + +Definition BLOB_GASPRICE_UPDATE_FRACTION : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 3338477 + ], + make_dict [] + |) +)). + +Definition ExtendMemory : Value.t := + builtins.make_klass + [] + [ + + ] + [ + + ]. + +Definition MessageCallGas : Value.t := + builtins.make_klass + [] + [ + + ] + [ + + ]. + +Definition charge_gas : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm"; "amount" ] |) in + let _ := Constant.str " + Subtracts `amount` from `evm.gas_left`. + + Parameters + ---------- + evm : + The current EVM. + amount : + The amount of gas the current operation requires. + + " in + let _ := M.call (| + M.get_name (| globals, "evm_trace" |), + make_list [ + M.get_name (| globals, "evm" |); + M.call (| + M.get_name (| globals, "GasAndRefund" |), + make_list [ + M.get_name (| globals, "amount" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.lt (| + M.get_field (| M.get_name (| globals, "evm" |), "gas_left" |), + M.get_name (| globals, "amount" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, "OutOfGasError" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_op (| + BinOp.sub, + M.get_field (| M.get_name (| globals, "evm" |), "gas_left" |), + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + M.get_name (| globals, "amount" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_)). + +Definition calculate_memory_gas_cost : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "size_in_bytes" ] |) in + let _ := Constant.str " + Calculates the gas cost for allocating memory + to the smallest multiple of 32 bytes, + such that the allocated size is at least as big as the given size. + + Parameters + ---------- + size_in_bytes : + The size of the data in bytes. + + Returns + ------- + total_gas_cost : `ethereum.base_types.Uint` + The gas cost for storing data in memory. + " in + let _ := M.assign_local (| + "size_in_words" , + BinOp.floor_div (| + M.call (| + M.get_name (| globals, "ceil32" |), + make_list [ + M.get_name (| globals, "size_in_bytes" |) + ], + make_dict [] + |), + Constant.int 32 + |) + |) in + let _ := M.assign_local (| + "linear_cost" , + BinOp.mult (| + M.get_name (| globals, "size_in_words" |), + M.get_name (| globals, "GAS_MEMORY" |) + |) + |) in + let _ := M.assign_local (| + "quadratic_cost" , + BinOp.floor_div (| + BinOp.pow (| + M.get_name (| globals, "size_in_words" |), + Constant.int 2 + |), + Constant.int 512 + |) + |) in + let _ := M.assign_local (| + "total_gas_cost" , + BinOp.add (| + M.get_name (| globals, "linear_cost" |), + M.get_name (| globals, "quadratic_cost" |) + |) + |) in +(* At stmt: unsupported node type: Try *) + M.pure Constant.None_)). + +Definition calculate_gas_extend_memory : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "memory"; "extensions" ] |) in + let _ := Constant.str " + Calculates the gas amount to extend memory + + Parameters + ---------- + memory : + Memory contents of the EVM. + extensions: + List of extensions to be made to the memory. + Consists of a tuple of start position and size. + + Returns + ------- + extend_memory: `ExtendMemory` + " in + let _ := M.assign_local (| + "size_to_extend" , + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "to_be_paid" , + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "current_size" , + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_name (| globals, "memory" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := + M.for_ (| + make_tuple [ M.get_name (| globals, "start_position" |); M.get_name (| globals, "size" |) ], + M.get_name (| globals, "extensions" |), + ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, "size" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.continue (| |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "before_size" , + M.call (| + M.get_name (| globals, "ceil32" |), + make_list [ + M.get_name (| globals, "current_size" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "after_size" , + M.call (| + M.get_name (| globals, "ceil32" |), + make_list [ + BinOp.add (| + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.get_name (| globals, "start_position" |) + ], + make_dict [] + |), + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.get_name (| globals, "size" |) + ], + make_dict [] + |) + |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.lt_e (| + M.get_name (| globals, "after_size" |), + M.get_name (| globals, "before_size" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.continue (| |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_op_local (| + BinOp.add, + "size_to_extend", + BinOp.sub (| + M.get_name (| globals, "after_size" |), + M.get_name (| globals, "before_size" |) + |) + |) in + let _ := M.assign_local (| + "already_paid" , + M.call (| + M.get_name (| globals, "calculate_memory_gas_cost" |), + make_list [ + M.get_name (| globals, "before_size" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "total_cost" , + M.call (| + M.get_name (| globals, "calculate_memory_gas_cost" |), + make_list [ + M.get_name (| globals, "after_size" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_op_local (| + BinOp.add, + "to_be_paid", + BinOp.sub (| + M.get_name (| globals, "total_cost" |), + M.get_name (| globals, "already_paid" |) + |) + |) in + let _ := M.assign_local (| + "current_size" , + M.get_name (| globals, "after_size" |) + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, "ExtendMemory" |), + make_list [ + M.get_name (| globals, "to_be_paid" |); + M.get_name (| globals, "size_to_extend" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Definition calculate_message_call_gas : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "value"; "gas"; "gas_left"; "memory_cost"; "extra_gas"; "call_stipend" ] |) in + let _ := Constant.str " + Calculates the MessageCallGas (cost and stipend) for + executing call Opcodes. + + Parameters + ---------- + value: + The amount of `ETH` that needs to be transferred. + gas : + The amount of gas provided to the message-call. + gas_left : + The amount of gas left in the current frame. + memory_cost : + The amount needed to extend the memory in the current frame. + extra_gas : + The amount of gas needed for transferring value + creating a new + account inside a message call. + call_stipend : + The amount of stipend provided to a message call to execute code while + transferring value(ETH). + + Returns + ------- + message_call_gas: `MessageCallGas` + " in + let _ := M.assign_local (| + "call_stipend" , + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, "value" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( +M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + (* else *) + )), ltac:(M.monadic ( +M.get_name (| globals, "call_stipend" |) + )) |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.lt (| + M.get_name (| globals, "gas_left" |), + BinOp.add (| + M.get_name (| globals, "extra_gas" |), + M.get_name (| globals, "memory_cost" |) + |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + M.call (| + M.get_name (| globals, "MessageCallGas" |), + make_list [ + BinOp.add (| + M.get_name (| globals, "gas" |), + M.get_name (| globals, "extra_gas" |) + |); + BinOp.add (| + M.get_name (| globals, "gas" |), + M.get_name (| globals, "call_stipend" |) + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "gas" , + M.call (| + M.get_name (| globals, "min" |), + make_list [ + M.get_name (| globals, "gas" |); + M.call (| + M.get_name (| globals, "max_message_call_gas" |), + make_list [ + BinOp.sub (| + BinOp.sub (| + M.get_name (| globals, "gas_left" |), + M.get_name (| globals, "memory_cost" |) + |), + M.get_name (| globals, "extra_gas" |) + |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, "MessageCallGas" |), + make_list [ + BinOp.add (| + M.get_name (| globals, "gas" |), + M.get_name (| globals, "extra_gas" |) + |); + BinOp.add (| + M.get_name (| globals, "gas" |), + M.get_name (| globals, "call_stipend" |) + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Definition max_message_call_gas : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "gas" ] |) in + let _ := Constant.str " + Calculates the maximum gas that is allowed for making a message call + + Parameters + ---------- + gas : + The amount of gas provided to the message-call. + + Returns + ------- + max_allowed_message_call_gas: `ethereum.base_types.Uint` + The maximum gas allowed for making the message-call. + " in + let _ := M.return_ (| + BinOp.sub (| + M.get_name (| globals, "gas" |), + BinOp.floor_div (| + M.get_name (| globals, "gas" |), + Constant.int 64 + |) + |) + |) in + M.pure Constant.None_)). + +Definition init_code_cost : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "init_code_length" ] |) in + let _ := Constant.str " + Calculates the gas to be charged for the init code in CREAT* + opcodes as well as create transactions. + + Parameters + ---------- + init_code_length : + The length of the init code provided to the opcode + or a create transaction + + Returns + ------- + init_code_gas: `ethereum.base_types.Uint` + The gas to be charged for the init code. + " in + let _ := M.return_ (| + BinOp.floor_div (| + BinOp.mult (| + M.get_name (| globals, "GAS_INIT_CODE_WORD_COST" |), + M.call (| + M.get_name (| globals, "ceil32" |), + make_list [ + M.get_name (| globals, "init_code_length" |) + ], + make_dict [] + |) + |), + Constant.int 32 + |) + |) in + M.pure Constant.None_)). + +Definition calculate_excess_blob_gas : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "parent_header" ] |) in + let _ := Constant.str " + Calculated the excess blob gas for the current block based + on the gas used in the parent block. + + Parameters + ---------- + parent_header : + The parent block of the current block. + + Returns + ------- + excess_blob_gas: `ethereum.base_types.U64` + The excess blob gas for the current block. + " in + let _ := M.assign_local (| + "parent_blob_gas" , + BinOp.add (| + M.get_field (| M.get_name (| globals, "parent_header" |), "excess_blob_gas" |), + M.get_field (| M.get_name (| globals, "parent_header" |), "blob_gas_used" |) + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.lt (| + M.get_name (| globals, "parent_blob_gas" |), + M.get_name (| globals, "TARGET_BLOB_GAS_PER_BLOCK" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + M.call (| + M.get_name (| globals, "U64" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.return_ (| + BinOp.sub (| + M.get_name (| globals, "parent_blob_gas" |), + M.get_name (| globals, "TARGET_BLOB_GAS_PER_BLOCK" |) + |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_)). + +Definition calculate_total_blob_gas : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "tx" ] |) in + let _ := Constant.str " + Calculate the total blob gas for a transaction. + + Parameters + ---------- + tx : + The transaction for which the blob gas is to be calculated. + + Returns + ------- + total_blob_gas: `ethereum.base_types.Uint` + The total blob gas for the transaction. + " in + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, "isinstance" |), + make_list [ + M.get_name (| globals, "tx" |); + M.get_name (| globals, "BlobTransaction" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + BinOp.mult (| + M.get_name (| globals, "GAS_PER_BLOB" |), + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_field (| M.get_name (| globals, "tx" |), "blob_versioned_hashes" |) + ], + make_dict [] + |) + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.return_ (| + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_)). + +Definition calculate_blob_gas_price : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "excess_blob_gas" ] |) in + let _ := Constant.str " + Calculate the blob gasprice for a block. + + Parameters + ---------- + excess_blob_gas : + The excess blob gas for the block. + + Returns + ------- + blob_gasprice: `Uint` + The blob gasprice. + " in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, "taylor_exponential" |), + make_list [ + M.get_name (| globals, "MIN_BLOB_GASPRICE" |); + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.get_name (| globals, "excess_blob_gas" |) + ], + make_dict [] + |); + M.get_name (| globals, "BLOB_GASPRICE_UPDATE_FRACTION" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Definition calculate_data_fee : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "excess_blob_gas"; "tx" ] |) in + let _ := Constant.str " + Calculate the blob data fee for a transaction. + + Parameters + ---------- + excess_blob_gas : + The excess_blob_gas for the execution. + tx : + The transaction for which the blob data fee is to be calculated. + + Returns + ------- + data_fee: `Uint` + The blob data fee. + " in + let _ := M.return_ (| + BinOp.mult (| + M.call (| + M.get_name (| globals, "calculate_total_blob_gas" |), + make_list [ + M.get_name (| globals, "tx" |) + ], + make_dict [] + |), + M.call (| + M.get_name (| globals, "calculate_blob_gas_price" |), + make_list [ + M.get_name (| globals, "excess_blob_gas" |) + ], + make_dict [] + |) + |) + |) in + M.pure Constant.None_)). diff --git a/CoqOfPython/ethereum/cancun/vm/instructions/__init__.v b/CoqOfPython/ethereum/cancun/vm/instructions/__init__.v new file mode 100644 index 0000000..0523587 --- /dev/null +++ b/CoqOfPython/ethereum/cancun/vm/instructions/__init__.v @@ -0,0 +1,74 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.cancun.vm.instructions.__init__". + +Definition expr_1 : Value.t := + Constant.str " +EVM Instruction Encoding (Opcodes) +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Machine readable representations of EVM instructions, and a mapping to their +implementations. +". + +(* At top_level_stmt: unsupported node type: Import *) + +Axiom typing_imports_Callable : + IsImported globals "typing" "Callable". +Axiom typing_imports_Dict : + IsImported globals "typing" "Dict". + +Axiom ethereum_cancun_vm_instructions_imports_arithmetic : + IsImported globals "ethereum.cancun.vm.instructions" "arithmetic". + +Axiom ethereum_cancun_vm_instructions_imports_bitwise : + IsImported globals "ethereum.cancun.vm.instructions" "bitwise". + +Axiom ethereum_cancun_vm_instructions_imports_block : + IsImported globals "ethereum.cancun.vm.instructions" "block". + +Axiom ethereum_cancun_vm_instructions_imports_comparison : + IsImported globals "ethereum.cancun.vm.instructions" "comparison". + +Axiom ethereum_cancun_vm_instructions_imports_control_flow : + IsImported globals "ethereum.cancun.vm.instructions" "control_flow". + +Axiom ethereum_cancun_vm_instructions_imports_environment : + IsImported globals "ethereum.cancun.vm.instructions" "environment". + +Axiom ethereum_cancun_vm_instructions_imports_keccak : + IsImported globals "ethereum.cancun.vm.instructions" "keccak". + +Axiom ethereum_cancun_vm_instructions_imports_log : + IsImported globals "ethereum.cancun.vm.instructions" "log". + +Axiom ethereum_cancun_vm_instructions_imports_memory : + IsImported globals "ethereum.cancun.vm.instructions" "memory". + +Axiom ethereum_cancun_vm_instructions_imports_stack : + IsImported globals "ethereum.cancun.vm.instructions" "stack". + +Axiom ethereum_cancun_vm_instructions_imports_storage : + IsImported globals "ethereum.cancun.vm.instructions" "storage". + +Axiom ethereum_cancun_vm_instructions_imports_system : + IsImported globals "ethereum.cancun.vm.instructions" "system". + +Definition Ops : Value.t := + builtins.make_klass + [(* At base: unsupported node type: Attribute *)] + [ + + ] + [ + + ]. + +(* At top_level_stmt: unsupported node type: AnnAssign *) diff --git a/CoqOfPython/ethereum/cancun/vm/instructions/arithmetic.v b/CoqOfPython/ethereum/cancun/vm/instructions/arithmetic.v new file mode 100644 index 0000000..dc9d022 --- /dev/null +++ b/CoqOfPython/ethereum/cancun/vm/instructions/arithmetic.v @@ -0,0 +1,1220 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.cancun.vm.instructions.arithmetic". + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) Arithmetic Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM Arithmetic instructions. +". + +Axiom ethereum_base_types_imports_U255_CEIL_VALUE : + IsImported globals "ethereum.base_types" "U255_CEIL_VALUE". +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_U256_CEIL_VALUE : + IsImported globals "ethereum.base_types" "U256_CEIL_VALUE". +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". + +Axiom ethereum_utils_numeric_imports_get_sign : + IsImported globals "ethereum.utils.numeric" "get_sign". + +Axiom ethereum_cancun_vm_imports_Evm : + IsImported globals "ethereum.cancun.vm" "Evm". + +Axiom ethereum_cancun_vm_gas_imports_GAS_EXPONENTIATION : + IsImported globals "ethereum.cancun.vm.gas" "GAS_EXPONENTIATION". +Axiom ethereum_cancun_vm_gas_imports_GAS_EXPONENTIATION_PER_BYTE : + IsImported globals "ethereum.cancun.vm.gas" "GAS_EXPONENTIATION_PER_BYTE". +Axiom ethereum_cancun_vm_gas_imports_GAS_LOW : + IsImported globals "ethereum.cancun.vm.gas" "GAS_LOW". +Axiom ethereum_cancun_vm_gas_imports_GAS_MID : + IsImported globals "ethereum.cancun.vm.gas" "GAS_MID". +Axiom ethereum_cancun_vm_gas_imports_GAS_VERY_LOW : + IsImported globals "ethereum.cancun.vm.gas" "GAS_VERY_LOW". +Axiom ethereum_cancun_vm_gas_imports_charge_gas : + IsImported globals "ethereum.cancun.vm.gas" "charge_gas". + +Axiom ethereum_cancun_vm_stack_imports_pop : + IsImported globals "ethereum.cancun.vm.stack" "pop". +Axiom ethereum_cancun_vm_stack_imports_push : + IsImported globals "ethereum.cancun.vm.stack" "push". + +Definition add : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Adds the top two elements of the stack together, and pushes the result back + on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "x" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "y" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_VERY_LOW" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "result" , + M.call (| + M.get_field (| M.get_name (| globals, "x" |), "wrapping_add" |), + make_list [ + M.get_name (| globals, "y" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.get_name (| globals, "result" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition sub : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Subtracts the top two elements of the stack, and pushes the result back + on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "x" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "y" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_VERY_LOW" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "result" , + M.call (| + M.get_field (| M.get_name (| globals, "x" |), "wrapping_sub" |), + make_list [ + M.get_name (| globals, "y" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.get_name (| globals, "result" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition mul : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Multiply the top two elements of the stack, and pushes the result back + on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "x" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "y" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_LOW" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "result" , + M.call (| + M.get_field (| M.get_name (| globals, "x" |), "wrapping_mul" |), + make_list [ + M.get_name (| globals, "y" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.get_name (| globals, "result" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition div : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Integer division of the top two elements of the stack. Pushes the result + back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "dividend" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "divisor" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_LOW" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, "divisor" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "quotient" , + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "quotient" , + BinOp.floor_div (| + M.get_name (| globals, "dividend" |), + M.get_name (| globals, "divisor" |) + |) + |) in + M.pure Constant.None_ + )) |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.get_name (| globals, "quotient" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition sdiv : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Signed integer division of the top two elements of the stack. Pushes the + result back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "dividend" , + M.call (| + M.get_field (| M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |), "to_signed" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "divisor" , + M.call (| + M.get_field (| M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |), "to_signed" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_LOW" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, "divisor" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "quotient" , + Constant.int 0 + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + BoolOp.and (| + Compare.eq (| + M.get_name (| globals, "dividend" |), + UnOp.sub (| M.get_name (| globals, "U255_CEIL_VALUE" |) |) + |), + ltac:(M.monadic ( + Compare.eq (| + M.get_name (| globals, "divisor" |), + UnOp.sub (| Constant.int 1 |) + |) + )) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "quotient" , + UnOp.sub (| M.get_name (| globals, "U255_CEIL_VALUE" |) |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "sign" , + M.call (| + M.get_name (| globals, "get_sign" |), + make_list [ + BinOp.mult (| + M.get_name (| globals, "dividend" |), + M.get_name (| globals, "divisor" |) + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "quotient" , + BinOp.mult (| + M.get_name (| globals, "sign" |), + BinOp.floor_div (| + M.call (| + M.get_name (| globals, "abs" |), + make_list [ + M.get_name (| globals, "dividend" |) + ], + make_dict [] + |), + M.call (| + M.get_name (| globals, "abs" |), + make_list [ + M.get_name (| globals, "divisor" |) + ], + make_dict [] + |) + |) + |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )) |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.call (| + M.get_field (| M.get_name (| globals, "U256" |), "from_signed" |), + make_list [ + M.get_name (| globals, "quotient" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition mod_ : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Modulo remainder of the top two elements of the stack. Pushes the result + back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "x" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "y" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_LOW" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, "y" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "remainder" , + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "remainder" , + BinOp.mod_ (| + M.get_name (| globals, "x" |), + M.get_name (| globals, "y" |) + |) + |) in + M.pure Constant.None_ + )) |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.get_name (| globals, "remainder" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition smod : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Signed modulo remainder of the top two elements of the stack. Pushes the + result back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "x" , + M.call (| + M.get_field (| M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |), "to_signed" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "y" , + M.call (| + M.get_field (| M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |), "to_signed" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_LOW" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, "y" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "remainder" , + Constant.int 0 + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "remainder" , + BinOp.mult (| + M.call (| + M.get_name (| globals, "get_sign" |), + make_list [ + M.get_name (| globals, "x" |) + ], + make_dict [] + |), + BinOp.mod_ (| + M.call (| + M.get_name (| globals, "abs" |), + make_list [ + M.get_name (| globals, "x" |) + ], + make_dict [] + |), + M.call (| + M.get_name (| globals, "abs" |), + make_list [ + M.get_name (| globals, "y" |) + ], + make_dict [] + |) + |) + |) + |) in + M.pure Constant.None_ + )) |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.call (| + M.get_field (| M.get_name (| globals, "U256" |), "from_signed" |), + make_list [ + M.get_name (| globals, "remainder" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition addmod : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Modulo addition of the top 2 elements with the 3rd element. Pushes the + result back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "x" , + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "y" , + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "z" , + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_MID" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, "z" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "result" , + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "result" , + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + BinOp.mod_ (| + BinOp.add (| + M.get_name (| globals, "x" |), + M.get_name (| globals, "y" |) + |), + M.get_name (| globals, "z" |) + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + )) |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.get_name (| globals, "result" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition mulmod : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Modulo multiplication of the top 2 elements with the 3rd element. Pushes + the result back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "x" , + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "y" , + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "z" , + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_MID" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, "z" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "result" , + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "result" , + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + BinOp.mod_ (| + BinOp.mult (| + M.get_name (| globals, "x" |), + M.get_name (| globals, "y" |) + |), + M.get_name (| globals, "z" |) + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + )) |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.get_name (| globals, "result" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition exp : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Exponential operation of the top 2 elements. Pushes the result back on + the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "base" , + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "exponent" , + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "exponent_bits" , + M.call (| + M.get_field (| M.get_name (| globals, "exponent" |), "bit_length" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "exponent_bytes" , + BinOp.floor_div (| + BinOp.add (| + M.get_name (| globals, "exponent_bits" |), + Constant.int 7 + |), + Constant.int 8 + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + BinOp.add (| + M.get_name (| globals, "GAS_EXPONENTIATION" |), + BinOp.mult (| + M.get_name (| globals, "GAS_EXPONENTIATION_PER_BYTE" |), + M.get_name (| globals, "exponent_bytes" |) + |) + |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "result" , + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + M.call (| + M.get_name (| globals, "pow" |), + make_list [ + M.get_name (| globals, "base" |); + M.get_name (| globals, "exponent" |); + M.get_name (| globals, "U256_CEIL_VALUE" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.get_name (| globals, "result" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition signextend : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Sign extend operation. In other words, extend a signed number which + fits in N bytes to 32 bytes. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "byte_num" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "value" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_LOW" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.gt (| + M.get_name (| globals, "byte_num" |), + Constant.int 31 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "result" , + M.get_name (| globals, "value" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "value_bytes" , + M.call (| + M.get_name (| globals, "bytes" |), + make_list [ + M.call (| + M.get_field (| M.get_name (| globals, "value" |), "to_be_bytes32" |), + make_list [], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "value_bytes" , + M.slice (| + M.get_name (| globals, "value_bytes" |), + BinOp.sub (| + Constant.int 31, + M.call (| + M.get_name (| globals, "int" |), + make_list [ + M.get_name (| globals, "byte_num" |) + ], + make_dict [] + |) + |), + Constant.None_, + Constant.None_ + |) + |) in + let _ := M.assign_local (| + "sign_bit" , + BinOp.r_shift (| + M.get_subscript (| + M.get_name (| globals, "value_bytes" |), + Constant.int 0 + |), + Constant.int 7 + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, "sign_bit" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "result" , + M.call (| + M.get_field (| M.get_name (| globals, "U256" |), "from_be_bytes" |), + make_list [ + M.get_name (| globals, "value_bytes" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "num_bytes_prepend" , + BinOp.sub (| + Constant.int 32, + BinOp.add (| + M.get_name (| globals, "byte_num" |), + Constant.int 1 + |) + |) + |) in + let _ := M.assign_local (| + "result" , + M.call (| + M.get_field (| M.get_name (| globals, "U256" |), "from_be_bytes" |), + make_list [ + BinOp.add (| + M.call (| + M.get_name (| globals, "bytearray" |), + make_list [ + BinOp.mult (| + make_list [ + Constant.int 255 + ], + M.get_name (| globals, "num_bytes_prepend" |) + |) + ], + make_dict [] + |), + M.get_name (| globals, "value_bytes" |) + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )) |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.get_name (| globals, "result" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). diff --git a/CoqOfPython/ethereum/cancun/vm/instructions/bitwise.v b/CoqOfPython/ethereum/cancun/vm/instructions/bitwise.v new file mode 100644 index 0000000..3a02f86 --- /dev/null +++ b/CoqOfPython/ethereum/cancun/vm/instructions/bitwise.v @@ -0,0 +1,666 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.cancun.vm.instructions.bitwise". + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) Bitwise Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM bitwise instructions. +". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_U256_CEIL_VALUE : + IsImported globals "ethereum.base_types" "U256_CEIL_VALUE". + +Axiom ethereum_cancun_vm_imports_Evm : + IsImported globals "ethereum.cancun.vm" "Evm". + +Axiom ethereum_cancun_vm_gas_imports_GAS_VERY_LOW : + IsImported globals "ethereum.cancun.vm.gas" "GAS_VERY_LOW". +Axiom ethereum_cancun_vm_gas_imports_charge_gas : + IsImported globals "ethereum.cancun.vm.gas" "charge_gas". + +Axiom ethereum_cancun_vm_stack_imports_pop : + IsImported globals "ethereum.cancun.vm.stack" "pop". +Axiom ethereum_cancun_vm_stack_imports_push : + IsImported globals "ethereum.cancun.vm.stack" "push". + +Definition bitwise_and : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Bitwise AND operation of the top 2 elements of the stack. Pushes the + result back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "x" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "y" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_VERY_LOW" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + BinOp.bit_and (| + M.get_name (| globals, "x" |), + M.get_name (| globals, "y" |) + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition bitwise_or : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Bitwise OR operation of the top 2 elements of the stack. Pushes the + result back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "x" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "y" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_VERY_LOW" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + BinOp.bit_or (| + M.get_name (| globals, "x" |), + M.get_name (| globals, "y" |) + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition bitwise_xor : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Bitwise XOR operation of the top 2 elements of the stack. Pushes the + result back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "x" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "y" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_VERY_LOW" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + BinOp.bit_xor (| + M.get_name (| globals, "x" |), + M.get_name (| globals, "y" |) + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition bitwise_not : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Bitwise NOT operation of the top element of the stack. Pushes the + result back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "x" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_VERY_LOW" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + UnOp.invert (| M.get_name (| globals, "x" |) |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition get_byte : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + For a word (defined by next top element of the stack), retrieve the + Nth byte (0-indexed and defined by top element of stack) from the + left (most significant) to right (least significant). + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "byte_index" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "word" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_VERY_LOW" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.gt_e (| + M.get_name (| globals, "byte_index" |), + Constant.int 32 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "result" , + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "extra_bytes_to_right" , + BinOp.sub (| + Constant.int 31, + M.get_name (| globals, "byte_index" |) + |) + |) in + let _ := M.assign_local (| + "word" , + BinOp.r_shift (| + M.get_name (| globals, "word" |), + BinOp.mult (| + M.get_name (| globals, "extra_bytes_to_right" |), + Constant.int 8 + |) + |) + |) in + let _ := M.assign_local (| + "word" , + BinOp.bit_and (| + M.get_name (| globals, "word" |), + Constant.int 255 + |) + |) in + let _ := M.assign_local (| + "result" , + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + M.get_name (| globals, "word" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + )) |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.get_name (| globals, "result" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition bitwise_shl : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Logical shift left (SHL) operation of the top 2 elements of the stack. + Pushes the result back on the stack. + Parameters + ---------- + evm : + The current EVM frame. + " in + let _ := M.assign_local (| + "shift" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "value" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_VERY_LOW" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.lt (| + M.get_name (| globals, "shift" |), + Constant.int 256 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "result" , + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + BinOp.mod_ (| + BinOp.l_shift (| + M.get_name (| globals, "value" |), + M.get_name (| globals, "shift" |) + |), + M.get_name (| globals, "U256_CEIL_VALUE" |) + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "result" , + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + )) |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.get_name (| globals, "result" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition bitwise_shr : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Logical shift right (SHR) operation of the top 2 elements of the stack. + Pushes the result back on the stack. + Parameters + ---------- + evm : + The current EVM frame. + " in + let _ := M.assign_local (| + "shift" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "value" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_VERY_LOW" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.lt (| + M.get_name (| globals, "shift" |), + Constant.int 256 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "result" , + BinOp.r_shift (| + M.get_name (| globals, "value" |), + M.get_name (| globals, "shift" |) + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "result" , + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + )) |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.get_name (| globals, "result" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition bitwise_sar : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Arithmetic shift right (SAR) operation of the top 2 elements of the stack. + Pushes the result back on the stack. + Parameters + ---------- + evm : + The current EVM frame. + " in + let _ := M.assign_local (| + "shift" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "signed_value" , + M.call (| + M.get_field (| M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |), "to_signed" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_VERY_LOW" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.lt (| + M.get_name (| globals, "shift" |), + Constant.int 256 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "result" , + M.call (| + M.get_field (| M.get_name (| globals, "U256" |), "from_signed" |), + make_list [ + BinOp.r_shift (| + M.get_name (| globals, "signed_value" |), + M.get_name (| globals, "shift" |) + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + Compare.gt_e (| + M.get_name (| globals, "signed_value" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "result" , + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "result" , + M.get_field (| M.get_name (| globals, "U256" |), "MAX_VALUE" |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )) |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.get_name (| globals, "result" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). diff --git a/CoqOfPython/ethereum/cancun/vm/instructions/block.v b/CoqOfPython/ethereum/cancun/vm/instructions/block.v new file mode 100644 index 0000000..f0c6cb2 --- /dev/null +++ b/CoqOfPython/ethereum/cancun/vm/instructions/block.v @@ -0,0 +1,432 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.cancun.vm.instructions.block". + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) Block Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM block instructions. +". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". + +Axiom ethereum_cancun_vm_imports_Evm : + IsImported globals "ethereum.cancun.vm" "Evm". + +Axiom ethereum_cancun_vm_gas_imports_GAS_BASE : + IsImported globals "ethereum.cancun.vm.gas" "GAS_BASE". +Axiom ethereum_cancun_vm_gas_imports_GAS_BLOCK_HASH : + IsImported globals "ethereum.cancun.vm.gas" "GAS_BLOCK_HASH". +Axiom ethereum_cancun_vm_gas_imports_charge_gas : + IsImported globals "ethereum.cancun.vm.gas" "charge_gas". + +Axiom ethereum_cancun_vm_stack_imports_pop : + IsImported globals "ethereum.cancun.vm.stack" "pop". +Axiom ethereum_cancun_vm_stack_imports_push : + IsImported globals "ethereum.cancun.vm.stack" "push". + +Definition block_hash : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Push the hash of one of the 256 most recent complete blocks onto the + stack. The block number to hash is present at the top of the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + Raises + ------ + :py:class:`~ethereum.cancun.vm.exceptions.StackUnderflowError` + If `len(stack)` is less than `1`. + :py:class:`~ethereum.cancun.vm.exceptions.OutOfGasError` + If `evm.gas_left` is less than `20`. + " in + let _ := M.assign_local (| + "block_number" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_BLOCK_HASH" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + BoolOp.or (| + Compare.lt_e (| + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "env" |), "number" |), + M.get_name (| globals, "block_number" |) + |), + ltac:(M.monadic ( + Compare.gt (| + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "env" |), "number" |), + BinOp.add (| + M.get_name (| globals, "block_number" |), + Constant.int 256 + |) + |) + )) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "hash" , + Constant.bytes "00" + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "hash" , + M.get_subscript (| + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "env" |), "block_hashes" |), + UnOp.sub (| BinOp.sub (| + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "env" |), "number" |), + M.get_name (| globals, "block_number" |) + |) |) + |) + |) in + M.pure Constant.None_ + )) |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.call (| + M.get_field (| M.get_name (| globals, "U256" |), "from_be_bytes" |), + make_list [ + M.get_name (| globals, "hash" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition coinbase : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Push the current block's beneficiary address (address of the block miner) + onto the stack. + + Here the current block refers to the block in which the currently + executing transaction/call resides. + + Parameters + ---------- + evm : + The current EVM frame. + + Raises + ------ + :py:class:`~ethereum.cancun.vm.exceptions.StackOverflowError` + If `len(stack)` is equal to `1024`. + :py:class:`~ethereum.cancun.vm.exceptions.OutOfGasError` + If `evm.gas_left` is less than `2`. + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_BASE" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.call (| + M.get_field (| M.get_name (| globals, "U256" |), "from_be_bytes" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "env" |), "coinbase" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition timestamp : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Push the current block's timestamp onto the stack. Here the timestamp + being referred is actually the unix timestamp in seconds. + + Here the current block refers to the block in which the currently + executing transaction/call resides. + + Parameters + ---------- + evm : + The current EVM frame. + + Raises + ------ + :py:class:`~ethereum.cancun.vm.exceptions.StackOverflowError` + If `len(stack)` is equal to `1024`. + :py:class:`~ethereum.cancun.vm.exceptions.OutOfGasError` + If `evm.gas_left` is less than `2`. + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_BASE" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "env" |), "time" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition number : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Push the current block's number onto the stack. + + Here the current block refers to the block in which the currently + executing transaction/call resides. + + Parameters + ---------- + evm : + The current EVM frame. + + Raises + ------ + :py:class:`~ethereum.cancun.vm.exceptions.StackOverflowError` + If `len(stack)` is equal to `1024`. + :py:class:`~ethereum.cancun.vm.exceptions.OutOfGasError` + If `evm.gas_left` is less than `2`. + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_BASE" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "env" |), "number" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition prev_randao : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Push the `prev_randao` value onto the stack. + + The `prev_randao` value is the random output of the beacon chain's + randomness oracle for the previous block. + + Parameters + ---------- + evm : + The current EVM frame. + + Raises + ------ + :py:class:`~ethereum.cancun.vm.exceptions.StackOverflowError` + If `len(stack)` is equal to `1024`. + :py:class:`~ethereum.cancun.vm.exceptions.OutOfGasError` + If `evm.gas_left` is less than `2`. + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_BASE" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.call (| + M.get_field (| M.get_name (| globals, "U256" |), "from_be_bytes" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "env" |), "prev_randao" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition gas_limit : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Push the current block's gas limit onto the stack. + + Here the current block refers to the block in which the currently + executing transaction/call resides. + + Parameters + ---------- + evm : + The current EVM frame. + + Raises + ------ + :py:class:`~ethereum.cancun.vm.exceptions.StackOverflowError` + If `len(stack)` is equal to `1024`. + :py:class:`~ethereum.cancun.vm.exceptions.OutOfGasError` + If `evm.gas_left` is less than `2`. + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_BASE" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "env" |), "gas_limit" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition chain_id : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Push the chain id onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + Raises + ------ + :py:class:`~ethereum.cancun.vm.exceptions.StackOverflowError` + If `len(stack)` is equal to `1024`. + :py:class:`~ethereum.cancun.vm.exceptions.OutOfGasError` + If `evm.gas_left` is less than `2`. + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_BASE" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "env" |), "chain_id" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). diff --git a/CoqOfPython/ethereum/cancun/vm/instructions/comparison.v b/CoqOfPython/ethereum/cancun/vm/instructions/comparison.v new file mode 100644 index 0000000..a80ba14 --- /dev/null +++ b/CoqOfPython/ethereum/cancun/vm/instructions/comparison.v @@ -0,0 +1,452 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.cancun.vm.instructions.comparison". + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) Comparison Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM Comparison instructions. +". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". + +Axiom ethereum_cancun_vm_imports_Evm : + IsImported globals "ethereum.cancun.vm" "Evm". + +Axiom ethereum_cancun_vm_gas_imports_GAS_VERY_LOW : + IsImported globals "ethereum.cancun.vm.gas" "GAS_VERY_LOW". +Axiom ethereum_cancun_vm_gas_imports_charge_gas : + IsImported globals "ethereum.cancun.vm.gas" "charge_gas". + +Axiom ethereum_cancun_vm_stack_imports_pop : + IsImported globals "ethereum.cancun.vm.stack" "pop". +Axiom ethereum_cancun_vm_stack_imports_push : + IsImported globals "ethereum.cancun.vm.stack" "push". + +Definition less_than : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Checks if the top element is less than the next top element. Pushes the + result back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "left" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "right" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_VERY_LOW" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "result" , + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Compare.lt (| + M.get_name (| globals, "left" |), + M.get_name (| globals, "right" |) + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.get_name (| globals, "result" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition signed_less_than : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Signed less-than comparison. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "left" , + M.call (| + M.get_field (| M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |), "to_signed" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "right" , + M.call (| + M.get_field (| M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |), "to_signed" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_VERY_LOW" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "result" , + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Compare.lt (| + M.get_name (| globals, "left" |), + M.get_name (| globals, "right" |) + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.get_name (| globals, "result" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition greater_than : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Checks if the top element is greater than the next top element. Pushes + the result back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "left" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "right" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_VERY_LOW" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "result" , + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Compare.gt (| + M.get_name (| globals, "left" |), + M.get_name (| globals, "right" |) + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.get_name (| globals, "result" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition signed_greater_than : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Signed greater-than comparison. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "left" , + M.call (| + M.get_field (| M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |), "to_signed" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "right" , + M.call (| + M.get_field (| M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |), "to_signed" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_VERY_LOW" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "result" , + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Compare.gt (| + M.get_name (| globals, "left" |), + M.get_name (| globals, "right" |) + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.get_name (| globals, "result" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition equal : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Checks if the top element is equal to the next top element. Pushes + the result back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "left" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "right" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_VERY_LOW" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "result" , + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Compare.eq (| + M.get_name (| globals, "left" |), + M.get_name (| globals, "right" |) + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.get_name (| globals, "result" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition is_zero : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Checks if the top element is equal to 0. Pushes the result back on the + stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "x" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_VERY_LOW" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "result" , + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Compare.eq (| + M.get_name (| globals, "x" |), + Constant.int 0 + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.get_name (| globals, "result" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). diff --git a/CoqOfPython/ethereum/cancun/vm/instructions/control_flow.v b/CoqOfPython/ethereum/cancun/vm/instructions/control_flow.v new file mode 100644 index 0000000..ac1ba96 --- /dev/null +++ b/CoqOfPython/ethereum/cancun/vm/instructions/control_flow.v @@ -0,0 +1,350 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.cancun.vm.instructions.control_flow". + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) Control Flow Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM control flow instructions. +". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". + +Axiom ethereum_cancun_vm_gas_imports_GAS_BASE : + IsImported globals "ethereum.cancun.vm.gas" "GAS_BASE". +Axiom ethereum_cancun_vm_gas_imports_GAS_HIGH : + IsImported globals "ethereum.cancun.vm.gas" "GAS_HIGH". +Axiom ethereum_cancun_vm_gas_imports_GAS_JUMPDEST : + IsImported globals "ethereum.cancun.vm.gas" "GAS_JUMPDEST". +Axiom ethereum_cancun_vm_gas_imports_GAS_MID : + IsImported globals "ethereum.cancun.vm.gas" "GAS_MID". +Axiom ethereum_cancun_vm_gas_imports_charge_gas : + IsImported globals "ethereum.cancun.vm.gas" "charge_gas". + +Axiom ethereum_cancun_vm_imports_Evm : + IsImported globals "ethereum.cancun.vm" "Evm". + +Axiom ethereum_cancun_vm_exceptions_imports_InvalidJumpDestError : + IsImported globals "ethereum.cancun.vm.exceptions" "InvalidJumpDestError". + +Axiom ethereum_cancun_vm_stack_imports_pop : + IsImported globals "ethereum.cancun.vm.stack" "pop". +Axiom ethereum_cancun_vm_stack_imports_push : + IsImported globals "ethereum.cancun.vm.stack" "push". + +Definition stop : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Stop further execution of EVM code. + + Parameters + ---------- + evm : + The current EVM frame. + " in + let _ := M.pass (| |) in + let _ := M.pass (| |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, "evm" |), "running" |), + Constant.bool false + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition jump : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Alter the program counter to the location specified by the top of the + stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "jump_dest" , + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_MID" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.not_in (| + M.get_name (| globals, "jump_dest" |), + M.get_field (| M.get_name (| globals, "evm" |), "valid_jump_destinations" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, "InvalidJumpDestError" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.get_name (| globals, "jump_dest" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Definition jumpi : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Alter the program counter to the specified location if and only if a + condition is true. If the condition is not true, then the program counter + would increase only by 1. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "jump_dest" , + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "conditional_value" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_HIGH" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, "conditional_value" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "destination" , + BinOp.add (| + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + Compare.not_in (| + M.get_name (| globals, "jump_dest" |), + M.get_field (| M.get_name (| globals, "evm" |), "valid_jump_destinations" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, "InvalidJumpDestError" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "destination" , + M.get_name (| globals, "jump_dest" |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )) |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.get_name (| globals, "destination" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Definition pc : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Push onto the stack the value of the program counter after reaching the + current instruction and without increasing it for the next instruction. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_BASE" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "pc" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition gas_left : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Push the amount of available gas (including the corresponding reduction + for the cost of this instruction) onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_BASE" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "gas_left" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition jumpdest : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Mark a valid destination for jumps. This is a noop, present only + to be used by `JUMP` and `JUMPI` opcodes to verify that their jump is + valid. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_JUMPDEST" |) + ], + make_dict [] + |) in + let _ := M.pass (| |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). diff --git a/CoqOfPython/ethereum/cancun/vm/instructions/environment.v b/CoqOfPython/ethereum/cancun/vm/instructions/environment.v new file mode 100644 index 0000000..ab22c8e --- /dev/null +++ b/CoqOfPython/ethereum/cancun/vm/instructions/environment.v @@ -0,0 +1,1678 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.cancun.vm.instructions.environment". + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) Environmental Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM environment related instructions. +". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_Bytes32 : + IsImported globals "ethereum.base_types" "Bytes32". +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". + +Axiom ethereum_crypto_hash_imports_keccak256 : + IsImported globals "ethereum.crypto.hash" "keccak256". + +Axiom ethereum_utils_ensure_imports_ensure : + IsImported globals "ethereum.utils.ensure" "ensure". + +Axiom ethereum_utils_numeric_imports_ceil32 : + IsImported globals "ethereum.utils.numeric" "ceil32". + +Axiom ethereum_cancun_fork_types_imports_EMPTY_ACCOUNT : + IsImported globals "ethereum.cancun.fork_types" "EMPTY_ACCOUNT". + +Axiom ethereum_cancun_state_imports_get_account : + IsImported globals "ethereum.cancun.state" "get_account". + +Axiom ethereum_cancun_utils_address_imports_to_address : + IsImported globals "ethereum.cancun.utils.address" "to_address". + +Axiom ethereum_cancun_vm_memory_imports_buffer_read : + IsImported globals "ethereum.cancun.vm.memory" "buffer_read". +Axiom ethereum_cancun_vm_memory_imports_memory_write : + IsImported globals "ethereum.cancun.vm.memory" "memory_write". + +Axiom ethereum_cancun_vm_imports_Evm : + IsImported globals "ethereum.cancun.vm" "Evm". + +Axiom ethereum_cancun_vm_exceptions_imports_OutOfBoundsRead : + IsImported globals "ethereum.cancun.vm.exceptions" "OutOfBoundsRead". + +Axiom ethereum_cancun_vm_gas_imports_GAS_BASE : + IsImported globals "ethereum.cancun.vm.gas" "GAS_BASE". +Axiom ethereum_cancun_vm_gas_imports_GAS_BLOBHASH_OPCODE : + IsImported globals "ethereum.cancun.vm.gas" "GAS_BLOBHASH_OPCODE". +Axiom ethereum_cancun_vm_gas_imports_GAS_COLD_ACCOUNT_ACCESS : + IsImported globals "ethereum.cancun.vm.gas" "GAS_COLD_ACCOUNT_ACCESS". +Axiom ethereum_cancun_vm_gas_imports_GAS_COPY : + IsImported globals "ethereum.cancun.vm.gas" "GAS_COPY". +Axiom ethereum_cancun_vm_gas_imports_GAS_FAST_STEP : + IsImported globals "ethereum.cancun.vm.gas" "GAS_FAST_STEP". +Axiom ethereum_cancun_vm_gas_imports_GAS_RETURN_DATA_COPY : + IsImported globals "ethereum.cancun.vm.gas" "GAS_RETURN_DATA_COPY". +Axiom ethereum_cancun_vm_gas_imports_GAS_VERY_LOW : + IsImported globals "ethereum.cancun.vm.gas" "GAS_VERY_LOW". +Axiom ethereum_cancun_vm_gas_imports_GAS_WARM_ACCESS : + IsImported globals "ethereum.cancun.vm.gas" "GAS_WARM_ACCESS". +Axiom ethereum_cancun_vm_gas_imports_calculate_blob_gas_price : + IsImported globals "ethereum.cancun.vm.gas" "calculate_blob_gas_price". +Axiom ethereum_cancun_vm_gas_imports_calculate_gas_extend_memory : + IsImported globals "ethereum.cancun.vm.gas" "calculate_gas_extend_memory". +Axiom ethereum_cancun_vm_gas_imports_charge_gas : + IsImported globals "ethereum.cancun.vm.gas" "charge_gas". + +Axiom ethereum_cancun_vm_stack_imports_pop : + IsImported globals "ethereum.cancun.vm.stack" "pop". +Axiom ethereum_cancun_vm_stack_imports_push : + IsImported globals "ethereum.cancun.vm.stack" "push". + +Definition address : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Pushes the address of the current executing account to the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_BASE" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.call (| + M.get_field (| M.get_name (| globals, "U256" |), "from_be_bytes" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "current_target" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition balance : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Pushes the balance of the given account onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "address" , + M.call (| + M.get_name (| globals, "to_address" |), + make_list [ + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.in_ (| + M.get_name (| globals, "address" |), + M.get_field (| M.get_name (| globals, "evm" |), "accessed_addresses" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_WARM_ACCESS" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "accessed_addresses" |), "add" |), + make_list [ + M.get_name (| globals, "address" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_COLD_ACCOUNT_ACCESS" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "balance" , + M.get_field (| M.call (| + M.get_name (| globals, "get_account" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "env" |), "state" |); + M.get_name (| globals, "address" |) + ], + make_dict [] + |), "balance" |) + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.get_name (| globals, "balance" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition origin : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Pushes the address of the original transaction sender to the stack. + The origin address can only be an EOA. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_BASE" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.call (| + M.get_field (| M.get_name (| globals, "U256" |), "from_be_bytes" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "env" |), "origin" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition caller : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Pushes the address of the caller onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_BASE" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.call (| + M.get_field (| M.get_name (| globals, "U256" |), "from_be_bytes" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "caller" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition callvalue : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Push the value (in wei) sent with the call onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_BASE" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "value" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition calldataload : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Push a word (32 bytes) of the input data belonging to the current + environment onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "start_index" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_VERY_LOW" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "value" , + M.call (| + M.get_name (| globals, "buffer_read" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "data" |); + M.get_name (| globals, "start_index" |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 32 + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.call (| + M.get_field (| M.get_name (| globals, "U256" |), "from_be_bytes" |), + make_list [ + M.get_name (| globals, "value" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition calldatasize : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Push the size of input data in current environment onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_BASE" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "data" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition calldatacopy : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Copy a portion of the input data in current environment to memory. + + This will also expand the memory, in case that the memory is insufficient + to store the data. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "memory_start_index" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "data_start_index" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "size" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "words" , + BinOp.floor_div (| + M.call (| + M.get_name (| globals, "ceil32" |), + make_list [ + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.get_name (| globals, "size" |) + ], + make_dict [] + |) + ], + make_dict [] + |), + Constant.int 32 + |) + |) in + let _ := M.assign_local (| + "copy_gas_cost" , + BinOp.mult (| + M.get_name (| globals, "GAS_COPY" |), + M.get_name (| globals, "words" |) + |) + |) in + let _ := M.assign_local (| + "extend_memory" , + M.call (| + M.get_name (| globals, "calculate_gas_extend_memory" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "memory" |); + make_list [ + make_tuple [ M.get_name (| globals, "memory_start_index" |); M.get_name (| globals, "size" |) ] + ] + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + BinOp.add (| + BinOp.add (| + M.get_name (| globals, "GAS_VERY_LOW" |), + M.get_name (| globals, "copy_gas_cost" |) + |), + M.get_field (| M.get_name (| globals, "extend_memory" |), "cost" |) + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "memory" |), + BinOp.mult (| + Constant.bytes "00", + M.get_field (| M.get_name (| globals, "extend_memory" |), "expand_by" |) + |) + |) in + let _ := M.assign_local (| + "value" , + M.call (| + M.get_name (| globals, "buffer_read" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "data" |); + M.get_name (| globals, "data_start_index" |); + M.get_name (| globals, "size" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "memory_write" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "memory" |); + M.get_name (| globals, "memory_start_index" |); + M.get_name (| globals, "value" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition codesize : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Push the size of code running in current environment onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_BASE" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "code" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition codecopy : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Copy a portion of the code in current environment to memory. + + This will also expand the memory, in case that the memory is insufficient + to store the data. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "memory_start_index" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "code_start_index" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "size" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "words" , + BinOp.floor_div (| + M.call (| + M.get_name (| globals, "ceil32" |), + make_list [ + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.get_name (| globals, "size" |) + ], + make_dict [] + |) + ], + make_dict [] + |), + Constant.int 32 + |) + |) in + let _ := M.assign_local (| + "copy_gas_cost" , + BinOp.mult (| + M.get_name (| globals, "GAS_COPY" |), + M.get_name (| globals, "words" |) + |) + |) in + let _ := M.assign_local (| + "extend_memory" , + M.call (| + M.get_name (| globals, "calculate_gas_extend_memory" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "memory" |); + make_list [ + make_tuple [ M.get_name (| globals, "memory_start_index" |); M.get_name (| globals, "size" |) ] + ] + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + BinOp.add (| + BinOp.add (| + M.get_name (| globals, "GAS_VERY_LOW" |), + M.get_name (| globals, "copy_gas_cost" |) + |), + M.get_field (| M.get_name (| globals, "extend_memory" |), "cost" |) + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "memory" |), + BinOp.mult (| + Constant.bytes "00", + M.get_field (| M.get_name (| globals, "extend_memory" |), "expand_by" |) + |) + |) in + let _ := M.assign_local (| + "value" , + M.call (| + M.get_name (| globals, "buffer_read" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "code" |); + M.get_name (| globals, "code_start_index" |); + M.get_name (| globals, "size" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "memory_write" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "memory" |); + M.get_name (| globals, "memory_start_index" |); + M.get_name (| globals, "value" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition gasprice : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Push the gas price used in current environment onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_BASE" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "env" |), "gas_price" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition extcodesize : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Push the code size of a given account onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "address" , + M.call (| + M.get_name (| globals, "to_address" |), + make_list [ + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.in_ (| + M.get_name (| globals, "address" |), + M.get_field (| M.get_name (| globals, "evm" |), "accessed_addresses" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_WARM_ACCESS" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "accessed_addresses" |), "add" |), + make_list [ + M.get_name (| globals, "address" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_COLD_ACCOUNT_ACCESS" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "codesize" , + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_field (| M.call (| + M.get_name (| globals, "get_account" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "env" |), "state" |); + M.get_name (| globals, "address" |) + ], + make_dict [] + |), "code" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.get_name (| globals, "codesize" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition extcodecopy : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Copy a portion of an account's code to memory. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "address" , + M.call (| + M.get_name (| globals, "to_address" |), + make_list [ + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_start_index" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "code_start_index" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "size" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "words" , + BinOp.floor_div (| + M.call (| + M.get_name (| globals, "ceil32" |), + make_list [ + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.get_name (| globals, "size" |) + ], + make_dict [] + |) + ], + make_dict [] + |), + Constant.int 32 + |) + |) in + let _ := M.assign_local (| + "copy_gas_cost" , + BinOp.mult (| + M.get_name (| globals, "GAS_COPY" |), + M.get_name (| globals, "words" |) + |) + |) in + let _ := M.assign_local (| + "extend_memory" , + M.call (| + M.get_name (| globals, "calculate_gas_extend_memory" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "memory" |); + make_list [ + make_tuple [ M.get_name (| globals, "memory_start_index" |); M.get_name (| globals, "size" |) ] + ] + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.in_ (| + M.get_name (| globals, "address" |), + M.get_field (| M.get_name (| globals, "evm" |), "accessed_addresses" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + BinOp.add (| + BinOp.add (| + M.get_name (| globals, "GAS_WARM_ACCESS" |), + M.get_name (| globals, "copy_gas_cost" |) + |), + M.get_field (| M.get_name (| globals, "extend_memory" |), "cost" |) + |) + ], + make_dict [] + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "accessed_addresses" |), "add" |), + make_list [ + M.get_name (| globals, "address" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + BinOp.add (| + BinOp.add (| + M.get_name (| globals, "GAS_COLD_ACCOUNT_ACCESS" |), + M.get_name (| globals, "copy_gas_cost" |) + |), + M.get_field (| M.get_name (| globals, "extend_memory" |), "cost" |) + |) + ], + make_dict [] + |) in + M.pure Constant.None_ + )) |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "memory" |), + BinOp.mult (| + Constant.bytes "00", + M.get_field (| M.get_name (| globals, "extend_memory" |), "expand_by" |) + |) + |) in + let _ := M.assign_local (| + "code" , + M.get_field (| M.call (| + M.get_name (| globals, "get_account" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "env" |), "state" |); + M.get_name (| globals, "address" |) + ], + make_dict [] + |), "code" |) + |) in + let _ := M.assign_local (| + "value" , + M.call (| + M.get_name (| globals, "buffer_read" |), + make_list [ + M.get_name (| globals, "code" |); + M.get_name (| globals, "code_start_index" |); + M.get_name (| globals, "size" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "memory_write" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "memory" |); + M.get_name (| globals, "memory_start_index" |); + M.get_name (| globals, "value" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition returndatasize : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Pushes the size of the return data buffer onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_BASE" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "return_data" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition returndatacopy : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Copies data from the return data buffer code to memory + + Parameters + ---------- + evm : + The current EVM frame. + " in + let _ := M.assign_local (| + "memory_start_index" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "return_data_start_position" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "size" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "words" , + BinOp.floor_div (| + M.call (| + M.get_name (| globals, "ceil32" |), + make_list [ + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.get_name (| globals, "size" |) + ], + make_dict [] + |) + ], + make_dict [] + |), + Constant.int 32 + |) + |) in + let _ := M.assign_local (| + "copy_gas_cost" , + BinOp.mult (| + M.get_name (| globals, "GAS_RETURN_DATA_COPY" |), + M.get_name (| globals, "words" |) + |) + |) in + let _ := M.assign_local (| + "extend_memory" , + M.call (| + M.get_name (| globals, "calculate_gas_extend_memory" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "memory" |); + make_list [ + make_tuple [ M.get_name (| globals, "memory_start_index" |); M.get_name (| globals, "size" |) ] + ] + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + BinOp.add (| + BinOp.add (| + M.get_name (| globals, "GAS_VERY_LOW" |), + M.get_name (| globals, "copy_gas_cost" |) + |), + M.get_field (| M.get_name (| globals, "extend_memory" |), "cost" |) + |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + Compare.lt_e (| + BinOp.add (| + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.get_name (| globals, "return_data_start_position" |) + ], + make_dict [] + |), + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.get_name (| globals, "size" |) + ], + make_dict [] + |) + |), + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "return_data" |) + ], + make_dict [] + |) + |); + M.get_name (| globals, "OutOfBoundsRead" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "memory" |), + BinOp.mult (| + Constant.bytes "00", + M.get_field (| M.get_name (| globals, "extend_memory" |), "expand_by" |) + |) + |) in + let _ := M.assign_local (| + "value" , + M.slice (| + M.get_field (| M.get_name (| globals, "evm" |), "return_data" |), + M.get_name (| globals, "return_data_start_position" |), + BinOp.add (| + M.get_name (| globals, "return_data_start_position" |), + M.get_name (| globals, "size" |) + |), + Constant.None_ + |) + |) in + let _ := M.call (| + M.get_name (| globals, "memory_write" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "memory" |); + M.get_name (| globals, "memory_start_index" |); + M.get_name (| globals, "value" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition extcodehash : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Returns the keccak256 hash of a contract’s bytecode + Parameters + ---------- + evm : + The current EVM frame. + " in + let _ := M.assign_local (| + "address" , + M.call (| + M.get_name (| globals, "to_address" |), + make_list [ + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.in_ (| + M.get_name (| globals, "address" |), + M.get_field (| M.get_name (| globals, "evm" |), "accessed_addresses" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_WARM_ACCESS" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "accessed_addresses" |), "add" |), + make_list [ + M.get_name (| globals, "address" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_COLD_ACCOUNT_ACCESS" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "account" , + M.call (| + M.get_name (| globals, "get_account" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "env" |), "state" |); + M.get_name (| globals, "address" |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, "account" |), + M.get_name (| globals, "EMPTY_ACCOUNT" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "codehash" , + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "codehash" , + M.call (| + M.get_field (| M.get_name (| globals, "U256" |), "from_be_bytes" |), + make_list [ + M.call (| + M.get_name (| globals, "keccak256" |), + make_list [ + M.get_field (| M.get_name (| globals, "account" |), "code" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + )) |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.get_name (| globals, "codehash" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition self_balance : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Pushes the balance of the current address to the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_FAST_STEP" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "balance" , + M.get_field (| M.call (| + M.get_name (| globals, "get_account" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "env" |), "state" |); + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "current_target" |) + ], + make_dict [] + |), "balance" |) + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.get_name (| globals, "balance" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition base_fee : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Pushes the base fee of the current block on to the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_BASE" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "env" |), "base_fee_per_gas" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition blob_hash : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Pushes the versioned hash at a particular index on to the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "index" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_BLOBHASH_OPCODE" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.lt (| + M.get_name (| globals, "index" |), + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "env" |), "blob_versioned_hashes" |) + ], + make_dict [] + |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "blob_hash" , + M.get_subscript (| + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "env" |), "blob_versioned_hashes" |), + M.get_name (| globals, "index" |) + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "blob_hash" , + M.call (| + M.get_name (| globals, "Bytes32" |), + make_list [ + BinOp.mult (| + Constant.bytes "00", + Constant.int 32 + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + )) |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.call (| + M.get_field (| M.get_name (| globals, "U256" |), "from_be_bytes" |), + make_list [ + M.get_name (| globals, "blob_hash" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition blob_base_fee : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Pushes the blob base fee on to the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_BASE" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "blob_base_fee" , + M.call (| + M.get_name (| globals, "calculate_blob_gas_price" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "env" |), "excess_blob_gas" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + M.get_name (| globals, "blob_base_fee" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). diff --git a/CoqOfPython/ethereum/cancun/vm/instructions/keccak.v b/CoqOfPython/ethereum/cancun/vm/instructions/keccak.v new file mode 100644 index 0000000..03a31d2 --- /dev/null +++ b/CoqOfPython/ethereum/cancun/vm/instructions/keccak.v @@ -0,0 +1,188 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.cancun.vm.instructions.keccak". + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) Keccak Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM keccak instructions. +". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". + +Axiom ethereum_crypto_hash_imports_keccak256 : + IsImported globals "ethereum.crypto.hash" "keccak256". + +Axiom ethereum_utils_numeric_imports_ceil32 : + IsImported globals "ethereum.utils.numeric" "ceil32". + +Axiom ethereum_cancun_vm_imports_Evm : + IsImported globals "ethereum.cancun.vm" "Evm". + +Axiom ethereum_cancun_vm_gas_imports_GAS_KECCAK256 : + IsImported globals "ethereum.cancun.vm.gas" "GAS_KECCAK256". +Axiom ethereum_cancun_vm_gas_imports_GAS_KECCAK256_WORD : + IsImported globals "ethereum.cancun.vm.gas" "GAS_KECCAK256_WORD". +Axiom ethereum_cancun_vm_gas_imports_calculate_gas_extend_memory : + IsImported globals "ethereum.cancun.vm.gas" "calculate_gas_extend_memory". +Axiom ethereum_cancun_vm_gas_imports_charge_gas : + IsImported globals "ethereum.cancun.vm.gas" "charge_gas". + +Axiom ethereum_cancun_vm_memory_imports_memory_read_bytes : + IsImported globals "ethereum.cancun.vm.memory" "memory_read_bytes". + +Axiom ethereum_cancun_vm_stack_imports_pop : + IsImported globals "ethereum.cancun.vm.stack" "pop". +Axiom ethereum_cancun_vm_stack_imports_push : + IsImported globals "ethereum.cancun.vm.stack" "push". + +Definition keccak : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Pushes to the stack the Keccak-256 hash of a region of memory. + + This also expands the memory, in case the memory is insufficient to + access the data's memory location. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "memory_start_index" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "size" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "words" , + BinOp.floor_div (| + M.call (| + M.get_name (| globals, "ceil32" |), + make_list [ + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.get_name (| globals, "size" |) + ], + make_dict [] + |) + ], + make_dict [] + |), + Constant.int 32 + |) + |) in + let _ := M.assign_local (| + "word_gas_cost" , + BinOp.mult (| + M.get_name (| globals, "GAS_KECCAK256_WORD" |), + M.get_name (| globals, "words" |) + |) + |) in + let _ := M.assign_local (| + "extend_memory" , + M.call (| + M.get_name (| globals, "calculate_gas_extend_memory" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "memory" |); + make_list [ + make_tuple [ M.get_name (| globals, "memory_start_index" |); M.get_name (| globals, "size" |) ] + ] + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + BinOp.add (| + BinOp.add (| + M.get_name (| globals, "GAS_KECCAK256" |), + M.get_name (| globals, "word_gas_cost" |) + |), + M.get_field (| M.get_name (| globals, "extend_memory" |), "cost" |) + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "memory" |), + BinOp.mult (| + Constant.bytes "00", + M.get_field (| M.get_name (| globals, "extend_memory" |), "expand_by" |) + |) + |) in + let _ := M.assign_local (| + "data" , + M.call (| + M.get_name (| globals, "memory_read_bytes" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "memory" |); + M.get_name (| globals, "memory_start_index" |); + M.get_name (| globals, "size" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "hash" , + M.call (| + M.get_name (| globals, "keccak256" |), + make_list [ + M.get_name (| globals, "data" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.call (| + M.get_field (| M.get_name (| globals, "U256" |), "from_be_bytes" |), + make_list [ + M.get_name (| globals, "hash" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). diff --git a/CoqOfPython/ethereum/cancun/vm/instructions/log.v b/CoqOfPython/ethereum/cancun/vm/instructions/log.v new file mode 100644 index 0000000..cfc4c02 --- /dev/null +++ b/CoqOfPython/ethereum/cancun/vm/instructions/log.v @@ -0,0 +1,256 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.cancun.vm.instructions.log". + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) Logging Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM logging instructions. +". + +Axiom functools_imports_partial : + IsImported globals "functools" "partial". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". + +Axiom ethereum_utils_ensure_imports_ensure : + IsImported globals "ethereum.utils.ensure" "ensure". + +Axiom ethereum_cancun_blocks_imports_Log : + IsImported globals "ethereum.cancun.blocks" "Log". + +Axiom ethereum_cancun_vm_imports_Evm : + IsImported globals "ethereum.cancun.vm" "Evm". + +Axiom ethereum_cancun_vm_exceptions_imports_WriteInStaticContext : + IsImported globals "ethereum.cancun.vm.exceptions" "WriteInStaticContext". + +Axiom ethereum_cancun_vm_gas_imports_GAS_LOG : + IsImported globals "ethereum.cancun.vm.gas" "GAS_LOG". +Axiom ethereum_cancun_vm_gas_imports_GAS_LOG_DATA : + IsImported globals "ethereum.cancun.vm.gas" "GAS_LOG_DATA". +Axiom ethereum_cancun_vm_gas_imports_GAS_LOG_TOPIC : + IsImported globals "ethereum.cancun.vm.gas" "GAS_LOG_TOPIC". +Axiom ethereum_cancun_vm_gas_imports_calculate_gas_extend_memory : + IsImported globals "ethereum.cancun.vm.gas" "calculate_gas_extend_memory". +Axiom ethereum_cancun_vm_gas_imports_charge_gas : + IsImported globals "ethereum.cancun.vm.gas" "charge_gas". + +Axiom ethereum_cancun_vm_memory_imports_memory_read_bytes : + IsImported globals "ethereum.cancun.vm.memory" "memory_read_bytes". + +Axiom ethereum_cancun_vm_stack_imports_pop : + IsImported globals "ethereum.cancun.vm.stack" "pop". + +Definition log_n : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm"; "num_topics" ] |) in + let _ := Constant.str " + Appends a log entry, having `num_topics` topics, to the evm logs. + + This will also expand the memory if the data (required by the log entry) + corresponding to the memory is not accessible. + + Parameters + ---------- + evm : + The current EVM frame. + num_topics : + The number of topics to be included in the log entry. + + " in + let _ := M.assign_local (| + "memory_start_index" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "size" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "topics" , + make_list [] + |) in + let _ := + M.for_ (| + M.get_name (| globals, "_" |), + M.call (| + M.get_name (| globals, "range" |), + make_list [ + M.get_name (| globals, "num_topics" |) + ], + make_dict [] + |), + ltac:(M.monadic ( + let _ := M.assign_local (| + "topic" , + M.call (| + M.get_field (| M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |), "to_be_bytes32" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_field (| M.get_name (| globals, "topics" |), "append" |), + make_list [ + M.get_name (| globals, "topic" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := M.assign_local (| + "extend_memory" , + M.call (| + M.get_name (| globals, "calculate_gas_extend_memory" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "memory" |); + make_list [ + make_tuple [ M.get_name (| globals, "memory_start_index" |); M.get_name (| globals, "size" |) ] + ] + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + BinOp.add (| + BinOp.add (| + BinOp.add (| + M.get_name (| globals, "GAS_LOG" |), + BinOp.mult (| + M.get_name (| globals, "GAS_LOG_DATA" |), + M.get_name (| globals, "size" |) + |) + |), + BinOp.mult (| + M.get_name (| globals, "GAS_LOG_TOPIC" |), + M.get_name (| globals, "num_topics" |) + |) + |), + M.get_field (| M.get_name (| globals, "extend_memory" |), "cost" |) + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "memory" |), + BinOp.mult (| + Constant.bytes "00", + M.get_field (| M.get_name (| globals, "extend_memory" |), "expand_by" |) + |) + |) in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + UnOp.not (| M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "is_static" |) |); + M.get_name (| globals, "WriteInStaticContext" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "log_entry" , + M.call (| + M.get_name (| globals, "Log" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, "evm" |), "logs" |), + BinOp.add (| + M.get_field (| M.get_name (| globals, "evm" |), "logs" |), + make_tuple [ M.get_name (| globals, "log_entry" |) ] + |) + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition log0 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "log_n" |) + ], + make_dict [] + |) +)). + +Definition log1 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "log_n" |) + ], + make_dict [] + |) +)). + +Definition log2 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "log_n" |) + ], + make_dict [] + |) +)). + +Definition log3 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "log_n" |) + ], + make_dict [] + |) +)). + +Definition log4 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "log_n" |) + ], + make_dict [] + |) +)). diff --git a/CoqOfPython/ethereum/cancun/vm/instructions/memory.v b/CoqOfPython/ethereum/cancun/vm/instructions/memory.v new file mode 100644 index 0000000..acd8e09 --- /dev/null +++ b/CoqOfPython/ethereum/cancun/vm/instructions/memory.v @@ -0,0 +1,532 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.cancun.vm.instructions.memory". + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) Memory Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM Memory instructions. +". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_Bytes : + IsImported globals "ethereum.base_types" "Bytes". +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". + +Axiom ethereum_utils_numeric_imports_ceil32 : + IsImported globals "ethereum.utils.numeric" "ceil32". + +Axiom ethereum_cancun_vm_imports_Evm : + IsImported globals "ethereum.cancun.vm" "Evm". + +Axiom ethereum_cancun_vm_gas_imports_GAS_BASE : + IsImported globals "ethereum.cancun.vm.gas" "GAS_BASE". +Axiom ethereum_cancun_vm_gas_imports_GAS_COPY : + IsImported globals "ethereum.cancun.vm.gas" "GAS_COPY". +Axiom ethereum_cancun_vm_gas_imports_GAS_VERY_LOW : + IsImported globals "ethereum.cancun.vm.gas" "GAS_VERY_LOW". +Axiom ethereum_cancun_vm_gas_imports_calculate_gas_extend_memory : + IsImported globals "ethereum.cancun.vm.gas" "calculate_gas_extend_memory". +Axiom ethereum_cancun_vm_gas_imports_charge_gas : + IsImported globals "ethereum.cancun.vm.gas" "charge_gas". + +Axiom ethereum_cancun_vm_memory_imports_memory_read_bytes : + IsImported globals "ethereum.cancun.vm.memory" "memory_read_bytes". +Axiom ethereum_cancun_vm_memory_imports_memory_write : + IsImported globals "ethereum.cancun.vm.memory" "memory_write". + +Axiom ethereum_cancun_vm_stack_imports_pop : + IsImported globals "ethereum.cancun.vm.stack" "pop". +Axiom ethereum_cancun_vm_stack_imports_push : + IsImported globals "ethereum.cancun.vm.stack" "push". + +Definition mstore : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Stores a word to memory. + This also expands the memory, if the memory is + insufficient to store the word. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "start_position" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "value" , + M.call (| + M.get_field (| M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |), "to_be_bytes32" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "extend_memory" , + M.call (| + M.get_name (| globals, "calculate_gas_extend_memory" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "memory" |); + make_list [ + make_tuple [ M.get_name (| globals, "start_position" |); M.call (| + M.get_name (| globals, "U256" |), + make_list [ + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_name (| globals, "value" |) + ], + make_dict [] + |) + ], + make_dict [] + |) ] + ] + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + BinOp.add (| + M.get_name (| globals, "GAS_VERY_LOW" |), + M.get_field (| M.get_name (| globals, "extend_memory" |), "cost" |) + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "memory" |), + BinOp.mult (| + Constant.bytes "00", + M.get_field (| M.get_name (| globals, "extend_memory" |), "expand_by" |) + |) + |) in + let _ := M.call (| + M.get_name (| globals, "memory_write" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "memory" |); + M.get_name (| globals, "start_position" |); + M.get_name (| globals, "value" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition mstore8 : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Stores a byte to memory. + This also expands the memory, if the memory is + insufficient to store the word. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "start_position" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "value" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "extend_memory" , + M.call (| + M.get_name (| globals, "calculate_gas_extend_memory" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "memory" |); + make_list [ + make_tuple [ M.get_name (| globals, "start_position" |); M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 1 + ], + make_dict [] + |) ] + ] + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + BinOp.add (| + M.get_name (| globals, "GAS_VERY_LOW" |), + M.get_field (| M.get_name (| globals, "extend_memory" |), "cost" |) + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "memory" |), + BinOp.mult (| + Constant.bytes "00", + M.get_field (| M.get_name (| globals, "extend_memory" |), "expand_by" |) + |) + |) in + let _ := M.assign_local (| + "normalized_bytes_value" , + M.call (| + M.get_name (| globals, "Bytes" |), + make_list [ + make_list [ + BinOp.bit_and (| + M.get_name (| globals, "value" |), + Constant.int 255 + |) + ] + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "memory_write" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "memory" |); + M.get_name (| globals, "start_position" |); + M.get_name (| globals, "normalized_bytes_value" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition mload : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Load word from memory. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "start_position" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "extend_memory" , + M.call (| + M.get_name (| globals, "calculate_gas_extend_memory" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "memory" |); + make_list [ + make_tuple [ M.get_name (| globals, "start_position" |); M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 32 + ], + make_dict [] + |) ] + ] + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + BinOp.add (| + M.get_name (| globals, "GAS_VERY_LOW" |), + M.get_field (| M.get_name (| globals, "extend_memory" |), "cost" |) + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "memory" |), + BinOp.mult (| + Constant.bytes "00", + M.get_field (| M.get_name (| globals, "extend_memory" |), "expand_by" |) + |) + |) in + let _ := M.assign_local (| + "value" , + M.call (| + M.get_field (| M.get_name (| globals, "U256" |), "from_be_bytes" |), + make_list [ + M.call (| + M.get_name (| globals, "memory_read_bytes" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "memory" |); + M.get_name (| globals, "start_position" |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 32 + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.get_name (| globals, "value" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition msize : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Push the size of active memory in bytes onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_BASE" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "memory" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition mcopy : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Copy the bytes in memory from one location to another. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "destination" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "source" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "length" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "words" , + BinOp.floor_div (| + M.call (| + M.get_name (| globals, "ceil32" |), + make_list [ + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.get_name (| globals, "length" |) + ], + make_dict [] + |) + ], + make_dict [] + |), + Constant.int 32 + |) + |) in + let _ := M.assign_local (| + "copy_gas_cost" , + BinOp.mult (| + M.get_name (| globals, "GAS_COPY" |), + M.get_name (| globals, "words" |) + |) + |) in + let _ := M.assign_local (| + "extend_memory" , + M.call (| + M.get_name (| globals, "calculate_gas_extend_memory" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "memory" |); + make_list [ + make_tuple [ M.get_name (| globals, "source" |); M.get_name (| globals, "length" |) ]; + make_tuple [ M.get_name (| globals, "destination" |); M.get_name (| globals, "length" |) ] + ] + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + BinOp.add (| + BinOp.add (| + M.get_name (| globals, "GAS_VERY_LOW" |), + M.get_name (| globals, "copy_gas_cost" |) + |), + M.get_field (| M.get_name (| globals, "extend_memory" |), "cost" |) + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "memory" |), + BinOp.mult (| + Constant.bytes "00", + M.get_field (| M.get_name (| globals, "extend_memory" |), "expand_by" |) + |) + |) in + let _ := M.assign_local (| + "value" , + M.call (| + M.get_name (| globals, "memory_read_bytes" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "memory" |); + M.get_name (| globals, "source" |); + M.get_name (| globals, "length" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "memory_write" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "memory" |); + M.get_name (| globals, "destination" |); + M.get_name (| globals, "value" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). diff --git a/CoqOfPython/ethereum/cancun/vm/instructions/stack.v b/CoqOfPython/ethereum/cancun/vm/instructions/stack.v new file mode 100644 index 0000000..aec7b04 --- /dev/null +++ b/CoqOfPython/ethereum/cancun/vm/instructions/stack.v @@ -0,0 +1,979 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.cancun.vm.instructions.stack". + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) Stack Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM stack related instructions. +". + +Axiom functools_imports_partial : + IsImported globals "functools" "partial". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". + +Axiom ethereum_utils_ensure_imports_ensure : + IsImported globals "ethereum.utils.ensure" "ensure". + +Axiom ethereum_cancun_vm_imports_Evm : + IsImported globals "ethereum.cancun.vm" "Evm". +Axiom ethereum_cancun_vm_imports_stack : + IsImported globals "ethereum.cancun.vm" "stack". + +Axiom ethereum_cancun_vm_exceptions_imports_StackUnderflowError : + IsImported globals "ethereum.cancun.vm.exceptions" "StackUnderflowError". + +Axiom ethereum_cancun_vm_gas_imports_GAS_BASE : + IsImported globals "ethereum.cancun.vm.gas" "GAS_BASE". +Axiom ethereum_cancun_vm_gas_imports_GAS_VERY_LOW : + IsImported globals "ethereum.cancun.vm.gas" "GAS_VERY_LOW". +Axiom ethereum_cancun_vm_gas_imports_charge_gas : + IsImported globals "ethereum.cancun.vm.gas" "charge_gas". + +Axiom ethereum_cancun_vm_memory_imports_buffer_read : + IsImported globals "ethereum.cancun.vm.memory" "buffer_read". + +Definition pop : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Remove item from stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.call (| + M.get_field (| M.get_name (| globals, "stack" |), "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_BASE" |) + ], + make_dict [] + |) in + let _ := M.pass (| |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition push_n : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm"; "num_bytes" ] |) in + let _ := Constant.str " + Pushes a N-byte immediate onto the stack. Push zero if num_bytes is zero. + + Parameters + ---------- + evm : + The current EVM frame. + + num_bytes : + The number of immediate bytes to be read from the code and pushed to + the stack. Push zero if num_bytes is zero. + + " in + let _ := M.pass (| |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, "num_bytes" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_BASE" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_VERY_LOW" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "data_to_push" , + M.call (| + M.get_field (| M.get_name (| globals, "U256" |), "from_be_bytes" |), + make_list [ + M.call (| + M.get_name (| globals, "buffer_read" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "code" |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + BinOp.add (| + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) + ], + make_dict [] + |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + M.get_name (| globals, "num_bytes" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_field (| M.get_name (| globals, "stack" |), "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.get_name (| globals, "data_to_push" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + BinOp.add (| + Constant.int 1, + M.get_name (| globals, "num_bytes" |) + |) + |) in + M.pure Constant.None_)). + +Definition dup_n : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm"; "item_number" ] |) in + let _ := Constant.str " + Duplicate the Nth stack item (from top of the stack) to the top of stack. + + Parameters + ---------- + evm : + The current EVM frame. + + item_number : + The stack item number (0-indexed from top of stack) to be duplicated + to the top of stack. + + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_VERY_LOW" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + Compare.lt (| + M.get_name (| globals, "item_number" |), + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |); + M.get_name (| globals, "StackUnderflowError" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "data_to_duplicate" , + M.get_subscript (| + M.get_field (| M.get_name (| globals, "evm" |), "stack" |), + BinOp.sub (| + BinOp.sub (| + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |), + Constant.int 1 + |), + M.get_name (| globals, "item_number" |) + |) + |) + |) in + let _ := M.call (| + M.get_field (| M.get_name (| globals, "stack" |), "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.get_name (| globals, "data_to_duplicate" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition swap_n : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm"; "item_number" ] |) in + let _ := Constant.str " + Swap the top and the `item_number` element of the stack, where + the top of the stack is position zero. + + If `item_number` is zero, this function does nothing (which should not be + possible, since there is no `SWAP0` instruction). + + Parameters + ---------- + evm : + The current EVM frame. + + item_number : + The stack item number (0-indexed from top of stack) to be swapped + with the top of stack element. + + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_VERY_LOW" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + Compare.lt (| + M.get_name (| globals, "item_number" |), + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |); + M.get_name (| globals, "StackUnderflowError" |) + ], + make_dict [] + |) in + let _ := M.assign (| + make_tuple [ M.get_subscript (| + M.get_field (| M.get_name (| globals, "evm" |), "stack" |), + UnOp.sub (| Constant.int 1 |) + |); M.get_subscript (| + M.get_field (| M.get_name (| globals, "evm" |), "stack" |), + BinOp.sub (| + UnOp.sub (| Constant.int 1 |), + M.get_name (| globals, "item_number" |) + |) + |) ], + make_tuple [ M.get_subscript (| + M.get_field (| M.get_name (| globals, "evm" |), "stack" |), + BinOp.sub (| + UnOp.sub (| Constant.int 1 |), + M.get_name (| globals, "item_number" |) + |) + |); M.get_subscript (| + M.get_field (| M.get_name (| globals, "evm" |), "stack" |), + UnOp.sub (| Constant.int 1 |) + |) ] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition push0 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push1 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push2 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push3 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push4 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push5 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push6 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push7 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push8 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push9 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push10 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push11 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push12 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push13 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push14 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push15 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push16 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push17 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push18 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push19 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push20 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push21 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push22 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push23 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push24 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push25 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push26 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push27 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push28 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push29 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push30 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push31 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push32 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "push_n" |) + ], + make_dict [] + |) +)). + +Definition dup1 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "dup_n" |) + ], + make_dict [] + |) +)). + +Definition dup2 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "dup_n" |) + ], + make_dict [] + |) +)). + +Definition dup3 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "dup_n" |) + ], + make_dict [] + |) +)). + +Definition dup4 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "dup_n" |) + ], + make_dict [] + |) +)). + +Definition dup5 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "dup_n" |) + ], + make_dict [] + |) +)). + +Definition dup6 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "dup_n" |) + ], + make_dict [] + |) +)). + +Definition dup7 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "dup_n" |) + ], + make_dict [] + |) +)). + +Definition dup8 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "dup_n" |) + ], + make_dict [] + |) +)). + +Definition dup9 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "dup_n" |) + ], + make_dict [] + |) +)). + +Definition dup10 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "dup_n" |) + ], + make_dict [] + |) +)). + +Definition dup11 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "dup_n" |) + ], + make_dict [] + |) +)). + +Definition dup12 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "dup_n" |) + ], + make_dict [] + |) +)). + +Definition dup13 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "dup_n" |) + ], + make_dict [] + |) +)). + +Definition dup14 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "dup_n" |) + ], + make_dict [] + |) +)). + +Definition dup15 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "dup_n" |) + ], + make_dict [] + |) +)). + +Definition dup16 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "dup_n" |) + ], + make_dict [] + |) +)). + +Definition swap1 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "swap_n" |) + ], + make_dict [] + |) +)). + +Definition swap2 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "swap_n" |) + ], + make_dict [] + |) +)). + +Definition swap3 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "swap_n" |) + ], + make_dict [] + |) +)). + +Definition swap4 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "swap_n" |) + ], + make_dict [] + |) +)). + +Definition swap5 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "swap_n" |) + ], + make_dict [] + |) +)). + +Definition swap6 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "swap_n" |) + ], + make_dict [] + |) +)). + +Definition swap7 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "swap_n" |) + ], + make_dict [] + |) +)). + +Definition swap8 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "swap_n" |) + ], + make_dict [] + |) +)). + +Definition swap9 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "swap_n" |) + ], + make_dict [] + |) +)). + +Definition swap10 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "swap_n" |) + ], + make_dict [] + |) +)). + +Definition swap11 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "swap_n" |) + ], + make_dict [] + |) +)). + +Definition swap12 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "swap_n" |) + ], + make_dict [] + |) +)). + +Definition swap13 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "swap_n" |) + ], + make_dict [] + |) +)). + +Definition swap14 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "swap_n" |) + ], + make_dict [] + |) +)). + +Definition swap15 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "swap_n" |) + ], + make_dict [] + |) +)). + +Definition swap16 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "swap_n" |) + ], + make_dict [] + |) +)). diff --git a/CoqOfPython/ethereum/cancun/vm/instructions/storage.v b/CoqOfPython/ethereum/cancun/vm/instructions/storage.v new file mode 100644 index 0000000..04025e4 --- /dev/null +++ b/CoqOfPython/ethereum/cancun/vm/instructions/storage.v @@ -0,0 +1,622 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.cancun.vm.instructions.storage". + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) Storage Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM storage related instructions. +". + +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". + +Axiom ethereum_utils_ensure_imports_ensure : + IsImported globals "ethereum.utils.ensure" "ensure". + +Axiom ethereum_cancun_state_imports_get_storage : + IsImported globals "ethereum.cancun.state" "get_storage". +Axiom ethereum_cancun_state_imports_get_storage_original : + IsImported globals "ethereum.cancun.state" "get_storage_original". +Axiom ethereum_cancun_state_imports_get_transient_storage : + IsImported globals "ethereum.cancun.state" "get_transient_storage". +Axiom ethereum_cancun_state_imports_set_storage : + IsImported globals "ethereum.cancun.state" "set_storage". +Axiom ethereum_cancun_state_imports_set_transient_storage : + IsImported globals "ethereum.cancun.state" "set_transient_storage". + +Axiom ethereum_cancun_vm_imports_Evm : + IsImported globals "ethereum.cancun.vm" "Evm". + +Axiom ethereum_cancun_vm_exceptions_imports_OutOfGasError : + IsImported globals "ethereum.cancun.vm.exceptions" "OutOfGasError". +Axiom ethereum_cancun_vm_exceptions_imports_WriteInStaticContext : + IsImported globals "ethereum.cancun.vm.exceptions" "WriteInStaticContext". + +Axiom ethereum_cancun_vm_gas_imports_GAS_CALL_STIPEND : + IsImported globals "ethereum.cancun.vm.gas" "GAS_CALL_STIPEND". +Axiom ethereum_cancun_vm_gas_imports_GAS_COLD_SLOAD : + IsImported globals "ethereum.cancun.vm.gas" "GAS_COLD_SLOAD". +Axiom ethereum_cancun_vm_gas_imports_GAS_STORAGE_CLEAR_REFUND : + IsImported globals "ethereum.cancun.vm.gas" "GAS_STORAGE_CLEAR_REFUND". +Axiom ethereum_cancun_vm_gas_imports_GAS_STORAGE_SET : + IsImported globals "ethereum.cancun.vm.gas" "GAS_STORAGE_SET". +Axiom ethereum_cancun_vm_gas_imports_GAS_STORAGE_UPDATE : + IsImported globals "ethereum.cancun.vm.gas" "GAS_STORAGE_UPDATE". +Axiom ethereum_cancun_vm_gas_imports_GAS_WARM_ACCESS : + IsImported globals "ethereum.cancun.vm.gas" "GAS_WARM_ACCESS". +Axiom ethereum_cancun_vm_gas_imports_charge_gas : + IsImported globals "ethereum.cancun.vm.gas" "charge_gas". + +Axiom ethereum_cancun_vm_stack_imports_pop : + IsImported globals "ethereum.cancun.vm.stack" "pop". +Axiom ethereum_cancun_vm_stack_imports_push : + IsImported globals "ethereum.cancun.vm.stack" "push". + +Definition sload : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Loads to the stack, the value corresponding to a certain key from the + storage of the current account. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "key" , + M.call (| + M.get_field (| M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |), "to_be_bytes32" |), + make_list [], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.in_ (| + make_tuple [ M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "current_target" |); M.get_name (| globals, "key" |) ], + M.get_field (| M.get_name (| globals, "evm" |), "accessed_storage_keys" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_WARM_ACCESS" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "accessed_storage_keys" |), "add" |), + make_list [ + make_tuple [ M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "current_target" |); M.get_name (| globals, "key" |) ] + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_COLD_SLOAD" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "value" , + M.call (| + M.get_name (| globals, "get_storage" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "env" |), "state" |); + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "current_target" |); + M.get_name (| globals, "key" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.get_name (| globals, "value" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition sstore : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Stores a value at a certain key in the current context's storage. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "key" , + M.call (| + M.get_field (| M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |), "to_be_bytes32" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "new_value" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + Compare.gt (| + M.get_field (| M.get_name (| globals, "evm" |), "gas_left" |), + M.get_name (| globals, "GAS_CALL_STIPEND" |) + |); + M.get_name (| globals, "OutOfGasError" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "original_value" , + M.call (| + M.get_name (| globals, "get_storage_original" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "env" |), "state" |); + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "current_target" |); + M.get_name (| globals, "key" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "current_value" , + M.call (| + M.get_name (| globals, "get_storage" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "env" |), "state" |); + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "current_target" |); + M.get_name (| globals, "key" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "gas_cost" , + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.not_in (| + make_tuple [ M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "current_target" |); M.get_name (| globals, "key" |) ], + M.get_field (| M.get_name (| globals, "evm" |), "accessed_storage_keys" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "accessed_storage_keys" |), "add" |), + make_list [ + make_tuple [ M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "current_target" |); M.get_name (| globals, "key" |) ] + ], + make_dict [] + |) in + let _ := M.assign_op_local (| + BinOp.add, + "gas_cost", + M.get_name (| globals, "GAS_COLD_SLOAD" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + BoolOp.and (| + Compare.eq (| + M.get_name (| globals, "original_value" |), + M.get_name (| globals, "current_value" |) + |), + ltac:(M.monadic ( + Compare.not_eq (| + M.get_name (| globals, "current_value" |), + M.get_name (| globals, "new_value" |) + |) + )) + |), + (* then *) + ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, "original_value" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_op_local (| + BinOp.add, + "gas_cost", + M.get_name (| globals, "GAS_STORAGE_SET" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_op_local (| + BinOp.add, + "gas_cost", + BinOp.sub (| + M.get_name (| globals, "GAS_STORAGE_UPDATE" |), + M.get_name (| globals, "GAS_COLD_SLOAD" |) + |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_op_local (| + BinOp.add, + "gas_cost", + M.get_name (| globals, "GAS_WARM_ACCESS" |) + |) in + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + Compare.not_eq (| + M.get_name (| globals, "current_value" |), + M.get_name (| globals, "new_value" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + BoolOp.and (| + Compare.not_eq (| + M.get_name (| globals, "original_value" |), + Constant.int 0 + |), + ltac:(M.monadic ( + BoolOp.and (| + Compare.not_eq (| + M.get_name (| globals, "current_value" |), + Constant.int 0 + |), + ltac:(M.monadic ( + Compare.eq (| + M.get_name (| globals, "new_value" |), + Constant.int 0 + |) + )) + |) + )) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "refund_counter" |), + M.call (| + M.get_name (| globals, "int" |), + make_list [ + M.get_name (| globals, "GAS_STORAGE_CLEAR_REFUND" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + BoolOp.and (| + Compare.not_eq (| + M.get_name (| globals, "original_value" |), + Constant.int 0 + |), + ltac:(M.monadic ( + Compare.eq (| + M.get_name (| globals, "current_value" |), + Constant.int 0 + |) + )) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_op (| + BinOp.sub, + M.get_field (| M.get_name (| globals, "evm" |), "refund_counter" |), + M.call (| + M.get_name (| globals, "int" |), + make_list [ + M.get_name (| globals, "GAS_STORAGE_CLEAR_REFUND" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, "original_value" |), + M.get_name (| globals, "new_value" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, "original_value" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "refund_counter" |), + M.call (| + M.get_name (| globals, "int" |), + make_list [ + BinOp.sub (| + M.get_name (| globals, "GAS_STORAGE_SET" |), + M.get_name (| globals, "GAS_WARM_ACCESS" |) + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "refund_counter" |), + M.call (| + M.get_name (| globals, "int" |), + make_list [ + BinOp.sub (| + BinOp.sub (| + M.get_name (| globals, "GAS_STORAGE_UPDATE" |), + M.get_name (| globals, "GAS_COLD_SLOAD" |) + |), + M.get_name (| globals, "GAS_WARM_ACCESS" |) + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "gas_cost" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + UnOp.not (| M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "is_static" |) |); + M.get_name (| globals, "WriteInStaticContext" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "set_storage" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "env" |), "state" |); + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "current_target" |); + M.get_name (| globals, "key" |); + M.get_name (| globals, "new_value" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition tload : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Loads to the stack, the value corresponding to a certain key from the + transient storage of the current account. + Parameters + ---------- + evm : + The current EVM frame. + " in + let _ := M.assign_local (| + "key" , + M.call (| + M.get_field (| M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |), "to_be_bytes32" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_WARM_ACCESS" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "value" , + M.call (| + M.get_name (| globals, "get_transient_storage" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "env" |), "transient_storage" |); + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "current_target" |); + M.get_name (| globals, "key" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.get_name (| globals, "value" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition tstore : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Stores a value at a certain key in the current context's transient storage. + Parameters + ---------- + evm : + The current EVM frame. + " in + let _ := M.assign_local (| + "key" , + M.call (| + M.get_field (| M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |), "to_be_bytes32" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "new_value" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_WARM_ACCESS" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + UnOp.not (| M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "is_static" |) |); + M.get_name (| globals, "WriteInStaticContext" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "set_transient_storage" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "env" |), "transient_storage" |); + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "current_target" |); + M.get_name (| globals, "key" |); + M.get_name (| globals, "new_value" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). diff --git a/CoqOfPython/ethereum/cancun/vm/instructions/system.v b/CoqOfPython/ethereum/cancun/vm/instructions/system.v new file mode 100644 index 0000000..07121d5 --- /dev/null +++ b/CoqOfPython/ethereum/cancun/vm/instructions/system.v @@ -0,0 +1,2282 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.cancun.vm.instructions.system". + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) System Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM system related instructions. +". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_Bytes0 : + IsImported globals "ethereum.base_types" "Bytes0". +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". + +Axiom ethereum_utils_ensure_imports_ensure : + IsImported globals "ethereum.utils.ensure" "ensure". + +Axiom ethereum_utils_numeric_imports_ceil32 : + IsImported globals "ethereum.utils.numeric" "ceil32". + +Axiom ethereum_cancun_fork_types_imports_Address : + IsImported globals "ethereum.cancun.fork_types" "Address". + +Axiom ethereum_cancun_state_imports_account_exists_and_is_empty : + IsImported globals "ethereum.cancun.state" "account_exists_and_is_empty". +Axiom ethereum_cancun_state_imports_account_has_code_or_nonce : + IsImported globals "ethereum.cancun.state" "account_has_code_or_nonce". +Axiom ethereum_cancun_state_imports_get_account : + IsImported globals "ethereum.cancun.state" "get_account". +Axiom ethereum_cancun_state_imports_increment_nonce : + IsImported globals "ethereum.cancun.state" "increment_nonce". +Axiom ethereum_cancun_state_imports_is_account_alive : + IsImported globals "ethereum.cancun.state" "is_account_alive". +Axiom ethereum_cancun_state_imports_move_ether : + IsImported globals "ethereum.cancun.state" "move_ether". +Axiom ethereum_cancun_state_imports_set_account_balance : + IsImported globals "ethereum.cancun.state" "set_account_balance". + +Axiom ethereum_cancun_utils_address_imports_compute_contract_address : + IsImported globals "ethereum.cancun.utils.address" "compute_contract_address". +Axiom ethereum_cancun_utils_address_imports_compute_create2_contract_address : + IsImported globals "ethereum.cancun.utils.address" "compute_create2_contract_address". +Axiom ethereum_cancun_utils_address_imports_to_address : + IsImported globals "ethereum.cancun.utils.address" "to_address". + +Axiom ethereum_cancun_vm_imports_Evm : + IsImported globals "ethereum.cancun.vm" "Evm". +Axiom ethereum_cancun_vm_imports_Message : + IsImported globals "ethereum.cancun.vm" "Message". +Axiom ethereum_cancun_vm_imports_incorporate_child_on_error : + IsImported globals "ethereum.cancun.vm" "incorporate_child_on_error". +Axiom ethereum_cancun_vm_imports_incorporate_child_on_success : + IsImported globals "ethereum.cancun.vm" "incorporate_child_on_success". + +Axiom ethereum_cancun_vm_exceptions_imports_OutOfGasError : + IsImported globals "ethereum.cancun.vm.exceptions" "OutOfGasError". +Axiom ethereum_cancun_vm_exceptions_imports_Revert : + IsImported globals "ethereum.cancun.vm.exceptions" "Revert". +Axiom ethereum_cancun_vm_exceptions_imports_WriteInStaticContext : + IsImported globals "ethereum.cancun.vm.exceptions" "WriteInStaticContext". + +Axiom ethereum_cancun_vm_gas_imports_GAS_CALL_VALUE : + IsImported globals "ethereum.cancun.vm.gas" "GAS_CALL_VALUE". +Axiom ethereum_cancun_vm_gas_imports_GAS_COLD_ACCOUNT_ACCESS : + IsImported globals "ethereum.cancun.vm.gas" "GAS_COLD_ACCOUNT_ACCESS". +Axiom ethereum_cancun_vm_gas_imports_GAS_CREATE : + IsImported globals "ethereum.cancun.vm.gas" "GAS_CREATE". +Axiom ethereum_cancun_vm_gas_imports_GAS_KECCAK256_WORD : + IsImported globals "ethereum.cancun.vm.gas" "GAS_KECCAK256_WORD". +Axiom ethereum_cancun_vm_gas_imports_GAS_NEW_ACCOUNT : + IsImported globals "ethereum.cancun.vm.gas" "GAS_NEW_ACCOUNT". +Axiom ethereum_cancun_vm_gas_imports_GAS_SELF_DESTRUCT : + IsImported globals "ethereum.cancun.vm.gas" "GAS_SELF_DESTRUCT". +Axiom ethereum_cancun_vm_gas_imports_GAS_SELF_DESTRUCT_NEW_ACCOUNT : + IsImported globals "ethereum.cancun.vm.gas" "GAS_SELF_DESTRUCT_NEW_ACCOUNT". +Axiom ethereum_cancun_vm_gas_imports_GAS_WARM_ACCESS : + IsImported globals "ethereum.cancun.vm.gas" "GAS_WARM_ACCESS". +Axiom ethereum_cancun_vm_gas_imports_GAS_ZERO : + IsImported globals "ethereum.cancun.vm.gas" "GAS_ZERO". +Axiom ethereum_cancun_vm_gas_imports_calculate_gas_extend_memory : + IsImported globals "ethereum.cancun.vm.gas" "calculate_gas_extend_memory". +Axiom ethereum_cancun_vm_gas_imports_calculate_message_call_gas : + IsImported globals "ethereum.cancun.vm.gas" "calculate_message_call_gas". +Axiom ethereum_cancun_vm_gas_imports_charge_gas : + IsImported globals "ethereum.cancun.vm.gas" "charge_gas". +Axiom ethereum_cancun_vm_gas_imports_init_code_cost : + IsImported globals "ethereum.cancun.vm.gas" "init_code_cost". +Axiom ethereum_cancun_vm_gas_imports_max_message_call_gas : + IsImported globals "ethereum.cancun.vm.gas" "max_message_call_gas". + +Axiom ethereum_cancun_vm_memory_imports_memory_read_bytes : + IsImported globals "ethereum.cancun.vm.memory" "memory_read_bytes". +Axiom ethereum_cancun_vm_memory_imports_memory_write : + IsImported globals "ethereum.cancun.vm.memory" "memory_write". + +Axiom ethereum_cancun_vm_stack_imports_pop : + IsImported globals "ethereum.cancun.vm.stack" "pop". +Axiom ethereum_cancun_vm_stack_imports_push : + IsImported globals "ethereum.cancun.vm.stack" "push". + +Definition generic_create : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm"; "endowment"; "contract_address"; "memory_start_position"; "memory_size"; "init_code_gas" ] |) in + let _ := Constant.str " + Core logic used by the `CREATE*` family of opcodes. + " in +(* At stmt: unsupported node type: ImportFrom *) + let _ := M.assign_local (| + "call_data" , + M.call (| + M.get_name (| globals, "memory_read_bytes" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "memory" |); + M.get_name (| globals, "memory_start_position" |); + M.get_name (| globals, "memory_size" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + Compare.lt_e (| + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_name (| globals, "call_data" |) + ], + make_dict [] + |), + BinOp.mult (| + Constant.int 2, + M.get_name (| globals, "MAX_CODE_SIZE" |) + |) + |); + M.get_name (| globals, "OutOfGasError" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "accessed_addresses" |), "add" |), + make_list [ + M.get_name (| globals, "contract_address" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "create_message_gas" , + M.call (| + M.get_name (| globals, "max_message_call_gas" |), + make_list [ + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "gas_left" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_op (| + BinOp.sub, + M.get_field (| M.get_name (| globals, "evm" |), "gas_left" |), + M.get_name (| globals, "create_message_gas" |) + |) in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + UnOp.not (| M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "is_static" |) |); + M.get_name (| globals, "WriteInStaticContext" |) + ], + make_dict [] + |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, "evm" |), "return_data" |), + Constant.bytes "" + |) in + let _ := M.assign_local (| + "sender_address" , + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "current_target" |) + |) in + let _ := M.assign_local (| + "sender" , + M.call (| + M.get_name (| globals, "get_account" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "env" |), "state" |); + M.get_name (| globals, "sender_address" |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + BoolOp.or (| + Compare.lt (| + M.get_field (| M.get_name (| globals, "sender" |), "balance" |), + M.get_name (| globals, "endowment" |) + |), + ltac:(M.monadic ( + BoolOp.or (| + Compare.eq (| + M.get_field (| M.get_name (| globals, "sender" |), "nonce" |), + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + BinOp.sub (| + BinOp.pow (| + Constant.int 2, + Constant.int 64 + |), + Constant.int 1 + |) + ], + make_dict [] + |) + |), + ltac:(M.monadic ( + Compare.gt (| + BinOp.add (| + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "depth" |), + Constant.int 1 + |), + M.get_name (| globals, "STACK_DEPTH_LIMIT" |) + |) + )) + |) + )) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "gas_left" |), + M.get_name (| globals, "create_message_gas" |) + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.return_ (| + Constant.None_ + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, "account_has_code_or_nonce" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "env" |), "state" |); + M.get_name (| globals, "contract_address" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, "increment_nonce" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "env" |), "state" |); + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "current_target" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.return_ (| + Constant.None_ + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.call (| + M.get_name (| globals, "increment_nonce" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "env" |), "state" |); + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "current_target" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "child_message" , + M.call (| + M.get_name (| globals, "Message" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "child_evm" , + M.call (| + M.get_name (| globals, "process_create_message" |), + make_list [ + M.get_name (| globals, "child_message" |); + M.get_field (| M.get_name (| globals, "evm" |), "env" |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + M.get_field (| M.get_name (| globals, "child_evm" |), "error" |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, "incorporate_child_on_error" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "child_evm" |) + ], + make_dict [] + |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, "evm" |), "return_data" |), + M.get_field (| M.get_name (| globals, "child_evm" |), "output" |) + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + ], + make_dict [] + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, "incorporate_child_on_success" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "child_evm" |) + ], + make_dict [] + |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, "evm" |), "return_data" |), + Constant.bytes "" + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.call (| + M.get_field (| M.get_name (| globals, "U256" |), "from_be_bytes" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "child_evm" |), "message" |), "current_target" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_)). + +Definition create : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Creates a new account with associated code. + + Parameters + ---------- + evm : + The current EVM frame. + " in + let _ := M.assign_local (| + "endowment" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_start_position" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_size" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "extend_memory" , + M.call (| + M.get_name (| globals, "calculate_gas_extend_memory" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "memory" |); + make_list [ + make_tuple [ M.get_name (| globals, "memory_start_position" |); M.get_name (| globals, "memory_size" |) ] + ] + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "init_code_gas" , + M.call (| + M.get_name (| globals, "init_code_cost" |), + make_list [ + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.get_name (| globals, "memory_size" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + BinOp.add (| + BinOp.add (| + M.get_name (| globals, "GAS_CREATE" |), + M.get_field (| M.get_name (| globals, "extend_memory" |), "cost" |) + |), + M.get_name (| globals, "init_code_gas" |) + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "memory" |), + BinOp.mult (| + Constant.bytes "00", + M.get_field (| M.get_name (| globals, "extend_memory" |), "expand_by" |) + |) + |) in + let _ := M.assign_local (| + "contract_address" , + M.call (| + M.get_name (| globals, "compute_contract_address" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "current_target" |); + M.get_field (| M.call (| + M.get_name (| globals, "get_account" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "env" |), "state" |); + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "current_target" |) + ], + make_dict [] + |), "nonce" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "generic_create" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "endowment" |); + M.get_name (| globals, "contract_address" |); + M.get_name (| globals, "memory_start_position" |); + M.get_name (| globals, "memory_size" |); + M.get_name (| globals, "init_code_gas" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition create2 : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Creates a new account with associated code. + + It's similar to CREATE opcode except that the address of new account + depends on the init_code instead of the nonce of sender. + + Parameters + ---------- + evm : + The current EVM frame. + " in + let _ := M.assign_local (| + "endowment" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_start_position" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_size" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "salt" , + M.call (| + M.get_field (| M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |), "to_be_bytes32" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "extend_memory" , + M.call (| + M.get_name (| globals, "calculate_gas_extend_memory" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "memory" |); + make_list [ + make_tuple [ M.get_name (| globals, "memory_start_position" |); M.get_name (| globals, "memory_size" |) ] + ] + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "call_data_words" , + BinOp.floor_div (| + M.call (| + M.get_name (| globals, "ceil32" |), + make_list [ + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.get_name (| globals, "memory_size" |) + ], + make_dict [] + |) + ], + make_dict [] + |), + Constant.int 32 + |) + |) in + let _ := M.assign_local (| + "init_code_gas" , + M.call (| + M.get_name (| globals, "init_code_cost" |), + make_list [ + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.get_name (| globals, "memory_size" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + BinOp.add (| + BinOp.add (| + BinOp.add (| + M.get_name (| globals, "GAS_CREATE" |), + BinOp.mult (| + M.get_name (| globals, "GAS_KECCAK256_WORD" |), + M.get_name (| globals, "call_data_words" |) + |) + |), + M.get_field (| M.get_name (| globals, "extend_memory" |), "cost" |) + |), + M.get_name (| globals, "init_code_gas" |) + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "memory" |), + BinOp.mult (| + Constant.bytes "00", + M.get_field (| M.get_name (| globals, "extend_memory" |), "expand_by" |) + |) + |) in + let _ := M.assign_local (| + "contract_address" , + M.call (| + M.get_name (| globals, "compute_create2_contract_address" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "current_target" |); + M.get_name (| globals, "salt" |); + M.call (| + M.get_name (| globals, "memory_read_bytes" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "memory" |); + M.get_name (| globals, "memory_start_position" |); + M.get_name (| globals, "memory_size" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "generic_create" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "endowment" |); + M.get_name (| globals, "contract_address" |); + M.get_name (| globals, "memory_start_position" |); + M.get_name (| globals, "memory_size" |); + M.get_name (| globals, "init_code_gas" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition return_ : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Halts execution returning output data. + + Parameters + ---------- + evm : + The current EVM frame. + " in + let _ := M.assign_local (| + "memory_start_position" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_size" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "extend_memory" , + M.call (| + M.get_name (| globals, "calculate_gas_extend_memory" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "memory" |); + make_list [ + make_tuple [ M.get_name (| globals, "memory_start_position" |); M.get_name (| globals, "memory_size" |) ] + ] + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + BinOp.add (| + M.get_name (| globals, "GAS_ZERO" |), + M.get_field (| M.get_name (| globals, "extend_memory" |), "cost" |) + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "memory" |), + BinOp.mult (| + Constant.bytes "00", + M.get_field (| M.get_name (| globals, "extend_memory" |), "expand_by" |) + |) + |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, "evm" |), "output" |), + M.call (| + M.get_name (| globals, "memory_read_bytes" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "memory" |); + M.get_name (| globals, "memory_start_position" |); + M.get_name (| globals, "memory_size" |) + ], + make_dict [] + |) + |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, "evm" |), "running" |), + Constant.bool false + |) in + let _ := M.pass (| |) in + M.pure Constant.None_)). + +Definition generic_call : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm"; "gas"; "value"; "caller"; "to"; "code_address"; "should_transfer_value"; "is_staticcall"; "memory_input_start_position"; "memory_input_size"; "memory_output_start_position"; "memory_output_size" ] |) in + let _ := Constant.str " + Perform the core logic of the `CALL*` family of opcodes. + " in +(* At stmt: unsupported node type: ImportFrom *) + let _ := M.assign (| + M.get_field (| M.get_name (| globals, "evm" |), "return_data" |), + Constant.bytes "" + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.gt (| + BinOp.add (| + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "depth" |), + Constant.int 1 + |), + M.get_name (| globals, "STACK_DEPTH_LIMIT" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "gas_left" |), + M.get_name (| globals, "gas" |) + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.return_ (| + Constant.None_ + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "call_data" , + M.call (| + M.get_name (| globals, "memory_read_bytes" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "memory" |); + M.get_name (| globals, "memory_input_start_position" |); + M.get_name (| globals, "memory_input_size" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "code" , + M.get_field (| M.call (| + M.get_name (| globals, "get_account" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "env" |), "state" |); + M.get_name (| globals, "code_address" |) + ], + make_dict [] + |), "code" |) + |) in + let _ := M.assign_local (| + "child_message" , + M.call (| + M.get_name (| globals, "Message" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "child_evm" , + M.call (| + M.get_name (| globals, "process_message" |), + make_list [ + M.get_name (| globals, "child_message" |); + M.get_field (| M.get_name (| globals, "evm" |), "env" |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + M.get_field (| M.get_name (| globals, "child_evm" |), "error" |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, "incorporate_child_on_error" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "child_evm" |) + ], + make_dict [] + |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, "evm" |), "return_data" |), + M.get_field (| M.get_name (| globals, "child_evm" |), "output" |) + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + ], + make_dict [] + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, "incorporate_child_on_success" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "child_evm" |) + ], + make_dict [] + |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, "evm" |), "return_data" |), + M.get_field (| M.get_name (| globals, "child_evm" |), "output" |) + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 1 + ], + make_dict [] + |) + ], + make_dict [] + |) in + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "actual_output_size" , + M.call (| + M.get_name (| globals, "min" |), + make_list [ + M.get_name (| globals, "memory_output_size" |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_field (| M.get_name (| globals, "child_evm" |), "output" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "memory_write" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "memory" |); + M.get_name (| globals, "memory_output_start_position" |); + M.slice (| + M.get_field (| M.get_name (| globals, "child_evm" |), "output" |), + Constant.None_, + M.get_name (| globals, "actual_output_size" |), + Constant.None_ + |) + ], + make_dict [] + |) in + M.pure Constant.None_)). + +Definition call : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Message-call into an account. + + Parameters + ---------- + evm : + The current EVM frame. + " in + let _ := M.assign_local (| + "gas" , + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "to" , + M.call (| + M.get_name (| globals, "to_address" |), + make_list [ + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "value" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_input_start_position" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_input_size" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_output_start_position" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_output_size" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "extend_memory" , + M.call (| + M.get_name (| globals, "calculate_gas_extend_memory" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "memory" |); + make_list [ + make_tuple [ M.get_name (| globals, "memory_input_start_position" |); M.get_name (| globals, "memory_input_size" |) ]; + make_tuple [ M.get_name (| globals, "memory_output_start_position" |); M.get_name (| globals, "memory_output_size" |) ] + ] + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.in_ (| + M.get_name (| globals, "to" |), + M.get_field (| M.get_name (| globals, "evm" |), "accessed_addresses" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "access_gas_cost" , + M.get_name (| globals, "GAS_WARM_ACCESS" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "accessed_addresses" |), "add" |), + make_list [ + M.get_name (| globals, "to" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "access_gas_cost" , + M.get_name (| globals, "GAS_COLD_ACCOUNT_ACCESS" |) + |) in + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "create_gas_cost" , + (* if *) + M.if_then_else (| + BoolOp.or (| + M.call (| + M.get_name (| globals, "is_account_alive" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "env" |), "state" |); + M.get_name (| globals, "to" |) + ], + make_dict [] + |), + ltac:(M.monadic ( + Compare.eq (| + M.get_name (| globals, "value" |), + Constant.int 0 + |) + )) + |), + (* then *) + ltac:(M.monadic ( +M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + (* else *) + )), ltac:(M.monadic ( +M.get_name (| globals, "GAS_NEW_ACCOUNT" |) + )) |) + |) in + let _ := M.assign_local (| + "transfer_gas_cost" , + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, "value" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( +M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + (* else *) + )), ltac:(M.monadic ( +M.get_name (| globals, "GAS_CALL_VALUE" |) + )) |) + |) in + let _ := M.assign_local (| + "message_call_gas" , + M.call (| + M.get_name (| globals, "calculate_message_call_gas" |), + make_list [ + M.get_name (| globals, "value" |); + M.get_name (| globals, "gas" |); + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "gas_left" |) + ], + make_dict [] + |); + M.get_field (| M.get_name (| globals, "extend_memory" |), "cost" |); + BinOp.add (| + BinOp.add (| + M.get_name (| globals, "access_gas_cost" |), + M.get_name (| globals, "create_gas_cost" |) + |), + M.get_name (| globals, "transfer_gas_cost" |) + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + BinOp.add (| + M.get_field (| M.get_name (| globals, "message_call_gas" |), "cost" |), + M.get_field (| M.get_name (| globals, "extend_memory" |), "cost" |) + |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + BoolOp.or (| + UnOp.not (| M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "is_static" |) |), + ltac:(M.monadic ( + Compare.eq (| + M.get_name (| globals, "value" |), + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + |) + )) + |); + M.get_name (| globals, "WriteInStaticContext" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "memory" |), + BinOp.mult (| + Constant.bytes "00", + M.get_field (| M.get_name (| globals, "extend_memory" |), "expand_by" |) + |) + |) in + let _ := M.assign_local (| + "sender_balance" , + M.get_field (| M.call (| + M.get_name (| globals, "get_account" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "env" |), "state" |); + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "current_target" |) + ], + make_dict [] + |), "balance" |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.lt (| + M.get_name (| globals, "sender_balance" |), + M.get_name (| globals, "value" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, "evm" |), "return_data" |), + Constant.bytes "" + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "gas_left" |), + M.get_field (| M.get_name (| globals, "message_call_gas" |), "stipend" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, "generic_call" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_field (| M.get_name (| globals, "message_call_gas" |), "stipend" |); + M.get_name (| globals, "value" |); + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "current_target" |); + M.get_name (| globals, "to" |); + M.get_name (| globals, "to" |); + Constant.bool true; + Constant.bool false; + M.get_name (| globals, "memory_input_start_position" |); + M.get_name (| globals, "memory_input_size" |); + M.get_name (| globals, "memory_output_start_position" |); + M.get_name (| globals, "memory_output_size" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + )) |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition callcode : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Message-call into this account with alternative account’s code. + + Parameters + ---------- + evm : + The current EVM frame. + " in + let _ := M.assign_local (| + "gas" , + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "code_address" , + M.call (| + M.get_name (| globals, "to_address" |), + make_list [ + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "value" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_input_start_position" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_input_size" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_output_start_position" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_output_size" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "to" , + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "current_target" |) + |) in + let _ := M.assign_local (| + "extend_memory" , + M.call (| + M.get_name (| globals, "calculate_gas_extend_memory" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "memory" |); + make_list [ + make_tuple [ M.get_name (| globals, "memory_input_start_position" |); M.get_name (| globals, "memory_input_size" |) ]; + make_tuple [ M.get_name (| globals, "memory_output_start_position" |); M.get_name (| globals, "memory_output_size" |) ] + ] + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.in_ (| + M.get_name (| globals, "code_address" |), + M.get_field (| M.get_name (| globals, "evm" |), "accessed_addresses" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "access_gas_cost" , + M.get_name (| globals, "GAS_WARM_ACCESS" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "accessed_addresses" |), "add" |), + make_list [ + M.get_name (| globals, "code_address" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "access_gas_cost" , + M.get_name (| globals, "GAS_COLD_ACCOUNT_ACCESS" |) + |) in + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "transfer_gas_cost" , + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, "value" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( +M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + (* else *) + )), ltac:(M.monadic ( +M.get_name (| globals, "GAS_CALL_VALUE" |) + )) |) + |) in + let _ := M.assign_local (| + "message_call_gas" , + M.call (| + M.get_name (| globals, "calculate_message_call_gas" |), + make_list [ + M.get_name (| globals, "value" |); + M.get_name (| globals, "gas" |); + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "gas_left" |) + ], + make_dict [] + |); + M.get_field (| M.get_name (| globals, "extend_memory" |), "cost" |); + BinOp.add (| + M.get_name (| globals, "access_gas_cost" |), + M.get_name (| globals, "transfer_gas_cost" |) + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + BinOp.add (| + M.get_field (| M.get_name (| globals, "message_call_gas" |), "cost" |), + M.get_field (| M.get_name (| globals, "extend_memory" |), "cost" |) + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "memory" |), + BinOp.mult (| + Constant.bytes "00", + M.get_field (| M.get_name (| globals, "extend_memory" |), "expand_by" |) + |) + |) in + let _ := M.assign_local (| + "sender_balance" , + M.get_field (| M.call (| + M.get_name (| globals, "get_account" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "env" |), "state" |); + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "current_target" |) + ], + make_dict [] + |), "balance" |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.lt (| + M.get_name (| globals, "sender_balance" |), + M.get_name (| globals, "value" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, "evm" |), "return_data" |), + Constant.bytes "" + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "gas_left" |), + M.get_field (| M.get_name (| globals, "message_call_gas" |), "stipend" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, "generic_call" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_field (| M.get_name (| globals, "message_call_gas" |), "stipend" |); + M.get_name (| globals, "value" |); + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "current_target" |); + M.get_name (| globals, "to" |); + M.get_name (| globals, "code_address" |); + Constant.bool true; + Constant.bool false; + M.get_name (| globals, "memory_input_start_position" |); + M.get_name (| globals, "memory_input_size" |); + M.get_name (| globals, "memory_output_start_position" |); + M.get_name (| globals, "memory_output_size" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + )) |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition selfdestruct : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Halt execution and register account for later deletion. + + Parameters + ---------- + evm : + The current EVM frame. + " in + let _ := M.assign_local (| + "beneficiary" , + M.call (| + M.get_name (| globals, "to_address" |), + make_list [ + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "gas_cost" , + M.get_name (| globals, "GAS_SELF_DESTRUCT" |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.not_in (| + M.get_name (| globals, "beneficiary" |), + M.get_field (| M.get_name (| globals, "evm" |), "accessed_addresses" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "accessed_addresses" |), "add" |), + make_list [ + M.get_name (| globals, "beneficiary" |) + ], + make_dict [] + |) in + let _ := M.assign_op_local (| + BinOp.add, + "gas_cost", + M.get_name (| globals, "GAS_COLD_ACCOUNT_ACCESS" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + BoolOp.and (| + UnOp.not (| M.call (| + M.get_name (| globals, "is_account_alive" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "env" |), "state" |); + M.get_name (| globals, "beneficiary" |) + ], + make_dict [] + |) |), + ltac:(M.monadic ( + Compare.not_eq (| + M.get_field (| M.call (| + M.get_name (| globals, "get_account" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "env" |), "state" |); + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "current_target" |) + ], + make_dict [] + |), "balance" |), + Constant.int 0 + |) + )) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_op_local (| + BinOp.add, + "gas_cost", + M.get_name (| globals, "GAS_SELF_DESTRUCT_NEW_ACCOUNT" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "gas_cost" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + UnOp.not (| M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "is_static" |) |); + M.get_name (| globals, "WriteInStaticContext" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "originator" , + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "current_target" |) + |) in + let _ := M.assign_local (| + "originator_balance" , + M.get_field (| M.call (| + M.get_name (| globals, "get_account" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "env" |), "state" |); + M.get_name (| globals, "originator" |) + ], + make_dict [] + |), "balance" |) + |) in + let _ := M.call (| + M.get_name (| globals, "move_ether" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "env" |), "state" |); + M.get_name (| globals, "originator" |); + M.get_name (| globals, "beneficiary" |); + M.get_name (| globals, "originator_balance" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.in_ (| + M.get_name (| globals, "originator" |), + M.get_field (| M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "env" |), "state" |), "created_accounts" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, "set_account_balance" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "env" |), "state" |); + M.get_name (| globals, "originator" |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "accounts_to_delete" |), "add" |), + make_list [ + M.get_name (| globals, "originator" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, "account_exists_and_is_empty" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "env" |), "state" |); + M.get_name (| globals, "beneficiary" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "touched_accounts" |), "add" |), + make_list [ + M.get_name (| globals, "beneficiary" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, "evm" |), "running" |), + Constant.bool false + |) in + let _ := M.pass (| |) in + M.pure Constant.None_)). + +Definition delegatecall : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Message-call into an account. + + Parameters + ---------- + evm : + The current EVM frame. + " in + let _ := M.assign_local (| + "gas" , + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "code_address" , + M.call (| + M.get_name (| globals, "to_address" |), + make_list [ + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_input_start_position" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_input_size" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_output_start_position" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_output_size" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "extend_memory" , + M.call (| + M.get_name (| globals, "calculate_gas_extend_memory" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "memory" |); + make_list [ + make_tuple [ M.get_name (| globals, "memory_input_start_position" |); M.get_name (| globals, "memory_input_size" |) ]; + make_tuple [ M.get_name (| globals, "memory_output_start_position" |); M.get_name (| globals, "memory_output_size" |) ] + ] + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.in_ (| + M.get_name (| globals, "code_address" |), + M.get_field (| M.get_name (| globals, "evm" |), "accessed_addresses" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "access_gas_cost" , + M.get_name (| globals, "GAS_WARM_ACCESS" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "accessed_addresses" |), "add" |), + make_list [ + M.get_name (| globals, "code_address" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "access_gas_cost" , + M.get_name (| globals, "GAS_COLD_ACCOUNT_ACCESS" |) + |) in + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "message_call_gas" , + M.call (| + M.get_name (| globals, "calculate_message_call_gas" |), + make_list [ + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |); + M.get_name (| globals, "gas" |); + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "gas_left" |) + ], + make_dict [] + |); + M.get_field (| M.get_name (| globals, "extend_memory" |), "cost" |); + M.get_name (| globals, "access_gas_cost" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + BinOp.add (| + M.get_field (| M.get_name (| globals, "message_call_gas" |), "cost" |), + M.get_field (| M.get_name (| globals, "extend_memory" |), "cost" |) + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "memory" |), + BinOp.mult (| + Constant.bytes "00", + M.get_field (| M.get_name (| globals, "extend_memory" |), "expand_by" |) + |) + |) in + let _ := M.call (| + M.get_name (| globals, "generic_call" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_field (| M.get_name (| globals, "message_call_gas" |), "stipend" |); + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "value" |); + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "caller" |); + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "current_target" |); + M.get_name (| globals, "code_address" |); + Constant.bool false; + Constant.bool false; + M.get_name (| globals, "memory_input_start_position" |); + M.get_name (| globals, "memory_input_size" |); + M.get_name (| globals, "memory_output_start_position" |); + M.get_name (| globals, "memory_output_size" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition staticcall : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Message-call into an account. + + Parameters + ---------- + evm : + The current EVM frame. + " in + let _ := M.assign_local (| + "gas" , + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "to" , + M.call (| + M.get_name (| globals, "to_address" |), + make_list [ + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_input_start_position" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_input_size" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_output_start_position" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_output_size" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "extend_memory" , + M.call (| + M.get_name (| globals, "calculate_gas_extend_memory" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "memory" |); + make_list [ + make_tuple [ M.get_name (| globals, "memory_input_start_position" |); M.get_name (| globals, "memory_input_size" |) ]; + make_tuple [ M.get_name (| globals, "memory_output_start_position" |); M.get_name (| globals, "memory_output_size" |) ] + ] + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.in_ (| + M.get_name (| globals, "to" |), + M.get_field (| M.get_name (| globals, "evm" |), "accessed_addresses" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "access_gas_cost" , + M.get_name (| globals, "GAS_WARM_ACCESS" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "accessed_addresses" |), "add" |), + make_list [ + M.get_name (| globals, "to" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "access_gas_cost" , + M.get_name (| globals, "GAS_COLD_ACCOUNT_ACCESS" |) + |) in + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "message_call_gas" , + M.call (| + M.get_name (| globals, "calculate_message_call_gas" |), + make_list [ + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |); + M.get_name (| globals, "gas" |); + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "gas_left" |) + ], + make_dict [] + |); + M.get_field (| M.get_name (| globals, "extend_memory" |), "cost" |); + M.get_name (| globals, "access_gas_cost" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + BinOp.add (| + M.get_field (| M.get_name (| globals, "message_call_gas" |), "cost" |), + M.get_field (| M.get_name (| globals, "extend_memory" |), "cost" |) + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "memory" |), + BinOp.mult (| + Constant.bytes "00", + M.get_field (| M.get_name (| globals, "extend_memory" |), "expand_by" |) + |) + |) in + let _ := M.call (| + M.get_name (| globals, "generic_call" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_field (| M.get_name (| globals, "message_call_gas" |), "stipend" |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |); + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "current_target" |); + M.get_name (| globals, "to" |); + M.get_name (| globals, "to" |); + Constant.bool true; + Constant.bool true; + M.get_name (| globals, "memory_input_start_position" |); + M.get_name (| globals, "memory_input_size" |); + M.get_name (| globals, "memory_output_start_position" |); + M.get_name (| globals, "memory_output_size" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition revert : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Stop execution and revert state changes, without consuming all provided gas + and also has the ability to return a reason + Parameters + ---------- + evm : + The current EVM frame. + " in + let _ := M.assign_local (| + "memory_start_index" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "size" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "extend_memory" , + M.call (| + M.get_name (| globals, "calculate_gas_extend_memory" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "memory" |); + make_list [ + make_tuple [ M.get_name (| globals, "memory_start_index" |); M.get_name (| globals, "size" |) ] + ] + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_field (| M.get_name (| globals, "extend_memory" |), "cost" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "memory" |), + BinOp.mult (| + Constant.bytes "00", + M.get_field (| M.get_name (| globals, "extend_memory" |), "expand_by" |) + |) + |) in + let _ := M.assign_local (| + "output" , + M.call (| + M.get_name (| globals, "memory_read_bytes" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "memory" |); + M.get_name (| globals, "memory_start_index" |); + M.get_name (| globals, "size" |) + ], + make_dict [] + |) + |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, "evm" |), "output" |), + M.call (| + M.get_name (| globals, "bytes" |), + make_list [ + M.get_name (| globals, "output" |) + ], + make_dict [] + |) + |) in + let _ := M.raise (| Some (M.get_name (| globals, "Revert" |)) |) in + let _ := M.pass (| |) in + M.pure Constant.None_)). diff --git a/CoqOfPython/ethereum/cancun/vm/interpreter.v b/CoqOfPython/ethereum/cancun/vm/interpreter.v new file mode 100644 index 0000000..c3551ef --- /dev/null +++ b/CoqOfPython/ethereum/cancun/vm/interpreter.v @@ -0,0 +1,682 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.cancun.vm.interpreter". + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) Interpreter +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +A straightforward interpreter that executes EVM code. +". + +Axiom dataclasses_imports_dataclass : + IsImported globals "dataclasses" "dataclass". + +Axiom typing_imports_Iterable : + IsImported globals "typing" "Iterable". +Axiom typing_imports_Optional : + IsImported globals "typing" "Optional". +Axiom typing_imports_Set : + IsImported globals "typing" "Set". +Axiom typing_imports_Tuple : + IsImported globals "typing" "Tuple". +Axiom typing_imports_Union : + IsImported globals "typing" "Union". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_Bytes0 : + IsImported globals "ethereum.base_types" "Bytes0". +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". + +Axiom ethereum_trace_imports_EvmStop : + IsImported globals "ethereum.trace" "EvmStop". +Axiom ethereum_trace_imports_OpEnd : + IsImported globals "ethereum.trace" "OpEnd". +Axiom ethereum_trace_imports_OpException : + IsImported globals "ethereum.trace" "OpException". +Axiom ethereum_trace_imports_OpStart : + IsImported globals "ethereum.trace" "OpStart". +Axiom ethereum_trace_imports_PrecompileEnd : + IsImported globals "ethereum.trace" "PrecompileEnd". +Axiom ethereum_trace_imports_PrecompileStart : + IsImported globals "ethereum.trace" "PrecompileStart". +Axiom ethereum_trace_imports_TransactionEnd : + IsImported globals "ethereum.trace" "TransactionEnd". +Axiom ethereum_trace_imports_evm_trace : + IsImported globals "ethereum.trace" "evm_trace". + +Axiom ethereum_utils_ensure_imports_ensure : + IsImported globals "ethereum.utils.ensure" "ensure". + +Axiom ethereum_cancun_blocks_imports_Log : + IsImported globals "ethereum.cancun.blocks" "Log". + +Axiom ethereum_cancun_fork_types_imports_Address : + IsImported globals "ethereum.cancun.fork_types" "Address". + +Axiom ethereum_cancun_state_imports_account_exists_and_is_empty : + IsImported globals "ethereum.cancun.state" "account_exists_and_is_empty". +Axiom ethereum_cancun_state_imports_account_has_code_or_nonce : + IsImported globals "ethereum.cancun.state" "account_has_code_or_nonce". +Axiom ethereum_cancun_state_imports_begin_transaction : + IsImported globals "ethereum.cancun.state" "begin_transaction". +Axiom ethereum_cancun_state_imports_commit_transaction : + IsImported globals "ethereum.cancun.state" "commit_transaction". +Axiom ethereum_cancun_state_imports_destroy_storage : + IsImported globals "ethereum.cancun.state" "destroy_storage". +Axiom ethereum_cancun_state_imports_increment_nonce : + IsImported globals "ethereum.cancun.state" "increment_nonce". +Axiom ethereum_cancun_state_imports_mark_account_created : + IsImported globals "ethereum.cancun.state" "mark_account_created". +Axiom ethereum_cancun_state_imports_move_ether : + IsImported globals "ethereum.cancun.state" "move_ether". +Axiom ethereum_cancun_state_imports_rollback_transaction : + IsImported globals "ethereum.cancun.state" "rollback_transaction". +Axiom ethereum_cancun_state_imports_set_code : + IsImported globals "ethereum.cancun.state" "set_code". +Axiom ethereum_cancun_state_imports_touch_account : + IsImported globals "ethereum.cancun.state" "touch_account". + +Axiom ethereum_cancun_vm_imports_Message : + IsImported globals "ethereum.cancun.vm" "Message". + +Axiom ethereum_cancun_vm_gas_imports_GAS_CODE_DEPOSIT : + IsImported globals "ethereum.cancun.vm.gas" "GAS_CODE_DEPOSIT". +Axiom ethereum_cancun_vm_gas_imports_charge_gas : + IsImported globals "ethereum.cancun.vm.gas" "charge_gas". + +Axiom ethereum_cancun_vm_precompiled_contracts_mapping_imports_PRE_COMPILED_CONTRACTS : + IsImported globals "ethereum.cancun.vm.precompiled_contracts.mapping" "PRE_COMPILED_CONTRACTS". + +Axiom ethereum_cancun_vm_imports_Environment : + IsImported globals "ethereum.cancun.vm" "Environment". +Axiom ethereum_cancun_vm_imports_Evm : + IsImported globals "ethereum.cancun.vm" "Evm". + +Axiom ethereum_cancun_vm_exceptions_imports_AddressCollision : + IsImported globals "ethereum.cancun.vm.exceptions" "AddressCollision". +Axiom ethereum_cancun_vm_exceptions_imports_ExceptionalHalt : + IsImported globals "ethereum.cancun.vm.exceptions" "ExceptionalHalt". +Axiom ethereum_cancun_vm_exceptions_imports_InvalidContractPrefix : + IsImported globals "ethereum.cancun.vm.exceptions" "InvalidContractPrefix". +Axiom ethereum_cancun_vm_exceptions_imports_InvalidOpcode : + IsImported globals "ethereum.cancun.vm.exceptions" "InvalidOpcode". +Axiom ethereum_cancun_vm_exceptions_imports_OutOfGasError : + IsImported globals "ethereum.cancun.vm.exceptions" "OutOfGasError". +Axiom ethereum_cancun_vm_exceptions_imports_Revert : + IsImported globals "ethereum.cancun.vm.exceptions" "Revert". +Axiom ethereum_cancun_vm_exceptions_imports_StackDepthLimitError : + IsImported globals "ethereum.cancun.vm.exceptions" "StackDepthLimitError". + +Axiom ethereum_cancun_vm_instructions_imports_Ops : + IsImported globals "ethereum.cancun.vm.instructions" "Ops". +Axiom ethereum_cancun_vm_instructions_imports_op_implementation : + IsImported globals "ethereum.cancun.vm.instructions" "op_implementation". + +Axiom ethereum_cancun_vm_runtime_imports_get_valid_jump_destinations : + IsImported globals "ethereum.cancun.vm.runtime" "get_valid_jump_destinations". + +Definition STACK_DEPTH_LIMIT : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 1024 + ], + make_dict [] + |) +)). + +Definition MAX_CODE_SIZE : Value.t := M.run ltac:(M.monadic ( + Constant.int 24576 +)). + +Definition MessageCallOutput : Value.t := + builtins.make_klass + [] + [ + + ] + [ + + ]. + +Definition process_message_call : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "message"; "env" ] |) in + let _ := Constant.str " + If `message.current` is empty then it creates a smart contract + else it executes a call from the `message.caller` to the `message.target`. + + Parameters + ---------- + message : + Transaction specific items. + + env : + External items required for EVM execution. + + Returns + ------- + output : `MessageCallOutput` + Output of the message call + " in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_field (| M.get_name (| globals, "message" |), "target" |), + M.call (| + M.get_name (| globals, "Bytes0" |), + make_list [ + Constant.bytes "" + ], + make_dict [] + |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "is_collision" , + M.call (| + M.get_name (| globals, "account_has_code_or_nonce" |), + make_list [ + M.get_field (| M.get_name (| globals, "env" |), "state" |); + M.get_field (| M.get_name (| globals, "message" |), "current_target" |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + M.get_name (| globals, "is_collision" |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + M.call (| + M.get_name (| globals, "MessageCallOutput" |), + make_list [ + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |); + M.call (| + M.get_name (| globals, "tuple" |), + make_list [], + make_dict [] + |); + M.call (| + M.get_name (| globals, "set" |), + make_list [], + make_dict [] + |); + M.call (| + M.get_name (| globals, "set" |), + make_list [], + make_dict [] + |); + M.call (| + M.get_name (| globals, "AddressCollision" |), + make_list [], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "evm" , + M.call (| + M.get_name (| globals, "process_create_message" |), + make_list [ + M.get_name (| globals, "message" |); + M.get_name (| globals, "env" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "evm" , + M.call (| + M.get_name (| globals, "process_message" |), + make_list [ + M.get_name (| globals, "message" |); + M.get_name (| globals, "env" |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, "account_exists_and_is_empty" |), + make_list [ + M.get_field (| M.get_name (| globals, "env" |), "state" |); + M.call (| + M.get_name (| globals, "Address" |), + make_list [ + M.get_field (| M.get_name (| globals, "message" |), "target" |) + ], + make_dict [] + |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "touched_accounts" |), "add" |), + make_list [ + M.call (| + M.get_name (| globals, "Address" |), + make_list [ + M.get_field (| M.get_name (| globals, "message" |), "target" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + M.get_field (| M.get_name (| globals, "evm" |), "error" |), + (* then *) + ltac:(M.monadic ( +(* At stmt: unsupported node type: AnnAssign *) + let _ := M.assign_local (| + "accounts_to_delete" , + M.call (| + M.get_name (| globals, "set" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "touched_accounts" , + M.call (| + M.get_name (| globals, "set" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "refund_counter" , + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "logs" , + M.get_field (| M.get_name (| globals, "evm" |), "logs" |) + |) in + let _ := M.assign_local (| + "accounts_to_delete" , + M.get_field (| M.get_name (| globals, "evm" |), "accounts_to_delete" |) + |) in + let _ := M.assign_local (| + "touched_accounts" , + M.get_field (| M.get_name (| globals, "evm" |), "touched_accounts" |) + |) in + let _ := M.assign_local (| + "refund_counter" , + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "refund_counter" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "tx_end" , + M.call (| + M.get_name (| globals, "TransactionEnd" |), + make_list [ + BinOp.sub (| + M.get_field (| M.get_name (| globals, "message" |), "gas" |), + M.get_field (| M.get_name (| globals, "evm" |), "gas_left" |) + |); + M.get_field (| M.get_name (| globals, "evm" |), "output" |); + M.get_field (| M.get_name (| globals, "evm" |), "error" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "evm_trace" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "tx_end" |) + ], + make_dict [] + |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, "MessageCallOutput" |), + make_list [], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Definition process_create_message : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "message"; "env" ] |) in + let _ := Constant.str " + Executes a call to create a smart contract. + + Parameters + ---------- + message : + Transaction specific items. + env : + External items required for EVM execution. + + Returns + ------- + evm: :py:class:`~ethereum.cancun.vm.Evm` + Items containing execution specific objects. + " in + let _ := M.call (| + M.get_name (| globals, "begin_transaction" |), + make_list [ + M.get_field (| M.get_name (| globals, "env" |), "state" |); + M.get_field (| M.get_name (| globals, "env" |), "transient_storage" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "destroy_storage" |), + make_list [ + M.get_field (| M.get_name (| globals, "env" |), "state" |); + M.get_field (| M.get_name (| globals, "message" |), "current_target" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "mark_account_created" |), + make_list [ + M.get_field (| M.get_name (| globals, "env" |), "state" |); + M.get_field (| M.get_name (| globals, "message" |), "current_target" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "increment_nonce" |), + make_list [ + M.get_field (| M.get_name (| globals, "env" |), "state" |); + M.get_field (| M.get_name (| globals, "message" |), "current_target" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "evm" , + M.call (| + M.get_name (| globals, "process_message" |), + make_list [ + M.get_name (| globals, "message" |); + M.get_name (| globals, "env" |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + UnOp.not (| M.get_field (| M.get_name (| globals, "evm" |), "error" |) |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "contract_code" , + M.get_field (| M.get_name (| globals, "evm" |), "output" |) + |) in + let _ := M.assign_local (| + "contract_code_gas" , + BinOp.mult (| + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_name (| globals, "contract_code" |) + ], + make_dict [] + |), + M.get_name (| globals, "GAS_CODE_DEPOSIT" |) + |) + |) in +(* At stmt: unsupported node type: Try *) + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, "rollback_transaction" |), + make_list [ + M.get_field (| M.get_name (| globals, "env" |), "state" |); + M.get_field (| M.get_name (| globals, "env" |), "transient_storage" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + )) |) in + let _ := M.return_ (| + M.get_name (| globals, "evm" |) + |) in + M.pure Constant.None_)). + +Definition process_message : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "message"; "env" ] |) in + let _ := Constant.str " + Executes a call to create a smart contract. + + Parameters + ---------- + message : + Transaction specific items. + env : + External items required for EVM execution. + + Returns + ------- + evm: :py:class:`~ethereum.cancun.vm.Evm` + Items containing execution specific objects + " in + let _ := + (* if *) + M.if_then_else (| + Compare.gt (| + M.get_field (| M.get_name (| globals, "message" |), "depth" |), + M.get_name (| globals, "STACK_DEPTH_LIMIT" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.call (| + M.get_name (| globals, "StackDepthLimitError" |), + make_list [ + Constant.str "Stack depth limit reached" + ], + make_dict [] + |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.call (| + M.get_name (| globals, "begin_transaction" |), + make_list [ + M.get_field (| M.get_name (| globals, "env" |), "state" |); + M.get_field (| M.get_name (| globals, "env" |), "transient_storage" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "touch_account" |), + make_list [ + M.get_field (| M.get_name (| globals, "env" |), "state" |); + M.get_field (| M.get_name (| globals, "message" |), "current_target" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + BoolOp.and (| + M.get_field (| M.get_name (| globals, "message" |), "should_transfer_value" |), + ltac:(M.monadic ( + Compare.not_eq (| + M.get_field (| M.get_name (| globals, "message" |), "value" |), + Constant.int 0 + |) + )) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, "move_ether" |), + make_list [ + M.get_field (| M.get_name (| globals, "env" |), "state" |); + M.get_field (| M.get_name (| globals, "message" |), "caller" |); + M.get_field (| M.get_name (| globals, "message" |), "current_target" |); + M.get_field (| M.get_name (| globals, "message" |), "value" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "evm" , + M.call (| + M.get_name (| globals, "execute_code" |), + make_list [ + M.get_name (| globals, "message" |); + M.get_name (| globals, "env" |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + M.get_field (| M.get_name (| globals, "evm" |), "error" |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, "rollback_transaction" |), + make_list [ + M.get_field (| M.get_name (| globals, "env" |), "state" |); + M.get_field (| M.get_name (| globals, "env" |), "transient_storage" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, "commit_transaction" |), + make_list [ + M.get_field (| M.get_name (| globals, "env" |), "state" |); + M.get_field (| M.get_name (| globals, "env" |), "transient_storage" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + )) |) in + let _ := M.return_ (| + M.get_name (| globals, "evm" |) + |) in + M.pure Constant.None_)). + +Definition execute_code : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "message"; "env" ] |) in + let _ := Constant.str " + Executes bytecode present in the `message`. + + Parameters + ---------- + message : + Transaction specific items. + env : + External items required for EVM execution. + + Returns + ------- + evm: `ethereum.vm.EVM` + Items containing execution specific objects + " in + let _ := M.assign_local (| + "code" , + M.get_field (| M.get_name (| globals, "message" |), "code" |) + |) in + let _ := M.assign_local (| + "valid_jump_destinations" , + M.call (| + M.get_name (| globals, "get_valid_jump_destinations" |), + make_list [ + M.get_name (| globals, "code" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "evm" , + M.call (| + M.get_name (| globals, "Evm" |), + make_list [], + make_dict [] + |) + |) in +(* At stmt: unsupported node type: Try *) + let _ := M.return_ (| + M.get_name (| globals, "evm" |) + |) in + M.pure Constant.None_)). diff --git a/CoqOfPython/ethereum/cancun/vm/memory.v b/CoqOfPython/ethereum/cancun/vm/memory.v new file mode 100644 index 0000000..71fb1d2 --- /dev/null +++ b/CoqOfPython/ethereum/cancun/vm/memory.v @@ -0,0 +1,166 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.cancun.vm.memory". + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) Memory +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +EVM memory operations. +". + +Axiom ethereum_utils_byte_imports_right_pad_zero_bytes : + IsImported globals "ethereum.utils.byte" "right_pad_zero_bytes". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_Bytes : + IsImported globals "ethereum.base_types" "Bytes". +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". + +Definition memory_write : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "memory"; "start_position"; "value" ] |) in + let _ := Constant.str " + Writes to memory. + + Parameters + ---------- + memory : + Memory contents of the EVM. + start_position : + Starting pointer to the memory. + value : + Data to write to memory. + " in + let _ := M.assign (| + M.slice (| + M.get_name (| globals, "memory" |), + M.get_name (| globals, "start_position" |), + BinOp.add (| + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.get_name (| globals, "start_position" |) + ], + make_dict [] + |), + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_name (| globals, "value" |) + ], + make_dict [] + |) + |), + Constant.None_ + |), + M.get_name (| globals, "value" |) + |) in + M.pure Constant.None_)). + +Definition memory_read_bytes : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "memory"; "start_position"; "size" ] |) in + let _ := Constant.str " + Read bytes from memory. + + Parameters + ---------- + memory : + Memory contents of the EVM. + start_position : + Starting pointer to the memory. + size : + Size of the data that needs to be read from `start_position`. + + Returns + ------- + data_bytes : + Data read from memory. + " in + let _ := M.return_ (| + M.slice (| + M.get_name (| globals, "memory" |), + M.get_name (| globals, "start_position" |), + BinOp.add (| + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.get_name (| globals, "start_position" |) + ], + make_dict [] + |), + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.get_name (| globals, "size" |) + ], + make_dict [] + |) + |), + Constant.None_ + |) + |) in + M.pure Constant.None_)). + +Definition buffer_read : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "buffer"; "start_position"; "size" ] |) in + let _ := Constant.str " + Read bytes from a buffer. Padding with zeros if necessary. + + Parameters + ---------- + buffer : + Memory contents of the EVM. + start_position : + Starting pointer to the memory. + size : + Size of the data that needs to be read from `start_position`. + + Returns + ------- + data_bytes : + Data read from memory. + " in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, "right_pad_zero_bytes" |), + make_list [ + M.slice (| + M.get_name (| globals, "buffer" |), + M.get_name (| globals, "start_position" |), + BinOp.add (| + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.get_name (| globals, "start_position" |) + ], + make_dict [] + |), + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.get_name (| globals, "size" |) + ], + make_dict [] + |) + |), + Constant.None_ + |); + M.get_name (| globals, "size" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). diff --git a/CoqOfPython/ethereum/cancun/vm/precompiled_contracts/__init__.v b/CoqOfPython/ethereum/cancun/vm/precompiled_contracts/__init__.v new file mode 100644 index 0000000..dbf6f8a --- /dev/null +++ b/CoqOfPython/ethereum/cancun/vm/precompiled_contracts/__init__.v @@ -0,0 +1,126 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.cancun.vm.precompiled_contracts.__init__". + +Definition expr_1 : Value.t := + Constant.str " +Precompiled Contract Addresses +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Addresses of precompiled contracts and mappings to their +implementations. +". + +Axiom ethereum_cancun_utils_hexadecimal_imports_hex_to_address : + IsImported globals "ethereum.cancun.utils.hexadecimal" "hex_to_address". + +Definition __all__ : Value.t := M.run ltac:(M.monadic ( + make_tuple [ Constant.str "ECRECOVER_ADDRESS"; Constant.str "SHA256_ADDRESS"; Constant.str "RIPEMD160_ADDRESS"; Constant.str "IDENTITY_ADDRESS"; Constant.str "MODEXP_ADDRESS"; Constant.str "ALT_BN128_ADD_ADDRESS"; Constant.str "ALT_BN128_MUL_ADDRESS"; Constant.str "ALT_BN128_PAIRING_CHECK_ADDRESS"; Constant.str "BLAKE2F_ADDRESS"; Constant.str "POINT_EVALUATION_ADDRESS" ] +)). + +Definition ECRECOVER_ADDRESS : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "hex_to_address" |), + make_list [ + Constant.str "0x01" + ], + make_dict [] + |) +)). + +Definition SHA256_ADDRESS : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "hex_to_address" |), + make_list [ + Constant.str "0x02" + ], + make_dict [] + |) +)). + +Definition RIPEMD160_ADDRESS : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "hex_to_address" |), + make_list [ + Constant.str "0x03" + ], + make_dict [] + |) +)). + +Definition IDENTITY_ADDRESS : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "hex_to_address" |), + make_list [ + Constant.str "0x04" + ], + make_dict [] + |) +)). + +Definition MODEXP_ADDRESS : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "hex_to_address" |), + make_list [ + Constant.str "0x05" + ], + make_dict [] + |) +)). + +Definition ALT_BN128_ADD_ADDRESS : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "hex_to_address" |), + make_list [ + Constant.str "0x06" + ], + make_dict [] + |) +)). + +Definition ALT_BN128_MUL_ADDRESS : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "hex_to_address" |), + make_list [ + Constant.str "0x07" + ], + make_dict [] + |) +)). + +Definition ALT_BN128_PAIRING_CHECK_ADDRESS : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "hex_to_address" |), + make_list [ + Constant.str "0x08" + ], + make_dict [] + |) +)). + +Definition BLAKE2F_ADDRESS : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "hex_to_address" |), + make_list [ + Constant.str "0x09" + ], + make_dict [] + |) +)). + +Definition POINT_EVALUATION_ADDRESS : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "hex_to_address" |), + make_list [ + Constant.str "0x0a" + ], + make_dict [] + |) +)). diff --git a/CoqOfPython/ethereum/cancun/vm/precompiled_contracts/alt_bn128.v b/CoqOfPython/ethereum/cancun/vm/precompiled_contracts/alt_bn128.v new file mode 100644 index 0000000..ec05c60 --- /dev/null +++ b/CoqOfPython/ethereum/cancun/vm/precompiled_contracts/alt_bn128.v @@ -0,0 +1,778 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.cancun.vm.precompiled_contracts.alt_bn128". + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) ALT_BN128 CONTRACTS +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementation of the ALT_BN128 precompiled contracts. +". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". + +Axiom ethereum_crypto_alt_bn128_imports_ALT_BN128_CURVE_ORDER : + IsImported globals "ethereum.crypto.alt_bn128" "ALT_BN128_CURVE_ORDER". +Axiom ethereum_crypto_alt_bn128_imports_ALT_BN128_PRIME : + IsImported globals "ethereum.crypto.alt_bn128" "ALT_BN128_PRIME". +Axiom ethereum_crypto_alt_bn128_imports_BNF : + IsImported globals "ethereum.crypto.alt_bn128" "BNF". +Axiom ethereum_crypto_alt_bn128_imports_BNF2 : + IsImported globals "ethereum.crypto.alt_bn128" "BNF2". +Axiom ethereum_crypto_alt_bn128_imports_BNF12 : + IsImported globals "ethereum.crypto.alt_bn128" "BNF12". +Axiom ethereum_crypto_alt_bn128_imports_BNP : + IsImported globals "ethereum.crypto.alt_bn128" "BNP". +Axiom ethereum_crypto_alt_bn128_imports_BNP2 : + IsImported globals "ethereum.crypto.alt_bn128" "BNP2". +Axiom ethereum_crypto_alt_bn128_imports_pairing : + IsImported globals "ethereum.crypto.alt_bn128" "pairing". + +Axiom ethereum_utils_ensure_imports_ensure : + IsImported globals "ethereum.utils.ensure" "ensure". + +Axiom ethereum_cancun_vm_imports_Evm : + IsImported globals "ethereum.cancun.vm" "Evm". + +Axiom ethereum_cancun_vm_gas_imports_charge_gas : + IsImported globals "ethereum.cancun.vm.gas" "charge_gas". + +Axiom ethereum_cancun_vm_memory_imports_buffer_read : + IsImported globals "ethereum.cancun.vm.memory" "buffer_read". + +Axiom ethereum_cancun_vm_exceptions_imports_OutOfGasError : + IsImported globals "ethereum.cancun.vm.exceptions" "OutOfGasError". + +Definition alt_bn128_add : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + The ALT_BN128 addition precompiled contract. + + Parameters + ---------- + evm : + The current EVM frame. + " in + let _ := M.assign_local (| + "data" , + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "data" |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 150 + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "x0_bytes" , + M.call (| + M.get_name (| globals, "buffer_read" |), + make_list [ + M.get_name (| globals, "data" |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 32 + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "x0_value" , + M.call (| + M.get_field (| M.get_name (| globals, "U256" |), "from_be_bytes" |), + make_list [ + M.get_name (| globals, "x0_bytes" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "y0_bytes" , + M.call (| + M.get_name (| globals, "buffer_read" |), + make_list [ + M.get_name (| globals, "data" |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 32 + ], + make_dict [] + |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 32 + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "y0_value" , + M.call (| + M.get_field (| M.get_name (| globals, "U256" |), "from_be_bytes" |), + make_list [ + M.get_name (| globals, "y0_bytes" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "x1_bytes" , + M.call (| + M.get_name (| globals, "buffer_read" |), + make_list [ + M.get_name (| globals, "data" |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 64 + ], + make_dict [] + |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 32 + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "x1_value" , + M.call (| + M.get_field (| M.get_name (| globals, "U256" |), "from_be_bytes" |), + make_list [ + M.get_name (| globals, "x1_bytes" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "y1_bytes" , + M.call (| + M.get_name (| globals, "buffer_read" |), + make_list [ + M.get_name (| globals, "data" |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 96 + ], + make_dict [] + |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 32 + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "y1_value" , + M.call (| + M.get_field (| M.get_name (| globals, "U256" |), "from_be_bytes" |), + make_list [ + M.get_name (| globals, "y1_bytes" |) + ], + make_dict [] + |) + |) in + let _ := + M.for_ (| + M.get_name (| globals, "i" |), + make_tuple [ M.get_name (| globals, "x0_value" |); M.get_name (| globals, "y0_value" |); M.get_name (| globals, "x1_value" |); M.get_name (| globals, "y1_value" |) ], + ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + Compare.gt_e (| + M.get_name (| globals, "i" |), + M.get_name (| globals, "ALT_BN128_PRIME" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, "OutOfGasError" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in +(* At stmt: unsupported node type: Try *) + let _ := M.assign_local (| + "p" , + BinOp.add (| + M.get_name (| globals, "p0" |), + M.get_name (| globals, "p1" |) + |) + |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, "evm" |), "output" |), + BinOp.add (| + M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, "p" |), "x" |), "to_be_bytes32" |), + make_list [], + make_dict [] + |), + M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, "p" |), "y" |), "to_be_bytes32" |), + make_list [], + make_dict [] + |) + |) + |) in + M.pure Constant.None_)). + +Definition alt_bn128_mul : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + The ALT_BN128 multiplication precompiled contract. + + Parameters + ---------- + evm : + The current EVM frame. + " in + let _ := M.assign_local (| + "data" , + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "data" |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 6000 + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "x0_bytes" , + M.call (| + M.get_name (| globals, "buffer_read" |), + make_list [ + M.get_name (| globals, "data" |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 32 + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "x0_value" , + M.call (| + M.get_field (| M.get_name (| globals, "U256" |), "from_be_bytes" |), + make_list [ + M.get_name (| globals, "x0_bytes" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "y0_bytes" , + M.call (| + M.get_name (| globals, "buffer_read" |), + make_list [ + M.get_name (| globals, "data" |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 32 + ], + make_dict [] + |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 32 + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "y0_value" , + M.call (| + M.get_field (| M.get_name (| globals, "U256" |), "from_be_bytes" |), + make_list [ + M.get_name (| globals, "y0_bytes" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "n" , + M.call (| + M.get_field (| M.get_name (| globals, "U256" |), "from_be_bytes" |), + make_list [ + M.call (| + M.get_name (| globals, "buffer_read" |), + make_list [ + M.get_name (| globals, "data" |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 64 + ], + make_dict [] + |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 32 + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := + M.for_ (| + M.get_name (| globals, "i" |), + make_tuple [ M.get_name (| globals, "x0_value" |); M.get_name (| globals, "y0_value" |) ], + ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + Compare.gt_e (| + M.get_name (| globals, "i" |), + M.get_name (| globals, "ALT_BN128_PRIME" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, "OutOfGasError" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in +(* At stmt: unsupported node type: Try *) + let _ := M.assign_local (| + "p" , + M.call (| + M.get_field (| M.get_name (| globals, "p0" |), "mul_by" |), + make_list [ + M.get_name (| globals, "n" |) + ], + make_dict [] + |) + |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, "evm" |), "output" |), + BinOp.add (| + M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, "p" |), "x" |), "to_be_bytes32" |), + make_list [], + make_dict [] + |), + M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, "p" |), "y" |), "to_be_bytes32" |), + make_list [], + make_dict [] + |) + |) + |) in + M.pure Constant.None_)). + +Definition alt_bn128_pairing_check : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + The ALT_BN128 pairing check precompiled contract. + + Parameters + ---------- + evm : + The current EVM frame. + " in + let _ := M.assign_local (| + "data" , + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "data" |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + BinOp.add (| + BinOp.mult (| + Constant.int 34000, + BinOp.floor_div (| + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_name (| globals, "data" |) + ], + make_dict [] + |), + Constant.int 192 + |) + |), + Constant.int 45000 + |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.not_eq (| + BinOp.mod_ (| + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_name (| globals, "data" |) + ], + make_dict [] + |), + Constant.int 192 + |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, "OutOfGasError" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "result" , + M.call (| + M.get_field (| M.get_name (| globals, "BNF12" |), "from_int" |), + make_list [ + Constant.int 1 + ], + make_dict [] + |) + |) in + let _ := + M.for_ (| + M.get_name (| globals, "i" |), + M.call (| + M.get_name (| globals, "range" |), + make_list [ + BinOp.floor_div (| + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_name (| globals, "data" |) + ], + make_dict [] + |), + Constant.int 192 + |) + ], + make_dict [] + |), + ltac:(M.monadic ( + let _ := M.assign_local (| + "values" , + make_list [] + |) in + let _ := + M.for_ (| + M.get_name (| globals, "j" |), + M.call (| + M.get_name (| globals, "range" |), + make_list [ + Constant.int 6 + ], + make_dict [] + |), + ltac:(M.monadic ( + let _ := M.assign_local (| + "value" , + M.call (| + M.get_field (| M.get_name (| globals, "U256" |), "from_be_bytes" |), + make_list [ + M.slice (| + M.get_name (| globals, "data" |), + BinOp.add (| + BinOp.mult (| + M.get_name (| globals, "i" |), + Constant.int 192 + |), + BinOp.mult (| + Constant.int 32, + M.get_name (| globals, "j" |) + |) + |), + BinOp.add (| + BinOp.mult (| + M.get_name (| globals, "i" |), + Constant.int 192 + |), + BinOp.mult (| + Constant.int 32, + BinOp.add (| + M.get_name (| globals, "j" |), + Constant.int 1 + |) + |) + |), + Constant.None_ + |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.gt_e (| + M.get_name (| globals, "value" |), + M.get_name (| globals, "ALT_BN128_PRIME" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, "OutOfGasError" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.call (| + M.get_field (| M.get_name (| globals, "values" |), "append" |), + make_list [ + M.call (| + M.get_name (| globals, "int" |), + make_list [ + M.get_name (| globals, "value" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in +(* At stmt: unsupported node type: Try *) + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + Compare.eq (| + M.call (| + M.get_field (| M.get_name (| globals, "p" |), "mul_by" |), + make_list [ + M.get_name (| globals, "ALT_BN128_CURVE_ORDER" |) + ], + make_dict [] + |), + M.call (| + M.get_field (| M.get_name (| globals, "BNP" |), "point_at_infinity" |), + make_list [], + make_dict [] + |) + |); + M.get_name (| globals, "OutOfGasError" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + Compare.eq (| + M.call (| + M.get_field (| M.get_name (| globals, "q" |), "mul_by" |), + make_list [ + M.get_name (| globals, "ALT_BN128_CURVE_ORDER" |) + ], + make_dict [] + |), + M.call (| + M.get_field (| M.get_name (| globals, "BNP2" |), "point_at_infinity" |), + make_list [], + make_dict [] + |) + |); + M.get_name (| globals, "OutOfGasError" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + BoolOp.and (| + Compare.not_eq (| + M.get_name (| globals, "p" |), + M.call (| + M.get_field (| M.get_name (| globals, "BNP" |), "point_at_infinity" |), + make_list [], + make_dict [] + |) + |), + ltac:(M.monadic ( + Compare.not_eq (| + M.get_name (| globals, "q" |), + M.call (| + M.get_field (| M.get_name (| globals, "BNP2" |), "point_at_infinity" |), + make_list [], + make_dict [] + |) + |) + )) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "result" , + BinOp.mult (| + M.get_name (| globals, "result" |), + M.call (| + M.get_name (| globals, "pairing" |), + make_list [ + M.get_name (| globals, "q" |); + M.get_name (| globals, "p" |) + ], + make_dict [] + |) + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, "result" |), + M.call (| + M.get_field (| M.get_name (| globals, "BNF12" |), "from_int" |), + make_list [ + Constant.int 1 + ], + make_dict [] + |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign (| + M.get_field (| M.get_name (| globals, "evm" |), "output" |), + M.call (| + M.get_field (| M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 1 + ], + make_dict [] + |), "to_be_bytes32" |), + make_list [], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign (| + M.get_field (| M.get_name (| globals, "evm" |), "output" |), + M.call (| + M.get_field (| M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |), "to_be_bytes32" |), + make_list [], + make_dict [] + |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_)). diff --git a/CoqOfPython/ethereum/cancun/vm/precompiled_contracts/blake2f.v b/CoqOfPython/ethereum/cancun/vm/precompiled_contracts/blake2f.v new file mode 100644 index 0000000..9f5c33f --- /dev/null +++ b/CoqOfPython/ethereum/cancun/vm/precompiled_contracts/blake2f.v @@ -0,0 +1,127 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.cancun.vm.precompiled_contracts.blake2f". + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) Blake2 PRECOMPILED CONTRACT +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementation of the `Blake2` precompiled contract. +". + +Axiom ethereum_crypto_blake2_imports_Blake2b : + IsImported globals "ethereum.crypto.blake2" "Blake2b". + +Axiom ethereum_utils_ensure_imports_ensure : + IsImported globals "ethereum.utils.ensure" "ensure". + +Axiom ethereum_cancun_vm_imports_Evm : + IsImported globals "ethereum.cancun.vm" "Evm". + +Axiom ethereum_cancun_vm_gas_imports_GAS_BLAKE2_PER_ROUND : + IsImported globals "ethereum.cancun.vm.gas" "GAS_BLAKE2_PER_ROUND". +Axiom ethereum_cancun_vm_gas_imports_charge_gas : + IsImported globals "ethereum.cancun.vm.gas" "charge_gas". + +Axiom ethereum_cancun_vm_exceptions_imports_InvalidParameter : + IsImported globals "ethereum.cancun.vm.exceptions" "InvalidParameter". + +Definition blake2f : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Writes the Blake2 hash to output. + + Parameters + ---------- + evm : + The current EVM frame. + " in + let _ := M.assign_local (| + "data" , + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "data" |) + |) in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + Compare.eq (| + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_name (| globals, "data" |) + ], + make_dict [] + |), + Constant.int 213 + |); + M.get_name (| globals, "InvalidParameter" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "blake2b" , + M.call (| + M.get_name (| globals, "Blake2b" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.assign (| + make_tuple [ M.get_name (| globals, "rounds" |); M.get_name (| globals, "h" |); M.get_name (| globals, "m" |); M.get_name (| globals, "t_0" |); M.get_name (| globals, "t_1" |); M.get_name (| globals, "f" |) ], + M.call (| + M.get_field (| M.get_name (| globals, "blake2b" |), "get_blake2_parameters" |), + make_list [ + M.get_name (| globals, "data" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + BinOp.mult (| + M.get_name (| globals, "GAS_BLAKE2_PER_ROUND" |), + M.get_name (| globals, "rounds" |) + |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + Compare.in_ (| + M.get_name (| globals, "f" |), + make_list [ + Constant.int 0; + Constant.int 1 + ] + |); + M.get_name (| globals, "InvalidParameter" |) + ], + make_dict [] + |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, "evm" |), "output" |), + M.call (| + M.get_field (| M.get_name (| globals, "blake2b" |), "compress" |), + make_list [ + M.get_name (| globals, "rounds" |); + M.get_name (| globals, "h" |); + M.get_name (| globals, "m" |); + M.get_name (| globals, "t_0" |); + M.get_name (| globals, "t_1" |); + M.get_name (| globals, "f" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). diff --git a/CoqOfPython/ethereum/cancun/vm/precompiled_contracts/ecrecover.v b/CoqOfPython/ethereum/cancun/vm/precompiled_contracts/ecrecover.v new file mode 100644 index 0000000..e169b9c --- /dev/null +++ b/CoqOfPython/ethereum/cancun/vm/precompiled_contracts/ecrecover.v @@ -0,0 +1,301 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.cancun.vm.precompiled_contracts.ecrecover". + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) ECRECOVER PRECOMPILED CONTRACT +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementation of the ECRECOVER precompiled contract. +". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". + +Axiom ethereum_crypto_elliptic_curve_imports_SECP256K1N : + IsImported globals "ethereum.crypto.elliptic_curve" "SECP256K1N". +Axiom ethereum_crypto_elliptic_curve_imports_secp256k1_recover : + IsImported globals "ethereum.crypto.elliptic_curve" "secp256k1_recover". + +Axiom ethereum_crypto_hash_imports_Hash32 : + IsImported globals "ethereum.crypto.hash" "Hash32". +Axiom ethereum_crypto_hash_imports_keccak256 : + IsImported globals "ethereum.crypto.hash" "keccak256". + +Axiom ethereum_utils_byte_imports_left_pad_zero_bytes : + IsImported globals "ethereum.utils.byte" "left_pad_zero_bytes". + +Axiom ethereum_cancun_vm_imports_Evm : + IsImported globals "ethereum.cancun.vm" "Evm". + +Axiom ethereum_cancun_vm_gas_imports_GAS_ECRECOVER : + IsImported globals "ethereum.cancun.vm.gas" "GAS_ECRECOVER". +Axiom ethereum_cancun_vm_gas_imports_charge_gas : + IsImported globals "ethereum.cancun.vm.gas" "charge_gas". + +Axiom ethereum_cancun_vm_memory_imports_buffer_read : + IsImported globals "ethereum.cancun.vm.memory" "buffer_read". + +Definition ecrecover : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Decrypts the address using elliptic curve DSA recovery mechanism and writes + the address to output. + + Parameters + ---------- + evm : + The current EVM frame. + " in + let _ := M.assign_local (| + "data" , + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "data" |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_ECRECOVER" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "message_hash_bytes" , + M.call (| + M.get_name (| globals, "buffer_read" |), + make_list [ + M.get_name (| globals, "data" |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 32 + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "message_hash" , + M.call (| + M.get_name (| globals, "Hash32" |), + make_list [ + M.get_name (| globals, "message_hash_bytes" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "v" , + M.call (| + M.get_field (| M.get_name (| globals, "U256" |), "from_be_bytes" |), + make_list [ + M.call (| + M.get_name (| globals, "buffer_read" |), + make_list [ + M.get_name (| globals, "data" |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 32 + ], + make_dict [] + |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 32 + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "r" , + M.call (| + M.get_field (| M.get_name (| globals, "U256" |), "from_be_bytes" |), + make_list [ + M.call (| + M.get_name (| globals, "buffer_read" |), + make_list [ + M.get_name (| globals, "data" |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 64 + ], + make_dict [] + |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 32 + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "s" , + M.call (| + M.get_field (| M.get_name (| globals, "U256" |), "from_be_bytes" |), + make_list [ + M.call (| + M.get_name (| globals, "buffer_read" |), + make_list [ + M.get_name (| globals, "data" |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 96 + ], + make_dict [] + |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 32 + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + BoolOp.and (| + Compare.not_eq (| + M.get_name (| globals, "v" |), + Constant.int 27 + |), + ltac:(M.monadic ( + Compare.not_eq (| + M.get_name (| globals, "v" |), + Constant.int 28 + |) + )) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + Constant.None_ + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + BoolOp.or (| + Compare.gt_e (| + Constant.int 0, + M.get_name (| globals, "r" |) + |), + ltac:(M.monadic ( + Compare.gt_e (| + M.get_name (| globals, "r" |), + M.get_name (| globals, "SECP256K1N" |) + |) + )) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + Constant.None_ + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + BoolOp.or (| + Compare.gt_e (| + Constant.int 0, + M.get_name (| globals, "s" |) + |), + ltac:(M.monadic ( + Compare.gt_e (| + M.get_name (| globals, "s" |), + M.get_name (| globals, "SECP256K1N" |) + |) + )) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + Constant.None_ + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in +(* At stmt: unsupported node type: Try *) + let _ := M.assign_local (| + "address" , + M.slice (| + M.call (| + M.get_name (| globals, "keccak256" |), + make_list [ + M.get_name (| globals, "public_key" |) + ], + make_dict [] + |), + Constant.int 12, + Constant.int 32, + Constant.None_ + |) + |) in + let _ := M.assign_local (| + "padded_address" , + M.call (| + M.get_name (| globals, "left_pad_zero_bytes" |), + make_list [ + M.get_name (| globals, "address" |); + Constant.int 32 + ], + make_dict [] + |) + |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, "evm" |), "output" |), + M.get_name (| globals, "padded_address" |) + |) in + M.pure Constant.None_)). diff --git a/CoqOfPython/ethereum/cancun/vm/precompiled_contracts/identity.v b/CoqOfPython/ethereum/cancun/vm/precompiled_contracts/identity.v new file mode 100644 index 0000000..bedd17c --- /dev/null +++ b/CoqOfPython/ethereum/cancun/vm/precompiled_contracts/identity.v @@ -0,0 +1,94 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.cancun.vm.precompiled_contracts.identity". + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) IDENTITY PRECOMPILED CONTRACT +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementation of the `IDENTITY` precompiled contract. +". + +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". + +Axiom ethereum_utils_numeric_imports_ceil32 : + IsImported globals "ethereum.utils.numeric" "ceil32". + +Axiom ethereum_cancun_vm_imports_Evm : + IsImported globals "ethereum.cancun.vm" "Evm". + +Axiom ethereum_cancun_vm_gas_imports_GAS_IDENTITY : + IsImported globals "ethereum.cancun.vm.gas" "GAS_IDENTITY". +Axiom ethereum_cancun_vm_gas_imports_GAS_IDENTITY_WORD : + IsImported globals "ethereum.cancun.vm.gas" "GAS_IDENTITY_WORD". +Axiom ethereum_cancun_vm_gas_imports_charge_gas : + IsImported globals "ethereum.cancun.vm.gas" "charge_gas". + +Definition identity : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Writes the message data to output. + + Parameters + ---------- + evm : + The current EVM frame. + " in + let _ := M.assign_local (| + "data" , + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "data" |) + |) in + let _ := M.assign_local (| + "word_count" , + BinOp.floor_div (| + M.call (| + M.get_name (| globals, "ceil32" |), + make_list [ + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_name (| globals, "data" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |), + Constant.int 32 + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + BinOp.add (| + M.get_name (| globals, "GAS_IDENTITY" |), + BinOp.mult (| + M.get_name (| globals, "GAS_IDENTITY_WORD" |), + M.get_name (| globals, "word_count" |) + |) + |) + ], + make_dict [] + |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, "evm" |), "output" |), + M.get_name (| globals, "data" |) + |) in + M.pure Constant.None_)). diff --git a/CoqOfPython/ethereum/cancun/vm/precompiled_contracts/mapping.v b/CoqOfPython/ethereum/cancun/vm/precompiled_contracts/mapping.v new file mode 100644 index 0000000..e780b97 --- /dev/null +++ b/CoqOfPython/ethereum/cancun/vm/precompiled_contracts/mapping.v @@ -0,0 +1,77 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.cancun.vm.precompiled_contracts.mapping". + +Definition expr_1 : Value.t := + Constant.str " +Precompiled Contract Addresses +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Mapping of precompiled contracts their implementations. +". + +Axiom typing_imports_Callable : + IsImported globals "typing" "Callable". +Axiom typing_imports_Dict : + IsImported globals "typing" "Dict". + +Axiom ethereum_cancun_fork_types_imports_Address : + IsImported globals "ethereum.cancun.fork_types" "Address". + +Axiom ethereum_cancun_vm_precompiled_contracts_imports_ALT_BN128_ADD_ADDRESS : + IsImported globals "ethereum.cancun.vm.precompiled_contracts" "ALT_BN128_ADD_ADDRESS". +Axiom ethereum_cancun_vm_precompiled_contracts_imports_ALT_BN128_MUL_ADDRESS : + IsImported globals "ethereum.cancun.vm.precompiled_contracts" "ALT_BN128_MUL_ADDRESS". +Axiom ethereum_cancun_vm_precompiled_contracts_imports_ALT_BN128_PAIRING_CHECK_ADDRESS : + IsImported globals "ethereum.cancun.vm.precompiled_contracts" "ALT_BN128_PAIRING_CHECK_ADDRESS". +Axiom ethereum_cancun_vm_precompiled_contracts_imports_BLAKE2F_ADDRESS : + IsImported globals "ethereum.cancun.vm.precompiled_contracts" "BLAKE2F_ADDRESS". +Axiom ethereum_cancun_vm_precompiled_contracts_imports_ECRECOVER_ADDRESS : + IsImported globals "ethereum.cancun.vm.precompiled_contracts" "ECRECOVER_ADDRESS". +Axiom ethereum_cancun_vm_precompiled_contracts_imports_IDENTITY_ADDRESS : + IsImported globals "ethereum.cancun.vm.precompiled_contracts" "IDENTITY_ADDRESS". +Axiom ethereum_cancun_vm_precompiled_contracts_imports_MODEXP_ADDRESS : + IsImported globals "ethereum.cancun.vm.precompiled_contracts" "MODEXP_ADDRESS". +Axiom ethereum_cancun_vm_precompiled_contracts_imports_POINT_EVALUATION_ADDRESS : + IsImported globals "ethereum.cancun.vm.precompiled_contracts" "POINT_EVALUATION_ADDRESS". +Axiom ethereum_cancun_vm_precompiled_contracts_imports_RIPEMD160_ADDRESS : + IsImported globals "ethereum.cancun.vm.precompiled_contracts" "RIPEMD160_ADDRESS". +Axiom ethereum_cancun_vm_precompiled_contracts_imports_SHA256_ADDRESS : + IsImported globals "ethereum.cancun.vm.precompiled_contracts" "SHA256_ADDRESS". + +Axiom ethereum_cancun_vm_precompiled_contracts_alt_bn128_imports_alt_bn128_add : + IsImported globals "ethereum.cancun.vm.precompiled_contracts.alt_bn128" "alt_bn128_add". +Axiom ethereum_cancun_vm_precompiled_contracts_alt_bn128_imports_alt_bn128_mul : + IsImported globals "ethereum.cancun.vm.precompiled_contracts.alt_bn128" "alt_bn128_mul". +Axiom ethereum_cancun_vm_precompiled_contracts_alt_bn128_imports_alt_bn128_pairing_check : + IsImported globals "ethereum.cancun.vm.precompiled_contracts.alt_bn128" "alt_bn128_pairing_check". + +Axiom ethereum_cancun_vm_precompiled_contracts_blake2f_imports_blake2f : + IsImported globals "ethereum.cancun.vm.precompiled_contracts.blake2f" "blake2f". + +Axiom ethereum_cancun_vm_precompiled_contracts_ecrecover_imports_ecrecover : + IsImported globals "ethereum.cancun.vm.precompiled_contracts.ecrecover" "ecrecover". + +Axiom ethereum_cancun_vm_precompiled_contracts_identity_imports_identity : + IsImported globals "ethereum.cancun.vm.precompiled_contracts.identity" "identity". + +Axiom ethereum_cancun_vm_precompiled_contracts_modexp_imports_modexp : + IsImported globals "ethereum.cancun.vm.precompiled_contracts.modexp" "modexp". + +Axiom ethereum_cancun_vm_precompiled_contracts_point_evaluation_imports_point_evaluation : + IsImported globals "ethereum.cancun.vm.precompiled_contracts.point_evaluation" "point_evaluation". + +Axiom ethereum_cancun_vm_precompiled_contracts_ripemd160_imports_ripemd160 : + IsImported globals "ethereum.cancun.vm.precompiled_contracts.ripemd160" "ripemd160". + +Axiom ethereum_cancun_vm_precompiled_contracts_sha256_imports_sha256 : + IsImported globals "ethereum.cancun.vm.precompiled_contracts.sha256" "sha256". + +(* At top_level_stmt: unsupported node type: AnnAssign *) diff --git a/CoqOfPython/ethereum/cancun/vm/precompiled_contracts/modexp.v b/CoqOfPython/ethereum/cancun/vm/precompiled_contracts/modexp.v new file mode 100644 index 0000000..ec4e35a --- /dev/null +++ b/CoqOfPython/ethereum/cancun/vm/precompiled_contracts/modexp.v @@ -0,0 +1,676 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.cancun.vm.precompiled_contracts.modexp". + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) MODEXP PRECOMPILED CONTRACT +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementation of the `MODEXP` precompiled contract. +". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_Bytes : + IsImported globals "ethereum.base_types" "Bytes". +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". + +Axiom ethereum_cancun_vm_imports_Evm : + IsImported globals "ethereum.cancun.vm" "Evm". + +Axiom ethereum_cancun_vm_gas_imports_charge_gas : + IsImported globals "ethereum.cancun.vm.gas" "charge_gas". + +Axiom ethereum_cancun_vm_memory_imports_buffer_read : + IsImported globals "ethereum.cancun.vm.memory" "buffer_read". + +Definition GQUADDIVISOR : Value.t := M.run ltac:(M.monadic ( + Constant.int 3 +)). + +Definition modexp : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Calculates `(base**exp) % modulus` for arbitrary sized `base`, `exp` and. + `modulus`. The return value is the same length as the modulus. + " in + let _ := M.assign_local (| + "data" , + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "data" |) + |) in + let _ := M.assign_local (| + "base_length" , + M.call (| + M.get_field (| M.get_name (| globals, "U256" |), "from_be_bytes" |), + make_list [ + M.call (| + M.get_name (| globals, "buffer_read" |), + make_list [ + M.get_name (| globals, "data" |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 32 + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "exp_length" , + M.call (| + M.get_field (| M.get_name (| globals, "U256" |), "from_be_bytes" |), + make_list [ + M.call (| + M.get_name (| globals, "buffer_read" |), + make_list [ + M.get_name (| globals, "data" |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 32 + ], + make_dict [] + |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 32 + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "modulus_length" , + M.call (| + M.get_field (| M.get_name (| globals, "U256" |), "from_be_bytes" |), + make_list [ + M.call (| + M.get_name (| globals, "buffer_read" |), + make_list [ + M.get_name (| globals, "data" |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 64 + ], + make_dict [] + |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 32 + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "exp_start" , + BinOp.add (| + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 96 + ], + make_dict [] + |), + M.get_name (| globals, "base_length" |) + |) + |) in + let _ := M.assign_local (| + "exp_head" , + M.call (| + M.get_field (| M.get_name (| globals, "Uint" |), "from_be_bytes" |), + make_list [ + M.call (| + M.get_name (| globals, "buffer_read" |), + make_list [ + M.get_name (| globals, "data" |); + M.get_name (| globals, "exp_start" |); + M.call (| + M.get_name (| globals, "min" |), + make_list [ + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 32 + ], + make_dict [] + |); + M.get_name (| globals, "exp_length" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.call (| + M.get_name (| globals, "gas_cost" |), + make_list [ + M.get_name (| globals, "base_length" |); + M.get_name (| globals, "modulus_length" |); + M.get_name (| globals, "exp_length" |); + M.get_name (| globals, "exp_head" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + BoolOp.and (| + Compare.eq (| + M.get_name (| globals, "base_length" |), + Constant.int 0 + |), + ltac:(M.monadic ( + Compare.eq (| + M.get_name (| globals, "modulus_length" |), + Constant.int 0 + |) + )) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign (| + M.get_field (| M.get_name (| globals, "evm" |), "output" |), + M.call (| + M.get_name (| globals, "Bytes" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.return_ (| + Constant.None_ + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "base" , + M.call (| + M.get_field (| M.get_name (| globals, "Uint" |), "from_be_bytes" |), + make_list [ + M.call (| + M.get_name (| globals, "buffer_read" |), + make_list [ + M.get_name (| globals, "data" |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 96 + ], + make_dict [] + |); + M.get_name (| globals, "base_length" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "exp" , + M.call (| + M.get_field (| M.get_name (| globals, "Uint" |), "from_be_bytes" |), + make_list [ + M.call (| + M.get_name (| globals, "buffer_read" |), + make_list [ + M.get_name (| globals, "data" |); + M.get_name (| globals, "exp_start" |); + M.get_name (| globals, "exp_length" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "modulus_start" , + BinOp.add (| + M.get_name (| globals, "exp_start" |), + M.get_name (| globals, "exp_length" |) + |) + |) in + let _ := M.assign_local (| + "modulus" , + M.call (| + M.get_field (| M.get_name (| globals, "Uint" |), "from_be_bytes" |), + make_list [ + M.call (| + M.get_name (| globals, "buffer_read" |), + make_list [ + M.get_name (| globals, "data" |); + M.get_name (| globals, "modulus_start" |); + M.get_name (| globals, "modulus_length" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, "modulus" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign (| + M.get_field (| M.get_name (| globals, "evm" |), "output" |), + BinOp.mult (| + M.call (| + M.get_name (| globals, "Bytes" |), + make_list [ + Constant.bytes "00" + ], + make_dict [] + |), + M.get_name (| globals, "modulus_length" |) + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign (| + M.get_field (| M.get_name (| globals, "evm" |), "output" |), + M.call (| + M.get_field (| M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, "pow" |), + make_list [ + M.get_name (| globals, "base" |); + M.get_name (| globals, "exp" |); + M.get_name (| globals, "modulus" |) + ], + make_dict [] + |) + ], + make_dict [] + |), "to_bytes" |), + make_list [ + M.get_name (| globals, "modulus_length" |); + Constant.str "big" + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_)). + +Definition complexity : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "base_length"; "modulus_length" ] |) in + let _ := Constant.str " + Estimate the complexity of performing a modular exponentiation. + + Parameters + ---------- + + base_length : + Length of the array representing the base integer. + + modulus_length : + Length of the array representing the modulus integer. + + Returns + ------- + + complexity : `Uint` + Complexity of performing the operation. + " in + let _ := M.assign_local (| + "max_length" , + M.call (| + M.get_name (| globals, "max" |), + make_list [ + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.get_name (| globals, "base_length" |) + ], + make_dict [] + |); + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.get_name (| globals, "modulus_length" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "words" , + BinOp.floor_div (| + BinOp.add (| + M.get_name (| globals, "max_length" |), + Constant.int 7 + |), + Constant.int 8 + |) + |) in + let _ := M.return_ (| + BinOp.pow (| + M.get_name (| globals, "words" |), + Constant.int 2 + |) + |) in + M.pure Constant.None_)). + +Definition iterations : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "exponent_length"; "exponent_head" ] |) in + let _ := Constant.str " + Calculate the number of iterations required to perform a modular + exponentiation. + + Parameters + ---------- + + exponent_length : + Length of the array representing the exponent integer. + + exponent_head : + First 32 bytes of the exponent (with leading zero padding if it is + shorter than 32 bytes), as an unsigned integer. + + Returns + ------- + + iterations : `Uint` + Number of iterations. + " in + let _ := + (* if *) + M.if_then_else (| + BoolOp.and (| + Compare.lt_e (| + M.get_name (| globals, "exponent_length" |), + Constant.int 32 + |), + ltac:(M.monadic ( + Compare.eq (| + M.get_name (| globals, "exponent_head" |), + Constant.int 0 + |) + )) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "count" , + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + Compare.lt_e (| + M.get_name (| globals, "exponent_length" |), + Constant.int 32 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "bit_length" , + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.call (| + M.get_field (| M.get_name (| globals, "exponent_head" |), "bit_length" |), + make_list [], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.gt (| + M.get_name (| globals, "bit_length" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_op_local (| + BinOp.sub, + "bit_length", + Constant.int 1 + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "count" , + M.get_name (| globals, "bit_length" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "length_part" , + BinOp.mult (| + Constant.int 8, + BinOp.sub (| + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.get_name (| globals, "exponent_length" |) + ], + make_dict [] + |), + Constant.int 32 + |) + |) + |) in + let _ := M.assign_local (| + "bits_part" , + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.call (| + M.get_field (| M.get_name (| globals, "exponent_head" |), "bit_length" |), + make_list [], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.gt (| + M.get_name (| globals, "bits_part" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_op_local (| + BinOp.sub, + "bits_part", + Constant.int 1 + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "count" , + BinOp.add (| + M.get_name (| globals, "length_part" |), + M.get_name (| globals, "bits_part" |) + |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )) |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, "max" |), + make_list [ + M.get_name (| globals, "count" |); + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 1 + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Definition gas_cost : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "base_length"; "modulus_length"; "exponent_length"; "exponent_head" ] |) in + let _ := Constant.str " + Calculate the gas cost of performing a modular exponentiation. + + Parameters + ---------- + + base_length : + Length of the array representing the base integer. + + modulus_length : + Length of the array representing the modulus integer. + + exponent_length : + Length of the array representing the exponent integer. + + exponent_head : + First 32 bytes of the exponent (with leading zero padding if it is + shorter than 32 bytes), as an unsigned integer. + + Returns + ------- + + gas_cost : `Uint` + Gas required for performing the operation. + " in + let _ := M.assign_local (| + "multiplication_complexity" , + M.call (| + M.get_name (| globals, "complexity" |), + make_list [ + M.get_name (| globals, "base_length" |); + M.get_name (| globals, "modulus_length" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "iteration_count" , + M.call (| + M.get_name (| globals, "iterations" |), + make_list [ + M.get_name (| globals, "exponent_length" |); + M.get_name (| globals, "exponent_head" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "cost" , + BinOp.mult (| + M.get_name (| globals, "multiplication_complexity" |), + M.get_name (| globals, "iteration_count" |) + |) + |) in + let _ := M.assign_op_local (| + BinOp.floor_div, + "cost", + M.get_name (| globals, "GQUADDIVISOR" |) + |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, "max" |), + make_list [ + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 200 + ], + make_dict [] + |); + M.get_name (| globals, "cost" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). diff --git a/CoqOfPython/ethereum/cancun/vm/precompiled_contracts/point_evaluation.v b/CoqOfPython/ethereum/cancun/vm/precompiled_contracts/point_evaluation.v new file mode 100644 index 0000000..4b6a5a2 --- /dev/null +++ b/CoqOfPython/ethereum/cancun/vm/precompiled_contracts/point_evaluation.v @@ -0,0 +1,210 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.cancun.vm.precompiled_contracts.point_evaluation". + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) POINT EVALUATION PRECOMPILED CONTRACT +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementation of the POINT EVALUATION precompiled contract. +". + +Axiom eth2spec_deneb_mainnet_imports_KZGCommitment : + IsImported globals "eth2spec.deneb.mainnet" "KZGCommitment". +Axiom eth2spec_deneb_mainnet_imports_kzg_commitment_to_versioned_hash : + IsImported globals "eth2spec.deneb.mainnet" "kzg_commitment_to_versioned_hash". +Axiom eth2spec_deneb_mainnet_imports_verify_kzg_proof : + IsImported globals "eth2spec.deneb.mainnet" "verify_kzg_proof". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_Bytes : + IsImported globals "ethereum.base_types" "Bytes". + +Axiom ethereum_utils_ensure_imports_ensure : + IsImported globals "ethereum.utils.ensure" "ensure". + +Axiom ethereum_cancun_vm_imports_Evm : + IsImported globals "ethereum.cancun.vm" "Evm". + +Axiom ethereum_cancun_vm_exceptions_imports_KZGProofError : + IsImported globals "ethereum.cancun.vm.exceptions" "KZGProofError". + +Axiom ethereum_cancun_vm_gas_imports_GAS_POINT_EVALUATION : + IsImported globals "ethereum.cancun.vm.gas" "GAS_POINT_EVALUATION". +Axiom ethereum_cancun_vm_gas_imports_charge_gas : + IsImported globals "ethereum.cancun.vm.gas" "charge_gas". + +Definition FIELD_ELEMENTS_PER_BLOB : Value.t := M.run ltac:(M.monadic ( + Constant.int 4096 +)). + +Definition BLS_MODULUS : Value.t := M.run ltac:(M.monadic ( + Constant.int 52435875175126190479447740508185965837690552500527637822603658699938581184513 +)). + +Definition VERSIONED_HASH_VERSION_KZG : Value.t := M.run ltac:(M.monadic ( + Constant.bytes "01" +)). + +Definition point_evaluation : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + A pre-compile that verifies a KZG proof which claims that a blob + (represented by a commitment) evaluates to a given value at a given point. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "data" , + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "data" |) + |) in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + Compare.eq (| + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_name (| globals, "data" |) + ], + make_dict [] + |), + Constant.int 192 + |); + M.get_name (| globals, "KZGProofError" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "versioned_hash" , + M.slice (| + M.get_name (| globals, "data" |), + Constant.None_, + Constant.int 32, + Constant.None_ + |) + |) in + let _ := M.assign_local (| + "z" , + M.slice (| + M.get_name (| globals, "data" |), + Constant.int 32, + Constant.int 64, + Constant.None_ + |) + |) in + let _ := M.assign_local (| + "y" , + M.slice (| + M.get_name (| globals, "data" |), + Constant.int 64, + Constant.int 96, + Constant.None_ + |) + |) in + let _ := M.assign_local (| + "commitment" , + M.call (| + M.get_name (| globals, "KZGCommitment" |), + make_list [ + M.slice (| + M.get_name (| globals, "data" |), + Constant.int 96, + Constant.int 144, + Constant.None_ + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "proof" , + M.slice (| + M.get_name (| globals, "data" |), + Constant.int 144, + Constant.int 192, + Constant.None_ + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_POINT_EVALUATION" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + Compare.eq (| + M.call (| + M.get_name (| globals, "kzg_commitment_to_versioned_hash" |), + make_list [ + M.get_name (| globals, "commitment" |) + ], + make_dict [] + |), + M.get_name (| globals, "versioned_hash" |) + |); + M.get_name (| globals, "KZGProofError" |) + ], + make_dict [] + |) in +(* At stmt: unsupported node type: Try *) + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + M.get_name (| globals, "kzg_proof_verification" |); + M.get_name (| globals, "KZGProofError" |) + ], + make_dict [] + |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, "evm" |), "output" |), + M.call (| + M.get_name (| globals, "Bytes" |), + make_list [ + BinOp.add (| + M.call (| + M.get_field (| M.call (| + M.get_name (| globals, "U256" |), + make_list [ + M.get_name (| globals, "FIELD_ELEMENTS_PER_BLOB" |) + ], + make_dict [] + |), "to_be_bytes32" |), + make_list [], + make_dict [] + |), + M.call (| + M.get_field (| M.call (| + M.get_name (| globals, "U256" |), + make_list [ + M.get_name (| globals, "BLS_MODULUS" |) + ], + make_dict [] + |), "to_be_bytes32" |), + make_list [], + make_dict [] + |) + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). diff --git a/CoqOfPython/ethereum/cancun/vm/precompiled_contracts/ripemd160.v b/CoqOfPython/ethereum/cancun/vm/precompiled_contracts/ripemd160.v new file mode 100644 index 0000000..18c8614 --- /dev/null +++ b/CoqOfPython/ethereum/cancun/vm/precompiled_contracts/ripemd160.v @@ -0,0 +1,125 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.cancun.vm.precompiled_contracts.ripemd160". + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) RIPEMD160 PRECOMPILED CONTRACT +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementation of the `RIPEMD160` precompiled contract. +". + +(* At top_level_stmt: unsupported node type: Import *) + +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". + +Axiom ethereum_utils_byte_imports_left_pad_zero_bytes : + IsImported globals "ethereum.utils.byte" "left_pad_zero_bytes". + +Axiom ethereum_utils_numeric_imports_ceil32 : + IsImported globals "ethereum.utils.numeric" "ceil32". + +Axiom ethereum_cancun_vm_imports_Evm : + IsImported globals "ethereum.cancun.vm" "Evm". + +Axiom ethereum_cancun_vm_gas_imports_GAS_RIPEMD160 : + IsImported globals "ethereum.cancun.vm.gas" "GAS_RIPEMD160". +Axiom ethereum_cancun_vm_gas_imports_GAS_RIPEMD160_WORD : + IsImported globals "ethereum.cancun.vm.gas" "GAS_RIPEMD160_WORD". +Axiom ethereum_cancun_vm_gas_imports_charge_gas : + IsImported globals "ethereum.cancun.vm.gas" "charge_gas". + +Definition ripemd160 : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Writes the ripemd160 hash to output. + + Parameters + ---------- + evm : + The current EVM frame. + " in + let _ := M.assign_local (| + "data" , + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "data" |) + |) in + let _ := M.assign_local (| + "word_count" , + BinOp.floor_div (| + M.call (| + M.get_name (| globals, "ceil32" |), + make_list [ + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_name (| globals, "data" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |), + Constant.int 32 + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + BinOp.add (| + M.get_name (| globals, "GAS_RIPEMD160" |), + BinOp.mult (| + M.get_name (| globals, "GAS_RIPEMD160_WORD" |), + M.get_name (| globals, "word_count" |) + |) + |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "hash_bytes" , + M.call (| + M.get_field (| M.call (| + M.get_field (| M.get_name (| globals, "hashlib" |), "new" |), + make_list [ + Constant.str "ripemd160"; + M.get_name (| globals, "data" |) + ], + make_dict [] + |), "digest" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "padded_hash" , + M.call (| + M.get_name (| globals, "left_pad_zero_bytes" |), + make_list [ + M.get_name (| globals, "hash_bytes" |); + Constant.int 32 + ], + make_dict [] + |) + |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, "evm" |), "output" |), + M.get_name (| globals, "padded_hash" |) + |) in + M.pure Constant.None_)). diff --git a/CoqOfPython/ethereum/cancun/vm/precompiled_contracts/sha256.v b/CoqOfPython/ethereum/cancun/vm/precompiled_contracts/sha256.v new file mode 100644 index 0000000..fe7ed42 --- /dev/null +++ b/CoqOfPython/ethereum/cancun/vm/precompiled_contracts/sha256.v @@ -0,0 +1,106 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.cancun.vm.precompiled_contracts.sha256". + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) SHA256 PRECOMPILED CONTRACT +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementation of the `SHA256` precompiled contract. +". + +(* At top_level_stmt: unsupported node type: Import *) + +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". + +Axiom ethereum_utils_numeric_imports_ceil32 : + IsImported globals "ethereum.utils.numeric" "ceil32". + +Axiom ethereum_cancun_vm_imports_Evm : + IsImported globals "ethereum.cancun.vm" "Evm". + +Axiom ethereum_cancun_vm_gas_imports_GAS_SHA256 : + IsImported globals "ethereum.cancun.vm.gas" "GAS_SHA256". +Axiom ethereum_cancun_vm_gas_imports_GAS_SHA256_WORD : + IsImported globals "ethereum.cancun.vm.gas" "GAS_SHA256_WORD". +Axiom ethereum_cancun_vm_gas_imports_charge_gas : + IsImported globals "ethereum.cancun.vm.gas" "charge_gas". + +Definition sha256 : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Writes the sha256 hash to output. + + Parameters + ---------- + evm : + The current EVM frame. + " in + let _ := M.assign_local (| + "data" , + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "data" |) + |) in + let _ := M.assign_local (| + "word_count" , + BinOp.floor_div (| + M.call (| + M.get_name (| globals, "ceil32" |), + make_list [ + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_name (| globals, "data" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |), + Constant.int 32 + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + BinOp.add (| + M.get_name (| globals, "GAS_SHA256" |), + BinOp.mult (| + M.get_name (| globals, "GAS_SHA256_WORD" |), + M.get_name (| globals, "word_count" |) + |) + |) + ], + make_dict [] + |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, "evm" |), "output" |), + M.call (| + M.get_field (| M.call (| + M.get_field (| M.get_name (| globals, "hashlib" |), "sha256" |), + make_list [ + M.get_name (| globals, "data" |) + ], + make_dict [] + |), "digest" |), + make_list [], + make_dict [] + |) + |) in + M.pure Constant.None_)). diff --git a/CoqOfPython/ethereum/cancun/vm/runtime.v b/CoqOfPython/ethereum/cancun/vm/runtime.v new file mode 100644 index 0000000..5c08753 --- /dev/null +++ b/CoqOfPython/ethereum/cancun/vm/runtime.v @@ -0,0 +1,157 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.cancun.vm.runtime". + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) Runtime Operations +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Runtime related operations used while executing EVM code. +". + +Axiom typing_imports_Set : + IsImported globals "typing" "Set". + +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". + +Axiom ethereum_cancun_vm_instructions_imports_Ops : + IsImported globals "ethereum.cancun.vm.instructions" "Ops". + +Definition get_valid_jump_destinations : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "code" ] |) in + let _ := Constant.str " + Analyze the evm code to obtain the set of valid jump destinations. + + Valid jump destinations are defined as follows: + * The jump destination is less than the length of the code. + * The jump destination should have the `JUMPDEST` opcode (0x5B). + * The jump destination shouldn't be part of the data corresponding to + `PUSH-N` opcodes. + + Note - Jump destinations are 0-indexed. + + Parameters + ---------- + code : + The EVM code which is to be executed. + + Returns + ------- + valid_jump_destinations: `Set[Uint]` + The set of valid jump destinations in the code. + " in + let _ := M.assign_local (| + "valid_jump_destinations" , + M.call (| + M.get_name (| globals, "set" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "pc" , + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + |) in + let _ := + M.while (| + Compare.lt (| + M.get_name (| globals, "pc" |), + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_name (| globals, "code" |) + ], + make_dict [] + |) + |), + ltac:(M.monadic ( +(* At stmt: unsupported node type: Try *) + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, "current_opcode" |), + M.get_field (| M.get_name (| globals, "Ops" |), "JUMPDEST" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_field (| M.get_name (| globals, "valid_jump_destinations" |), "add" |), + make_list [ + M.get_name (| globals, "pc" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + BoolOp.and (| + Compare.lt_e (| + M.get_field (| M.get_field (| M.get_name (| globals, "Ops" |), "PUSH1" |), "value" |), + M.get_field (| M.get_name (| globals, "current_opcode" |), "value" |) + |), + ltac:(M.monadic ( + Compare.lt_e (| + M.get_field (| M.get_name (| globals, "current_opcode" |), "value" |), + M.get_field (| M.get_field (| M.get_name (| globals, "Ops" |), "PUSH32" |), "value" |) + |) + )) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "push_data_size" , + BinOp.add (| + BinOp.sub (| + M.get_field (| M.get_name (| globals, "current_opcode" |), "value" |), + M.get_field (| M.get_field (| M.get_name (| globals, "Ops" |), "PUSH1" |), "value" |) + |), + Constant.int 1 + |) + |) in + let _ := M.assign_op_local (| + BinOp.add, + "pc", + M.get_name (| globals, "push_data_size" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )) |) in + let _ := M.assign_op_local (| + BinOp.add, + "pc", + Constant.int 1 + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := M.return_ (| + M.get_name (| globals, "valid_jump_destinations" |) + |) in + M.pure Constant.None_)). diff --git a/CoqOfPython/ethereum/cancun/vm/stack.v b/CoqOfPython/ethereum/cancun/vm/stack.v new file mode 100644 index 0000000..8c8a63b --- /dev/null +++ b/CoqOfPython/ethereum/cancun/vm/stack.v @@ -0,0 +1,123 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.cancun.vm.stack". + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) Stack +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementation of the stack operators for the EVM. +". + +Axiom typing_imports_List : + IsImported globals "typing" "List". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". + +Axiom ethereum_cancun_vm_exceptions_imports_StackOverflowError : + IsImported globals "ethereum.cancun.vm.exceptions" "StackOverflowError". +Axiom ethereum_cancun_vm_exceptions_imports_StackUnderflowError : + IsImported globals "ethereum.cancun.vm.exceptions" "StackUnderflowError". + +Definition pop : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "stack" ] |) in + let _ := Constant.str " + Pops the top item off of `stack`. + + Parameters + ---------- + stack : + EVM stack. + + Returns + ------- + value : `U256` + The top element on the stack. + + " in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_name (| globals, "stack" |) + ], + make_dict [] + |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, "StackUnderflowError" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.return_ (| + M.call (| + M.get_field (| M.get_name (| globals, "stack" |), "pop" |), + make_list [], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Definition push : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "stack"; "value" ] |) in + let _ := Constant.str " + Pushes `value` onto `stack`. + + Parameters + ---------- + stack : + EVM stack. + + value : + Item to be pushed onto `stack`. + + " in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_name (| globals, "stack" |) + ], + make_dict [] + |), + Constant.int 1024 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, "StackOverflowError" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.return_ (| + M.call (| + M.get_field (| M.get_name (| globals, "stack" |), "append" |), + make_list [ + M.get_name (| globals, "value" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). diff --git a/CoqOfPython/ethereum/constantinople/__init__.v b/CoqOfPython/ethereum/constantinople/__init__.v new file mode 100644 index 0000000..4727e2a --- /dev/null +++ b/CoqOfPython/ethereum/constantinople/__init__.v @@ -0,0 +1,23 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.constantinople.__init__". + +Definition expr_1 : Value.t := + Constant.str " +The Constantinople fork reduces mining rewards, delays the difficulty bomb, +and introduces new EVM instructions for logical shifts, counterfactual +contract deployment, and computing bytecode hashes. +". + +Axiom ethereum_fork_criteria_imports_ByBlockNumber : + IsImported globals "ethereum.fork_criteria" "ByBlockNumber". + +Definition FORK_CRITERIA : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "ByBlockNumber" |), + make_list [ + Constant.int 7280000 + ], + make_dict [] + |) +)). diff --git a/CoqOfPython/ethereum/constantinople/blocks.v b/CoqOfPython/ethereum/constantinople/blocks.v new file mode 100644 index 0000000..e6c6eb3 --- /dev/null +++ b/CoqOfPython/ethereum/constantinople/blocks.v @@ -0,0 +1,87 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.constantinople.blocks". + +Definition expr_1 : Value.t := + Constant.str " +A `Block` is a single link in the chain that is Ethereum. Each `Block` contains +a `Header` and zero or more transactions. Each `Header` contains associated +metadata like the block number, parent block hash, and how much gas was +consumed by its transactions. + +Together, these blocks form a cryptographically secure journal recording the +history of all state transitions that have happened since the genesis of the +chain. +". + +Axiom dataclasses_imports_dataclass : + IsImported globals "dataclasses" "dataclass". + +Axiom typing_imports_Tuple : + IsImported globals "typing" "Tuple". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_Bytes : + IsImported globals "ethereum.base_types" "Bytes". +Axiom ethereum_base_types_imports_Bytes8 : + IsImported globals "ethereum.base_types" "Bytes8". +Axiom ethereum_base_types_imports_Bytes32 : + IsImported globals "ethereum.base_types" "Bytes32". +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". +Axiom ethereum_base_types_imports_slotted_freezable : + IsImported globals "ethereum.base_types" "slotted_freezable". + +Axiom ethereum_crypto_hash_imports_Hash32 : + IsImported globals "ethereum.crypto.hash" "Hash32". + +Axiom ethereum_constantinople_fork_types_imports_Address : + IsImported globals "ethereum.constantinople.fork_types" "Address". +Axiom ethereum_constantinople_fork_types_imports_Bloom : + IsImported globals "ethereum.constantinople.fork_types" "Bloom". +Axiom ethereum_constantinople_fork_types_imports_Root : + IsImported globals "ethereum.constantinople.fork_types" "Root". + +Axiom ethereum_constantinople_transactions_imports_Transaction : + IsImported globals "ethereum.constantinople.transactions" "Transaction". + +Definition Header : Value.t := + builtins.make_klass + [] + [ + + ] + [ + + ]. + +Definition Block : Value.t := + builtins.make_klass + [] + [ + + ] + [ + + ]. + +Definition Log : Value.t := + builtins.make_klass + [] + [ + + ] + [ + + ]. + +Definition Receipt : Value.t := + builtins.make_klass + [] + [ + + ] + [ + + ]. diff --git a/CoqOfPython/ethereum/constantinople/bloom.v b/CoqOfPython/ethereum/constantinople/bloom.v new file mode 100644 index 0000000..a432ffc --- /dev/null +++ b/CoqOfPython/ethereum/constantinople/bloom.v @@ -0,0 +1,207 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.constantinople.bloom". + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Logs Bloom +^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +This modules defines functions for calculating bloom filters of logs. For the +general theory of bloom filters see e.g. `Wikipedia +`_. Bloom filters are used to allow +for efficient searching of logs by address and/or topic, by rapidly +eliminating blocks and receipts from their search. +". + +Axiom typing_imports_Tuple : + IsImported globals "typing" "Tuple". + +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". + +Axiom ethereum_crypto_hash_imports_keccak256 : + IsImported globals "ethereum.crypto.hash" "keccak256". + +Axiom ethereum_constantinople_blocks_imports_Log : + IsImported globals "ethereum.constantinople.blocks" "Log". + +Axiom ethereum_constantinople_fork_types_imports_Bloom : + IsImported globals "ethereum.constantinople.fork_types" "Bloom". + +Definition add_to_bloom : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "bloom"; "bloom_entry" ] |) in + let _ := Constant.str " + Add a bloom entry to the bloom filter (`bloom`). + + The number of hash functions used is 3. They are calculated by taking the + least significant 11 bits from the first 3 16-bit words of the + `keccak_256()` hash of `bloom_entry`. + + Parameters + ---------- + bloom : + The bloom filter. + bloom_entry : + An entry which is to be added to bloom filter. + " in + let _ := M.assign_local (| + "hash" , + M.call (| + M.get_name (| globals, "keccak256" |), + make_list [ + M.get_name (| globals, "bloom_entry" |) + ], + make_dict [] + |) + |) in + let _ := + M.for_ (| + M.get_name (| globals, "idx" |), + make_tuple [ Constant.int 0; Constant.int 2; Constant.int 4 ], + ltac:(M.monadic ( + let _ := M.assign_local (| + "bit_to_set" , + BinOp.bit_and (| + M.call (| + M.get_field (| M.get_name (| globals, "Uint" |), "from_be_bytes" |), + make_list [ + M.slice (| + M.get_name (| globals, "hash" |), + M.get_name (| globals, "idx" |), + BinOp.add (| + M.get_name (| globals, "idx" |), + Constant.int 2 + |), + Constant.None_ + |) + ], + make_dict [] + |), + Constant.int 2047 + |) + |) in + let _ := M.assign_local (| + "bit_index" , + BinOp.sub (| + Constant.int 2047, + M.get_name (| globals, "bit_to_set" |) + |) + |) in + let _ := M.assign_local (| + "byte_index" , + BinOp.floor_div (| + M.get_name (| globals, "bit_index" |), + Constant.int 8 + |) + |) in + let _ := M.assign_local (| + "bit_value" , + BinOp.l_shift (| + Constant.int 1, + BinOp.sub (| + Constant.int 7, + BinOp.mod_ (| + M.get_name (| globals, "bit_index" |), + Constant.int 8 + |) + |) + |) + |) in + let _ := M.assign (| + M.get_subscript (| + M.get_name (| globals, "bloom" |), + M.get_name (| globals, "byte_index" |) + |), + BinOp.bit_or (| + M.get_subscript (| + M.get_name (| globals, "bloom" |), + M.get_name (| globals, "byte_index" |) + |), + M.get_name (| globals, "bit_value" |) + |) + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + M.pure Constant.None_)). + +Definition logs_bloom : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "logs" ] |) in + let _ := Constant.str " + Obtain the logs bloom from a list of log entries. + + The address and each topic of a log are added to the bloom filter. + + Parameters + ---------- + logs : + List of logs for which the logs bloom is to be obtained. + + Returns + ------- + logs_bloom : `Bloom` + The logs bloom obtained which is 256 bytes with some bits set as per + the caller address and the log topics. + " in +(* At stmt: unsupported node type: AnnAssign *) + let _ := + M.for_ (| + M.get_name (| globals, "log" |), + M.get_name (| globals, "logs" |), + ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, "add_to_bloom" |), + make_list [ + M.get_name (| globals, "bloom" |); + M.get_field (| M.get_name (| globals, "log" |), "address" |) + ], + make_dict [] + |) in + let _ := + M.for_ (| + M.get_name (| globals, "topic" |), + M.get_field (| M.get_name (| globals, "log" |), "topics" |), + ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, "add_to_bloom" |), + make_list [ + M.get_name (| globals, "bloom" |); + M.get_name (| globals, "topic" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, "Bloom" |), + make_list [ + M.get_name (| globals, "bloom" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). diff --git a/CoqOfPython/ethereum/constantinople/fork.v b/CoqOfPython/ethereum/constantinople/fork.v new file mode 100644 index 0000000..06668fb --- /dev/null +++ b/CoqOfPython/ethereum/constantinople/fork.v @@ -0,0 +1,2655 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.constantinople.fork". + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Specification +^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Entry point for the Ethereum specification. +". + +Axiom dataclasses_imports_dataclass : + IsImported globals "dataclasses" "dataclass". + +Axiom typing_imports_List : + IsImported globals "typing" "List". +Axiom typing_imports_Optional : + IsImported globals "typing" "Optional". +Axiom typing_imports_Set : + IsImported globals "typing" "Set". +Axiom typing_imports_Tuple : + IsImported globals "typing" "Tuple". + +Axiom ethereum_base_types_imports_Bytes0 : + IsImported globals "ethereum.base_types" "Bytes0". + +Axiom ethereum_crypto_elliptic_curve_imports_SECP256K1N : + IsImported globals "ethereum.crypto.elliptic_curve" "SECP256K1N". +Axiom ethereum_crypto_elliptic_curve_imports_secp256k1_recover : + IsImported globals "ethereum.crypto.elliptic_curve" "secp256k1_recover". + +Axiom ethereum_crypto_hash_imports_Hash32 : + IsImported globals "ethereum.crypto.hash" "Hash32". +Axiom ethereum_crypto_hash_imports_keccak256 : + IsImported globals "ethereum.crypto.hash" "keccak256". + +Axiom ethereum_ethash_imports_dataset_size : + IsImported globals "ethereum.ethash" "dataset_size". +Axiom ethereum_ethash_imports_generate_cache : + IsImported globals "ethereum.ethash" "generate_cache". +Axiom ethereum_ethash_imports_hashimoto_light : + IsImported globals "ethereum.ethash" "hashimoto_light". + +Axiom ethereum_exceptions_imports_InvalidBlock : + IsImported globals "ethereum.exceptions" "InvalidBlock". + +Axiom ethereum_utils_ensure_imports_ensure : + IsImported globals "ethereum.utils.ensure" "ensure". + +Axiom ethereum_imports_rlp : + IsImported globals "ethereum" "rlp". + +Axiom ethereum_base_types_imports_U64 : + IsImported globals "ethereum.base_types" "U64". +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_U256_CEIL_VALUE : + IsImported globals "ethereum.base_types" "U256_CEIL_VALUE". +Axiom ethereum_base_types_imports_Bytes : + IsImported globals "ethereum.base_types" "Bytes". +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". + +Axiom ethereum_constantinople_imports_vm : + IsImported globals "ethereum.constantinople" "vm". + +Axiom ethereum_constantinople_blocks_imports_Block : + IsImported globals "ethereum.constantinople.blocks" "Block". +Axiom ethereum_constantinople_blocks_imports_Header : + IsImported globals "ethereum.constantinople.blocks" "Header". +Axiom ethereum_constantinople_blocks_imports_Log : + IsImported globals "ethereum.constantinople.blocks" "Log". +Axiom ethereum_constantinople_blocks_imports_Receipt : + IsImported globals "ethereum.constantinople.blocks" "Receipt". + +Axiom ethereum_constantinople_bloom_imports_logs_bloom : + IsImported globals "ethereum.constantinople.bloom" "logs_bloom". + +Axiom ethereum_constantinople_fork_types_imports_Address : + IsImported globals "ethereum.constantinople.fork_types" "Address". +Axiom ethereum_constantinople_fork_types_imports_Bloom : + IsImported globals "ethereum.constantinople.fork_types" "Bloom". +Axiom ethereum_constantinople_fork_types_imports_Root : + IsImported globals "ethereum.constantinople.fork_types" "Root". + +Axiom ethereum_constantinople_state_imports_State : + IsImported globals "ethereum.constantinople.state" "State". +Axiom ethereum_constantinople_state_imports_account_exists_and_is_empty : + IsImported globals "ethereum.constantinople.state" "account_exists_and_is_empty". +Axiom ethereum_constantinople_state_imports_create_ether : + IsImported globals "ethereum.constantinople.state" "create_ether". +Axiom ethereum_constantinople_state_imports_destroy_account : + IsImported globals "ethereum.constantinople.state" "destroy_account". +Axiom ethereum_constantinople_state_imports_get_account : + IsImported globals "ethereum.constantinople.state" "get_account". +Axiom ethereum_constantinople_state_imports_increment_nonce : + IsImported globals "ethereum.constantinople.state" "increment_nonce". +Axiom ethereum_constantinople_state_imports_set_account_balance : + IsImported globals "ethereum.constantinople.state" "set_account_balance". +Axiom ethereum_constantinople_state_imports_state_root : + IsImported globals "ethereum.constantinople.state" "state_root". + +Axiom ethereum_constantinople_transactions_imports_TX_BASE_COST : + IsImported globals "ethereum.constantinople.transactions" "TX_BASE_COST". +Axiom ethereum_constantinople_transactions_imports_TX_CREATE_COST : + IsImported globals "ethereum.constantinople.transactions" "TX_CREATE_COST". +Axiom ethereum_constantinople_transactions_imports_TX_DATA_COST_PER_NON_ZERO : + IsImported globals "ethereum.constantinople.transactions" "TX_DATA_COST_PER_NON_ZERO". +Axiom ethereum_constantinople_transactions_imports_TX_DATA_COST_PER_ZERO : + IsImported globals "ethereum.constantinople.transactions" "TX_DATA_COST_PER_ZERO". +Axiom ethereum_constantinople_transactions_imports_Transaction : + IsImported globals "ethereum.constantinople.transactions" "Transaction". + +Axiom ethereum_constantinople_trie_imports_Trie : + IsImported globals "ethereum.constantinople.trie" "Trie". +Axiom ethereum_constantinople_trie_imports_root : + IsImported globals "ethereum.constantinople.trie" "root". +Axiom ethereum_constantinople_trie_imports_trie_set : + IsImported globals "ethereum.constantinople.trie" "trie_set". + +Axiom ethereum_constantinople_utils_message_imports_prepare_message : + IsImported globals "ethereum.constantinople.utils.message" "prepare_message". + +Axiom ethereum_constantinople_vm_interpreter_imports_process_message_call : + IsImported globals "ethereum.constantinople.vm.interpreter" "process_message_call". + +Definition BLOCK_REWARD : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + BinOp.mult (| + Constant.int 2, + BinOp.pow (| + Constant.int 10, + Constant.int 18 + |) + |) + ], + make_dict [] + |) +)). + +Definition GAS_LIMIT_ADJUSTMENT_FACTOR : Value.t := M.run ltac:(M.monadic ( + Constant.int 1024 +)). + +Definition GAS_LIMIT_MINIMUM : Value.t := M.run ltac:(M.monadic ( + Constant.int 5000 +)). + +Definition MINIMUM_DIFFICULTY : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 131072 + ], + make_dict [] + |) +)). + +Definition MAX_OMMER_DEPTH : Value.t := M.run ltac:(M.monadic ( + Constant.int 6 +)). + +Definition BOMB_DELAY_BLOCKS : Value.t := M.run ltac:(M.monadic ( + Constant.int 5000000 +)). + +Definition EMPTY_OMMER_HASH : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "keccak256" |), + make_list [ + M.call (| + M.get_field (| M.get_name (| globals, "rlp" |), "encode" |), + make_list [ + make_list [] + ], + make_dict [] + |) + ], + make_dict [] + |) +)). + +Definition BlockChain : Value.t := + builtins.make_klass + [] + [ + + ] + [ + + ]. + +Definition apply_fork : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "old" ] |) in + let _ := Constant.str " + Transforms the state from the previous hard fork (`old`) into the block + chain object for this hard fork and returns it. + + When forks need to implement an irregular state transition, this function + is used to handle the irregularity. See the :ref:`DAO Fork ` for + an example. + + Parameters + ---------- + old : + Previous block chain object. + + Returns + ------- + new : `BlockChain` + Upgraded block chain object for this hard fork. + " in + let _ := M.return_ (| + M.get_name (| globals, "old" |) + |) in + M.pure Constant.None_)). + +Definition get_last_256_block_hashes : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "chain" ] |) in + let _ := Constant.str " + Obtain the list of hashes of the previous 256 blocks in order of + increasing block number. + + This function will return less hashes for the first 256 blocks. + + The ``BLOCKHASH`` opcode needs to access the latest hashes on the chain, + therefore this function retrieves them. + + Parameters + ---------- + chain : + History and current state. + + Returns + ------- + recent_block_hashes : `List[Hash32]` + Hashes of the recent 256 blocks in order of increasing block number. + " in + let _ := M.assign_local (| + "recent_blocks" , + M.slice (| + M.get_field (| M.get_name (| globals, "chain" |), "blocks" |), + UnOp.sub (| Constant.int 255 |), + Constant.None_, + Constant.None_ + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_name (| globals, "recent_blocks" |) + ], + make_dict [] + |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + make_list [] + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "recent_block_hashes" , + make_list [] + |) in + let _ := + M.for_ (| + M.get_name (| globals, "block" |), + M.get_name (| globals, "recent_blocks" |), + ltac:(M.monadic ( + let _ := M.assign_local (| + "prev_block_hash" , + M.get_field (| M.get_field (| M.get_name (| globals, "block" |), "header" |), "parent_hash" |) + |) in + let _ := M.call (| + M.get_field (| M.get_name (| globals, "recent_block_hashes" |), "append" |), + make_list [ + M.get_name (| globals, "prev_block_hash" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := M.assign_local (| + "most_recent_block_hash" , + M.call (| + M.get_name (| globals, "keccak256" |), + make_list [ + M.call (| + M.get_field (| M.get_name (| globals, "rlp" |), "encode" |), + make_list [ + M.get_field (| M.get_subscript (| + M.get_name (| globals, "recent_blocks" |), + UnOp.sub (| Constant.int 1 |) + |), "header" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_field (| M.get_name (| globals, "recent_block_hashes" |), "append" |), + make_list [ + M.get_name (| globals, "most_recent_block_hash" |) + ], + make_dict [] + |) in + let _ := M.return_ (| + M.get_name (| globals, "recent_block_hashes" |) + |) in + M.pure Constant.None_)). + +Definition state_transition : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "chain"; "block" ] |) in + let _ := Constant.str " + Attempts to apply a block to an existing block chain. + + All parts of the block's contents need to be verified before being added + to the chain. Blocks are verified by ensuring that the contents of the + block make logical sense with the contents of the parent block. The + information in the block's header must also match the corresponding + information in the block. + + To implement Ethereum, in theory clients are only required to store the + most recent 255 blocks of the chain since as far as execution is + concerned, only those blocks are accessed. Practically, however, clients + should store more blocks to handle reorgs. + + Parameters + ---------- + chain : + History and current state. + block : + Block to apply to `chain`. + " in + let _ := M.assign_local (| + "parent_header" , + M.get_field (| M.get_subscript (| + M.get_field (| M.get_name (| globals, "chain" |), "blocks" |), + UnOp.sub (| Constant.int 1 |) + |), "header" |) + |) in + let _ := M.call (| + M.get_name (| globals, "validate_header" |), + make_list [ + M.get_field (| M.get_name (| globals, "block" |), "header" |); + M.get_name (| globals, "parent_header" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "validate_ommers" |), + make_list [ + M.get_field (| M.get_name (| globals, "block" |), "ommers" |); + M.get_field (| M.get_name (| globals, "block" |), "header" |); + M.get_name (| globals, "chain" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "apply_body_output" , + M.call (| + M.get_name (| globals, "apply_body" |), + make_list [ + M.get_field (| M.get_name (| globals, "chain" |), "state" |); + M.call (| + M.get_name (| globals, "get_last_256_block_hashes" |), + make_list [ + M.get_name (| globals, "chain" |) + ], + make_dict [] + |); + M.get_field (| M.get_field (| M.get_name (| globals, "block" |), "header" |), "coinbase" |); + M.get_field (| M.get_field (| M.get_name (| globals, "block" |), "header" |), "number" |); + M.get_field (| M.get_field (| M.get_name (| globals, "block" |), "header" |), "gas_limit" |); + M.get_field (| M.get_field (| M.get_name (| globals, "block" |), "header" |), "timestamp" |); + M.get_field (| M.get_field (| M.get_name (| globals, "block" |), "header" |), "difficulty" |); + M.get_field (| M.get_name (| globals, "block" |), "transactions" |); + M.get_field (| M.get_name (| globals, "block" |), "ommers" |); + M.get_field (| M.get_name (| globals, "chain" |), "chain_id" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + Compare.eq (| + M.get_field (| M.get_name (| globals, "apply_body_output" |), "block_gas_used" |), + M.get_field (| M.get_field (| M.get_name (| globals, "block" |), "header" |), "gas_used" |) + |); + M.get_name (| globals, "InvalidBlock" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + Compare.eq (| + M.get_field (| M.get_name (| globals, "apply_body_output" |), "transactions_root" |), + M.get_field (| M.get_field (| M.get_name (| globals, "block" |), "header" |), "transactions_root" |) + |); + M.get_name (| globals, "InvalidBlock" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + Compare.eq (| + M.get_field (| M.get_name (| globals, "apply_body_output" |), "state_root" |), + M.get_field (| M.get_field (| M.get_name (| globals, "block" |), "header" |), "state_root" |) + |); + M.get_name (| globals, "InvalidBlock" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + Compare.eq (| + M.get_field (| M.get_name (| globals, "apply_body_output" |), "receipt_root" |), + M.get_field (| M.get_field (| M.get_name (| globals, "block" |), "header" |), "receipt_root" |) + |); + M.get_name (| globals, "InvalidBlock" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + Compare.eq (| + M.get_field (| M.get_name (| globals, "apply_body_output" |), "block_logs_bloom" |), + M.get_field (| M.get_field (| M.get_name (| globals, "block" |), "header" |), "bloom" |) + |); + M.get_name (| globals, "InvalidBlock" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, "chain" |), "blocks" |), "append" |), + make_list [ + M.get_name (| globals, "block" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.gt (| + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_field (| M.get_name (| globals, "chain" |), "blocks" |) + ], + make_dict [] + |), + Constant.int 255 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign (| + M.get_field (| M.get_name (| globals, "chain" |), "blocks" |), + M.slice (| + M.get_field (| M.get_name (| globals, "chain" |), "blocks" |), + UnOp.sub (| Constant.int 255 |), + Constant.None_, + Constant.None_ + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + M.pure Constant.None_)). + +Definition validate_header : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "header"; "parent_header" ] |) in + let _ := Constant.str " + Verifies a block header. + + In order to consider a block's header valid, the logic for the + quantities in the header should match the logic for the block itself. + For example the header timestamp should be greater than the block's parent + timestamp because the block was created *after* the parent block. + Additionally, the block's number should be directly following the parent + block's number since it is the next block in the sequence. + + Parameters + ---------- + header : + Header to check for correctness. + parent_header : + Parent Header of the header to check for correctness + " in + let _ := M.assign_local (| + "parent_has_ommers" , + Compare.not_eq (| + M.get_field (| M.get_name (| globals, "parent_header" |), "ommers_hash" |), + M.get_name (| globals, "EMPTY_OMMER_HASH" |) + |) + |) in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + Compare.gt (| + M.get_field (| M.get_name (| globals, "header" |), "timestamp" |), + M.get_field (| M.get_name (| globals, "parent_header" |), "timestamp" |) + |); + M.get_name (| globals, "InvalidBlock" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + Compare.eq (| + M.get_field (| M.get_name (| globals, "header" |), "number" |), + BinOp.add (| + M.get_field (| M.get_name (| globals, "parent_header" |), "number" |), + Constant.int 1 + |) + |); + M.get_name (| globals, "InvalidBlock" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + M.call (| + M.get_name (| globals, "check_gas_limit" |), + make_list [ + M.get_field (| M.get_name (| globals, "header" |), "gas_limit" |); + M.get_field (| M.get_name (| globals, "parent_header" |), "gas_limit" |) + ], + make_dict [] + |); + M.get_name (| globals, "InvalidBlock" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + Compare.lt_e (| + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_field (| M.get_name (| globals, "header" |), "extra_data" |) + ], + make_dict [] + |), + Constant.int 32 + |); + M.get_name (| globals, "InvalidBlock" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "block_difficulty" , + M.call (| + M.get_name (| globals, "calculate_block_difficulty" |), + make_list [ + M.get_field (| M.get_name (| globals, "header" |), "number" |); + M.get_field (| M.get_name (| globals, "header" |), "timestamp" |); + M.get_field (| M.get_name (| globals, "parent_header" |), "timestamp" |); + M.get_field (| M.get_name (| globals, "parent_header" |), "difficulty" |); + M.get_name (| globals, "parent_has_ommers" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + Compare.eq (| + M.get_field (| M.get_name (| globals, "header" |), "difficulty" |), + M.get_name (| globals, "block_difficulty" |) + |); + M.get_name (| globals, "InvalidBlock" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "block_parent_hash" , + M.call (| + M.get_name (| globals, "keccak256" |), + make_list [ + M.call (| + M.get_field (| M.get_name (| globals, "rlp" |), "encode" |), + make_list [ + M.get_name (| globals, "parent_header" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + Compare.eq (| + M.get_field (| M.get_name (| globals, "header" |), "parent_hash" |), + M.get_name (| globals, "block_parent_hash" |) + |); + M.get_name (| globals, "InvalidBlock" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "validate_proof_of_work" |), + make_list [ + M.get_name (| globals, "header" |) + ], + make_dict [] + |) in + M.pure Constant.None_)). + +Definition generate_header_hash_for_pow : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "header" ] |) in + let _ := Constant.str " + Generate rlp hash of the header which is to be used for Proof-of-Work + verification. + + In other words, the PoW artefacts `mix_digest` and `nonce` are ignored + while calculating this hash. + + A particular PoW is valid for a single hash, that hash is computed by + this function. The `nonce` and `mix_digest` are omitted from this hash + because they are being changed by miners in their search for a sufficient + proof-of-work. + + Parameters + ---------- + header : + The header object for which the hash is to be generated. + + Returns + ------- + hash : `Hash32` + The PoW valid rlp hash of the passed in header. + " in + let _ := M.assign_local (| + "header_data_without_pow_artefacts" , + make_list [ + M.get_field (| M.get_name (| globals, "header" |), "parent_hash" |); + M.get_field (| M.get_name (| globals, "header" |), "ommers_hash" |); + M.get_field (| M.get_name (| globals, "header" |), "coinbase" |); + M.get_field (| M.get_name (| globals, "header" |), "state_root" |); + M.get_field (| M.get_name (| globals, "header" |), "transactions_root" |); + M.get_field (| M.get_name (| globals, "header" |), "receipt_root" |); + M.get_field (| M.get_name (| globals, "header" |), "bloom" |); + M.get_field (| M.get_name (| globals, "header" |), "difficulty" |); + M.get_field (| M.get_name (| globals, "header" |), "number" |); + M.get_field (| M.get_name (| globals, "header" |), "gas_limit" |); + M.get_field (| M.get_name (| globals, "header" |), "gas_used" |); + M.get_field (| M.get_name (| globals, "header" |), "timestamp" |); + M.get_field (| M.get_name (| globals, "header" |), "extra_data" |) + ] + |) in + let _ := M.return_ (| + M.call (| + M.get_field (| M.get_name (| globals, "rlp" |), "rlp_hash" |), + make_list [ + M.get_name (| globals, "header_data_without_pow_artefacts" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Definition validate_proof_of_work : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "header" ] |) in + let _ := Constant.str " + Validates the Proof of Work constraints. + + In order to verify that a miner's proof-of-work is valid for a block, a + ``mix-digest`` and ``result`` are calculated using the ``hashimoto_light`` + hash function. The mix digest is a hash of the header and the nonce that + is passed through and it confirms whether or not proof-of-work was done + on the correct block. The result is the actual hash value of the block. + + Parameters + ---------- + header : + Header of interest. + " in + let _ := M.assign_local (| + "header_hash" , + M.call (| + M.get_name (| globals, "generate_header_hash_for_pow" |), + make_list [ + M.get_name (| globals, "header" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "cache" , + M.call (| + M.get_name (| globals, "generate_cache" |), + make_list [ + M.get_field (| M.get_name (| globals, "header" |), "number" |) + ], + make_dict [] + |) + |) in + let _ := M.assign (| + make_tuple [ M.get_name (| globals, "mix_digest" |); M.get_name (| globals, "result" |) ], + M.call (| + M.get_name (| globals, "hashimoto_light" |), + make_list [ + M.get_name (| globals, "header_hash" |); + M.get_field (| M.get_name (| globals, "header" |), "nonce" |); + M.get_name (| globals, "cache" |); + M.call (| + M.get_name (| globals, "dataset_size" |), + make_list [ + M.get_field (| M.get_name (| globals, "header" |), "number" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + Compare.eq (| + M.get_name (| globals, "mix_digest" |), + M.get_field (| M.get_name (| globals, "header" |), "mix_digest" |) + |); + M.get_name (| globals, "InvalidBlock" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + Compare.lt_e (| + M.call (| + M.get_field (| M.get_name (| globals, "Uint" |), "from_be_bytes" |), + make_list [ + M.get_name (| globals, "result" |) + ], + make_dict [] + |), + BinOp.floor_div (| + M.get_name (| globals, "U256_CEIL_VALUE" |), + M.get_field (| M.get_name (| globals, "header" |), "difficulty" |) + |) + |); + M.get_name (| globals, "InvalidBlock" |) + ], + make_dict [] + |) in + M.pure Constant.None_)). + +Definition check_transaction : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "tx"; "gas_available"; "chain_id" ] |) in + let _ := Constant.str " + Check if the transaction is includable in the block. + + Parameters + ---------- + tx : + The transaction. + gas_available : + The gas remaining in the block. + chain_id : + The ID of the current chain. + + Returns + ------- + sender_address : + The sender of the transaction. + + Raises + ------ + InvalidBlock : + If the transaction is not includable. + " in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + Compare.lt_e (| + M.get_field (| M.get_name (| globals, "tx" |), "gas" |), + M.get_name (| globals, "gas_available" |) + |); + M.get_name (| globals, "InvalidBlock" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "sender_address" , + M.call (| + M.get_name (| globals, "recover_sender" |), + make_list [ + M.get_name (| globals, "chain_id" |); + M.get_name (| globals, "tx" |) + ], + make_dict [] + |) + |) in + let _ := M.return_ (| + M.get_name (| globals, "sender_address" |) + |) in + M.pure Constant.None_)). + +Definition make_receipt : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "tx"; "error"; "cumulative_gas_used"; "logs" ] |) in + let _ := Constant.str " + Make the receipt for a transaction that was executed. + + Parameters + ---------- + tx : + The executed transaction. + error : + Error in the top level frame of the transaction, if any. + cumulative_gas_used : + The total gas used so far in the block after the transaction was + executed. + logs : + The logs produced by the transaction. + + Returns + ------- + receipt : + The receipt for the transaction. + " in + let _ := M.assign_local (| + "receipt" , + M.call (| + M.get_name (| globals, "Receipt" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.return_ (| + M.get_name (| globals, "receipt" |) + |) in + M.pure Constant.None_)). + +Definition ApplyBodyOutput : Value.t := + builtins.make_klass + [] + [ + + ] + [ + + ]. + +Definition apply_body : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "state"; "block_hashes"; "coinbase"; "block_number"; "block_gas_limit"; "block_time"; "block_difficulty"; "transactions"; "ommers"; "chain_id" ] |) in + let _ := Constant.str " + Executes a block. + + Many of the contents of a block are stored in data structures called + tries. There is a transactions trie which is similar to a ledger of the + transactions stored in the current block. There is also a receipts trie + which stores the results of executing a transaction, like the post state + and gas used. This function creates and executes the block that is to be + added to the chain. + + Parameters + ---------- + state : + Current account state. + block_hashes : + List of hashes of the previous 256 blocks in the order of + increasing block number. + coinbase : + Address of account which receives block reward and transaction fees. + block_number : + Position of the block within the chain. + block_gas_limit : + Initial amount of gas available for execution in this block. + block_time : + Time the block was produced, measured in seconds since the epoch. + block_difficulty : + Difficulty of the block. + transactions : + Transactions included in the block. + ommers : + Headers of ancestor blocks which are not direct parents (formerly + uncles.) + chain_id : + ID of the executing chain. + + Returns + ------- + apply_body_output : `ApplyBodyOutput` + Output of applying the block body to the state. + " in + let _ := M.assign_local (| + "gas_available" , + M.get_name (| globals, "block_gas_limit" |) + |) in +(* At stmt: unsupported node type: AnnAssign *) +(* At stmt: unsupported node type: AnnAssign *) +(* At stmt: unsupported node type: AnnAssign *) + let _ := + M.for_ (| + make_tuple [ M.get_name (| globals, "i" |); M.get_name (| globals, "tx" |) ], + M.call (| + M.get_name (| globals, "enumerate" |), + make_list [ + M.get_name (| globals, "transactions" |) + ], + make_dict [] + |), + ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, "trie_set" |), + make_list [ + M.get_name (| globals, "transactions_trie" |); + M.call (| + M.get_field (| M.get_name (| globals, "rlp" |), "encode" |), + make_list [ + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.get_name (| globals, "i" |) + ], + make_dict [] + |) + ], + make_dict [] + |); + M.get_name (| globals, "tx" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "sender_address" , + M.call (| + M.get_name (| globals, "check_transaction" |), + make_list [ + M.get_name (| globals, "tx" |); + M.get_name (| globals, "gas_available" |); + M.get_name (| globals, "chain_id" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "env" , + M.call (| + M.get_field (| M.get_name (| globals, "vm" |), "Environment" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.assign (| + make_tuple [ M.get_name (| globals, "gas_used" |); M.get_name (| globals, "logs" |); M.get_name (| globals, "error" |) ], + M.call (| + M.get_name (| globals, "process_transaction" |), + make_list [ + M.get_name (| globals, "env" |); + M.get_name (| globals, "tx" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_op_local (| + BinOp.sub, + "gas_available", + M.get_name (| globals, "gas_used" |) + |) in + let _ := M.assign_local (| + "receipt" , + M.call (| + M.get_name (| globals, "make_receipt" |), + make_list [ + M.get_name (| globals, "tx" |); + M.get_name (| globals, "error" |); + BinOp.sub (| + M.get_name (| globals, "block_gas_limit" |), + M.get_name (| globals, "gas_available" |) + |); + M.get_name (| globals, "logs" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "trie_set" |), + make_list [ + M.get_name (| globals, "receipts_trie" |); + M.call (| + M.get_field (| M.get_name (| globals, "rlp" |), "encode" |), + make_list [ + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.get_name (| globals, "i" |) + ], + make_dict [] + |) + ], + make_dict [] + |); + M.get_name (| globals, "receipt" |) + ], + make_dict [] + |) in + let _ := M.assign_op_local (| + BinOp.add, + "block_logs", + M.get_name (| globals, "logs" |) + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := M.call (| + M.get_name (| globals, "pay_rewards" |), + make_list [ + M.get_name (| globals, "state" |); + M.get_name (| globals, "block_number" |); + M.get_name (| globals, "coinbase" |); + M.get_name (| globals, "ommers" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "block_gas_used" , + BinOp.sub (| + M.get_name (| globals, "block_gas_limit" |), + M.get_name (| globals, "gas_available" |) + |) + |) in + let _ := M.assign_local (| + "block_logs_bloom" , + M.call (| + M.get_name (| globals, "logs_bloom" |), + make_list [ + M.get_name (| globals, "block_logs" |) + ], + make_dict [] + |) + |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, "ApplyBodyOutput" |), + make_list [ + M.get_name (| globals, "block_gas_used" |); + M.call (| + M.get_name (| globals, "root" |), + make_list [ + M.get_name (| globals, "transactions_trie" |) + ], + make_dict [] + |); + M.call (| + M.get_name (| globals, "root" |), + make_list [ + M.get_name (| globals, "receipts_trie" |) + ], + make_dict [] + |); + M.get_name (| globals, "block_logs_bloom" |); + M.call (| + M.get_name (| globals, "state_root" |), + make_list [ + M.get_name (| globals, "state" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Definition validate_ommers : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "ommers"; "block_header"; "chain" ] |) in + let _ := Constant.str " + Validates the ommers mentioned in the block. + + An ommer block is a block that wasn't canonically added to the + blockchain because it wasn't validated as fast as the canonical block + but was mined at the same time. + + To be considered valid, the ommers must adhere to the rules defined in + the Ethereum protocol. The maximum amount of ommers is 2 per block and + there cannot be duplicate ommers in a block. Many of the other ommer + constraints are listed in the in-line comments of this function. + + Parameters + ---------- + ommers : + List of ommers mentioned in the current block. + block_header: + The header of current block. + chain : + History and current state. + " in + let _ := M.assign_local (| + "block_hash" , + M.call (| + M.get_field (| M.get_name (| globals, "rlp" |), "rlp_hash" |), + make_list [ + M.get_name (| globals, "block_header" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + Compare.eq (| + M.call (| + M.get_field (| M.get_name (| globals, "rlp" |), "rlp_hash" |), + make_list [ + M.get_name (| globals, "ommers" |) + ], + make_dict [] + |), + M.get_field (| M.get_name (| globals, "block_header" |), "ommers_hash" |) + |); + M.get_name (| globals, "InvalidBlock" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_name (| globals, "ommers" |) + ], + make_dict [] + |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + Constant.None_ + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + M.for_ (| + M.get_name (| globals, "ommer" |), + M.get_name (| globals, "ommers" |), + ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + BoolOp.and (| + Compare.lt_e (| + Constant.int 1, + M.get_field (| M.get_name (| globals, "ommer" |), "number" |) + |), + ltac:(M.monadic ( + Compare.lt (| + M.get_field (| M.get_name (| globals, "ommer" |), "number" |), + M.get_field (| M.get_name (| globals, "block_header" |), "number" |) + |) + )) + |); + M.get_name (| globals, "InvalidBlock" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "ommer_parent_header" , + M.get_field (| M.get_subscript (| + M.get_field (| M.get_name (| globals, "chain" |), "blocks" |), + BinOp.sub (| + UnOp.sub (| BinOp.sub (| + M.get_field (| M.get_name (| globals, "block_header" |), "number" |), + M.get_field (| M.get_name (| globals, "ommer" |), "number" |) + |) |), + Constant.int 1 + |) + |), "header" |) + |) in + let _ := M.call (| + M.get_name (| globals, "validate_header" |), + make_list [ + M.get_name (| globals, "ommer" |); + M.get_name (| globals, "ommer_parent_header" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + Compare.lt_e (| + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_name (| globals, "ommers" |) + ], + make_dict [] + |), + Constant.int 2 + |); + M.get_name (| globals, "InvalidBlock" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "ommers_hashes" , + Constant.str "(* At expr: unsupported node type: ListComp *)" + |) in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + Compare.eq (| + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_name (| globals, "ommers_hashes" |) + ], + make_dict [] + |), + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.call (| + M.get_name (| globals, "set" |), + make_list [ + M.get_name (| globals, "ommers_hashes" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |); + M.get_name (| globals, "InvalidBlock" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "recent_canonical_blocks" , + M.slice (| + M.get_field (| M.get_name (| globals, "chain" |), "blocks" |), + UnOp.sub (| BinOp.add (| + M.get_name (| globals, "MAX_OMMER_DEPTH" |), + Constant.int 1 + |) |), + Constant.None_, + Constant.None_ + |) + |) in + let _ := M.assign_local (| + "recent_canonical_block_hashes" , + Constant.str "(* At expr: unsupported node type: SetComp *)" + |) in +(* At stmt: unsupported node type: AnnAssign *) + let _ := + M.for_ (| + M.get_name (| globals, "block" |), + M.get_name (| globals, "recent_canonical_blocks" |), + ltac:(M.monadic ( + let _ := M.assign_local (| + "recent_ommers_hashes" , + M.call (| + M.get_field (| M.get_name (| globals, "recent_ommers_hashes" |), "union" |), + make_list [ + Constant.str "(* At expr: unsupported node type: SetComp *)" + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := + M.for_ (| + make_tuple [ M.get_name (| globals, "ommer_index" |); M.get_name (| globals, "ommer" |) ], + M.call (| + M.get_name (| globals, "enumerate" |), + make_list [ + M.get_name (| globals, "ommers" |) + ], + make_dict [] + |), + ltac:(M.monadic ( + let _ := M.assign_local (| + "ommer_hash" , + M.get_subscript (| + M.get_name (| globals, "ommers_hashes" |), + M.get_name (| globals, "ommer_index" |) + |) + |) in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + Compare.not_eq (| + M.get_name (| globals, "ommer_hash" |), + M.get_name (| globals, "block_hash" |) + |); + M.get_name (| globals, "InvalidBlock" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + Compare.not_in (| + M.get_name (| globals, "ommer_hash" |), + M.get_name (| globals, "recent_canonical_block_hashes" |) + |); + M.get_name (| globals, "InvalidBlock" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + Compare.not_in (| + M.get_name (| globals, "ommer_hash" |), + M.get_name (| globals, "recent_ommers_hashes" |) + |); + M.get_name (| globals, "InvalidBlock" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "ommer_age" , + BinOp.sub (| + M.get_field (| M.get_name (| globals, "block_header" |), "number" |), + M.get_field (| M.get_name (| globals, "ommer" |), "number" |) + |) + |) in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + BoolOp.and (| + Compare.lt_e (| + Constant.int 1, + M.get_name (| globals, "ommer_age" |) + |), + ltac:(M.monadic ( + Compare.lt_e (| + M.get_name (| globals, "ommer_age" |), + M.get_name (| globals, "MAX_OMMER_DEPTH" |) + |) + )) + |); + M.get_name (| globals, "InvalidBlock" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + Compare.in_ (| + M.get_field (| M.get_name (| globals, "ommer" |), "parent_hash" |), + M.get_name (| globals, "recent_canonical_block_hashes" |) + |); + M.get_name (| globals, "InvalidBlock" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + Compare.not_eq (| + M.get_field (| M.get_name (| globals, "ommer" |), "parent_hash" |), + M.get_field (| M.get_name (| globals, "block_header" |), "parent_hash" |) + |); + M.get_name (| globals, "InvalidBlock" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + M.pure Constant.None_)). + +Definition pay_rewards : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "state"; "block_number"; "coinbase"; "ommers" ] |) in + let _ := Constant.str " + Pay rewards to the block miner as well as the ommers miners. + + The miner of the canonical block is rewarded with the predetermined + block reward, ``BLOCK_REWARD``, plus a variable award based off of the + number of ommer blocks that were mined around the same time, and included + in the canonical block's header. An ommer block is a block that wasn't + added to the canonical blockchain because it wasn't validated as fast as + the accepted block but was mined at the same time. Although not all blocks + that are mined are added to the canonical chain, miners are still paid a + reward for their efforts. This reward is called an ommer reward and is + calculated based on the number associated with the ommer block that they + mined. + + Parameters + ---------- + state : + Current account state. + block_number : + Position of the block within the chain. + coinbase : + Address of account which receives block reward and transaction fees. + ommers : + List of ommers mentioned in the current block. + " in + let _ := M.assign_local (| + "miner_reward" , + BinOp.add (| + M.get_name (| globals, "BLOCK_REWARD" |), + BinOp.mult (| + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_name (| globals, "ommers" |) + ], + make_dict [] + |), + BinOp.floor_div (| + M.get_name (| globals, "BLOCK_REWARD" |), + Constant.int 32 + |) + |) + |) + |) in + let _ := M.call (| + M.get_name (| globals, "create_ether" |), + make_list [ + M.get_name (| globals, "state" |); + M.get_name (| globals, "coinbase" |); + M.get_name (| globals, "miner_reward" |) + ], + make_dict [] + |) in + let _ := + M.for_ (| + M.get_name (| globals, "ommer" |), + M.get_name (| globals, "ommers" |), + ltac:(M.monadic ( + let _ := M.assign_local (| + "ommer_age" , + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + BinOp.sub (| + M.get_name (| globals, "block_number" |), + M.get_field (| M.get_name (| globals, "ommer" |), "number" |) + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "ommer_miner_reward" , + BinOp.floor_div (| + BinOp.mult (| + BinOp.sub (| + Constant.int 8, + M.get_name (| globals, "ommer_age" |) + |), + M.get_name (| globals, "BLOCK_REWARD" |) + |), + Constant.int 8 + |) + |) in + let _ := M.call (| + M.get_name (| globals, "create_ether" |), + make_list [ + M.get_name (| globals, "state" |); + M.get_field (| M.get_name (| globals, "ommer" |), "coinbase" |); + M.get_name (| globals, "ommer_miner_reward" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + M.pure Constant.None_)). + +Definition process_transaction : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "env"; "tx" ] |) in + let _ := Constant.str " + Execute a transaction against the provided environment. + + This function processes the actions needed to execute a transaction. + It decrements the sender's account after calculating the gas fee and + refunds them the proper amount after execution. Calling contracts, + deploying code, and incrementing nonces are all examples of actions that + happen within this function or from a call made within this function. + + Accounts that are marked for deletion are processed and destroyed after + execution. + + Parameters + ---------- + env : + Environment for the Ethereum Virtual Machine. + tx : + Transaction to execute. + + Returns + ------- + gas_left : `ethereum.base_types.U256` + Remaining gas after execution. + logs : `Tuple[ethereum.blocks.Log, ...]` + Logs generated during execution. + " in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + M.call (| + M.get_name (| globals, "validate_transaction" |), + make_list [ + M.get_name (| globals, "tx" |) + ], + make_dict [] + |); + M.get_name (| globals, "InvalidBlock" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "sender" , + M.get_field (| M.get_name (| globals, "env" |), "origin" |) + |) in + let _ := M.assign_local (| + "sender_account" , + M.call (| + M.get_name (| globals, "get_account" |), + make_list [ + M.get_field (| M.get_name (| globals, "env" |), "state" |); + M.get_name (| globals, "sender" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "gas_fee" , + BinOp.mult (| + M.get_field (| M.get_name (| globals, "tx" |), "gas" |), + M.get_field (| M.get_name (| globals, "tx" |), "gas_price" |) + |) + |) in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + Compare.eq (| + M.get_field (| M.get_name (| globals, "sender_account" |), "nonce" |), + M.get_field (| M.get_name (| globals, "tx" |), "nonce" |) + |); + M.get_name (| globals, "InvalidBlock" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + Compare.gt_e (| + M.get_field (| M.get_name (| globals, "sender_account" |), "balance" |), + BinOp.add (| + M.get_name (| globals, "gas_fee" |), + M.get_field (| M.get_name (| globals, "tx" |), "value" |) + |) + |); + M.get_name (| globals, "InvalidBlock" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + Compare.eq (| + M.get_field (| M.get_name (| globals, "sender_account" |), "code" |), + M.call (| + M.get_name (| globals, "bytearray" |), + make_list [], + make_dict [] + |) + |); + M.get_name (| globals, "InvalidBlock" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "gas" , + BinOp.sub (| + M.get_field (| M.get_name (| globals, "tx" |), "gas" |), + M.call (| + M.get_name (| globals, "calculate_intrinsic_cost" |), + make_list [ + M.get_name (| globals, "tx" |) + ], + make_dict [] + |) + |) + |) in + let _ := M.call (| + M.get_name (| globals, "increment_nonce" |), + make_list [ + M.get_field (| M.get_name (| globals, "env" |), "state" |); + M.get_name (| globals, "sender" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "sender_balance_after_gas_fee" , + BinOp.sub (| + M.get_field (| M.get_name (| globals, "sender_account" |), "balance" |), + M.get_name (| globals, "gas_fee" |) + |) + |) in + let _ := M.call (| + M.get_name (| globals, "set_account_balance" |), + make_list [ + M.get_field (| M.get_name (| globals, "env" |), "state" |); + M.get_name (| globals, "sender" |); + M.get_name (| globals, "sender_balance_after_gas_fee" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "message" , + M.call (| + M.get_name (| globals, "prepare_message" |), + make_list [ + M.get_name (| globals, "sender" |); + M.get_field (| M.get_name (| globals, "tx" |), "to" |); + M.get_field (| M.get_name (| globals, "tx" |), "value" |); + M.get_field (| M.get_name (| globals, "tx" |), "data" |); + M.get_name (| globals, "gas" |); + M.get_name (| globals, "env" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "output" , + M.call (| + M.get_name (| globals, "process_message_call" |), + make_list [ + M.get_name (| globals, "message" |); + M.get_name (| globals, "env" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "gas_used" , + BinOp.sub (| + M.get_field (| M.get_name (| globals, "tx" |), "gas" |), + M.get_field (| M.get_name (| globals, "output" |), "gas_left" |) + |) + |) in + let _ := M.assign_local (| + "gas_refund" , + M.call (| + M.get_name (| globals, "min" |), + make_list [ + BinOp.floor_div (| + M.get_name (| globals, "gas_used" |), + Constant.int 2 + |); + M.get_field (| M.get_name (| globals, "output" |), "refund_counter" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "gas_refund_amount" , + BinOp.mult (| + BinOp.add (| + M.get_field (| M.get_name (| globals, "output" |), "gas_left" |), + M.get_name (| globals, "gas_refund" |) + |), + M.get_field (| M.get_name (| globals, "tx" |), "gas_price" |) + |) + |) in + let _ := M.assign_local (| + "transaction_fee" , + BinOp.mult (| + BinOp.sub (| + BinOp.sub (| + M.get_field (| M.get_name (| globals, "tx" |), "gas" |), + M.get_field (| M.get_name (| globals, "output" |), "gas_left" |) + |), + M.get_name (| globals, "gas_refund" |) + |), + M.get_field (| M.get_name (| globals, "tx" |), "gas_price" |) + |) + |) in + let _ := M.assign_local (| + "total_gas_used" , + BinOp.sub (| + M.get_name (| globals, "gas_used" |), + M.get_name (| globals, "gas_refund" |) + |) + |) in + let _ := M.assign_local (| + "sender_balance_after_refund" , + BinOp.add (| + M.get_field (| M.call (| + M.get_name (| globals, "get_account" |), + make_list [ + M.get_field (| M.get_name (| globals, "env" |), "state" |); + M.get_name (| globals, "sender" |) + ], + make_dict [] + |), "balance" |), + M.get_name (| globals, "gas_refund_amount" |) + |) + |) in + let _ := M.call (| + M.get_name (| globals, "set_account_balance" |), + make_list [ + M.get_field (| M.get_name (| globals, "env" |), "state" |); + M.get_name (| globals, "sender" |); + M.get_name (| globals, "sender_balance_after_refund" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "coinbase_balance_after_mining_fee" , + BinOp.add (| + M.get_field (| M.call (| + M.get_name (| globals, "get_account" |), + make_list [ + M.get_field (| M.get_name (| globals, "env" |), "state" |); + M.get_field (| M.get_name (| globals, "env" |), "coinbase" |) + ], + make_dict [] + |), "balance" |), + M.get_name (| globals, "transaction_fee" |) + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.not_eq (| + M.get_name (| globals, "coinbase_balance_after_mining_fee" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, "set_account_balance" |), + make_list [ + M.get_field (| M.get_name (| globals, "env" |), "state" |); + M.get_field (| M.get_name (| globals, "env" |), "coinbase" |); + M.get_name (| globals, "coinbase_balance_after_mining_fee" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, "account_exists_and_is_empty" |), + make_list [ + M.get_field (| M.get_name (| globals, "env" |), "state" |); + M.get_field (| M.get_name (| globals, "env" |), "coinbase" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, "destroy_account" |), + make_list [ + M.get_field (| M.get_name (| globals, "env" |), "state" |); + M.get_field (| M.get_name (| globals, "env" |), "coinbase" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )) |) in + let _ := + M.for_ (| + M.get_name (| globals, "address" |), + M.get_field (| M.get_name (| globals, "output" |), "accounts_to_delete" |), + ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, "destroy_account" |), + make_list [ + M.get_field (| M.get_name (| globals, "env" |), "state" |); + M.get_name (| globals, "address" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := + M.for_ (| + M.get_name (| globals, "address" |), + M.get_field (| M.get_name (| globals, "output" |), "touched_accounts" |), + ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, "account_exists_and_is_empty" |), + make_list [ + M.get_field (| M.get_name (| globals, "env" |), "state" |); + M.get_name (| globals, "address" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, "destroy_account" |), + make_list [ + M.get_field (| M.get_name (| globals, "env" |), "state" |); + M.get_name (| globals, "address" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := M.return_ (| + make_tuple [ M.get_name (| globals, "total_gas_used" |); M.get_field (| M.get_name (| globals, "output" |), "logs" |); M.get_field (| M.get_name (| globals, "output" |), "error" |) ] + |) in + M.pure Constant.None_)). + +Definition validate_transaction : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "tx" ] |) in + let _ := Constant.str " + Verifies a transaction. + + The gas in a transaction gets used to pay for the intrinsic cost of + operations, therefore if there is insufficient gas then it would not + be possible to execute a transaction and it will be declared invalid. + + Additionally, the nonce of a transaction must not equal or exceed the + limit defined in `EIP-2681 `_. + In practice, defining the limit as ``2**64-1`` has no impact because + sending ``2**64-1`` transactions is improbable. It's not strictly + impossible though, ``2**64-1`` transactions is the entire capacity of the + Ethereum blockchain at 2022 gas limits for a little over 22 years. + + Parameters + ---------- + tx : + Transaction to validate. + + Returns + ------- + verified : `bool` + True if the transaction can be executed, or False otherwise. + " in + let _ := M.return_ (| + BoolOp.and (| + Compare.lt_e (| + M.call (| + M.get_name (| globals, "calculate_intrinsic_cost" |), + make_list [ + M.get_name (| globals, "tx" |) + ], + make_dict [] + |), + M.get_field (| M.get_name (| globals, "tx" |), "gas" |) + |), + ltac:(M.monadic ( + Compare.lt (| + M.get_field (| M.get_name (| globals, "tx" |), "nonce" |), + BinOp.sub (| + BinOp.pow (| + Constant.int 2, + Constant.int 64 + |), + Constant.int 1 + |) + |) + )) + |) + |) in + M.pure Constant.None_)). + +Definition calculate_intrinsic_cost : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "tx" ] |) in + let _ := Constant.str " + Calculates the gas that is charged before execution is started. + + The intrinsic cost of the transaction is charged before execution has + begun. Functions/operations in the EVM cost money to execute so this + intrinsic cost is for the operations that need to be paid for as part of + the transaction. Data transfer, for example, is part of this intrinsic + cost. It costs ether to send data over the wire and that ether is + accounted for in the intrinsic cost calculated in this function. This + intrinsic cost must be calculated and paid for before execution in order + for all operations to be implemented. + + Parameters + ---------- + tx : + Transaction to compute the intrinsic cost of. + + Returns + ------- + verified : `ethereum.base_types.Uint` + The intrinsic cost of the transaction. + " in + let _ := M.assign_local (| + "data_cost" , + Constant.int 0 + |) in + let _ := + M.for_ (| + M.get_name (| globals, "byte" |), + M.get_field (| M.get_name (| globals, "tx" |), "data" |), + ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, "byte" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_op_local (| + BinOp.add, + "data_cost", + M.get_name (| globals, "TX_DATA_COST_PER_ZERO" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_op_local (| + BinOp.add, + "data_cost", + M.get_name (| globals, "TX_DATA_COST_PER_NON_ZERO" |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_field (| M.get_name (| globals, "tx" |), "to" |), + M.call (| + M.get_name (| globals, "Bytes0" |), + make_list [ + Constant.bytes "" + ], + make_dict [] + |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "create_cost" , + M.get_name (| globals, "TX_CREATE_COST" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "create_cost" , + Constant.int 0 + |) in + M.pure Constant.None_ + )) |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + BinOp.add (| + BinOp.add (| + M.get_name (| globals, "TX_BASE_COST" |), + M.get_name (| globals, "data_cost" |) + |), + M.get_name (| globals, "create_cost" |) + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Definition recover_sender : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "chain_id"; "tx" ] |) in + let _ := Constant.str " + Extracts the sender address from a transaction. + + The v, r, and s values are the three parts that make up the signature + of a transaction. In order to recover the sender of a transaction the two + components needed are the signature (``v``, ``r``, and ``s``) and the + signing hash of the transaction. The sender's public key can be obtained + with these two values and therefore the sender address can be retrieved. + + Parameters + ---------- + tx : + Transaction of interest. + chain_id : + ID of the executing chain. + + Returns + ------- + sender : `ethereum.fork_types.Address` + The address of the account that signed the transaction. + " in + let _ := M.assign (| + make_tuple [ M.get_name (| globals, "v" |); M.get_name (| globals, "r" |); M.get_name (| globals, "s" |) ], + make_tuple [ M.get_field (| M.get_name (| globals, "tx" |), "v" |); M.get_field (| M.get_name (| globals, "tx" |), "r" |); M.get_field (| M.get_name (| globals, "tx" |), "s" |) ] + |) in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + BoolOp.and (| + Compare.lt (| + Constant.int 0, + M.get_name (| globals, "r" |) + |), + ltac:(M.monadic ( + Compare.lt (| + M.get_name (| globals, "r" |), + M.get_name (| globals, "SECP256K1N" |) + |) + )) + |); + M.get_name (| globals, "InvalidBlock" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + BoolOp.and (| + Compare.lt (| + Constant.int 0, + M.get_name (| globals, "s" |) + |), + ltac:(M.monadic ( + Compare.lt_e (| + M.get_name (| globals, "s" |), + BinOp.floor_div (| + M.get_name (| globals, "SECP256K1N" |), + Constant.int 2 + |) + |) + )) + |); + M.get_name (| globals, "InvalidBlock" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + BoolOp.or (| + Compare.eq (| + M.get_name (| globals, "v" |), + Constant.int 27 + |), + ltac:(M.monadic ( + Compare.eq (| + M.get_name (| globals, "v" |), + Constant.int 28 + |) + )) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "public_key" , + M.call (| + M.get_name (| globals, "secp256k1_recover" |), + make_list [ + M.get_name (| globals, "r" |); + M.get_name (| globals, "s" |); + BinOp.sub (| + M.get_name (| globals, "v" |), + Constant.int 27 + |); + M.call (| + M.get_name (| globals, "signing_hash_pre155" |), + make_list [ + M.get_name (| globals, "tx" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + BoolOp.or (| + Compare.eq (| + M.get_name (| globals, "v" |), + BinOp.add (| + Constant.int 35, + BinOp.mult (| + M.get_name (| globals, "chain_id" |), + Constant.int 2 + |) + |) + |), + ltac:(M.monadic ( + Compare.eq (| + M.get_name (| globals, "v" |), + BinOp.add (| + Constant.int 36, + BinOp.mult (| + M.get_name (| globals, "chain_id" |), + Constant.int 2 + |) + |) + |) + )) + |); + M.get_name (| globals, "InvalidBlock" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "public_key" , + M.call (| + M.get_name (| globals, "secp256k1_recover" |), + make_list [ + M.get_name (| globals, "r" |); + M.get_name (| globals, "s" |); + BinOp.sub (| + BinOp.sub (| + M.get_name (| globals, "v" |), + Constant.int 35 + |), + BinOp.mult (| + M.get_name (| globals, "chain_id" |), + Constant.int 2 + |) + |); + M.call (| + M.get_name (| globals, "signing_hash_155" |), + make_list [ + M.get_name (| globals, "tx" |); + M.get_name (| globals, "chain_id" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + )) |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, "Address" |), + make_list [ + M.slice (| + M.call (| + M.get_name (| globals, "keccak256" |), + make_list [ + M.get_name (| globals, "public_key" |) + ], + make_dict [] + |), + Constant.int 12, + Constant.int 32, + Constant.None_ + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Definition signing_hash_pre155 : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "tx" ] |) in + let _ := Constant.str " + Compute the hash of a transaction used in a legacy (pre EIP 155) signature. + + Parameters + ---------- + tx : + Transaction of interest. + + Returns + ------- + hash : `ethereum.crypto.hash.Hash32` + Hash of the transaction. + " in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, "keccak256" |), + make_list [ + M.call (| + M.get_field (| M.get_name (| globals, "rlp" |), "encode" |), + make_list [ + make_tuple [ M.get_field (| M.get_name (| globals, "tx" |), "nonce" |); M.get_field (| M.get_name (| globals, "tx" |), "gas_price" |); M.get_field (| M.get_name (| globals, "tx" |), "gas" |); M.get_field (| M.get_name (| globals, "tx" |), "to" |); M.get_field (| M.get_name (| globals, "tx" |), "value" |); M.get_field (| M.get_name (| globals, "tx" |), "data" |) ] + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Definition signing_hash_155 : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "tx"; "chain_id" ] |) in + let _ := Constant.str " + Compute the hash of a transaction used in a EIP 155 signature. + + Parameters + ---------- + tx : + Transaction of interest. + chain_id : + The id of the current chain. + + Returns + ------- + hash : `ethereum.crypto.hash.Hash32` + Hash of the transaction. + " in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, "keccak256" |), + make_list [ + M.call (| + M.get_field (| M.get_name (| globals, "rlp" |), "encode" |), + make_list [ + make_tuple [ M.get_field (| M.get_name (| globals, "tx" |), "nonce" |); M.get_field (| M.get_name (| globals, "tx" |), "gas_price" |); M.get_field (| M.get_name (| globals, "tx" |), "gas" |); M.get_field (| M.get_name (| globals, "tx" |), "to" |); M.get_field (| M.get_name (| globals, "tx" |), "value" |); M.get_field (| M.get_name (| globals, "tx" |), "data" |); M.get_name (| globals, "chain_id" |); M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |); M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) ] + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Definition compute_header_hash : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "header" ] |) in + let _ := Constant.str " + Computes the hash of a block header. + + The header hash of a block is the canonical hash that is used to refer + to a specific block and completely distinguishes a block from another. + + ``keccak256`` is a function that produces a 256 bit hash of any input. + It also takes in any number of bytes as an input and produces a single + hash for them. A hash is a completely unique output for a single input. + So an input corresponds to one unique hash that can be used to identify + the input exactly. + + Prior to using the ``keccak256`` hash function, the header must be + encoded using the Recursive-Length Prefix. See :ref:`rlp`. + RLP encoding the header converts it into a space-efficient format that + allows for easy transfer of data between nodes. The purpose of RLP is to + encode arbitrarily nested arrays of binary data, and RLP is the primary + encoding method used to serialize objects in Ethereum's execution layer. + The only purpose of RLP is to encode structure; encoding specific data + types (e.g. strings, floats) is left up to higher-order protocols. + + Parameters + ---------- + header : + Header of interest. + + Returns + ------- + hash : `ethereum.crypto.hash.Hash32` + Hash of the header. + " in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, "keccak256" |), + make_list [ + M.call (| + M.get_field (| M.get_name (| globals, "rlp" |), "encode" |), + make_list [ + M.get_name (| globals, "header" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Definition check_gas_limit : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "gas_limit"; "parent_gas_limit" ] |) in + let _ := Constant.str " + Validates the gas limit for a block. + + The bounds of the gas limit, ``max_adjustment_delta``, is set as the + quotient of the parent block's gas limit and the + ``GAS_LIMIT_ADJUSTMENT_FACTOR``. Therefore, if the gas limit that is + passed through as a parameter is greater than or equal to the *sum* of + the parent's gas and the adjustment delta then the limit for gas is too + high and fails this function's check. Similarly, if the limit is less + than or equal to the *difference* of the parent's gas and the adjustment + delta *or* the predefined ``GAS_LIMIT_MINIMUM`` then this function's + check fails because the gas limit doesn't allow for a sufficient or + reasonable amount of gas to be used on a block. + + Parameters + ---------- + gas_limit : + Gas limit to validate. + + parent_gas_limit : + Gas limit of the parent block. + + Returns + ------- + check : `bool` + True if gas limit constraints are satisfied, False otherwise. + " in + let _ := M.assign_local (| + "max_adjustment_delta" , + BinOp.floor_div (| + M.get_name (| globals, "parent_gas_limit" |), + M.get_name (| globals, "GAS_LIMIT_ADJUSTMENT_FACTOR" |) + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.gt_e (| + M.get_name (| globals, "gas_limit" |), + BinOp.add (| + M.get_name (| globals, "parent_gas_limit" |), + M.get_name (| globals, "max_adjustment_delta" |) + |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + Constant.bool false + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + Compare.lt_e (| + M.get_name (| globals, "gas_limit" |), + BinOp.sub (| + M.get_name (| globals, "parent_gas_limit" |), + M.get_name (| globals, "max_adjustment_delta" |) + |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + Constant.bool false + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + Compare.lt (| + M.get_name (| globals, "gas_limit" |), + M.get_name (| globals, "GAS_LIMIT_MINIMUM" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + Constant.bool false + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.return_ (| + Constant.bool true + |) in + M.pure Constant.None_)). + +Definition calculate_block_difficulty : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "block_number"; "block_timestamp"; "parent_timestamp"; "parent_difficulty"; "parent_has_ommers" ] |) in + let _ := Constant.str " + Computes difficulty of a block using its header and parent header. + + The difficulty is determined by the time the block was created after its + parent. The ``offset`` is calculated using the parent block's difficulty, + ``parent_difficulty``, and the timestamp between blocks. This offset is + then added to the parent difficulty and is stored as the ``difficulty`` + variable. If the time between the block and its parent is too short, the + offset will result in a positive number thus making the sum of + ``parent_difficulty`` and ``offset`` to be a greater value in order to + avoid mass forking. But, if the time is long enough, then the offset + results in a negative value making the block less difficult than + its parent. + + The base standard for a block's difficulty is the predefined value + set for the genesis block since it has no parent. So, a block + can't be less difficult than the genesis block, therefore each block's + difficulty is set to the maximum value between the calculated + difficulty and the ``GENESIS_DIFFICULTY``. + + Parameters + ---------- + block_number : + Block number of the block. + block_timestamp : + Timestamp of the block. + parent_timestamp : + Timestamp of the parent block. + parent_difficulty : + difficulty of the parent block. + parent_has_ommers: + does the parent have ommers. + + Returns + ------- + difficulty : `ethereum.base_types.Uint` + Computed difficulty for a block. + " in + let _ := M.assign_local (| + "offset" , + BinOp.mult (| + BinOp.floor_div (| + M.call (| + M.get_name (| globals, "int" |), + make_list [ + M.get_name (| globals, "parent_difficulty" |) + ], + make_dict [] + |), + Constant.int 2048 + |), + M.call (| + M.get_name (| globals, "max" |), + make_list [ + BinOp.sub (| + (* if *) + M.if_then_else (| + M.get_name (| globals, "parent_has_ommers" |), + (* then *) + ltac:(M.monadic ( +Constant.int 2 + (* else *) + )), ltac:(M.monadic ( +Constant.int 1 + )) |), + BinOp.floor_div (| + M.call (| + M.get_name (| globals, "int" |), + make_list [ + BinOp.sub (| + M.get_name (| globals, "block_timestamp" |), + M.get_name (| globals, "parent_timestamp" |) + |) + ], + make_dict [] + |), + Constant.int 9 + |) + |); + UnOp.sub (| Constant.int 99 |) + ], + make_dict [] + |) + |) + |) in + let _ := M.assign_local (| + "difficulty" , + BinOp.add (| + M.call (| + M.get_name (| globals, "int" |), + make_list [ + M.get_name (| globals, "parent_difficulty" |) + ], + make_dict [] + |), + M.get_name (| globals, "offset" |) + |) + |) in + let _ := M.assign_local (| + "num_bomb_periods" , + BinOp.sub (| + BinOp.floor_div (| + BinOp.sub (| + M.call (| + M.get_name (| globals, "int" |), + make_list [ + M.get_name (| globals, "block_number" |) + ], + make_dict [] + |), + M.get_name (| globals, "BOMB_DELAY_BLOCKS" |) + |), + Constant.int 100000 + |), + Constant.int 2 + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.gt_e (| + M.get_name (| globals, "num_bomb_periods" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_op_local (| + BinOp.add, + "difficulty", + BinOp.pow (| + Constant.int 2, + M.get_name (| globals, "num_bomb_periods" |) + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, "max" |), + make_list [ + M.get_name (| globals, "difficulty" |); + M.get_name (| globals, "MINIMUM_DIFFICULTY" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). diff --git a/CoqOfPython/ethereum/constantinople/fork_types.v b/CoqOfPython/ethereum/constantinople/fork_types.v new file mode 100644 index 0000000..351e1ef --- /dev/null +++ b/CoqOfPython/ethereum/constantinople/fork_types.v @@ -0,0 +1,98 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.constantinople.fork_types". + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Types +^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Types re-used throughout the specification, which are specific to Ethereum. +". + +Axiom dataclasses_imports_dataclass : + IsImported globals "dataclasses" "dataclass". + +Axiom ethereum_imports_rlp : + IsImported globals "ethereum" "rlp". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_Bytes : + IsImported globals "ethereum.base_types" "Bytes". +Axiom ethereum_base_types_imports_Bytes20 : + IsImported globals "ethereum.base_types" "Bytes20". +Axiom ethereum_base_types_imports_Bytes256 : + IsImported globals "ethereum.base_types" "Bytes256". +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". +Axiom ethereum_base_types_imports_slotted_freezable : + IsImported globals "ethereum.base_types" "slotted_freezable". + +Axiom ethereum_crypto_hash_imports_Hash32 : + IsImported globals "ethereum.crypto.hash" "Hash32". +Axiom ethereum_crypto_hash_imports_keccak256 : + IsImported globals "ethereum.crypto.hash" "keccak256". + +Definition Address : Value.t := M.run ltac:(M.monadic ( + M.get_name (| globals, "Bytes20" |) +)). + +Definition Root : Value.t := M.run ltac:(M.monadic ( + M.get_name (| globals, "Hash32" |) +)). + +Definition Bloom : Value.t := M.run ltac:(M.monadic ( + M.get_name (| globals, "Bytes256" |) +)). + +Definition Account : Value.t := + builtins.make_klass + [] + [ + + ] + [ + + ]. + +Definition EMPTY_ACCOUNT : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Account" |), + make_list [], + make_dict [] + |) +)). + +Definition encode_account : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "raw_account_data"; "storage_root" ] |) in + let _ := Constant.str " + Encode `Account` dataclass. + + Storage is not stored in the `Account` dataclass, so `Accounts` cannot be + encoded with providing a storage root. + " in + let _ := M.return_ (| + M.call (| + M.get_field (| M.get_name (| globals, "rlp" |), "encode" |), + make_list [ + make_tuple [ M.get_field (| M.get_name (| globals, "raw_account_data" |), "nonce" |); M.get_field (| M.get_name (| globals, "raw_account_data" |), "balance" |); M.get_name (| globals, "storage_root" |); M.call (| + M.get_name (| globals, "keccak256" |), + make_list [ + M.get_field (| M.get_name (| globals, "raw_account_data" |), "code" |) + ], + make_dict [] + |) ] + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). diff --git a/CoqOfPython/ethereum/constantinople/state.v b/CoqOfPython/ethereum/constantinople/state.v new file mode 100644 index 0000000..15a1a6d --- /dev/null +++ b/CoqOfPython/ethereum/constantinople/state.v @@ -0,0 +1,1111 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.constantinople.state". + +Definition expr_1 : Value.t := + Constant.str " +State +^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +The state contains all information that is preserved between transactions. + +It consists of a main account trie and storage tries for each contract. + +There is a distinction between an account that does not exist and +`EMPTY_ACCOUNT`. +". + +Axiom dataclasses_imports_dataclass : + IsImported globals "dataclasses" "dataclass". +Axiom dataclasses_imports_field : + IsImported globals "dataclasses" "field". + +Axiom typing_imports_Callable : + IsImported globals "typing" "Callable". +Axiom typing_imports_Dict : + IsImported globals "typing" "Dict". +Axiom typing_imports_List : + IsImported globals "typing" "List". +Axiom typing_imports_Optional : + IsImported globals "typing" "Optional". +Axiom typing_imports_Tuple : + IsImported globals "typing" "Tuple". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_Bytes : + IsImported globals "ethereum.base_types" "Bytes". +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". +Axiom ethereum_base_types_imports_modify : + IsImported globals "ethereum.base_types" "modify". + +Axiom ethereum_utils_ensure_imports_ensure : + IsImported globals "ethereum.utils.ensure" "ensure". + +Axiom ethereum_constantinople_fork_types_imports_EMPTY_ACCOUNT : + IsImported globals "ethereum.constantinople.fork_types" "EMPTY_ACCOUNT". +Axiom ethereum_constantinople_fork_types_imports_Account : + IsImported globals "ethereum.constantinople.fork_types" "Account". +Axiom ethereum_constantinople_fork_types_imports_Address : + IsImported globals "ethereum.constantinople.fork_types" "Address". +Axiom ethereum_constantinople_fork_types_imports_Root : + IsImported globals "ethereum.constantinople.fork_types" "Root". + +Axiom ethereum_constantinople_trie_imports_EMPTY_TRIE_ROOT : + IsImported globals "ethereum.constantinople.trie" "EMPTY_TRIE_ROOT". +Axiom ethereum_constantinople_trie_imports_Trie : + IsImported globals "ethereum.constantinople.trie" "Trie". +Axiom ethereum_constantinople_trie_imports_copy_trie : + IsImported globals "ethereum.constantinople.trie" "copy_trie". +Axiom ethereum_constantinople_trie_imports_root : + IsImported globals "ethereum.constantinople.trie" "root". +Axiom ethereum_constantinople_trie_imports_trie_get : + IsImported globals "ethereum.constantinople.trie" "trie_get". +Axiom ethereum_constantinople_trie_imports_trie_set : + IsImported globals "ethereum.constantinople.trie" "trie_set". + +Definition State : Value.t := + builtins.make_klass + [] + [ + + ] + [ + + ]. + +Definition close_state : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "state" ] |) in + let _ := Constant.str " + Free resources held by the state. Used by optimized implementations to + release file descriptors. + " in + let _ := M.delete (| M.get_field (| M.get_name (| globals, "state" |), "_main_trie" |) |) in + let _ := M.delete (| M.get_field (| M.get_name (| globals, "state" |), "_storage_tries" |) |) in + let _ := M.delete (| M.get_field (| M.get_name (| globals, "state" |), "_snapshots" |) |) in + M.pure Constant.None_)). + +Definition begin_transaction : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "state" ] |) in + let _ := Constant.str " + Start a state transaction. + + Transactions are entirely implicit and can be nested. It is not possible to + calculate the state root during a transaction. + + Parameters + ---------- + state : State + The state. + " in + let _ := M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, "state" |), "_snapshots" |), "append" |), + make_list [ + make_tuple [ M.call (| + M.get_name (| globals, "copy_trie" |), + make_list [ + M.get_field (| M.get_name (| globals, "state" |), "_main_trie" |) + ], + make_dict [] + |); Constant.str "(* At expr: unsupported node type: DictComp *)" ] + ], + make_dict [] + |) in + M.pure Constant.None_)). + +Definition commit_transaction : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "state" ] |) in + let _ := Constant.str " + Commit a state transaction. + + Parameters + ---------- + state : State + The state. + " in + let _ := M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, "state" |), "_snapshots" |), "pop" |), + make_list [], + make_dict [] + |) in + M.pure Constant.None_)). + +Definition rollback_transaction : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "state" ] |) in + let _ := Constant.str " + Rollback a state transaction, resetting the state to the point when the + corresponding `start_transaction()` call was made. + + Parameters + ---------- + state : State + The state. + " in + let _ := M.assign (| + make_tuple [ M.get_field (| M.get_name (| globals, "state" |), "_main_trie" |); M.get_field (| M.get_name (| globals, "state" |), "_storage_tries" |) ], + M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, "state" |), "_snapshots" |), "pop" |), + make_list [], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Definition get_account : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "state"; "address" ] |) in + let _ := Constant.str " + Get the `Account` object at an address. Returns `EMPTY_ACCOUNT` if there + is no account at the address. + + Use `get_account_optional()` if you care about the difference between a + non-existent account and `EMPTY_ACCOUNT`. + + Parameters + ---------- + state: `State` + The state + address : `Address` + Address to lookup. + + Returns + ------- + account : `Account` + Account at address. + " in + let _ := M.assign_local (| + "account" , + M.call (| + M.get_name (| globals, "get_account_optional" |), + make_list [ + M.get_name (| globals, "state" |); + M.get_name (| globals, "address" |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, "isinstance" |), + make_list [ + M.get_name (| globals, "account" |); + M.get_name (| globals, "Account" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + M.get_name (| globals, "account" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.return_ (| + M.get_name (| globals, "EMPTY_ACCOUNT" |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_)). + +Definition get_account_optional : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "state"; "address" ] |) in + let _ := Constant.str " + Get the `Account` object at an address. Returns `None` (rather than + `EMPTY_ACCOUNT`) if there is no account at the address. + + Parameters + ---------- + state: `State` + The state + address : `Address` + Address to lookup. + + Returns + ------- + account : `Account` + Account at address. + " in + let _ := M.assign_local (| + "account" , + M.call (| + M.get_name (| globals, "trie_get" |), + make_list [ + M.get_field (| M.get_name (| globals, "state" |), "_main_trie" |); + M.get_name (| globals, "address" |) + ], + make_dict [] + |) + |) in + let _ := M.return_ (| + M.get_name (| globals, "account" |) + |) in + M.pure Constant.None_)). + +Definition set_account : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "state"; "address"; "account" ] |) in + let _ := Constant.str " + Set the `Account` object at an address. Setting to `None` deletes + the account (but not its storage, see `destroy_account()`). + + Parameters + ---------- + state: `State` + The state + address : `Address` + Address to set. + account : `Account` + Account to set at address. + " in + let _ := M.call (| + M.get_name (| globals, "trie_set" |), + make_list [ + M.get_field (| M.get_name (| globals, "state" |), "_main_trie" |); + M.get_name (| globals, "address" |); + M.get_name (| globals, "account" |) + ], + make_dict [] + |) in + M.pure Constant.None_)). + +Definition destroy_account : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "state"; "address" ] |) in + let _ := Constant.str " + Completely remove the account at `address` and all of its storage. + + This function is made available exclusively for the `SELFDESTRUCT` + opcode. It is expected that `SELFDESTRUCT` will be disabled in a future + hardfork and this function will be removed. + + Parameters + ---------- + state: `State` + The state + address : `Address` + Address of account to destroy. + " in + let _ := M.call (| + M.get_name (| globals, "destroy_storage" |), + make_list [ + M.get_name (| globals, "state" |); + M.get_name (| globals, "address" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "set_account" |), + make_list [ + M.get_name (| globals, "state" |); + M.get_name (| globals, "address" |); + Constant.None_ + ], + make_dict [] + |) in + M.pure Constant.None_)). + +Definition destroy_storage : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "state"; "address" ] |) in + let _ := Constant.str " + Completely remove the storage at `address`. + + Parameters + ---------- + state: `State` + The state + address : `Address` + Address of account whose storage is to be deleted. + " in + let _ := + (* if *) + M.if_then_else (| + Compare.in_ (| + M.get_name (| globals, "address" |), + M.get_field (| M.get_name (| globals, "state" |), "_storage_tries" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.delete (| M.get_subscript (| + M.get_field (| M.get_name (| globals, "state" |), "_storage_tries" |), + M.get_name (| globals, "address" |) + |) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + M.pure Constant.None_)). + +Definition get_storage : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "state"; "address"; "key" ] |) in + let _ := Constant.str " + Get a value at a storage key on an account. Returns `U256(0)` if the + storage key has not been set previously. + + Parameters + ---------- + state: `State` + The state + address : `Address` + Address of the account. + key : `Bytes` + Key to lookup. + + Returns + ------- + value : `U256` + Value at the key. + " in + let _ := M.assign_local (| + "trie" , + M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, "state" |), "_storage_tries" |), "get" |), + make_list [ + M.get_name (| globals, "address" |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.is (| + M.get_name (| globals, "trie" |), + Constant.None_ + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "value" , + M.call (| + M.get_name (| globals, "trie_get" |), + make_list [ + M.get_name (| globals, "trie" |); + M.get_name (| globals, "key" |) + ], + make_dict [] + |) + |) in + let _ := M.assert (| M.call (| + M.get_name (| globals, "isinstance" |), + make_list [ + M.get_name (| globals, "value" |); + M.get_name (| globals, "U256" |) + ], + make_dict [] + |) |) in + let _ := M.return_ (| + M.get_name (| globals, "value" |) + |) in + M.pure Constant.None_)). + +Definition set_storage : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "state"; "address"; "key"; "value" ] |) in + let _ := Constant.str " + Set a value at a storage key on an account. Setting to `U256(0)` deletes + the key. + + Parameters + ---------- + state: `State` + The state + address : `Address` + Address of the account. + key : `Bytes` + Key to set. + value : `U256` + Value to set at the key. + " in + let _ := M.assert (| Compare.is_not (| + M.call (| + M.get_name (| globals, "trie_get" |), + make_list [ + M.get_field (| M.get_name (| globals, "state" |), "_main_trie" |); + M.get_name (| globals, "address" |) + ], + make_dict [] + |), + Constant.None_ + |) |) in + let _ := M.assign_local (| + "trie" , + M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, "state" |), "_storage_tries" |), "get" |), + make_list [ + M.get_name (| globals, "address" |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.is (| + M.get_name (| globals, "trie" |), + Constant.None_ + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "trie" , + M.call (| + M.get_name (| globals, "Trie" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.assign (| + M.get_subscript (| + M.get_field (| M.get_name (| globals, "state" |), "_storage_tries" |), + M.get_name (| globals, "address" |) + |), + M.get_name (| globals, "trie" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.call (| + M.get_name (| globals, "trie_set" |), + make_list [ + M.get_name (| globals, "trie" |); + M.get_name (| globals, "key" |); + M.get_name (| globals, "value" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_field (| M.get_name (| globals, "trie" |), "_data" |), + Constant.str "(* At expr: unsupported node type: Dict *)" + |), + (* then *) + ltac:(M.monadic ( + let _ := M.delete (| M.get_subscript (| + M.get_field (| M.get_name (| globals, "state" |), "_storage_tries" |), + M.get_name (| globals, "address" |) + |) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + M.pure Constant.None_)). + +Definition storage_root : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "state"; "address" ] |) in + let _ := Constant.str " + Calculate the storage root of an account. + + Parameters + ---------- + state: + The state + address : + Address of the account. + + Returns + ------- + root : `Root` + Storage root of the account. + " in + let _ := M.assert (| UnOp.not (| M.get_field (| M.get_name (| globals, "state" |), "_snapshots" |) |) |) in + let _ := + (* if *) + M.if_then_else (| + Compare.in_ (| + M.get_name (| globals, "address" |), + M.get_field (| M.get_name (| globals, "state" |), "_storage_tries" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + M.call (| + M.get_name (| globals, "root" |), + make_list [ + M.get_subscript (| + M.get_field (| M.get_name (| globals, "state" |), "_storage_tries" |), + M.get_name (| globals, "address" |) + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.return_ (| + M.get_name (| globals, "EMPTY_TRIE_ROOT" |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_)). + +Definition state_root : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "state" ] |) in + let _ := Constant.str " + Calculate the state root. + + Parameters + ---------- + state: + The current state. + + Returns + ------- + root : `Root` + The state root. + " in + let _ := M.assert (| UnOp.not (| M.get_field (| M.get_name (| globals, "state" |), "_snapshots" |) |) |) in +(* At stmt: unsupported node type: FunctionDef *) + let _ := M.return_ (| + M.call (| + M.get_name (| globals, "root" |), + make_list [ + M.get_field (| M.get_name (| globals, "state" |), "_main_trie" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Definition account_exists : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "state"; "address" ] |) in + let _ := Constant.str " + Checks if an account exists in the state trie + + Parameters + ---------- + state: + The state + address: + Address of the account that needs to be checked. + + Returns + ------- + account_exists : `bool` + True if account exists in the state trie, False otherwise + " in + let _ := M.return_ (| + Compare.is_not (| + M.call (| + M.get_name (| globals, "get_account_optional" |), + make_list [ + M.get_name (| globals, "state" |); + M.get_name (| globals, "address" |) + ], + make_dict [] + |), + Constant.None_ + |) + |) in + M.pure Constant.None_)). + +Definition account_has_code_or_nonce : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "state"; "address" ] |) in + let _ := Constant.str " + Checks if an account has non zero nonce or non empty code + + Parameters + ---------- + state: + The state + address: + Address of the account that needs to be checked. + + Returns + ------- + has_code_or_nonce : `bool` + True if if an account has non zero nonce or non empty code, + False otherwise. + " in + let _ := M.assign_local (| + "account" , + M.call (| + M.get_name (| globals, "get_account" |), + make_list [ + M.get_name (| globals, "state" |); + M.get_name (| globals, "address" |) + ], + make_dict [] + |) + |) in + let _ := M.return_ (| + BoolOp.or (| + Compare.not_eq (| + M.get_field (| M.get_name (| globals, "account" |), "nonce" |), + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + |), + ltac:(M.monadic ( + Compare.not_eq (| + M.get_field (| M.get_name (| globals, "account" |), "code" |), + Constant.bytes "" + |) + )) + |) + |) in + M.pure Constant.None_)). + +Definition is_account_empty : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "state"; "address" ] |) in + let _ := Constant.str " + Checks if an account has zero nonce, empty code and zero balance. + + Parameters + ---------- + state: + The state + address: + Address of the account that needs to be checked. + + Returns + ------- + is_empty : `bool` + True if if an account has zero nonce, empty code and zero balance, + False otherwise. + " in + let _ := M.assign_local (| + "account" , + M.call (| + M.get_name (| globals, "get_account" |), + make_list [ + M.get_name (| globals, "state" |); + M.get_name (| globals, "address" |) + ], + make_dict [] + |) + |) in + let _ := M.return_ (| + BoolOp.and (| + Compare.eq (| + M.get_field (| M.get_name (| globals, "account" |), "nonce" |), + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + |), + ltac:(M.monadic ( + BoolOp.and (| + Compare.eq (| + M.get_field (| M.get_name (| globals, "account" |), "code" |), + Constant.bytes "" + |), + ltac:(M.monadic ( + Compare.eq (| + M.get_field (| M.get_name (| globals, "account" |), "balance" |), + Constant.int 0 + |) + )) + |) + )) + |) + |) in + M.pure Constant.None_)). + +Definition account_exists_and_is_empty : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "state"; "address" ] |) in + let _ := Constant.str " + Checks if an account exists and has zero nonce, empty code and zero + balance. + + Parameters + ---------- + state: + The state + address: + Address of the account that needs to be checked. + + Returns + ------- + exists_and_is_empty : `bool` + True if an account exists and has zero nonce, empty code and zero + balance, False otherwise. + " in + let _ := M.assign_local (| + "account" , + M.call (| + M.get_name (| globals, "get_account_optional" |), + make_list [ + M.get_name (| globals, "state" |); + M.get_name (| globals, "address" |) + ], + make_dict [] + |) + |) in + let _ := M.return_ (| + BoolOp.and (| + Compare.is_not (| + M.get_name (| globals, "account" |), + Constant.None_ + |), + ltac:(M.monadic ( + BoolOp.and (| + Compare.eq (| + M.get_field (| M.get_name (| globals, "account" |), "nonce" |), + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + |), + ltac:(M.monadic ( + BoolOp.and (| + Compare.eq (| + M.get_field (| M.get_name (| globals, "account" |), "code" |), + Constant.bytes "" + |), + ltac:(M.monadic ( + Compare.eq (| + M.get_field (| M.get_name (| globals, "account" |), "balance" |), + Constant.int 0 + |) + )) + |) + )) + |) + )) + |) + |) in + M.pure Constant.None_)). + +Definition is_account_alive : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "state"; "address" ] |) in + let _ := Constant.str " + Check whether is an account is both in the state and non empty. + + Parameters + ---------- + state: + The state + address: + Address of the account that needs to be checked. + + Returns + ------- + is_alive : `bool` + True if the account is alive. + " in + let _ := M.assign_local (| + "account" , + M.call (| + M.get_name (| globals, "get_account_optional" |), + make_list [ + M.get_name (| globals, "state" |); + M.get_name (| globals, "address" |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.is (| + M.get_name (| globals, "account" |), + Constant.None_ + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + Constant.bool false + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.return_ (| + UnOp.not (| BoolOp.and (| + Compare.eq (| + M.get_field (| M.get_name (| globals, "account" |), "nonce" |), + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + |), + ltac:(M.monadic ( + BoolOp.and (| + Compare.eq (| + M.get_field (| M.get_name (| globals, "account" |), "code" |), + Constant.bytes "" + |), + ltac:(M.monadic ( + Compare.eq (| + M.get_field (| M.get_name (| globals, "account" |), "balance" |), + Constant.int 0 + |) + )) + |) + )) + |) |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_)). + +Definition modify_state : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "state"; "address"; "f" ] |) in + let _ := Constant.str " + Modify an `Account` in the `State`. + " in + let _ := M.call (| + M.get_name (| globals, "set_account" |), + make_list [ + M.get_name (| globals, "state" |); + M.get_name (| globals, "address" |); + M.call (| + M.get_name (| globals, "modify" |), + make_list [ + M.call (| + M.get_name (| globals, "get_account" |), + make_list [ + M.get_name (| globals, "state" |); + M.get_name (| globals, "address" |) + ], + make_dict [] + |); + M.get_name (| globals, "f" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + M.pure Constant.None_)). + +Definition move_ether : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "state"; "sender_address"; "recipient_address"; "amount" ] |) in + let _ := Constant.str " + Move funds between accounts. + " in +(* At stmt: unsupported node type: FunctionDef *) +(* At stmt: unsupported node type: FunctionDef *) + let _ := M.call (| + M.get_name (| globals, "modify_state" |), + make_list [ + M.get_name (| globals, "state" |); + M.get_name (| globals, "sender_address" |); + M.get_name (| globals, "reduce_sender_balance" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "modify_state" |), + make_list [ + M.get_name (| globals, "state" |); + M.get_name (| globals, "recipient_address" |); + M.get_name (| globals, "increase_recipient_balance" |) + ], + make_dict [] + |) in + M.pure Constant.None_)). + +Definition set_account_balance : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "state"; "address"; "amount" ] |) in + let _ := Constant.str " + Sets the balance of an account. + + Parameters + ---------- + state: + The current state. + + address: + Address of the account whose nonce needs to be incremented. + + amount: + The amount that needs to set in balance. + " in +(* At stmt: unsupported node type: FunctionDef *) + let _ := M.call (| + M.get_name (| globals, "modify_state" |), + make_list [ + M.get_name (| globals, "state" |); + M.get_name (| globals, "address" |); + M.get_name (| globals, "set_balance" |) + ], + make_dict [] + |) in + M.pure Constant.None_)). + +Definition touch_account : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "state"; "address" ] |) in + let _ := Constant.str " + Initializes an account to state. + + Parameters + ---------- + state: + The current state. + + address: + The address of the account that need to initialised. + " in + let _ := + (* if *) + M.if_then_else (| + UnOp.not (| M.call (| + M.get_name (| globals, "account_exists" |), + make_list [ + M.get_name (| globals, "state" |); + M.get_name (| globals, "address" |) + ], + make_dict [] + |) |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, "set_account" |), + make_list [ + M.get_name (| globals, "state" |); + M.get_name (| globals, "address" |); + M.get_name (| globals, "EMPTY_ACCOUNT" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + M.pure Constant.None_)). + +Definition increment_nonce : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "state"; "address" ] |) in + let _ := Constant.str " + Increments the nonce of an account. + + Parameters + ---------- + state: + The current state. + + address: + Address of the account whose nonce needs to be incremented. + " in +(* At stmt: unsupported node type: FunctionDef *) + let _ := M.call (| + M.get_name (| globals, "modify_state" |), + make_list [ + M.get_name (| globals, "state" |); + M.get_name (| globals, "address" |); + M.get_name (| globals, "increase_nonce" |) + ], + make_dict [] + |) in + M.pure Constant.None_)). + +Definition set_code : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "state"; "address"; "code" ] |) in + let _ := Constant.str " + Sets Account code. + + Parameters + ---------- + state: + The current state. + + address: + Address of the account whose code needs to be update. + + code: + The bytecode that needs to be set. + " in +(* At stmt: unsupported node type: FunctionDef *) + let _ := M.call (| + M.get_name (| globals, "modify_state" |), + make_list [ + M.get_name (| globals, "state" |); + M.get_name (| globals, "address" |); + M.get_name (| globals, "write_code" |) + ], + make_dict [] + |) in + M.pure Constant.None_)). + +Definition create_ether : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "state"; "address"; "amount" ] |) in + let _ := Constant.str " + Add newly created ether to an account. + + Parameters + ---------- + state: + The current state. + address: + Address of the account to which ether is added. + amount: + The amount of ether to be added to the account of interest. + " in +(* At stmt: unsupported node type: FunctionDef *) + let _ := M.call (| + M.get_name (| globals, "modify_state" |), + make_list [ + M.get_name (| globals, "state" |); + M.get_name (| globals, "address" |); + M.get_name (| globals, "increase_balance" |) + ], + make_dict [] + |) in + M.pure Constant.None_)). diff --git a/CoqOfPython/ethereum/constantinople/transactions.v b/CoqOfPython/ethereum/constantinople/transactions.v new file mode 100644 index 0000000..e2158f5 --- /dev/null +++ b/CoqOfPython/ethereum/constantinople/transactions.v @@ -0,0 +1,56 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.constantinople.transactions". + +Definition expr_1 : Value.t := + Constant.str " +Transactions are atomic units of work created externally to Ethereum and +submitted to be executed. If Ethereum is viewed as a state machine, +transactions are the events that move between states. +". + +Axiom dataclasses_imports_dataclass : + IsImported globals "dataclasses" "dataclass". + +Axiom typing_imports_Union : + IsImported globals "typing" "Union". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_Bytes : + IsImported globals "ethereum.base_types" "Bytes". +Axiom ethereum_base_types_imports_Bytes0 : + IsImported globals "ethereum.base_types" "Bytes0". +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". +Axiom ethereum_base_types_imports_slotted_freezable : + IsImported globals "ethereum.base_types" "slotted_freezable". + +Axiom ethereum_constantinople_fork_types_imports_Address : + IsImported globals "ethereum.constantinople.fork_types" "Address". + +Definition TX_BASE_COST : Value.t := M.run ltac:(M.monadic ( + Constant.int 21000 +)). + +Definition TX_DATA_COST_PER_NON_ZERO : Value.t := M.run ltac:(M.monadic ( + Constant.int 68 +)). + +Definition TX_DATA_COST_PER_ZERO : Value.t := M.run ltac:(M.monadic ( + Constant.int 4 +)). + +Definition TX_CREATE_COST : Value.t := M.run ltac:(M.monadic ( + Constant.int 32000 +)). + +Definition Transaction : Value.t := + builtins.make_klass + [] + [ + + ] + [ + + ]. diff --git a/CoqOfPython/ethereum/constantinople/trie.v b/CoqOfPython/ethereum/constantinople/trie.v new file mode 100644 index 0000000..18f9155 --- /dev/null +++ b/CoqOfPython/ethereum/constantinople/trie.v @@ -0,0 +1,1589 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.constantinople.trie". + +Definition expr_1 : Value.t := + Constant.str " +State Trie +^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +The state trie is the structure responsible for storing +`.fork_types.Account` objects. +". + +(* At top_level_stmt: unsupported node type: Import *) + +Axiom dataclasses_imports_dataclass : + IsImported globals "dataclasses" "dataclass". +Axiom dataclasses_imports_field : + IsImported globals "dataclasses" "field". + +Axiom typing_imports_Callable : + IsImported globals "typing" "Callable". +Axiom typing_imports_Dict : + IsImported globals "typing" "Dict". +Axiom typing_imports_Generic : + IsImported globals "typing" "Generic". +Axiom typing_imports_List : + IsImported globals "typing" "List". +Axiom typing_imports_Mapping : + IsImported globals "typing" "Mapping". +Axiom typing_imports_MutableMapping : + IsImported globals "typing" "MutableMapping". +Axiom typing_imports_Optional : + IsImported globals "typing" "Optional". +Axiom typing_imports_Sequence : + IsImported globals "typing" "Sequence". +Axiom typing_imports_TypeVar : + IsImported globals "typing" "TypeVar". +Axiom typing_imports_Union : + IsImported globals "typing" "Union". +Axiom typing_imports_cast : + IsImported globals "typing" "cast". + +Axiom ethereum_byzantium_imports_trie : + IsImported globals "ethereum.byzantium" "trie". + +Axiom ethereum_crypto_hash_imports_keccak256 : + IsImported globals "ethereum.crypto.hash" "keccak256". + +Axiom ethereum_utils_ensure_imports_ensure : + IsImported globals "ethereum.utils.ensure" "ensure". + +Axiom ethereum_utils_hexadecimal_imports_hex_to_bytes : + IsImported globals "ethereum.utils.hexadecimal" "hex_to_bytes". + +Axiom ethereum_imports_rlp : + IsImported globals "ethereum" "rlp". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_Bytes : + IsImported globals "ethereum.base_types" "Bytes". +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". +Axiom ethereum_base_types_imports_slotted_freezable : + IsImported globals "ethereum.base_types" "slotted_freezable". + +Axiom ethereum_constantinople_blocks_imports_Receipt : + IsImported globals "ethereum.constantinople.blocks" "Receipt". + +Axiom ethereum_constantinople_fork_types_imports_Account : + IsImported globals "ethereum.constantinople.fork_types" "Account". +Axiom ethereum_constantinople_fork_types_imports_Address : + IsImported globals "ethereum.constantinople.fork_types" "Address". +Axiom ethereum_constantinople_fork_types_imports_Root : + IsImported globals "ethereum.constantinople.fork_types" "Root". +Axiom ethereum_constantinople_fork_types_imports_encode_account : + IsImported globals "ethereum.constantinople.fork_types" "encode_account". + +Axiom ethereum_constantinople_transactions_imports_Transaction : + IsImported globals "ethereum.constantinople.transactions" "Transaction". + +Definition EMPTY_TRIE_ROOT : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Root" |), + make_list [ + M.call (| + M.get_name (| globals, "hex_to_bytes" |), + make_list [ + Constant.str "56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421" + ], + make_dict [] + |) + ], + make_dict [] + |) +)). + +Definition Node : Value.t := M.run ltac:(M.monadic ( + M.get_subscript (| + M.get_name (| globals, "Union" |), + make_tuple [ M.get_name (| globals, "Account" |); M.get_name (| globals, "Bytes" |); M.get_name (| globals, "Transaction" |); M.get_name (| globals, "Receipt" |); M.get_name (| globals, "Uint" |); M.get_name (| globals, "U256" |); Constant.None_ ] + |) +)). + +Definition K : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "TypeVar" |), + make_list [ + Constant.str "K" + ], + make_dict [] + |) +)). + +Definition V : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "TypeVar" |), + make_list [ + Constant.str "V"; + M.get_subscript (| + M.get_name (| globals, "Optional" |), + M.get_name (| globals, "Account" |) + |); + M.get_subscript (| + M.get_name (| globals, "Optional" |), + M.get_name (| globals, "Bytes" |) + |); + M.get_name (| globals, "Bytes" |); + M.get_subscript (| + M.get_name (| globals, "Optional" |), + M.get_name (| globals, "Transaction" |) + |); + M.get_subscript (| + M.get_name (| globals, "Optional" |), + M.get_name (| globals, "Receipt" |) + |); + M.get_name (| globals, "Uint" |); + M.get_name (| globals, "U256" |) + ], + make_dict [] + |) +)). + +Definition LeafNode : Value.t := + builtins.make_klass + [] + [ + + ] + [ + + ]. + +Definition ExtensionNode : Value.t := + builtins.make_klass + [] + [ + + ] + [ + + ]. + +Definition BranchNode : Value.t := + builtins.make_klass + [] + [ + + ] + [ + + ]. + +Definition InternalNode : Value.t := M.run ltac:(M.monadic ( + M.get_subscript (| + M.get_name (| globals, "Union" |), + make_tuple [ M.get_name (| globals, "LeafNode" |); M.get_name (| globals, "ExtensionNode" |); M.get_name (| globals, "BranchNode" |) ] + |) +)). + +Definition encode_internal_node : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "node" ] |) in + let _ := Constant.str " + Encodes a Merkle Trie node into its RLP form. The RLP will then be + serialized into a `Bytes` and hashed unless it is less that 32 bytes + when serialized. + + This function also accepts `None`, representing the absence of a node, + which is encoded to `b""""`. + + Parameters + ---------- + node : Optional[InternalNode] + The node to encode. + + Returns + ------- + encoded : `rlp.RLP` + The node encoded as RLP. + " in +(* At stmt: unsupported node type: AnnAssign *) + let _ := + (* if *) + M.if_then_else (| + Compare.is (| + M.get_name (| globals, "node" |), + Constant.None_ + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "unencoded" , + Constant.bytes "" + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, "isinstance" |), + make_list [ + M.get_name (| globals, "node" |); + M.get_name (| globals, "LeafNode" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "unencoded" , + make_tuple [ M.call (| + M.get_name (| globals, "nibble_list_to_compact" |), + make_list [ + M.get_field (| M.get_name (| globals, "node" |), "rest_of_key" |); + Constant.bool true + ], + make_dict [] + |); M.get_field (| M.get_name (| globals, "node" |), "value" |) ] + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, "isinstance" |), + make_list [ + M.get_name (| globals, "node" |); + M.get_name (| globals, "ExtensionNode" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "unencoded" , + make_tuple [ M.call (| + M.get_name (| globals, "nibble_list_to_compact" |), + make_list [ + M.get_field (| M.get_name (| globals, "node" |), "key_segment" |); + Constant.bool false + ], + make_dict [] + |); M.get_field (| M.get_name (| globals, "node" |), "subnode" |) ] + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, "isinstance" |), + make_list [ + M.get_name (| globals, "node" |); + M.get_name (| globals, "BranchNode" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "unencoded" , + BinOp.add (| + M.get_field (| M.get_name (| globals, "node" |), "subnodes" |), + make_list [ + M.get_field (| M.get_name (| globals, "node" |), "value" |) + ] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.raise (| Some (M.call (| + M.get_name (| globals, "AssertionError" |), + make_list [ + Constant.str "(* At expr: unsupported node type: JoinedStr *)" + ], + make_dict [] + |)) |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "encoded" , + M.call (| + M.get_field (| M.get_name (| globals, "rlp" |), "encode" |), + make_list [ + M.get_name (| globals, "unencoded" |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.lt (| + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_name (| globals, "encoded" |) + ], + make_dict [] + |), + Constant.int 32 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + M.get_name (| globals, "unencoded" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.return_ (| + M.call (| + M.get_name (| globals, "keccak256" |), + make_list [ + M.get_name (| globals, "encoded" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_)). + +Definition encode_node : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "node"; "storage_root" ] |) in + let _ := Constant.str " + Encode a Node for storage in the Merkle Trie. + + Currently mostly an unimplemented stub. + " in + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, "isinstance" |), + make_list [ + M.get_name (| globals, "node" |); + M.get_name (| globals, "Account" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assert (| Compare.is_not (| + M.get_name (| globals, "storage_root" |), + Constant.None_ + |) |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, "encode_account" |), + make_list [ + M.get_name (| globals, "node" |); + M.get_name (| globals, "storage_root" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, "isinstance" |), + make_list [ + M.get_name (| globals, "node" |); + make_tuple [ M.get_name (| globals, "Transaction" |); M.get_name (| globals, "Receipt" |); M.get_name (| globals, "U256" |) ] + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + M.call (| + M.get_field (| M.get_name (| globals, "rlp" |), "encode" |), + make_list [ + M.call (| + M.get_name (| globals, "cast" |), + make_list [ + M.get_field (| M.get_name (| globals, "rlp" |), "RLP" |); + M.get_name (| globals, "node" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, "isinstance" |), + make_list [ + M.get_name (| globals, "node" |); + M.get_name (| globals, "Bytes" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + M.get_name (| globals, "node" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.return_ (| + M.call (| + M.get_field (| M.get_name (| globals, "previous_trie" |), "encode_node" |), + make_list [ + M.get_name (| globals, "node" |); + M.get_name (| globals, "storage_root" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_)). + +Definition Trie : Value.t := + builtins.make_klass + [(* At base: unsupported node type: Subscript *)] + [ + + ] + [ + + ]. + +Definition copy_trie : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "trie" ] |) in + let _ := Constant.str " + Create a copy of `trie`. Since only frozen objects may be stored in tries, + the contents are reused. + + Parameters + ---------- + trie: `Trie` + Trie to copy. + + Returns + ------- + new_trie : `Trie[K, V]` + A copy of the trie. + " in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, "Trie" |), + make_list [ + M.get_field (| M.get_name (| globals, "trie" |), "secured" |); + M.get_field (| M.get_name (| globals, "trie" |), "default" |); + M.call (| + M.get_field (| M.get_name (| globals, "copy" |), "copy" |), + make_list [ + M.get_field (| M.get_name (| globals, "trie" |), "_data" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Definition trie_set : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "trie"; "key"; "value" ] |) in + let _ := Constant.str " + Stores an item in a Merkle Trie. + + This method deletes the key if `value == trie.default`, because the Merkle + Trie represents the default value by omitting it from the trie. + + Parameters + ---------- + trie: `Trie` + Trie to store in. + key : `Bytes` + Key to lookup. + value : `V` + Node to insert at `key`. + " in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, "value" |), + M.get_field (| M.get_name (| globals, "trie" |), "default" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + Compare.in_ (| + M.get_name (| globals, "key" |), + M.get_field (| M.get_name (| globals, "trie" |), "_data" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.delete (| M.get_subscript (| + M.get_field (| M.get_name (| globals, "trie" |), "_data" |), + M.get_name (| globals, "key" |) + |) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign (| + M.get_subscript (| + M.get_field (| M.get_name (| globals, "trie" |), "_data" |), + M.get_name (| globals, "key" |) + |), + M.get_name (| globals, "value" |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_)). + +Definition trie_get : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "trie"; "key" ] |) in + let _ := Constant.str " + Gets an item from the Merkle Trie. + + This method returns `trie.default` if the key is missing. + + Parameters + ---------- + trie: + Trie to lookup in. + key : + Key to lookup. + + Returns + ------- + node : `V` + Node at `key` in the trie. + " in + let _ := M.return_ (| + M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, "trie" |), "_data" |), "get" |), + make_list [ + M.get_name (| globals, "key" |); + M.get_field (| M.get_name (| globals, "trie" |), "default" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Definition common_prefix_length : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "a"; "b" ] |) in + let _ := Constant.str " + Find the longest common prefix of two sequences. + " in + let _ := + M.for_ (| + M.get_name (| globals, "i" |), + M.call (| + M.get_name (| globals, "range" |), + make_list [ + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_name (| globals, "a" |) + ], + make_dict [] + |) + ], + make_dict [] + |), + ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + BoolOp.or (| + Compare.gt_e (| + M.get_name (| globals, "i" |), + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_name (| globals, "b" |) + ], + make_dict [] + |) + |), + ltac:(M.monadic ( + Compare.not_eq (| + M.get_subscript (| + M.get_name (| globals, "a" |), + M.get_name (| globals, "i" |) + |), + M.get_subscript (| + M.get_name (| globals, "b" |), + M.get_name (| globals, "i" |) + |) + |) + )) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + M.get_name (| globals, "i" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_name (| globals, "a" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Definition nibble_list_to_compact : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "x"; "is_leaf" ] |) in + let _ := Constant.str " + Compresses nibble-list into a standard byte array with a flag. + + A nibble-list is a list of byte values no greater than `15`. The flag is + encoded in high nibble of the highest byte. The flag nibble can be broken + down into two two-bit flags. + + Highest nibble:: + + +---+---+----------+--------+ + | _ | _ | is_leaf | parity | + +---+---+----------+--------+ + 3 2 1 0 + + + The lowest bit of the nibble encodes the parity of the length of the + remaining nibbles -- `0` when even and `1` when odd. The second lowest bit + is used to distinguish leaf and extension nodes. The other two bits are not + used. + + Parameters + ---------- + x : + Array of nibbles. + is_leaf : + True if this is part of a leaf node, or false if it is an extension + node. + + Returns + ------- + compressed : `bytearray` + Compact byte array. + " in + let _ := M.assign_local (| + "compact" , + M.call (| + M.get_name (| globals, "bytearray" |), + make_list [], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + BinOp.mod_ (| + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_name (| globals, "x" |) + ], + make_dict [] + |), + Constant.int 2 + |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_field (| M.get_name (| globals, "compact" |), "append" |), + make_list [ + BinOp.mult (| + Constant.int 16, + BinOp.mult (| + Constant.int 2, + M.get_name (| globals, "is_leaf" |) + |) + |) + ], + make_dict [] + |) in + let _ := + M.for_ (| + M.get_name (| globals, "i" |), + M.call (| + M.get_name (| globals, "range" |), + make_list [ + Constant.int 0; + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_name (| globals, "x" |) + ], + make_dict [] + |); + Constant.int 2 + ], + make_dict [] + |), + ltac:(M.monadic ( + let _ := M.call (| + M.get_field (| M.get_name (| globals, "compact" |), "append" |), + make_list [ + BinOp.add (| + BinOp.mult (| + Constant.int 16, + M.get_subscript (| + M.get_name (| globals, "x" |), + M.get_name (| globals, "i" |) + |) + |), + M.get_subscript (| + M.get_name (| globals, "x" |), + BinOp.add (| + M.get_name (| globals, "i" |), + Constant.int 1 + |) + |) + |) + ], + make_dict [] + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.call (| + M.get_field (| M.get_name (| globals, "compact" |), "append" |), + make_list [ + BinOp.add (| + BinOp.mult (| + Constant.int 16, + BinOp.add (| + BinOp.mult (| + Constant.int 2, + M.get_name (| globals, "is_leaf" |) + |), + Constant.int 1 + |) + |), + M.get_subscript (| + M.get_name (| globals, "x" |), + Constant.int 0 + |) + |) + ], + make_dict [] + |) in + let _ := + M.for_ (| + M.get_name (| globals, "i" |), + M.call (| + M.get_name (| globals, "range" |), + make_list [ + Constant.int 1; + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_name (| globals, "x" |) + ], + make_dict [] + |); + Constant.int 2 + ], + make_dict [] + |), + ltac:(M.monadic ( + let _ := M.call (| + M.get_field (| M.get_name (| globals, "compact" |), "append" |), + make_list [ + BinOp.add (| + BinOp.mult (| + Constant.int 16, + M.get_subscript (| + M.get_name (| globals, "x" |), + M.get_name (| globals, "i" |) + |) + |), + M.get_subscript (| + M.get_name (| globals, "x" |), + BinOp.add (| + M.get_name (| globals, "i" |), + Constant.int 1 + |) + |) + |) + ], + make_dict [] + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + M.pure Constant.None_ + )) |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, "Bytes" |), + make_list [ + M.get_name (| globals, "compact" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Definition bytes_to_nibble_list : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "bytes_" ] |) in + let _ := Constant.str " + Converts a `Bytes` into to a sequence of nibbles (bytes with value < 16). + + Parameters + ---------- + bytes_: + The `Bytes` to convert. + + Returns + ------- + nibble_list : `Bytes` + The `Bytes` in nibble-list format. + " in + let _ := M.assign_local (| + "nibble_list" , + M.call (| + M.get_name (| globals, "bytearray" |), + make_list [ + BinOp.mult (| + Constant.int 2, + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_name (| globals, "bytes_" |) + ], + make_dict [] + |) + |) + ], + make_dict [] + |) + |) in + let _ := + M.for_ (| + make_tuple [ M.get_name (| globals, "byte_index" |); M.get_name (| globals, "byte" |) ], + M.call (| + M.get_name (| globals, "enumerate" |), + make_list [ + M.get_name (| globals, "bytes_" |) + ], + make_dict [] + |), + ltac:(M.monadic ( + let _ := M.assign (| + M.get_subscript (| + M.get_name (| globals, "nibble_list" |), + BinOp.mult (| + M.get_name (| globals, "byte_index" |), + Constant.int 2 + |) + |), + BinOp.r_shift (| + BinOp.bit_and (| + M.get_name (| globals, "byte" |), + Constant.int 240 + |), + Constant.int 4 + |) + |) in + let _ := M.assign (| + M.get_subscript (| + M.get_name (| globals, "nibble_list" |), + BinOp.add (| + BinOp.mult (| + M.get_name (| globals, "byte_index" |), + Constant.int 2 + |), + Constant.int 1 + |) + |), + BinOp.bit_and (| + M.get_name (| globals, "byte" |), + Constant.int 15 + |) + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, "Bytes" |), + make_list [ + M.get_name (| globals, "nibble_list" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Definition _prepare_trie : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "trie"; "get_storage_root" ] |) in + let _ := Constant.str " + Prepares the trie for root calculation. Removes values that are empty, + hashes the keys (if `secured == True`) and encodes all the nodes. + + Parameters + ---------- + trie : + The `Trie` to prepare. + get_storage_root : + Function to get the storage root of an account. Needed to encode + `Account` objects. + + Returns + ------- + out : `Mapping[ethereum.base_types.Bytes, Node]` + Object with keys mapped to nibble-byte form. + " in +(* At stmt: unsupported node type: AnnAssign *) + let _ := + M.for_ (| + make_tuple [ M.get_name (| globals, "preimage" |); M.get_name (| globals, "value" |) ], + M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, "trie" |), "_data" |), "items" |), + make_list [], + make_dict [] + |), + ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, "isinstance" |), + make_list [ + M.get_name (| globals, "value" |); + M.get_name (| globals, "Account" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assert (| Compare.is_not (| + M.get_name (| globals, "get_storage_root" |), + Constant.None_ + |) |) in + let _ := M.assign_local (| + "address" , + M.call (| + M.get_name (| globals, "Address" |), + make_list [ + M.get_name (| globals, "preimage" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "encoded_value" , + M.call (| + M.get_name (| globals, "encode_node" |), + make_list [ + M.get_name (| globals, "value" |); + M.call (| + M.get_name (| globals, "get_storage_root" |), + make_list [ + M.get_name (| globals, "address" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "encoded_value" , + M.call (| + M.get_name (| globals, "encode_node" |), + make_list [ + M.get_name (| globals, "value" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + )) |) in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + Compare.not_eq (| + M.get_name (| globals, "encoded_value" |), + Constant.bytes "" + |); + M.get_name (| globals, "AssertionError" |) + ], + make_dict [] + |) in +(* At stmt: unsupported node type: AnnAssign *) + let _ := + (* if *) + M.if_then_else (| + M.get_field (| M.get_name (| globals, "trie" |), "secured" |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "key" , + M.call (| + M.get_name (| globals, "keccak256" |), + make_list [ + M.get_name (| globals, "preimage" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "key" , + M.get_name (| globals, "preimage" |) + |) in + M.pure Constant.None_ + )) |) in + let _ := M.assign (| + M.get_subscript (| + M.get_name (| globals, "mapped" |), + M.call (| + M.get_name (| globals, "bytes_to_nibble_list" |), + make_list [ + M.get_name (| globals, "key" |) + ], + make_dict [] + |) + |), + M.get_name (| globals, "encoded_value" |) + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := M.return_ (| + M.get_name (| globals, "mapped" |) + |) in + M.pure Constant.None_)). + +Definition root : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "trie"; "get_storage_root" ] |) in + let _ := Constant.str " + Computes the root of a modified merkle patricia trie (MPT). + + Parameters + ---------- + trie : + `Trie` to get the root of. + get_storage_root : + Function to get the storage root of an account. Needed to encode + `Account` objects. + + + Returns + ------- + root : `.fork_types.Root` + MPT root of the underlying key-value pairs. + " in + let _ := M.assign_local (| + "obj" , + M.call (| + M.get_name (| globals, "_prepare_trie" |), + make_list [ + M.get_name (| globals, "trie" |); + M.get_name (| globals, "get_storage_root" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "root_node" , + M.call (| + M.get_name (| globals, "encode_internal_node" |), + make_list [ + M.call (| + M.get_name (| globals, "patricialize" |), + make_list [ + M.get_name (| globals, "obj" |); + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.lt (| + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.call (| + M.get_field (| M.get_name (| globals, "rlp" |), "encode" |), + make_list [ + M.get_name (| globals, "root_node" |) + ], + make_dict [] + |) + ], + make_dict [] + |), + Constant.int 32 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + M.call (| + M.get_name (| globals, "keccak256" |), + make_list [ + M.call (| + M.get_field (| M.get_name (| globals, "rlp" |), "encode" |), + make_list [ + M.get_name (| globals, "root_node" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assert (| M.call (| + M.get_name (| globals, "isinstance" |), + make_list [ + M.get_name (| globals, "root_node" |); + M.get_name (| globals, "Bytes" |) + ], + make_dict [] + |) |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, "Root" |), + make_list [ + M.get_name (| globals, "root_node" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_)). + +Definition patricialize : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "obj"; "level" ] |) in + let _ := Constant.str " + Structural composition function. + + Used to recursively patricialize and merkleize a dictionary. Includes + memoization of the tree structure and hashes. + + Parameters + ---------- + obj : + Underlying trie key-value pairs, with keys in nibble-list format. + level : + Current trie level. + + Returns + ------- + node : `ethereum.base_types.Bytes` + Root node of `obj`. + " in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_name (| globals, "obj" |) + ], + make_dict [] + |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + Constant.None_ + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "arbitrary_key" , + M.call (| + M.get_name (| globals, "next" |), + make_list [ + M.call (| + M.get_name (| globals, "iter" |), + make_list [ + M.get_name (| globals, "obj" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_name (| globals, "obj" |) + ], + make_dict [] + |), + Constant.int 1 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "leaf" , + M.call (| + M.get_name (| globals, "LeafNode" |), + make_list [ + M.slice (| + M.get_name (| globals, "arbitrary_key" |), + M.get_name (| globals, "level" |), + Constant.None_, + Constant.None_ + |); + M.get_subscript (| + M.get_name (| globals, "obj" |), + M.get_name (| globals, "arbitrary_key" |) + |) + ], + make_dict [] + |) + |) in + let _ := M.return_ (| + M.get_name (| globals, "leaf" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "substring" , + M.slice (| + M.get_name (| globals, "arbitrary_key" |), + M.get_name (| globals, "level" |), + Constant.None_, + Constant.None_ + |) + |) in + let _ := M.assign_local (| + "prefix_length" , + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_name (| globals, "substring" |) + ], + make_dict [] + |) + |) in + let _ := + M.for_ (| + M.get_name (| globals, "key" |), + M.get_name (| globals, "obj" |), + ltac:(M.monadic ( + let _ := M.assign_local (| + "prefix_length" , + M.call (| + M.get_name (| globals, "min" |), + make_list [ + M.get_name (| globals, "prefix_length" |); + M.call (| + M.get_name (| globals, "common_prefix_length" |), + make_list [ + M.get_name (| globals, "substring" |); + M.slice (| + M.get_name (| globals, "key" |), + M.get_name (| globals, "level" |), + Constant.None_, + Constant.None_ + |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, "prefix_length" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.break (| |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.gt (| + M.get_name (| globals, "prefix_length" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "prefix" , + M.slice (| + M.get_name (| globals, "arbitrary_key" |), + M.get_name (| globals, "level" |), + BinOp.add (| + M.get_name (| globals, "level" |), + M.get_name (| globals, "prefix_length" |) + |), + Constant.None_ + |) + |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, "ExtensionNode" |), + make_list [ + M.get_name (| globals, "prefix" |); + M.call (| + M.get_name (| globals, "encode_internal_node" |), + make_list [ + M.call (| + M.get_name (| globals, "patricialize" |), + make_list [ + M.get_name (| globals, "obj" |); + BinOp.add (| + M.get_name (| globals, "level" |), + M.get_name (| globals, "prefix_length" |) + |) + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in +(* At stmt: unsupported node type: AnnAssign *) + let _ := + M.for_ (| + M.get_name (| globals, "_" |), + M.call (| + M.get_name (| globals, "range" |), + make_list [ + Constant.int 16 + ], + make_dict [] + |), + ltac:(M.monadic ( + let _ := M.call (| + M.get_field (| M.get_name (| globals, "branches" |), "append" |), + make_list [ + Constant.str "(* At expr: unsupported node type: Dict *)" + ], + make_dict [] + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := M.assign_local (| + "value" , + Constant.bytes "" + |) in + let _ := + M.for_ (| + M.get_name (| globals, "key" |), + M.get_name (| globals, "obj" |), + ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_name (| globals, "key" |) + ], + make_dict [] + |), + M.get_name (| globals, "level" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, "isinstance" |), + make_list [ + M.get_subscript (| + M.get_name (| globals, "obj" |), + M.get_name (| globals, "key" |) + |); + make_tuple [ M.get_name (| globals, "Account" |); M.get_name (| globals, "Receipt" |); M.get_name (| globals, "Uint" |) ] + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, "AssertionError" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "value" , + M.get_subscript (| + M.get_name (| globals, "obj" |), + M.get_name (| globals, "key" |) + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign (| + M.get_subscript (| + M.get_subscript (| + M.get_name (| globals, "branches" |), + M.get_subscript (| + M.get_name (| globals, "key" |), + M.get_name (| globals, "level" |) + |) + |), + M.get_name (| globals, "key" |) + |), + M.get_subscript (| + M.get_name (| globals, "obj" |), + M.get_name (| globals, "key" |) + |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, "BranchNode" |), + make_list [ + Constant.str "(* At expr: unsupported node type: ListComp *)"; + M.get_name (| globals, "value" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). diff --git a/CoqOfPython/ethereum/constantinople/utils/__init__.v b/CoqOfPython/ethereum/constantinople/utils/__init__.v new file mode 100644 index 0000000..e5396b1 --- /dev/null +++ b/CoqOfPython/ethereum/constantinople/utils/__init__.v @@ -0,0 +1,8 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.constantinople.utils.__init__". + +Definition expr_1 : Value.t := + Constant.str " +Utility functions unique to this particular fork. +". diff --git a/CoqOfPython/ethereum/constantinople/utils/address.v b/CoqOfPython/ethereum/constantinople/utils/address.v new file mode 100644 index 0000000..a23e9b8 --- /dev/null +++ b/CoqOfPython/ethereum/constantinople/utils/address.v @@ -0,0 +1,227 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.constantinople.utils.address". + +Definition expr_1 : Value.t := + Constant.str " +Hardfork Utility Functions For Addresses +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Address specific functions used in this constantinople version of +specification. +". + +Axiom typing_imports_Union : + IsImported globals "typing" "Union". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_Bytes32 : + IsImported globals "ethereum.base_types" "Bytes32". +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". + +Axiom ethereum_crypto_hash_imports_keccak256 : + IsImported globals "ethereum.crypto.hash" "keccak256". + +Axiom ethereum_utils_byte_imports_left_pad_zero_bytes : + IsImported globals "ethereum.utils.byte" "left_pad_zero_bytes". + +Axiom ethereum_imports_rlp : + IsImported globals "ethereum" "rlp". + +Axiom ethereum_constantinople_fork_types_imports_Address : + IsImported globals "ethereum.constantinople.fork_types" "Address". + +Definition to_address : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "data" ] |) in + let _ := Constant.str " + Convert a Uint or U256 value to a valid address (20 bytes). + + Parameters + ---------- + data : + The string to be converted to bytes. + + Returns + ------- + address : `Address` + The obtained address. + " in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, "Address" |), + make_list [ + M.slice (| + M.call (| + M.get_field (| M.get_name (| globals, "data" |), "to_be_bytes32" |), + make_list [], + make_dict [] + |), + UnOp.sub (| Constant.int 20 |), + Constant.None_, + Constant.None_ + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Definition compute_contract_address : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "address"; "nonce" ] |) in + let _ := Constant.str " + Computes address of the new account that needs to be created. + + Parameters + ---------- + address : + The address of the account that wants to create the new account. + nonce : + The transaction count of the account that wants to create the new + account. + + Returns + ------- + address: `Address` + The computed address of the new account. + " in + let _ := M.assign_local (| + "computed_address" , + M.call (| + M.get_name (| globals, "keccak256" |), + make_list [ + M.call (| + M.get_field (| M.get_name (| globals, "rlp" |), "encode" |), + make_list [ + make_list [ + M.get_name (| globals, "address" |); + M.get_name (| globals, "nonce" |) + ] + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "canonical_address" , + M.slice (| + M.get_name (| globals, "computed_address" |), + UnOp.sub (| Constant.int 20 |), + Constant.None_, + Constant.None_ + |) + |) in + let _ := M.assign_local (| + "padded_address" , + M.call (| + M.get_name (| globals, "left_pad_zero_bytes" |), + make_list [ + M.get_name (| globals, "canonical_address" |); + Constant.int 20 + ], + make_dict [] + |) + |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, "Address" |), + make_list [ + M.get_name (| globals, "padded_address" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Definition compute_create2_contract_address : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "address"; "salt"; "call_data" ] |) in + let _ := Constant.str " + Computes address of the new account that needs to be created, which is + based on the sender address, salt and the call data as well. + + Parameters + ---------- + address : + The address of the account that wants to create the new account. + salt : + Address generation salt. + call_data : + The code of the new account which is to be created. + + Returns + ------- + address: `ethereum.constantinople.fork_types.Address` + The computed address of the new account. + " in + let _ := M.assign_local (| + "preimage" , + BinOp.add (| + BinOp.add (| + BinOp.add (| + Constant.bytes "ff", + M.get_name (| globals, "address" |) + |), + M.get_name (| globals, "salt" |) + |), + M.call (| + M.get_name (| globals, "keccak256" |), + make_list [ + M.get_name (| globals, "call_data" |) + ], + make_dict [] + |) + |) + |) in + let _ := M.assign_local (| + "computed_address" , + M.call (| + M.get_name (| globals, "keccak256" |), + make_list [ + M.get_name (| globals, "preimage" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "canonical_address" , + M.slice (| + M.get_name (| globals, "computed_address" |), + UnOp.sub (| Constant.int 20 |), + Constant.None_, + Constant.None_ + |) + |) in + let _ := M.assign_local (| + "padded_address" , + M.call (| + M.get_name (| globals, "left_pad_zero_bytes" |), + make_list [ + M.get_name (| globals, "canonical_address" |); + Constant.int 20 + ], + make_dict [] + |) + |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, "Address" |), + make_list [ + M.get_name (| globals, "padded_address" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). diff --git a/CoqOfPython/ethereum/constantinople/utils/hexadecimal.v b/CoqOfPython/ethereum/constantinople/utils/hexadecimal.v new file mode 100644 index 0000000..6eae082 --- /dev/null +++ b/CoqOfPython/ethereum/constantinople/utils/hexadecimal.v @@ -0,0 +1,153 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.constantinople.utils.hexadecimal". + +Definition expr_1 : Value.t := + Constant.str " +Utility Functions For Hexadecimal Strings +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Hexadecimal utility functions used in this specification, specific to +Constantinople types. +". + +Axiom ethereum_utils_hexadecimal_imports_remove_hex_prefix : + IsImported globals "ethereum.utils.hexadecimal" "remove_hex_prefix". + +Axiom ethereum_constantinople_fork_types_imports_Address : + IsImported globals "ethereum.constantinople.fork_types" "Address". +Axiom ethereum_constantinople_fork_types_imports_Bloom : + IsImported globals "ethereum.constantinople.fork_types" "Bloom". +Axiom ethereum_constantinople_fork_types_imports_Root : + IsImported globals "ethereum.constantinople.fork_types" "Root". + +Definition hex_to_root : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "hex_string" ] |) in + let _ := Constant.str " + Convert hex string to trie root. + + Parameters + ---------- + hex_string : + The hexadecimal string to be converted to trie root. + + Returns + ------- + root : `Root` + Trie root obtained from the given hexadecimal string. + " in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, "Root" |), + make_list [ + M.call (| + M.get_field (| M.get_name (| globals, "bytes" |), "fromhex" |), + make_list [ + M.call (| + M.get_name (| globals, "remove_hex_prefix" |), + make_list [ + M.get_name (| globals, "hex_string" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Definition hex_to_bloom : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "hex_string" ] |) in + let _ := Constant.str " + Convert hex string to bloom. + + Parameters + ---------- + hex_string : + The hexadecimal string to be converted to bloom. + + Returns + ------- + bloom : `Bloom` + Bloom obtained from the given hexadecimal string. + " in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, "Bloom" |), + make_list [ + M.call (| + M.get_field (| M.get_name (| globals, "bytes" |), "fromhex" |), + make_list [ + M.call (| + M.get_name (| globals, "remove_hex_prefix" |), + make_list [ + M.get_name (| globals, "hex_string" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Definition hex_to_address : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "hex_string" ] |) in + let _ := Constant.str " + Convert hex string to Address (20 bytes). + + Parameters + ---------- + hex_string : + The hexadecimal string to be converted to Address. + + Returns + ------- + address : `Address` + The address obtained from the given hexadecimal string. + " in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, "Address" |), + make_list [ + M.call (| + M.get_field (| M.get_name (| globals, "bytes" |), "fromhex" |), + make_list [ + M.call (| + M.get_field (| M.call (| + M.get_name (| globals, "remove_hex_prefix" |), + make_list [ + M.get_name (| globals, "hex_string" |) + ], + make_dict [] + |), "rjust" |), + make_list [ + Constant.int 40; + Constant.str "0" + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). diff --git a/CoqOfPython/ethereum/constantinople/utils/message.v b/CoqOfPython/ethereum/constantinople/utils/message.v new file mode 100644 index 0000000..202ca4d --- /dev/null +++ b/CoqOfPython/ethereum/constantinople/utils/message.v @@ -0,0 +1,212 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.constantinople.utils.message". + +Definition expr_1 : Value.t := + Constant.str " +Hardfork Utility Functions For The Message Data-structure +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Message specific functions used in this constantinople version of +specification. +". + +Axiom typing_imports_Optional : + IsImported globals "typing" "Optional". +Axiom typing_imports_Union : + IsImported globals "typing" "Union". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_Bytes : + IsImported globals "ethereum.base_types" "Bytes". +Axiom ethereum_base_types_imports_Bytes0 : + IsImported globals "ethereum.base_types" "Bytes0". +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". + +Axiom ethereum_constantinople_fork_types_imports_Address : + IsImported globals "ethereum.constantinople.fork_types" "Address". + +Axiom ethereum_constantinople_state_imports_get_account : + IsImported globals "ethereum.constantinople.state" "get_account". + +Axiom ethereum_constantinople_vm_imports_Environment : + IsImported globals "ethereum.constantinople.vm" "Environment". +Axiom ethereum_constantinople_vm_imports_Message : + IsImported globals "ethereum.constantinople.vm" "Message". + +Axiom ethereum_constantinople_utils_address_imports_compute_contract_address : + IsImported globals "ethereum.constantinople.utils.address" "compute_contract_address". + +Definition prepare_message : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "caller"; "target"; "value"; "data"; "gas"; "env"; "code_address"; "should_transfer_value"; "is_static" ] |) in + let _ := Constant.str " + Execute a transaction against the provided environment. + + Parameters + ---------- + caller : + Address which initiated the transaction + target : + Address whose code will be executed + value : + Value to be transferred. + data : + Array of bytes provided to the code in `target`. + gas : + Gas provided for the code in `target`. + env : + Environment for the Ethereum Virtual Machine. + code_address : + This is usually same as the `target` address except when an alternative + accounts code needs to be executed. + eg. `CALLCODE` calling a precompile. + should_transfer_value : + if True ETH should be transferred while executing a message call. + is_static: + if True then it prevents all state-changing operations from being + executed. + + Returns + ------- + message: `ethereum.constantinople.vm.Message` + Items containing contract creation or message call specific data. + " in + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, "isinstance" |), + make_list [ + M.get_name (| globals, "target" |); + M.get_name (| globals, "Bytes0" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "current_target" , + M.call (| + M.get_name (| globals, "compute_contract_address" |), + make_list [ + M.get_name (| globals, "caller" |); + BinOp.sub (| + M.get_field (| M.call (| + M.get_name (| globals, "get_account" |), + make_list [ + M.get_field (| M.get_name (| globals, "env" |), "state" |); + M.get_name (| globals, "caller" |) + ], + make_dict [] + |), "nonce" |), + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 1 + ], + make_dict [] + |) + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "msg_data" , + M.call (| + M.get_name (| globals, "Bytes" |), + make_list [ + Constant.bytes "" + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "code" , + M.get_name (| globals, "data" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, "isinstance" |), + make_list [ + M.get_name (| globals, "target" |); + M.get_name (| globals, "Address" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "current_target" , + M.get_name (| globals, "target" |) + |) in + let _ := M.assign_local (| + "msg_data" , + M.get_name (| globals, "data" |) + |) in + let _ := M.assign_local (| + "code" , + M.get_field (| M.call (| + M.get_name (| globals, "get_account" |), + make_list [ + M.get_field (| M.get_name (| globals, "env" |), "state" |); + M.get_name (| globals, "target" |) + ], + make_dict [] + |), "code" |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.is (| + M.get_name (| globals, "code_address" |), + Constant.None_ + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "code_address" , + M.get_name (| globals, "target" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.raise (| Some (M.call (| + M.get_name (| globals, "AssertionError" |), + make_list [ + Constant.str "Target must be address or empty bytes" + ], + make_dict [] + |)) |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )) |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, "Message" |), + make_list [], + make_dict [] + |) + |) in + M.pure Constant.None_)). diff --git a/CoqOfPython/ethereum/constantinople/vm/__init__.v b/CoqOfPython/ethereum/constantinople/vm/__init__.v new file mode 100644 index 0000000..73a0539 --- /dev/null +++ b/CoqOfPython/ethereum/constantinople/vm/__init__.v @@ -0,0 +1,242 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.constantinople.vm.__init__". + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +The abstract computer which runs the code stored in an +`.fork_types.Account`. +". + +Axiom dataclasses_imports_dataclass : + IsImported globals "dataclasses" "dataclass". + +Axiom typing_imports_List : + IsImported globals "typing" "List". +Axiom typing_imports_Optional : + IsImported globals "typing" "Optional". +Axiom typing_imports_Set : + IsImported globals "typing" "Set". +Axiom typing_imports_Tuple : + IsImported globals "typing" "Tuple". +Axiom typing_imports_Union : + IsImported globals "typing" "Union". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_Bytes : + IsImported globals "ethereum.base_types" "Bytes". +Axiom ethereum_base_types_imports_Bytes0 : + IsImported globals "ethereum.base_types" "Bytes0". +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". + +Axiom ethereum_crypto_hash_imports_Hash32 : + IsImported globals "ethereum.crypto.hash" "Hash32". + +Axiom ethereum_constantinople_blocks_imports_Log : + IsImported globals "ethereum.constantinople.blocks" "Log". + +Axiom ethereum_constantinople_fork_types_imports_Address : + IsImported globals "ethereum.constantinople.fork_types" "Address". + +Axiom ethereum_constantinople_state_imports_State : + IsImported globals "ethereum.constantinople.state" "State". +Axiom ethereum_constantinople_state_imports_account_exists_and_is_empty : + IsImported globals "ethereum.constantinople.state" "account_exists_and_is_empty". + +Axiom ethereum_constantinople_vm_precompiled_contracts_imports_RIPEMD160_ADDRESS : + IsImported globals "ethereum.constantinople.vm.precompiled_contracts" "RIPEMD160_ADDRESS". + +Definition __all__ : Value.t := M.run ltac:(M.monadic ( + make_tuple [ Constant.str "Environment"; Constant.str "Evm"; Constant.str "Message" ] +)). + +Definition Environment : Value.t := + builtins.make_klass + [] + [ + + ] + [ + + ]. + +Definition Message : Value.t := + builtins.make_klass + [] + [ + + ] + [ + + ]. + +Definition Evm : Value.t := + builtins.make_klass + [] + [ + + ] + [ + + ]. + +Definition incorporate_child_on_success : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm"; "child_evm" ] |) in + let _ := Constant.str " + Incorporate the state of a successful `child_evm` into the parent `evm`. + + Parameters + ---------- + evm : + The parent `EVM`. + child_evm : + The child evm to incorporate. + " in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "gas_left" |), + M.get_field (| M.get_name (| globals, "child_evm" |), "gas_left" |) + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "logs" |), + M.get_field (| M.get_name (| globals, "child_evm" |), "logs" |) + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "refund_counter" |), + M.get_field (| M.get_name (| globals, "child_evm" |), "refund_counter" |) + |) in + let _ := M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "accounts_to_delete" |), "update" |), + make_list [ + M.get_field (| M.get_name (| globals, "child_evm" |), "accounts_to_delete" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "touched_accounts" |), "update" |), + make_list [ + M.get_field (| M.get_name (| globals, "child_evm" |), "touched_accounts" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, "account_exists_and_is_empty" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "env" |), "state" |); + M.get_field (| M.get_field (| M.get_name (| globals, "child_evm" |), "message" |), "current_target" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "touched_accounts" |), "add" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "child_evm" |), "message" |), "current_target" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + M.pure Constant.None_)). + +Definition incorporate_child_on_error : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm"; "child_evm" ] |) in + let _ := Constant.str " + Incorporate the state of an unsuccessful `child_evm` into the parent `evm`. + + Parameters + ---------- + evm : + The parent `EVM`. + child_evm : + The child evm to incorporate. + " in + let _ := + (* if *) + M.if_then_else (| + Compare.in_ (| + M.get_name (| globals, "RIPEMD160_ADDRESS" |), + M.get_field (| M.get_name (| globals, "child_evm" |), "touched_accounts" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "touched_accounts" |), "add" |), + make_list [ + M.get_name (| globals, "RIPEMD160_ADDRESS" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_field (| M.get_field (| M.get_name (| globals, "child_evm" |), "message" |), "current_target" |), + M.get_name (| globals, "RIPEMD160_ADDRESS" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, "account_exists_and_is_empty" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "env" |), "state" |); + M.get_field (| M.get_field (| M.get_name (| globals, "child_evm" |), "message" |), "current_target" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "touched_accounts" |), "add" |), + make_list [ + M.get_name (| globals, "RIPEMD160_ADDRESS" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "gas_left" |), + M.get_field (| M.get_name (| globals, "child_evm" |), "gas_left" |) + |) in + M.pure Constant.None_)). diff --git a/CoqOfPython/ethereum/constantinople/vm/exceptions.v b/CoqOfPython/ethereum/constantinople/vm/exceptions.v new file mode 100644 index 0000000..6a2283c --- /dev/null +++ b/CoqOfPython/ethereum/constantinople/vm/exceptions.v @@ -0,0 +1,151 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.constantinople.vm.exceptions". + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) Exceptions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Exceptions which cause the EVM to halt exceptionally. +". + +Axiom ethereum_exceptions_imports_EthereumException : + IsImported globals "ethereum.exceptions" "EthereumException". + +Definition ExceptionalHalt : Value.t := + builtins.make_klass + [(globals, "EthereumException")] + [ + + ] + [ + + ]. + +Definition Revert : Value.t := + builtins.make_klass + [(globals, "EthereumException")] + [ + + ] + [ + + ]. + +Definition StackUnderflowError : Value.t := + builtins.make_klass + [(globals, "ExceptionalHalt")] + [ + + ] + [ + + ]. + +Definition StackOverflowError : Value.t := + builtins.make_klass + [(globals, "ExceptionalHalt")] + [ + + ] + [ + + ]. + +Definition OutOfGasError : Value.t := + builtins.make_klass + [(globals, "ExceptionalHalt")] + [ + + ] + [ + + ]. + +Definition InvalidOpcode : Value.t := + builtins.make_klass + [(globals, "ExceptionalHalt")] + [ + + ] + [ + ( + "__init__", + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "self"; "code" ] |) in + let _ := M.call (| + M.get_field (| M.call (| + M.get_name (| globals, "super" |), + make_list [], + make_dict [] + |), "__init__" |), + make_list [ + M.get_name (| globals, "code" |) + ], + make_dict [] + |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, "self" |), "code" |), + M.get_name (| globals, "code" |) + |) in + M.pure Constant.None_)) + ) + ]. + +Definition InvalidJumpDestError : Value.t := + builtins.make_klass + [(globals, "ExceptionalHalt")] + [ + + ] + [ + + ]. + +Definition StackDepthLimitError : Value.t := + builtins.make_klass + [(globals, "ExceptionalHalt")] + [ + + ] + [ + + ]. + +Definition WriteInStaticContext : Value.t := + builtins.make_klass + [(globals, "ExceptionalHalt")] + [ + + ] + [ + + ]. + +Definition OutOfBoundsRead : Value.t := + builtins.make_klass + [(globals, "ExceptionalHalt")] + [ + + ] + [ + + ]. + +Definition AddressCollision : Value.t := + builtins.make_klass + [(globals, "ExceptionalHalt")] + [ + + ] + [ + + ]. diff --git a/CoqOfPython/ethereum/constantinople/vm/gas.v b/CoqOfPython/ethereum/constantinople/vm/gas.v new file mode 100644 index 0000000..7a776c8 --- /dev/null +++ b/CoqOfPython/ethereum/constantinople/vm/gas.v @@ -0,0 +1,922 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.constantinople.vm.gas". + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) Gas +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +EVM gas constants and calculators. +". + +Axiom dataclasses_imports_dataclass : + IsImported globals "dataclasses" "dataclass". + +Axiom typing_imports_List : + IsImported globals "typing" "List". +Axiom typing_imports_Tuple : + IsImported globals "typing" "Tuple". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". + +Axiom ethereum_trace_imports_GasAndRefund : + IsImported globals "ethereum.trace" "GasAndRefund". +Axiom ethereum_trace_imports_evm_trace : + IsImported globals "ethereum.trace" "evm_trace". + +Axiom ethereum_utils_numeric_imports_ceil32 : + IsImported globals "ethereum.utils.numeric" "ceil32". + +Axiom ethereum_constantinople_vm_imports_Evm : + IsImported globals "ethereum.constantinople.vm" "Evm". + +Axiom ethereum_constantinople_vm_exceptions_imports_OutOfGasError : + IsImported globals "ethereum.constantinople.vm.exceptions" "OutOfGasError". + +Definition GAS_JUMPDEST : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 1 + ], + make_dict [] + |) +)). + +Definition GAS_BASE : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 2 + ], + make_dict [] + |) +)). + +Definition GAS_VERY_LOW : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 3 + ], + make_dict [] + |) +)). + +Definition GAS_SLOAD : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 200 + ], + make_dict [] + |) +)). + +Definition GAS_STORAGE_SET : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 20000 + ], + make_dict [] + |) +)). + +Definition GAS_STORAGE_UPDATE : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 5000 + ], + make_dict [] + |) +)). + +Definition GAS_STORAGE_CLEAR_REFUND : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 15000 + ], + make_dict [] + |) +)). + +Definition GAS_LOW : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 5 + ], + make_dict [] + |) +)). + +Definition GAS_MID : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 8 + ], + make_dict [] + |) +)). + +Definition GAS_HIGH : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 10 + ], + make_dict [] + |) +)). + +Definition GAS_EXPONENTIATION : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 10 + ], + make_dict [] + |) +)). + +Definition GAS_EXPONENTIATION_PER_BYTE : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 50 + ], + make_dict [] + |) +)). + +Definition GAS_MEMORY : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 3 + ], + make_dict [] + |) +)). + +Definition GAS_KECCAK256 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 30 + ], + make_dict [] + |) +)). + +Definition GAS_KECCAK256_WORD : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 6 + ], + make_dict [] + |) +)). + +Definition GAS_COPY : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 3 + ], + make_dict [] + |) +)). + +Definition GAS_BLOCK_HASH : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 20 + ], + make_dict [] + |) +)). + +Definition GAS_EXTERNAL : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 700 + ], + make_dict [] + |) +)). + +Definition GAS_BALANCE : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 400 + ], + make_dict [] + |) +)). + +Definition GAS_LOG : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 375 + ], + make_dict [] + |) +)). + +Definition GAS_LOG_DATA : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 8 + ], + make_dict [] + |) +)). + +Definition GAS_LOG_TOPIC : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 375 + ], + make_dict [] + |) +)). + +Definition GAS_CREATE : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 32000 + ], + make_dict [] + |) +)). + +Definition GAS_CODE_DEPOSIT : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 200 + ], + make_dict [] + |) +)). + +Definition GAS_ZERO : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) +)). + +Definition GAS_CALL : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 700 + ], + make_dict [] + |) +)). + +Definition GAS_NEW_ACCOUNT : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 25000 + ], + make_dict [] + |) +)). + +Definition GAS_CALL_VALUE : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 9000 + ], + make_dict [] + |) +)). + +Definition GAS_CALL_STIPEND : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 2300 + ], + make_dict [] + |) +)). + +Definition GAS_SELF_DESTRUCT : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 5000 + ], + make_dict [] + |) +)). + +Definition GAS_SELF_DESTRUCT_NEW_ACCOUNT : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 25000 + ], + make_dict [] + |) +)). + +Definition REFUND_SELF_DESTRUCT : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 24000 + ], + make_dict [] + |) +)). + +Definition GAS_ECRECOVER : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 3000 + ], + make_dict [] + |) +)). + +Definition GAS_SHA256 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 60 + ], + make_dict [] + |) +)). + +Definition GAS_SHA256_WORD : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 12 + ], + make_dict [] + |) +)). + +Definition GAS_RIPEMD160 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 600 + ], + make_dict [] + |) +)). + +Definition GAS_RIPEMD160_WORD : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 120 + ], + make_dict [] + |) +)). + +Definition GAS_IDENTITY : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 15 + ], + make_dict [] + |) +)). + +Definition GAS_IDENTITY_WORD : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 3 + ], + make_dict [] + |) +)). + +Definition GAS_RETURN_DATA_COPY : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 3 + ], + make_dict [] + |) +)). + +Definition GAS_CODE_HASH : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 400 + ], + make_dict [] + |) +)). + +Definition ExtendMemory : Value.t := + builtins.make_klass + [] + [ + + ] + [ + + ]. + +Definition MessageCallGas : Value.t := + builtins.make_klass + [] + [ + + ] + [ + + ]. + +Definition charge_gas : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm"; "amount" ] |) in + let _ := Constant.str " + Subtracts `amount` from `evm.gas_left`. + + Parameters + ---------- + evm : + The current EVM. + amount : + The amount of gas the current operation requires. + + " in + let _ := M.call (| + M.get_name (| globals, "evm_trace" |), + make_list [ + M.get_name (| globals, "evm" |); + M.call (| + M.get_name (| globals, "GasAndRefund" |), + make_list [ + M.get_name (| globals, "amount" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.lt (| + M.get_field (| M.get_name (| globals, "evm" |), "gas_left" |), + M.get_name (| globals, "amount" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, "OutOfGasError" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_op (| + BinOp.sub, + M.get_field (| M.get_name (| globals, "evm" |), "gas_left" |), + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + M.get_name (| globals, "amount" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_)). + +Definition calculate_memory_gas_cost : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "size_in_bytes" ] |) in + let _ := Constant.str " + Calculates the gas cost for allocating memory + to the smallest multiple of 32 bytes, + such that the allocated size is at least as big as the given size. + + Parameters + ---------- + size_in_bytes : + The size of the data in bytes. + + Returns + ------- + total_gas_cost : `ethereum.base_types.Uint` + The gas cost for storing data in memory. + " in + let _ := M.assign_local (| + "size_in_words" , + BinOp.floor_div (| + M.call (| + M.get_name (| globals, "ceil32" |), + make_list [ + M.get_name (| globals, "size_in_bytes" |) + ], + make_dict [] + |), + Constant.int 32 + |) + |) in + let _ := M.assign_local (| + "linear_cost" , + BinOp.mult (| + M.get_name (| globals, "size_in_words" |), + M.get_name (| globals, "GAS_MEMORY" |) + |) + |) in + let _ := M.assign_local (| + "quadratic_cost" , + BinOp.floor_div (| + BinOp.pow (| + M.get_name (| globals, "size_in_words" |), + Constant.int 2 + |), + Constant.int 512 + |) + |) in + let _ := M.assign_local (| + "total_gas_cost" , + BinOp.add (| + M.get_name (| globals, "linear_cost" |), + M.get_name (| globals, "quadratic_cost" |) + |) + |) in +(* At stmt: unsupported node type: Try *) + M.pure Constant.None_)). + +Definition calculate_gas_extend_memory : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "memory"; "extensions" ] |) in + let _ := Constant.str " + Calculates the gas amount to extend memory + + Parameters + ---------- + memory : + Memory contents of the EVM. + extensions: + List of extensions to be made to the memory. + Consists of a tuple of start position and size. + + Returns + ------- + extend_memory: `ExtendMemory` + " in + let _ := M.assign_local (| + "size_to_extend" , + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "to_be_paid" , + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "current_size" , + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_name (| globals, "memory" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := + M.for_ (| + make_tuple [ M.get_name (| globals, "start_position" |); M.get_name (| globals, "size" |) ], + M.get_name (| globals, "extensions" |), + ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, "size" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.continue (| |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "before_size" , + M.call (| + M.get_name (| globals, "ceil32" |), + make_list [ + M.get_name (| globals, "current_size" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "after_size" , + M.call (| + M.get_name (| globals, "ceil32" |), + make_list [ + BinOp.add (| + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.get_name (| globals, "start_position" |) + ], + make_dict [] + |), + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.get_name (| globals, "size" |) + ], + make_dict [] + |) + |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.lt_e (| + M.get_name (| globals, "after_size" |), + M.get_name (| globals, "before_size" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.continue (| |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_op_local (| + BinOp.add, + "size_to_extend", + BinOp.sub (| + M.get_name (| globals, "after_size" |), + M.get_name (| globals, "before_size" |) + |) + |) in + let _ := M.assign_local (| + "already_paid" , + M.call (| + M.get_name (| globals, "calculate_memory_gas_cost" |), + make_list [ + M.get_name (| globals, "before_size" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "total_cost" , + M.call (| + M.get_name (| globals, "calculate_memory_gas_cost" |), + make_list [ + M.get_name (| globals, "after_size" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_op_local (| + BinOp.add, + "to_be_paid", + BinOp.sub (| + M.get_name (| globals, "total_cost" |), + M.get_name (| globals, "already_paid" |) + |) + |) in + let _ := M.assign_local (| + "current_size" , + M.get_name (| globals, "after_size" |) + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, "ExtendMemory" |), + make_list [ + M.get_name (| globals, "to_be_paid" |); + M.get_name (| globals, "size_to_extend" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Definition calculate_message_call_gas : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "value"; "gas"; "gas_left"; "memory_cost"; "extra_gas"; "call_stipend" ] |) in + let _ := Constant.str " + Calculates the MessageCallGas (cost and stipend) for + executing call Opcodes. + + Parameters + ---------- + value: + The amount of `ETH` that needs to be transferred. + gas : + The amount of gas provided to the message-call. + gas_left : + The amount of gas left in the current frame. + memory_cost : + The amount needed to extend the memory in the current frame. + extra_gas : + The amount of gas needed for transferring value + creating a new + account inside a message call. + call_stipend : + The amount of stipend provided to a message call to execute code while + transferring value(ETH). + + Returns + ------- + message_call_gas: `MessageCallGas` + " in + let _ := M.assign_local (| + "call_stipend" , + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, "value" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( +M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + (* else *) + )), ltac:(M.monadic ( +M.get_name (| globals, "call_stipend" |) + )) |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.lt (| + M.get_name (| globals, "gas_left" |), + BinOp.add (| + M.get_name (| globals, "extra_gas" |), + M.get_name (| globals, "memory_cost" |) + |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + M.call (| + M.get_name (| globals, "MessageCallGas" |), + make_list [ + BinOp.add (| + M.get_name (| globals, "gas" |), + M.get_name (| globals, "extra_gas" |) + |); + BinOp.add (| + M.get_name (| globals, "gas" |), + M.get_name (| globals, "call_stipend" |) + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "gas" , + M.call (| + M.get_name (| globals, "min" |), + make_list [ + M.get_name (| globals, "gas" |); + M.call (| + M.get_name (| globals, "max_message_call_gas" |), + make_list [ + BinOp.sub (| + BinOp.sub (| + M.get_name (| globals, "gas_left" |), + M.get_name (| globals, "memory_cost" |) + |), + M.get_name (| globals, "extra_gas" |) + |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, "MessageCallGas" |), + make_list [ + BinOp.add (| + M.get_name (| globals, "gas" |), + M.get_name (| globals, "extra_gas" |) + |); + BinOp.add (| + M.get_name (| globals, "gas" |), + M.get_name (| globals, "call_stipend" |) + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Definition max_message_call_gas : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "gas" ] |) in + let _ := Constant.str " + Calculates the maximum gas that is allowed for making a message call + + Parameters + ---------- + gas : + The amount of gas provided to the message-call. + + Returns + ------- + max_allowed_message_call_gas: `ethereum.base_types.Uint` + The maximum gas allowed for making the message-call. + " in + let _ := M.return_ (| + BinOp.sub (| + M.get_name (| globals, "gas" |), + BinOp.floor_div (| + M.get_name (| globals, "gas" |), + Constant.int 64 + |) + |) + |) in + M.pure Constant.None_)). diff --git a/CoqOfPython/ethereum/constantinople/vm/instructions/__init__.v b/CoqOfPython/ethereum/constantinople/vm/instructions/__init__.v new file mode 100644 index 0000000..b8c6731 --- /dev/null +++ b/CoqOfPython/ethereum/constantinople/vm/instructions/__init__.v @@ -0,0 +1,74 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.constantinople.vm.instructions.__init__". + +Definition expr_1 : Value.t := + Constant.str " +EVM Instruction Encoding (Opcodes) +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Machine readable representations of EVM instructions, and a mapping to their +implementations. +". + +(* At top_level_stmt: unsupported node type: Import *) + +Axiom typing_imports_Callable : + IsImported globals "typing" "Callable". +Axiom typing_imports_Dict : + IsImported globals "typing" "Dict". + +Axiom ethereum_constantinople_vm_instructions_imports_arithmetic : + IsImported globals "ethereum.constantinople.vm.instructions" "arithmetic". + +Axiom ethereum_constantinople_vm_instructions_imports_bitwise : + IsImported globals "ethereum.constantinople.vm.instructions" "bitwise". + +Axiom ethereum_constantinople_vm_instructions_imports_block : + IsImported globals "ethereum.constantinople.vm.instructions" "block". + +Axiom ethereum_constantinople_vm_instructions_imports_comparison : + IsImported globals "ethereum.constantinople.vm.instructions" "comparison". + +Axiom ethereum_constantinople_vm_instructions_imports_control_flow : + IsImported globals "ethereum.constantinople.vm.instructions" "control_flow". + +Axiom ethereum_constantinople_vm_instructions_imports_environment : + IsImported globals "ethereum.constantinople.vm.instructions" "environment". + +Axiom ethereum_constantinople_vm_instructions_imports_keccak : + IsImported globals "ethereum.constantinople.vm.instructions" "keccak". + +Axiom ethereum_constantinople_vm_instructions_imports_log : + IsImported globals "ethereum.constantinople.vm.instructions" "log". + +Axiom ethereum_constantinople_vm_instructions_imports_memory : + IsImported globals "ethereum.constantinople.vm.instructions" "memory". + +Axiom ethereum_constantinople_vm_instructions_imports_stack : + IsImported globals "ethereum.constantinople.vm.instructions" "stack". + +Axiom ethereum_constantinople_vm_instructions_imports_storage : + IsImported globals "ethereum.constantinople.vm.instructions" "storage". + +Axiom ethereum_constantinople_vm_instructions_imports_system : + IsImported globals "ethereum.constantinople.vm.instructions" "system". + +Definition Ops : Value.t := + builtins.make_klass + [(* At base: unsupported node type: Attribute *)] + [ + + ] + [ + + ]. + +(* At top_level_stmt: unsupported node type: AnnAssign *) diff --git a/CoqOfPython/ethereum/constantinople/vm/instructions/arithmetic.v b/CoqOfPython/ethereum/constantinople/vm/instructions/arithmetic.v new file mode 100644 index 0000000..3e3a445 --- /dev/null +++ b/CoqOfPython/ethereum/constantinople/vm/instructions/arithmetic.v @@ -0,0 +1,1220 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.constantinople.vm.instructions.arithmetic". + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) Arithmetic Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM Arithmetic instructions. +". + +Axiom ethereum_base_types_imports_U255_CEIL_VALUE : + IsImported globals "ethereum.base_types" "U255_CEIL_VALUE". +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_U256_CEIL_VALUE : + IsImported globals "ethereum.base_types" "U256_CEIL_VALUE". +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". + +Axiom ethereum_utils_numeric_imports_get_sign : + IsImported globals "ethereum.utils.numeric" "get_sign". + +Axiom ethereum_constantinople_vm_imports_Evm : + IsImported globals "ethereum.constantinople.vm" "Evm". + +Axiom ethereum_constantinople_vm_gas_imports_GAS_EXPONENTIATION : + IsImported globals "ethereum.constantinople.vm.gas" "GAS_EXPONENTIATION". +Axiom ethereum_constantinople_vm_gas_imports_GAS_EXPONENTIATION_PER_BYTE : + IsImported globals "ethereum.constantinople.vm.gas" "GAS_EXPONENTIATION_PER_BYTE". +Axiom ethereum_constantinople_vm_gas_imports_GAS_LOW : + IsImported globals "ethereum.constantinople.vm.gas" "GAS_LOW". +Axiom ethereum_constantinople_vm_gas_imports_GAS_MID : + IsImported globals "ethereum.constantinople.vm.gas" "GAS_MID". +Axiom ethereum_constantinople_vm_gas_imports_GAS_VERY_LOW : + IsImported globals "ethereum.constantinople.vm.gas" "GAS_VERY_LOW". +Axiom ethereum_constantinople_vm_gas_imports_charge_gas : + IsImported globals "ethereum.constantinople.vm.gas" "charge_gas". + +Axiom ethereum_constantinople_vm_stack_imports_pop : + IsImported globals "ethereum.constantinople.vm.stack" "pop". +Axiom ethereum_constantinople_vm_stack_imports_push : + IsImported globals "ethereum.constantinople.vm.stack" "push". + +Definition add : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Adds the top two elements of the stack together, and pushes the result back + on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "x" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "y" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_VERY_LOW" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "result" , + M.call (| + M.get_field (| M.get_name (| globals, "x" |), "wrapping_add" |), + make_list [ + M.get_name (| globals, "y" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.get_name (| globals, "result" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition sub : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Subtracts the top two elements of the stack, and pushes the result back + on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "x" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "y" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_VERY_LOW" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "result" , + M.call (| + M.get_field (| M.get_name (| globals, "x" |), "wrapping_sub" |), + make_list [ + M.get_name (| globals, "y" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.get_name (| globals, "result" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition mul : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Multiply the top two elements of the stack, and pushes the result back + on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "x" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "y" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_LOW" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "result" , + M.call (| + M.get_field (| M.get_name (| globals, "x" |), "wrapping_mul" |), + make_list [ + M.get_name (| globals, "y" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.get_name (| globals, "result" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition div : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Integer division of the top two elements of the stack. Pushes the result + back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "dividend" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "divisor" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_LOW" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, "divisor" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "quotient" , + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "quotient" , + BinOp.floor_div (| + M.get_name (| globals, "dividend" |), + M.get_name (| globals, "divisor" |) + |) + |) in + M.pure Constant.None_ + )) |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.get_name (| globals, "quotient" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition sdiv : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Signed integer division of the top two elements of the stack. Pushes the + result back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "dividend" , + M.call (| + M.get_field (| M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |), "to_signed" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "divisor" , + M.call (| + M.get_field (| M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |), "to_signed" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_LOW" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, "divisor" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "quotient" , + Constant.int 0 + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + BoolOp.and (| + Compare.eq (| + M.get_name (| globals, "dividend" |), + UnOp.sub (| M.get_name (| globals, "U255_CEIL_VALUE" |) |) + |), + ltac:(M.monadic ( + Compare.eq (| + M.get_name (| globals, "divisor" |), + UnOp.sub (| Constant.int 1 |) + |) + )) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "quotient" , + UnOp.sub (| M.get_name (| globals, "U255_CEIL_VALUE" |) |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "sign" , + M.call (| + M.get_name (| globals, "get_sign" |), + make_list [ + BinOp.mult (| + M.get_name (| globals, "dividend" |), + M.get_name (| globals, "divisor" |) + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "quotient" , + BinOp.mult (| + M.get_name (| globals, "sign" |), + BinOp.floor_div (| + M.call (| + M.get_name (| globals, "abs" |), + make_list [ + M.get_name (| globals, "dividend" |) + ], + make_dict [] + |), + M.call (| + M.get_name (| globals, "abs" |), + make_list [ + M.get_name (| globals, "divisor" |) + ], + make_dict [] + |) + |) + |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )) |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.call (| + M.get_field (| M.get_name (| globals, "U256" |), "from_signed" |), + make_list [ + M.get_name (| globals, "quotient" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition mod_ : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Modulo remainder of the top two elements of the stack. Pushes the result + back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "x" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "y" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_LOW" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, "y" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "remainder" , + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "remainder" , + BinOp.mod_ (| + M.get_name (| globals, "x" |), + M.get_name (| globals, "y" |) + |) + |) in + M.pure Constant.None_ + )) |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.get_name (| globals, "remainder" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition smod : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Signed modulo remainder of the top two elements of the stack. Pushes the + result back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "x" , + M.call (| + M.get_field (| M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |), "to_signed" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "y" , + M.call (| + M.get_field (| M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |), "to_signed" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_LOW" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, "y" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "remainder" , + Constant.int 0 + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "remainder" , + BinOp.mult (| + M.call (| + M.get_name (| globals, "get_sign" |), + make_list [ + M.get_name (| globals, "x" |) + ], + make_dict [] + |), + BinOp.mod_ (| + M.call (| + M.get_name (| globals, "abs" |), + make_list [ + M.get_name (| globals, "x" |) + ], + make_dict [] + |), + M.call (| + M.get_name (| globals, "abs" |), + make_list [ + M.get_name (| globals, "y" |) + ], + make_dict [] + |) + |) + |) + |) in + M.pure Constant.None_ + )) |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.call (| + M.get_field (| M.get_name (| globals, "U256" |), "from_signed" |), + make_list [ + M.get_name (| globals, "remainder" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition addmod : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Modulo addition of the top 2 elements with the 3rd element. Pushes the + result back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "x" , + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "y" , + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "z" , + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_MID" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, "z" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "result" , + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "result" , + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + BinOp.mod_ (| + BinOp.add (| + M.get_name (| globals, "x" |), + M.get_name (| globals, "y" |) + |), + M.get_name (| globals, "z" |) + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + )) |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.get_name (| globals, "result" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition mulmod : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Modulo multiplication of the top 2 elements with the 3rd element. Pushes + the result back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "x" , + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "y" , + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "z" , + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_MID" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, "z" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "result" , + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "result" , + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + BinOp.mod_ (| + BinOp.mult (| + M.get_name (| globals, "x" |), + M.get_name (| globals, "y" |) + |), + M.get_name (| globals, "z" |) + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + )) |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.get_name (| globals, "result" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition exp : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Exponential operation of the top 2 elements. Pushes the result back on + the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "base" , + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "exponent" , + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "exponent_bits" , + M.call (| + M.get_field (| M.get_name (| globals, "exponent" |), "bit_length" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "exponent_bytes" , + BinOp.floor_div (| + BinOp.add (| + M.get_name (| globals, "exponent_bits" |), + Constant.int 7 + |), + Constant.int 8 + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + BinOp.add (| + M.get_name (| globals, "GAS_EXPONENTIATION" |), + BinOp.mult (| + M.get_name (| globals, "GAS_EXPONENTIATION_PER_BYTE" |), + M.get_name (| globals, "exponent_bytes" |) + |) + |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "result" , + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + M.call (| + M.get_name (| globals, "pow" |), + make_list [ + M.get_name (| globals, "base" |); + M.get_name (| globals, "exponent" |); + M.get_name (| globals, "U256_CEIL_VALUE" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.get_name (| globals, "result" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition signextend : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Sign extend operation. In other words, extend a signed number which + fits in N bytes to 32 bytes. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "byte_num" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "value" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_LOW" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.gt (| + M.get_name (| globals, "byte_num" |), + Constant.int 31 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "result" , + M.get_name (| globals, "value" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "value_bytes" , + M.call (| + M.get_name (| globals, "bytes" |), + make_list [ + M.call (| + M.get_field (| M.get_name (| globals, "value" |), "to_be_bytes32" |), + make_list [], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "value_bytes" , + M.slice (| + M.get_name (| globals, "value_bytes" |), + BinOp.sub (| + Constant.int 31, + M.call (| + M.get_name (| globals, "int" |), + make_list [ + M.get_name (| globals, "byte_num" |) + ], + make_dict [] + |) + |), + Constant.None_, + Constant.None_ + |) + |) in + let _ := M.assign_local (| + "sign_bit" , + BinOp.r_shift (| + M.get_subscript (| + M.get_name (| globals, "value_bytes" |), + Constant.int 0 + |), + Constant.int 7 + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, "sign_bit" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "result" , + M.call (| + M.get_field (| M.get_name (| globals, "U256" |), "from_be_bytes" |), + make_list [ + M.get_name (| globals, "value_bytes" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "num_bytes_prepend" , + BinOp.sub (| + Constant.int 32, + BinOp.add (| + M.get_name (| globals, "byte_num" |), + Constant.int 1 + |) + |) + |) in + let _ := M.assign_local (| + "result" , + M.call (| + M.get_field (| M.get_name (| globals, "U256" |), "from_be_bytes" |), + make_list [ + BinOp.add (| + M.call (| + M.get_name (| globals, "bytearray" |), + make_list [ + BinOp.mult (| + make_list [ + Constant.int 255 + ], + M.get_name (| globals, "num_bytes_prepend" |) + |) + ], + make_dict [] + |), + M.get_name (| globals, "value_bytes" |) + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )) |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.get_name (| globals, "result" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). diff --git a/CoqOfPython/ethereum/constantinople/vm/instructions/bitwise.v b/CoqOfPython/ethereum/constantinople/vm/instructions/bitwise.v new file mode 100644 index 0000000..76a9113 --- /dev/null +++ b/CoqOfPython/ethereum/constantinople/vm/instructions/bitwise.v @@ -0,0 +1,666 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.constantinople.vm.instructions.bitwise". + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) Bitwise Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM bitwise instructions. +". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_U256_CEIL_VALUE : + IsImported globals "ethereum.base_types" "U256_CEIL_VALUE". + +Axiom ethereum_constantinople_vm_imports_Evm : + IsImported globals "ethereum.constantinople.vm" "Evm". + +Axiom ethereum_constantinople_vm_gas_imports_GAS_VERY_LOW : + IsImported globals "ethereum.constantinople.vm.gas" "GAS_VERY_LOW". +Axiom ethereum_constantinople_vm_gas_imports_charge_gas : + IsImported globals "ethereum.constantinople.vm.gas" "charge_gas". + +Axiom ethereum_constantinople_vm_stack_imports_pop : + IsImported globals "ethereum.constantinople.vm.stack" "pop". +Axiom ethereum_constantinople_vm_stack_imports_push : + IsImported globals "ethereum.constantinople.vm.stack" "push". + +Definition bitwise_and : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Bitwise AND operation of the top 2 elements of the stack. Pushes the + result back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "x" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "y" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_VERY_LOW" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + BinOp.bit_and (| + M.get_name (| globals, "x" |), + M.get_name (| globals, "y" |) + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition bitwise_or : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Bitwise OR operation of the top 2 elements of the stack. Pushes the + result back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "x" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "y" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_VERY_LOW" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + BinOp.bit_or (| + M.get_name (| globals, "x" |), + M.get_name (| globals, "y" |) + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition bitwise_xor : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Bitwise XOR operation of the top 2 elements of the stack. Pushes the + result back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "x" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "y" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_VERY_LOW" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + BinOp.bit_xor (| + M.get_name (| globals, "x" |), + M.get_name (| globals, "y" |) + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition bitwise_not : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Bitwise NOT operation of the top element of the stack. Pushes the + result back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "x" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_VERY_LOW" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + UnOp.invert (| M.get_name (| globals, "x" |) |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition get_byte : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + For a word (defined by next top element of the stack), retrieve the + Nth byte (0-indexed and defined by top element of stack) from the + left (most significant) to right (least significant). + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "byte_index" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "word" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_VERY_LOW" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.gt_e (| + M.get_name (| globals, "byte_index" |), + Constant.int 32 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "result" , + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "extra_bytes_to_right" , + BinOp.sub (| + Constant.int 31, + M.get_name (| globals, "byte_index" |) + |) + |) in + let _ := M.assign_local (| + "word" , + BinOp.r_shift (| + M.get_name (| globals, "word" |), + BinOp.mult (| + M.get_name (| globals, "extra_bytes_to_right" |), + Constant.int 8 + |) + |) + |) in + let _ := M.assign_local (| + "word" , + BinOp.bit_and (| + M.get_name (| globals, "word" |), + Constant.int 255 + |) + |) in + let _ := M.assign_local (| + "result" , + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + M.get_name (| globals, "word" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + )) |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.get_name (| globals, "result" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition bitwise_shl : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Logical shift left (SHL) operation of the top 2 elements of the stack. + Pushes the result back on the stack. + Parameters + ---------- + evm : + The current EVM frame. + " in + let _ := M.assign_local (| + "shift" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "value" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_VERY_LOW" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.lt (| + M.get_name (| globals, "shift" |), + Constant.int 256 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "result" , + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + BinOp.mod_ (| + BinOp.l_shift (| + M.get_name (| globals, "value" |), + M.get_name (| globals, "shift" |) + |), + M.get_name (| globals, "U256_CEIL_VALUE" |) + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "result" , + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + )) |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.get_name (| globals, "result" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition bitwise_shr : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Logical shift right (SHR) operation of the top 2 elements of the stack. + Pushes the result back on the stack. + Parameters + ---------- + evm : + The current EVM frame. + " in + let _ := M.assign_local (| + "shift" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "value" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_VERY_LOW" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.lt (| + M.get_name (| globals, "shift" |), + Constant.int 256 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "result" , + BinOp.r_shift (| + M.get_name (| globals, "value" |), + M.get_name (| globals, "shift" |) + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "result" , + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + )) |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.get_name (| globals, "result" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition bitwise_sar : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Arithmetic shift right (SAR) operation of the top 2 elements of the stack. + Pushes the result back on the stack. + Parameters + ---------- + evm : + The current EVM frame. + " in + let _ := M.assign_local (| + "shift" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "signed_value" , + M.call (| + M.get_field (| M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |), "to_signed" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_VERY_LOW" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.lt (| + M.get_name (| globals, "shift" |), + Constant.int 256 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "result" , + M.call (| + M.get_field (| M.get_name (| globals, "U256" |), "from_signed" |), + make_list [ + BinOp.r_shift (| + M.get_name (| globals, "signed_value" |), + M.get_name (| globals, "shift" |) + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + Compare.gt_e (| + M.get_name (| globals, "signed_value" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "result" , + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "result" , + M.get_field (| M.get_name (| globals, "U256" |), "MAX_VALUE" |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )) |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.get_name (| globals, "result" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). diff --git a/CoqOfPython/ethereum/constantinople/vm/instructions/block.v b/CoqOfPython/ethereum/constantinople/vm/instructions/block.v new file mode 100644 index 0000000..5481330 --- /dev/null +++ b/CoqOfPython/ethereum/constantinople/vm/instructions/block.v @@ -0,0 +1,348 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.constantinople.vm.instructions.block". + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) Block Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM block instructions. +". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". + +Axiom ethereum_constantinople_vm_imports_Evm : + IsImported globals "ethereum.constantinople.vm" "Evm". + +Axiom ethereum_constantinople_vm_gas_imports_GAS_BASE : + IsImported globals "ethereum.constantinople.vm.gas" "GAS_BASE". +Axiom ethereum_constantinople_vm_gas_imports_GAS_BLOCK_HASH : + IsImported globals "ethereum.constantinople.vm.gas" "GAS_BLOCK_HASH". +Axiom ethereum_constantinople_vm_gas_imports_charge_gas : + IsImported globals "ethereum.constantinople.vm.gas" "charge_gas". + +Axiom ethereum_constantinople_vm_stack_imports_pop : + IsImported globals "ethereum.constantinople.vm.stack" "pop". +Axiom ethereum_constantinople_vm_stack_imports_push : + IsImported globals "ethereum.constantinople.vm.stack" "push". + +Definition block_hash : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Push the hash of one of the 256 most recent complete blocks onto the + stack. The block number to hash is present at the top of the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "block_number" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_BLOCK_HASH" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + BoolOp.or (| + Compare.lt_e (| + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "env" |), "number" |), + M.get_name (| globals, "block_number" |) + |), + ltac:(M.monadic ( + Compare.gt (| + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "env" |), "number" |), + BinOp.add (| + M.get_name (| globals, "block_number" |), + Constant.int 256 + |) + |) + )) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "hash" , + Constant.bytes "00" + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "hash" , + M.get_subscript (| + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "env" |), "block_hashes" |), + UnOp.sub (| BinOp.sub (| + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "env" |), "number" |), + M.get_name (| globals, "block_number" |) + |) |) + |) + |) in + M.pure Constant.None_ + )) |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.call (| + M.get_field (| M.get_name (| globals, "U256" |), "from_be_bytes" |), + make_list [ + M.get_name (| globals, "hash" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition coinbase : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Push the current block's beneficiary address (address of the block miner) + onto the stack. + + Here the current block refers to the block in which the currently + executing transaction/call resides. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_BASE" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.call (| + M.get_field (| M.get_name (| globals, "U256" |), "from_be_bytes" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "env" |), "coinbase" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition timestamp : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Push the current block's timestamp onto the stack. Here the timestamp + being referred is actually the unix timestamp in seconds. + + Here the current block refers to the block in which the currently + executing transaction/call resides. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_BASE" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "env" |), "time" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition number : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Push the current block's number onto the stack. + + Here the current block refers to the block in which the currently + executing transaction/call resides. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_BASE" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "env" |), "number" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition difficulty : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Push the current block's difficulty onto the stack. + + Here the current block refers to the block in which the currently + executing transaction/call resides. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_BASE" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "env" |), "difficulty" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition gas_limit : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Push the current block's gas limit onto the stack. + + Here the current block refers to the block in which the currently + executing transaction/call resides. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_BASE" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "env" |), "gas_limit" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). diff --git a/CoqOfPython/ethereum/constantinople/vm/instructions/comparison.v b/CoqOfPython/ethereum/constantinople/vm/instructions/comparison.v new file mode 100644 index 0000000..50cbb7f --- /dev/null +++ b/CoqOfPython/ethereum/constantinople/vm/instructions/comparison.v @@ -0,0 +1,452 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.constantinople.vm.instructions.comparison". + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) Comparison Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM Comparison instructions. +". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". + +Axiom ethereum_constantinople_vm_imports_Evm : + IsImported globals "ethereum.constantinople.vm" "Evm". + +Axiom ethereum_constantinople_vm_gas_imports_GAS_VERY_LOW : + IsImported globals "ethereum.constantinople.vm.gas" "GAS_VERY_LOW". +Axiom ethereum_constantinople_vm_gas_imports_charge_gas : + IsImported globals "ethereum.constantinople.vm.gas" "charge_gas". + +Axiom ethereum_constantinople_vm_stack_imports_pop : + IsImported globals "ethereum.constantinople.vm.stack" "pop". +Axiom ethereum_constantinople_vm_stack_imports_push : + IsImported globals "ethereum.constantinople.vm.stack" "push". + +Definition less_than : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Checks if the top element is less than the next top element. Pushes the + result back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "left" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "right" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_VERY_LOW" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "result" , + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Compare.lt (| + M.get_name (| globals, "left" |), + M.get_name (| globals, "right" |) + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.get_name (| globals, "result" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition signed_less_than : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Signed less-than comparison. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "left" , + M.call (| + M.get_field (| M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |), "to_signed" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "right" , + M.call (| + M.get_field (| M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |), "to_signed" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_VERY_LOW" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "result" , + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Compare.lt (| + M.get_name (| globals, "left" |), + M.get_name (| globals, "right" |) + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.get_name (| globals, "result" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition greater_than : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Checks if the top element is greater than the next top element. Pushes + the result back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "left" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "right" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_VERY_LOW" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "result" , + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Compare.gt (| + M.get_name (| globals, "left" |), + M.get_name (| globals, "right" |) + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.get_name (| globals, "result" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition signed_greater_than : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Signed greater-than comparison. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "left" , + M.call (| + M.get_field (| M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |), "to_signed" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "right" , + M.call (| + M.get_field (| M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |), "to_signed" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_VERY_LOW" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "result" , + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Compare.gt (| + M.get_name (| globals, "left" |), + M.get_name (| globals, "right" |) + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.get_name (| globals, "result" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition equal : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Checks if the top element is equal to the next top element. Pushes + the result back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "left" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "right" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_VERY_LOW" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "result" , + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Compare.eq (| + M.get_name (| globals, "left" |), + M.get_name (| globals, "right" |) + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.get_name (| globals, "result" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition is_zero : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Checks if the top element is equal to 0. Pushes the result back on the + stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "x" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_VERY_LOW" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "result" , + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Compare.eq (| + M.get_name (| globals, "x" |), + Constant.int 0 + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.get_name (| globals, "result" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). diff --git a/CoqOfPython/ethereum/constantinople/vm/instructions/control_flow.v b/CoqOfPython/ethereum/constantinople/vm/instructions/control_flow.v new file mode 100644 index 0000000..4b37436 --- /dev/null +++ b/CoqOfPython/ethereum/constantinople/vm/instructions/control_flow.v @@ -0,0 +1,350 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.constantinople.vm.instructions.control_flow". + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) Control Flow Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM control flow instructions. +". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". + +Axiom ethereum_constantinople_vm_gas_imports_GAS_BASE : + IsImported globals "ethereum.constantinople.vm.gas" "GAS_BASE". +Axiom ethereum_constantinople_vm_gas_imports_GAS_HIGH : + IsImported globals "ethereum.constantinople.vm.gas" "GAS_HIGH". +Axiom ethereum_constantinople_vm_gas_imports_GAS_JUMPDEST : + IsImported globals "ethereum.constantinople.vm.gas" "GAS_JUMPDEST". +Axiom ethereum_constantinople_vm_gas_imports_GAS_MID : + IsImported globals "ethereum.constantinople.vm.gas" "GAS_MID". +Axiom ethereum_constantinople_vm_gas_imports_charge_gas : + IsImported globals "ethereum.constantinople.vm.gas" "charge_gas". + +Axiom ethereum_constantinople_vm_imports_Evm : + IsImported globals "ethereum.constantinople.vm" "Evm". + +Axiom ethereum_constantinople_vm_exceptions_imports_InvalidJumpDestError : + IsImported globals "ethereum.constantinople.vm.exceptions" "InvalidJumpDestError". + +Axiom ethereum_constantinople_vm_stack_imports_pop : + IsImported globals "ethereum.constantinople.vm.stack" "pop". +Axiom ethereum_constantinople_vm_stack_imports_push : + IsImported globals "ethereum.constantinople.vm.stack" "push". + +Definition stop : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Stop further execution of EVM code. + + Parameters + ---------- + evm : + The current EVM frame. + " in + let _ := M.pass (| |) in + let _ := M.pass (| |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, "evm" |), "running" |), + Constant.bool false + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition jump : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Alter the program counter to the location specified by the top of the + stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "jump_dest" , + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_MID" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.not_in (| + M.get_name (| globals, "jump_dest" |), + M.get_field (| M.get_name (| globals, "evm" |), "valid_jump_destinations" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, "InvalidJumpDestError" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.get_name (| globals, "jump_dest" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Definition jumpi : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Alter the program counter to the specified location if and only if a + condition is true. If the condition is not true, then the program counter + would increase only by 1. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "jump_dest" , + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "conditional_value" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_HIGH" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, "conditional_value" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "destination" , + BinOp.add (| + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + Compare.not_in (| + M.get_name (| globals, "jump_dest" |), + M.get_field (| M.get_name (| globals, "evm" |), "valid_jump_destinations" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, "InvalidJumpDestError" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "destination" , + M.get_name (| globals, "jump_dest" |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )) |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.get_name (| globals, "destination" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Definition pc : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Push onto the stack the value of the program counter after reaching the + current instruction and without increasing it for the next instruction. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_BASE" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "pc" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition gas_left : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Push the amount of available gas (including the corresponding reduction + for the cost of this instruction) onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_BASE" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "gas_left" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition jumpdest : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Mark a valid destination for jumps. This is a noop, present only + to be used by `JUMP` and `JUMPI` opcodes to verify that their jump is + valid. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_JUMPDEST" |) + ], + make_dict [] + |) in + let _ := M.pass (| |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). diff --git a/CoqOfPython/ethereum/constantinople/vm/instructions/environment.v b/CoqOfPython/ethereum/constantinople/vm/instructions/environment.v new file mode 100644 index 0000000..e6edba3 --- /dev/null +++ b/CoqOfPython/ethereum/constantinople/vm/instructions/environment.v @@ -0,0 +1,1318 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.constantinople.vm.instructions.environment". + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) Environmental Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM environment related instructions. +". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". + +Axiom ethereum_crypto_hash_imports_keccak256 : + IsImported globals "ethereum.crypto.hash" "keccak256". + +Axiom ethereum_utils_ensure_imports_ensure : + IsImported globals "ethereum.utils.ensure" "ensure". + +Axiom ethereum_utils_numeric_imports_ceil32 : + IsImported globals "ethereum.utils.numeric" "ceil32". + +Axiom ethereum_constantinople_fork_types_imports_EMPTY_ACCOUNT : + IsImported globals "ethereum.constantinople.fork_types" "EMPTY_ACCOUNT". + +Axiom ethereum_constantinople_state_imports_get_account : + IsImported globals "ethereum.constantinople.state" "get_account". + +Axiom ethereum_constantinople_utils_address_imports_to_address : + IsImported globals "ethereum.constantinople.utils.address" "to_address". + +Axiom ethereum_constantinople_vm_memory_imports_buffer_read : + IsImported globals "ethereum.constantinople.vm.memory" "buffer_read". +Axiom ethereum_constantinople_vm_memory_imports_memory_write : + IsImported globals "ethereum.constantinople.vm.memory" "memory_write". + +Axiom ethereum_constantinople_vm_imports_Evm : + IsImported globals "ethereum.constantinople.vm" "Evm". + +Axiom ethereum_constantinople_vm_exceptions_imports_OutOfBoundsRead : + IsImported globals "ethereum.constantinople.vm.exceptions" "OutOfBoundsRead". + +Axiom ethereum_constantinople_vm_gas_imports_GAS_BALANCE : + IsImported globals "ethereum.constantinople.vm.gas" "GAS_BALANCE". +Axiom ethereum_constantinople_vm_gas_imports_GAS_BASE : + IsImported globals "ethereum.constantinople.vm.gas" "GAS_BASE". +Axiom ethereum_constantinople_vm_gas_imports_GAS_CODE_HASH : + IsImported globals "ethereum.constantinople.vm.gas" "GAS_CODE_HASH". +Axiom ethereum_constantinople_vm_gas_imports_GAS_COPY : + IsImported globals "ethereum.constantinople.vm.gas" "GAS_COPY". +Axiom ethereum_constantinople_vm_gas_imports_GAS_EXTERNAL : + IsImported globals "ethereum.constantinople.vm.gas" "GAS_EXTERNAL". +Axiom ethereum_constantinople_vm_gas_imports_GAS_RETURN_DATA_COPY : + IsImported globals "ethereum.constantinople.vm.gas" "GAS_RETURN_DATA_COPY". +Axiom ethereum_constantinople_vm_gas_imports_GAS_VERY_LOW : + IsImported globals "ethereum.constantinople.vm.gas" "GAS_VERY_LOW". +Axiom ethereum_constantinople_vm_gas_imports_calculate_gas_extend_memory : + IsImported globals "ethereum.constantinople.vm.gas" "calculate_gas_extend_memory". +Axiom ethereum_constantinople_vm_gas_imports_charge_gas : + IsImported globals "ethereum.constantinople.vm.gas" "charge_gas". + +Axiom ethereum_constantinople_vm_stack_imports_pop : + IsImported globals "ethereum.constantinople.vm.stack" "pop". +Axiom ethereum_constantinople_vm_stack_imports_push : + IsImported globals "ethereum.constantinople.vm.stack" "push". + +Definition address : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Pushes the address of the current executing account to the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_BASE" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.call (| + M.get_field (| M.get_name (| globals, "U256" |), "from_be_bytes" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "current_target" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition balance : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Pushes the balance of the given account onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "address" , + M.call (| + M.get_name (| globals, "to_address" |), + make_list [ + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_BALANCE" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "balance" , + M.get_field (| M.call (| + M.get_name (| globals, "get_account" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "env" |), "state" |); + M.get_name (| globals, "address" |) + ], + make_dict [] + |), "balance" |) + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.get_name (| globals, "balance" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition origin : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Pushes the address of the original transaction sender to the stack. + The origin address can only be an EOA. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_BASE" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.call (| + M.get_field (| M.get_name (| globals, "U256" |), "from_be_bytes" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "env" |), "origin" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition caller : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Pushes the address of the caller onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_BASE" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.call (| + M.get_field (| M.get_name (| globals, "U256" |), "from_be_bytes" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "caller" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition callvalue : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Push the value (in wei) sent with the call onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_BASE" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "value" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition calldataload : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Push a word (32 bytes) of the input data belonging to the current + environment onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "start_index" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_VERY_LOW" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "value" , + M.call (| + M.get_name (| globals, "buffer_read" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "data" |); + M.get_name (| globals, "start_index" |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 32 + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.call (| + M.get_field (| M.get_name (| globals, "U256" |), "from_be_bytes" |), + make_list [ + M.get_name (| globals, "value" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition calldatasize : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Push the size of input data in current environment onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_BASE" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "data" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition calldatacopy : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Copy a portion of the input data in current environment to memory. + + This will also expand the memory, in case that the memory is insufficient + to store the data. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "memory_start_index" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "data_start_index" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "size" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "words" , + BinOp.floor_div (| + M.call (| + M.get_name (| globals, "ceil32" |), + make_list [ + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.get_name (| globals, "size" |) + ], + make_dict [] + |) + ], + make_dict [] + |), + Constant.int 32 + |) + |) in + let _ := M.assign_local (| + "copy_gas_cost" , + BinOp.mult (| + M.get_name (| globals, "GAS_COPY" |), + M.get_name (| globals, "words" |) + |) + |) in + let _ := M.assign_local (| + "extend_memory" , + M.call (| + M.get_name (| globals, "calculate_gas_extend_memory" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "memory" |); + make_list [ + make_tuple [ M.get_name (| globals, "memory_start_index" |); M.get_name (| globals, "size" |) ] + ] + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + BinOp.add (| + BinOp.add (| + M.get_name (| globals, "GAS_VERY_LOW" |), + M.get_name (| globals, "copy_gas_cost" |) + |), + M.get_field (| M.get_name (| globals, "extend_memory" |), "cost" |) + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "memory" |), + BinOp.mult (| + Constant.bytes "00", + M.get_field (| M.get_name (| globals, "extend_memory" |), "expand_by" |) + |) + |) in + let _ := M.assign_local (| + "value" , + M.call (| + M.get_name (| globals, "buffer_read" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "data" |); + M.get_name (| globals, "data_start_index" |); + M.get_name (| globals, "size" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "memory_write" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "memory" |); + M.get_name (| globals, "memory_start_index" |); + M.get_name (| globals, "value" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition codesize : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Push the size of code running in current environment onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_BASE" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "code" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition codecopy : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Copy a portion of the code in current environment to memory. + + This will also expand the memory, in case that the memory is insufficient + to store the data. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "memory_start_index" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "code_start_index" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "size" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "words" , + BinOp.floor_div (| + M.call (| + M.get_name (| globals, "ceil32" |), + make_list [ + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.get_name (| globals, "size" |) + ], + make_dict [] + |) + ], + make_dict [] + |), + Constant.int 32 + |) + |) in + let _ := M.assign_local (| + "copy_gas_cost" , + BinOp.mult (| + M.get_name (| globals, "GAS_COPY" |), + M.get_name (| globals, "words" |) + |) + |) in + let _ := M.assign_local (| + "extend_memory" , + M.call (| + M.get_name (| globals, "calculate_gas_extend_memory" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "memory" |); + make_list [ + make_tuple [ M.get_name (| globals, "memory_start_index" |); M.get_name (| globals, "size" |) ] + ] + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + BinOp.add (| + BinOp.add (| + M.get_name (| globals, "GAS_VERY_LOW" |), + M.get_name (| globals, "copy_gas_cost" |) + |), + M.get_field (| M.get_name (| globals, "extend_memory" |), "cost" |) + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "memory" |), + BinOp.mult (| + Constant.bytes "00", + M.get_field (| M.get_name (| globals, "extend_memory" |), "expand_by" |) + |) + |) in + let _ := M.assign_local (| + "value" , + M.call (| + M.get_name (| globals, "buffer_read" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "code" |); + M.get_name (| globals, "code_start_index" |); + M.get_name (| globals, "size" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "memory_write" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "memory" |); + M.get_name (| globals, "memory_start_index" |); + M.get_name (| globals, "value" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition gasprice : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Push the gas price used in current environment onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_BASE" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "env" |), "gas_price" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition extcodesize : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Push the code size of a given account onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "address" , + M.call (| + M.get_name (| globals, "to_address" |), + make_list [ + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_EXTERNAL" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "codesize" , + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_field (| M.call (| + M.get_name (| globals, "get_account" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "env" |), "state" |); + M.get_name (| globals, "address" |) + ], + make_dict [] + |), "code" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.get_name (| globals, "codesize" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition extcodecopy : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Copy a portion of an account's code to memory. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "address" , + M.call (| + M.get_name (| globals, "to_address" |), + make_list [ + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_start_index" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "code_start_index" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "size" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "words" , + BinOp.floor_div (| + M.call (| + M.get_name (| globals, "ceil32" |), + make_list [ + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.get_name (| globals, "size" |) + ], + make_dict [] + |) + ], + make_dict [] + |), + Constant.int 32 + |) + |) in + let _ := M.assign_local (| + "copy_gas_cost" , + BinOp.mult (| + M.get_name (| globals, "GAS_COPY" |), + M.get_name (| globals, "words" |) + |) + |) in + let _ := M.assign_local (| + "extend_memory" , + M.call (| + M.get_name (| globals, "calculate_gas_extend_memory" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "memory" |); + make_list [ + make_tuple [ M.get_name (| globals, "memory_start_index" |); M.get_name (| globals, "size" |) ] + ] + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + BinOp.add (| + BinOp.add (| + M.get_name (| globals, "GAS_EXTERNAL" |), + M.get_name (| globals, "copy_gas_cost" |) + |), + M.get_field (| M.get_name (| globals, "extend_memory" |), "cost" |) + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "memory" |), + BinOp.mult (| + Constant.bytes "00", + M.get_field (| M.get_name (| globals, "extend_memory" |), "expand_by" |) + |) + |) in + let _ := M.assign_local (| + "code" , + M.get_field (| M.call (| + M.get_name (| globals, "get_account" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "env" |), "state" |); + M.get_name (| globals, "address" |) + ], + make_dict [] + |), "code" |) + |) in + let _ := M.assign_local (| + "value" , + M.call (| + M.get_name (| globals, "buffer_read" |), + make_list [ + M.get_name (| globals, "code" |); + M.get_name (| globals, "code_start_index" |); + M.get_name (| globals, "size" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "memory_write" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "memory" |); + M.get_name (| globals, "memory_start_index" |); + M.get_name (| globals, "value" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition returndatasize : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Pushes the size of the return data buffer onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_BASE" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "return_data" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition returndatacopy : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Copies data from the return data buffer code to memory + + Parameters + ---------- + evm : + The current EVM frame. + " in + let _ := M.assign_local (| + "memory_start_index" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "return_data_start_position" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "size" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "words" , + BinOp.floor_div (| + M.call (| + M.get_name (| globals, "ceil32" |), + make_list [ + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.get_name (| globals, "size" |) + ], + make_dict [] + |) + ], + make_dict [] + |), + Constant.int 32 + |) + |) in + let _ := M.assign_local (| + "copy_gas_cost" , + BinOp.mult (| + M.get_name (| globals, "GAS_RETURN_DATA_COPY" |), + M.get_name (| globals, "words" |) + |) + |) in + let _ := M.assign_local (| + "extend_memory" , + M.call (| + M.get_name (| globals, "calculate_gas_extend_memory" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "memory" |); + make_list [ + make_tuple [ M.get_name (| globals, "memory_start_index" |); M.get_name (| globals, "size" |) ] + ] + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + BinOp.add (| + BinOp.add (| + M.get_name (| globals, "GAS_VERY_LOW" |), + M.get_name (| globals, "copy_gas_cost" |) + |), + M.get_field (| M.get_name (| globals, "extend_memory" |), "cost" |) + |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + Compare.lt_e (| + BinOp.add (| + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.get_name (| globals, "return_data_start_position" |) + ], + make_dict [] + |), + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.get_name (| globals, "size" |) + ], + make_dict [] + |) + |), + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "return_data" |) + ], + make_dict [] + |) + |); + M.get_name (| globals, "OutOfBoundsRead" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "memory" |), + BinOp.mult (| + Constant.bytes "00", + M.get_field (| M.get_name (| globals, "extend_memory" |), "expand_by" |) + |) + |) in + let _ := M.assign_local (| + "value" , + M.slice (| + M.get_field (| M.get_name (| globals, "evm" |), "return_data" |), + M.get_name (| globals, "return_data_start_position" |), + BinOp.add (| + M.get_name (| globals, "return_data_start_position" |), + M.get_name (| globals, "size" |) + |), + Constant.None_ + |) + |) in + let _ := M.call (| + M.get_name (| globals, "memory_write" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "memory" |); + M.get_name (| globals, "memory_start_index" |); + M.get_name (| globals, "value" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition extcodehash : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Returns the keccak256 hash of a contract’s bytecode + Parameters + ---------- + evm : + The current EVM frame. + " in + let _ := M.assign_local (| + "address" , + M.call (| + M.get_name (| globals, "to_address" |), + make_list [ + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_CODE_HASH" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "account" , + M.call (| + M.get_name (| globals, "get_account" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "env" |), "state" |); + M.get_name (| globals, "address" |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, "account" |), + M.get_name (| globals, "EMPTY_ACCOUNT" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "codehash" , + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "codehash" , + M.call (| + M.get_field (| M.get_name (| globals, "U256" |), "from_be_bytes" |), + make_list [ + M.call (| + M.get_name (| globals, "keccak256" |), + make_list [ + M.get_field (| M.get_name (| globals, "account" |), "code" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + )) |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.get_name (| globals, "codehash" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). diff --git a/CoqOfPython/ethereum/constantinople/vm/instructions/keccak.v b/CoqOfPython/ethereum/constantinople/vm/instructions/keccak.v new file mode 100644 index 0000000..8e00e8f --- /dev/null +++ b/CoqOfPython/ethereum/constantinople/vm/instructions/keccak.v @@ -0,0 +1,188 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.constantinople.vm.instructions.keccak". + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) Keccak Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM keccak instructions. +". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". + +Axiom ethereum_crypto_hash_imports_keccak256 : + IsImported globals "ethereum.crypto.hash" "keccak256". + +Axiom ethereum_utils_numeric_imports_ceil32 : + IsImported globals "ethereum.utils.numeric" "ceil32". + +Axiom ethereum_constantinople_vm_imports_Evm : + IsImported globals "ethereum.constantinople.vm" "Evm". + +Axiom ethereum_constantinople_vm_gas_imports_GAS_KECCAK256 : + IsImported globals "ethereum.constantinople.vm.gas" "GAS_KECCAK256". +Axiom ethereum_constantinople_vm_gas_imports_GAS_KECCAK256_WORD : + IsImported globals "ethereum.constantinople.vm.gas" "GAS_KECCAK256_WORD". +Axiom ethereum_constantinople_vm_gas_imports_calculate_gas_extend_memory : + IsImported globals "ethereum.constantinople.vm.gas" "calculate_gas_extend_memory". +Axiom ethereum_constantinople_vm_gas_imports_charge_gas : + IsImported globals "ethereum.constantinople.vm.gas" "charge_gas". + +Axiom ethereum_constantinople_vm_memory_imports_memory_read_bytes : + IsImported globals "ethereum.constantinople.vm.memory" "memory_read_bytes". + +Axiom ethereum_constantinople_vm_stack_imports_pop : + IsImported globals "ethereum.constantinople.vm.stack" "pop". +Axiom ethereum_constantinople_vm_stack_imports_push : + IsImported globals "ethereum.constantinople.vm.stack" "push". + +Definition keccak : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Pushes to the stack the Keccak-256 hash of a region of memory. + + This also expands the memory, in case the memory is insufficient to + access the data's memory location. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "memory_start_index" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "size" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "words" , + BinOp.floor_div (| + M.call (| + M.get_name (| globals, "ceil32" |), + make_list [ + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.get_name (| globals, "size" |) + ], + make_dict [] + |) + ], + make_dict [] + |), + Constant.int 32 + |) + |) in + let _ := M.assign_local (| + "word_gas_cost" , + BinOp.mult (| + M.get_name (| globals, "GAS_KECCAK256_WORD" |), + M.get_name (| globals, "words" |) + |) + |) in + let _ := M.assign_local (| + "extend_memory" , + M.call (| + M.get_name (| globals, "calculate_gas_extend_memory" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "memory" |); + make_list [ + make_tuple [ M.get_name (| globals, "memory_start_index" |); M.get_name (| globals, "size" |) ] + ] + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + BinOp.add (| + BinOp.add (| + M.get_name (| globals, "GAS_KECCAK256" |), + M.get_name (| globals, "word_gas_cost" |) + |), + M.get_field (| M.get_name (| globals, "extend_memory" |), "cost" |) + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "memory" |), + BinOp.mult (| + Constant.bytes "00", + M.get_field (| M.get_name (| globals, "extend_memory" |), "expand_by" |) + |) + |) in + let _ := M.assign_local (| + "data" , + M.call (| + M.get_name (| globals, "memory_read_bytes" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "memory" |); + M.get_name (| globals, "memory_start_index" |); + M.get_name (| globals, "size" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "hash" , + M.call (| + M.get_name (| globals, "keccak256" |), + make_list [ + M.get_name (| globals, "data" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.call (| + M.get_field (| M.get_name (| globals, "U256" |), "from_be_bytes" |), + make_list [ + M.get_name (| globals, "hash" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). diff --git a/CoqOfPython/ethereum/constantinople/vm/instructions/log.v b/CoqOfPython/ethereum/constantinople/vm/instructions/log.v new file mode 100644 index 0000000..51269e5 --- /dev/null +++ b/CoqOfPython/ethereum/constantinople/vm/instructions/log.v @@ -0,0 +1,256 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.constantinople.vm.instructions.log". + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) Logging Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM logging instructions. +". + +Axiom functools_imports_partial : + IsImported globals "functools" "partial". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". + +Axiom ethereum_utils_ensure_imports_ensure : + IsImported globals "ethereum.utils.ensure" "ensure". + +Axiom ethereum_constantinople_blocks_imports_Log : + IsImported globals "ethereum.constantinople.blocks" "Log". + +Axiom ethereum_constantinople_vm_imports_Evm : + IsImported globals "ethereum.constantinople.vm" "Evm". + +Axiom ethereum_constantinople_vm_exceptions_imports_WriteInStaticContext : + IsImported globals "ethereum.constantinople.vm.exceptions" "WriteInStaticContext". + +Axiom ethereum_constantinople_vm_gas_imports_GAS_LOG : + IsImported globals "ethereum.constantinople.vm.gas" "GAS_LOG". +Axiom ethereum_constantinople_vm_gas_imports_GAS_LOG_DATA : + IsImported globals "ethereum.constantinople.vm.gas" "GAS_LOG_DATA". +Axiom ethereum_constantinople_vm_gas_imports_GAS_LOG_TOPIC : + IsImported globals "ethereum.constantinople.vm.gas" "GAS_LOG_TOPIC". +Axiom ethereum_constantinople_vm_gas_imports_calculate_gas_extend_memory : + IsImported globals "ethereum.constantinople.vm.gas" "calculate_gas_extend_memory". +Axiom ethereum_constantinople_vm_gas_imports_charge_gas : + IsImported globals "ethereum.constantinople.vm.gas" "charge_gas". + +Axiom ethereum_constantinople_vm_memory_imports_memory_read_bytes : + IsImported globals "ethereum.constantinople.vm.memory" "memory_read_bytes". + +Axiom ethereum_constantinople_vm_stack_imports_pop : + IsImported globals "ethereum.constantinople.vm.stack" "pop". + +Definition log_n : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm"; "num_topics" ] |) in + let _ := Constant.str " + Appends a log entry, having `num_topics` topics, to the evm logs. + + This will also expand the memory if the data (required by the log entry) + corresponding to the memory is not accessible. + + Parameters + ---------- + evm : + The current EVM frame. + num_topics : + The number of topics to be included in the log entry. + + " in + let _ := M.assign_local (| + "memory_start_index" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "size" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "topics" , + make_list [] + |) in + let _ := + M.for_ (| + M.get_name (| globals, "_" |), + M.call (| + M.get_name (| globals, "range" |), + make_list [ + M.get_name (| globals, "num_topics" |) + ], + make_dict [] + |), + ltac:(M.monadic ( + let _ := M.assign_local (| + "topic" , + M.call (| + M.get_field (| M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |), "to_be_bytes32" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_field (| M.get_name (| globals, "topics" |), "append" |), + make_list [ + M.get_name (| globals, "topic" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := M.assign_local (| + "extend_memory" , + M.call (| + M.get_name (| globals, "calculate_gas_extend_memory" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "memory" |); + make_list [ + make_tuple [ M.get_name (| globals, "memory_start_index" |); M.get_name (| globals, "size" |) ] + ] + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + BinOp.add (| + BinOp.add (| + BinOp.add (| + M.get_name (| globals, "GAS_LOG" |), + BinOp.mult (| + M.get_name (| globals, "GAS_LOG_DATA" |), + M.get_name (| globals, "size" |) + |) + |), + BinOp.mult (| + M.get_name (| globals, "GAS_LOG_TOPIC" |), + M.get_name (| globals, "num_topics" |) + |) + |), + M.get_field (| M.get_name (| globals, "extend_memory" |), "cost" |) + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "memory" |), + BinOp.mult (| + Constant.bytes "00", + M.get_field (| M.get_name (| globals, "extend_memory" |), "expand_by" |) + |) + |) in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + UnOp.not (| M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "is_static" |) |); + M.get_name (| globals, "WriteInStaticContext" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "log_entry" , + M.call (| + M.get_name (| globals, "Log" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, "evm" |), "logs" |), + BinOp.add (| + M.get_field (| M.get_name (| globals, "evm" |), "logs" |), + make_tuple [ M.get_name (| globals, "log_entry" |) ] + |) + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition log0 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "log_n" |) + ], + make_dict [] + |) +)). + +Definition log1 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "log_n" |) + ], + make_dict [] + |) +)). + +Definition log2 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "log_n" |) + ], + make_dict [] + |) +)). + +Definition log3 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "log_n" |) + ], + make_dict [] + |) +)). + +Definition log4 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "log_n" |) + ], + make_dict [] + |) +)). diff --git a/CoqOfPython/ethereum/constantinople/vm/instructions/memory.v b/CoqOfPython/ethereum/constantinople/vm/instructions/memory.v new file mode 100644 index 0000000..9b9ada6 --- /dev/null +++ b/CoqOfPython/ethereum/constantinople/vm/instructions/memory.v @@ -0,0 +1,393 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.constantinople.vm.instructions.memory". + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) Memory Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM Memory instructions. +". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_Bytes : + IsImported globals "ethereum.base_types" "Bytes". + +Axiom ethereum_constantinople_vm_imports_Evm : + IsImported globals "ethereum.constantinople.vm" "Evm". + +Axiom ethereum_constantinople_vm_gas_imports_GAS_BASE : + IsImported globals "ethereum.constantinople.vm.gas" "GAS_BASE". +Axiom ethereum_constantinople_vm_gas_imports_GAS_VERY_LOW : + IsImported globals "ethereum.constantinople.vm.gas" "GAS_VERY_LOW". +Axiom ethereum_constantinople_vm_gas_imports_calculate_gas_extend_memory : + IsImported globals "ethereum.constantinople.vm.gas" "calculate_gas_extend_memory". +Axiom ethereum_constantinople_vm_gas_imports_charge_gas : + IsImported globals "ethereum.constantinople.vm.gas" "charge_gas". + +Axiom ethereum_constantinople_vm_memory_imports_memory_read_bytes : + IsImported globals "ethereum.constantinople.vm.memory" "memory_read_bytes". +Axiom ethereum_constantinople_vm_memory_imports_memory_write : + IsImported globals "ethereum.constantinople.vm.memory" "memory_write". + +Axiom ethereum_constantinople_vm_stack_imports_pop : + IsImported globals "ethereum.constantinople.vm.stack" "pop". +Axiom ethereum_constantinople_vm_stack_imports_push : + IsImported globals "ethereum.constantinople.vm.stack" "push". + +Definition mstore : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Stores a word to memory. + This also expands the memory, if the memory is + insufficient to store the word. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "start_position" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "value" , + M.call (| + M.get_field (| M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |), "to_be_bytes32" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "extend_memory" , + M.call (| + M.get_name (| globals, "calculate_gas_extend_memory" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "memory" |); + make_list [ + make_tuple [ M.get_name (| globals, "start_position" |); M.call (| + M.get_name (| globals, "U256" |), + make_list [ + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_name (| globals, "value" |) + ], + make_dict [] + |) + ], + make_dict [] + |) ] + ] + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + BinOp.add (| + M.get_name (| globals, "GAS_VERY_LOW" |), + M.get_field (| M.get_name (| globals, "extend_memory" |), "cost" |) + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "memory" |), + BinOp.mult (| + Constant.bytes "00", + M.get_field (| M.get_name (| globals, "extend_memory" |), "expand_by" |) + |) + |) in + let _ := M.call (| + M.get_name (| globals, "memory_write" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "memory" |); + M.get_name (| globals, "start_position" |); + M.get_name (| globals, "value" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition mstore8 : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Stores a byte to memory. + This also expands the memory, if the memory is + insufficient to store the word. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "start_position" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "value" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "extend_memory" , + M.call (| + M.get_name (| globals, "calculate_gas_extend_memory" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "memory" |); + make_list [ + make_tuple [ M.get_name (| globals, "start_position" |); M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 1 + ], + make_dict [] + |) ] + ] + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + BinOp.add (| + M.get_name (| globals, "GAS_VERY_LOW" |), + M.get_field (| M.get_name (| globals, "extend_memory" |), "cost" |) + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "memory" |), + BinOp.mult (| + Constant.bytes "00", + M.get_field (| M.get_name (| globals, "extend_memory" |), "expand_by" |) + |) + |) in + let _ := M.assign_local (| + "normalized_bytes_value" , + M.call (| + M.get_name (| globals, "Bytes" |), + make_list [ + make_list [ + BinOp.bit_and (| + M.get_name (| globals, "value" |), + Constant.int 255 + |) + ] + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "memory_write" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "memory" |); + M.get_name (| globals, "start_position" |); + M.get_name (| globals, "normalized_bytes_value" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition mload : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Load word from memory. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "start_position" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "extend_memory" , + M.call (| + M.get_name (| globals, "calculate_gas_extend_memory" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "memory" |); + make_list [ + make_tuple [ M.get_name (| globals, "start_position" |); M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 32 + ], + make_dict [] + |) ] + ] + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + BinOp.add (| + M.get_name (| globals, "GAS_VERY_LOW" |), + M.get_field (| M.get_name (| globals, "extend_memory" |), "cost" |) + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "memory" |), + BinOp.mult (| + Constant.bytes "00", + M.get_field (| M.get_name (| globals, "extend_memory" |), "expand_by" |) + |) + |) in + let _ := M.assign_local (| + "value" , + M.call (| + M.get_field (| M.get_name (| globals, "U256" |), "from_be_bytes" |), + make_list [ + M.call (| + M.get_name (| globals, "memory_read_bytes" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "memory" |); + M.get_name (| globals, "start_position" |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 32 + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.get_name (| globals, "value" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition msize : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Push the size of active memory in bytes onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_BASE" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "memory" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). diff --git a/CoqOfPython/ethereum/constantinople/vm/instructions/stack.v b/CoqOfPython/ethereum/constantinople/vm/instructions/stack.v new file mode 100644 index 0000000..a87c0aa --- /dev/null +++ b/CoqOfPython/ethereum/constantinople/vm/instructions/stack.v @@ -0,0 +1,947 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.constantinople.vm.instructions.stack". + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) Stack Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM stack related instructions. +". + +Axiom functools_imports_partial : + IsImported globals "functools" "partial". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". + +Axiom ethereum_utils_ensure_imports_ensure : + IsImported globals "ethereum.utils.ensure" "ensure". + +Axiom ethereum_constantinople_vm_imports_Evm : + IsImported globals "ethereum.constantinople.vm" "Evm". +Axiom ethereum_constantinople_vm_imports_stack : + IsImported globals "ethereum.constantinople.vm" "stack". + +Axiom ethereum_constantinople_vm_exceptions_imports_StackUnderflowError : + IsImported globals "ethereum.constantinople.vm.exceptions" "StackUnderflowError". + +Axiom ethereum_constantinople_vm_gas_imports_GAS_BASE : + IsImported globals "ethereum.constantinople.vm.gas" "GAS_BASE". +Axiom ethereum_constantinople_vm_gas_imports_GAS_VERY_LOW : + IsImported globals "ethereum.constantinople.vm.gas" "GAS_VERY_LOW". +Axiom ethereum_constantinople_vm_gas_imports_charge_gas : + IsImported globals "ethereum.constantinople.vm.gas" "charge_gas". + +Axiom ethereum_constantinople_vm_memory_imports_buffer_read : + IsImported globals "ethereum.constantinople.vm.memory" "buffer_read". + +Definition pop : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Remove item from stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.call (| + M.get_field (| M.get_name (| globals, "stack" |), "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_BASE" |) + ], + make_dict [] + |) in + let _ := M.pass (| |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition push_n : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm"; "num_bytes" ] |) in + let _ := Constant.str " + Pushes a N-byte immediate onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + num_bytes : + The number of immediate bytes to be read from the code and pushed to + the stack. + + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_VERY_LOW" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "data_to_push" , + M.call (| + M.get_field (| M.get_name (| globals, "U256" |), "from_be_bytes" |), + make_list [ + M.call (| + M.get_name (| globals, "buffer_read" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "code" |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + BinOp.add (| + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) + ], + make_dict [] + |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + M.get_name (| globals, "num_bytes" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_field (| M.get_name (| globals, "stack" |), "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.get_name (| globals, "data_to_push" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + BinOp.add (| + Constant.int 1, + M.get_name (| globals, "num_bytes" |) + |) + |) in + M.pure Constant.None_)). + +Definition dup_n : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm"; "item_number" ] |) in + let _ := Constant.str " + Duplicate the Nth stack item (from top of the stack) to the top of stack. + + Parameters + ---------- + evm : + The current EVM frame. + + item_number : + The stack item number (0-indexed from top of stack) to be duplicated + to the top of stack. + + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_VERY_LOW" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + Compare.lt (| + M.get_name (| globals, "item_number" |), + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |); + M.get_name (| globals, "StackUnderflowError" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "data_to_duplicate" , + M.get_subscript (| + M.get_field (| M.get_name (| globals, "evm" |), "stack" |), + BinOp.sub (| + BinOp.sub (| + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |), + Constant.int 1 + |), + M.get_name (| globals, "item_number" |) + |) + |) + |) in + let _ := M.call (| + M.get_field (| M.get_name (| globals, "stack" |), "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.get_name (| globals, "data_to_duplicate" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition swap_n : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm"; "item_number" ] |) in + let _ := Constant.str " + Swap the top and the `item_number` element of the stack, where + the top of the stack is position zero. + + If `item_number` is zero, this function does nothing (which should not be + possible, since there is no `SWAP0` instruction). + + Parameters + ---------- + evm : + The current EVM frame. + + item_number : + The stack item number (0-indexed from top of stack) to be swapped + with the top of stack element. + + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_VERY_LOW" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + Compare.lt (| + M.get_name (| globals, "item_number" |), + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |); + M.get_name (| globals, "StackUnderflowError" |) + ], + make_dict [] + |) in + let _ := M.assign (| + make_tuple [ M.get_subscript (| + M.get_field (| M.get_name (| globals, "evm" |), "stack" |), + UnOp.sub (| Constant.int 1 |) + |); M.get_subscript (| + M.get_field (| M.get_name (| globals, "evm" |), "stack" |), + BinOp.sub (| + UnOp.sub (| Constant.int 1 |), + M.get_name (| globals, "item_number" |) + |) + |) ], + make_tuple [ M.get_subscript (| + M.get_field (| M.get_name (| globals, "evm" |), "stack" |), + BinOp.sub (| + UnOp.sub (| Constant.int 1 |), + M.get_name (| globals, "item_number" |) + |) + |); M.get_subscript (| + M.get_field (| M.get_name (| globals, "evm" |), "stack" |), + UnOp.sub (| Constant.int 1 |) + |) ] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition push1 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push2 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push3 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push4 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push5 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push6 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push7 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push8 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push9 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push10 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push11 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push12 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push13 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push14 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push15 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push16 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push17 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push18 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push19 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push20 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push21 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push22 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push23 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push24 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push25 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push26 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push27 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push28 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push29 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push30 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push31 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push32 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "push_n" |) + ], + make_dict [] + |) +)). + +Definition dup1 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "dup_n" |) + ], + make_dict [] + |) +)). + +Definition dup2 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "dup_n" |) + ], + make_dict [] + |) +)). + +Definition dup3 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "dup_n" |) + ], + make_dict [] + |) +)). + +Definition dup4 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "dup_n" |) + ], + make_dict [] + |) +)). + +Definition dup5 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "dup_n" |) + ], + make_dict [] + |) +)). + +Definition dup6 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "dup_n" |) + ], + make_dict [] + |) +)). + +Definition dup7 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "dup_n" |) + ], + make_dict [] + |) +)). + +Definition dup8 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "dup_n" |) + ], + make_dict [] + |) +)). + +Definition dup9 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "dup_n" |) + ], + make_dict [] + |) +)). + +Definition dup10 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "dup_n" |) + ], + make_dict [] + |) +)). + +Definition dup11 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "dup_n" |) + ], + make_dict [] + |) +)). + +Definition dup12 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "dup_n" |) + ], + make_dict [] + |) +)). + +Definition dup13 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "dup_n" |) + ], + make_dict [] + |) +)). + +Definition dup14 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "dup_n" |) + ], + make_dict [] + |) +)). + +Definition dup15 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "dup_n" |) + ], + make_dict [] + |) +)). + +Definition dup16 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "dup_n" |) + ], + make_dict [] + |) +)). + +Definition swap1 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "swap_n" |) + ], + make_dict [] + |) +)). + +Definition swap2 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "swap_n" |) + ], + make_dict [] + |) +)). + +Definition swap3 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "swap_n" |) + ], + make_dict [] + |) +)). + +Definition swap4 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "swap_n" |) + ], + make_dict [] + |) +)). + +Definition swap5 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "swap_n" |) + ], + make_dict [] + |) +)). + +Definition swap6 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "swap_n" |) + ], + make_dict [] + |) +)). + +Definition swap7 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "swap_n" |) + ], + make_dict [] + |) +)). + +Definition swap8 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "swap_n" |) + ], + make_dict [] + |) +)). + +Definition swap9 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "swap_n" |) + ], + make_dict [] + |) +)). + +Definition swap10 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "swap_n" |) + ], + make_dict [] + |) +)). + +Definition swap11 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "swap_n" |) + ], + make_dict [] + |) +)). + +Definition swap12 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "swap_n" |) + ], + make_dict [] + |) +)). + +Definition swap13 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "swap_n" |) + ], + make_dict [] + |) +)). + +Definition swap14 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "swap_n" |) + ], + make_dict [] + |) +)). + +Definition swap15 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "swap_n" |) + ], + make_dict [] + |) +)). + +Definition swap16 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "swap_n" |) + ], + make_dict [] + |) +)). diff --git a/CoqOfPython/ethereum/constantinople/vm/instructions/storage.v b/CoqOfPython/ethereum/constantinople/vm/instructions/storage.v new file mode 100644 index 0000000..95bb7fb --- /dev/null +++ b/CoqOfPython/ethereum/constantinople/vm/instructions/storage.v @@ -0,0 +1,248 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.constantinople.vm.instructions.storage". + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) Storage Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM storage related instructions. +". + +Axiom ethereum_utils_ensure_imports_ensure : + IsImported globals "ethereum.utils.ensure" "ensure". + +Axiom ethereum_constantinople_state_imports_get_storage : + IsImported globals "ethereum.constantinople.state" "get_storage". +Axiom ethereum_constantinople_state_imports_set_storage : + IsImported globals "ethereum.constantinople.state" "set_storage". + +Axiom ethereum_constantinople_vm_imports_Evm : + IsImported globals "ethereum.constantinople.vm" "Evm". + +Axiom ethereum_constantinople_vm_exceptions_imports_WriteInStaticContext : + IsImported globals "ethereum.constantinople.vm.exceptions" "WriteInStaticContext". + +Axiom ethereum_constantinople_vm_gas_imports_GAS_SLOAD : + IsImported globals "ethereum.constantinople.vm.gas" "GAS_SLOAD". +Axiom ethereum_constantinople_vm_gas_imports_GAS_STORAGE_CLEAR_REFUND : + IsImported globals "ethereum.constantinople.vm.gas" "GAS_STORAGE_CLEAR_REFUND". +Axiom ethereum_constantinople_vm_gas_imports_GAS_STORAGE_SET : + IsImported globals "ethereum.constantinople.vm.gas" "GAS_STORAGE_SET". +Axiom ethereum_constantinople_vm_gas_imports_GAS_STORAGE_UPDATE : + IsImported globals "ethereum.constantinople.vm.gas" "GAS_STORAGE_UPDATE". +Axiom ethereum_constantinople_vm_gas_imports_charge_gas : + IsImported globals "ethereum.constantinople.vm.gas" "charge_gas". + +Axiom ethereum_constantinople_vm_stack_imports_pop : + IsImported globals "ethereum.constantinople.vm.stack" "pop". +Axiom ethereum_constantinople_vm_stack_imports_push : + IsImported globals "ethereum.constantinople.vm.stack" "push". + +Definition sload : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Loads to the stack, the value corresponding to a certain key from the + storage of the current account. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "key" , + M.call (| + M.get_field (| M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |), "to_be_bytes32" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_SLOAD" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "value" , + M.call (| + M.get_name (| globals, "get_storage" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "env" |), "state" |); + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "current_target" |); + M.get_name (| globals, "key" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.get_name (| globals, "value" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition sstore : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Stores a value at a certain key in the current context's storage. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "key" , + M.call (| + M.get_field (| M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |), "to_be_bytes32" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "new_value" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "current_value" , + M.call (| + M.get_name (| globals, "get_storage" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "env" |), "state" |); + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "current_target" |); + M.get_name (| globals, "key" |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + BoolOp.and (| + Compare.not_eq (| + M.get_name (| globals, "new_value" |), + Constant.int 0 + |), + ltac:(M.monadic ( + Compare.eq (| + M.get_name (| globals, "current_value" |), + Constant.int 0 + |) + )) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "gas_cost" , + M.get_name (| globals, "GAS_STORAGE_SET" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "gas_cost" , + M.get_name (| globals, "GAS_STORAGE_UPDATE" |) + |) in + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + BoolOp.and (| + Compare.eq (| + M.get_name (| globals, "new_value" |), + Constant.int 0 + |), + ltac:(M.monadic ( + Compare.not_eq (| + M.get_name (| globals, "current_value" |), + Constant.int 0 + |) + )) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "refund_counter" |), + M.get_name (| globals, "GAS_STORAGE_CLEAR_REFUND" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "gas_cost" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + UnOp.not (| M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "is_static" |) |); + M.get_name (| globals, "WriteInStaticContext" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "set_storage" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "env" |), "state" |); + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "current_target" |); + M.get_name (| globals, "key" |); + M.get_name (| globals, "new_value" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). diff --git a/CoqOfPython/ethereum/constantinople/vm/instructions/system.v b/CoqOfPython/ethereum/constantinople/vm/instructions/system.v new file mode 100644 index 0000000..d27c09f --- /dev/null +++ b/CoqOfPython/ethereum/constantinople/vm/instructions/system.v @@ -0,0 +1,2117 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.constantinople.vm.instructions.system". + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) System Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM system related instructions. +". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_Bytes0 : + IsImported globals "ethereum.base_types" "Bytes0". +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". + +Axiom ethereum_utils_ensure_imports_ensure : + IsImported globals "ethereum.utils.ensure" "ensure". + +Axiom ethereum_utils_numeric_imports_ceil32 : + IsImported globals "ethereum.utils.numeric" "ceil32". + +Axiom ethereum_constantinople_fork_types_imports_Address : + IsImported globals "ethereum.constantinople.fork_types" "Address". + +Axiom ethereum_constantinople_state_imports_account_exists_and_is_empty : + IsImported globals "ethereum.constantinople.state" "account_exists_and_is_empty". +Axiom ethereum_constantinople_state_imports_account_has_code_or_nonce : + IsImported globals "ethereum.constantinople.state" "account_has_code_or_nonce". +Axiom ethereum_constantinople_state_imports_get_account : + IsImported globals "ethereum.constantinople.state" "get_account". +Axiom ethereum_constantinople_state_imports_increment_nonce : + IsImported globals "ethereum.constantinople.state" "increment_nonce". +Axiom ethereum_constantinople_state_imports_is_account_alive : + IsImported globals "ethereum.constantinople.state" "is_account_alive". +Axiom ethereum_constantinople_state_imports_set_account_balance : + IsImported globals "ethereum.constantinople.state" "set_account_balance". + +Axiom ethereum_constantinople_utils_address_imports_compute_contract_address : + IsImported globals "ethereum.constantinople.utils.address" "compute_contract_address". +Axiom ethereum_constantinople_utils_address_imports_compute_create2_contract_address : + IsImported globals "ethereum.constantinople.utils.address" "compute_create2_contract_address". +Axiom ethereum_constantinople_utils_address_imports_to_address : + IsImported globals "ethereum.constantinople.utils.address" "to_address". + +Axiom ethereum_constantinople_vm_imports_Evm : + IsImported globals "ethereum.constantinople.vm" "Evm". +Axiom ethereum_constantinople_vm_imports_Message : + IsImported globals "ethereum.constantinople.vm" "Message". +Axiom ethereum_constantinople_vm_imports_incorporate_child_on_error : + IsImported globals "ethereum.constantinople.vm" "incorporate_child_on_error". +Axiom ethereum_constantinople_vm_imports_incorporate_child_on_success : + IsImported globals "ethereum.constantinople.vm" "incorporate_child_on_success". + +Axiom ethereum_constantinople_vm_exceptions_imports_Revert : + IsImported globals "ethereum.constantinople.vm.exceptions" "Revert". +Axiom ethereum_constantinople_vm_exceptions_imports_WriteInStaticContext : + IsImported globals "ethereum.constantinople.vm.exceptions" "WriteInStaticContext". + +Axiom ethereum_constantinople_vm_gas_imports_GAS_CALL : + IsImported globals "ethereum.constantinople.vm.gas" "GAS_CALL". +Axiom ethereum_constantinople_vm_gas_imports_GAS_CALL_VALUE : + IsImported globals "ethereum.constantinople.vm.gas" "GAS_CALL_VALUE". +Axiom ethereum_constantinople_vm_gas_imports_GAS_CREATE : + IsImported globals "ethereum.constantinople.vm.gas" "GAS_CREATE". +Axiom ethereum_constantinople_vm_gas_imports_GAS_KECCAK256_WORD : + IsImported globals "ethereum.constantinople.vm.gas" "GAS_KECCAK256_WORD". +Axiom ethereum_constantinople_vm_gas_imports_GAS_NEW_ACCOUNT : + IsImported globals "ethereum.constantinople.vm.gas" "GAS_NEW_ACCOUNT". +Axiom ethereum_constantinople_vm_gas_imports_GAS_SELF_DESTRUCT : + IsImported globals "ethereum.constantinople.vm.gas" "GAS_SELF_DESTRUCT". +Axiom ethereum_constantinople_vm_gas_imports_GAS_SELF_DESTRUCT_NEW_ACCOUNT : + IsImported globals "ethereum.constantinople.vm.gas" "GAS_SELF_DESTRUCT_NEW_ACCOUNT". +Axiom ethereum_constantinople_vm_gas_imports_GAS_ZERO : + IsImported globals "ethereum.constantinople.vm.gas" "GAS_ZERO". +Axiom ethereum_constantinople_vm_gas_imports_REFUND_SELF_DESTRUCT : + IsImported globals "ethereum.constantinople.vm.gas" "REFUND_SELF_DESTRUCT". +Axiom ethereum_constantinople_vm_gas_imports_calculate_gas_extend_memory : + IsImported globals "ethereum.constantinople.vm.gas" "calculate_gas_extend_memory". +Axiom ethereum_constantinople_vm_gas_imports_calculate_message_call_gas : + IsImported globals "ethereum.constantinople.vm.gas" "calculate_message_call_gas". +Axiom ethereum_constantinople_vm_gas_imports_charge_gas : + IsImported globals "ethereum.constantinople.vm.gas" "charge_gas". +Axiom ethereum_constantinople_vm_gas_imports_max_message_call_gas : + IsImported globals "ethereum.constantinople.vm.gas" "max_message_call_gas". + +Axiom ethereum_constantinople_vm_memory_imports_memory_read_bytes : + IsImported globals "ethereum.constantinople.vm.memory" "memory_read_bytes". +Axiom ethereum_constantinople_vm_memory_imports_memory_write : + IsImported globals "ethereum.constantinople.vm.memory" "memory_write". + +Axiom ethereum_constantinople_vm_stack_imports_pop : + IsImported globals "ethereum.constantinople.vm.stack" "pop". +Axiom ethereum_constantinople_vm_stack_imports_push : + IsImported globals "ethereum.constantinople.vm.stack" "push". + +Definition generic_create : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm"; "endowment"; "contract_address"; "memory_start_position"; "memory_size" ] |) in + let _ := Constant.str " + Core logic used by the `CREATE*` family of opcodes. + " in +(* At stmt: unsupported node type: ImportFrom *) + let _ := M.assign_local (| + "create_message_gas" , + M.call (| + M.get_name (| globals, "max_message_call_gas" |), + make_list [ + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "gas_left" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_op (| + BinOp.sub, + M.get_field (| M.get_name (| globals, "evm" |), "gas_left" |), + M.get_name (| globals, "create_message_gas" |) + |) in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + UnOp.not (| M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "is_static" |) |); + M.get_name (| globals, "WriteInStaticContext" |) + ], + make_dict [] + |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, "evm" |), "return_data" |), + Constant.bytes "" + |) in + let _ := M.assign_local (| + "sender_address" , + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "current_target" |) + |) in + let _ := M.assign_local (| + "sender" , + M.call (| + M.get_name (| globals, "get_account" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "env" |), "state" |); + M.get_name (| globals, "sender_address" |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + BoolOp.or (| + Compare.lt (| + M.get_field (| M.get_name (| globals, "sender" |), "balance" |), + M.get_name (| globals, "endowment" |) + |), + ltac:(M.monadic ( + BoolOp.or (| + Compare.eq (| + M.get_field (| M.get_name (| globals, "sender" |), "nonce" |), + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + BinOp.sub (| + BinOp.pow (| + Constant.int 2, + Constant.int 64 + |), + Constant.int 1 + |) + ], + make_dict [] + |) + |), + ltac:(M.monadic ( + Compare.gt (| + BinOp.add (| + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "depth" |), + Constant.int 1 + |), + M.get_name (| globals, "STACK_DEPTH_LIMIT" |) + |) + )) + |) + )) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "gas_left" |), + M.get_name (| globals, "create_message_gas" |) + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.return_ (| + Constant.None_ + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, "account_has_code_or_nonce" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "env" |), "state" |); + M.get_name (| globals, "contract_address" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, "increment_nonce" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "env" |), "state" |); + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "current_target" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.return_ (| + Constant.None_ + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "call_data" , + M.call (| + M.get_name (| globals, "memory_read_bytes" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "memory" |); + M.get_name (| globals, "memory_start_position" |); + M.get_name (| globals, "memory_size" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "increment_nonce" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "env" |), "state" |); + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "current_target" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "child_message" , + M.call (| + M.get_name (| globals, "Message" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "child_evm" , + M.call (| + M.get_name (| globals, "process_create_message" |), + make_list [ + M.get_name (| globals, "child_message" |); + M.get_field (| M.get_name (| globals, "evm" |), "env" |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + M.get_field (| M.get_name (| globals, "child_evm" |), "error" |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, "incorporate_child_on_error" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "child_evm" |) + ], + make_dict [] + |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, "evm" |), "return_data" |), + M.get_field (| M.get_name (| globals, "child_evm" |), "output" |) + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + ], + make_dict [] + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, "incorporate_child_on_success" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "child_evm" |) + ], + make_dict [] + |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, "evm" |), "return_data" |), + Constant.bytes "" + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.call (| + M.get_field (| M.get_name (| globals, "U256" |), "from_be_bytes" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "child_evm" |), "message" |), "current_target" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_)). + +Definition create : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Creates a new account with associated code. + + Parameters + ---------- + evm : + The current EVM frame. + " in + let _ := M.assign_local (| + "endowment" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_start_position" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_size" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "extend_memory" , + M.call (| + M.get_name (| globals, "calculate_gas_extend_memory" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "memory" |); + make_list [ + make_tuple [ M.get_name (| globals, "memory_start_position" |); M.get_name (| globals, "memory_size" |) ] + ] + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + BinOp.add (| + M.get_name (| globals, "GAS_CREATE" |), + M.get_field (| M.get_name (| globals, "extend_memory" |), "cost" |) + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "memory" |), + BinOp.mult (| + Constant.bytes "00", + M.get_field (| M.get_name (| globals, "extend_memory" |), "expand_by" |) + |) + |) in + let _ := M.assign_local (| + "contract_address" , + M.call (| + M.get_name (| globals, "compute_contract_address" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "current_target" |); + M.get_field (| M.call (| + M.get_name (| globals, "get_account" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "env" |), "state" |); + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "current_target" |) + ], + make_dict [] + |), "nonce" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "generic_create" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "endowment" |); + M.get_name (| globals, "contract_address" |); + M.get_name (| globals, "memory_start_position" |); + M.get_name (| globals, "memory_size" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition create2 : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Creates a new account with associated code. + + It's similar to CREATE opcode except that the address of new account + depends on the init_code instead of the nonce of sender. + + Parameters + ---------- + evm : + The current EVM frame. + " in + let _ := M.assign_local (| + "endowment" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_start_position" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_size" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "salt" , + M.call (| + M.get_field (| M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |), "to_be_bytes32" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "extend_memory" , + M.call (| + M.get_name (| globals, "calculate_gas_extend_memory" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "memory" |); + make_list [ + make_tuple [ M.get_name (| globals, "memory_start_position" |); M.get_name (| globals, "memory_size" |) ] + ] + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "call_data_words" , + BinOp.floor_div (| + M.call (| + M.get_name (| globals, "ceil32" |), + make_list [ + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.get_name (| globals, "memory_size" |) + ], + make_dict [] + |) + ], + make_dict [] + |), + Constant.int 32 + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + BinOp.add (| + BinOp.add (| + M.get_name (| globals, "GAS_CREATE" |), + BinOp.mult (| + M.get_name (| globals, "GAS_KECCAK256_WORD" |), + M.get_name (| globals, "call_data_words" |) + |) + |), + M.get_field (| M.get_name (| globals, "extend_memory" |), "cost" |) + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "memory" |), + BinOp.mult (| + Constant.bytes "00", + M.get_field (| M.get_name (| globals, "extend_memory" |), "expand_by" |) + |) + |) in + let _ := M.assign_local (| + "contract_address" , + M.call (| + M.get_name (| globals, "compute_create2_contract_address" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "current_target" |); + M.get_name (| globals, "salt" |); + M.call (| + M.get_name (| globals, "memory_read_bytes" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "memory" |); + M.get_name (| globals, "memory_start_position" |); + M.get_name (| globals, "memory_size" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "generic_create" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "endowment" |); + M.get_name (| globals, "contract_address" |); + M.get_name (| globals, "memory_start_position" |); + M.get_name (| globals, "memory_size" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition return_ : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Halts execution returning output data. + + Parameters + ---------- + evm : + The current EVM frame. + " in + let _ := M.assign_local (| + "memory_start_position" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_size" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "extend_memory" , + M.call (| + M.get_name (| globals, "calculate_gas_extend_memory" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "memory" |); + make_list [ + make_tuple [ M.get_name (| globals, "memory_start_position" |); M.get_name (| globals, "memory_size" |) ] + ] + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + BinOp.add (| + M.get_name (| globals, "GAS_ZERO" |), + M.get_field (| M.get_name (| globals, "extend_memory" |), "cost" |) + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "memory" |), + BinOp.mult (| + Constant.bytes "00", + M.get_field (| M.get_name (| globals, "extend_memory" |), "expand_by" |) + |) + |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, "evm" |), "output" |), + M.call (| + M.get_name (| globals, "memory_read_bytes" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "memory" |); + M.get_name (| globals, "memory_start_position" |); + M.get_name (| globals, "memory_size" |) + ], + make_dict [] + |) + |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, "evm" |), "running" |), + Constant.bool false + |) in + let _ := M.pass (| |) in + M.pure Constant.None_)). + +Definition generic_call : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm"; "gas"; "value"; "caller"; "to"; "code_address"; "should_transfer_value"; "is_staticcall"; "memory_input_start_position"; "memory_input_size"; "memory_output_start_position"; "memory_output_size" ] |) in + let _ := Constant.str " + Perform the core logic of the `CALL*` family of opcodes. + " in +(* At stmt: unsupported node type: ImportFrom *) + let _ := M.assign (| + M.get_field (| M.get_name (| globals, "evm" |), "return_data" |), + Constant.bytes "" + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.gt (| + BinOp.add (| + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "depth" |), + Constant.int 1 + |), + M.get_name (| globals, "STACK_DEPTH_LIMIT" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "gas_left" |), + M.get_name (| globals, "gas" |) + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.return_ (| + Constant.None_ + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "call_data" , + M.call (| + M.get_name (| globals, "memory_read_bytes" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "memory" |); + M.get_name (| globals, "memory_input_start_position" |); + M.get_name (| globals, "memory_input_size" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "code" , + M.get_field (| M.call (| + M.get_name (| globals, "get_account" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "env" |), "state" |); + M.get_name (| globals, "code_address" |) + ], + make_dict [] + |), "code" |) + |) in + let _ := M.assign_local (| + "child_message" , + M.call (| + M.get_name (| globals, "Message" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "child_evm" , + M.call (| + M.get_name (| globals, "process_message" |), + make_list [ + M.get_name (| globals, "child_message" |); + M.get_field (| M.get_name (| globals, "evm" |), "env" |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + M.get_field (| M.get_name (| globals, "child_evm" |), "error" |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, "incorporate_child_on_error" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "child_evm" |) + ], + make_dict [] + |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, "evm" |), "return_data" |), + M.get_field (| M.get_name (| globals, "child_evm" |), "output" |) + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + ], + make_dict [] + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, "incorporate_child_on_success" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "child_evm" |) + ], + make_dict [] + |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, "evm" |), "return_data" |), + M.get_field (| M.get_name (| globals, "child_evm" |), "output" |) + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 1 + ], + make_dict [] + |) + ], + make_dict [] + |) in + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "actual_output_size" , + M.call (| + M.get_name (| globals, "min" |), + make_list [ + M.get_name (| globals, "memory_output_size" |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_field (| M.get_name (| globals, "child_evm" |), "output" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "memory_write" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "memory" |); + M.get_name (| globals, "memory_output_start_position" |); + M.slice (| + M.get_field (| M.get_name (| globals, "child_evm" |), "output" |), + Constant.None_, + M.get_name (| globals, "actual_output_size" |), + Constant.None_ + |) + ], + make_dict [] + |) in + M.pure Constant.None_)). + +Definition call : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Message-call into an account. + + Parameters + ---------- + evm : + The current EVM frame. + " in + let _ := M.assign_local (| + "gas" , + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "to" , + M.call (| + M.get_name (| globals, "to_address" |), + make_list [ + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "value" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_input_start_position" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_input_size" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_output_start_position" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_output_size" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "extend_memory" , + M.call (| + M.get_name (| globals, "calculate_gas_extend_memory" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "memory" |); + make_list [ + make_tuple [ M.get_name (| globals, "memory_input_start_position" |); M.get_name (| globals, "memory_input_size" |) ]; + make_tuple [ M.get_name (| globals, "memory_output_start_position" |); M.get_name (| globals, "memory_output_size" |) ] + ] + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "create_gas_cost" , + (* if *) + M.if_then_else (| + BoolOp.or (| + Compare.eq (| + M.get_name (| globals, "value" |), + Constant.int 0 + |), + ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "is_account_alive" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "env" |), "state" |); + M.get_name (| globals, "to" |) + ], + make_dict [] + |) + )) + |), + (* then *) + ltac:(M.monadic ( +M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + (* else *) + )), ltac:(M.monadic ( +M.get_name (| globals, "GAS_NEW_ACCOUNT" |) + )) |) + |) in + let _ := M.assign_local (| + "transfer_gas_cost" , + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, "value" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( +M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + (* else *) + )), ltac:(M.monadic ( +M.get_name (| globals, "GAS_CALL_VALUE" |) + )) |) + |) in + let _ := M.assign_local (| + "message_call_gas" , + M.call (| + M.get_name (| globals, "calculate_message_call_gas" |), + make_list [ + M.get_name (| globals, "value" |); + M.get_name (| globals, "gas" |); + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "gas_left" |) + ], + make_dict [] + |); + M.get_field (| M.get_name (| globals, "extend_memory" |), "cost" |); + BinOp.add (| + BinOp.add (| + M.get_name (| globals, "GAS_CALL" |), + M.get_name (| globals, "create_gas_cost" |) + |), + M.get_name (| globals, "transfer_gas_cost" |) + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + BinOp.add (| + M.get_field (| M.get_name (| globals, "message_call_gas" |), "cost" |), + M.get_field (| M.get_name (| globals, "extend_memory" |), "cost" |) + |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + BoolOp.or (| + UnOp.not (| M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "is_static" |) |), + ltac:(M.monadic ( + Compare.eq (| + M.get_name (| globals, "value" |), + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + |) + )) + |); + M.get_name (| globals, "WriteInStaticContext" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "memory" |), + BinOp.mult (| + Constant.bytes "00", + M.get_field (| M.get_name (| globals, "extend_memory" |), "expand_by" |) + |) + |) in + let _ := M.assign_local (| + "sender_balance" , + M.get_field (| M.call (| + M.get_name (| globals, "get_account" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "env" |), "state" |); + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "current_target" |) + ], + make_dict [] + |), "balance" |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.lt (| + M.get_name (| globals, "sender_balance" |), + M.get_name (| globals, "value" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, "evm" |), "return_data" |), + Constant.bytes "" + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "gas_left" |), + M.get_field (| M.get_name (| globals, "message_call_gas" |), "stipend" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, "generic_call" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_field (| M.get_name (| globals, "message_call_gas" |), "stipend" |); + M.get_name (| globals, "value" |); + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "current_target" |); + M.get_name (| globals, "to" |); + M.get_name (| globals, "to" |); + Constant.bool true; + Constant.bool false; + M.get_name (| globals, "memory_input_start_position" |); + M.get_name (| globals, "memory_input_size" |); + M.get_name (| globals, "memory_output_start_position" |); + M.get_name (| globals, "memory_output_size" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + )) |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition callcode : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Message-call into this account with alternative account’s code. + + Parameters + ---------- + evm : + The current EVM frame. + " in + let _ := M.assign_local (| + "gas" , + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "code_address" , + M.call (| + M.get_name (| globals, "to_address" |), + make_list [ + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "value" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_input_start_position" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_input_size" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_output_start_position" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_output_size" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "to" , + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "current_target" |) + |) in + let _ := M.assign_local (| + "extend_memory" , + M.call (| + M.get_name (| globals, "calculate_gas_extend_memory" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "memory" |); + make_list [ + make_tuple [ M.get_name (| globals, "memory_input_start_position" |); M.get_name (| globals, "memory_input_size" |) ]; + make_tuple [ M.get_name (| globals, "memory_output_start_position" |); M.get_name (| globals, "memory_output_size" |) ] + ] + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "transfer_gas_cost" , + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, "value" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( +M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + (* else *) + )), ltac:(M.monadic ( +M.get_name (| globals, "GAS_CALL_VALUE" |) + )) |) + |) in + let _ := M.assign_local (| + "message_call_gas" , + M.call (| + M.get_name (| globals, "calculate_message_call_gas" |), + make_list [ + M.get_name (| globals, "value" |); + M.get_name (| globals, "gas" |); + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "gas_left" |) + ], + make_dict [] + |); + M.get_field (| M.get_name (| globals, "extend_memory" |), "cost" |); + BinOp.add (| + M.get_name (| globals, "GAS_CALL" |), + M.get_name (| globals, "transfer_gas_cost" |) + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + BinOp.add (| + M.get_field (| M.get_name (| globals, "message_call_gas" |), "cost" |), + M.get_field (| M.get_name (| globals, "extend_memory" |), "cost" |) + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "memory" |), + BinOp.mult (| + Constant.bytes "00", + M.get_field (| M.get_name (| globals, "extend_memory" |), "expand_by" |) + |) + |) in + let _ := M.assign_local (| + "sender_balance" , + M.get_field (| M.call (| + M.get_name (| globals, "get_account" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "env" |), "state" |); + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "current_target" |) + ], + make_dict [] + |), "balance" |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.lt (| + M.get_name (| globals, "sender_balance" |), + M.get_name (| globals, "value" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, "evm" |), "return_data" |), + Constant.bytes "" + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "gas_left" |), + M.get_field (| M.get_name (| globals, "message_call_gas" |), "stipend" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, "generic_call" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_field (| M.get_name (| globals, "message_call_gas" |), "stipend" |); + M.get_name (| globals, "value" |); + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "current_target" |); + M.get_name (| globals, "to" |); + M.get_name (| globals, "code_address" |); + Constant.bool true; + Constant.bool false; + M.get_name (| globals, "memory_input_start_position" |); + M.get_name (| globals, "memory_input_size" |); + M.get_name (| globals, "memory_output_start_position" |); + M.get_name (| globals, "memory_output_size" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + )) |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition selfdestruct : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Halt execution and register account for later deletion. + + Parameters + ---------- + evm : + The current EVM frame. + " in + let _ := M.assign_local (| + "beneficiary" , + M.call (| + M.get_name (| globals, "to_address" |), + make_list [ + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "gas_cost" , + M.get_name (| globals, "GAS_SELF_DESTRUCT" |) + |) in + let _ := + (* if *) + M.if_then_else (| + BoolOp.and (| + UnOp.not (| M.call (| + M.get_name (| globals, "is_account_alive" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "env" |), "state" |); + M.get_name (| globals, "beneficiary" |) + ], + make_dict [] + |) |), + ltac:(M.monadic ( + Compare.not_eq (| + M.get_field (| M.call (| + M.get_name (| globals, "get_account" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "env" |), "state" |); + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "current_target" |) + ], + make_dict [] + |), "balance" |), + Constant.int 0 + |) + )) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_op_local (| + BinOp.add, + "gas_cost", + M.get_name (| globals, "GAS_SELF_DESTRUCT_NEW_ACCOUNT" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "originator" , + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "current_target" |) + |) in + let _ := M.assign_local (| + "refunded_accounts" , + M.get_field (| M.get_name (| globals, "evm" |), "accounts_to_delete" |) + |) in + let _ := M.assign_local (| + "parent_evm" , + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "parent_evm" |) + |) in + let _ := + M.while (| + Compare.is_not (| + M.get_name (| globals, "parent_evm" |), + Constant.None_ + |), + ltac:(M.monadic ( + let _ := M.call (| + M.get_field (| M.get_name (| globals, "refunded_accounts" |), "update" |), + make_list [ + M.get_field (| M.get_name (| globals, "parent_evm" |), "accounts_to_delete" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "parent_evm" , + M.get_field (| M.get_field (| M.get_name (| globals, "parent_evm" |), "message" |), "parent_evm" |) + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.not_in (| + M.get_name (| globals, "originator" |), + M.get_name (| globals, "refunded_accounts" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "refund_counter" |), + M.get_name (| globals, "REFUND_SELF_DESTRUCT" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "gas_cost" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + UnOp.not (| M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "is_static" |) |); + M.get_name (| globals, "WriteInStaticContext" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "beneficiary_balance" , + M.get_field (| M.call (| + M.get_name (| globals, "get_account" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "env" |), "state" |); + M.get_name (| globals, "beneficiary" |) + ], + make_dict [] + |), "balance" |) + |) in + let _ := M.assign_local (| + "originator_balance" , + M.get_field (| M.call (| + M.get_name (| globals, "get_account" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "env" |), "state" |); + M.get_name (| globals, "originator" |) + ], + make_dict [] + |), "balance" |) + |) in + let _ := M.call (| + M.get_name (| globals, "set_account_balance" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "env" |), "state" |); + M.get_name (| globals, "beneficiary" |); + BinOp.add (| + M.get_name (| globals, "beneficiary_balance" |), + M.get_name (| globals, "originator_balance" |) + |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "set_account_balance" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "env" |), "state" |); + M.get_name (| globals, "originator" |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "accounts_to_delete" |), "add" |), + make_list [ + M.get_name (| globals, "originator" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, "account_exists_and_is_empty" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "env" |), "state" |); + M.get_name (| globals, "beneficiary" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "touched_accounts" |), "add" |), + make_list [ + M.get_name (| globals, "beneficiary" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, "evm" |), "running" |), + Constant.bool false + |) in + let _ := M.pass (| |) in + M.pure Constant.None_)). + +Definition delegatecall : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Message-call into an account. + + Parameters + ---------- + evm : + The current EVM frame. + " in + let _ := M.assign_local (| + "gas" , + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "code_address" , + M.call (| + M.get_name (| globals, "to_address" |), + make_list [ + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_input_start_position" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_input_size" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_output_start_position" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_output_size" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "extend_memory" , + M.call (| + M.get_name (| globals, "calculate_gas_extend_memory" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "memory" |); + make_list [ + make_tuple [ M.get_name (| globals, "memory_input_start_position" |); M.get_name (| globals, "memory_input_size" |) ]; + make_tuple [ M.get_name (| globals, "memory_output_start_position" |); M.get_name (| globals, "memory_output_size" |) ] + ] + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "message_call_gas" , + M.call (| + M.get_name (| globals, "calculate_message_call_gas" |), + make_list [ + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |); + M.get_name (| globals, "gas" |); + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "gas_left" |) + ], + make_dict [] + |); + M.get_field (| M.get_name (| globals, "extend_memory" |), "cost" |); + M.get_name (| globals, "GAS_CALL" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + BinOp.add (| + M.get_field (| M.get_name (| globals, "message_call_gas" |), "cost" |), + M.get_field (| M.get_name (| globals, "extend_memory" |), "cost" |) + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "memory" |), + BinOp.mult (| + Constant.bytes "00", + M.get_field (| M.get_name (| globals, "extend_memory" |), "expand_by" |) + |) + |) in + let _ := M.call (| + M.get_name (| globals, "generic_call" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_field (| M.get_name (| globals, "message_call_gas" |), "stipend" |); + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "value" |); + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "caller" |); + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "current_target" |); + M.get_name (| globals, "code_address" |); + Constant.bool false; + Constant.bool false; + M.get_name (| globals, "memory_input_start_position" |); + M.get_name (| globals, "memory_input_size" |); + M.get_name (| globals, "memory_output_start_position" |); + M.get_name (| globals, "memory_output_size" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition staticcall : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Message-call into an account. + + Parameters + ---------- + evm : + The current EVM frame. + " in + let _ := M.assign_local (| + "gas" , + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "to" , + M.call (| + M.get_name (| globals, "to_address" |), + make_list [ + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_input_start_position" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_input_size" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_output_start_position" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_output_size" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "extend_memory" , + M.call (| + M.get_name (| globals, "calculate_gas_extend_memory" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "memory" |); + make_list [ + make_tuple [ M.get_name (| globals, "memory_input_start_position" |); M.get_name (| globals, "memory_input_size" |) ]; + make_tuple [ M.get_name (| globals, "memory_output_start_position" |); M.get_name (| globals, "memory_output_size" |) ] + ] + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "message_call_gas" , + M.call (| + M.get_name (| globals, "calculate_message_call_gas" |), + make_list [ + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |); + M.get_name (| globals, "gas" |); + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "gas_left" |) + ], + make_dict [] + |); + M.get_field (| M.get_name (| globals, "extend_memory" |), "cost" |); + M.get_name (| globals, "GAS_CALL" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + BinOp.add (| + M.get_field (| M.get_name (| globals, "message_call_gas" |), "cost" |), + M.get_field (| M.get_name (| globals, "extend_memory" |), "cost" |) + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "memory" |), + BinOp.mult (| + Constant.bytes "00", + M.get_field (| M.get_name (| globals, "extend_memory" |), "expand_by" |) + |) + |) in + let _ := M.call (| + M.get_name (| globals, "generic_call" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_field (| M.get_name (| globals, "message_call_gas" |), "stipend" |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |); + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "current_target" |); + M.get_name (| globals, "to" |); + M.get_name (| globals, "to" |); + Constant.bool true; + Constant.bool true; + M.get_name (| globals, "memory_input_start_position" |); + M.get_name (| globals, "memory_input_size" |); + M.get_name (| globals, "memory_output_start_position" |); + M.get_name (| globals, "memory_output_size" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition revert : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Stop execution and revert state changes, without consuming all provided gas + and also has the ability to return a reason + Parameters + ---------- + evm : + The current EVM frame. + " in + let _ := M.assign_local (| + "memory_start_index" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "size" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "extend_memory" , + M.call (| + M.get_name (| globals, "calculate_gas_extend_memory" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "memory" |); + make_list [ + make_tuple [ M.get_name (| globals, "memory_start_index" |); M.get_name (| globals, "size" |) ] + ] + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_field (| M.get_name (| globals, "extend_memory" |), "cost" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "memory" |), + BinOp.mult (| + Constant.bytes "00", + M.get_field (| M.get_name (| globals, "extend_memory" |), "expand_by" |) + |) + |) in + let _ := M.assign_local (| + "output" , + M.call (| + M.get_name (| globals, "memory_read_bytes" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "memory" |); + M.get_name (| globals, "memory_start_index" |); + M.get_name (| globals, "size" |) + ], + make_dict [] + |) + |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, "evm" |), "output" |), + M.call (| + M.get_name (| globals, "bytes" |), + make_list [ + M.get_name (| globals, "output" |) + ], + make_dict [] + |) + |) in + let _ := M.raise (| Some (M.get_name (| globals, "Revert" |)) |) in + let _ := M.pass (| |) in + M.pure Constant.None_)). diff --git a/CoqOfPython/ethereum/constantinople/vm/interpreter.v b/CoqOfPython/ethereum/constantinople/vm/interpreter.v new file mode 100644 index 0000000..b589da7 --- /dev/null +++ b/CoqOfPython/ethereum/constantinople/vm/interpreter.v @@ -0,0 +1,657 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.constantinople.vm.interpreter". + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) Interpreter +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +A straightforward interpreter that executes EVM code. +". + +Axiom dataclasses_imports_dataclass : + IsImported globals "dataclasses" "dataclass". + +Axiom typing_imports_Iterable : + IsImported globals "typing" "Iterable". +Axiom typing_imports_Optional : + IsImported globals "typing" "Optional". +Axiom typing_imports_Set : + IsImported globals "typing" "Set". +Axiom typing_imports_Tuple : + IsImported globals "typing" "Tuple". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_Bytes0 : + IsImported globals "ethereum.base_types" "Bytes0". +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". + +Axiom ethereum_trace_imports_EvmStop : + IsImported globals "ethereum.trace" "EvmStop". +Axiom ethereum_trace_imports_OpEnd : + IsImported globals "ethereum.trace" "OpEnd". +Axiom ethereum_trace_imports_OpException : + IsImported globals "ethereum.trace" "OpException". +Axiom ethereum_trace_imports_OpStart : + IsImported globals "ethereum.trace" "OpStart". +Axiom ethereum_trace_imports_PrecompileEnd : + IsImported globals "ethereum.trace" "PrecompileEnd". +Axiom ethereum_trace_imports_PrecompileStart : + IsImported globals "ethereum.trace" "PrecompileStart". +Axiom ethereum_trace_imports_TransactionEnd : + IsImported globals "ethereum.trace" "TransactionEnd". +Axiom ethereum_trace_imports_evm_trace : + IsImported globals "ethereum.trace" "evm_trace". + +Axiom ethereum_utils_ensure_imports_ensure : + IsImported globals "ethereum.utils.ensure" "ensure". + +Axiom ethereum_constantinople_blocks_imports_Log : + IsImported globals "ethereum.constantinople.blocks" "Log". + +Axiom ethereum_constantinople_fork_types_imports_Address : + IsImported globals "ethereum.constantinople.fork_types" "Address". + +Axiom ethereum_constantinople_state_imports_account_exists_and_is_empty : + IsImported globals "ethereum.constantinople.state" "account_exists_and_is_empty". +Axiom ethereum_constantinople_state_imports_account_has_code_or_nonce : + IsImported globals "ethereum.constantinople.state" "account_has_code_or_nonce". +Axiom ethereum_constantinople_state_imports_begin_transaction : + IsImported globals "ethereum.constantinople.state" "begin_transaction". +Axiom ethereum_constantinople_state_imports_commit_transaction : + IsImported globals "ethereum.constantinople.state" "commit_transaction". +Axiom ethereum_constantinople_state_imports_destroy_storage : + IsImported globals "ethereum.constantinople.state" "destroy_storage". +Axiom ethereum_constantinople_state_imports_increment_nonce : + IsImported globals "ethereum.constantinople.state" "increment_nonce". +Axiom ethereum_constantinople_state_imports_move_ether : + IsImported globals "ethereum.constantinople.state" "move_ether". +Axiom ethereum_constantinople_state_imports_rollback_transaction : + IsImported globals "ethereum.constantinople.state" "rollback_transaction". +Axiom ethereum_constantinople_state_imports_set_code : + IsImported globals "ethereum.constantinople.state" "set_code". +Axiom ethereum_constantinople_state_imports_touch_account : + IsImported globals "ethereum.constantinople.state" "touch_account". + +Axiom ethereum_constantinople_vm_imports_Message : + IsImported globals "ethereum.constantinople.vm" "Message". + +Axiom ethereum_constantinople_vm_gas_imports_GAS_CODE_DEPOSIT : + IsImported globals "ethereum.constantinople.vm.gas" "GAS_CODE_DEPOSIT". +Axiom ethereum_constantinople_vm_gas_imports_charge_gas : + IsImported globals "ethereum.constantinople.vm.gas" "charge_gas". + +Axiom ethereum_constantinople_vm_precompiled_contracts_mapping_imports_PRE_COMPILED_CONTRACTS : + IsImported globals "ethereum.constantinople.vm.precompiled_contracts.mapping" "PRE_COMPILED_CONTRACTS". + +Axiom ethereum_constantinople_vm_imports_Environment : + IsImported globals "ethereum.constantinople.vm" "Environment". +Axiom ethereum_constantinople_vm_imports_Evm : + IsImported globals "ethereum.constantinople.vm" "Evm". + +Axiom ethereum_constantinople_vm_exceptions_imports_AddressCollision : + IsImported globals "ethereum.constantinople.vm.exceptions" "AddressCollision". +Axiom ethereum_constantinople_vm_exceptions_imports_ExceptionalHalt : + IsImported globals "ethereum.constantinople.vm.exceptions" "ExceptionalHalt". +Axiom ethereum_constantinople_vm_exceptions_imports_InvalidOpcode : + IsImported globals "ethereum.constantinople.vm.exceptions" "InvalidOpcode". +Axiom ethereum_constantinople_vm_exceptions_imports_OutOfGasError : + IsImported globals "ethereum.constantinople.vm.exceptions" "OutOfGasError". +Axiom ethereum_constantinople_vm_exceptions_imports_Revert : + IsImported globals "ethereum.constantinople.vm.exceptions" "Revert". +Axiom ethereum_constantinople_vm_exceptions_imports_StackDepthLimitError : + IsImported globals "ethereum.constantinople.vm.exceptions" "StackDepthLimitError". + +Axiom ethereum_constantinople_vm_instructions_imports_Ops : + IsImported globals "ethereum.constantinople.vm.instructions" "Ops". +Axiom ethereum_constantinople_vm_instructions_imports_op_implementation : + IsImported globals "ethereum.constantinople.vm.instructions" "op_implementation". + +Axiom ethereum_constantinople_vm_runtime_imports_get_valid_jump_destinations : + IsImported globals "ethereum.constantinople.vm.runtime" "get_valid_jump_destinations". + +Definition STACK_DEPTH_LIMIT : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 1024 + ], + make_dict [] + |) +)). + +Definition MAX_CODE_SIZE : Value.t := M.run ltac:(M.monadic ( + Constant.int 24576 +)). + +Definition MessageCallOutput : Value.t := + builtins.make_klass + [] + [ + + ] + [ + + ]. + +Definition process_message_call : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "message"; "env" ] |) in + let _ := Constant.str " + If `message.current` is empty then it creates a smart contract + else it executes a call from the `message.caller` to the `message.target`. + + Parameters + ---------- + message : + Transaction specific items. + + env : + External items required for EVM execution. + + Returns + ------- + output : `MessageCallOutput` + Output of the message call + " in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_field (| M.get_name (| globals, "message" |), "target" |), + M.call (| + M.get_name (| globals, "Bytes0" |), + make_list [ + Constant.bytes "" + ], + make_dict [] + |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "is_collision" , + M.call (| + M.get_name (| globals, "account_has_code_or_nonce" |), + make_list [ + M.get_field (| M.get_name (| globals, "env" |), "state" |); + M.get_field (| M.get_name (| globals, "message" |), "current_target" |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + M.get_name (| globals, "is_collision" |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + M.call (| + M.get_name (| globals, "MessageCallOutput" |), + make_list [ + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |); + M.call (| + M.get_name (| globals, "tuple" |), + make_list [], + make_dict [] + |); + M.call (| + M.get_name (| globals, "set" |), + make_list [], + make_dict [] + |); + M.call (| + M.get_name (| globals, "set" |), + make_list [], + make_dict [] + |); + M.call (| + M.get_name (| globals, "AddressCollision" |), + make_list [], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "evm" , + M.call (| + M.get_name (| globals, "process_create_message" |), + make_list [ + M.get_name (| globals, "message" |); + M.get_name (| globals, "env" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "evm" , + M.call (| + M.get_name (| globals, "process_message" |), + make_list [ + M.get_name (| globals, "message" |); + M.get_name (| globals, "env" |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, "account_exists_and_is_empty" |), + make_list [ + M.get_field (| M.get_name (| globals, "env" |), "state" |); + M.call (| + M.get_name (| globals, "Address" |), + make_list [ + M.get_field (| M.get_name (| globals, "message" |), "target" |) + ], + make_dict [] + |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "touched_accounts" |), "add" |), + make_list [ + M.call (| + M.get_name (| globals, "Address" |), + make_list [ + M.get_field (| M.get_name (| globals, "message" |), "target" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + M.get_field (| M.get_name (| globals, "evm" |), "error" |), + (* then *) + ltac:(M.monadic ( +(* At stmt: unsupported node type: AnnAssign *) + let _ := M.assign_local (| + "accounts_to_delete" , + M.call (| + M.get_name (| globals, "set" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "touched_accounts" , + M.call (| + M.get_name (| globals, "set" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "refund_counter" , + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "logs" , + M.get_field (| M.get_name (| globals, "evm" |), "logs" |) + |) in + let _ := M.assign_local (| + "accounts_to_delete" , + M.get_field (| M.get_name (| globals, "evm" |), "accounts_to_delete" |) + |) in + let _ := M.assign_local (| + "touched_accounts" , + M.get_field (| M.get_name (| globals, "evm" |), "touched_accounts" |) + |) in + let _ := M.assign_local (| + "refund_counter" , + M.get_field (| M.get_name (| globals, "evm" |), "refund_counter" |) + |) in + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "tx_end" , + M.call (| + M.get_name (| globals, "TransactionEnd" |), + make_list [ + BinOp.sub (| + M.get_field (| M.get_name (| globals, "message" |), "gas" |), + M.get_field (| M.get_name (| globals, "evm" |), "gas_left" |) + |); + M.get_field (| M.get_name (| globals, "evm" |), "output" |); + M.get_field (| M.get_name (| globals, "evm" |), "error" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "evm_trace" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "tx_end" |) + ], + make_dict [] + |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, "MessageCallOutput" |), + make_list [], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Definition process_create_message : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "message"; "env" ] |) in + let _ := Constant.str " + Executes a call to create a smart contract. + + Parameters + ---------- + message : + Transaction specific items. + env : + External items required for EVM execution. + + Returns + ------- + evm: :py:class:`~ethereum.constantinople.vm.Evm` + Items containing execution specific objects. + " in + let _ := M.call (| + M.get_name (| globals, "begin_transaction" |), + make_list [ + M.get_field (| M.get_name (| globals, "env" |), "state" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "destroy_storage" |), + make_list [ + M.get_field (| M.get_name (| globals, "env" |), "state" |); + M.get_field (| M.get_name (| globals, "message" |), "current_target" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "increment_nonce" |), + make_list [ + M.get_field (| M.get_name (| globals, "env" |), "state" |); + M.get_field (| M.get_name (| globals, "message" |), "current_target" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "evm" , + M.call (| + M.get_name (| globals, "process_message" |), + make_list [ + M.get_name (| globals, "message" |); + M.get_name (| globals, "env" |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + UnOp.not (| M.get_field (| M.get_name (| globals, "evm" |), "error" |) |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "contract_code" , + M.get_field (| M.get_name (| globals, "evm" |), "output" |) + |) in + let _ := M.assign_local (| + "contract_code_gas" , + BinOp.mult (| + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_name (| globals, "contract_code" |) + ], + make_dict [] + |), + M.get_name (| globals, "GAS_CODE_DEPOSIT" |) + |) + |) in +(* At stmt: unsupported node type: Try *) + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, "rollback_transaction" |), + make_list [ + M.get_field (| M.get_name (| globals, "env" |), "state" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + )) |) in + let _ := M.return_ (| + M.get_name (| globals, "evm" |) + |) in + M.pure Constant.None_)). + +Definition process_message : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "message"; "env" ] |) in + let _ := Constant.str " + Executes a call to create a smart contract. + + Parameters + ---------- + message : + Transaction specific items. + env : + External items required for EVM execution. + + Returns + ------- + evm: :py:class:`~ethereum.constantinople.vm.Evm` + Items containing execution specific objects + " in + let _ := + (* if *) + M.if_then_else (| + Compare.gt (| + M.get_field (| M.get_name (| globals, "message" |), "depth" |), + M.get_name (| globals, "STACK_DEPTH_LIMIT" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.call (| + M.get_name (| globals, "StackDepthLimitError" |), + make_list [ + Constant.str "Stack depth limit reached" + ], + make_dict [] + |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.call (| + M.get_name (| globals, "begin_transaction" |), + make_list [ + M.get_field (| M.get_name (| globals, "env" |), "state" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "touch_account" |), + make_list [ + M.get_field (| M.get_name (| globals, "env" |), "state" |); + M.get_field (| M.get_name (| globals, "message" |), "current_target" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + BoolOp.and (| + M.get_field (| M.get_name (| globals, "message" |), "should_transfer_value" |), + ltac:(M.monadic ( + Compare.not_eq (| + M.get_field (| M.get_name (| globals, "message" |), "value" |), + Constant.int 0 + |) + )) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, "move_ether" |), + make_list [ + M.get_field (| M.get_name (| globals, "env" |), "state" |); + M.get_field (| M.get_name (| globals, "message" |), "caller" |); + M.get_field (| M.get_name (| globals, "message" |), "current_target" |); + M.get_field (| M.get_name (| globals, "message" |), "value" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "evm" , + M.call (| + M.get_name (| globals, "execute_code" |), + make_list [ + M.get_name (| globals, "message" |); + M.get_name (| globals, "env" |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + M.get_field (| M.get_name (| globals, "evm" |), "error" |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, "rollback_transaction" |), + make_list [ + M.get_field (| M.get_name (| globals, "env" |), "state" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, "commit_transaction" |), + make_list [ + M.get_field (| M.get_name (| globals, "env" |), "state" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + )) |) in + let _ := M.return_ (| + M.get_name (| globals, "evm" |) + |) in + M.pure Constant.None_)). + +Definition execute_code : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "message"; "env" ] |) in + let _ := Constant.str " + Executes bytecode present in the `message`. + + Parameters + ---------- + message : + Transaction specific items. + env : + External items required for EVM execution. + + Returns + ------- + evm: `ethereum.vm.EVM` + Items containing execution specific objects + " in + let _ := M.assign_local (| + "code" , + M.get_field (| M.get_name (| globals, "message" |), "code" |) + |) in + let _ := M.assign_local (| + "valid_jump_destinations" , + M.call (| + M.get_name (| globals, "get_valid_jump_destinations" |), + make_list [ + M.get_name (| globals, "code" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "evm" , + M.call (| + M.get_name (| globals, "Evm" |), + make_list [], + make_dict [] + |) + |) in +(* At stmt: unsupported node type: Try *) + let _ := M.return_ (| + M.get_name (| globals, "evm" |) + |) in + M.pure Constant.None_)). diff --git a/CoqOfPython/ethereum/constantinople/vm/memory.v b/CoqOfPython/ethereum/constantinople/vm/memory.v new file mode 100644 index 0000000..f8c1898 --- /dev/null +++ b/CoqOfPython/ethereum/constantinople/vm/memory.v @@ -0,0 +1,166 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.constantinople.vm.memory". + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) Memory +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +EVM memory operations. +". + +Axiom ethereum_utils_byte_imports_right_pad_zero_bytes : + IsImported globals "ethereum.utils.byte" "right_pad_zero_bytes". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_Bytes : + IsImported globals "ethereum.base_types" "Bytes". +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". + +Definition memory_write : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "memory"; "start_position"; "value" ] |) in + let _ := Constant.str " + Writes to memory. + + Parameters + ---------- + memory : + Memory contents of the EVM. + start_position : + Starting pointer to the memory. + value : + Data to write to memory. + " in + let _ := M.assign (| + M.slice (| + M.get_name (| globals, "memory" |), + M.get_name (| globals, "start_position" |), + BinOp.add (| + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.get_name (| globals, "start_position" |) + ], + make_dict [] + |), + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_name (| globals, "value" |) + ], + make_dict [] + |) + |), + Constant.None_ + |), + M.get_name (| globals, "value" |) + |) in + M.pure Constant.None_)). + +Definition memory_read_bytes : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "memory"; "start_position"; "size" ] |) in + let _ := Constant.str " + Read bytes from memory. + + Parameters + ---------- + memory : + Memory contents of the EVM. + start_position : + Starting pointer to the memory. + size : + Size of the data that needs to be read from `start_position`. + + Returns + ------- + data_bytes : + Data read from memory. + " in + let _ := M.return_ (| + M.slice (| + M.get_name (| globals, "memory" |), + M.get_name (| globals, "start_position" |), + BinOp.add (| + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.get_name (| globals, "start_position" |) + ], + make_dict [] + |), + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.get_name (| globals, "size" |) + ], + make_dict [] + |) + |), + Constant.None_ + |) + |) in + M.pure Constant.None_)). + +Definition buffer_read : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "buffer"; "start_position"; "size" ] |) in + let _ := Constant.str " + Read bytes from a buffer. Padding with zeros if necessary. + + Parameters + ---------- + buffer : + Memory contents of the EVM. + start_position : + Starting pointer to the memory. + size : + Size of the data that needs to be read from `start_position`. + + Returns + ------- + data_bytes : + Data read from memory. + " in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, "right_pad_zero_bytes" |), + make_list [ + M.slice (| + M.get_name (| globals, "buffer" |), + M.get_name (| globals, "start_position" |), + BinOp.add (| + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.get_name (| globals, "start_position" |) + ], + make_dict [] + |), + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.get_name (| globals, "size" |) + ], + make_dict [] + |) + |), + Constant.None_ + |); + M.get_name (| globals, "size" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). diff --git a/CoqOfPython/ethereum/constantinople/vm/precompiled_contracts/__init__.v b/CoqOfPython/ethereum/constantinople/vm/precompiled_contracts/__init__.v new file mode 100644 index 0000000..028d559 --- /dev/null +++ b/CoqOfPython/ethereum/constantinople/vm/precompiled_contracts/__init__.v @@ -0,0 +1,106 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.constantinople.vm.precompiled_contracts.__init__". + +Definition expr_1 : Value.t := + Constant.str " +Precompiled Contract Addresses +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Addresses of precompiled contracts and mappings to their +implementations. +". + +Axiom ethereum_constantinople_utils_hexadecimal_imports_hex_to_address : + IsImported globals "ethereum.constantinople.utils.hexadecimal" "hex_to_address". + +Definition __all__ : Value.t := M.run ltac:(M.monadic ( + make_tuple [ Constant.str "ECRECOVER_ADDRESS"; Constant.str "SHA256_ADDRESS"; Constant.str "RIPEMD160_ADDRESS"; Constant.str "IDENTITY_ADDRESS"; Constant.str "MODEXP_ADDRESS"; Constant.str "ALT_BN128_ADD_ADDRESS"; Constant.str "ALT_BN128_MUL_ADDRESS"; Constant.str "ALT_BN128_PAIRING_CHECK_ADDRESS"; Constant.str "BLAKE2F_ADDRESS" ] +)). + +Definition ECRECOVER_ADDRESS : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "hex_to_address" |), + make_list [ + Constant.str "0x01" + ], + make_dict [] + |) +)). + +Definition SHA256_ADDRESS : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "hex_to_address" |), + make_list [ + Constant.str "0x02" + ], + make_dict [] + |) +)). + +Definition RIPEMD160_ADDRESS : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "hex_to_address" |), + make_list [ + Constant.str "0x03" + ], + make_dict [] + |) +)). + +Definition IDENTITY_ADDRESS : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "hex_to_address" |), + make_list [ + Constant.str "0x04" + ], + make_dict [] + |) +)). + +Definition MODEXP_ADDRESS : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "hex_to_address" |), + make_list [ + Constant.str "0x05" + ], + make_dict [] + |) +)). + +Definition ALT_BN128_ADD_ADDRESS : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "hex_to_address" |), + make_list [ + Constant.str "0x06" + ], + make_dict [] + |) +)). + +Definition ALT_BN128_MUL_ADDRESS : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "hex_to_address" |), + make_list [ + Constant.str "0x07" + ], + make_dict [] + |) +)). + +Definition ALT_BN128_PAIRING_CHECK_ADDRESS : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "hex_to_address" |), + make_list [ + Constant.str "0x08" + ], + make_dict [] + |) +)). diff --git a/CoqOfPython/ethereum/constantinople/vm/precompiled_contracts/alt_bn128.v b/CoqOfPython/ethereum/constantinople/vm/precompiled_contracts/alt_bn128.v new file mode 100644 index 0000000..35d5ffd --- /dev/null +++ b/CoqOfPython/ethereum/constantinople/vm/precompiled_contracts/alt_bn128.v @@ -0,0 +1,778 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.constantinople.vm.precompiled_contracts.alt_bn128". + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) ALT_BN128 CONTRACTS +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementation of the ALT_BN128 precompiled contracts. +". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". + +Axiom ethereum_crypto_alt_bn128_imports_ALT_BN128_CURVE_ORDER : + IsImported globals "ethereum.crypto.alt_bn128" "ALT_BN128_CURVE_ORDER". +Axiom ethereum_crypto_alt_bn128_imports_ALT_BN128_PRIME : + IsImported globals "ethereum.crypto.alt_bn128" "ALT_BN128_PRIME". +Axiom ethereum_crypto_alt_bn128_imports_BNF : + IsImported globals "ethereum.crypto.alt_bn128" "BNF". +Axiom ethereum_crypto_alt_bn128_imports_BNF2 : + IsImported globals "ethereum.crypto.alt_bn128" "BNF2". +Axiom ethereum_crypto_alt_bn128_imports_BNF12 : + IsImported globals "ethereum.crypto.alt_bn128" "BNF12". +Axiom ethereum_crypto_alt_bn128_imports_BNP : + IsImported globals "ethereum.crypto.alt_bn128" "BNP". +Axiom ethereum_crypto_alt_bn128_imports_BNP2 : + IsImported globals "ethereum.crypto.alt_bn128" "BNP2". +Axiom ethereum_crypto_alt_bn128_imports_pairing : + IsImported globals "ethereum.crypto.alt_bn128" "pairing". + +Axiom ethereum_utils_ensure_imports_ensure : + IsImported globals "ethereum.utils.ensure" "ensure". + +Axiom ethereum_constantinople_vm_imports_Evm : + IsImported globals "ethereum.constantinople.vm" "Evm". + +Axiom ethereum_constantinople_vm_gas_imports_charge_gas : + IsImported globals "ethereum.constantinople.vm.gas" "charge_gas". + +Axiom ethereum_constantinople_vm_memory_imports_buffer_read : + IsImported globals "ethereum.constantinople.vm.memory" "buffer_read". + +Axiom ethereum_constantinople_vm_exceptions_imports_OutOfGasError : + IsImported globals "ethereum.constantinople.vm.exceptions" "OutOfGasError". + +Definition alt_bn128_add : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + The ALT_BN128 addition precompiled contract. + + Parameters + ---------- + evm : + The current EVM frame. + " in + let _ := M.assign_local (| + "data" , + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "data" |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 500 + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "x0_bytes" , + M.call (| + M.get_name (| globals, "buffer_read" |), + make_list [ + M.get_name (| globals, "data" |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 32 + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "x0_value" , + M.call (| + M.get_field (| M.get_name (| globals, "U256" |), "from_be_bytes" |), + make_list [ + M.get_name (| globals, "x0_bytes" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "y0_bytes" , + M.call (| + M.get_name (| globals, "buffer_read" |), + make_list [ + M.get_name (| globals, "data" |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 32 + ], + make_dict [] + |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 32 + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "y0_value" , + M.call (| + M.get_field (| M.get_name (| globals, "U256" |), "from_be_bytes" |), + make_list [ + M.get_name (| globals, "y0_bytes" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "x1_bytes" , + M.call (| + M.get_name (| globals, "buffer_read" |), + make_list [ + M.get_name (| globals, "data" |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 64 + ], + make_dict [] + |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 32 + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "x1_value" , + M.call (| + M.get_field (| M.get_name (| globals, "U256" |), "from_be_bytes" |), + make_list [ + M.get_name (| globals, "x1_bytes" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "y1_bytes" , + M.call (| + M.get_name (| globals, "buffer_read" |), + make_list [ + M.get_name (| globals, "data" |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 96 + ], + make_dict [] + |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 32 + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "y1_value" , + M.call (| + M.get_field (| M.get_name (| globals, "U256" |), "from_be_bytes" |), + make_list [ + M.get_name (| globals, "y1_bytes" |) + ], + make_dict [] + |) + |) in + let _ := + M.for_ (| + M.get_name (| globals, "i" |), + make_tuple [ M.get_name (| globals, "x0_value" |); M.get_name (| globals, "y0_value" |); M.get_name (| globals, "x1_value" |); M.get_name (| globals, "y1_value" |) ], + ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + Compare.gt_e (| + M.get_name (| globals, "i" |), + M.get_name (| globals, "ALT_BN128_PRIME" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, "OutOfGasError" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in +(* At stmt: unsupported node type: Try *) + let _ := M.assign_local (| + "p" , + BinOp.add (| + M.get_name (| globals, "p0" |), + M.get_name (| globals, "p1" |) + |) + |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, "evm" |), "output" |), + BinOp.add (| + M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, "p" |), "x" |), "to_be_bytes32" |), + make_list [], + make_dict [] + |), + M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, "p" |), "y" |), "to_be_bytes32" |), + make_list [], + make_dict [] + |) + |) + |) in + M.pure Constant.None_)). + +Definition alt_bn128_mul : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + The ALT_BN128 multiplication precompiled contract. + + Parameters + ---------- + evm : + The current EVM frame. + " in + let _ := M.assign_local (| + "data" , + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "data" |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 40000 + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "x0_bytes" , + M.call (| + M.get_name (| globals, "buffer_read" |), + make_list [ + M.get_name (| globals, "data" |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 32 + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "x0_value" , + M.call (| + M.get_field (| M.get_name (| globals, "U256" |), "from_be_bytes" |), + make_list [ + M.get_name (| globals, "x0_bytes" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "y0_bytes" , + M.call (| + M.get_name (| globals, "buffer_read" |), + make_list [ + M.get_name (| globals, "data" |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 32 + ], + make_dict [] + |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 32 + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "y0_value" , + M.call (| + M.get_field (| M.get_name (| globals, "U256" |), "from_be_bytes" |), + make_list [ + M.get_name (| globals, "y0_bytes" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "n" , + M.call (| + M.get_field (| M.get_name (| globals, "U256" |), "from_be_bytes" |), + make_list [ + M.call (| + M.get_name (| globals, "buffer_read" |), + make_list [ + M.get_name (| globals, "data" |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 64 + ], + make_dict [] + |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 32 + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := + M.for_ (| + M.get_name (| globals, "i" |), + make_tuple [ M.get_name (| globals, "x0_value" |); M.get_name (| globals, "y0_value" |) ], + ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + Compare.gt_e (| + M.get_name (| globals, "i" |), + M.get_name (| globals, "ALT_BN128_PRIME" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, "OutOfGasError" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in +(* At stmt: unsupported node type: Try *) + let _ := M.assign_local (| + "p" , + M.call (| + M.get_field (| M.get_name (| globals, "p0" |), "mul_by" |), + make_list [ + M.get_name (| globals, "n" |) + ], + make_dict [] + |) + |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, "evm" |), "output" |), + BinOp.add (| + M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, "p" |), "x" |), "to_be_bytes32" |), + make_list [], + make_dict [] + |), + M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, "p" |), "y" |), "to_be_bytes32" |), + make_list [], + make_dict [] + |) + |) + |) in + M.pure Constant.None_)). + +Definition alt_bn128_pairing_check : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + The ALT_BN128 pairing check precompiled contract. + + Parameters + ---------- + evm : + The current EVM frame. + " in + let _ := M.assign_local (| + "data" , + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "data" |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + BinOp.add (| + BinOp.mult (| + Constant.int 80000, + BinOp.floor_div (| + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_name (| globals, "data" |) + ], + make_dict [] + |), + Constant.int 192 + |) + |), + Constant.int 100000 + |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.not_eq (| + BinOp.mod_ (| + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_name (| globals, "data" |) + ], + make_dict [] + |), + Constant.int 192 + |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, "OutOfGasError" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "result" , + M.call (| + M.get_field (| M.get_name (| globals, "BNF12" |), "from_int" |), + make_list [ + Constant.int 1 + ], + make_dict [] + |) + |) in + let _ := + M.for_ (| + M.get_name (| globals, "i" |), + M.call (| + M.get_name (| globals, "range" |), + make_list [ + BinOp.floor_div (| + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_name (| globals, "data" |) + ], + make_dict [] + |), + Constant.int 192 + |) + ], + make_dict [] + |), + ltac:(M.monadic ( + let _ := M.assign_local (| + "values" , + make_list [] + |) in + let _ := + M.for_ (| + M.get_name (| globals, "j" |), + M.call (| + M.get_name (| globals, "range" |), + make_list [ + Constant.int 6 + ], + make_dict [] + |), + ltac:(M.monadic ( + let _ := M.assign_local (| + "value" , + M.call (| + M.get_field (| M.get_name (| globals, "U256" |), "from_be_bytes" |), + make_list [ + M.slice (| + M.get_name (| globals, "data" |), + BinOp.add (| + BinOp.mult (| + M.get_name (| globals, "i" |), + Constant.int 192 + |), + BinOp.mult (| + Constant.int 32, + M.get_name (| globals, "j" |) + |) + |), + BinOp.add (| + BinOp.mult (| + M.get_name (| globals, "i" |), + Constant.int 192 + |), + BinOp.mult (| + Constant.int 32, + BinOp.add (| + M.get_name (| globals, "j" |), + Constant.int 1 + |) + |) + |), + Constant.None_ + |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.gt_e (| + M.get_name (| globals, "value" |), + M.get_name (| globals, "ALT_BN128_PRIME" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, "OutOfGasError" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.call (| + M.get_field (| M.get_name (| globals, "values" |), "append" |), + make_list [ + M.call (| + M.get_name (| globals, "int" |), + make_list [ + M.get_name (| globals, "value" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in +(* At stmt: unsupported node type: Try *) + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + Compare.eq (| + M.call (| + M.get_field (| M.get_name (| globals, "p" |), "mul_by" |), + make_list [ + M.get_name (| globals, "ALT_BN128_CURVE_ORDER" |) + ], + make_dict [] + |), + M.call (| + M.get_field (| M.get_name (| globals, "BNP" |), "point_at_infinity" |), + make_list [], + make_dict [] + |) + |); + M.get_name (| globals, "OutOfGasError" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + Compare.eq (| + M.call (| + M.get_field (| M.get_name (| globals, "q" |), "mul_by" |), + make_list [ + M.get_name (| globals, "ALT_BN128_CURVE_ORDER" |) + ], + make_dict [] + |), + M.call (| + M.get_field (| M.get_name (| globals, "BNP2" |), "point_at_infinity" |), + make_list [], + make_dict [] + |) + |); + M.get_name (| globals, "OutOfGasError" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + BoolOp.and (| + Compare.not_eq (| + M.get_name (| globals, "p" |), + M.call (| + M.get_field (| M.get_name (| globals, "BNP" |), "point_at_infinity" |), + make_list [], + make_dict [] + |) + |), + ltac:(M.monadic ( + Compare.not_eq (| + M.get_name (| globals, "q" |), + M.call (| + M.get_field (| M.get_name (| globals, "BNP2" |), "point_at_infinity" |), + make_list [], + make_dict [] + |) + |) + )) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "result" , + BinOp.mult (| + M.get_name (| globals, "result" |), + M.call (| + M.get_name (| globals, "pairing" |), + make_list [ + M.get_name (| globals, "q" |); + M.get_name (| globals, "p" |) + ], + make_dict [] + |) + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, "result" |), + M.call (| + M.get_field (| M.get_name (| globals, "BNF12" |), "from_int" |), + make_list [ + Constant.int 1 + ], + make_dict [] + |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign (| + M.get_field (| M.get_name (| globals, "evm" |), "output" |), + M.call (| + M.get_field (| M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 1 + ], + make_dict [] + |), "to_be_bytes32" |), + make_list [], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign (| + M.get_field (| M.get_name (| globals, "evm" |), "output" |), + M.call (| + M.get_field (| M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |), "to_be_bytes32" |), + make_list [], + make_dict [] + |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_)). diff --git a/CoqOfPython/ethereum/constantinople/vm/precompiled_contracts/ecrecover.v b/CoqOfPython/ethereum/constantinople/vm/precompiled_contracts/ecrecover.v new file mode 100644 index 0000000..3738033 --- /dev/null +++ b/CoqOfPython/ethereum/constantinople/vm/precompiled_contracts/ecrecover.v @@ -0,0 +1,301 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.constantinople.vm.precompiled_contracts.ecrecover". + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) ECRECOVER PRECOMPILED CONTRACT +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementation of the ECRECOVER precompiled contract. +". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". + +Axiom ethereum_crypto_elliptic_curve_imports_SECP256K1N : + IsImported globals "ethereum.crypto.elliptic_curve" "SECP256K1N". +Axiom ethereum_crypto_elliptic_curve_imports_secp256k1_recover : + IsImported globals "ethereum.crypto.elliptic_curve" "secp256k1_recover". + +Axiom ethereum_crypto_hash_imports_Hash32 : + IsImported globals "ethereum.crypto.hash" "Hash32". +Axiom ethereum_crypto_hash_imports_keccak256 : + IsImported globals "ethereum.crypto.hash" "keccak256". + +Axiom ethereum_utils_byte_imports_left_pad_zero_bytes : + IsImported globals "ethereum.utils.byte" "left_pad_zero_bytes". + +Axiom ethereum_constantinople_vm_imports_Evm : + IsImported globals "ethereum.constantinople.vm" "Evm". + +Axiom ethereum_constantinople_vm_gas_imports_GAS_ECRECOVER : + IsImported globals "ethereum.constantinople.vm.gas" "GAS_ECRECOVER". +Axiom ethereum_constantinople_vm_gas_imports_charge_gas : + IsImported globals "ethereum.constantinople.vm.gas" "charge_gas". + +Axiom ethereum_constantinople_vm_memory_imports_buffer_read : + IsImported globals "ethereum.constantinople.vm.memory" "buffer_read". + +Definition ecrecover : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Decrypts the address using elliptic curve DSA recovery mechanism and writes + the address to output. + + Parameters + ---------- + evm : + The current EVM frame. + " in + let _ := M.assign_local (| + "data" , + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "data" |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_ECRECOVER" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "message_hash_bytes" , + M.call (| + M.get_name (| globals, "buffer_read" |), + make_list [ + M.get_name (| globals, "data" |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 32 + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "message_hash" , + M.call (| + M.get_name (| globals, "Hash32" |), + make_list [ + M.get_name (| globals, "message_hash_bytes" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "v" , + M.call (| + M.get_field (| M.get_name (| globals, "U256" |), "from_be_bytes" |), + make_list [ + M.call (| + M.get_name (| globals, "buffer_read" |), + make_list [ + M.get_name (| globals, "data" |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 32 + ], + make_dict [] + |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 32 + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "r" , + M.call (| + M.get_field (| M.get_name (| globals, "U256" |), "from_be_bytes" |), + make_list [ + M.call (| + M.get_name (| globals, "buffer_read" |), + make_list [ + M.get_name (| globals, "data" |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 64 + ], + make_dict [] + |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 32 + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "s" , + M.call (| + M.get_field (| M.get_name (| globals, "U256" |), "from_be_bytes" |), + make_list [ + M.call (| + M.get_name (| globals, "buffer_read" |), + make_list [ + M.get_name (| globals, "data" |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 96 + ], + make_dict [] + |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 32 + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + BoolOp.and (| + Compare.not_eq (| + M.get_name (| globals, "v" |), + Constant.int 27 + |), + ltac:(M.monadic ( + Compare.not_eq (| + M.get_name (| globals, "v" |), + Constant.int 28 + |) + )) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + Constant.None_ + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + BoolOp.or (| + Compare.gt_e (| + Constant.int 0, + M.get_name (| globals, "r" |) + |), + ltac:(M.monadic ( + Compare.gt_e (| + M.get_name (| globals, "r" |), + M.get_name (| globals, "SECP256K1N" |) + |) + )) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + Constant.None_ + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + BoolOp.or (| + Compare.gt_e (| + Constant.int 0, + M.get_name (| globals, "s" |) + |), + ltac:(M.monadic ( + Compare.gt_e (| + M.get_name (| globals, "s" |), + M.get_name (| globals, "SECP256K1N" |) + |) + )) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + Constant.None_ + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in +(* At stmt: unsupported node type: Try *) + let _ := M.assign_local (| + "address" , + M.slice (| + M.call (| + M.get_name (| globals, "keccak256" |), + make_list [ + M.get_name (| globals, "public_key" |) + ], + make_dict [] + |), + Constant.int 12, + Constant.int 32, + Constant.None_ + |) + |) in + let _ := M.assign_local (| + "padded_address" , + M.call (| + M.get_name (| globals, "left_pad_zero_bytes" |), + make_list [ + M.get_name (| globals, "address" |); + Constant.int 32 + ], + make_dict [] + |) + |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, "evm" |), "output" |), + M.get_name (| globals, "padded_address" |) + |) in + M.pure Constant.None_)). diff --git a/CoqOfPython/ethereum/constantinople/vm/precompiled_contracts/identity.v b/CoqOfPython/ethereum/constantinople/vm/precompiled_contracts/identity.v new file mode 100644 index 0000000..f7e428a --- /dev/null +++ b/CoqOfPython/ethereum/constantinople/vm/precompiled_contracts/identity.v @@ -0,0 +1,94 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.constantinople.vm.precompiled_contracts.identity". + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) IDENTITY PRECOMPILED CONTRACT +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementation of the `IDENTITY` precompiled contract. +". + +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". + +Axiom ethereum_utils_numeric_imports_ceil32 : + IsImported globals "ethereum.utils.numeric" "ceil32". + +Axiom ethereum_constantinople_vm_imports_Evm : + IsImported globals "ethereum.constantinople.vm" "Evm". + +Axiom ethereum_constantinople_vm_gas_imports_GAS_IDENTITY : + IsImported globals "ethereum.constantinople.vm.gas" "GAS_IDENTITY". +Axiom ethereum_constantinople_vm_gas_imports_GAS_IDENTITY_WORD : + IsImported globals "ethereum.constantinople.vm.gas" "GAS_IDENTITY_WORD". +Axiom ethereum_constantinople_vm_gas_imports_charge_gas : + IsImported globals "ethereum.constantinople.vm.gas" "charge_gas". + +Definition identity : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Writes the message data to output. + + Parameters + ---------- + evm : + The current EVM frame. + " in + let _ := M.assign_local (| + "data" , + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "data" |) + |) in + let _ := M.assign_local (| + "word_count" , + BinOp.floor_div (| + M.call (| + M.get_name (| globals, "ceil32" |), + make_list [ + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_name (| globals, "data" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |), + Constant.int 32 + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + BinOp.add (| + M.get_name (| globals, "GAS_IDENTITY" |), + BinOp.mult (| + M.get_name (| globals, "GAS_IDENTITY_WORD" |), + M.get_name (| globals, "word_count" |) + |) + |) + ], + make_dict [] + |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, "evm" |), "output" |), + M.get_name (| globals, "data" |) + |) in + M.pure Constant.None_)). diff --git a/CoqOfPython/ethereum/constantinople/vm/precompiled_contracts/mapping.v b/CoqOfPython/ethereum/constantinople/vm/precompiled_contracts/mapping.v new file mode 100644 index 0000000..90f0895 --- /dev/null +++ b/CoqOfPython/ethereum/constantinople/vm/precompiled_contracts/mapping.v @@ -0,0 +1,67 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.constantinople.vm.precompiled_contracts.mapping". + +Definition expr_1 : Value.t := + Constant.str " +Precompiled Contract Addresses +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Mapping of precompiled contracts their implementations. +". + +Axiom typing_imports_Callable : + IsImported globals "typing" "Callable". +Axiom typing_imports_Dict : + IsImported globals "typing" "Dict". + +Axiom ethereum_constantinople_fork_types_imports_Address : + IsImported globals "ethereum.constantinople.fork_types" "Address". + +Axiom ethereum_constantinople_vm_precompiled_contracts_imports_ALT_BN128_ADD_ADDRESS : + IsImported globals "ethereum.constantinople.vm.precompiled_contracts" "ALT_BN128_ADD_ADDRESS". +Axiom ethereum_constantinople_vm_precompiled_contracts_imports_ALT_BN128_MUL_ADDRESS : + IsImported globals "ethereum.constantinople.vm.precompiled_contracts" "ALT_BN128_MUL_ADDRESS". +Axiom ethereum_constantinople_vm_precompiled_contracts_imports_ALT_BN128_PAIRING_CHECK_ADDRESS : + IsImported globals "ethereum.constantinople.vm.precompiled_contracts" "ALT_BN128_PAIRING_CHECK_ADDRESS". +Axiom ethereum_constantinople_vm_precompiled_contracts_imports_ECRECOVER_ADDRESS : + IsImported globals "ethereum.constantinople.vm.precompiled_contracts" "ECRECOVER_ADDRESS". +Axiom ethereum_constantinople_vm_precompiled_contracts_imports_IDENTITY_ADDRESS : + IsImported globals "ethereum.constantinople.vm.precompiled_contracts" "IDENTITY_ADDRESS". +Axiom ethereum_constantinople_vm_precompiled_contracts_imports_MODEXP_ADDRESS : + IsImported globals "ethereum.constantinople.vm.precompiled_contracts" "MODEXP_ADDRESS". +Axiom ethereum_constantinople_vm_precompiled_contracts_imports_RIPEMD160_ADDRESS : + IsImported globals "ethereum.constantinople.vm.precompiled_contracts" "RIPEMD160_ADDRESS". +Axiom ethereum_constantinople_vm_precompiled_contracts_imports_SHA256_ADDRESS : + IsImported globals "ethereum.constantinople.vm.precompiled_contracts" "SHA256_ADDRESS". + +Axiom ethereum_constantinople_vm_precompiled_contracts_alt_bn128_imports_alt_bn128_add : + IsImported globals "ethereum.constantinople.vm.precompiled_contracts.alt_bn128" "alt_bn128_add". +Axiom ethereum_constantinople_vm_precompiled_contracts_alt_bn128_imports_alt_bn128_mul : + IsImported globals "ethereum.constantinople.vm.precompiled_contracts.alt_bn128" "alt_bn128_mul". +Axiom ethereum_constantinople_vm_precompiled_contracts_alt_bn128_imports_alt_bn128_pairing_check : + IsImported globals "ethereum.constantinople.vm.precompiled_contracts.alt_bn128" "alt_bn128_pairing_check". + +Axiom ethereum_constantinople_vm_precompiled_contracts_ecrecover_imports_ecrecover : + IsImported globals "ethereum.constantinople.vm.precompiled_contracts.ecrecover" "ecrecover". + +Axiom ethereum_constantinople_vm_precompiled_contracts_identity_imports_identity : + IsImported globals "ethereum.constantinople.vm.precompiled_contracts.identity" "identity". + +Axiom ethereum_constantinople_vm_precompiled_contracts_modexp_imports_modexp : + IsImported globals "ethereum.constantinople.vm.precompiled_contracts.modexp" "modexp". + +Axiom ethereum_constantinople_vm_precompiled_contracts_ripemd160_imports_ripemd160 : + IsImported globals "ethereum.constantinople.vm.precompiled_contracts.ripemd160" "ripemd160". + +Axiom ethereum_constantinople_vm_precompiled_contracts_sha256_imports_sha256 : + IsImported globals "ethereum.constantinople.vm.precompiled_contracts.sha256" "sha256". + +(* At top_level_stmt: unsupported node type: AnnAssign *) diff --git a/CoqOfPython/ethereum/constantinople/vm/precompiled_contracts/modexp.v b/CoqOfPython/ethereum/constantinople/vm/precompiled_contracts/modexp.v new file mode 100644 index 0000000..8bbf71b --- /dev/null +++ b/CoqOfPython/ethereum/constantinople/vm/precompiled_contracts/modexp.v @@ -0,0 +1,544 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.constantinople.vm.precompiled_contracts.modexp". + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) MODEXP PRECOMPILED CONTRACT +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementation of the `MODEXP` precompiled contract. +". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_Bytes : + IsImported globals "ethereum.base_types" "Bytes". +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". + +Axiom ethereum_constantinople_vm_imports_Evm : + IsImported globals "ethereum.constantinople.vm" "Evm". + +Axiom ethereum_constantinople_vm_gas_imports_charge_gas : + IsImported globals "ethereum.constantinople.vm.gas" "charge_gas". + +Axiom ethereum_constantinople_vm_memory_imports_buffer_read : + IsImported globals "ethereum.constantinople.vm.memory" "buffer_read". + +Definition GQUADDIVISOR : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 20 + ], + make_dict [] + |) +)). + +Definition modexp : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Calculates `(base**exp) % modulus` for arbitrary sized `base`, `exp` and. + `modulus`. The return value is the same length as the modulus. + " in + let _ := M.assign_local (| + "data" , + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "data" |) + |) in + let _ := M.assign_local (| + "base_length" , + M.call (| + M.get_field (| M.get_name (| globals, "U256" |), "from_be_bytes" |), + make_list [ + M.call (| + M.get_name (| globals, "buffer_read" |), + make_list [ + M.get_name (| globals, "data" |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 32 + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "exp_length" , + M.call (| + M.get_field (| M.get_name (| globals, "U256" |), "from_be_bytes" |), + make_list [ + M.call (| + M.get_name (| globals, "buffer_read" |), + make_list [ + M.get_name (| globals, "data" |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 32 + ], + make_dict [] + |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 32 + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "modulus_length" , + M.call (| + M.get_field (| M.get_name (| globals, "U256" |), "from_be_bytes" |), + make_list [ + M.call (| + M.get_name (| globals, "buffer_read" |), + make_list [ + M.get_name (| globals, "data" |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 64 + ], + make_dict [] + |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 32 + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "exp_start" , + BinOp.add (| + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 96 + ], + make_dict [] + |), + M.get_name (| globals, "base_length" |) + |) + |) in + let _ := M.assign_local (| + "exp_head" , + M.call (| + M.get_field (| M.get_name (| globals, "U256" |), "from_be_bytes" |), + make_list [ + M.call (| + M.get_name (| globals, "buffer_read" |), + make_list [ + M.get_name (| globals, "data" |); + M.get_name (| globals, "exp_start" |); + M.call (| + M.get_name (| globals, "min" |), + make_list [ + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 32 + ], + make_dict [] + |); + M.get_name (| globals, "exp_length" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.lt (| + M.get_name (| globals, "exp_length" |), + Constant.int 32 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "adjusted_exp_length" , + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, "max" |), + make_list [ + Constant.int 0; + BinOp.sub (| + M.call (| + M.get_field (| M.get_name (| globals, "exp_head" |), "bit_length" |), + make_list [], + make_dict [] + |), + Constant.int 1 + |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "adjusted_exp_length" , + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + BinOp.add (| + BinOp.mult (| + Constant.int 8, + BinOp.sub (| + M.call (| + M.get_name (| globals, "int" |), + make_list [ + M.get_name (| globals, "exp_length" |) + ], + make_dict [] + |), + Constant.int 32 + |) + |), + M.call (| + M.get_name (| globals, "max" |), + make_list [ + Constant.int 0; + BinOp.sub (| + M.call (| + M.get_field (| M.get_name (| globals, "exp_head" |), "bit_length" |), + make_list [], + make_dict [] + |), + Constant.int 1 + |) + ], + make_dict [] + |) + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + )) |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + BinOp.floor_div (| + BinOp.mult (| + M.call (| + M.get_name (| globals, "get_mult_complexity" |), + make_list [ + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, "max" |), + make_list [ + M.get_name (| globals, "base_length" |); + M.get_name (| globals, "modulus_length" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |), + M.call (| + M.get_name (| globals, "max" |), + make_list [ + M.get_name (| globals, "adjusted_exp_length" |); + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 1 + ], + make_dict [] + |) + ], + make_dict [] + |) + |), + M.get_name (| globals, "GQUADDIVISOR" |) + |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + BoolOp.and (| + Compare.eq (| + M.get_name (| globals, "base_length" |), + Constant.int 0 + |), + ltac:(M.monadic ( + Compare.eq (| + M.get_name (| globals, "modulus_length" |), + Constant.int 0 + |) + )) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign (| + M.get_field (| M.get_name (| globals, "evm" |), "output" |), + M.call (| + M.get_name (| globals, "Bytes" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.return_ (| + Constant.None_ + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "base" , + M.call (| + M.get_field (| M.get_name (| globals, "Uint" |), "from_be_bytes" |), + make_list [ + M.call (| + M.get_name (| globals, "buffer_read" |), + make_list [ + M.get_name (| globals, "data" |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 96 + ], + make_dict [] + |); + M.get_name (| globals, "base_length" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "exp" , + M.call (| + M.get_field (| M.get_name (| globals, "Uint" |), "from_be_bytes" |), + make_list [ + M.call (| + M.get_name (| globals, "buffer_read" |), + make_list [ + M.get_name (| globals, "data" |); + M.get_name (| globals, "exp_start" |); + M.get_name (| globals, "exp_length" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "modulus_start" , + BinOp.add (| + M.get_name (| globals, "exp_start" |), + M.get_name (| globals, "exp_length" |) + |) + |) in + let _ := M.assign_local (| + "modulus" , + M.call (| + M.get_field (| M.get_name (| globals, "Uint" |), "from_be_bytes" |), + make_list [ + M.call (| + M.get_name (| globals, "buffer_read" |), + make_list [ + M.get_name (| globals, "data" |); + M.get_name (| globals, "modulus_start" |); + M.get_name (| globals, "modulus_length" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, "modulus" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign (| + M.get_field (| M.get_name (| globals, "evm" |), "output" |), + BinOp.mult (| + M.call (| + M.get_name (| globals, "Bytes" |), + make_list [ + Constant.bytes "00" + ], + make_dict [] + |), + M.get_name (| globals, "modulus_length" |) + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign (| + M.get_field (| M.get_name (| globals, "evm" |), "output" |), + M.call (| + M.get_field (| M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, "pow" |), + make_list [ + M.get_name (| globals, "base" |); + M.get_name (| globals, "exp" |); + M.get_name (| globals, "modulus" |) + ], + make_dict [] + |) + ], + make_dict [] + |), "to_bytes" |), + make_list [ + M.get_name (| globals, "modulus_length" |); + Constant.str "big" + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_)). + +Definition get_mult_complexity : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "x" ] |) in + let _ := Constant.str " + Estimate the complexity of performing Karatsuba multiplication. + " in + let _ := + (* if *) + M.if_then_else (| + Compare.lt_e (| + M.get_name (| globals, "x" |), + Constant.int 64 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + BinOp.pow (| + M.get_name (| globals, "x" |), + Constant.int 2 + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + Compare.lt_e (| + M.get_name (| globals, "x" |), + Constant.int 1024 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + BinOp.sub (| + BinOp.add (| + BinOp.floor_div (| + BinOp.pow (| + M.get_name (| globals, "x" |), + Constant.int 2 + |), + Constant.int 4 + |), + BinOp.mult (| + Constant.int 96, + M.get_name (| globals, "x" |) + |) + |), + Constant.int 3072 + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.return_ (| + BinOp.sub (| + BinOp.add (| + BinOp.floor_div (| + BinOp.pow (| + M.get_name (| globals, "x" |), + Constant.int 2 + |), + Constant.int 16 + |), + BinOp.mult (| + Constant.int 480, + M.get_name (| globals, "x" |) + |) + |), + Constant.int 199680 + |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_)). diff --git a/CoqOfPython/ethereum/constantinople/vm/precompiled_contracts/ripemd160.v b/CoqOfPython/ethereum/constantinople/vm/precompiled_contracts/ripemd160.v new file mode 100644 index 0000000..9077c68 --- /dev/null +++ b/CoqOfPython/ethereum/constantinople/vm/precompiled_contracts/ripemd160.v @@ -0,0 +1,125 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.constantinople.vm.precompiled_contracts.ripemd160". + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) RIPEMD160 PRECOMPILED CONTRACT +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementation of the `RIPEMD160` precompiled contract. +". + +(* At top_level_stmt: unsupported node type: Import *) + +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". + +Axiom ethereum_utils_byte_imports_left_pad_zero_bytes : + IsImported globals "ethereum.utils.byte" "left_pad_zero_bytes". + +Axiom ethereum_utils_numeric_imports_ceil32 : + IsImported globals "ethereum.utils.numeric" "ceil32". + +Axiom ethereum_constantinople_vm_imports_Evm : + IsImported globals "ethereum.constantinople.vm" "Evm". + +Axiom ethereum_constantinople_vm_gas_imports_GAS_RIPEMD160 : + IsImported globals "ethereum.constantinople.vm.gas" "GAS_RIPEMD160". +Axiom ethereum_constantinople_vm_gas_imports_GAS_RIPEMD160_WORD : + IsImported globals "ethereum.constantinople.vm.gas" "GAS_RIPEMD160_WORD". +Axiom ethereum_constantinople_vm_gas_imports_charge_gas : + IsImported globals "ethereum.constantinople.vm.gas" "charge_gas". + +Definition ripemd160 : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Writes the ripemd160 hash to output. + + Parameters + ---------- + evm : + The current EVM frame. + " in + let _ := M.assign_local (| + "data" , + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "data" |) + |) in + let _ := M.assign_local (| + "word_count" , + BinOp.floor_div (| + M.call (| + M.get_name (| globals, "ceil32" |), + make_list [ + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_name (| globals, "data" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |), + Constant.int 32 + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + BinOp.add (| + M.get_name (| globals, "GAS_RIPEMD160" |), + BinOp.mult (| + M.get_name (| globals, "GAS_RIPEMD160_WORD" |), + M.get_name (| globals, "word_count" |) + |) + |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "hash_bytes" , + M.call (| + M.get_field (| M.call (| + M.get_field (| M.get_name (| globals, "hashlib" |), "new" |), + make_list [ + Constant.str "ripemd160"; + M.get_name (| globals, "data" |) + ], + make_dict [] + |), "digest" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "padded_hash" , + M.call (| + M.get_name (| globals, "left_pad_zero_bytes" |), + make_list [ + M.get_name (| globals, "hash_bytes" |); + Constant.int 32 + ], + make_dict [] + |) + |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, "evm" |), "output" |), + M.get_name (| globals, "padded_hash" |) + |) in + M.pure Constant.None_)). diff --git a/CoqOfPython/ethereum/constantinople/vm/precompiled_contracts/sha256.v b/CoqOfPython/ethereum/constantinople/vm/precompiled_contracts/sha256.v new file mode 100644 index 0000000..5e11ce8 --- /dev/null +++ b/CoqOfPython/ethereum/constantinople/vm/precompiled_contracts/sha256.v @@ -0,0 +1,106 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.constantinople.vm.precompiled_contracts.sha256". + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) SHA256 PRECOMPILED CONTRACT +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementation of the `SHA256` precompiled contract. +". + +(* At top_level_stmt: unsupported node type: Import *) + +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". + +Axiom ethereum_utils_numeric_imports_ceil32 : + IsImported globals "ethereum.utils.numeric" "ceil32". + +Axiom ethereum_constantinople_vm_imports_Evm : + IsImported globals "ethereum.constantinople.vm" "Evm". + +Axiom ethereum_constantinople_vm_gas_imports_GAS_SHA256 : + IsImported globals "ethereum.constantinople.vm.gas" "GAS_SHA256". +Axiom ethereum_constantinople_vm_gas_imports_GAS_SHA256_WORD : + IsImported globals "ethereum.constantinople.vm.gas" "GAS_SHA256_WORD". +Axiom ethereum_constantinople_vm_gas_imports_charge_gas : + IsImported globals "ethereum.constantinople.vm.gas" "charge_gas". + +Definition sha256 : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Writes the sha256 hash to output. + + Parameters + ---------- + evm : + The current EVM frame. + " in + let _ := M.assign_local (| + "data" , + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "data" |) + |) in + let _ := M.assign_local (| + "word_count" , + BinOp.floor_div (| + M.call (| + M.get_name (| globals, "ceil32" |), + make_list [ + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_name (| globals, "data" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |), + Constant.int 32 + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + BinOp.add (| + M.get_name (| globals, "GAS_SHA256" |), + BinOp.mult (| + M.get_name (| globals, "GAS_SHA256_WORD" |), + M.get_name (| globals, "word_count" |) + |) + |) + ], + make_dict [] + |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, "evm" |), "output" |), + M.call (| + M.get_field (| M.call (| + M.get_field (| M.get_name (| globals, "hashlib" |), "sha256" |), + make_list [ + M.get_name (| globals, "data" |) + ], + make_dict [] + |), "digest" |), + make_list [], + make_dict [] + |) + |) in + M.pure Constant.None_)). diff --git a/CoqOfPython/ethereum/constantinople/vm/runtime.v b/CoqOfPython/ethereum/constantinople/vm/runtime.v new file mode 100644 index 0000000..f830abe --- /dev/null +++ b/CoqOfPython/ethereum/constantinople/vm/runtime.v @@ -0,0 +1,157 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.constantinople.vm.runtime". + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) Runtime Operations +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Runtime related operations used while executing EVM code. +". + +Axiom typing_imports_Set : + IsImported globals "typing" "Set". + +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". + +Axiom ethereum_constantinople_vm_instructions_imports_Ops : + IsImported globals "ethereum.constantinople.vm.instructions" "Ops". + +Definition get_valid_jump_destinations : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "code" ] |) in + let _ := Constant.str " + Analyze the evm code to obtain the set of valid jump destinations. + + Valid jump destinations are defined as follows: + * The jump destination is less than the length of the code. + * The jump destination should have the `JUMPDEST` opcode (0x5B). + * The jump destination shouldn't be part of the data corresponding to + `PUSH-N` opcodes. + + Note - Jump destinations are 0-indexed. + + Parameters + ---------- + code : + The EVM code which is to be executed. + + Returns + ------- + valid_jump_destinations: `Set[Uint]` + The set of valid jump destinations in the code. + " in + let _ := M.assign_local (| + "valid_jump_destinations" , + M.call (| + M.get_name (| globals, "set" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "pc" , + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + |) in + let _ := + M.while (| + Compare.lt (| + M.get_name (| globals, "pc" |), + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_name (| globals, "code" |) + ], + make_dict [] + |) + |), + ltac:(M.monadic ( +(* At stmt: unsupported node type: Try *) + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, "current_opcode" |), + M.get_field (| M.get_name (| globals, "Ops" |), "JUMPDEST" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_field (| M.get_name (| globals, "valid_jump_destinations" |), "add" |), + make_list [ + M.get_name (| globals, "pc" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + BoolOp.and (| + Compare.lt_e (| + M.get_field (| M.get_field (| M.get_name (| globals, "Ops" |), "PUSH1" |), "value" |), + M.get_field (| M.get_name (| globals, "current_opcode" |), "value" |) + |), + ltac:(M.monadic ( + Compare.lt_e (| + M.get_field (| M.get_name (| globals, "current_opcode" |), "value" |), + M.get_field (| M.get_field (| M.get_name (| globals, "Ops" |), "PUSH32" |), "value" |) + |) + )) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "push_data_size" , + BinOp.add (| + BinOp.sub (| + M.get_field (| M.get_name (| globals, "current_opcode" |), "value" |), + M.get_field (| M.get_field (| M.get_name (| globals, "Ops" |), "PUSH1" |), "value" |) + |), + Constant.int 1 + |) + |) in + let _ := M.assign_op_local (| + BinOp.add, + "pc", + M.get_name (| globals, "push_data_size" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )) |) in + let _ := M.assign_op_local (| + BinOp.add, + "pc", + Constant.int 1 + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := M.return_ (| + M.get_name (| globals, "valid_jump_destinations" |) + |) in + M.pure Constant.None_)). diff --git a/CoqOfPython/ethereum/constantinople/vm/stack.v b/CoqOfPython/ethereum/constantinople/vm/stack.v new file mode 100644 index 0000000..afbe789 --- /dev/null +++ b/CoqOfPython/ethereum/constantinople/vm/stack.v @@ -0,0 +1,123 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.constantinople.vm.stack". + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) Stack +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementation of the stack operators for the EVM. +". + +Axiom typing_imports_List : + IsImported globals "typing" "List". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". + +Axiom ethereum_constantinople_vm_exceptions_imports_StackOverflowError : + IsImported globals "ethereum.constantinople.vm.exceptions" "StackOverflowError". +Axiom ethereum_constantinople_vm_exceptions_imports_StackUnderflowError : + IsImported globals "ethereum.constantinople.vm.exceptions" "StackUnderflowError". + +Definition pop : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "stack" ] |) in + let _ := Constant.str " + Pops the top item off of `stack`. + + Parameters + ---------- + stack : + EVM stack. + + Returns + ------- + value : `U256` + The top element on the stack. + + " in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_name (| globals, "stack" |) + ], + make_dict [] + |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, "StackUnderflowError" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.return_ (| + M.call (| + M.get_field (| M.get_name (| globals, "stack" |), "pop" |), + make_list [], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Definition push : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "stack"; "value" ] |) in + let _ := Constant.str " + Pushes `value` onto `stack`. + + Parameters + ---------- + stack : + EVM stack. + + value : + Item to be pushed onto `stack`. + + " in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_name (| globals, "stack" |) + ], + make_dict [] + |), + Constant.int 1024 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, "StackOverflowError" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.return_ (| + M.call (| + M.get_field (| M.get_name (| globals, "stack" |), "append" |), + make_list [ + M.get_name (| globals, "value" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). diff --git a/CoqOfPython/ethereum/crypto/__init__.v b/CoqOfPython/ethereum/crypto/__init__.v new file mode 100644 index 0000000..d20cfb4 --- /dev/null +++ b/CoqOfPython/ethereum/crypto/__init__.v @@ -0,0 +1,8 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.crypto.__init__". + +Definition expr_1 : Value.t := + Constant.str " +Cryptographic primitives used in Ethereum. +". diff --git a/CoqOfPython/ethereum/crypto/alt_bn128.v b/CoqOfPython/ethereum/crypto/alt_bn128.v new file mode 100644 index 0000000..bc2b4ac --- /dev/null +++ b/CoqOfPython/ethereum/crypto/alt_bn128.v @@ -0,0 +1,787 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.crypto.alt_bn128". + +Definition expr_1 : Value.t := + Constant.str " +The alt_bn128 curve +^^^^^^^^^^^^^^^^^^^ +". + +Axiom ethereum_crypto_imports_elliptic_curve : + IsImported globals "ethereum.crypto" "elliptic_curve". +Axiom ethereum_crypto_imports_finite_field : + IsImported globals "ethereum.crypto" "finite_field". + +Definition ALT_BN128_PRIME : Value.t := M.run ltac:(M.monadic ( + Constant.int 21888242871839275222246405745257275088696311157297823662689037894645226208583 +)). + +Definition ALT_BN128_CURVE_ORDER : Value.t := M.run ltac:(M.monadic ( + Constant.int 21888242871839275222246405745257275088548364400416034343698204186575808495617 +)). + +Definition ATE_PAIRING_COUNT : Value.t := M.run ltac:(M.monadic ( + Constant.int 29793968203157093289 +)). + +Definition ATE_PAIRING_COUNT_BITS : Value.t := M.run ltac:(M.monadic ( + Constant.int 63 +)). + +Definition BNF : Value.t := + builtins.make_klass + [(* At base: unsupported node type: Attribute *)] + [ + + ] + [ + + ]. + +Definition BNP : Value.t := + builtins.make_klass + [(* At base: unsupported node type: Attribute *)] + [ + + ] + [ + + ]. + +Definition BNF2 : Value.t := + builtins.make_klass + [(* At base: unsupported node type: Attribute *)] + [ + + ] + [ + + ]. + +(* At top_level_stmt: unsupported node type: Assign *) + +Definition expr_45 : Value.t := + Constant.str "autoapi_noindex". + +(* At top_level_stmt: unsupported node type: Assign *) + +Definition expr_48 : Value.t := + Constant.str "autoapi_noindex". + +(* At top_level_stmt: unsupported node type: Assign *) + +Definition expr_51 : Value.t := + Constant.str "autoapi_noindex". + +Definition BNP2 : Value.t := + builtins.make_klass + [(* At base: unsupported node type: Attribute *)] + [ + + ] + [ + + ]. + +Definition BNF12 : Value.t := + builtins.make_klass + [(* At base: unsupported node type: Attribute *)] + [ + + ] + [ + ( + "__mul__", + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "self"; "right" ] |) in + let _ := Constant.str " + Multiplication special cased for BNF12. + " in + let _ := M.assign_local (| + "mul" , + BinOp.mult (| + make_list [ + Constant.int 0 + ], + Constant.int 23 + |) + |) in + let _ := + M.for_ (| + M.get_name (| globals, "i" |), + M.call (| + M.get_name (| globals, "range" |), + make_list [ + Constant.int 12 + ], + make_dict [] + |), + ltac:(M.monadic ( + let _ := + M.for_ (| + M.get_name (| globals, "j" |), + M.call (| + M.get_name (| globals, "range" |), + make_list [ + Constant.int 12 + ], + make_dict [] + |), + ltac:(M.monadic ( + let _ := M.assign_op (| + BinOp.add, + M.get_subscript (| + M.get_name (| globals, "mul" |), + BinOp.add (| + M.get_name (| globals, "i" |), + M.get_name (| globals, "j" |) + |) + |), + BinOp.mult (| + M.get_subscript (| + M.get_name (| globals, "self" |), + M.get_name (| globals, "i" |) + |), + M.get_subscript (| + M.get_name (| globals, "right" |), + M.get_name (| globals, "j" |) + |) + |) + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := + M.for_ (| + M.get_name (| globals, "i" |), + M.call (| + M.get_name (| globals, "range" |), + make_list [ + Constant.int 22; + Constant.int 11; + UnOp.sub (| Constant.int 1 |) + ], + make_dict [] + |), + ltac:(M.monadic ( + let _ := M.assign_op (| + BinOp.sub, + M.get_subscript (| + M.get_name (| globals, "mul" |), + BinOp.sub (| + M.get_name (| globals, "i" |), + Constant.int 6 + |) + |), + BinOp.mult (| + M.get_subscript (| + M.get_name (| globals, "mul" |), + M.get_name (| globals, "i" |) + |), + UnOp.sub (| Constant.int 18 |) + |) + |) in + let _ := M.assign_op (| + BinOp.sub, + M.get_subscript (| + M.get_name (| globals, "mul" |), + BinOp.sub (| + M.get_name (| globals, "i" |), + Constant.int 12 + |) + |), + BinOp.mult (| + M.get_subscript (| + M.get_name (| globals, "mul" |), + M.get_name (| globals, "i" |) + |), + Constant.int 82 + |) + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := M.return_ (| + M.call (| + M.get_field (| M.get_name (| globals, "BNF12" |), "__new__" |), + make_list [ + M.get_name (| globals, "BNF12" |); + M.slice (| + M.get_name (| globals, "mul" |), + Constant.None_, + Constant.int 12, + Constant.None_ + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)) + ) + ]. + +(* At top_level_stmt: unsupported node type: Assign *) + +Definition expr_98 : Value.t := + Constant.str "autoapi_noindex". + +(* At top_level_stmt: unsupported node type: Assign *) + +Definition expr_101 : Value.t := + Constant.str "autoapi_noindex". + +(* At top_level_stmt: unsupported node type: Assign *) + +Definition expr_104 : Value.t := + Constant.str "autoapi_noindex". + +Definition BNP12 : Value.t := + builtins.make_klass + [(* At base: unsupported node type: Attribute *)] + [ + + ] + [ + + ]. + +Definition bnf2_to_bnf12 : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "x" ] |) in + let _ := Constant.str " + Lift a field element in `BNF2` to `BNF12`. + " in + let _ := M.return_ (| + BinOp.add (| + M.call (| + M.get_field (| M.get_name (| globals, "BNF12" |), "from_int" |), + make_list [ + M.get_subscript (| + M.get_name (| globals, "x" |), + Constant.int 0 + |) + ], + make_dict [] + |), + BinOp.mult (| + M.call (| + M.get_field (| M.get_name (| globals, "BNF12" |), "from_int" |), + make_list [ + M.get_subscript (| + M.get_name (| globals, "x" |), + Constant.int 1 + |) + ], + make_dict [] + |), + BinOp.sub (| + M.get_field (| M.get_name (| globals, "BNF12" |), "i_plus_9" |), + M.call (| + M.get_field (| M.get_name (| globals, "BNF12" |), "from_int" |), + make_list [ + Constant.int 9 + ], + make_dict [] + |) + |) + |) + |) + |) in + M.pure Constant.None_)). + +Definition bnp_to_bnp12 : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "p" ] |) in + let _ := Constant.str " + Lift a point from `BNP` to `BNP12`. + " in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, "BNP12" |), + make_list [ + M.call (| + M.get_field (| M.get_name (| globals, "BNF12" |), "from_int" |), + make_list [ + M.call (| + M.get_name (| globals, "int" |), + make_list [ + M.get_field (| M.get_name (| globals, "p" |), "x" |) + ], + make_dict [] + |) + ], + make_dict [] + |); + M.call (| + M.get_field (| M.get_name (| globals, "BNF12" |), "from_int" |), + make_list [ + M.call (| + M.get_name (| globals, "int" |), + make_list [ + M.get_field (| M.get_name (| globals, "p" |), "y" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Definition twist : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "p" ] |) in + let _ := Constant.str " + Apply to twist to change variables from the curve `BNP2` to `BNP12`. + " in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, "BNP12" |), + make_list [ + BinOp.mult (| + M.call (| + M.get_name (| globals, "bnf2_to_bnf12" |), + make_list [ + M.get_field (| M.get_name (| globals, "p" |), "x" |) + ], + make_dict [] + |), + BinOp.pow (| + M.get_field (| M.get_name (| globals, "BNF12" |), "w" |), + Constant.int 2 + |) + |); + BinOp.mult (| + M.call (| + M.get_name (| globals, "bnf2_to_bnf12" |), + make_list [ + M.get_field (| M.get_name (| globals, "p" |), "y" |) + ], + make_dict [] + |), + BinOp.pow (| + M.get_field (| M.get_name (| globals, "BNF12" |), "w" |), + Constant.int 3 + |) + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Definition linefunc : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "p1"; "p2"; "t" ] |) in + let _ := Constant.str " + Evaluate the function defining the line between points `p1` and `p2` at the + point `t`. The mathematical significance of this function is that is has + divisor `(p1) + (p2) + (p1 + p2) - 3(O)`. + + Note: Abstract mathematical presentations of Miller's algorithm often + specify the divisor `(p1) + (p2) - (p1 + p2) - (O)`. This turns out not to + matter. + " in + let _ := + (* if *) + M.if_then_else (| + Compare.not_eq (| + M.get_field (| M.get_name (| globals, "p1" |), "x" |), + M.get_field (| M.get_name (| globals, "p2" |), "x" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "lam" , + BinOp.div (| + BinOp.sub (| + M.get_field (| M.get_name (| globals, "p2" |), "y" |), + M.get_field (| M.get_name (| globals, "p1" |), "y" |) + |), + BinOp.sub (| + M.get_field (| M.get_name (| globals, "p2" |), "x" |), + M.get_field (| M.get_name (| globals, "p1" |), "x" |) + |) + |) + |) in + let _ := M.return_ (| + BinOp.sub (| + BinOp.mult (| + M.get_name (| globals, "lam" |), + BinOp.sub (| + M.get_field (| M.get_name (| globals, "t" |), "x" |), + M.get_field (| M.get_name (| globals, "p1" |), "x" |) + |) + |), + BinOp.sub (| + M.get_field (| M.get_name (| globals, "t" |), "y" |), + M.get_field (| M.get_name (| globals, "p1" |), "y" |) + |) + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_field (| M.get_name (| globals, "p1" |), "y" |), + M.get_field (| M.get_name (| globals, "p2" |), "y" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "lam" , + BinOp.div (| + BinOp.mult (| + M.call (| + M.get_field (| M.get_name (| globals, "BNF12" |), "from_int" |), + make_list [ + Constant.int 3 + ], + make_dict [] + |), + BinOp.pow (| + M.get_field (| M.get_name (| globals, "p1" |), "x" |), + Constant.int 2 + |) + |), + BinOp.mult (| + M.call (| + M.get_field (| M.get_name (| globals, "BNF12" |), "from_int" |), + make_list [ + Constant.int 2 + ], + make_dict [] + |), + M.get_field (| M.get_name (| globals, "p1" |), "y" |) + |) + |) + |) in + let _ := M.return_ (| + BinOp.sub (| + BinOp.mult (| + M.get_name (| globals, "lam" |), + BinOp.sub (| + M.get_field (| M.get_name (| globals, "t" |), "x" |), + M.get_field (| M.get_name (| globals, "p1" |), "x" |) + |) + |), + BinOp.sub (| + M.get_field (| M.get_name (| globals, "t" |), "y" |), + M.get_field (| M.get_name (| globals, "p1" |), "y" |) + |) + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.return_ (| + BinOp.sub (| + M.get_field (| M.get_name (| globals, "t" |), "x" |), + M.get_field (| M.get_name (| globals, "p1" |), "x" |) + |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_)). + +Definition miller_loop : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "q"; "p" ] |) in + let _ := Constant.str " + The core of the pairing algorithm. + " in + let _ := + (* if *) + M.if_then_else (| + BoolOp.or (| + Compare.eq (| + M.get_name (| globals, "p" |), + M.call (| + M.get_field (| M.get_name (| globals, "BNP12" |), "point_at_infinity" |), + make_list [], + make_dict [] + |) + |), + ltac:(M.monadic ( + Compare.eq (| + M.get_name (| globals, "q" |), + M.call (| + M.get_field (| M.get_name (| globals, "BNP12" |), "point_at_infinity" |), + make_list [], + make_dict [] + |) + |) + )) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + M.call (| + M.get_field (| M.get_name (| globals, "BNF12" |), "from_int" |), + make_list [ + Constant.int 1 + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "r" , + M.get_name (| globals, "q" |) + |) in + let _ := M.assign_local (| + "f" , + M.call (| + M.get_field (| M.get_name (| globals, "BNF12" |), "from_int" |), + make_list [ + Constant.int 1 + ], + make_dict [] + |) + |) in + let _ := + M.for_ (| + M.get_name (| globals, "i" |), + M.call (| + M.get_name (| globals, "range" |), + make_list [ + M.get_name (| globals, "ATE_PAIRING_COUNT_BITS" |); + UnOp.sub (| Constant.int 1 |); + UnOp.sub (| Constant.int 1 |) + ], + make_dict [] + |), + ltac:(M.monadic ( + let _ := M.assign_local (| + "f" , + BinOp.mult (| + BinOp.mult (| + M.get_name (| globals, "f" |), + M.get_name (| globals, "f" |) + |), + M.call (| + M.get_name (| globals, "linefunc" |), + make_list [ + M.get_name (| globals, "r" |); + M.get_name (| globals, "r" |); + M.get_name (| globals, "p" |) + ], + make_dict [] + |) + |) + |) in + let _ := M.assign_local (| + "r" , + M.call (| + M.get_field (| M.get_name (| globals, "r" |), "double" |), + make_list [], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + BinOp.bit_and (| + BinOp.sub (| + M.get_name (| globals, "ATE_PAIRING_COUNT" |), + Constant.int 1 + |), + BinOp.pow (| + Constant.int 2, + M.get_name (| globals, "i" |) + |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "f" , + BinOp.mult (| + M.get_name (| globals, "f" |), + M.call (| + M.get_name (| globals, "linefunc" |), + make_list [ + M.get_name (| globals, "r" |); + M.get_name (| globals, "q" |); + M.get_name (| globals, "p" |) + ], + make_dict [] + |) + |) + |) in + let _ := M.assign_local (| + "r" , + BinOp.add (| + M.get_name (| globals, "r" |), + M.get_name (| globals, "q" |) + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := M.assert (| Compare.eq (| + M.get_name (| globals, "r" |), + M.call (| + M.get_field (| M.get_name (| globals, "q" |), "mul_by" |), + make_list [ + BinOp.sub (| + M.get_name (| globals, "ATE_PAIRING_COUNT" |), + Constant.int 1 + |) + ], + make_dict [] + |) + |) |) in + let _ := M.assign_local (| + "q1" , + M.call (| + M.get_name (| globals, "BNP12" |), + make_list [ + M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, "q" |), "x" |), "frobenius" |), + make_list [], + make_dict [] + |); + M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, "q" |), "y" |), "frobenius" |), + make_list [], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "nq2" , + M.call (| + M.get_name (| globals, "BNP12" |), + make_list [ + M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, "q1" |), "x" |), "frobenius" |), + make_list [], + make_dict [] + |); + UnOp.sub (| M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, "q1" |), "y" |), "frobenius" |), + make_list [], + make_dict [] + |) |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "f" , + BinOp.mult (| + M.get_name (| globals, "f" |), + M.call (| + M.get_name (| globals, "linefunc" |), + make_list [ + M.get_name (| globals, "r" |); + M.get_name (| globals, "q1" |); + M.get_name (| globals, "p" |) + ], + make_dict [] + |) + |) + |) in + let _ := M.assign_local (| + "r" , + BinOp.add (| + M.get_name (| globals, "r" |), + M.get_name (| globals, "q1" |) + |) + |) in + let _ := M.assign_local (| + "f" , + BinOp.mult (| + M.get_name (| globals, "f" |), + M.call (| + M.get_name (| globals, "linefunc" |), + make_list [ + M.get_name (| globals, "r" |); + M.get_name (| globals, "nq2" |); + M.get_name (| globals, "p" |) + ], + make_dict [] + |) + |) + |) in + let _ := M.return_ (| + BinOp.pow (| + M.get_name (| globals, "f" |), + BinOp.floor_div (| + BinOp.sub (| + BinOp.pow (| + M.get_name (| globals, "ALT_BN128_PRIME" |), + Constant.int 12 + |), + Constant.int 1 + |), + M.get_name (| globals, "ALT_BN128_CURVE_ORDER" |) + |) + |) + |) in + M.pure Constant.None_)). + +Definition pairing : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "q"; "p" ] |) in + let _ := Constant.str " + Compute the pairing of `q` and `p`. + " in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, "miller_loop" |), + make_list [ + M.call (| + M.get_name (| globals, "twist" |), + make_list [ + M.get_name (| globals, "q" |) + ], + make_dict [] + |); + M.call (| + M.get_name (| globals, "bnp_to_bnp12" |), + make_list [ + M.get_name (| globals, "p" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). diff --git a/CoqOfPython/ethereum/crypto/blake2.v b/CoqOfPython/ethereum/crypto/blake2.v new file mode 100644 index 0000000..6cd27f7 --- /dev/null +++ b/CoqOfPython/ethereum/crypto/blake2.v @@ -0,0 +1,819 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.crypto.blake2". + +Definition expr_1 : Value.t := + Constant.str " +The Blake2 Implementation +^^^^^^^^^^^^^^^^^^^^^^^^^^ +". + +(* At top_level_stmt: unsupported node type: Import *) + +Axiom dataclasses_imports_dataclass : + IsImported globals "dataclasses" "dataclass". + +Axiom typing_imports_List : + IsImported globals "typing" "List". +Axiom typing_imports_Tuple : + IsImported globals "typing" "Tuple". + +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". + +Definition spit_le_to_uint : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "data"; "start"; "num_words" ] |) in + let _ := Constant.str " + Extracts 8 byte words from a given data. + + Parameters + ---------- + data : + The data in bytes from which the words need to be extracted + start : + Position to start the extraction + num_words: + The number of words to be extracted + " in + let _ := M.assign_local (| + "words" , + make_list [] + |) in + let _ := + M.for_ (| + M.get_name (| globals, "i" |), + M.call (| + M.get_name (| globals, "range" |), + make_list [ + M.get_name (| globals, "num_words" |) + ], + make_dict [] + |), + ltac:(M.monadic ( + let _ := M.assign_local (| + "start_position" , + BinOp.add (| + M.get_name (| globals, "start" |), + BinOp.mult (| + M.get_name (| globals, "i" |), + Constant.int 8 + |) + |) + |) in + let _ := M.call (| + M.get_field (| M.get_name (| globals, "words" |), "append" |), + make_list [ + M.call (| + M.get_field (| M.get_name (| globals, "Uint" |), "from_le_bytes" |), + make_list [ + M.slice (| + M.get_name (| globals, "data" |), + M.get_name (| globals, "start_position" |), + BinOp.add (| + M.get_name (| globals, "start_position" |), + Constant.int 8 + |), + Constant.None_ + |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := M.return_ (| + M.get_name (| globals, "words" |) + |) in + M.pure Constant.None_)). + +Definition Blake2 : Value.t := + builtins.make_klass + [] + [ + + ] + [ + ( + "get_blake2_parameters", + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "self"; "data" ] |) in + let _ := Constant.str " + Extract the parameters required in the Blake2 compression function + from the provided bytes data. + + Parameters + ---------- + data : + The bytes data that has been passed in the message. + " in + let _ := M.assign_local (| + "rounds" , + M.call (| + M.get_field (| M.get_name (| globals, "Uint" |), "from_be_bytes" |), + make_list [ + M.slice (| + M.get_name (| globals, "data" |), + Constant.None_, + Constant.int 4, + Constant.None_ + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "h" , + M.call (| + M.get_name (| globals, "spit_le_to_uint" |), + make_list [ + M.get_name (| globals, "data" |); + Constant.int 4; + Constant.int 8 + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "m" , + M.call (| + M.get_name (| globals, "spit_le_to_uint" |), + make_list [ + M.get_name (| globals, "data" |); + Constant.int 68; + Constant.int 16 + ], + make_dict [] + |) + |) in + let _ := M.assign (| + make_tuple [ M.get_name (| globals, "t_0" |); M.get_name (| globals, "t_1" |) ], + M.call (| + M.get_name (| globals, "spit_le_to_uint" |), + make_list [ + M.get_name (| globals, "data" |); + Constant.int 196; + Constant.int 2 + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "f" , + M.call (| + M.get_field (| M.get_name (| globals, "Uint" |), "from_be_bytes" |), + make_list [ + M.slice (| + M.get_name (| globals, "data" |), + Constant.int 212, + Constant.None_, + Constant.None_ + |) + ], + make_dict [] + |) + |) in + let _ := M.return_ (| + make_tuple [ M.get_name (| globals, "rounds" |); M.get_name (| globals, "h" |); M.get_name (| globals, "m" |); M.get_name (| globals, "t_0" |); M.get_name (| globals, "t_1" |); M.get_name (| globals, "f" |) ] + |) in + M.pure Constant.None_)) + ); + ( + "G", + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "self"; "v"; "a"; "b"; "c"; "d"; "x"; "y" ] |) in + let _ := Constant.str " + The mixing function used in Blake2 + https://datatracker.ietf.org/doc/html/rfc7693#section-3.1 + + Parameters + ---------- + v : + The working vector to be mixed. + a, b, c, d : + Indexes within v of the words to be mixed. + x, y : + The two input words for the mixing. + " in + let _ := M.assign (| + M.get_subscript (| + M.get_name (| globals, "v" |), + M.get_name (| globals, "a" |) + |), + BinOp.mod_ (| + BinOp.add (| + BinOp.add (| + M.get_subscript (| + M.get_name (| globals, "v" |), + M.get_name (| globals, "a" |) + |), + M.get_subscript (| + M.get_name (| globals, "v" |), + M.get_name (| globals, "b" |) + |) + |), + M.get_name (| globals, "x" |) + |), + M.get_field (| M.get_name (| globals, "self" |), "max_word" |) + |) + |) in + let _ := M.assign (| + M.get_subscript (| + M.get_name (| globals, "v" |), + M.get_name (| globals, "d" |) + |), + BinOp.bit_xor (| + BinOp.r_shift (| + BinOp.bit_xor (| + M.get_subscript (| + M.get_name (| globals, "v" |), + M.get_name (| globals, "d" |) + |), + M.get_subscript (| + M.get_name (| globals, "v" |), + M.get_name (| globals, "a" |) + |) + |), + M.get_field (| M.get_name (| globals, "self" |), "R1" |) + |), + BinOp.mod_ (| + BinOp.l_shift (| + BinOp.bit_xor (| + M.get_subscript (| + M.get_name (| globals, "v" |), + M.get_name (| globals, "d" |) + |), + M.get_subscript (| + M.get_name (| globals, "v" |), + M.get_name (| globals, "a" |) + |) + |), + M.get_field (| M.get_name (| globals, "self" |), "w_R1" |) + |), + M.get_field (| M.get_name (| globals, "self" |), "max_word" |) + |) + |) + |) in + let _ := M.assign (| + M.get_subscript (| + M.get_name (| globals, "v" |), + M.get_name (| globals, "c" |) + |), + BinOp.mod_ (| + BinOp.add (| + M.get_subscript (| + M.get_name (| globals, "v" |), + M.get_name (| globals, "c" |) + |), + M.get_subscript (| + M.get_name (| globals, "v" |), + M.get_name (| globals, "d" |) + |) + |), + M.get_field (| M.get_name (| globals, "self" |), "max_word" |) + |) + |) in + let _ := M.assign (| + M.get_subscript (| + M.get_name (| globals, "v" |), + M.get_name (| globals, "b" |) + |), + BinOp.bit_xor (| + BinOp.r_shift (| + BinOp.bit_xor (| + M.get_subscript (| + M.get_name (| globals, "v" |), + M.get_name (| globals, "b" |) + |), + M.get_subscript (| + M.get_name (| globals, "v" |), + M.get_name (| globals, "c" |) + |) + |), + M.get_field (| M.get_name (| globals, "self" |), "R2" |) + |), + BinOp.mod_ (| + BinOp.l_shift (| + BinOp.bit_xor (| + M.get_subscript (| + M.get_name (| globals, "v" |), + M.get_name (| globals, "b" |) + |), + M.get_subscript (| + M.get_name (| globals, "v" |), + M.get_name (| globals, "c" |) + |) + |), + M.get_field (| M.get_name (| globals, "self" |), "w_R2" |) + |), + M.get_field (| M.get_name (| globals, "self" |), "max_word" |) + |) + |) + |) in + let _ := M.assign (| + M.get_subscript (| + M.get_name (| globals, "v" |), + M.get_name (| globals, "a" |) + |), + BinOp.mod_ (| + BinOp.add (| + BinOp.add (| + M.get_subscript (| + M.get_name (| globals, "v" |), + M.get_name (| globals, "a" |) + |), + M.get_subscript (| + M.get_name (| globals, "v" |), + M.get_name (| globals, "b" |) + |) + |), + M.get_name (| globals, "y" |) + |), + M.get_field (| M.get_name (| globals, "self" |), "max_word" |) + |) + |) in + let _ := M.assign (| + M.get_subscript (| + M.get_name (| globals, "v" |), + M.get_name (| globals, "d" |) + |), + BinOp.bit_xor (| + BinOp.r_shift (| + BinOp.bit_xor (| + M.get_subscript (| + M.get_name (| globals, "v" |), + M.get_name (| globals, "d" |) + |), + M.get_subscript (| + M.get_name (| globals, "v" |), + M.get_name (| globals, "a" |) + |) + |), + M.get_field (| M.get_name (| globals, "self" |), "R3" |) + |), + BinOp.mod_ (| + BinOp.l_shift (| + BinOp.bit_xor (| + M.get_subscript (| + M.get_name (| globals, "v" |), + M.get_name (| globals, "d" |) + |), + M.get_subscript (| + M.get_name (| globals, "v" |), + M.get_name (| globals, "a" |) + |) + |), + M.get_field (| M.get_name (| globals, "self" |), "w_R3" |) + |), + M.get_field (| M.get_name (| globals, "self" |), "max_word" |) + |) + |) + |) in + let _ := M.assign (| + M.get_subscript (| + M.get_name (| globals, "v" |), + M.get_name (| globals, "c" |) + |), + BinOp.mod_ (| + BinOp.add (| + M.get_subscript (| + M.get_name (| globals, "v" |), + M.get_name (| globals, "c" |) + |), + M.get_subscript (| + M.get_name (| globals, "v" |), + M.get_name (| globals, "d" |) + |) + |), + M.get_field (| M.get_name (| globals, "self" |), "max_word" |) + |) + |) in + let _ := M.assign (| + M.get_subscript (| + M.get_name (| globals, "v" |), + M.get_name (| globals, "b" |) + |), + BinOp.bit_xor (| + BinOp.r_shift (| + BinOp.bit_xor (| + M.get_subscript (| + M.get_name (| globals, "v" |), + M.get_name (| globals, "b" |) + |), + M.get_subscript (| + M.get_name (| globals, "v" |), + M.get_name (| globals, "c" |) + |) + |), + M.get_field (| M.get_name (| globals, "self" |), "R4" |) + |), + BinOp.mod_ (| + BinOp.l_shift (| + BinOp.bit_xor (| + M.get_subscript (| + M.get_name (| globals, "v" |), + M.get_name (| globals, "b" |) + |), + M.get_subscript (| + M.get_name (| globals, "v" |), + M.get_name (| globals, "c" |) + |) + |), + M.get_field (| M.get_name (| globals, "self" |), "w_R4" |) + |), + M.get_field (| M.get_name (| globals, "self" |), "max_word" |) + |) + |) + |) in + let _ := M.return_ (| + M.get_name (| globals, "v" |) + |) in + M.pure Constant.None_)) + ); + ( + "compress", + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "self"; "num_rounds"; "h"; "m"; "t_0"; "t_1"; "f" ] |) in + let _ := Constant.str " + 'F Compression' from section 3.2 of RFC 7693: + https://tools.ietf.org/html/rfc7693#section-3.2 + + Parameters + ---------- + num_rounds : + The number of rounds. A 32-bit unsigned big-endian word + h : + The state vector. 8 unsigned 64-bit little-endian words + m : + The message block vector. 16 unsigned 64-bit little-endian words + t_0, t_1 : + Offset counters. 2 unsigned 64-bit little-endian words + f: + The final block indicator flag. An 8-bit word + " in + let _ := M.assign_local (| + "v" , + BinOp.mult (| + make_list [ + Constant.int 0 + ], + Constant.int 16 + |) + |) in + let _ := M.assign (| + M.slice (| + M.get_name (| globals, "v" |), + Constant.int 0, + Constant.int 8, + Constant.None_ + |), + M.get_name (| globals, "h" |) + |) in + let _ := M.assign (| + M.slice (| + M.get_name (| globals, "v" |), + Constant.int 8, + Constant.int 15, + Constant.None_ + |), + M.get_field (| M.get_name (| globals, "self" |), "IV" |) + |) in + let _ := M.assign (| + M.get_subscript (| + M.get_name (| globals, "v" |), + Constant.int 12 + |), + BinOp.bit_xor (| + M.get_name (| globals, "t_0" |), + M.get_subscript (| + M.get_field (| M.get_name (| globals, "self" |), "IV" |), + Constant.int 4 + |) + |) + |) in + let _ := M.assign (| + M.get_subscript (| + M.get_name (| globals, "v" |), + Constant.int 13 + |), + BinOp.bit_xor (| + M.get_name (| globals, "t_1" |), + M.get_subscript (| + M.get_field (| M.get_name (| globals, "self" |), "IV" |), + Constant.int 5 + |) + |) + |) in + let _ := + (* if *) + M.if_then_else (| + M.get_name (| globals, "f" |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign (| + M.get_subscript (| + M.get_name (| globals, "v" |), + Constant.int 14 + |), + BinOp.bit_xor (| + M.get_subscript (| + M.get_name (| globals, "v" |), + Constant.int 14 + |), + M.get_field (| M.get_name (| globals, "self" |), "mask_bits" |) + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + M.for_ (| + M.get_name (| globals, "r" |), + M.call (| + M.get_name (| globals, "range" |), + make_list [ + M.get_name (| globals, "num_rounds" |) + ], + make_dict [] + |), + ltac:(M.monadic ( + let _ := M.assign_local (| + "s" , + M.get_subscript (| + M.get_field (| M.get_name (| globals, "self" |), "sigma" |), + BinOp.mod_ (| + M.get_name (| globals, "r" |), + M.get_field (| M.get_name (| globals, "self" |), "sigma_len" |) + |) + |) + |) in + let _ := M.assign_local (| + "v" , + M.call (| + M.get_field (| M.get_name (| globals, "self" |), "G" |), + make_list [ + M.get_name (| globals, "v" |); + Constant.int 0; + Constant.int 4; + Constant.int 8; + Constant.int 12; + M.get_subscript (| + M.get_name (| globals, "m" |), + M.get_subscript (| + M.get_name (| globals, "s" |), + Constant.int 0 + |) + |); + M.get_subscript (| + M.get_name (| globals, "m" |), + M.get_subscript (| + M.get_name (| globals, "s" |), + Constant.int 1 + |) + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "v" , + M.call (| + M.get_field (| M.get_name (| globals, "self" |), "G" |), + make_list [ + M.get_name (| globals, "v" |); + Constant.int 1; + Constant.int 5; + Constant.int 9; + Constant.int 13; + M.get_subscript (| + M.get_name (| globals, "m" |), + M.get_subscript (| + M.get_name (| globals, "s" |), + Constant.int 2 + |) + |); + M.get_subscript (| + M.get_name (| globals, "m" |), + M.get_subscript (| + M.get_name (| globals, "s" |), + Constant.int 3 + |) + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "v" , + M.call (| + M.get_field (| M.get_name (| globals, "self" |), "G" |), + make_list [ + M.get_name (| globals, "v" |); + Constant.int 2; + Constant.int 6; + Constant.int 10; + Constant.int 14; + M.get_subscript (| + M.get_name (| globals, "m" |), + M.get_subscript (| + M.get_name (| globals, "s" |), + Constant.int 4 + |) + |); + M.get_subscript (| + M.get_name (| globals, "m" |), + M.get_subscript (| + M.get_name (| globals, "s" |), + Constant.int 5 + |) + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "v" , + M.call (| + M.get_field (| M.get_name (| globals, "self" |), "G" |), + make_list [ + M.get_name (| globals, "v" |); + Constant.int 3; + Constant.int 7; + Constant.int 11; + Constant.int 15; + M.get_subscript (| + M.get_name (| globals, "m" |), + M.get_subscript (| + M.get_name (| globals, "s" |), + Constant.int 6 + |) + |); + M.get_subscript (| + M.get_name (| globals, "m" |), + M.get_subscript (| + M.get_name (| globals, "s" |), + Constant.int 7 + |) + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "v" , + M.call (| + M.get_field (| M.get_name (| globals, "self" |), "G" |), + make_list [ + M.get_name (| globals, "v" |); + Constant.int 0; + Constant.int 5; + Constant.int 10; + Constant.int 15; + M.get_subscript (| + M.get_name (| globals, "m" |), + M.get_subscript (| + M.get_name (| globals, "s" |), + Constant.int 8 + |) + |); + M.get_subscript (| + M.get_name (| globals, "m" |), + M.get_subscript (| + M.get_name (| globals, "s" |), + Constant.int 9 + |) + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "v" , + M.call (| + M.get_field (| M.get_name (| globals, "self" |), "G" |), + make_list [ + M.get_name (| globals, "v" |); + Constant.int 1; + Constant.int 6; + Constant.int 11; + Constant.int 12; + M.get_subscript (| + M.get_name (| globals, "m" |), + M.get_subscript (| + M.get_name (| globals, "s" |), + Constant.int 10 + |) + |); + M.get_subscript (| + M.get_name (| globals, "m" |), + M.get_subscript (| + M.get_name (| globals, "s" |), + Constant.int 11 + |) + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "v" , + M.call (| + M.get_field (| M.get_name (| globals, "self" |), "G" |), + make_list [ + M.get_name (| globals, "v" |); + Constant.int 2; + Constant.int 7; + Constant.int 8; + Constant.int 13; + M.get_subscript (| + M.get_name (| globals, "m" |), + M.get_subscript (| + M.get_name (| globals, "s" |), + Constant.int 12 + |) + |); + M.get_subscript (| + M.get_name (| globals, "m" |), + M.get_subscript (| + M.get_name (| globals, "s" |), + Constant.int 13 + |) + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "v" , + M.call (| + M.get_field (| M.get_name (| globals, "self" |), "G" |), + make_list [ + M.get_name (| globals, "v" |); + Constant.int 3; + Constant.int 4; + Constant.int 9; + Constant.int 14; + M.get_subscript (| + M.get_name (| globals, "m" |), + M.get_subscript (| + M.get_name (| globals, "s" |), + Constant.int 14 + |) + |); + M.get_subscript (| + M.get_name (| globals, "m" |), + M.get_subscript (| + M.get_name (| globals, "s" |), + Constant.int 15 + |) + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := M.assign_local (| + "result_message_words" , + Constant.str "(* At expr: unsupported node type: GeneratorExp *)" + |) in + let _ := M.return_ (| + M.call (| + M.get_field (| M.get_name (| globals, "struct" |), "pack" |), + make_list_concat (| [ + make_list [ + BinOp.mod_ (| + Constant.str "<8%s", + M.get_field (| M.get_name (| globals, "self" |), "word_format" |) + |) + ]; + M.get_name (| globals, "result_message_words" |) + ] |), + make_dict [] + |) + |) in + M.pure Constant.None_)) + ) + ]. + +Definition Blake2b : Value.t := + builtins.make_klass + [(globals, "Blake2")] + [ + + ] + [ + + ]. diff --git a/CoqOfPython/ethereum/crypto/elliptic_curve.v b/CoqOfPython/ethereum/crypto/elliptic_curve.v new file mode 100644 index 0000000..3b7436b --- /dev/null +++ b/CoqOfPython/ethereum/crypto/elliptic_curve.v @@ -0,0 +1,772 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.crypto.elliptic_curve". + +Definition expr_1 : Value.t := + Constant.str " +Elliptic Curves +^^^^^^^^^^^^^^^ +". + +Axiom typing_imports_Generic : + IsImported globals "typing" "Generic". +Axiom typing_imports_Type : + IsImported globals "typing" "Type". +Axiom typing_imports_TypeVar : + IsImported globals "typing" "TypeVar". + +(* At top_level_stmt: unsupported node type: Import *) + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_Bytes : + IsImported globals "ethereum.base_types" "Bytes". + +Axiom ethereum_crypto_finite_field_imports_Field : + IsImported globals "ethereum.crypto.finite_field" "Field". + +Axiom ethereum_crypto_hash_imports_Hash32 : + IsImported globals "ethereum.crypto.hash" "Hash32". + +Definition SECP256K1N : Value.t := M.run ltac:(M.monadic ( + Constant.int 115792089237316195423570985008687907852837564279074904382605163141518161494337 +)). + +Definition F : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "TypeVar" |), + make_list [ + Constant.str "F" + ], + make_dict [] + |) +)). + +Definition T : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "TypeVar" |), + make_list [ + Constant.str "T" + ], + make_dict [] + |) +)). + +Definition secp256k1_recover : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "r"; "s"; "v"; "msg_hash" ] |) in + let _ := Constant.str " + Recovers the public key from a given signature. + + Parameters + ---------- + r : + TODO + s : + TODO + v : + TODO + msg_hash : + Hash of the message being recovered. + + Returns + ------- + public_key : `ethereum.base_types.Bytes` + Recovered public key. + " in + let _ := M.assign_local (| + "r_bytes" , + M.call (| + M.get_field (| M.get_name (| globals, "r" |), "to_be_bytes32" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "s_bytes" , + M.call (| + M.get_field (| M.get_name (| globals, "s" |), "to_be_bytes32" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "signature" , + M.call (| + M.get_name (| globals, "bytearray" |), + make_list [ + BinOp.mult (| + make_list [ + Constant.int 0 + ], + Constant.int 65 + |) + ], + make_dict [] + |) + |) in + let _ := M.assign (| + M.slice (| + M.get_name (| globals, "signature" |), + BinOp.sub (| + Constant.int 32, + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_name (| globals, "r_bytes" |) + ], + make_dict [] + |) + |), + Constant.int 32, + Constant.None_ + |), + M.get_name (| globals, "r_bytes" |) + |) in + let _ := M.assign (| + M.slice (| + M.get_name (| globals, "signature" |), + BinOp.sub (| + Constant.int 64, + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_name (| globals, "s_bytes" |) + ], + make_dict [] + |) + |), + Constant.int 64, + Constant.None_ + |), + M.get_name (| globals, "s_bytes" |) + |) in + let _ := M.assign (| + M.get_subscript (| + M.get_name (| globals, "signature" |), + Constant.int 64 + |), + M.get_name (| globals, "v" |) + |) in + let _ := M.assign_local (| + "public_key" , + M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, "coincurve" |), "PublicKey" |), "from_signature_and_message" |), + make_list [ + M.call (| + M.get_name (| globals, "bytes" |), + make_list [ + M.get_name (| globals, "signature" |) + ], + make_dict [] + |); + M.get_name (| globals, "msg_hash" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "public_key" , + M.slice (| + M.call (| + M.get_field (| M.get_name (| globals, "public_key" |), "format" |), + make_list [], + make_dict [] + |), + Constant.int 1, + Constant.None_, + Constant.None_ + |) + |) in + let _ := M.return_ (| + M.get_name (| globals, "public_key" |) + |) in + M.pure Constant.None_)). + +Definition EllipticCurve : Value.t := + builtins.make_klass + [(* At base: unsupported node type: Subscript *)] + [ + ( + "point_at_infinity", + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "cls" ] |) in + let _ := Constant.str " + Return the point at infinity. This is the identity element of the group + operation. + + The point at infinity doesn't actually have coordinates so we use + `(0, 0)` (which isn't on the curve) to represent it. + " in + let _ := M.return_ (| + M.call (| + M.get_field (| M.get_name (| globals, "cls" |), "__new__" |), + make_list [ + M.get_name (| globals, "cls" |); + M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, "cls" |), "FIELD" |), "zero" |), + make_list [], + make_dict [] + |); + M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, "cls" |), "FIELD" |), "zero" |), + make_list [], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)) + ) + ] + [ + ( + "__new__", + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "cls"; "x"; "y" ] |) in + let _ := Constant.str " + Make new point on the curve. The point is not checked to see if it is + on the curve. + " in + let _ := M.assign_local (| + "res" , + M.call (| + M.get_field (| M.get_name (| globals, "object" |), "__new__" |), + make_list [ + M.get_name (| globals, "cls" |) + ], + make_dict [] + |) + |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, "res" |), "x" |), + M.get_name (| globals, "x" |) + |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, "res" |), "y" |), + M.get_name (| globals, "y" |) + |) in + let _ := M.return_ (| + M.get_name (| globals, "res" |) + |) in + M.pure Constant.None_)) + ); + ( + "__init__", + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "self"; "x"; "y" ] |) in + let _ := Constant.str " + Checks if the point is on the curve. To skip this check call + `__new__()` directly. + " in + let _ := + (* if *) + M.if_then_else (| + BoolOp.and (| + BoolOp.or (| + Compare.not_eq (| + M.get_name (| globals, "x" |), + M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, "self" |), "FIELD" |), "zero" |), + make_list [], + make_dict [] + |) + |), + ltac:(M.monadic ( + Compare.not_eq (| + M.get_name (| globals, "y" |), + M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, "self" |), "FIELD" |), "zero" |), + make_list [], + make_dict [] + |) + |) + )) + |), + ltac:(M.monadic ( + Compare.not_eq (| + BinOp.sub (| + BinOp.sub (| + BinOp.sub (| + BinOp.pow (| + M.get_name (| globals, "y" |), + Constant.int 2 + |), + BinOp.pow (| + M.get_name (| globals, "x" |), + Constant.int 3 + |) + |), + BinOp.mult (| + M.get_field (| M.get_name (| globals, "self" |), "A" |), + M.get_name (| globals, "x" |) + |) + |), + M.get_field (| M.get_name (| globals, "self" |), "B" |) + |), + M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, "self" |), "FIELD" |), "zero" |), + make_list [], + make_dict [] + |) + |) + )) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.call (| + M.get_name (| globals, "ValueError" |), + make_list [ + Constant.str "Point not on curve" + ], + make_dict [] + |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + M.pure Constant.None_)) + ); + ( + "__eq__", + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "self"; "other" ] |) in + let _ := Constant.str " + Test two points for equality. + " in + let _ := + (* if *) + M.if_then_else (| + UnOp.not (| M.call (| + M.get_name (| globals, "isinstance" |), + make_list [ + M.get_name (| globals, "other" |); + M.call (| + M.get_name (| globals, "type" |), + make_list [ + M.get_name (| globals, "self" |) + ], + make_dict [] + |) + ], + make_dict [] + |) |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + Constant.bool false + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.return_ (| + BoolOp.and (| + Compare.eq (| + M.get_field (| M.get_name (| globals, "self" |), "x" |), + M.get_field (| M.get_name (| globals, "other" |), "x" |) + |), + ltac:(M.monadic ( + Compare.eq (| + M.get_field (| M.get_name (| globals, "self" |), "y" |), + M.get_field (| M.get_name (| globals, "other" |), "y" |) + |) + )) + |) + |) in + M.pure Constant.None_)) + ); + ( + "__str__", + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "self" ] |) in + let _ := Constant.str " + Stringify a point as its coordinates. + " in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, "str" |), + make_list [ + make_tuple [ M.get_field (| M.get_name (| globals, "self" |), "x" |); M.get_field (| M.get_name (| globals, "self" |), "y" |) ] + ], + make_dict [] + |) + |) in + M.pure Constant.None_)) + ); + ( + "double", + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "self" ] |) in + let _ := Constant.str " + Add a point to itself. + " in + let _ := M.assign (| + make_tuple [ M.get_name (| globals, "x" |); M.get_name (| globals, "y" |); M.get_name (| globals, "F" |) ], + make_tuple [ M.get_field (| M.get_name (| globals, "self" |), "x" |); M.get_field (| M.get_name (| globals, "self" |), "y" |); M.get_field (| M.get_name (| globals, "self" |), "FIELD" |) ] + |) in + let _ := + (* if *) + M.if_then_else (| + BoolOp.and (| + Compare.eq (| + M.get_name (| globals, "x" |), + Constant.int 0 + |), + ltac:(M.monadic ( + Compare.eq (| + M.get_name (| globals, "y" |), + Constant.int 0 + |) + )) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + M.get_name (| globals, "self" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "lam" , + BinOp.div (| + BinOp.add (| + BinOp.mult (| + M.call (| + M.get_field (| M.get_name (| globals, "F" |), "from_int" |), + make_list [ + Constant.int 3 + ], + make_dict [] + |), + BinOp.pow (| + M.get_name (| globals, "x" |), + Constant.int 2 + |) + |), + M.get_field (| M.get_name (| globals, "self" |), "A" |) + |), + BinOp.mult (| + M.call (| + M.get_field (| M.get_name (| globals, "F" |), "from_int" |), + make_list [ + Constant.int 2 + ], + make_dict [] + |), + M.get_name (| globals, "y" |) + |) + |) + |) in + let _ := M.assign_local (| + "new_x" , + BinOp.sub (| + BinOp.sub (| + BinOp.pow (| + M.get_name (| globals, "lam" |), + Constant.int 2 + |), + M.get_name (| globals, "x" |) + |), + M.get_name (| globals, "x" |) + |) + |) in + let _ := M.assign_local (| + "new_y" , + BinOp.sub (| + BinOp.mult (| + M.get_name (| globals, "lam" |), + BinOp.sub (| + M.get_name (| globals, "x" |), + M.get_name (| globals, "new_x" |) + |) + |), + M.get_name (| globals, "y" |) + |) + |) in + let _ := M.return_ (| + M.call (| + M.get_field (| M.get_name (| globals, "self" |), "__new__" |), + make_list [ + M.call (| + M.get_name (| globals, "type" |), + make_list [ + M.get_name (| globals, "self" |) + ], + make_dict [] + |); + M.get_name (| globals, "new_x" |); + M.get_name (| globals, "new_y" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)) + ); + ( + "__add__", + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "self"; "other" ] |) in + let _ := Constant.str " + Add two points together. + " in + let _ := M.assign_local (| + "ZERO" , + M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, "self" |), "FIELD" |), "zero" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.assign (| + make_tuple [ M.get_name (| globals, "self_x" |); M.get_name (| globals, "self_y" |); M.get_name (| globals, "other_x" |); M.get_name (| globals, "other_y" |) ], + make_tuple [ M.get_field (| M.get_name (| globals, "self" |), "x" |); M.get_field (| M.get_name (| globals, "self" |), "y" |); M.get_field (| M.get_name (| globals, "other" |), "x" |); M.get_field (| M.get_name (| globals, "other" |), "y" |) ] + |) in + let _ := + (* if *) + M.if_then_else (| + BoolOp.and (| + Compare.eq (| + M.get_name (| globals, "self_x" |), + M.get_name (| globals, "ZERO" |) + |), + ltac:(M.monadic ( + Compare.eq (| + M.get_name (| globals, "self_y" |), + M.get_name (| globals, "ZERO" |) + |) + )) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + M.get_name (| globals, "other" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + BoolOp.and (| + Compare.eq (| + M.get_name (| globals, "other_x" |), + M.get_name (| globals, "ZERO" |) + |), + ltac:(M.monadic ( + Compare.eq (| + M.get_name (| globals, "other_y" |), + M.get_name (| globals, "ZERO" |) + |) + )) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + M.get_name (| globals, "self" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, "self_x" |), + M.get_name (| globals, "other_x" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, "self_y" |), + M.get_name (| globals, "other_y" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + M.call (| + M.get_field (| M.get_name (| globals, "self" |), "double" |), + make_list [], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.return_ (| + M.call (| + M.get_field (| M.get_name (| globals, "self" |), "point_at_infinity" |), + make_list [], + make_dict [] + |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "lam" , + BinOp.div (| + BinOp.sub (| + M.get_name (| globals, "other_y" |), + M.get_name (| globals, "self_y" |) + |), + BinOp.sub (| + M.get_name (| globals, "other_x" |), + M.get_name (| globals, "self_x" |) + |) + |) + |) in + let _ := M.assign_local (| + "x" , + BinOp.sub (| + BinOp.sub (| + BinOp.pow (| + M.get_name (| globals, "lam" |), + Constant.int 2 + |), + M.get_name (| globals, "self_x" |) + |), + M.get_name (| globals, "other_x" |) + |) + |) in + let _ := M.assign_local (| + "y" , + BinOp.sub (| + BinOp.mult (| + M.get_name (| globals, "lam" |), + BinOp.sub (| + M.get_name (| globals, "self_x" |), + M.get_name (| globals, "x" |) + |) + |), + M.get_name (| globals, "self_y" |) + |) + |) in + let _ := M.return_ (| + M.call (| + M.get_field (| M.get_name (| globals, "self" |), "__new__" |), + make_list [ + M.call (| + M.get_name (| globals, "type" |), + make_list [ + M.get_name (| globals, "self" |) + ], + make_dict [] + |); + M.get_name (| globals, "x" |); + M.get_name (| globals, "y" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)) + ); + ( + "mul_by", + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "self"; "n" ] |) in + let _ := Constant.str " + Multiply `self` by `n` using the double and add algorithm. + " in + let _ := M.assign_local (| + "res" , + M.call (| + M.get_field (| M.get_name (| globals, "self" |), "__new__" |), + make_list [ + M.call (| + M.get_name (| globals, "type" |), + make_list [ + M.get_name (| globals, "self" |) + ], + make_dict [] + |); + M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, "self" |), "FIELD" |), "zero" |), + make_list [], + make_dict [] + |); + M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, "self" |), "FIELD" |), "zero" |), + make_list [], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "s" , + M.get_name (| globals, "self" |) + |) in + let _ := + M.while (| + Compare.not_eq (| + M.get_name (| globals, "n" |), + Constant.int 0 + |), + ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + BinOp.mod_ (| + M.get_name (| globals, "n" |), + Constant.int 2 + |), + Constant.int 1 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "res" , + BinOp.add (| + M.get_name (| globals, "res" |), + M.get_name (| globals, "s" |) + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "s" , + BinOp.add (| + M.get_name (| globals, "s" |), + M.get_name (| globals, "s" |) + |) + |) in + let _ := M.assign_op_local (| + BinOp.floor_div, + "n", + Constant.int 2 + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := M.return_ (| + M.get_name (| globals, "res" |) + |) in + M.pure Constant.None_)) + ) + ]. diff --git a/CoqOfPython/ethereum/crypto/finite_field.v b/CoqOfPython/ethereum/crypto/finite_field.v new file mode 100644 index 0000000..fa90840 --- /dev/null +++ b/CoqOfPython/ethereum/crypto/finite_field.v @@ -0,0 +1,2257 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.crypto.finite_field". + +Definition expr_1 : Value.t := + Constant.str " +Finite Fields +^^^^^^^^^^^^^ +". + +Axiom typing_imports_Iterable : + IsImported globals "typing" "Iterable". +Axiom typing_imports_List : + IsImported globals "typing" "List". +Axiom typing_imports_Tuple : + IsImported globals "typing" "Tuple". +Axiom typing_imports_Type : + IsImported globals "typing" "Type". +Axiom typing_imports_TypeVar : + IsImported globals "typing" "TypeVar". +Axiom typing_imports_cast : + IsImported globals "typing" "cast". + +Axiom typing_extensions_imports_Protocol : + IsImported globals "typing_extensions" "Protocol". + +Axiom ethereum_base_types_imports_Bytes : + IsImported globals "ethereum.base_types" "Bytes". +Axiom ethereum_base_types_imports_Bytes32 : + IsImported globals "ethereum.base_types" "Bytes32". + +Definition F : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "TypeVar" |), + make_list [ + Constant.str "F" + ], + make_dict [] + |) +)). + +Definition Field : Value.t := + builtins.make_klass + [(globals, "Protocol")] + [ + ( + "zero", + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "cls" ] |) in + let _ := Constant.ellipsis in + M.pure Constant.None_)) + ); + ( + "from_int", + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "cls"; "n" ] |) in + let _ := Constant.ellipsis in + M.pure Constant.None_)) + ) + ] + [ + ( + "__radd__", + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "self"; "left" ] |) in + let _ := Constant.ellipsis in + M.pure Constant.None_)) + ); + ( + "__add__", + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "self"; "right" ] |) in + let _ := Constant.ellipsis in + M.pure Constant.None_)) + ); + ( + "__iadd__", + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "self"; "right" ] |) in + let _ := Constant.ellipsis in + M.pure Constant.None_)) + ); + ( + "__sub__", + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "self"; "right" ] |) in + let _ := Constant.ellipsis in + M.pure Constant.None_)) + ); + ( + "__rsub__", + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "self"; "left" ] |) in + let _ := Constant.ellipsis in + M.pure Constant.None_)) + ); + ( + "__mul__", + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "self"; "right" ] |) in + let _ := Constant.ellipsis in + M.pure Constant.None_)) + ); + ( + "__rmul__", + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "self"; "left" ] |) in + let _ := Constant.ellipsis in + M.pure Constant.None_)) + ); + ( + "__imul__", + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "self"; "right" ] |) in + let _ := Constant.ellipsis in + M.pure Constant.None_)) + ); + ( + "__pow__", + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "self"; "exponent" ] |) in + let _ := Constant.ellipsis in + M.pure Constant.None_)) + ); + ( + "__ipow__", + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "self"; "right" ] |) in + let _ := Constant.ellipsis in + M.pure Constant.None_)) + ); + ( + "__neg__", + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "self" ] |) in + let _ := Constant.ellipsis in + M.pure Constant.None_)) + ); + ( + "__truediv__", + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "self"; "right" ] |) in + let _ := Constant.ellipsis in + M.pure Constant.None_)) + ) + ]. + +Definition T : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "TypeVar" |), + make_list [ + Constant.str "T" + ], + make_dict [] + |) +)). + +Definition PrimeField : Value.t := + builtins.make_klass + [(globals, "int"); (globals, "Field")] + [ + ( + "from_be_bytes", + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "cls"; "buffer" ] |) in + let _ := Constant.str " + Converts a sequence of bytes into a element of the field. + Parameters + ---------- + buffer : + Bytes to decode. + Returns + ------- + self : `T` + Unsigned integer decoded from `buffer`. + " in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, "cls" |), + make_list [ + M.call (| + M.get_field (| M.get_name (| globals, "int" |), "from_bytes" |), + make_list [ + M.get_name (| globals, "buffer" |); + Constant.str "big" + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)) + ); + ( + "zero", + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "cls" ] |) in + let _ := M.return_ (| + M.call (| + M.get_field (| M.get_name (| globals, "cls" |), "__new__" |), + make_list [ + M.get_name (| globals, "cls" |); + Constant.int 0 + ], + make_dict [] + |) + |) in + M.pure Constant.None_)) + ); + ( + "from_int", + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "cls"; "n" ] |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, "cls" |), + make_list [ + M.get_name (| globals, "n" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)) + ) + ] + [ + ( + "__new__", + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "cls"; "value" ] |) in + let _ := M.return_ (| + M.call (| + M.get_field (| M.get_name (| globals, "int" |), "__new__" |), + make_list [ + M.get_name (| globals, "cls" |); + BinOp.mod_ (| + M.get_name (| globals, "value" |), + M.get_field (| M.get_name (| globals, "cls" |), "PRIME" |) + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)) + ); + ( + "__radd__", + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "self"; "left" ] |) in + let _ := M.return_ (| + M.call (| + M.get_field (| M.get_name (| globals, "self" |), "__add__" |), + make_list [ + M.get_name (| globals, "left" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)) + ); + ( + "__add__", + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "self"; "right" ] |) in + let _ := + (* if *) + M.if_then_else (| + UnOp.not (| M.call (| + M.get_name (| globals, "isinstance" |), + make_list [ + M.get_name (| globals, "right" |); + M.get_name (| globals, "int" |) + ], + make_dict [] + |) |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + M.get_name (| globals, "NotImplemented" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.return_ (| + M.call (| + M.get_field (| M.get_name (| globals, "self" |), "__new__" |), + make_list [ + M.call (| + M.get_name (| globals, "type" |), + make_list [ + M.get_name (| globals, "self" |) + ], + make_dict [] + |); + M.call (| + M.get_field (| M.get_name (| globals, "int" |), "__add__" |), + make_list [ + M.get_name (| globals, "self" |); + M.get_name (| globals, "right" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)) + ); + ( + "__iadd__", + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "self"; "right" ] |) in + let _ := M.return_ (| + M.call (| + M.get_field (| M.get_name (| globals, "self" |), "__add__" |), + make_list [ + M.get_name (| globals, "right" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)) + ); + ( + "__sub__", + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "self"; "right" ] |) in + let _ := + (* if *) + M.if_then_else (| + UnOp.not (| M.call (| + M.get_name (| globals, "isinstance" |), + make_list [ + M.get_name (| globals, "right" |); + M.get_name (| globals, "int" |) + ], + make_dict [] + |) |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + M.get_name (| globals, "NotImplemented" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.return_ (| + M.call (| + M.get_field (| M.get_name (| globals, "self" |), "__new__" |), + make_list [ + M.call (| + M.get_name (| globals, "type" |), + make_list [ + M.get_name (| globals, "self" |) + ], + make_dict [] + |); + M.call (| + M.get_field (| M.get_name (| globals, "int" |), "__sub__" |), + make_list [ + M.get_name (| globals, "self" |); + M.get_name (| globals, "right" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)) + ); + ( + "__rsub__", + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "self"; "left" ] |) in + let _ := + (* if *) + M.if_then_else (| + UnOp.not (| M.call (| + M.get_name (| globals, "isinstance" |), + make_list [ + M.get_name (| globals, "left" |); + M.get_name (| globals, "int" |) + ], + make_dict [] + |) |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + M.get_name (| globals, "NotImplemented" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.return_ (| + M.call (| + M.get_field (| M.get_name (| globals, "self" |), "__new__" |), + make_list [ + M.call (| + M.get_name (| globals, "type" |), + make_list [ + M.get_name (| globals, "self" |) + ], + make_dict [] + |); + M.call (| + M.get_field (| M.get_name (| globals, "int" |), "__rsub__" |), + make_list [ + M.get_name (| globals, "self" |); + M.get_name (| globals, "left" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)) + ); + ( + "__mul__", + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "self"; "right" ] |) in + let _ := + (* if *) + M.if_then_else (| + UnOp.not (| M.call (| + M.get_name (| globals, "isinstance" |), + make_list [ + M.get_name (| globals, "right" |); + M.get_name (| globals, "int" |) + ], + make_dict [] + |) |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + M.get_name (| globals, "NotImplemented" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.return_ (| + M.call (| + M.get_field (| M.get_name (| globals, "self" |), "__new__" |), + make_list [ + M.call (| + M.get_name (| globals, "type" |), + make_list [ + M.get_name (| globals, "self" |) + ], + make_dict [] + |); + M.call (| + M.get_field (| M.get_name (| globals, "int" |), "__mul__" |), + make_list [ + M.get_name (| globals, "self" |); + M.get_name (| globals, "right" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)) + ); + ( + "__rmul__", + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "self"; "left" ] |) in + let _ := M.return_ (| + M.call (| + M.get_field (| M.get_name (| globals, "self" |), "__mul__" |), + make_list [ + M.get_name (| globals, "left" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)) + ); + ( + "__imul__", + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "self"; "right" ] |) in + let _ := M.return_ (| + M.call (| + M.get_field (| M.get_name (| globals, "self" |), "__mul__" |), + make_list [ + M.get_name (| globals, "right" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)) + ); + ( + "__pow__", + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "self"; "exponent" ] |) in + let _ := M.return_ (| + M.call (| + M.get_field (| M.get_name (| globals, "self" |), "__new__" |), + make_list [ + M.call (| + M.get_name (| globals, "type" |), + make_list [ + M.get_name (| globals, "self" |) + ], + make_dict [] + |); + M.call (| + M.get_field (| M.get_name (| globals, "int" |), "__pow__" |), + make_list [ + M.call (| + M.get_name (| globals, "int" |), + make_list [ + M.get_name (| globals, "self" |) + ], + make_dict [] + |); + M.get_name (| globals, "exponent" |); + M.get_field (| M.get_name (| globals, "self" |), "PRIME" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)) + ); + ( + "__ipow__", + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "self"; "right" ] |) in + let _ := M.return_ (| + M.call (| + M.get_field (| M.get_name (| globals, "self" |), "__pow__" |), + make_list [ + M.get_name (| globals, "right" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)) + ); + ( + "__neg__", + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "self" ] |) in + let _ := M.return_ (| + M.call (| + M.get_field (| M.get_name (| globals, "self" |), "__new__" |), + make_list [ + M.call (| + M.get_name (| globals, "type" |), + make_list [ + M.get_name (| globals, "self" |) + ], + make_dict [] + |); + M.call (| + M.get_field (| M.get_name (| globals, "int" |), "__neg__" |), + make_list [ + M.get_name (| globals, "self" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)) + ); + ( + "__truediv__", + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "self"; "right" ] |) in + let _ := M.return_ (| + BinOp.mult (| + M.get_name (| globals, "self" |), + M.call (| + M.get_field (| M.get_name (| globals, "right" |), "multiplicative_inverse" |), + make_list [], + make_dict [] + |) + |) + |) in + M.pure Constant.None_)) + ); + ( + "multiplicative_inverse", + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "self" ] |) in + let _ := M.return_ (| + BinOp.pow (| + M.get_name (| globals, "self" |), + UnOp.sub (| Constant.int 1 |) + |) + |) in + M.pure Constant.None_)) + ); + ( + "to_be_bytes32", + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "self" ] |) in + let _ := Constant.str " + Converts this arbitrarily sized unsigned integer into its big endian + representation with exactly 32 bytes. + Returns + ------- + big_endian : `Bytes32` + Big endian (most significant bits first) representation. + " in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, "Bytes32" |), + make_list [ + M.call (| + M.get_field (| M.get_name (| globals, "self" |), "to_bytes" |), + make_list [ + Constant.int 32; + Constant.str "big" + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)) + ) + ]. + +Definition U : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "TypeVar" |), + make_list [ + Constant.str "U" + ], + make_dict [] + |) +)). + +Definition GaloisField : Value.t := + builtins.make_klass + [(globals, "tuple"); (globals, "Field")] + [ + ( + "zero", + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "cls" ] |) in + let _ := M.return_ (| + M.call (| + M.get_field (| M.get_name (| globals, "cls" |), "__new__" |), + make_list [ + M.get_name (| globals, "cls" |); + BinOp.mult (| + make_list [ + Constant.int 0 + ], + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_field (| M.get_name (| globals, "cls" |), "MODULUS" |) + ], + make_dict [] + |) + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)) + ); + ( + "from_int", + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "cls"; "n" ] |) in + let _ := M.return_ (| + M.call (| + M.get_field (| M.get_name (| globals, "cls" |), "__new__" |), + make_list [ + M.get_name (| globals, "cls" |); + BinOp.add (| + make_list [ + M.get_name (| globals, "n" |) + ], + BinOp.mult (| + make_list [ + Constant.int 0 + ], + BinOp.sub (| + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_field (| M.get_name (| globals, "cls" |), "MODULUS" |) + ], + make_dict [] + |), + Constant.int 1 + |) + |) + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)) + ); + ( + "calculate_frobenius_coefficients", + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "cls" ] |) in + let _ := Constant.str " + Calculate the coefficients needed by `frobenius()`. + " in + let _ := M.assign_local (| + "coefficients" , + make_list [] + |) in + let _ := + M.for_ (| + M.get_name (| globals, "i" |), + M.call (| + M.get_name (| globals, "range" |), + make_list [ + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_field (| M.get_name (| globals, "cls" |), "MODULUS" |) + ], + make_dict [] + |) + ], + make_dict [] + |), + ltac:(M.monadic ( + let _ := M.assign_local (| + "x" , + BinOp.mult (| + make_list [ + Constant.int 0 + ], + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_field (| M.get_name (| globals, "cls" |), "MODULUS" |) + ], + make_dict [] + |) + |) + |) in + let _ := M.assign (| + M.get_subscript (| + M.get_name (| globals, "x" |), + M.get_name (| globals, "i" |) + |), + Constant.int 1 + |) in + let _ := M.call (| + M.get_field (| M.get_name (| globals, "coefficients" |), "append" |), + make_list [ + BinOp.pow (| + M.call (| + M.get_field (| M.get_name (| globals, "cls" |), "__new__" |), + make_list [ + M.get_name (| globals, "cls" |); + M.get_name (| globals, "x" |) + ], + make_dict [] + |), + M.get_field (| M.get_name (| globals, "cls" |), "PRIME" |) + |) + ], + make_dict [] + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, "tuple" |), + make_list [ + M.get_name (| globals, "coefficients" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)) + ) + ] + [ + ( + "__new__", + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "cls"; "iterable" ] |) in + let _ := M.assign_local (| + "self" , + M.call (| + M.get_field (| M.get_name (| globals, "tuple" |), "__new__" |), + make_list [ + M.get_name (| globals, "cls" |); + Constant.str "(* At expr: unsupported node type: GeneratorExp *)" + ], + make_dict [] + |) + |) in + let _ := M.assert (| Compare.eq (| + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_name (| globals, "self" |) + ], + make_dict [] + |), + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_field (| M.get_name (| globals, "cls" |), "MODULUS" |) + ], + make_dict [] + |) + |) |) in + let _ := M.return_ (| + M.get_name (| globals, "self" |) + |) in + M.pure Constant.None_)) + ); + ( + "__add__", + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "self"; "right" ] |) in + let _ := + (* if *) + M.if_then_else (| + UnOp.not (| M.call (| + M.get_name (| globals, "isinstance" |), + make_list [ + M.get_name (| globals, "right" |); + M.call (| + M.get_name (| globals, "type" |), + make_list [ + M.get_name (| globals, "self" |) + ], + make_dict [] + |) + ], + make_dict [] + |) |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + M.get_name (| globals, "NotImplemented" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.return_ (| + M.call (| + M.get_field (| M.get_name (| globals, "self" |), "__new__" |), + make_list [ + M.call (| + M.get_name (| globals, "type" |), + make_list [ + M.get_name (| globals, "self" |) + ], + make_dict [] + |); + Constant.str "(* At expr: unsupported node type: GeneratorExp *)" + ], + make_dict [] + |) + |) in + M.pure Constant.None_)) + ); + ( + "__radd__", + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "self"; "left" ] |) in + let _ := M.return_ (| + M.call (| + M.get_field (| M.get_name (| globals, "self" |), "__add__" |), + make_list [ + M.get_name (| globals, "left" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)) + ); + ( + "__iadd__", + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "self"; "right" ] |) in + let _ := M.return_ (| + M.call (| + M.get_field (| M.get_name (| globals, "self" |), "__add__" |), + make_list [ + M.get_name (| globals, "right" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)) + ); + ( + "__sub__", + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "self"; "right" ] |) in + let _ := + (* if *) + M.if_then_else (| + UnOp.not (| M.call (| + M.get_name (| globals, "isinstance" |), + make_list [ + M.get_name (| globals, "right" |); + M.call (| + M.get_name (| globals, "type" |), + make_list [ + M.get_name (| globals, "self" |) + ], + make_dict [] + |) + ], + make_dict [] + |) |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + M.get_name (| globals, "NotImplemented" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in +(* At stmt: unsupported node type: AnnAssign *) +(* At stmt: unsupported node type: AnnAssign *) + let _ := M.return_ (| + M.call (| + M.get_field (| M.get_name (| globals, "self" |), "__new__" |), + make_list [ + M.call (| + M.get_name (| globals, "type" |), + make_list [ + M.get_name (| globals, "self" |) + ], + make_dict [] + |); + Constant.str "(* At expr: unsupported node type: GeneratorExp *)" + ], + make_dict [] + |) + |) in + M.pure Constant.None_)) + ); + ( + "__rsub__", + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "self"; "left" ] |) in + let _ := + (* if *) + M.if_then_else (| + UnOp.not (| M.call (| + M.get_name (| globals, "isinstance" |), + make_list [ + M.get_name (| globals, "left" |); + M.call (| + M.get_name (| globals, "type" |), + make_list [ + M.get_name (| globals, "self" |) + ], + make_dict [] + |) + ], + make_dict [] + |) |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + M.get_name (| globals, "NotImplemented" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.return_ (| + M.call (| + M.get_field (| M.get_name (| globals, "self" |), "__new__" |), + make_list [ + M.call (| + M.get_name (| globals, "type" |), + make_list [ + M.get_name (| globals, "self" |) + ], + make_dict [] + |); + Constant.str "(* At expr: unsupported node type: GeneratorExp *)" + ], + make_dict [] + |) + |) in + M.pure Constant.None_)) + ); + ( + "__mul__", + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "self"; "right" ] |) in + let _ := M.assign_local (| + "modulus" , + M.get_field (| M.get_name (| globals, "self" |), "MODULUS" |) + |) in + let _ := M.assign_local (| + "degree" , + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_name (| globals, "modulus" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "prime" , + M.get_field (| M.get_name (| globals, "self" |), "PRIME" |) + |) in + let _ := M.assign_local (| + "mul" , + BinOp.mult (| + make_list [ + Constant.int 0 + ], + BinOp.mult (| + M.get_name (| globals, "degree" |), + Constant.int 2 + |) + |) + |) in + let _ := + M.for_ (| + M.get_name (| globals, "i" |), + M.call (| + M.get_name (| globals, "range" |), + make_list [ + M.get_name (| globals, "degree" |) + ], + make_dict [] + |), + ltac:(M.monadic ( + let _ := + M.for_ (| + M.get_name (| globals, "j" |), + M.call (| + M.get_name (| globals, "range" |), + make_list [ + M.get_name (| globals, "degree" |) + ], + make_dict [] + |), + ltac:(M.monadic ( + let _ := M.assign_op (| + BinOp.add, + M.get_subscript (| + M.get_name (| globals, "mul" |), + BinOp.add (| + M.get_name (| globals, "i" |), + M.get_name (| globals, "j" |) + |) + |), + BinOp.mult (| + M.get_subscript (| + M.get_name (| globals, "self" |), + M.get_name (| globals, "i" |) + |), + M.get_subscript (| + M.get_name (| globals, "right" |), + M.get_name (| globals, "j" |) + |) + |) + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := + M.for_ (| + M.get_name (| globals, "i" |), + M.call (| + M.get_name (| globals, "range" |), + make_list [ + BinOp.sub (| + BinOp.mult (| + M.get_name (| globals, "degree" |), + Constant.int 2 + |), + Constant.int 1 + |); + BinOp.sub (| + M.get_name (| globals, "degree" |), + Constant.int 1 + |); + UnOp.sub (| Constant.int 1 |) + ], + make_dict [] + |), + ltac:(M.monadic ( + let _ := + M.for_ (| + M.get_name (| globals, "j" |), + M.call (| + M.get_name (| globals, "range" |), + make_list [ + BinOp.sub (| + M.get_name (| globals, "i" |), + M.get_name (| globals, "degree" |) + |); + M.get_name (| globals, "i" |) + ], + make_dict [] + |), + ltac:(M.monadic ( + let _ := M.assign_op (| + BinOp.sub, + M.get_subscript (| + M.get_name (| globals, "mul" |), + M.get_name (| globals, "j" |) + |), + BinOp.mod_ (| + BinOp.mult (| + M.get_subscript (| + M.get_name (| globals, "mul" |), + M.get_name (| globals, "i" |) + |), + M.get_subscript (| + M.get_name (| globals, "modulus" |), + BinOp.sub (| + M.get_name (| globals, "degree" |), + BinOp.sub (| + M.get_name (| globals, "i" |), + M.get_name (| globals, "j" |) + |) + |) + |) + |), + M.get_name (| globals, "prime" |) + |) + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := M.return_ (| + M.call (| + M.get_field (| M.get_name (| globals, "self" |), "__new__" |), + make_list [ + M.call (| + M.get_name (| globals, "type" |), + make_list [ + M.get_name (| globals, "self" |) + ], + make_dict [] + |); + M.slice (| + M.get_name (| globals, "mul" |), + Constant.None_, + M.get_name (| globals, "degree" |), + Constant.None_ + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)) + ); + ( + "__rmul__", + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "self"; "left" ] |) in + let _ := M.return_ (| + M.call (| + M.get_field (| M.get_name (| globals, "self" |), "__mul__" |), + make_list [ + M.get_name (| globals, "left" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)) + ); + ( + "__imul__", + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "self"; "right" ] |) in + let _ := M.return_ (| + M.call (| + M.get_field (| M.get_name (| globals, "self" |), "__mul__" |), + make_list [ + M.get_name (| globals, "right" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)) + ); + ( + "__truediv__", + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "self"; "right" ] |) in + let _ := M.return_ (| + BinOp.mult (| + M.get_name (| globals, "self" |), + M.call (| + M.get_field (| M.get_name (| globals, "right" |), "multiplicative_inverse" |), + make_list [], + make_dict [] + |) + |) + |) in + M.pure Constant.None_)) + ); + ( + "__neg__", + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "self" ] |) in + let _ := M.return_ (| + M.call (| + M.get_field (| M.get_name (| globals, "self" |), "__new__" |), + make_list [ + M.call (| + M.get_name (| globals, "type" |), + make_list [ + M.get_name (| globals, "self" |) + ], + make_dict [] + |); + Constant.str "(* At expr: unsupported node type: GeneratorExp *)" + ], + make_dict [] + |) + |) in + M.pure Constant.None_)) + ); + ( + "scalar_mul", + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "self"; "x" ] |) in + let _ := Constant.str " + Multiply a field element by a integer. This is faster than using + `from_int()` and field multiplication. + " in + let _ := M.return_ (| + M.call (| + M.get_field (| M.get_name (| globals, "self" |), "__new__" |), + make_list [ + M.call (| + M.get_name (| globals, "type" |), + make_list [ + M.get_name (| globals, "self" |) + ], + make_dict [] + |); + Constant.str "(* At expr: unsupported node type: GeneratorExp *)" + ], + make_dict [] + |) + |) in + M.pure Constant.None_)) + ); + ( + "deg", + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "self" ] |) in + let _ := Constant.str " + This is a support function for `multiplicative_inverse()`. + " in + let _ := + M.for_ (| + M.get_name (| globals, "i" |), + M.call (| + M.get_name (| globals, "range" |), + make_list [ + BinOp.sub (| + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_field (| M.get_name (| globals, "self" |), "MODULUS" |) + ], + make_dict [] + |), + Constant.int 1 + |); + UnOp.sub (| Constant.int 1 |); + UnOp.sub (| Constant.int 1 |) + ], + make_dict [] + |), + ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + Compare.not_eq (| + M.get_subscript (| + M.get_name (| globals, "self" |), + M.get_name (| globals, "i" |) + |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + M.get_name (| globals, "i" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := M.raise (| Some (M.call (| + M.get_name (| globals, "ValueError" |), + make_list [ + Constant.str "deg() does not support zero" + ], + make_dict [] + |)) |) in + M.pure Constant.None_)) + ); + ( + "multiplicative_inverse", + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "self" ] |) in + let _ := Constant.str " + Calculate the multiplicative inverse. Uses the Euclidean algorithm. + " in +(* At stmt: unsupported node type: AnnAssign *) + let _ := M.assign_local (| + "p" , + M.get_field (| M.get_name (| globals, "self" |), "PRIME" |) + |) in + let _ := M.assign (| + make_tuple [ M.get_name (| globals, "x1" |); M.get_name (| globals, "f1" |) ], + make_tuple [ M.call (| + M.get_name (| globals, "list" |), + make_list [ + M.get_field (| M.get_name (| globals, "self" |), "MODULUS" |) + ], + make_dict [] + |); BinOp.mult (| + make_list [ + Constant.int 0 + ], + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_name (| globals, "self" |) + ], + make_dict [] + |) + |) ] + |) in + let _ := M.assign (| + make_tuple [ M.get_name (| globals, "x2" |); M.get_name (| globals, "f2" |); M.get_name (| globals, "d2" |) ], + make_tuple [ M.call (| + M.get_name (| globals, "list" |), + make_list [ + M.get_name (| globals, "self" |) + ], + make_dict [] + |); BinOp.add (| + make_list [ + Constant.int 1 + ], + BinOp.mult (| + make_list [ + Constant.int 0 + ], + BinOp.sub (| + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_name (| globals, "self" |) + ], + make_dict [] + |), + Constant.int 1 + |) + |) + |); M.call (| + M.get_field (| M.get_name (| globals, "self" |), "deg" |), + make_list [], + make_dict [] + |) ] + |) in + let _ := M.assign_local (| + "q_0" , + M.call (| + M.get_name (| globals, "pow" |), + make_list [ + M.get_subscript (| + M.get_name (| globals, "x2" |), + M.get_name (| globals, "d2" |) + |); + UnOp.sub (| Constant.int 1 |); + M.get_name (| globals, "p" |) + ], + make_dict [] + |) + |) in + let _ := + M.for_ (| + M.get_name (| globals, "i" |), + M.call (| + M.get_name (| globals, "range" |), + make_list [ + M.get_name (| globals, "d2" |) + ], + make_dict [] + |), + ltac:(M.monadic ( + let _ := M.assign (| + M.get_subscript (| + M.get_name (| globals, "x1" |), + BinOp.sub (| + BinOp.add (| + M.get_name (| globals, "i" |), + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_name (| globals, "x1" |) + ], + make_dict [] + |) + |), + M.get_name (| globals, "d2" |) + |) + |), + BinOp.mod_ (| + BinOp.sub (| + M.get_subscript (| + M.get_name (| globals, "x1" |), + BinOp.sub (| + BinOp.add (| + M.get_name (| globals, "i" |), + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_name (| globals, "x1" |) + ], + make_dict [] + |) + |), + M.get_name (| globals, "d2" |) + |) + |), + BinOp.mult (| + M.get_name (| globals, "q_0" |), + M.get_subscript (| + M.get_name (| globals, "x2" |), + M.get_name (| globals, "i" |) + |) + |) + |), + M.get_name (| globals, "p" |) + |) + |) in + let _ := M.assign (| + M.get_subscript (| + M.get_name (| globals, "f1" |), + BinOp.sub (| + BinOp.add (| + M.get_name (| globals, "i" |), + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_name (| globals, "x1" |) + ], + make_dict [] + |) + |), + M.get_name (| globals, "d2" |) + |) + |), + BinOp.mod_ (| + BinOp.sub (| + M.get_subscript (| + M.get_name (| globals, "f1" |), + BinOp.sub (| + BinOp.add (| + M.get_name (| globals, "i" |), + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_name (| globals, "x1" |) + ], + make_dict [] + |) + |), + M.get_name (| globals, "d2" |) + |) + |), + BinOp.mult (| + M.get_name (| globals, "q_0" |), + M.get_subscript (| + M.get_name (| globals, "f2" |), + M.get_name (| globals, "i" |) + |) + |) + |), + M.get_name (| globals, "p" |) + |) + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := + M.for_ (| + M.get_name (| globals, "i" |), + M.call (| + M.get_name (| globals, "range" |), + make_list [ + BinOp.sub (| + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_field (| M.get_name (| globals, "self" |), "MODULUS" |) + ], + make_dict [] + |), + Constant.int 1 + |); + UnOp.sub (| Constant.int 1 |); + UnOp.sub (| Constant.int 1 |) + ], + make_dict [] + |), + ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + Compare.not_eq (| + M.get_subscript (| + M.get_name (| globals, "x1" |), + M.get_name (| globals, "i" |) + |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "d1" , + M.get_name (| globals, "i" |) + |) in + let _ := M.break (| |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := + M.while (| + Constant.bool true, + ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, "d1" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "ans" , + M.get_name (| globals, "f1" |) + |) in + let _ := M.assign_local (| + "q" , + M.call (| + M.get_name (| globals, "pow" |), + make_list [ + M.get_subscript (| + M.get_name (| globals, "x1" |), + Constant.int 0 + |); + UnOp.sub (| Constant.int 1 |); + M.get_field (| M.get_name (| globals, "self" |), "PRIME" |) + ], + make_dict [] + |) + |) in + let _ := + M.for_ (| + M.get_name (| globals, "i" |), + M.call (| + M.get_name (| globals, "range" |), + make_list [ + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_name (| globals, "ans" |) + ], + make_dict [] + |) + ], + make_dict [] + |), + ltac:(M.monadic ( + let _ := M.assign_op (| + BinOp.mult, + M.get_subscript (| + M.get_name (| globals, "ans" |), + M.get_name (| globals, "i" |) + |), + M.get_name (| globals, "q" |) + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := M.break (| |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, "d2" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "ans" , + M.get_name (| globals, "f2" |) + |) in + let _ := M.assign_local (| + "q" , + M.call (| + M.get_name (| globals, "pow" |), + make_list [ + M.get_subscript (| + M.get_name (| globals, "x2" |), + Constant.int 0 + |); + UnOp.sub (| Constant.int 1 |); + M.get_field (| M.get_name (| globals, "self" |), "PRIME" |) + ], + make_dict [] + |) + |) in + let _ := + M.for_ (| + M.get_name (| globals, "i" |), + M.call (| + M.get_name (| globals, "range" |), + make_list [ + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_name (| globals, "ans" |) + ], + make_dict [] + |) + ], + make_dict [] + |), + ltac:(M.monadic ( + let _ := M.assign_op_local (| + BinOp.mult, + "ans", + M.get_name (| globals, "q" |) + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := M.break (| |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + Compare.lt (| + M.get_name (| globals, "d1" |), + M.get_name (| globals, "d2" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "q" , + BinOp.mult (| + M.get_subscript (| + M.get_name (| globals, "x2" |), + M.get_name (| globals, "d2" |) + |), + M.call (| + M.get_name (| globals, "pow" |), + make_list [ + M.get_subscript (| + M.get_name (| globals, "x1" |), + M.get_name (| globals, "d1" |) + |); + UnOp.sub (| Constant.int 1 |); + M.get_field (| M.get_name (| globals, "self" |), "PRIME" |) + ], + make_dict [] + |) + |) + |) in + let _ := + M.for_ (| + M.get_name (| globals, "i" |), + M.call (| + M.get_name (| globals, "range" |), + make_list [ + BinOp.sub (| + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_field (| M.get_name (| globals, "self" |), "MODULUS" |) + ], + make_dict [] + |), + BinOp.sub (| + M.get_name (| globals, "d2" |), + M.get_name (| globals, "d1" |) + |) + |) + ], + make_dict [] + |), + ltac:(M.monadic ( + let _ := M.assign (| + M.get_subscript (| + M.get_name (| globals, "x2" |), + BinOp.add (| + M.get_name (| globals, "i" |), + BinOp.sub (| + M.get_name (| globals, "d2" |), + M.get_name (| globals, "d1" |) + |) + |) + |), + BinOp.mod_ (| + BinOp.sub (| + M.get_subscript (| + M.get_name (| globals, "x2" |), + BinOp.add (| + M.get_name (| globals, "i" |), + BinOp.sub (| + M.get_name (| globals, "d2" |), + M.get_name (| globals, "d1" |) + |) + |) + |), + BinOp.mult (| + M.get_name (| globals, "q" |), + M.get_subscript (| + M.get_name (| globals, "x1" |), + M.get_name (| globals, "i" |) + |) + |) + |), + M.get_name (| globals, "p" |) + |) + |) in + let _ := M.assign (| + M.get_subscript (| + M.get_name (| globals, "f2" |), + BinOp.add (| + M.get_name (| globals, "i" |), + BinOp.sub (| + M.get_name (| globals, "d2" |), + M.get_name (| globals, "d1" |) + |) + |) + |), + BinOp.mod_ (| + BinOp.sub (| + M.get_subscript (| + M.get_name (| globals, "f2" |), + BinOp.add (| + M.get_name (| globals, "i" |), + BinOp.sub (| + M.get_name (| globals, "d2" |), + M.get_name (| globals, "d1" |) + |) + |) + |), + BinOp.mult (| + M.get_name (| globals, "q" |), + M.get_subscript (| + M.get_name (| globals, "f1" |), + M.get_name (| globals, "i" |) + |) + |) + |), + M.get_name (| globals, "p" |) + |) + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := + M.while (| + Compare.eq (| + M.get_subscript (| + M.get_name (| globals, "x2" |), + M.get_name (| globals, "d2" |) + |), + Constant.int 0 + |), + ltac:(M.monadic ( + let _ := M.assign_op_local (| + BinOp.sub, + "d2", + Constant.int 1 + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "q" , + BinOp.mult (| + M.get_subscript (| + M.get_name (| globals, "x1" |), + M.get_name (| globals, "d1" |) + |), + M.call (| + M.get_name (| globals, "pow" |), + make_list [ + M.get_subscript (| + M.get_name (| globals, "x2" |), + M.get_name (| globals, "d2" |) + |); + UnOp.sub (| Constant.int 1 |); + M.get_field (| M.get_name (| globals, "self" |), "PRIME" |) + ], + make_dict [] + |) + |) + |) in + let _ := + M.for_ (| + M.get_name (| globals, "i" |), + M.call (| + M.get_name (| globals, "range" |), + make_list [ + BinOp.sub (| + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_field (| M.get_name (| globals, "self" |), "MODULUS" |) + ], + make_dict [] + |), + BinOp.sub (| + M.get_name (| globals, "d1" |), + M.get_name (| globals, "d2" |) + |) + |) + ], + make_dict [] + |), + ltac:(M.monadic ( + let _ := M.assign (| + M.get_subscript (| + M.get_name (| globals, "x1" |), + BinOp.add (| + M.get_name (| globals, "i" |), + BinOp.sub (| + M.get_name (| globals, "d1" |), + M.get_name (| globals, "d2" |) + |) + |) + |), + BinOp.mod_ (| + BinOp.sub (| + M.get_subscript (| + M.get_name (| globals, "x1" |), + BinOp.add (| + M.get_name (| globals, "i" |), + BinOp.sub (| + M.get_name (| globals, "d1" |), + M.get_name (| globals, "d2" |) + |) + |) + |), + BinOp.mult (| + M.get_name (| globals, "q" |), + M.get_subscript (| + M.get_name (| globals, "x2" |), + M.get_name (| globals, "i" |) + |) + |) + |), + M.get_name (| globals, "p" |) + |) + |) in + let _ := M.assign (| + M.get_subscript (| + M.get_name (| globals, "f1" |), + BinOp.add (| + M.get_name (| globals, "i" |), + BinOp.sub (| + M.get_name (| globals, "d1" |), + M.get_name (| globals, "d2" |) + |) + |) + |), + BinOp.mod_ (| + BinOp.sub (| + M.get_subscript (| + M.get_name (| globals, "f1" |), + BinOp.add (| + M.get_name (| globals, "i" |), + BinOp.sub (| + M.get_name (| globals, "d1" |), + M.get_name (| globals, "d2" |) + |) + |) + |), + BinOp.mult (| + M.get_name (| globals, "q" |), + M.get_subscript (| + M.get_name (| globals, "f2" |), + M.get_name (| globals, "i" |) + |) + |) + |), + M.get_name (| globals, "p" |) + |) + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := + M.while (| + Compare.eq (| + M.get_subscript (| + M.get_name (| globals, "x1" |), + M.get_name (| globals, "d1" |) + |), + Constant.int 0 + |), + ltac:(M.monadic ( + let _ := M.assign_op_local (| + BinOp.sub, + "d1", + Constant.int 1 + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := M.return_ (| + M.call (| + M.get_field (| M.get_name (| globals, "self" |), "__new__" |), + make_list [ + M.call (| + M.get_name (| globals, "type" |), + make_list [ + M.get_name (| globals, "self" |) + ], + make_dict [] + |); + M.get_name (| globals, "ans" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)) + ); + ( + "__pow__", + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "self"; "exponent" ] |) in + let _ := M.assign_local (| + "degree" , + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_field (| M.get_name (| globals, "self" |), "MODULUS" |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.lt (| + M.get_name (| globals, "exponent" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "self" , + M.call (| + M.get_field (| M.get_name (| globals, "self" |), "multiplicative_inverse" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "exponent" , + UnOp.sub (| M.get_name (| globals, "exponent" |) |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "res" , + M.call (| + M.get_field (| M.get_name (| globals, "self" |), "__new__" |), + make_list [ + M.call (| + M.get_name (| globals, "type" |), + make_list [ + M.get_name (| globals, "self" |) + ], + make_dict [] + |); + BinOp.add (| + make_list [ + Constant.int 1 + ], + BinOp.mult (| + make_list [ + Constant.int 0 + ], + BinOp.sub (| + M.get_name (| globals, "degree" |), + Constant.int 1 + |) + |) + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "s" , + M.get_name (| globals, "self" |) + |) in + let _ := + M.while (| + Compare.not_eq (| + M.get_name (| globals, "exponent" |), + Constant.int 0 + |), + ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + BinOp.mod_ (| + M.get_name (| globals, "exponent" |), + Constant.int 2 + |), + Constant.int 1 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_op_local (| + BinOp.mult, + "res", + M.get_name (| globals, "s" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_op_local (| + BinOp.mult, + "s", + M.get_name (| globals, "s" |) + |) in + let _ := M.assign_op_local (| + BinOp.floor_div, + "exponent", + Constant.int 2 + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := M.return_ (| + M.get_name (| globals, "res" |) + |) in + M.pure Constant.None_)) + ); + ( + "__ipow__", + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "self"; "right" ] |) in + let _ := M.return_ (| + M.call (| + M.get_field (| M.get_name (| globals, "self" |), "__pow__" |), + make_list [ + M.get_name (| globals, "right" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)) + ); + ( + "frobenius", + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "self" ] |) in + let _ := Constant.str " + Returns `self ** p`. This function is known as the Frobenius + endomorphism and has many special mathematical properties. In + particular it is extremely cheap to compute compared to other + exponentiations. + " in + let _ := M.assign_local (| + "ans" , + M.call (| + M.get_field (| M.get_name (| globals, "self" |), "from_int" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + |) in +(* At stmt: unsupported node type: AnnAssign *) + let _ := + M.for_ (| + make_tuple [ M.get_name (| globals, "i" |); M.get_name (| globals, "a" |) ], + M.call (| + M.get_name (| globals, "enumerate" |), + make_list [ + M.get_name (| globals, "self" |) + ], + make_dict [] + |), + ltac:(M.monadic ( + let _ := M.assign_op_local (| + BinOp.add, + "ans", + M.call (| + M.get_field (| M.call (| + M.get_name (| globals, "cast" |), + make_list [ + M.get_name (| globals, "U" |); + M.get_subscript (| + M.get_field (| M.get_name (| globals, "self" |), "FROBENIUS_COEFFICIENTS" |), + M.get_name (| globals, "i" |) + |) + ], + make_dict [] + |), "scalar_mul" |), + make_list [ + M.get_name (| globals, "a" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := M.return_ (| + M.get_name (| globals, "ans" |) + |) in + M.pure Constant.None_)) + ) + ]. diff --git a/CoqOfPython/ethereum/crypto/hash.v b/CoqOfPython/ethereum/crypto/hash.v new file mode 100644 index 0000000..ffb11bc --- /dev/null +++ b/CoqOfPython/ethereum/crypto/hash.v @@ -0,0 +1,126 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.crypto.hash". + +Definition expr_1 : Value.t := + Constant.str " +Cryptographic Hash Functions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Cryptographic hashing functions. +". + +Axiom Crypto_Hash_imports_keccak : + IsImported globals "Crypto.Hash" "keccak". + +Axiom ethereum_base_types_imports_Bytes : + IsImported globals "ethereum.base_types" "Bytes". +Axiom ethereum_base_types_imports_Bytes32 : + IsImported globals "ethereum.base_types" "Bytes32". +Axiom ethereum_base_types_imports_Bytes64 : + IsImported globals "ethereum.base_types" "Bytes64". + +Definition Hash32 : Value.t := M.run ltac:(M.monadic ( + M.get_name (| globals, "Bytes32" |) +)). + +Definition Hash64 : Value.t := M.run ltac:(M.monadic ( + M.get_name (| globals, "Bytes64" |) +)). + +Definition keccak256 : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "buffer" ] |) in + let _ := Constant.str " + Computes the keccak256 hash of the input `buffer`. + + Parameters + ---------- + buffer : + Input for the hashing function. + + Returns + ------- + hash : `ethereum.base_types.Hash32` + Output of the hash function. + " in + let _ := M.assign_local (| + "k" , + M.call (| + M.get_field (| M.get_name (| globals, "keccak" |), "new" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, "Hash32" |), + make_list [ + M.call (| + M.get_field (| M.call (| + M.get_field (| M.get_name (| globals, "k" |), "update" |), + make_list [ + M.get_name (| globals, "buffer" |) + ], + make_dict [] + |), "digest" |), + make_list [], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Definition keccak512 : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "buffer" ] |) in + let _ := Constant.str " + Computes the keccak512 hash of the input `buffer`. + + Parameters + ---------- + buffer : + Input for the hashing function. + + Returns + ------- + hash : `ethereum.base_types.Hash32` + Output of the hash function. + " in + let _ := M.assign_local (| + "k" , + M.call (| + M.get_field (| M.get_name (| globals, "keccak" |), "new" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, "Hash64" |), + make_list [ + M.call (| + M.get_field (| M.call (| + M.get_field (| M.get_name (| globals, "k" |), "update" |), + make_list [ + M.get_name (| globals, "buffer" |) + ], + make_dict [] + |), "digest" |), + make_list [], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). diff --git a/CoqOfPython/ethereum/dao_fork/__init__.v b/CoqOfPython/ethereum/dao_fork/__init__.v new file mode 100644 index 0000000..12b0f7a --- /dev/null +++ b/CoqOfPython/ethereum/dao_fork/__init__.v @@ -0,0 +1,23 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.dao_fork.__init__". + +Definition expr_1 : Value.t := + Constant.str " +The DAO Fork is a response to a smart contract exploit known as the 2016 DAO +Attack where a vulnerable contract was drained of its ether. This fork recovers +the stolen funds into a new contract. +". + +Axiom ethereum_fork_criteria_imports_ByBlockNumber : + IsImported globals "ethereum.fork_criteria" "ByBlockNumber". + +Definition FORK_CRITERIA : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "ByBlockNumber" |), + make_list [ + Constant.int 1920000 + ], + make_dict [] + |) +)). diff --git a/CoqOfPython/ethereum/dao_fork/blocks.v b/CoqOfPython/ethereum/dao_fork/blocks.v new file mode 100644 index 0000000..0707efe --- /dev/null +++ b/CoqOfPython/ethereum/dao_fork/blocks.v @@ -0,0 +1,87 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.dao_fork.blocks". + +Definition expr_1 : Value.t := + Constant.str " +A `Block` is a single link in the chain that is Ethereum. Each `Block` contains +a `Header` and zero or more transactions. Each `Header` contains associated +metadata like the block number, parent block hash, and how much gas was +consumed by its transactions. + +Together, these blocks form a cryptographically secure journal recording the +history of all state transitions that have happened since the genesis of the +chain. +". + +Axiom dataclasses_imports_dataclass : + IsImported globals "dataclasses" "dataclass". + +Axiom typing_imports_Tuple : + IsImported globals "typing" "Tuple". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_Bytes : + IsImported globals "ethereum.base_types" "Bytes". +Axiom ethereum_base_types_imports_Bytes8 : + IsImported globals "ethereum.base_types" "Bytes8". +Axiom ethereum_base_types_imports_Bytes32 : + IsImported globals "ethereum.base_types" "Bytes32". +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". +Axiom ethereum_base_types_imports_slotted_freezable : + IsImported globals "ethereum.base_types" "slotted_freezable". + +Axiom ethereum_crypto_hash_imports_Hash32 : + IsImported globals "ethereum.crypto.hash" "Hash32". + +Axiom ethereum_dao_fork_fork_types_imports_Address : + IsImported globals "ethereum.dao_fork.fork_types" "Address". +Axiom ethereum_dao_fork_fork_types_imports_Bloom : + IsImported globals "ethereum.dao_fork.fork_types" "Bloom". +Axiom ethereum_dao_fork_fork_types_imports_Root : + IsImported globals "ethereum.dao_fork.fork_types" "Root". + +Axiom ethereum_dao_fork_transactions_imports_Transaction : + IsImported globals "ethereum.dao_fork.transactions" "Transaction". + +Definition Header : Value.t := + builtins.make_klass + [] + [ + + ] + [ + + ]. + +Definition Block : Value.t := + builtins.make_klass + [] + [ + + ] + [ + + ]. + +Definition Log : Value.t := + builtins.make_klass + [] + [ + + ] + [ + + ]. + +Definition Receipt : Value.t := + builtins.make_klass + [] + [ + + ] + [ + + ]. diff --git a/CoqOfPython/ethereum/dao_fork/bloom.v b/CoqOfPython/ethereum/dao_fork/bloom.v new file mode 100644 index 0000000..4b83130 --- /dev/null +++ b/CoqOfPython/ethereum/dao_fork/bloom.v @@ -0,0 +1,207 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.dao_fork.bloom". + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Logs Bloom +^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +This modules defines functions for calculating bloom filters of logs. For the +general theory of bloom filters see e.g. `Wikipedia +`_. Bloom filters are used to allow +for efficient searching of logs by address and/or topic, by rapidly +eliminating blocks and receipts from their search. +". + +Axiom typing_imports_Tuple : + IsImported globals "typing" "Tuple". + +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". + +Axiom ethereum_crypto_hash_imports_keccak256 : + IsImported globals "ethereum.crypto.hash" "keccak256". + +Axiom ethereum_dao_fork_blocks_imports_Log : + IsImported globals "ethereum.dao_fork.blocks" "Log". + +Axiom ethereum_dao_fork_fork_types_imports_Bloom : + IsImported globals "ethereum.dao_fork.fork_types" "Bloom". + +Definition add_to_bloom : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "bloom"; "bloom_entry" ] |) in + let _ := Constant.str " + Add a bloom entry to the bloom filter (`bloom`). + + The number of hash functions used is 3. They are calculated by taking the + least significant 11 bits from the first 3 16-bit words of the + `keccak_256()` hash of `bloom_entry`. + + Parameters + ---------- + bloom : + The bloom filter. + bloom_entry : + An entry which is to be added to bloom filter. + " in + let _ := M.assign_local (| + "hash" , + M.call (| + M.get_name (| globals, "keccak256" |), + make_list [ + M.get_name (| globals, "bloom_entry" |) + ], + make_dict [] + |) + |) in + let _ := + M.for_ (| + M.get_name (| globals, "idx" |), + make_tuple [ Constant.int 0; Constant.int 2; Constant.int 4 ], + ltac:(M.monadic ( + let _ := M.assign_local (| + "bit_to_set" , + BinOp.bit_and (| + M.call (| + M.get_field (| M.get_name (| globals, "Uint" |), "from_be_bytes" |), + make_list [ + M.slice (| + M.get_name (| globals, "hash" |), + M.get_name (| globals, "idx" |), + BinOp.add (| + M.get_name (| globals, "idx" |), + Constant.int 2 + |), + Constant.None_ + |) + ], + make_dict [] + |), + Constant.int 2047 + |) + |) in + let _ := M.assign_local (| + "bit_index" , + BinOp.sub (| + Constant.int 2047, + M.get_name (| globals, "bit_to_set" |) + |) + |) in + let _ := M.assign_local (| + "byte_index" , + BinOp.floor_div (| + M.get_name (| globals, "bit_index" |), + Constant.int 8 + |) + |) in + let _ := M.assign_local (| + "bit_value" , + BinOp.l_shift (| + Constant.int 1, + BinOp.sub (| + Constant.int 7, + BinOp.mod_ (| + M.get_name (| globals, "bit_index" |), + Constant.int 8 + |) + |) + |) + |) in + let _ := M.assign (| + M.get_subscript (| + M.get_name (| globals, "bloom" |), + M.get_name (| globals, "byte_index" |) + |), + BinOp.bit_or (| + M.get_subscript (| + M.get_name (| globals, "bloom" |), + M.get_name (| globals, "byte_index" |) + |), + M.get_name (| globals, "bit_value" |) + |) + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + M.pure Constant.None_)). + +Definition logs_bloom : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "logs" ] |) in + let _ := Constant.str " + Obtain the logs bloom from a list of log entries. + + The address and each topic of a log are added to the bloom filter. + + Parameters + ---------- + logs : + List of logs for which the logs bloom is to be obtained. + + Returns + ------- + logs_bloom : `Bloom` + The logs bloom obtained which is 256 bytes with some bits set as per + the caller address and the log topics. + " in +(* At stmt: unsupported node type: AnnAssign *) + let _ := + M.for_ (| + M.get_name (| globals, "log" |), + M.get_name (| globals, "logs" |), + ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, "add_to_bloom" |), + make_list [ + M.get_name (| globals, "bloom" |); + M.get_field (| M.get_name (| globals, "log" |), "address" |) + ], + make_dict [] + |) in + let _ := + M.for_ (| + M.get_name (| globals, "topic" |), + M.get_field (| M.get_name (| globals, "log" |), "topics" |), + ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, "add_to_bloom" |), + make_list [ + M.get_name (| globals, "bloom" |); + M.get_name (| globals, "topic" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, "Bloom" |), + make_list [ + M.get_name (| globals, "bloom" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). diff --git a/CoqOfPython/ethereum/dao_fork/dao.v b/CoqOfPython/ethereum/dao_fork/dao.v new file mode 100644 index 0000000..160f310 --- /dev/null +++ b/CoqOfPython/ethereum/dao_fork/dao.v @@ -0,0 +1,90 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.dao_fork.dao". + +Definition expr_1 : Value.t := + Constant.str " +Dao Fork +^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +The Dao Fork was an irregular state change that moved all Ether from a large +collection of accounts (The Dao and all its children) to a recovery contract. + +The recovery contract was previously created using normal contract deployment. +". + +Axiom ethereum_dao_fork_state_imports_State : + IsImported globals "ethereum.dao_fork.state" "State". +Axiom ethereum_dao_fork_state_imports_get_account : + IsImported globals "ethereum.dao_fork.state" "get_account". +Axiom ethereum_dao_fork_state_imports_move_ether : + IsImported globals "ethereum.dao_fork.state" "move_ether". + +Axiom ethereum_dao_fork_utils_hexadecimal_imports_hex_to_address : + IsImported globals "ethereum.dao_fork.utils.hexadecimal" "hex_to_address". + +Definition DAO_ACCOUNTS : Value.t := M.run ltac:(M.monadic ( + Constant.str "(* At expr: unsupported node type: ListComp *)" +)). + +Definition DAO_RECOVERY : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "hex_to_address" |), + make_list [ + Constant.str "0xbf4ed7b27f1d666546e30d74d50d173d20bca754" + ], + make_dict [] + |) +)). + +Definition apply_dao : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "state" ] |) in + let _ := Constant.str " + Apply the dao fork to the state. + + Parameters + ---------- + state : + State before applying the DAO Fork. + " in + let _ := + M.for_ (| + M.get_name (| globals, "address" |), + M.get_name (| globals, "DAO_ACCOUNTS" |), + ltac:(M.monadic ( + let _ := M.assign_local (| + "balance" , + M.get_field (| M.call (| + M.get_name (| globals, "get_account" |), + make_list [ + M.get_name (| globals, "state" |); + M.get_name (| globals, "address" |) + ], + make_dict [] + |), "balance" |) + |) in + let _ := M.call (| + M.get_name (| globals, "move_ether" |), + make_list [ + M.get_name (| globals, "state" |); + M.get_name (| globals, "address" |); + M.get_name (| globals, "DAO_RECOVERY" |); + M.get_name (| globals, "balance" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + M.pure Constant.None_)). diff --git a/CoqOfPython/ethereum/dao_fork/fork.v b/CoqOfPython/ethereum/dao_fork/fork.v new file mode 100644 index 0000000..cd0c092 --- /dev/null +++ b/CoqOfPython/ethereum/dao_fork/fork.v @@ -0,0 +1,2484 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.dao_fork.fork". + +Definition expr_1 : Value.t := + Constant.str " +.. _dao-fork: + +Ethereum Specification +^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Entry point for the Ethereum specification. +". + +Axiom dataclasses_imports_dataclass : + IsImported globals "dataclasses" "dataclass". + +Axiom typing_imports_List : + IsImported globals "typing" "List". +Axiom typing_imports_Optional : + IsImported globals "typing" "Optional". +Axiom typing_imports_Set : + IsImported globals "typing" "Set". +Axiom typing_imports_Tuple : + IsImported globals "typing" "Tuple". + +Axiom ethereum_base_types_imports_Bytes0 : + IsImported globals "ethereum.base_types" "Bytes0". + +Axiom ethereum_crypto_elliptic_curve_imports_SECP256K1N : + IsImported globals "ethereum.crypto.elliptic_curve" "SECP256K1N". +Axiom ethereum_crypto_elliptic_curve_imports_secp256k1_recover : + IsImported globals "ethereum.crypto.elliptic_curve" "secp256k1_recover". + +Axiom ethereum_crypto_hash_imports_Hash32 : + IsImported globals "ethereum.crypto.hash" "Hash32". +Axiom ethereum_crypto_hash_imports_keccak256 : + IsImported globals "ethereum.crypto.hash" "keccak256". + +Axiom ethereum_ethash_imports_dataset_size : + IsImported globals "ethereum.ethash" "dataset_size". +Axiom ethereum_ethash_imports_generate_cache : + IsImported globals "ethereum.ethash" "generate_cache". +Axiom ethereum_ethash_imports_hashimoto_light : + IsImported globals "ethereum.ethash" "hashimoto_light". + +Axiom ethereum_exceptions_imports_InvalidBlock : + IsImported globals "ethereum.exceptions" "InvalidBlock". + +Axiom ethereum_utils_ensure_imports_ensure : + IsImported globals "ethereum.utils.ensure" "ensure". + +Axiom ethereum_imports_rlp : + IsImported globals "ethereum" "rlp". + +Axiom ethereum_base_types_imports_U64 : + IsImported globals "ethereum.base_types" "U64". +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_U256_CEIL_VALUE : + IsImported globals "ethereum.base_types" "U256_CEIL_VALUE". +Axiom ethereum_base_types_imports_Bytes : + IsImported globals "ethereum.base_types" "Bytes". +Axiom ethereum_base_types_imports_Bytes32 : + IsImported globals "ethereum.base_types" "Bytes32". +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". + +Axiom ethereum_dao_fork_imports_FORK_CRITERIA : + IsImported globals "ethereum.dao_fork" "FORK_CRITERIA". +Axiom ethereum_dao_fork_imports_vm : + IsImported globals "ethereum.dao_fork" "vm". + +Axiom ethereum_dao_fork_blocks_imports_Block : + IsImported globals "ethereum.dao_fork.blocks" "Block". +Axiom ethereum_dao_fork_blocks_imports_Header : + IsImported globals "ethereum.dao_fork.blocks" "Header". +Axiom ethereum_dao_fork_blocks_imports_Log : + IsImported globals "ethereum.dao_fork.blocks" "Log". +Axiom ethereum_dao_fork_blocks_imports_Receipt : + IsImported globals "ethereum.dao_fork.blocks" "Receipt". + +Axiom ethereum_dao_fork_bloom_imports_logs_bloom : + IsImported globals "ethereum.dao_fork.bloom" "logs_bloom". + +Axiom ethereum_dao_fork_dao_imports_apply_dao : + IsImported globals "ethereum.dao_fork.dao" "apply_dao". + +Axiom ethereum_dao_fork_fork_types_imports_Address : + IsImported globals "ethereum.dao_fork.fork_types" "Address". +Axiom ethereum_dao_fork_fork_types_imports_Bloom : + IsImported globals "ethereum.dao_fork.fork_types" "Bloom". +Axiom ethereum_dao_fork_fork_types_imports_Root : + IsImported globals "ethereum.dao_fork.fork_types" "Root". + +Axiom ethereum_dao_fork_state_imports_State : + IsImported globals "ethereum.dao_fork.state" "State". +Axiom ethereum_dao_fork_state_imports_create_ether : + IsImported globals "ethereum.dao_fork.state" "create_ether". +Axiom ethereum_dao_fork_state_imports_destroy_account : + IsImported globals "ethereum.dao_fork.state" "destroy_account". +Axiom ethereum_dao_fork_state_imports_get_account : + IsImported globals "ethereum.dao_fork.state" "get_account". +Axiom ethereum_dao_fork_state_imports_increment_nonce : + IsImported globals "ethereum.dao_fork.state" "increment_nonce". +Axiom ethereum_dao_fork_state_imports_set_account_balance : + IsImported globals "ethereum.dao_fork.state" "set_account_balance". +Axiom ethereum_dao_fork_state_imports_state_root : + IsImported globals "ethereum.dao_fork.state" "state_root". + +Axiom ethereum_dao_fork_transactions_imports_TX_BASE_COST : + IsImported globals "ethereum.dao_fork.transactions" "TX_BASE_COST". +Axiom ethereum_dao_fork_transactions_imports_TX_CREATE_COST : + IsImported globals "ethereum.dao_fork.transactions" "TX_CREATE_COST". +Axiom ethereum_dao_fork_transactions_imports_TX_DATA_COST_PER_NON_ZERO : + IsImported globals "ethereum.dao_fork.transactions" "TX_DATA_COST_PER_NON_ZERO". +Axiom ethereum_dao_fork_transactions_imports_TX_DATA_COST_PER_ZERO : + IsImported globals "ethereum.dao_fork.transactions" "TX_DATA_COST_PER_ZERO". +Axiom ethereum_dao_fork_transactions_imports_Transaction : + IsImported globals "ethereum.dao_fork.transactions" "Transaction". + +Axiom ethereum_dao_fork_trie_imports_Trie : + IsImported globals "ethereum.dao_fork.trie" "Trie". +Axiom ethereum_dao_fork_trie_imports_root : + IsImported globals "ethereum.dao_fork.trie" "root". +Axiom ethereum_dao_fork_trie_imports_trie_set : + IsImported globals "ethereum.dao_fork.trie" "trie_set". + +Axiom ethereum_dao_fork_utils_message_imports_prepare_message : + IsImported globals "ethereum.dao_fork.utils.message" "prepare_message". + +Axiom ethereum_dao_fork_vm_interpreter_imports_process_message_call : + IsImported globals "ethereum.dao_fork.vm.interpreter" "process_message_call". + +Definition BLOCK_REWARD : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + BinOp.mult (| + Constant.int 5, + BinOp.pow (| + Constant.int 10, + Constant.int 18 + |) + |) + ], + make_dict [] + |) +)). + +Definition GAS_LIMIT_ADJUSTMENT_FACTOR : Value.t := M.run ltac:(M.monadic ( + Constant.int 1024 +)). + +Definition GAS_LIMIT_MINIMUM : Value.t := M.run ltac:(M.monadic ( + Constant.int 5000 +)). + +Definition MINIMUM_DIFFICULTY : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 131072 + ], + make_dict [] + |) +)). + +Definition MAX_OMMER_DEPTH : Value.t := M.run ltac:(M.monadic ( + Constant.int 6 +)). + +Definition BlockChain : Value.t := + builtins.make_klass + [] + [ + + ] + [ + + ]. + +Definition apply_fork : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "old" ] |) in + let _ := Constant.str " + Transforms the state from the previous hard fork (`old`) into the block + chain object for this hard fork and returns it. + + When forks need to implement an irregular state transition, this function + is used to handle the irregularity. + + The DAO-Fork occurred as a result of the `2016 DAO Hacks + `_ in which an + unknown entity managed to drain more than 3.6 million ether causing the + price of ether to drop by nearly 35%. This fork was the solution to the + hacks and manually reset the affected parties' accounts to their state + prior to the attack. This fork essentially rewrote the history of the + Ethereum network. + + Parameters + ---------- + old : + Previous block chain object. + + Returns + ------- + new : `BlockChain` + Upgraded block chain object for this hard fork. + " in + let _ := M.call (| + M.get_name (| globals, "apply_dao" |), + make_list [ + M.get_field (| M.get_name (| globals, "old" |), "state" |) + ], + make_dict [] + |) in + let _ := M.return_ (| + M.get_name (| globals, "old" |) + |) in + M.pure Constant.None_)). + +Definition get_last_256_block_hashes : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "chain" ] |) in + let _ := Constant.str " + Obtain the list of hashes of the previous 256 blocks in order of + increasing block number. + + This function will return less hashes for the first 256 blocks. + + The ``BLOCKHASH`` opcode needs to access the latest hashes on the chain, + therefore this function retrieves them. + + Parameters + ---------- + chain : + History and current state. + + Returns + ------- + recent_block_hashes : `List[Hash32]` + Hashes of the recent 256 blocks in order of increasing block number. + " in + let _ := M.assign_local (| + "recent_blocks" , + M.slice (| + M.get_field (| M.get_name (| globals, "chain" |), "blocks" |), + UnOp.sub (| Constant.int 255 |), + Constant.None_, + Constant.None_ + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_name (| globals, "recent_blocks" |) + ], + make_dict [] + |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + make_list [] + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "recent_block_hashes" , + make_list [] + |) in + let _ := + M.for_ (| + M.get_name (| globals, "block" |), + M.get_name (| globals, "recent_blocks" |), + ltac:(M.monadic ( + let _ := M.assign_local (| + "prev_block_hash" , + M.get_field (| M.get_field (| M.get_name (| globals, "block" |), "header" |), "parent_hash" |) + |) in + let _ := M.call (| + M.get_field (| M.get_name (| globals, "recent_block_hashes" |), "append" |), + make_list [ + M.get_name (| globals, "prev_block_hash" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := M.assign_local (| + "most_recent_block_hash" , + M.call (| + M.get_name (| globals, "keccak256" |), + make_list [ + M.call (| + M.get_field (| M.get_name (| globals, "rlp" |), "encode" |), + make_list [ + M.get_field (| M.get_subscript (| + M.get_name (| globals, "recent_blocks" |), + UnOp.sub (| Constant.int 1 |) + |), "header" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_field (| M.get_name (| globals, "recent_block_hashes" |), "append" |), + make_list [ + M.get_name (| globals, "most_recent_block_hash" |) + ], + make_dict [] + |) in + let _ := M.return_ (| + M.get_name (| globals, "recent_block_hashes" |) + |) in + M.pure Constant.None_)). + +Definition state_transition : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "chain"; "block" ] |) in + let _ := Constant.str " + Attempts to apply a block to an existing block chain. + + All parts of the block's contents need to be verified before being added + to the chain. Blocks are verified by ensuring that the contents of the + block make logical sense with the contents of the parent block. The + information in the block's header must also match the corresponding + information in the block. + + To implement Ethereum, in theory clients are only required to store the + most recent 255 blocks of the chain since as far as execution is + concerned, only those blocks are accessed. Practically, however, clients + should store more blocks to handle reorgs. + + Parameters + ---------- + chain : + History and current state. + block : + Block to apply to `chain`. + " in + let _ := M.assign_local (| + "parent_header" , + M.get_field (| M.get_subscript (| + M.get_field (| M.get_name (| globals, "chain" |), "blocks" |), + UnOp.sub (| Constant.int 1 |) + |), "header" |) + |) in + let _ := M.call (| + M.get_name (| globals, "validate_header" |), + make_list [ + M.get_field (| M.get_name (| globals, "block" |), "header" |); + M.get_name (| globals, "parent_header" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "validate_ommers" |), + make_list [ + M.get_field (| M.get_name (| globals, "block" |), "ommers" |); + M.get_field (| M.get_name (| globals, "block" |), "header" |); + M.get_name (| globals, "chain" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "apply_body_output" , + M.call (| + M.get_name (| globals, "apply_body" |), + make_list [ + M.get_field (| M.get_name (| globals, "chain" |), "state" |); + M.call (| + M.get_name (| globals, "get_last_256_block_hashes" |), + make_list [ + M.get_name (| globals, "chain" |) + ], + make_dict [] + |); + M.get_field (| M.get_field (| M.get_name (| globals, "block" |), "header" |), "coinbase" |); + M.get_field (| M.get_field (| M.get_name (| globals, "block" |), "header" |), "number" |); + M.get_field (| M.get_field (| M.get_name (| globals, "block" |), "header" |), "gas_limit" |); + M.get_field (| M.get_field (| M.get_name (| globals, "block" |), "header" |), "timestamp" |); + M.get_field (| M.get_field (| M.get_name (| globals, "block" |), "header" |), "difficulty" |); + M.get_field (| M.get_name (| globals, "block" |), "transactions" |); + M.get_field (| M.get_name (| globals, "block" |), "ommers" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + Compare.eq (| + M.get_field (| M.get_name (| globals, "apply_body_output" |), "block_gas_used" |), + M.get_field (| M.get_field (| M.get_name (| globals, "block" |), "header" |), "gas_used" |) + |); + M.get_name (| globals, "InvalidBlock" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + Compare.eq (| + M.get_field (| M.get_name (| globals, "apply_body_output" |), "transactions_root" |), + M.get_field (| M.get_field (| M.get_name (| globals, "block" |), "header" |), "transactions_root" |) + |); + M.get_name (| globals, "InvalidBlock" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + Compare.eq (| + M.get_field (| M.get_name (| globals, "apply_body_output" |), "state_root" |), + M.get_field (| M.get_field (| M.get_name (| globals, "block" |), "header" |), "state_root" |) + |); + M.get_name (| globals, "InvalidBlock" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + Compare.eq (| + M.get_field (| M.get_name (| globals, "apply_body_output" |), "receipt_root" |), + M.get_field (| M.get_field (| M.get_name (| globals, "block" |), "header" |), "receipt_root" |) + |); + M.get_name (| globals, "InvalidBlock" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + Compare.eq (| + M.get_field (| M.get_name (| globals, "apply_body_output" |), "block_logs_bloom" |), + M.get_field (| M.get_field (| M.get_name (| globals, "block" |), "header" |), "bloom" |) + |); + M.get_name (| globals, "InvalidBlock" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, "chain" |), "blocks" |), "append" |), + make_list [ + M.get_name (| globals, "block" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.gt (| + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_field (| M.get_name (| globals, "chain" |), "blocks" |) + ], + make_dict [] + |), + Constant.int 255 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign (| + M.get_field (| M.get_name (| globals, "chain" |), "blocks" |), + M.slice (| + M.get_field (| M.get_name (| globals, "chain" |), "blocks" |), + UnOp.sub (| Constant.int 255 |), + Constant.None_, + Constant.None_ + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + M.pure Constant.None_)). + +Definition validate_header : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "header"; "parent_header" ] |) in + let _ := Constant.str " + Verifies a block header. + + In order to consider a block's header valid, the logic for the + quantities in the header should match the logic for the block itself. + For example the header timestamp should be greater than the block's parent + timestamp because the block was created *after* the parent block. + Additionally, the block's number should be directly following the parent + block's number since it is the next block in the sequence. + + Parameters + ---------- + header : + Header to check for correctness. + parent_header : + Parent Header of the header to check for correctness + " in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + Compare.gt (| + M.get_field (| M.get_name (| globals, "header" |), "timestamp" |), + M.get_field (| M.get_name (| globals, "parent_header" |), "timestamp" |) + |); + M.get_name (| globals, "InvalidBlock" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + Compare.eq (| + M.get_field (| M.get_name (| globals, "header" |), "number" |), + BinOp.add (| + M.get_field (| M.get_name (| globals, "parent_header" |), "number" |), + Constant.int 1 + |) + |); + M.get_name (| globals, "InvalidBlock" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + M.call (| + M.get_name (| globals, "check_gas_limit" |), + make_list [ + M.get_field (| M.get_name (| globals, "header" |), "gas_limit" |); + M.get_field (| M.get_name (| globals, "parent_header" |), "gas_limit" |) + ], + make_dict [] + |); + M.get_name (| globals, "InvalidBlock" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + Compare.lt_e (| + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_field (| M.get_name (| globals, "header" |), "extra_data" |) + ], + make_dict [] + |), + Constant.int 32 + |); + M.get_name (| globals, "InvalidBlock" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "block_difficulty" , + M.call (| + M.get_name (| globals, "calculate_block_difficulty" |), + make_list [ + M.get_field (| M.get_name (| globals, "header" |), "number" |); + M.get_field (| M.get_name (| globals, "header" |), "timestamp" |); + M.get_field (| M.get_name (| globals, "parent_header" |), "timestamp" |); + M.get_field (| M.get_name (| globals, "parent_header" |), "difficulty" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + Compare.eq (| + M.get_field (| M.get_name (| globals, "header" |), "difficulty" |), + M.get_name (| globals, "block_difficulty" |) + |); + M.get_name (| globals, "InvalidBlock" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "block_parent_hash" , + M.call (| + M.get_name (| globals, "keccak256" |), + make_list [ + M.call (| + M.get_field (| M.get_name (| globals, "rlp" |), "encode" |), + make_list [ + M.get_name (| globals, "parent_header" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + Compare.eq (| + M.get_field (| M.get_name (| globals, "header" |), "parent_hash" |), + M.get_name (| globals, "block_parent_hash" |) + |); + M.get_name (| globals, "InvalidBlock" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + BoolOp.and (| + Compare.gt_e (| + M.get_field (| M.get_name (| globals, "header" |), "number" |), + M.get_field (| M.get_name (| globals, "FORK_CRITERIA" |), "block_number" |) + |), + ltac:(M.monadic ( + Compare.lt (| + M.get_field (| M.get_name (| globals, "header" |), "number" |), + BinOp.add (| + M.get_field (| M.get_name (| globals, "FORK_CRITERIA" |), "block_number" |), + Constant.int 10 + |) + |) + )) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + Compare.eq (| + M.get_field (| M.get_name (| globals, "header" |), "extra_data" |), + Constant.bytes "64616f2d686172642d666f726b" + |); + M.get_name (| globals, "InvalidBlock" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.call (| + M.get_name (| globals, "validate_proof_of_work" |), + make_list [ + M.get_name (| globals, "header" |) + ], + make_dict [] + |) in + M.pure Constant.None_)). + +Definition generate_header_hash_for_pow : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "header" ] |) in + let _ := Constant.str " + Generate rlp hash of the header which is to be used for Proof-of-Work + verification. + + In other words, the PoW artefacts `mix_digest` and `nonce` are ignored + while calculating this hash. + + A particular PoW is valid for a single hash, that hash is computed by + this function. The `nonce` and `mix_digest` are omitted from this hash + because they are being changed by miners in their search for a sufficient + proof-of-work. + + Parameters + ---------- + header : + The header object for which the hash is to be generated. + + Returns + ------- + hash : `Hash32` + The PoW valid rlp hash of the passed in header. + " in + let _ := M.assign_local (| + "header_data_without_pow_artefacts" , + make_list [ + M.get_field (| M.get_name (| globals, "header" |), "parent_hash" |); + M.get_field (| M.get_name (| globals, "header" |), "ommers_hash" |); + M.get_field (| M.get_name (| globals, "header" |), "coinbase" |); + M.get_field (| M.get_name (| globals, "header" |), "state_root" |); + M.get_field (| M.get_name (| globals, "header" |), "transactions_root" |); + M.get_field (| M.get_name (| globals, "header" |), "receipt_root" |); + M.get_field (| M.get_name (| globals, "header" |), "bloom" |); + M.get_field (| M.get_name (| globals, "header" |), "difficulty" |); + M.get_field (| M.get_name (| globals, "header" |), "number" |); + M.get_field (| M.get_name (| globals, "header" |), "gas_limit" |); + M.get_field (| M.get_name (| globals, "header" |), "gas_used" |); + M.get_field (| M.get_name (| globals, "header" |), "timestamp" |); + M.get_field (| M.get_name (| globals, "header" |), "extra_data" |) + ] + |) in + let _ := M.return_ (| + M.call (| + M.get_field (| M.get_name (| globals, "rlp" |), "rlp_hash" |), + make_list [ + M.get_name (| globals, "header_data_without_pow_artefacts" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Definition validate_proof_of_work : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "header" ] |) in + let _ := Constant.str " + Validates the Proof of Work constraints. + + In order to verify that a miner's proof-of-work is valid for a block, a + ``mix-digest`` and ``result`` are calculated using the ``hashimoto_light`` + hash function. The mix digest is a hash of the header and the nonce that + is passed through and it confirms whether or not proof-of-work was done + on the correct block. The result is the actual hash value of the block. + + Parameters + ---------- + header : + Header of interest. + " in + let _ := M.assign_local (| + "header_hash" , + M.call (| + M.get_name (| globals, "generate_header_hash_for_pow" |), + make_list [ + M.get_name (| globals, "header" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "cache" , + M.call (| + M.get_name (| globals, "generate_cache" |), + make_list [ + M.get_field (| M.get_name (| globals, "header" |), "number" |) + ], + make_dict [] + |) + |) in + let _ := M.assign (| + make_tuple [ M.get_name (| globals, "mix_digest" |); M.get_name (| globals, "result" |) ], + M.call (| + M.get_name (| globals, "hashimoto_light" |), + make_list [ + M.get_name (| globals, "header_hash" |); + M.get_field (| M.get_name (| globals, "header" |), "nonce" |); + M.get_name (| globals, "cache" |); + M.call (| + M.get_name (| globals, "dataset_size" |), + make_list [ + M.get_field (| M.get_name (| globals, "header" |), "number" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + Compare.eq (| + M.get_name (| globals, "mix_digest" |), + M.get_field (| M.get_name (| globals, "header" |), "mix_digest" |) + |); + M.get_name (| globals, "InvalidBlock" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + Compare.lt_e (| + M.call (| + M.get_field (| M.get_name (| globals, "Uint" |), "from_be_bytes" |), + make_list [ + M.get_name (| globals, "result" |) + ], + make_dict [] + |), + BinOp.floor_div (| + M.get_name (| globals, "U256_CEIL_VALUE" |), + M.get_field (| M.get_name (| globals, "header" |), "difficulty" |) + |) + |); + M.get_name (| globals, "InvalidBlock" |) + ], + make_dict [] + |) in + M.pure Constant.None_)). + +Definition check_transaction : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "tx"; "gas_available" ] |) in + let _ := Constant.str " + Check if the transaction is includable in the block. + + Parameters + ---------- + tx : + The transaction. + gas_available : + The gas remaining in the block. + + Returns + ------- + sender_address : + The sender of the transaction. + + Raises + ------ + InvalidBlock : + If the transaction is not includable. + " in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + Compare.lt_e (| + M.get_field (| M.get_name (| globals, "tx" |), "gas" |), + M.get_name (| globals, "gas_available" |) + |); + M.get_name (| globals, "InvalidBlock" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "sender_address" , + M.call (| + M.get_name (| globals, "recover_sender" |), + make_list [ + M.get_name (| globals, "tx" |) + ], + make_dict [] + |) + |) in + let _ := M.return_ (| + M.get_name (| globals, "sender_address" |) + |) in + M.pure Constant.None_)). + +Definition make_receipt : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "tx"; "post_state"; "cumulative_gas_used"; "logs" ] |) in + let _ := Constant.str " + Make the receipt for a transaction that was executed. + + Parameters + ---------- + tx : + The executed transaction. + post_state : + The state root immediately after this transaction. + cumulative_gas_used : + The total gas used so far in the block after the transaction was + executed. + logs : + The logs produced by the transaction. + + Returns + ------- + receipt : + The receipt for the transaction. + " in + let _ := M.assign_local (| + "receipt" , + M.call (| + M.get_name (| globals, "Receipt" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.return_ (| + M.get_name (| globals, "receipt" |) + |) in + M.pure Constant.None_)). + +Definition ApplyBodyOutput : Value.t := + builtins.make_klass + [] + [ + + ] + [ + + ]. + +Definition apply_body : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "state"; "block_hashes"; "coinbase"; "block_number"; "block_gas_limit"; "block_time"; "block_difficulty"; "transactions"; "ommers" ] |) in + let _ := Constant.str " + Executes a block. + + Many of the contents of a block are stored in data structures called + tries. There is a transactions trie which is similar to a ledger of the + transactions stored in the current block. There is also a receipts trie + which stores the results of executing a transaction, like the post state + and gas used. This function creates and executes the block that is to be + added to the chain. + + Parameters + ---------- + state : + Current account state. + block_hashes : + List of hashes of the previous 256 blocks in the order of + increasing block number. + coinbase : + Address of account which receives block reward and transaction fees. + block_number : + Position of the block within the chain. + block_gas_limit : + Initial amount of gas available for execution in this block. + block_time : + Time the block was produced, measured in seconds since the epoch. + block_difficulty : + Difficulty of the block. + transactions : + Transactions included in the block. + ommers : + Headers of ancestor blocks which are not direct parents (formerly + uncles.) + + Returns + ------- + apply_body_output : `ApplyBodyOutput` + Output of applying the block body to the state. + " in + let _ := M.assign_local (| + "gas_available" , + M.get_name (| globals, "block_gas_limit" |) + |) in +(* At stmt: unsupported node type: AnnAssign *) +(* At stmt: unsupported node type: AnnAssign *) +(* At stmt: unsupported node type: AnnAssign *) + let _ := + M.for_ (| + make_tuple [ M.get_name (| globals, "i" |); M.get_name (| globals, "tx" |) ], + M.call (| + M.get_name (| globals, "enumerate" |), + make_list [ + M.get_name (| globals, "transactions" |) + ], + make_dict [] + |), + ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, "trie_set" |), + make_list [ + M.get_name (| globals, "transactions_trie" |); + M.call (| + M.get_field (| M.get_name (| globals, "rlp" |), "encode" |), + make_list [ + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.get_name (| globals, "i" |) + ], + make_dict [] + |) + ], + make_dict [] + |); + M.get_name (| globals, "tx" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "sender_address" , + M.call (| + M.get_name (| globals, "check_transaction" |), + make_list [ + M.get_name (| globals, "tx" |); + M.get_name (| globals, "gas_available" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "env" , + M.call (| + M.get_field (| M.get_name (| globals, "vm" |), "Environment" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.assign (| + make_tuple [ M.get_name (| globals, "gas_used" |); M.get_name (| globals, "logs" |) ], + M.call (| + M.get_name (| globals, "process_transaction" |), + make_list [ + M.get_name (| globals, "env" |); + M.get_name (| globals, "tx" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_op_local (| + BinOp.sub, + "gas_available", + M.get_name (| globals, "gas_used" |) + |) in + let _ := M.assign_local (| + "receipt" , + M.call (| + M.get_name (| globals, "make_receipt" |), + make_list [ + M.get_name (| globals, "tx" |); + M.call (| + M.get_name (| globals, "state_root" |), + make_list [ + M.get_name (| globals, "state" |) + ], + make_dict [] + |); + BinOp.sub (| + M.get_name (| globals, "block_gas_limit" |), + M.get_name (| globals, "gas_available" |) + |); + M.get_name (| globals, "logs" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "trie_set" |), + make_list [ + M.get_name (| globals, "receipts_trie" |); + M.call (| + M.get_field (| M.get_name (| globals, "rlp" |), "encode" |), + make_list [ + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.get_name (| globals, "i" |) + ], + make_dict [] + |) + ], + make_dict [] + |); + M.get_name (| globals, "receipt" |) + ], + make_dict [] + |) in + let _ := M.assign_op_local (| + BinOp.add, + "block_logs", + M.get_name (| globals, "logs" |) + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := M.call (| + M.get_name (| globals, "pay_rewards" |), + make_list [ + M.get_name (| globals, "state" |); + M.get_name (| globals, "block_number" |); + M.get_name (| globals, "coinbase" |); + M.get_name (| globals, "ommers" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "block_gas_used" , + BinOp.sub (| + M.get_name (| globals, "block_gas_limit" |), + M.get_name (| globals, "gas_available" |) + |) + |) in + let _ := M.assign_local (| + "block_logs_bloom" , + M.call (| + M.get_name (| globals, "logs_bloom" |), + make_list [ + M.get_name (| globals, "block_logs" |) + ], + make_dict [] + |) + |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, "ApplyBodyOutput" |), + make_list [ + M.get_name (| globals, "block_gas_used" |); + M.call (| + M.get_name (| globals, "root" |), + make_list [ + M.get_name (| globals, "transactions_trie" |) + ], + make_dict [] + |); + M.call (| + M.get_name (| globals, "root" |), + make_list [ + M.get_name (| globals, "receipts_trie" |) + ], + make_dict [] + |); + M.get_name (| globals, "block_logs_bloom" |); + M.call (| + M.get_name (| globals, "state_root" |), + make_list [ + M.get_name (| globals, "state" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Definition validate_ommers : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "ommers"; "block_header"; "chain" ] |) in + let _ := Constant.str " + Validates the ommers mentioned in the block. + + An ommer block is a block that wasn't canonically added to the + blockchain because it wasn't validated as fast as the canonical block + but was mined at the same time. + + To be considered valid, the ommers must adhere to the rules defined in + the Ethereum protocol. The maximum amount of ommers is 2 per block and + there cannot be duplicate ommers in a block. Many of the other ommer + constraints are listed in the in-line comments of this function. + + Parameters + ---------- + ommers : + List of ommers mentioned in the current block. + block_header: + The header of current block. + chain : + History and current state. + " in + let _ := M.assign_local (| + "block_hash" , + M.call (| + M.get_field (| M.get_name (| globals, "rlp" |), "rlp_hash" |), + make_list [ + M.get_name (| globals, "block_header" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + Compare.eq (| + M.call (| + M.get_field (| M.get_name (| globals, "rlp" |), "rlp_hash" |), + make_list [ + M.get_name (| globals, "ommers" |) + ], + make_dict [] + |), + M.get_field (| M.get_name (| globals, "block_header" |), "ommers_hash" |) + |); + M.get_name (| globals, "InvalidBlock" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_name (| globals, "ommers" |) + ], + make_dict [] + |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + Constant.None_ + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + M.for_ (| + M.get_name (| globals, "ommer" |), + M.get_name (| globals, "ommers" |), + ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + BoolOp.and (| + Compare.lt_e (| + Constant.int 1, + M.get_field (| M.get_name (| globals, "ommer" |), "number" |) + |), + ltac:(M.monadic ( + Compare.lt (| + M.get_field (| M.get_name (| globals, "ommer" |), "number" |), + M.get_field (| M.get_name (| globals, "block_header" |), "number" |) + |) + )) + |); + M.get_name (| globals, "InvalidBlock" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "ommer_parent_header" , + M.get_field (| M.get_subscript (| + M.get_field (| M.get_name (| globals, "chain" |), "blocks" |), + BinOp.sub (| + UnOp.sub (| BinOp.sub (| + M.get_field (| M.get_name (| globals, "block_header" |), "number" |), + M.get_field (| M.get_name (| globals, "ommer" |), "number" |) + |) |), + Constant.int 1 + |) + |), "header" |) + |) in + let _ := M.call (| + M.get_name (| globals, "validate_header" |), + make_list [ + M.get_name (| globals, "ommer" |); + M.get_name (| globals, "ommer_parent_header" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + Compare.lt_e (| + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_name (| globals, "ommers" |) + ], + make_dict [] + |), + Constant.int 2 + |); + M.get_name (| globals, "InvalidBlock" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "ommers_hashes" , + Constant.str "(* At expr: unsupported node type: ListComp *)" + |) in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + Compare.eq (| + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_name (| globals, "ommers_hashes" |) + ], + make_dict [] + |), + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.call (| + M.get_name (| globals, "set" |), + make_list [ + M.get_name (| globals, "ommers_hashes" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |); + M.get_name (| globals, "InvalidBlock" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "recent_canonical_blocks" , + M.slice (| + M.get_field (| M.get_name (| globals, "chain" |), "blocks" |), + UnOp.sub (| BinOp.add (| + M.get_name (| globals, "MAX_OMMER_DEPTH" |), + Constant.int 1 + |) |), + Constant.None_, + Constant.None_ + |) + |) in + let _ := M.assign_local (| + "recent_canonical_block_hashes" , + Constant.str "(* At expr: unsupported node type: SetComp *)" + |) in +(* At stmt: unsupported node type: AnnAssign *) + let _ := + M.for_ (| + M.get_name (| globals, "block" |), + M.get_name (| globals, "recent_canonical_blocks" |), + ltac:(M.monadic ( + let _ := M.assign_local (| + "recent_ommers_hashes" , + M.call (| + M.get_field (| M.get_name (| globals, "recent_ommers_hashes" |), "union" |), + make_list [ + Constant.str "(* At expr: unsupported node type: SetComp *)" + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := + M.for_ (| + make_tuple [ M.get_name (| globals, "ommer_index" |); M.get_name (| globals, "ommer" |) ], + M.call (| + M.get_name (| globals, "enumerate" |), + make_list [ + M.get_name (| globals, "ommers" |) + ], + make_dict [] + |), + ltac:(M.monadic ( + let _ := M.assign_local (| + "ommer_hash" , + M.get_subscript (| + M.get_name (| globals, "ommers_hashes" |), + M.get_name (| globals, "ommer_index" |) + |) + |) in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + Compare.not_eq (| + M.get_name (| globals, "ommer_hash" |), + M.get_name (| globals, "block_hash" |) + |); + M.get_name (| globals, "InvalidBlock" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + Compare.not_in (| + M.get_name (| globals, "ommer_hash" |), + M.get_name (| globals, "recent_canonical_block_hashes" |) + |); + M.get_name (| globals, "InvalidBlock" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + Compare.not_in (| + M.get_name (| globals, "ommer_hash" |), + M.get_name (| globals, "recent_ommers_hashes" |) + |); + M.get_name (| globals, "InvalidBlock" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "ommer_age" , + BinOp.sub (| + M.get_field (| M.get_name (| globals, "block_header" |), "number" |), + M.get_field (| M.get_name (| globals, "ommer" |), "number" |) + |) + |) in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + BoolOp.and (| + Compare.lt_e (| + Constant.int 1, + M.get_name (| globals, "ommer_age" |) + |), + ltac:(M.monadic ( + Compare.lt_e (| + M.get_name (| globals, "ommer_age" |), + M.get_name (| globals, "MAX_OMMER_DEPTH" |) + |) + )) + |); + M.get_name (| globals, "InvalidBlock" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + Compare.in_ (| + M.get_field (| M.get_name (| globals, "ommer" |), "parent_hash" |), + M.get_name (| globals, "recent_canonical_block_hashes" |) + |); + M.get_name (| globals, "InvalidBlock" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + Compare.not_eq (| + M.get_field (| M.get_name (| globals, "ommer" |), "parent_hash" |), + M.get_field (| M.get_name (| globals, "block_header" |), "parent_hash" |) + |); + M.get_name (| globals, "InvalidBlock" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + M.pure Constant.None_)). + +Definition pay_rewards : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "state"; "block_number"; "coinbase"; "ommers" ] |) in + let _ := Constant.str " + Pay rewards to the block miner as well as the ommers miners. + + The miner of the canonical block is rewarded with the predetermined + block reward, ``BLOCK_REWARD``, plus a variable award based off of the + number of ommer blocks that were mined around the same time, and included + in the canonical block's header. An ommer block is a block that wasn't + added to the canonical blockchain because it wasn't validated as fast as + the accepted block but was mined at the same time. Although not all blocks + that are mined are added to the canonical chain, miners are still paid a + reward for their efforts. This reward is called an ommer reward and is + calculated based on the number associated with the ommer block that they + mined. + + Parameters + ---------- + state : + Current account state. + block_number : + Position of the block within the chain. + coinbase : + Address of account which receives block reward and transaction fees. + ommers : + List of ommers mentioned in the current block. + " in + let _ := M.assign_local (| + "miner_reward" , + BinOp.add (| + M.get_name (| globals, "BLOCK_REWARD" |), + BinOp.mult (| + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_name (| globals, "ommers" |) + ], + make_dict [] + |), + BinOp.floor_div (| + M.get_name (| globals, "BLOCK_REWARD" |), + Constant.int 32 + |) + |) + |) + |) in + let _ := M.call (| + M.get_name (| globals, "create_ether" |), + make_list [ + M.get_name (| globals, "state" |); + M.get_name (| globals, "coinbase" |); + M.get_name (| globals, "miner_reward" |) + ], + make_dict [] + |) in + let _ := + M.for_ (| + M.get_name (| globals, "ommer" |), + M.get_name (| globals, "ommers" |), + ltac:(M.monadic ( + let _ := M.assign_local (| + "ommer_age" , + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + BinOp.sub (| + M.get_name (| globals, "block_number" |), + M.get_field (| M.get_name (| globals, "ommer" |), "number" |) + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "ommer_miner_reward" , + BinOp.floor_div (| + BinOp.mult (| + BinOp.sub (| + Constant.int 8, + M.get_name (| globals, "ommer_age" |) + |), + M.get_name (| globals, "BLOCK_REWARD" |) + |), + Constant.int 8 + |) + |) in + let _ := M.call (| + M.get_name (| globals, "create_ether" |), + make_list [ + M.get_name (| globals, "state" |); + M.get_field (| M.get_name (| globals, "ommer" |), "coinbase" |); + M.get_name (| globals, "ommer_miner_reward" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + M.pure Constant.None_)). + +Definition process_transaction : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "env"; "tx" ] |) in + let _ := Constant.str " + Execute a transaction against the provided environment. + + This function processes the actions needed to execute a transaction. + It decrements the sender's account after calculating the gas fee and + refunds them the proper amount after execution. Calling contracts, + deploying code, and incrementing nonces are all examples of actions that + happen within this function or from a call made within this function. + + Accounts that are marked for deletion are processed and destroyed after + execution. + + Parameters + ---------- + env : + Environment for the Ethereum Virtual Machine. + tx : + Transaction to execute. + + Returns + ------- + gas_left : `ethereum.base_types.U256` + Remaining gas after execution. + logs : `Tuple[ethereum.blocks.Log, ...]` + Logs generated during execution. + " in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + M.call (| + M.get_name (| globals, "validate_transaction" |), + make_list [ + M.get_name (| globals, "tx" |) + ], + make_dict [] + |); + M.get_name (| globals, "InvalidBlock" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "sender" , + M.get_field (| M.get_name (| globals, "env" |), "origin" |) + |) in + let _ := M.assign_local (| + "sender_account" , + M.call (| + M.get_name (| globals, "get_account" |), + make_list [ + M.get_field (| M.get_name (| globals, "env" |), "state" |); + M.get_name (| globals, "sender" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "gas_fee" , + BinOp.mult (| + M.get_field (| M.get_name (| globals, "tx" |), "gas" |), + M.get_field (| M.get_name (| globals, "tx" |), "gas_price" |) + |) + |) in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + Compare.eq (| + M.get_field (| M.get_name (| globals, "sender_account" |), "nonce" |), + M.get_field (| M.get_name (| globals, "tx" |), "nonce" |) + |); + M.get_name (| globals, "InvalidBlock" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + Compare.gt_e (| + M.get_field (| M.get_name (| globals, "sender_account" |), "balance" |), + BinOp.add (| + M.get_name (| globals, "gas_fee" |), + M.get_field (| M.get_name (| globals, "tx" |), "value" |) + |) + |); + M.get_name (| globals, "InvalidBlock" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + Compare.eq (| + M.get_field (| M.get_name (| globals, "sender_account" |), "code" |), + M.call (| + M.get_name (| globals, "bytearray" |), + make_list [], + make_dict [] + |) + |); + M.get_name (| globals, "InvalidBlock" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "gas" , + BinOp.sub (| + M.get_field (| M.get_name (| globals, "tx" |), "gas" |), + M.call (| + M.get_name (| globals, "calculate_intrinsic_cost" |), + make_list [ + M.get_name (| globals, "tx" |) + ], + make_dict [] + |) + |) + |) in + let _ := M.call (| + M.get_name (| globals, "increment_nonce" |), + make_list [ + M.get_field (| M.get_name (| globals, "env" |), "state" |); + M.get_name (| globals, "sender" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "sender_balance_after_gas_fee" , + BinOp.sub (| + M.get_field (| M.get_name (| globals, "sender_account" |), "balance" |), + M.get_name (| globals, "gas_fee" |) + |) + |) in + let _ := M.call (| + M.get_name (| globals, "set_account_balance" |), + make_list [ + M.get_field (| M.get_name (| globals, "env" |), "state" |); + M.get_name (| globals, "sender" |); + M.get_name (| globals, "sender_balance_after_gas_fee" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "message" , + M.call (| + M.get_name (| globals, "prepare_message" |), + make_list [ + M.get_name (| globals, "sender" |); + M.get_field (| M.get_name (| globals, "tx" |), "to" |); + M.get_field (| M.get_name (| globals, "tx" |), "value" |); + M.get_field (| M.get_name (| globals, "tx" |), "data" |); + M.get_name (| globals, "gas" |); + M.get_name (| globals, "env" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "output" , + M.call (| + M.get_name (| globals, "process_message_call" |), + make_list [ + M.get_name (| globals, "message" |); + M.get_name (| globals, "env" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "gas_used" , + BinOp.sub (| + M.get_field (| M.get_name (| globals, "tx" |), "gas" |), + M.get_field (| M.get_name (| globals, "output" |), "gas_left" |) + |) + |) in + let _ := M.assign_local (| + "gas_refund" , + M.call (| + M.get_name (| globals, "min" |), + make_list [ + BinOp.floor_div (| + M.get_name (| globals, "gas_used" |), + Constant.int 2 + |); + M.get_field (| M.get_name (| globals, "output" |), "refund_counter" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "gas_refund_amount" , + BinOp.mult (| + BinOp.add (| + M.get_field (| M.get_name (| globals, "output" |), "gas_left" |), + M.get_name (| globals, "gas_refund" |) + |), + M.get_field (| M.get_name (| globals, "tx" |), "gas_price" |) + |) + |) in + let _ := M.assign_local (| + "transaction_fee" , + BinOp.mult (| + BinOp.sub (| + BinOp.sub (| + M.get_field (| M.get_name (| globals, "tx" |), "gas" |), + M.get_field (| M.get_name (| globals, "output" |), "gas_left" |) + |), + M.get_name (| globals, "gas_refund" |) + |), + M.get_field (| M.get_name (| globals, "tx" |), "gas_price" |) + |) + |) in + let _ := M.assign_local (| + "total_gas_used" , + BinOp.sub (| + M.get_name (| globals, "gas_used" |), + M.get_name (| globals, "gas_refund" |) + |) + |) in + let _ := M.assign_local (| + "sender_balance_after_refund" , + BinOp.add (| + M.get_field (| M.call (| + M.get_name (| globals, "get_account" |), + make_list [ + M.get_field (| M.get_name (| globals, "env" |), "state" |); + M.get_name (| globals, "sender" |) + ], + make_dict [] + |), "balance" |), + M.get_name (| globals, "gas_refund_amount" |) + |) + |) in + let _ := M.call (| + M.get_name (| globals, "set_account_balance" |), + make_list [ + M.get_field (| M.get_name (| globals, "env" |), "state" |); + M.get_name (| globals, "sender" |); + M.get_name (| globals, "sender_balance_after_refund" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "coinbase_balance_after_mining_fee" , + BinOp.add (| + M.get_field (| M.call (| + M.get_name (| globals, "get_account" |), + make_list [ + M.get_field (| M.get_name (| globals, "env" |), "state" |); + M.get_field (| M.get_name (| globals, "env" |), "coinbase" |) + ], + make_dict [] + |), "balance" |), + M.get_name (| globals, "transaction_fee" |) + |) + |) in + let _ := M.call (| + M.get_name (| globals, "set_account_balance" |), + make_list [ + M.get_field (| M.get_name (| globals, "env" |), "state" |); + M.get_field (| M.get_name (| globals, "env" |), "coinbase" |); + M.get_name (| globals, "coinbase_balance_after_mining_fee" |) + ], + make_dict [] + |) in + let _ := + M.for_ (| + M.get_name (| globals, "address" |), + M.get_field (| M.get_name (| globals, "output" |), "accounts_to_delete" |), + ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, "destroy_account" |), + make_list [ + M.get_field (| M.get_name (| globals, "env" |), "state" |); + M.get_name (| globals, "address" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := M.return_ (| + make_tuple [ M.get_name (| globals, "total_gas_used" |); M.get_field (| M.get_name (| globals, "output" |), "logs" |) ] + |) in + M.pure Constant.None_)). + +Definition validate_transaction : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "tx" ] |) in + let _ := Constant.str " + Verifies a transaction. + + The gas in a transaction gets used to pay for the intrinsic cost of + operations, therefore if there is insufficient gas then it would not + be possible to execute a transaction and it will be declared invalid. + + Additionally, the nonce of a transaction must not equal or exceed the + limit defined in `EIP-2681 `_. + In practice, defining the limit as ``2**64-1`` has no impact because + sending ``2**64-1`` transactions is improbable. It's not strictly + impossible though, ``2**64-1`` transactions is the entire capacity of the + Ethereum blockchain at 2022 gas limits for a little over 22 years. + + Parameters + ---------- + tx : + Transaction to validate. + + Returns + ------- + verified : `bool` + True if the transaction can be executed, or False otherwise. + " in + let _ := M.return_ (| + BoolOp.and (| + Compare.lt_e (| + M.call (| + M.get_name (| globals, "calculate_intrinsic_cost" |), + make_list [ + M.get_name (| globals, "tx" |) + ], + make_dict [] + |), + M.get_field (| M.get_name (| globals, "tx" |), "gas" |) + |), + ltac:(M.monadic ( + Compare.lt (| + M.get_field (| M.get_name (| globals, "tx" |), "nonce" |), + BinOp.sub (| + BinOp.pow (| + Constant.int 2, + Constant.int 64 + |), + Constant.int 1 + |) + |) + )) + |) + |) in + M.pure Constant.None_)). + +Definition calculate_intrinsic_cost : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "tx" ] |) in + let _ := Constant.str " + Calculates the gas that is charged before execution is started. + + The intrinsic cost of the transaction is charged before execution has + begun. Functions/operations in the EVM cost money to execute so this + intrinsic cost is for the operations that need to be paid for as part of + the transaction. Data transfer, for example, is part of this intrinsic + cost. It costs ether to send data over the wire and that ether is + accounted for in the intrinsic cost calculated in this function. This + intrinsic cost must be calculated and paid for before execution in order + for all operations to be implemented. + + Parameters + ---------- + tx : + Transaction to compute the intrinsic cost of. + + Returns + ------- + verified : `ethereum.base_types.Uint` + The intrinsic cost of the transaction. + " in + let _ := M.assign_local (| + "data_cost" , + Constant.int 0 + |) in + let _ := + M.for_ (| + M.get_name (| globals, "byte" |), + M.get_field (| M.get_name (| globals, "tx" |), "data" |), + ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, "byte" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_op_local (| + BinOp.add, + "data_cost", + M.get_name (| globals, "TX_DATA_COST_PER_ZERO" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_op_local (| + BinOp.add, + "data_cost", + M.get_name (| globals, "TX_DATA_COST_PER_NON_ZERO" |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_field (| M.get_name (| globals, "tx" |), "to" |), + M.call (| + M.get_name (| globals, "Bytes0" |), + make_list [ + Constant.bytes "" + ], + make_dict [] + |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "create_cost" , + M.get_name (| globals, "TX_CREATE_COST" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "create_cost" , + Constant.int 0 + |) in + M.pure Constant.None_ + )) |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + BinOp.add (| + BinOp.add (| + M.get_name (| globals, "TX_BASE_COST" |), + M.get_name (| globals, "data_cost" |) + |), + M.get_name (| globals, "create_cost" |) + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Definition recover_sender : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "tx" ] |) in + let _ := Constant.str " + Extracts the sender address from a transaction. + + The v, r, and s values are the three parts that make up the signature + of a transaction. In order to recover the sender of a transaction the two + components needed are the signature (``v``, ``r``, and ``s``) and the + signing hash of the transaction. The sender's public key can be obtained + with these two values and therefore the sender address can be retrieved. + + Parameters + ---------- + tx : + Transaction of interest. + + Returns + ------- + sender : `ethereum.fork_types.Address` + The address of the account that signed the transaction. + " in + let _ := M.assign (| + make_tuple [ M.get_name (| globals, "v" |); M.get_name (| globals, "r" |); M.get_name (| globals, "s" |) ], + make_tuple [ M.get_field (| M.get_name (| globals, "tx" |), "v" |); M.get_field (| M.get_name (| globals, "tx" |), "r" |); M.get_field (| M.get_name (| globals, "tx" |), "s" |) ] + |) in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + BoolOp.or (| + Compare.eq (| + M.get_name (| globals, "v" |), + Constant.int 27 + |), + ltac:(M.monadic ( + Compare.eq (| + M.get_name (| globals, "v" |), + Constant.int 28 + |) + )) + |); + M.get_name (| globals, "InvalidBlock" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + BoolOp.and (| + Compare.lt (| + Constant.int 0, + M.get_name (| globals, "r" |) + |), + ltac:(M.monadic ( + Compare.lt (| + M.get_name (| globals, "r" |), + M.get_name (| globals, "SECP256K1N" |) + |) + )) + |); + M.get_name (| globals, "InvalidBlock" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + BoolOp.and (| + Compare.lt (| + Constant.int 0, + M.get_name (| globals, "s" |) + |), + ltac:(M.monadic ( + Compare.lt_e (| + M.get_name (| globals, "s" |), + BinOp.floor_div (| + M.get_name (| globals, "SECP256K1N" |), + Constant.int 2 + |) + |) + )) + |); + M.get_name (| globals, "InvalidBlock" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "public_key" , + M.call (| + M.get_name (| globals, "secp256k1_recover" |), + make_list [ + M.get_name (| globals, "r" |); + M.get_name (| globals, "s" |); + BinOp.sub (| + M.get_name (| globals, "v" |), + Constant.int 27 + |); + M.call (| + M.get_name (| globals, "signing_hash" |), + make_list [ + M.get_name (| globals, "tx" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, "Address" |), + make_list [ + M.slice (| + M.call (| + M.get_name (| globals, "keccak256" |), + make_list [ + M.get_name (| globals, "public_key" |) + ], + make_dict [] + |), + Constant.int 12, + Constant.int 32, + Constant.None_ + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Definition signing_hash : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "tx" ] |) in + let _ := Constant.str " + Compute the hash of a transaction used in the signature. + + The values that are used to compute the signing hash set the rules for a + transaction. For example, signing over the gas sets a limit for the + amount of money that is allowed to be pulled out of the sender's account. + + Parameters + ---------- + tx : + Transaction of interest. + + Returns + ------- + hash : `ethereum.crypto.hash.Hash32` + Hash of the transaction. + " in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, "keccak256" |), + make_list [ + M.call (| + M.get_field (| M.get_name (| globals, "rlp" |), "encode" |), + make_list [ + make_tuple [ M.get_field (| M.get_name (| globals, "tx" |), "nonce" |); M.get_field (| M.get_name (| globals, "tx" |), "gas_price" |); M.get_field (| M.get_name (| globals, "tx" |), "gas" |); M.get_field (| M.get_name (| globals, "tx" |), "to" |); M.get_field (| M.get_name (| globals, "tx" |), "value" |); M.get_field (| M.get_name (| globals, "tx" |), "data" |) ] + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Definition compute_header_hash : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "header" ] |) in + let _ := Constant.str " + Computes the hash of a block header. + + The header hash of a block is the canonical hash that is used to refer + to a specific block and completely distinguishes a block from another. + + ``keccak256`` is a function that produces a 256 bit hash of any input. + It also takes in any number of bytes as an input and produces a single + hash for them. A hash is a completely unique output for a single input. + So an input corresponds to one unique hash that can be used to identify + the input exactly. + + Prior to using the ``keccak256`` hash function, the header must be + encoded using the Recursive-Length Prefix. See :ref:`rlp`. + RLP encoding the header converts it into a space-efficient format that + allows for easy transfer of data between nodes. The purpose of RLP is to + encode arbitrarily nested arrays of binary data, and RLP is the primary + encoding method used to serialize objects in Ethereum's execution layer. + The only purpose of RLP is to encode structure; encoding specific data + types (e.g. strings, floats) is left up to higher-order protocols. + + Parameters + ---------- + header : + Header of interest. + + Returns + ------- + hash : `ethereum.crypto.hash.Hash32` + Hash of the header. + " in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, "keccak256" |), + make_list [ + M.call (| + M.get_field (| M.get_name (| globals, "rlp" |), "encode" |), + make_list [ + M.get_name (| globals, "header" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Definition check_gas_limit : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "gas_limit"; "parent_gas_limit" ] |) in + let _ := Constant.str " + Validates the gas limit for a block. + + The bounds of the gas limit, ``max_adjustment_delta``, is set as the + quotient of the parent block's gas limit and the + ``GAS_LIMIT_ADJUSTMENT_FACTOR``. Therefore, if the gas limit that is + passed through as a parameter is greater than or equal to the *sum* of + the parent's gas and the adjustment delta then the limit for gas is too + high and fails this function's check. Similarly, if the limit is less + than or equal to the *difference* of the parent's gas and the adjustment + delta *or* the predefined ``GAS_LIMIT_MINIMUM`` then this function's + check fails because the gas limit doesn't allow for a sufficient or + reasonable amount of gas to be used on a block. + + Parameters + ---------- + gas_limit : + Gas limit to validate. + + parent_gas_limit : + Gas limit of the parent block. + + Returns + ------- + check : `bool` + True if gas limit constraints are satisfied, False otherwise. + " in + let _ := M.assign_local (| + "max_adjustment_delta" , + BinOp.floor_div (| + M.get_name (| globals, "parent_gas_limit" |), + M.get_name (| globals, "GAS_LIMIT_ADJUSTMENT_FACTOR" |) + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.gt_e (| + M.get_name (| globals, "gas_limit" |), + BinOp.add (| + M.get_name (| globals, "parent_gas_limit" |), + M.get_name (| globals, "max_adjustment_delta" |) + |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + Constant.bool false + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + Compare.lt_e (| + M.get_name (| globals, "gas_limit" |), + BinOp.sub (| + M.get_name (| globals, "parent_gas_limit" |), + M.get_name (| globals, "max_adjustment_delta" |) + |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + Constant.bool false + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + Compare.lt (| + M.get_name (| globals, "gas_limit" |), + M.get_name (| globals, "GAS_LIMIT_MINIMUM" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + Constant.bool false + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.return_ (| + Constant.bool true + |) in + M.pure Constant.None_)). + +Definition calculate_block_difficulty : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "block_number"; "block_timestamp"; "parent_timestamp"; "parent_difficulty" ] |) in + let _ := Constant.str " + Computes difficulty of a block using its header and parent header. + + The difficulty is determined by the time the block was created after its + parent. The ``offset`` is calculated using the parent block's difficulty, + ``parent_difficulty``, and the timestamp between blocks. This offset is + then added to the parent difficulty and is stored as the ``difficulty`` + variable. If the time between the block and its parent is too short, the + offset will result in a positive number thus making the sum of + ``parent_difficulty`` and ``offset`` to be a greater value in order to + avoid mass forking. But, if the time is long enough, then the offset + results in a negative value making the block less difficult than + its parent. + + The base standard for a block's difficulty is the predefined value + set for the genesis block since it has no parent. So, a block + can't be less difficult than the genesis block, therefore each block's + difficulty is set to the maximum value between the calculated + difficulty and the ``GENESIS_DIFFICULTY``. + + Parameters + ---------- + block_number : + Block number of the block. + block_timestamp : + Timestamp of the block. + parent_timestamp : + Timestamp of the parent block. + parent_difficulty : + difficulty of the parent block. + + Returns + ------- + difficulty : `ethereum.base_types.Uint` + Computed difficulty for a block. + " in + let _ := M.assign_local (| + "offset" , + BinOp.mult (| + BinOp.floor_div (| + M.call (| + M.get_name (| globals, "int" |), + make_list [ + M.get_name (| globals, "parent_difficulty" |) + ], + make_dict [] + |), + Constant.int 2048 + |), + M.call (| + M.get_name (| globals, "max" |), + make_list [ + BinOp.sub (| + Constant.int 1, + BinOp.floor_div (| + M.call (| + M.get_name (| globals, "int" |), + make_list [ + BinOp.sub (| + M.get_name (| globals, "block_timestamp" |), + M.get_name (| globals, "parent_timestamp" |) + |) + ], + make_dict [] + |), + Constant.int 10 + |) + |); + UnOp.sub (| Constant.int 99 |) + ], + make_dict [] + |) + |) + |) in + let _ := M.assign_local (| + "difficulty" , + BinOp.add (| + M.call (| + M.get_name (| globals, "int" |), + make_list [ + M.get_name (| globals, "parent_difficulty" |) + ], + make_dict [] + |), + M.get_name (| globals, "offset" |) + |) + |) in + let _ := M.assign_local (| + "num_bomb_periods" , + BinOp.sub (| + BinOp.floor_div (| + M.call (| + M.get_name (| globals, "int" |), + make_list [ + M.get_name (| globals, "block_number" |) + ], + make_dict [] + |), + Constant.int 100000 + |), + Constant.int 2 + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.gt_e (| + M.get_name (| globals, "num_bomb_periods" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_op_local (| + BinOp.add, + "difficulty", + BinOp.pow (| + Constant.int 2, + M.get_name (| globals, "num_bomb_periods" |) + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, "max" |), + make_list [ + M.get_name (| globals, "difficulty" |); + M.get_name (| globals, "MINIMUM_DIFFICULTY" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). diff --git a/CoqOfPython/ethereum/dao_fork/fork_types.v b/CoqOfPython/ethereum/dao_fork/fork_types.v new file mode 100644 index 0000000..7d58b79 --- /dev/null +++ b/CoqOfPython/ethereum/dao_fork/fork_types.v @@ -0,0 +1,98 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.dao_fork.fork_types". + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Types +^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Types re-used throughout the specification, which are specific to Ethereum. +". + +Axiom dataclasses_imports_dataclass : + IsImported globals "dataclasses" "dataclass". + +Axiom ethereum_imports_rlp : + IsImported globals "ethereum" "rlp". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_Bytes : + IsImported globals "ethereum.base_types" "Bytes". +Axiom ethereum_base_types_imports_Bytes20 : + IsImported globals "ethereum.base_types" "Bytes20". +Axiom ethereum_base_types_imports_Bytes256 : + IsImported globals "ethereum.base_types" "Bytes256". +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". +Axiom ethereum_base_types_imports_slotted_freezable : + IsImported globals "ethereum.base_types" "slotted_freezable". + +Axiom ethereum_crypto_hash_imports_Hash32 : + IsImported globals "ethereum.crypto.hash" "Hash32". +Axiom ethereum_crypto_hash_imports_keccak256 : + IsImported globals "ethereum.crypto.hash" "keccak256". + +Definition Address : Value.t := M.run ltac:(M.monadic ( + M.get_name (| globals, "Bytes20" |) +)). + +Definition Root : Value.t := M.run ltac:(M.monadic ( + M.get_name (| globals, "Hash32" |) +)). + +Definition Bloom : Value.t := M.run ltac:(M.monadic ( + M.get_name (| globals, "Bytes256" |) +)). + +Definition Account : Value.t := + builtins.make_klass + [] + [ + + ] + [ + + ]. + +Definition EMPTY_ACCOUNT : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Account" |), + make_list [], + make_dict [] + |) +)). + +Definition encode_account : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "raw_account_data"; "storage_root" ] |) in + let _ := Constant.str " + Encode `Account` dataclass. + + Storage is not stored in the `Account` dataclass, so `Accounts` cannot be + encoded with providing a storage root. + " in + let _ := M.return_ (| + M.call (| + M.get_field (| M.get_name (| globals, "rlp" |), "encode" |), + make_list [ + make_tuple [ M.get_field (| M.get_name (| globals, "raw_account_data" |), "nonce" |); M.get_field (| M.get_name (| globals, "raw_account_data" |), "balance" |); M.get_name (| globals, "storage_root" |); M.call (| + M.get_name (| globals, "keccak256" |), + make_list [ + M.get_field (| M.get_name (| globals, "raw_account_data" |), "code" |) + ], + make_dict [] + |) ] + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). diff --git a/CoqOfPython/ethereum/dao_fork/state.v b/CoqOfPython/ethereum/dao_fork/state.v new file mode 100644 index 0000000..c526dbf --- /dev/null +++ b/CoqOfPython/ethereum/dao_fork/state.v @@ -0,0 +1,906 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.dao_fork.state". + +Definition expr_1 : Value.t := + Constant.str " +State +^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +The state contains all information that is preserved between transactions. + +It consists of a main account trie and storage tries for each contract. + +There is a distinction between an account that does not exist and +`EMPTY_ACCOUNT`. +". + +Axiom dataclasses_imports_dataclass : + IsImported globals "dataclasses" "dataclass". +Axiom dataclasses_imports_field : + IsImported globals "dataclasses" "field". + +Axiom typing_imports_Callable : + IsImported globals "typing" "Callable". +Axiom typing_imports_Dict : + IsImported globals "typing" "Dict". +Axiom typing_imports_List : + IsImported globals "typing" "List". +Axiom typing_imports_Optional : + IsImported globals "typing" "Optional". +Axiom typing_imports_Tuple : + IsImported globals "typing" "Tuple". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_Bytes : + IsImported globals "ethereum.base_types" "Bytes". +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". +Axiom ethereum_base_types_imports_modify : + IsImported globals "ethereum.base_types" "modify". + +Axiom ethereum_utils_ensure_imports_ensure : + IsImported globals "ethereum.utils.ensure" "ensure". + +Axiom ethereum_dao_fork_fork_types_imports_EMPTY_ACCOUNT : + IsImported globals "ethereum.dao_fork.fork_types" "EMPTY_ACCOUNT". +Axiom ethereum_dao_fork_fork_types_imports_Account : + IsImported globals "ethereum.dao_fork.fork_types" "Account". +Axiom ethereum_dao_fork_fork_types_imports_Address : + IsImported globals "ethereum.dao_fork.fork_types" "Address". +Axiom ethereum_dao_fork_fork_types_imports_Root : + IsImported globals "ethereum.dao_fork.fork_types" "Root". + +Axiom ethereum_dao_fork_trie_imports_EMPTY_TRIE_ROOT : + IsImported globals "ethereum.dao_fork.trie" "EMPTY_TRIE_ROOT". +Axiom ethereum_dao_fork_trie_imports_Trie : + IsImported globals "ethereum.dao_fork.trie" "Trie". +Axiom ethereum_dao_fork_trie_imports_copy_trie : + IsImported globals "ethereum.dao_fork.trie" "copy_trie". +Axiom ethereum_dao_fork_trie_imports_root : + IsImported globals "ethereum.dao_fork.trie" "root". +Axiom ethereum_dao_fork_trie_imports_trie_get : + IsImported globals "ethereum.dao_fork.trie" "trie_get". +Axiom ethereum_dao_fork_trie_imports_trie_set : + IsImported globals "ethereum.dao_fork.trie" "trie_set". + +Definition State : Value.t := + builtins.make_klass + [] + [ + + ] + [ + + ]. + +Definition close_state : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "state" ] |) in + let _ := Constant.str " + Free resources held by the state. Used by optimized implementations to + release file descriptors. + " in + let _ := M.delete (| M.get_field (| M.get_name (| globals, "state" |), "_main_trie" |) |) in + let _ := M.delete (| M.get_field (| M.get_name (| globals, "state" |), "_storage_tries" |) |) in + let _ := M.delete (| M.get_field (| M.get_name (| globals, "state" |), "_snapshots" |) |) in + M.pure Constant.None_)). + +Definition begin_transaction : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "state" ] |) in + let _ := Constant.str " + Start a state transaction. + + Transactions are entirely implicit and can be nested. It is not possible to + calculate the state root during a transaction. + + Parameters + ---------- + state : State + The state. + " in + let _ := M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, "state" |), "_snapshots" |), "append" |), + make_list [ + make_tuple [ M.call (| + M.get_name (| globals, "copy_trie" |), + make_list [ + M.get_field (| M.get_name (| globals, "state" |), "_main_trie" |) + ], + make_dict [] + |); Constant.str "(* At expr: unsupported node type: DictComp *)" ] + ], + make_dict [] + |) in + M.pure Constant.None_)). + +Definition commit_transaction : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "state" ] |) in + let _ := Constant.str " + Commit a state transaction. + + Parameters + ---------- + state : State + The state. + " in + let _ := M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, "state" |), "_snapshots" |), "pop" |), + make_list [], + make_dict [] + |) in + M.pure Constant.None_)). + +Definition rollback_transaction : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "state" ] |) in + let _ := Constant.str " + Rollback a state transaction, resetting the state to the point when the + corresponding `start_transaction()` call was made. + + Parameters + ---------- + state : State + The state. + " in + let _ := M.assign (| + make_tuple [ M.get_field (| M.get_name (| globals, "state" |), "_main_trie" |); M.get_field (| M.get_name (| globals, "state" |), "_storage_tries" |) ], + M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, "state" |), "_snapshots" |), "pop" |), + make_list [], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Definition get_account : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "state"; "address" ] |) in + let _ := Constant.str " + Get the `Account` object at an address. Returns `EMPTY_ACCOUNT` if there + is no account at the address. + + Use `get_account_optional()` if you care about the difference between a + non-existent account and `EMPTY_ACCOUNT`. + + Parameters + ---------- + state: `State` + The state + address : `Address` + Address to lookup. + + Returns + ------- + account : `Account` + Account at address. + " in + let _ := M.assign_local (| + "account" , + M.call (| + M.get_name (| globals, "get_account_optional" |), + make_list [ + M.get_name (| globals, "state" |); + M.get_name (| globals, "address" |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, "isinstance" |), + make_list [ + M.get_name (| globals, "account" |); + M.get_name (| globals, "Account" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + M.get_name (| globals, "account" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.return_ (| + M.get_name (| globals, "EMPTY_ACCOUNT" |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_)). + +Definition get_account_optional : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "state"; "address" ] |) in + let _ := Constant.str " + Get the `Account` object at an address. Returns `None` (rather than + `EMPTY_ACCOUNT`) if there is no account at the address. + + Parameters + ---------- + state: `State` + The state + address : `Address` + Address to lookup. + + Returns + ------- + account : `Account` + Account at address. + " in + let _ := M.assign_local (| + "account" , + M.call (| + M.get_name (| globals, "trie_get" |), + make_list [ + M.get_field (| M.get_name (| globals, "state" |), "_main_trie" |); + M.get_name (| globals, "address" |) + ], + make_dict [] + |) + |) in + let _ := M.return_ (| + M.get_name (| globals, "account" |) + |) in + M.pure Constant.None_)). + +Definition set_account : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "state"; "address"; "account" ] |) in + let _ := Constant.str " + Set the `Account` object at an address. Setting to `None` deletes + the account (but not its storage, see `destroy_account()`). + + Parameters + ---------- + state: `State` + The state + address : `Address` + Address to set. + account : `Account` + Account to set at address. + " in + let _ := M.call (| + M.get_name (| globals, "trie_set" |), + make_list [ + M.get_field (| M.get_name (| globals, "state" |), "_main_trie" |); + M.get_name (| globals, "address" |); + M.get_name (| globals, "account" |) + ], + make_dict [] + |) in + M.pure Constant.None_)). + +Definition destroy_account : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "state"; "address" ] |) in + let _ := Constant.str " + Completely remove the account at `address` and all of its storage. + + This function is made available exclusively for the `SELFDESTRUCT` + opcode. It is expected that `SELFDESTRUCT` will be disabled in a future + hardfork and this function will be removed. + + Parameters + ---------- + state: `State` + The state + address : `Address` + Address of account to destroy. + " in + let _ := M.call (| + M.get_name (| globals, "destroy_storage" |), + make_list [ + M.get_name (| globals, "state" |); + M.get_name (| globals, "address" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "set_account" |), + make_list [ + M.get_name (| globals, "state" |); + M.get_name (| globals, "address" |); + Constant.None_ + ], + make_dict [] + |) in + M.pure Constant.None_)). + +Definition destroy_storage : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "state"; "address" ] |) in + let _ := Constant.str " + Completely remove the storage at `address`. + + Parameters + ---------- + state: `State` + The state + address : `Address` + Address of account whose storage is to be deleted. + " in + let _ := + (* if *) + M.if_then_else (| + Compare.in_ (| + M.get_name (| globals, "address" |), + M.get_field (| M.get_name (| globals, "state" |), "_storage_tries" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.delete (| M.get_subscript (| + M.get_field (| M.get_name (| globals, "state" |), "_storage_tries" |), + M.get_name (| globals, "address" |) + |) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + M.pure Constant.None_)). + +Definition get_storage : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "state"; "address"; "key" ] |) in + let _ := Constant.str " + Get a value at a storage key on an account. Returns `U256(0)` if the + storage key has not been set previously. + + Parameters + ---------- + state: `State` + The state + address : `Address` + Address of the account. + key : `Bytes` + Key to lookup. + + Returns + ------- + value : `U256` + Value at the key. + " in + let _ := M.assign_local (| + "trie" , + M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, "state" |), "_storage_tries" |), "get" |), + make_list [ + M.get_name (| globals, "address" |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.is (| + M.get_name (| globals, "trie" |), + Constant.None_ + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "value" , + M.call (| + M.get_name (| globals, "trie_get" |), + make_list [ + M.get_name (| globals, "trie" |); + M.get_name (| globals, "key" |) + ], + make_dict [] + |) + |) in + let _ := M.assert (| M.call (| + M.get_name (| globals, "isinstance" |), + make_list [ + M.get_name (| globals, "value" |); + M.get_name (| globals, "U256" |) + ], + make_dict [] + |) |) in + let _ := M.return_ (| + M.get_name (| globals, "value" |) + |) in + M.pure Constant.None_)). + +Definition set_storage : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "state"; "address"; "key"; "value" ] |) in + let _ := Constant.str " + Set a value at a storage key on an account. Setting to `U256(0)` deletes + the key. + + Parameters + ---------- + state: `State` + The state + address : `Address` + Address of the account. + key : `Bytes` + Key to set. + value : `U256` + Value to set at the key. + " in + let _ := M.assert (| Compare.is_not (| + M.call (| + M.get_name (| globals, "trie_get" |), + make_list [ + M.get_field (| M.get_name (| globals, "state" |), "_main_trie" |); + M.get_name (| globals, "address" |) + ], + make_dict [] + |), + Constant.None_ + |) |) in + let _ := M.assign_local (| + "trie" , + M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, "state" |), "_storage_tries" |), "get" |), + make_list [ + M.get_name (| globals, "address" |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.is (| + M.get_name (| globals, "trie" |), + Constant.None_ + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "trie" , + M.call (| + M.get_name (| globals, "Trie" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.assign (| + M.get_subscript (| + M.get_field (| M.get_name (| globals, "state" |), "_storage_tries" |), + M.get_name (| globals, "address" |) + |), + M.get_name (| globals, "trie" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.call (| + M.get_name (| globals, "trie_set" |), + make_list [ + M.get_name (| globals, "trie" |); + M.get_name (| globals, "key" |); + M.get_name (| globals, "value" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_field (| M.get_name (| globals, "trie" |), "_data" |), + Constant.str "(* At expr: unsupported node type: Dict *)" + |), + (* then *) + ltac:(M.monadic ( + let _ := M.delete (| M.get_subscript (| + M.get_field (| M.get_name (| globals, "state" |), "_storage_tries" |), + M.get_name (| globals, "address" |) + |) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + M.pure Constant.None_)). + +Definition storage_root : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "state"; "address" ] |) in + let _ := Constant.str " + Calculate the storage root of an account. + + Parameters + ---------- + state: + The state + address : + Address of the account. + + Returns + ------- + root : `Root` + Storage root of the account. + " in + let _ := M.assert (| UnOp.not (| M.get_field (| M.get_name (| globals, "state" |), "_snapshots" |) |) |) in + let _ := + (* if *) + M.if_then_else (| + Compare.in_ (| + M.get_name (| globals, "address" |), + M.get_field (| M.get_name (| globals, "state" |), "_storage_tries" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + M.call (| + M.get_name (| globals, "root" |), + make_list [ + M.get_subscript (| + M.get_field (| M.get_name (| globals, "state" |), "_storage_tries" |), + M.get_name (| globals, "address" |) + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.return_ (| + M.get_name (| globals, "EMPTY_TRIE_ROOT" |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_)). + +Definition state_root : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "state" ] |) in + let _ := Constant.str " + Calculate the state root. + + Parameters + ---------- + state: + The current state. + + Returns + ------- + root : `Root` + The state root. + " in + let _ := M.assert (| UnOp.not (| M.get_field (| M.get_name (| globals, "state" |), "_snapshots" |) |) |) in +(* At stmt: unsupported node type: FunctionDef *) + let _ := M.return_ (| + M.call (| + M.get_name (| globals, "root" |), + make_list [ + M.get_field (| M.get_name (| globals, "state" |), "_main_trie" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Definition account_exists : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "state"; "address" ] |) in + let _ := Constant.str " + Checks if an account exists in the state trie + + Parameters + ---------- + state: + The state + address: + Address of the account that needs to be checked. + + Returns + ------- + account_exists : `bool` + True if account exists in the state trie, False otherwise + " in + let _ := M.return_ (| + Compare.is_not (| + M.call (| + M.get_name (| globals, "get_account_optional" |), + make_list [ + M.get_name (| globals, "state" |); + M.get_name (| globals, "address" |) + ], + make_dict [] + |), + Constant.None_ + |) + |) in + M.pure Constant.None_)). + +Definition account_has_code_or_nonce : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "state"; "address" ] |) in + let _ := Constant.str " + Checks if an account has non zero nonce or non empty code + + Parameters + ---------- + state: + The state + address: + Address of the account that needs to be checked. + + Returns + ------- + has_code_or_nonce : `bool` + True if if an account has non zero nonce or non empty code, + False otherwise. + " in + let _ := M.assign_local (| + "account" , + M.call (| + M.get_name (| globals, "get_account" |), + make_list [ + M.get_name (| globals, "state" |); + M.get_name (| globals, "address" |) + ], + make_dict [] + |) + |) in + let _ := M.return_ (| + BoolOp.or (| + Compare.not_eq (| + M.get_field (| M.get_name (| globals, "account" |), "nonce" |), + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + |), + ltac:(M.monadic ( + Compare.not_eq (| + M.get_field (| M.get_name (| globals, "account" |), "code" |), + Constant.bytes "" + |) + )) + |) + |) in + M.pure Constant.None_)). + +Definition modify_state : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "state"; "address"; "f" ] |) in + let _ := Constant.str " + Modify an `Account` in the `State`. + " in + let _ := M.call (| + M.get_name (| globals, "set_account" |), + make_list [ + M.get_name (| globals, "state" |); + M.get_name (| globals, "address" |); + M.call (| + M.get_name (| globals, "modify" |), + make_list [ + M.call (| + M.get_name (| globals, "get_account" |), + make_list [ + M.get_name (| globals, "state" |); + M.get_name (| globals, "address" |) + ], + make_dict [] + |); + M.get_name (| globals, "f" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + M.pure Constant.None_)). + +Definition move_ether : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "state"; "sender_address"; "recipient_address"; "amount" ] |) in + let _ := Constant.str " + Move funds between accounts. + " in +(* At stmt: unsupported node type: FunctionDef *) +(* At stmt: unsupported node type: FunctionDef *) + let _ := M.call (| + M.get_name (| globals, "modify_state" |), + make_list [ + M.get_name (| globals, "state" |); + M.get_name (| globals, "sender_address" |); + M.get_name (| globals, "reduce_sender_balance" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "modify_state" |), + make_list [ + M.get_name (| globals, "state" |); + M.get_name (| globals, "recipient_address" |); + M.get_name (| globals, "increase_recipient_balance" |) + ], + make_dict [] + |) in + M.pure Constant.None_)). + +Definition set_account_balance : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "state"; "address"; "amount" ] |) in + let _ := Constant.str " + Sets the balance of an account. + + Parameters + ---------- + state: + The current state. + + address: + Address of the account whose nonce needs to be incremented. + + amount: + The amount that needs to set in balance. + " in +(* At stmt: unsupported node type: FunctionDef *) + let _ := M.call (| + M.get_name (| globals, "modify_state" |), + make_list [ + M.get_name (| globals, "state" |); + M.get_name (| globals, "address" |); + M.get_name (| globals, "set_balance" |) + ], + make_dict [] + |) in + M.pure Constant.None_)). + +Definition touch_account : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "state"; "address" ] |) in + let _ := Constant.str " + Initializes an account to state. + + Parameters + ---------- + state: + The current state. + + address: + The address of the account that need to initialised. + " in + let _ := + (* if *) + M.if_then_else (| + UnOp.not (| M.call (| + M.get_name (| globals, "account_exists" |), + make_list [ + M.get_name (| globals, "state" |); + M.get_name (| globals, "address" |) + ], + make_dict [] + |) |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, "set_account" |), + make_list [ + M.get_name (| globals, "state" |); + M.get_name (| globals, "address" |); + M.get_name (| globals, "EMPTY_ACCOUNT" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + M.pure Constant.None_)). + +Definition increment_nonce : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "state"; "address" ] |) in + let _ := Constant.str " + Increments the nonce of an account. + + Parameters + ---------- + state: + The current state. + + address: + Address of the account whose nonce needs to be incremented. + " in +(* At stmt: unsupported node type: FunctionDef *) + let _ := M.call (| + M.get_name (| globals, "modify_state" |), + make_list [ + M.get_name (| globals, "state" |); + M.get_name (| globals, "address" |); + M.get_name (| globals, "increase_nonce" |) + ], + make_dict [] + |) in + M.pure Constant.None_)). + +Definition set_code : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "state"; "address"; "code" ] |) in + let _ := Constant.str " + Sets Account code. + + Parameters + ---------- + state: + The current state. + + address: + Address of the account whose code needs to be update. + + code: + The bytecode that needs to be set. + " in +(* At stmt: unsupported node type: FunctionDef *) + let _ := M.call (| + M.get_name (| globals, "modify_state" |), + make_list [ + M.get_name (| globals, "state" |); + M.get_name (| globals, "address" |); + M.get_name (| globals, "write_code" |) + ], + make_dict [] + |) in + M.pure Constant.None_)). + +Definition create_ether : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "state"; "address"; "amount" ] |) in + let _ := Constant.str " + Add newly created ether to an account. + + Parameters + ---------- + state: + The current state. + address: + Address of the account to which ether is added. + amount: + The amount of ether to be added to the account of interest. + " in +(* At stmt: unsupported node type: FunctionDef *) + let _ := M.call (| + M.get_name (| globals, "modify_state" |), + make_list [ + M.get_name (| globals, "state" |); + M.get_name (| globals, "address" |); + M.get_name (| globals, "increase_balance" |) + ], + make_dict [] + |) in + M.pure Constant.None_)). diff --git a/CoqOfPython/ethereum/dao_fork/transactions.v b/CoqOfPython/ethereum/dao_fork/transactions.v new file mode 100644 index 0000000..c515aad --- /dev/null +++ b/CoqOfPython/ethereum/dao_fork/transactions.v @@ -0,0 +1,56 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.dao_fork.transactions". + +Definition expr_1 : Value.t := + Constant.str " +Transactions are atomic units of work created externally to Ethereum and +submitted to be executed. If Ethereum is viewed as a state machine, +transactions are the events that move between states. +". + +Axiom dataclasses_imports_dataclass : + IsImported globals "dataclasses" "dataclass". + +Axiom typing_imports_Union : + IsImported globals "typing" "Union". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_Bytes : + IsImported globals "ethereum.base_types" "Bytes". +Axiom ethereum_base_types_imports_Bytes0 : + IsImported globals "ethereum.base_types" "Bytes0". +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". +Axiom ethereum_base_types_imports_slotted_freezable : + IsImported globals "ethereum.base_types" "slotted_freezable". + +Axiom ethereum_dao_fork_fork_types_imports_Address : + IsImported globals "ethereum.dao_fork.fork_types" "Address". + +Definition TX_BASE_COST : Value.t := M.run ltac:(M.monadic ( + Constant.int 21000 +)). + +Definition TX_DATA_COST_PER_NON_ZERO : Value.t := M.run ltac:(M.monadic ( + Constant.int 68 +)). + +Definition TX_DATA_COST_PER_ZERO : Value.t := M.run ltac:(M.monadic ( + Constant.int 4 +)). + +Definition TX_CREATE_COST : Value.t := M.run ltac:(M.monadic ( + Constant.int 32000 +)). + +Definition Transaction : Value.t := + builtins.make_klass + [] + [ + + ] + [ + + ]. diff --git a/CoqOfPython/ethereum/dao_fork/trie.v b/CoqOfPython/ethereum/dao_fork/trie.v new file mode 100644 index 0000000..77ab51e --- /dev/null +++ b/CoqOfPython/ethereum/dao_fork/trie.v @@ -0,0 +1,1589 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.dao_fork.trie". + +Definition expr_1 : Value.t := + Constant.str " +State Trie +^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +The state trie is the structure responsible for storing +`.fork_types.Account` objects. +". + +(* At top_level_stmt: unsupported node type: Import *) + +Axiom dataclasses_imports_dataclass : + IsImported globals "dataclasses" "dataclass". +Axiom dataclasses_imports_field : + IsImported globals "dataclasses" "field". + +Axiom typing_imports_Callable : + IsImported globals "typing" "Callable". +Axiom typing_imports_Dict : + IsImported globals "typing" "Dict". +Axiom typing_imports_Generic : + IsImported globals "typing" "Generic". +Axiom typing_imports_List : + IsImported globals "typing" "List". +Axiom typing_imports_Mapping : + IsImported globals "typing" "Mapping". +Axiom typing_imports_MutableMapping : + IsImported globals "typing" "MutableMapping". +Axiom typing_imports_Optional : + IsImported globals "typing" "Optional". +Axiom typing_imports_Sequence : + IsImported globals "typing" "Sequence". +Axiom typing_imports_TypeVar : + IsImported globals "typing" "TypeVar". +Axiom typing_imports_Union : + IsImported globals "typing" "Union". +Axiom typing_imports_cast : + IsImported globals "typing" "cast". + +Axiom ethereum_crypto_hash_imports_keccak256 : + IsImported globals "ethereum.crypto.hash" "keccak256". + +Axiom ethereum_homestead_imports_trie : + IsImported globals "ethereum.homestead" "trie". + +Axiom ethereum_utils_ensure_imports_ensure : + IsImported globals "ethereum.utils.ensure" "ensure". + +Axiom ethereum_utils_hexadecimal_imports_hex_to_bytes : + IsImported globals "ethereum.utils.hexadecimal" "hex_to_bytes". + +Axiom ethereum_imports_rlp : + IsImported globals "ethereum" "rlp". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_Bytes : + IsImported globals "ethereum.base_types" "Bytes". +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". +Axiom ethereum_base_types_imports_slotted_freezable : + IsImported globals "ethereum.base_types" "slotted_freezable". + +Axiom ethereum_dao_fork_blocks_imports_Receipt : + IsImported globals "ethereum.dao_fork.blocks" "Receipt". + +Axiom ethereum_dao_fork_fork_types_imports_Account : + IsImported globals "ethereum.dao_fork.fork_types" "Account". +Axiom ethereum_dao_fork_fork_types_imports_Address : + IsImported globals "ethereum.dao_fork.fork_types" "Address". +Axiom ethereum_dao_fork_fork_types_imports_Root : + IsImported globals "ethereum.dao_fork.fork_types" "Root". +Axiom ethereum_dao_fork_fork_types_imports_encode_account : + IsImported globals "ethereum.dao_fork.fork_types" "encode_account". + +Axiom ethereum_dao_fork_transactions_imports_Transaction : + IsImported globals "ethereum.dao_fork.transactions" "Transaction". + +Definition EMPTY_TRIE_ROOT : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Root" |), + make_list [ + M.call (| + M.get_name (| globals, "hex_to_bytes" |), + make_list [ + Constant.str "56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421" + ], + make_dict [] + |) + ], + make_dict [] + |) +)). + +Definition Node : Value.t := M.run ltac:(M.monadic ( + M.get_subscript (| + M.get_name (| globals, "Union" |), + make_tuple [ M.get_name (| globals, "Account" |); M.get_name (| globals, "Bytes" |); M.get_name (| globals, "Transaction" |); M.get_name (| globals, "Receipt" |); M.get_name (| globals, "Uint" |); M.get_name (| globals, "U256" |); Constant.None_ ] + |) +)). + +Definition K : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "TypeVar" |), + make_list [ + Constant.str "K" + ], + make_dict [] + |) +)). + +Definition V : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "TypeVar" |), + make_list [ + Constant.str "V"; + M.get_subscript (| + M.get_name (| globals, "Optional" |), + M.get_name (| globals, "Account" |) + |); + M.get_subscript (| + M.get_name (| globals, "Optional" |), + M.get_name (| globals, "Bytes" |) + |); + M.get_name (| globals, "Bytes" |); + M.get_subscript (| + M.get_name (| globals, "Optional" |), + M.get_name (| globals, "Transaction" |) + |); + M.get_subscript (| + M.get_name (| globals, "Optional" |), + M.get_name (| globals, "Receipt" |) + |); + M.get_name (| globals, "Uint" |); + M.get_name (| globals, "U256" |) + ], + make_dict [] + |) +)). + +Definition LeafNode : Value.t := + builtins.make_klass + [] + [ + + ] + [ + + ]. + +Definition ExtensionNode : Value.t := + builtins.make_klass + [] + [ + + ] + [ + + ]. + +Definition BranchNode : Value.t := + builtins.make_klass + [] + [ + + ] + [ + + ]. + +Definition InternalNode : Value.t := M.run ltac:(M.monadic ( + M.get_subscript (| + M.get_name (| globals, "Union" |), + make_tuple [ M.get_name (| globals, "LeafNode" |); M.get_name (| globals, "ExtensionNode" |); M.get_name (| globals, "BranchNode" |) ] + |) +)). + +Definition encode_internal_node : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "node" ] |) in + let _ := Constant.str " + Encodes a Merkle Trie node into its RLP form. The RLP will then be + serialized into a `Bytes` and hashed unless it is less that 32 bytes + when serialized. + + This function also accepts `None`, representing the absence of a node, + which is encoded to `b""""`. + + Parameters + ---------- + node : Optional[InternalNode] + The node to encode. + + Returns + ------- + encoded : `rlp.RLP` + The node encoded as RLP. + " in +(* At stmt: unsupported node type: AnnAssign *) + let _ := + (* if *) + M.if_then_else (| + Compare.is (| + M.get_name (| globals, "node" |), + Constant.None_ + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "unencoded" , + Constant.bytes "" + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, "isinstance" |), + make_list [ + M.get_name (| globals, "node" |); + M.get_name (| globals, "LeafNode" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "unencoded" , + make_tuple [ M.call (| + M.get_name (| globals, "nibble_list_to_compact" |), + make_list [ + M.get_field (| M.get_name (| globals, "node" |), "rest_of_key" |); + Constant.bool true + ], + make_dict [] + |); M.get_field (| M.get_name (| globals, "node" |), "value" |) ] + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, "isinstance" |), + make_list [ + M.get_name (| globals, "node" |); + M.get_name (| globals, "ExtensionNode" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "unencoded" , + make_tuple [ M.call (| + M.get_name (| globals, "nibble_list_to_compact" |), + make_list [ + M.get_field (| M.get_name (| globals, "node" |), "key_segment" |); + Constant.bool false + ], + make_dict [] + |); M.get_field (| M.get_name (| globals, "node" |), "subnode" |) ] + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, "isinstance" |), + make_list [ + M.get_name (| globals, "node" |); + M.get_name (| globals, "BranchNode" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "unencoded" , + BinOp.add (| + M.get_field (| M.get_name (| globals, "node" |), "subnodes" |), + make_list [ + M.get_field (| M.get_name (| globals, "node" |), "value" |) + ] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.raise (| Some (M.call (| + M.get_name (| globals, "AssertionError" |), + make_list [ + Constant.str "(* At expr: unsupported node type: JoinedStr *)" + ], + make_dict [] + |)) |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "encoded" , + M.call (| + M.get_field (| M.get_name (| globals, "rlp" |), "encode" |), + make_list [ + M.get_name (| globals, "unencoded" |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.lt (| + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_name (| globals, "encoded" |) + ], + make_dict [] + |), + Constant.int 32 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + M.get_name (| globals, "unencoded" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.return_ (| + M.call (| + M.get_name (| globals, "keccak256" |), + make_list [ + M.get_name (| globals, "encoded" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_)). + +Definition encode_node : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "node"; "storage_root" ] |) in + let _ := Constant.str " + Encode a Node for storage in the Merkle Trie. + + Currently mostly an unimplemented stub. + " in + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, "isinstance" |), + make_list [ + M.get_name (| globals, "node" |); + M.get_name (| globals, "Account" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assert (| Compare.is_not (| + M.get_name (| globals, "storage_root" |), + Constant.None_ + |) |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, "encode_account" |), + make_list [ + M.get_name (| globals, "node" |); + M.get_name (| globals, "storage_root" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, "isinstance" |), + make_list [ + M.get_name (| globals, "node" |); + make_tuple [ M.get_name (| globals, "Transaction" |); M.get_name (| globals, "Receipt" |); M.get_name (| globals, "U256" |) ] + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + M.call (| + M.get_field (| M.get_name (| globals, "rlp" |), "encode" |), + make_list [ + M.call (| + M.get_name (| globals, "cast" |), + make_list [ + M.get_field (| M.get_name (| globals, "rlp" |), "RLP" |); + M.get_name (| globals, "node" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, "isinstance" |), + make_list [ + M.get_name (| globals, "node" |); + M.get_name (| globals, "Bytes" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + M.get_name (| globals, "node" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.return_ (| + M.call (| + M.get_field (| M.get_name (| globals, "previous_trie" |), "encode_node" |), + make_list [ + M.get_name (| globals, "node" |); + M.get_name (| globals, "storage_root" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_)). + +Definition Trie : Value.t := + builtins.make_klass + [(* At base: unsupported node type: Subscript *)] + [ + + ] + [ + + ]. + +Definition copy_trie : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "trie" ] |) in + let _ := Constant.str " + Create a copy of `trie`. Since only frozen objects may be stored in tries, + the contents are reused. + + Parameters + ---------- + trie: `Trie` + Trie to copy. + + Returns + ------- + new_trie : `Trie[K, V]` + A copy of the trie. + " in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, "Trie" |), + make_list [ + M.get_field (| M.get_name (| globals, "trie" |), "secured" |); + M.get_field (| M.get_name (| globals, "trie" |), "default" |); + M.call (| + M.get_field (| M.get_name (| globals, "copy" |), "copy" |), + make_list [ + M.get_field (| M.get_name (| globals, "trie" |), "_data" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Definition trie_set : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "trie"; "key"; "value" ] |) in + let _ := Constant.str " + Stores an item in a Merkle Trie. + + This method deletes the key if `value == trie.default`, because the Merkle + Trie represents the default value by omitting it from the trie. + + Parameters + ---------- + trie: `Trie` + Trie to store in. + key : `Bytes` + Key to lookup. + value : `V` + Node to insert at `key`. + " in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, "value" |), + M.get_field (| M.get_name (| globals, "trie" |), "default" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + Compare.in_ (| + M.get_name (| globals, "key" |), + M.get_field (| M.get_name (| globals, "trie" |), "_data" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.delete (| M.get_subscript (| + M.get_field (| M.get_name (| globals, "trie" |), "_data" |), + M.get_name (| globals, "key" |) + |) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign (| + M.get_subscript (| + M.get_field (| M.get_name (| globals, "trie" |), "_data" |), + M.get_name (| globals, "key" |) + |), + M.get_name (| globals, "value" |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_)). + +Definition trie_get : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "trie"; "key" ] |) in + let _ := Constant.str " + Gets an item from the Merkle Trie. + + This method returns `trie.default` if the key is missing. + + Parameters + ---------- + trie: + Trie to lookup in. + key : + Key to lookup. + + Returns + ------- + node : `V` + Node at `key` in the trie. + " in + let _ := M.return_ (| + M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, "trie" |), "_data" |), "get" |), + make_list [ + M.get_name (| globals, "key" |); + M.get_field (| M.get_name (| globals, "trie" |), "default" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Definition common_prefix_length : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "a"; "b" ] |) in + let _ := Constant.str " + Find the longest common prefix of two sequences. + " in + let _ := + M.for_ (| + M.get_name (| globals, "i" |), + M.call (| + M.get_name (| globals, "range" |), + make_list [ + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_name (| globals, "a" |) + ], + make_dict [] + |) + ], + make_dict [] + |), + ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + BoolOp.or (| + Compare.gt_e (| + M.get_name (| globals, "i" |), + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_name (| globals, "b" |) + ], + make_dict [] + |) + |), + ltac:(M.monadic ( + Compare.not_eq (| + M.get_subscript (| + M.get_name (| globals, "a" |), + M.get_name (| globals, "i" |) + |), + M.get_subscript (| + M.get_name (| globals, "b" |), + M.get_name (| globals, "i" |) + |) + |) + )) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + M.get_name (| globals, "i" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_name (| globals, "a" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Definition nibble_list_to_compact : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "x"; "is_leaf" ] |) in + let _ := Constant.str " + Compresses nibble-list into a standard byte array with a flag. + + A nibble-list is a list of byte values no greater than `15`. The flag is + encoded in high nibble of the highest byte. The flag nibble can be broken + down into two two-bit flags. + + Highest nibble:: + + +---+---+----------+--------+ + | _ | _ | is_leaf | parity | + +---+---+----------+--------+ + 3 2 1 0 + + + The lowest bit of the nibble encodes the parity of the length of the + remaining nibbles -- `0` when even and `1` when odd. The second lowest bit + is used to distinguish leaf and extension nodes. The other two bits are not + used. + + Parameters + ---------- + x : + Array of nibbles. + is_leaf : + True if this is part of a leaf node, or false if it is an extension + node. + + Returns + ------- + compressed : `bytearray` + Compact byte array. + " in + let _ := M.assign_local (| + "compact" , + M.call (| + M.get_name (| globals, "bytearray" |), + make_list [], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + BinOp.mod_ (| + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_name (| globals, "x" |) + ], + make_dict [] + |), + Constant.int 2 + |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_field (| M.get_name (| globals, "compact" |), "append" |), + make_list [ + BinOp.mult (| + Constant.int 16, + BinOp.mult (| + Constant.int 2, + M.get_name (| globals, "is_leaf" |) + |) + |) + ], + make_dict [] + |) in + let _ := + M.for_ (| + M.get_name (| globals, "i" |), + M.call (| + M.get_name (| globals, "range" |), + make_list [ + Constant.int 0; + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_name (| globals, "x" |) + ], + make_dict [] + |); + Constant.int 2 + ], + make_dict [] + |), + ltac:(M.monadic ( + let _ := M.call (| + M.get_field (| M.get_name (| globals, "compact" |), "append" |), + make_list [ + BinOp.add (| + BinOp.mult (| + Constant.int 16, + M.get_subscript (| + M.get_name (| globals, "x" |), + M.get_name (| globals, "i" |) + |) + |), + M.get_subscript (| + M.get_name (| globals, "x" |), + BinOp.add (| + M.get_name (| globals, "i" |), + Constant.int 1 + |) + |) + |) + ], + make_dict [] + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.call (| + M.get_field (| M.get_name (| globals, "compact" |), "append" |), + make_list [ + BinOp.add (| + BinOp.mult (| + Constant.int 16, + BinOp.add (| + BinOp.mult (| + Constant.int 2, + M.get_name (| globals, "is_leaf" |) + |), + Constant.int 1 + |) + |), + M.get_subscript (| + M.get_name (| globals, "x" |), + Constant.int 0 + |) + |) + ], + make_dict [] + |) in + let _ := + M.for_ (| + M.get_name (| globals, "i" |), + M.call (| + M.get_name (| globals, "range" |), + make_list [ + Constant.int 1; + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_name (| globals, "x" |) + ], + make_dict [] + |); + Constant.int 2 + ], + make_dict [] + |), + ltac:(M.monadic ( + let _ := M.call (| + M.get_field (| M.get_name (| globals, "compact" |), "append" |), + make_list [ + BinOp.add (| + BinOp.mult (| + Constant.int 16, + M.get_subscript (| + M.get_name (| globals, "x" |), + M.get_name (| globals, "i" |) + |) + |), + M.get_subscript (| + M.get_name (| globals, "x" |), + BinOp.add (| + M.get_name (| globals, "i" |), + Constant.int 1 + |) + |) + |) + ], + make_dict [] + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + M.pure Constant.None_ + )) |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, "Bytes" |), + make_list [ + M.get_name (| globals, "compact" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Definition bytes_to_nibble_list : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "bytes_" ] |) in + let _ := Constant.str " + Converts a `Bytes` into to a sequence of nibbles (bytes with value < 16). + + Parameters + ---------- + bytes_: + The `Bytes` to convert. + + Returns + ------- + nibble_list : `Bytes` + The `Bytes` in nibble-list format. + " in + let _ := M.assign_local (| + "nibble_list" , + M.call (| + M.get_name (| globals, "bytearray" |), + make_list [ + BinOp.mult (| + Constant.int 2, + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_name (| globals, "bytes_" |) + ], + make_dict [] + |) + |) + ], + make_dict [] + |) + |) in + let _ := + M.for_ (| + make_tuple [ M.get_name (| globals, "byte_index" |); M.get_name (| globals, "byte" |) ], + M.call (| + M.get_name (| globals, "enumerate" |), + make_list [ + M.get_name (| globals, "bytes_" |) + ], + make_dict [] + |), + ltac:(M.monadic ( + let _ := M.assign (| + M.get_subscript (| + M.get_name (| globals, "nibble_list" |), + BinOp.mult (| + M.get_name (| globals, "byte_index" |), + Constant.int 2 + |) + |), + BinOp.r_shift (| + BinOp.bit_and (| + M.get_name (| globals, "byte" |), + Constant.int 240 + |), + Constant.int 4 + |) + |) in + let _ := M.assign (| + M.get_subscript (| + M.get_name (| globals, "nibble_list" |), + BinOp.add (| + BinOp.mult (| + M.get_name (| globals, "byte_index" |), + Constant.int 2 + |), + Constant.int 1 + |) + |), + BinOp.bit_and (| + M.get_name (| globals, "byte" |), + Constant.int 15 + |) + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, "Bytes" |), + make_list [ + M.get_name (| globals, "nibble_list" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Definition _prepare_trie : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "trie"; "get_storage_root" ] |) in + let _ := Constant.str " + Prepares the trie for root calculation. Removes values that are empty, + hashes the keys (if `secured == True`) and encodes all the nodes. + + Parameters + ---------- + trie : + The `Trie` to prepare. + get_storage_root : + Function to get the storage root of an account. Needed to encode + `Account` objects. + + Returns + ------- + out : `Mapping[ethereum.base_types.Bytes, Node]` + Object with keys mapped to nibble-byte form. + " in +(* At stmt: unsupported node type: AnnAssign *) + let _ := + M.for_ (| + make_tuple [ M.get_name (| globals, "preimage" |); M.get_name (| globals, "value" |) ], + M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, "trie" |), "_data" |), "items" |), + make_list [], + make_dict [] + |), + ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, "isinstance" |), + make_list [ + M.get_name (| globals, "value" |); + M.get_name (| globals, "Account" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assert (| Compare.is_not (| + M.get_name (| globals, "get_storage_root" |), + Constant.None_ + |) |) in + let _ := M.assign_local (| + "address" , + M.call (| + M.get_name (| globals, "Address" |), + make_list [ + M.get_name (| globals, "preimage" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "encoded_value" , + M.call (| + M.get_name (| globals, "encode_node" |), + make_list [ + M.get_name (| globals, "value" |); + M.call (| + M.get_name (| globals, "get_storage_root" |), + make_list [ + M.get_name (| globals, "address" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "encoded_value" , + M.call (| + M.get_name (| globals, "encode_node" |), + make_list [ + M.get_name (| globals, "value" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + )) |) in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + Compare.not_eq (| + M.get_name (| globals, "encoded_value" |), + Constant.bytes "" + |); + M.get_name (| globals, "AssertionError" |) + ], + make_dict [] + |) in +(* At stmt: unsupported node type: AnnAssign *) + let _ := + (* if *) + M.if_then_else (| + M.get_field (| M.get_name (| globals, "trie" |), "secured" |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "key" , + M.call (| + M.get_name (| globals, "keccak256" |), + make_list [ + M.get_name (| globals, "preimage" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "key" , + M.get_name (| globals, "preimage" |) + |) in + M.pure Constant.None_ + )) |) in + let _ := M.assign (| + M.get_subscript (| + M.get_name (| globals, "mapped" |), + M.call (| + M.get_name (| globals, "bytes_to_nibble_list" |), + make_list [ + M.get_name (| globals, "key" |) + ], + make_dict [] + |) + |), + M.get_name (| globals, "encoded_value" |) + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := M.return_ (| + M.get_name (| globals, "mapped" |) + |) in + M.pure Constant.None_)). + +Definition root : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "trie"; "get_storage_root" ] |) in + let _ := Constant.str " + Computes the root of a modified merkle patricia trie (MPT). + + Parameters + ---------- + trie : + `Trie` to get the root of. + get_storage_root : + Function to get the storage root of an account. Needed to encode + `Account` objects. + + + Returns + ------- + root : `.fork_types.Root` + MPT root of the underlying key-value pairs. + " in + let _ := M.assign_local (| + "obj" , + M.call (| + M.get_name (| globals, "_prepare_trie" |), + make_list [ + M.get_name (| globals, "trie" |); + M.get_name (| globals, "get_storage_root" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "root_node" , + M.call (| + M.get_name (| globals, "encode_internal_node" |), + make_list [ + M.call (| + M.get_name (| globals, "patricialize" |), + make_list [ + M.get_name (| globals, "obj" |); + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.lt (| + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.call (| + M.get_field (| M.get_name (| globals, "rlp" |), "encode" |), + make_list [ + M.get_name (| globals, "root_node" |) + ], + make_dict [] + |) + ], + make_dict [] + |), + Constant.int 32 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + M.call (| + M.get_name (| globals, "keccak256" |), + make_list [ + M.call (| + M.get_field (| M.get_name (| globals, "rlp" |), "encode" |), + make_list [ + M.get_name (| globals, "root_node" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assert (| M.call (| + M.get_name (| globals, "isinstance" |), + make_list [ + M.get_name (| globals, "root_node" |); + M.get_name (| globals, "Bytes" |) + ], + make_dict [] + |) |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, "Root" |), + make_list [ + M.get_name (| globals, "root_node" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_)). + +Definition patricialize : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "obj"; "level" ] |) in + let _ := Constant.str " + Structural composition function. + + Used to recursively patricialize and merkleize a dictionary. Includes + memoization of the tree structure and hashes. + + Parameters + ---------- + obj : + Underlying trie key-value pairs, with keys in nibble-list format. + level : + Current trie level. + + Returns + ------- + node : `ethereum.base_types.Bytes` + Root node of `obj`. + " in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_name (| globals, "obj" |) + ], + make_dict [] + |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + Constant.None_ + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "arbitrary_key" , + M.call (| + M.get_name (| globals, "next" |), + make_list [ + M.call (| + M.get_name (| globals, "iter" |), + make_list [ + M.get_name (| globals, "obj" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_name (| globals, "obj" |) + ], + make_dict [] + |), + Constant.int 1 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "leaf" , + M.call (| + M.get_name (| globals, "LeafNode" |), + make_list [ + M.slice (| + M.get_name (| globals, "arbitrary_key" |), + M.get_name (| globals, "level" |), + Constant.None_, + Constant.None_ + |); + M.get_subscript (| + M.get_name (| globals, "obj" |), + M.get_name (| globals, "arbitrary_key" |) + |) + ], + make_dict [] + |) + |) in + let _ := M.return_ (| + M.get_name (| globals, "leaf" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "substring" , + M.slice (| + M.get_name (| globals, "arbitrary_key" |), + M.get_name (| globals, "level" |), + Constant.None_, + Constant.None_ + |) + |) in + let _ := M.assign_local (| + "prefix_length" , + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_name (| globals, "substring" |) + ], + make_dict [] + |) + |) in + let _ := + M.for_ (| + M.get_name (| globals, "key" |), + M.get_name (| globals, "obj" |), + ltac:(M.monadic ( + let _ := M.assign_local (| + "prefix_length" , + M.call (| + M.get_name (| globals, "min" |), + make_list [ + M.get_name (| globals, "prefix_length" |); + M.call (| + M.get_name (| globals, "common_prefix_length" |), + make_list [ + M.get_name (| globals, "substring" |); + M.slice (| + M.get_name (| globals, "key" |), + M.get_name (| globals, "level" |), + Constant.None_, + Constant.None_ + |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, "prefix_length" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.break (| |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.gt (| + M.get_name (| globals, "prefix_length" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "prefix" , + M.slice (| + M.get_name (| globals, "arbitrary_key" |), + M.get_name (| globals, "level" |), + BinOp.add (| + M.get_name (| globals, "level" |), + M.get_name (| globals, "prefix_length" |) + |), + Constant.None_ + |) + |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, "ExtensionNode" |), + make_list [ + M.get_name (| globals, "prefix" |); + M.call (| + M.get_name (| globals, "encode_internal_node" |), + make_list [ + M.call (| + M.get_name (| globals, "patricialize" |), + make_list [ + M.get_name (| globals, "obj" |); + BinOp.add (| + M.get_name (| globals, "level" |), + M.get_name (| globals, "prefix_length" |) + |) + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in +(* At stmt: unsupported node type: AnnAssign *) + let _ := + M.for_ (| + M.get_name (| globals, "_" |), + M.call (| + M.get_name (| globals, "range" |), + make_list [ + Constant.int 16 + ], + make_dict [] + |), + ltac:(M.monadic ( + let _ := M.call (| + M.get_field (| M.get_name (| globals, "branches" |), "append" |), + make_list [ + Constant.str "(* At expr: unsupported node type: Dict *)" + ], + make_dict [] + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := M.assign_local (| + "value" , + Constant.bytes "" + |) in + let _ := + M.for_ (| + M.get_name (| globals, "key" |), + M.get_name (| globals, "obj" |), + ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_name (| globals, "key" |) + ], + make_dict [] + |), + M.get_name (| globals, "level" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, "isinstance" |), + make_list [ + M.get_subscript (| + M.get_name (| globals, "obj" |), + M.get_name (| globals, "key" |) + |); + make_tuple [ M.get_name (| globals, "Account" |); M.get_name (| globals, "Receipt" |); M.get_name (| globals, "Uint" |) ] + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, "AssertionError" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "value" , + M.get_subscript (| + M.get_name (| globals, "obj" |), + M.get_name (| globals, "key" |) + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign (| + M.get_subscript (| + M.get_subscript (| + M.get_name (| globals, "branches" |), + M.get_subscript (| + M.get_name (| globals, "key" |), + M.get_name (| globals, "level" |) + |) + |), + M.get_name (| globals, "key" |) + |), + M.get_subscript (| + M.get_name (| globals, "obj" |), + M.get_name (| globals, "key" |) + |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, "BranchNode" |), + make_list [ + Constant.str "(* At expr: unsupported node type: ListComp *)"; + M.get_name (| globals, "value" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). diff --git a/CoqOfPython/ethereum/dao_fork/utils/__init__.v b/CoqOfPython/ethereum/dao_fork/utils/__init__.v new file mode 100644 index 0000000..dbf11fc --- /dev/null +++ b/CoqOfPython/ethereum/dao_fork/utils/__init__.v @@ -0,0 +1,8 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.dao_fork.utils.__init__". + +Definition expr_1 : Value.t := + Constant.str " +Utility functions unique to this particular fork. +". diff --git a/CoqOfPython/ethereum/dao_fork/utils/address.v b/CoqOfPython/ethereum/dao_fork/utils/address.v new file mode 100644 index 0000000..43700aa --- /dev/null +++ b/CoqOfPython/ethereum/dao_fork/utils/address.v @@ -0,0 +1,143 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.dao_fork.utils.address". + +Definition expr_1 : Value.t := + Constant.str " +Hardfork Utility Functions For Addresses +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Address specific functions used in this Dao Fork version of specification. +". + +Axiom typing_imports_Union : + IsImported globals "typing" "Union". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". + +Axiom ethereum_crypto_hash_imports_keccak256 : + IsImported globals "ethereum.crypto.hash" "keccak256". + +Axiom ethereum_utils_byte_imports_left_pad_zero_bytes : + IsImported globals "ethereum.utils.byte" "left_pad_zero_bytes". + +Axiom ethereum_imports_rlp : + IsImported globals "ethereum" "rlp". + +Axiom ethereum_dao_fork_fork_types_imports_Address : + IsImported globals "ethereum.dao_fork.fork_types" "Address". + +Definition to_address : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "data" ] |) in + let _ := Constant.str " + Convert a Uint or U256 value to a valid address (20 bytes). + + Parameters + ---------- + data : + The string to be converted to bytes. + + Returns + ------- + address : `Address` + The obtained address. + " in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, "Address" |), + make_list [ + M.slice (| + M.call (| + M.get_field (| M.get_name (| globals, "data" |), "to_be_bytes32" |), + make_list [], + make_dict [] + |), + UnOp.sub (| Constant.int 20 |), + Constant.None_, + Constant.None_ + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Definition compute_contract_address : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "address"; "nonce" ] |) in + let _ := Constant.str " + Computes address of the new account that needs to be created. + + Parameters + ---------- + address : + The address of the account that wants to create the new account. + nonce : + The transaction count of the account that wants to create the new + account. + + Returns + ------- + address: `ethereum.dao_fork.fork_types.Address` + The computed address of the new account. + " in + let _ := M.assign_local (| + "computed_address" , + M.call (| + M.get_name (| globals, "keccak256" |), + make_list [ + M.call (| + M.get_field (| M.get_name (| globals, "rlp" |), "encode" |), + make_list [ + make_list [ + M.get_name (| globals, "address" |); + M.get_name (| globals, "nonce" |) + ] + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "canonical_address" , + M.slice (| + M.get_name (| globals, "computed_address" |), + UnOp.sub (| Constant.int 20 |), + Constant.None_, + Constant.None_ + |) + |) in + let _ := M.assign_local (| + "padded_address" , + M.call (| + M.get_name (| globals, "left_pad_zero_bytes" |), + make_list [ + M.get_name (| globals, "canonical_address" |); + Constant.int 20 + ], + make_dict [] + |) + |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, "Address" |), + make_list [ + M.get_name (| globals, "padded_address" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). diff --git a/CoqOfPython/ethereum/dao_fork/utils/hexadecimal.v b/CoqOfPython/ethereum/dao_fork/utils/hexadecimal.v new file mode 100644 index 0000000..3f19f3d --- /dev/null +++ b/CoqOfPython/ethereum/dao_fork/utils/hexadecimal.v @@ -0,0 +1,153 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.dao_fork.utils.hexadecimal". + +Definition expr_1 : Value.t := + Constant.str " +Utility Functions For Hexadecimal Strings +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Hexadecimal utility functions used in this specification, specific to Dao Fork +types. +". + +Axiom ethereum_utils_hexadecimal_imports_remove_hex_prefix : + IsImported globals "ethereum.utils.hexadecimal" "remove_hex_prefix". + +Axiom ethereum_dao_fork_fork_types_imports_Address : + IsImported globals "ethereum.dao_fork.fork_types" "Address". +Axiom ethereum_dao_fork_fork_types_imports_Bloom : + IsImported globals "ethereum.dao_fork.fork_types" "Bloom". +Axiom ethereum_dao_fork_fork_types_imports_Root : + IsImported globals "ethereum.dao_fork.fork_types" "Root". + +Definition hex_to_root : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "hex_string" ] |) in + let _ := Constant.str " + Convert hex string to trie root. + + Parameters + ---------- + hex_string : + The hexadecimal string to be converted to trie root. + + Returns + ------- + root : `Root` + Trie root obtained from the given hexadecimal string. + " in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, "Root" |), + make_list [ + M.call (| + M.get_field (| M.get_name (| globals, "bytes" |), "fromhex" |), + make_list [ + M.call (| + M.get_name (| globals, "remove_hex_prefix" |), + make_list [ + M.get_name (| globals, "hex_string" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Definition hex_to_bloom : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "hex_string" ] |) in + let _ := Constant.str " + Convert hex string to bloom. + + Parameters + ---------- + hex_string : + The hexadecimal string to be converted to bloom. + + Returns + ------- + bloom : `Bloom` + Bloom obtained from the given hexadecimal string. + " in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, "Bloom" |), + make_list [ + M.call (| + M.get_field (| M.get_name (| globals, "bytes" |), "fromhex" |), + make_list [ + M.call (| + M.get_name (| globals, "remove_hex_prefix" |), + make_list [ + M.get_name (| globals, "hex_string" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Definition hex_to_address : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "hex_string" ] |) in + let _ := Constant.str " + Convert hex string to Address (20 bytes). + + Parameters + ---------- + hex_string : + The hexadecimal string to be converted to Address. + + Returns + ------- + address : `Address` + The address obtained from the given hexadecimal string. + " in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, "Address" |), + make_list [ + M.call (| + M.get_field (| M.get_name (| globals, "bytes" |), "fromhex" |), + make_list [ + M.call (| + M.get_field (| M.call (| + M.get_name (| globals, "remove_hex_prefix" |), + make_list [ + M.get_name (| globals, "hex_string" |) + ], + make_dict [] + |), "rjust" |), + make_list [ + Constant.int 40; + Constant.str "0" + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). diff --git a/CoqOfPython/ethereum/dao_fork/utils/message.v b/CoqOfPython/ethereum/dao_fork/utils/message.v new file mode 100644 index 0000000..9520a0a --- /dev/null +++ b/CoqOfPython/ethereum/dao_fork/utils/message.v @@ -0,0 +1,208 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.dao_fork.utils.message". + +Definition expr_1 : Value.t := + Constant.str " +Hardfork Utility Functions For The Message Data-structure +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Message specific functions used in this Dao Fork version of specification. +". + +Axiom typing_imports_Optional : + IsImported globals "typing" "Optional". +Axiom typing_imports_Union : + IsImported globals "typing" "Union". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_Bytes : + IsImported globals "ethereum.base_types" "Bytes". +Axiom ethereum_base_types_imports_Bytes0 : + IsImported globals "ethereum.base_types" "Bytes0". +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". + +Axiom ethereum_dao_fork_fork_types_imports_Address : + IsImported globals "ethereum.dao_fork.fork_types" "Address". + +Axiom ethereum_dao_fork_state_imports_get_account : + IsImported globals "ethereum.dao_fork.state" "get_account". + +Axiom ethereum_dao_fork_vm_imports_Environment : + IsImported globals "ethereum.dao_fork.vm" "Environment". +Axiom ethereum_dao_fork_vm_imports_Message : + IsImported globals "ethereum.dao_fork.vm" "Message". + +Axiom ethereum_dao_fork_utils_address_imports_compute_contract_address : + IsImported globals "ethereum.dao_fork.utils.address" "compute_contract_address". + +Definition prepare_message : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "caller"; "target"; "value"; "data"; "gas"; "env"; "code_address"; "should_transfer_value" ] |) in + let _ := Constant.str " + Execute a transaction against the provided environment. + + Parameters + ---------- + caller : + Address which initiated the transaction + target : + Address whose code will be executed + value : + Value to be transferred. + data : + Array of bytes provided to the code in `target`. + gas : + Gas provided for the code in `target`. + env : + Environment for the Ethereum Virtual Machine. + code_address : + This is usually same as the `target` address except when an alternative + accounts code needs to be executed. + eg. `CALLCODE` calling a precompile. + should_transfer_value : + if True ETH should be transferred while executing a message call. + + Returns + ------- + message: `ethereum.dao_fork.vm.Message` + Items containing contract creation or message call specific data. + " in + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, "isinstance" |), + make_list [ + M.get_name (| globals, "target" |); + M.get_name (| globals, "Bytes0" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "current_target" , + M.call (| + M.get_name (| globals, "compute_contract_address" |), + make_list [ + M.get_name (| globals, "caller" |); + BinOp.sub (| + M.get_field (| M.call (| + M.get_name (| globals, "get_account" |), + make_list [ + M.get_field (| M.get_name (| globals, "env" |), "state" |); + M.get_name (| globals, "caller" |) + ], + make_dict [] + |), "nonce" |), + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 1 + ], + make_dict [] + |) + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "msg_data" , + M.call (| + M.get_name (| globals, "Bytes" |), + make_list [ + Constant.bytes "" + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "code" , + M.get_name (| globals, "data" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, "isinstance" |), + make_list [ + M.get_name (| globals, "target" |); + M.get_name (| globals, "Address" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "current_target" , + M.get_name (| globals, "target" |) + |) in + let _ := M.assign_local (| + "msg_data" , + M.get_name (| globals, "data" |) + |) in + let _ := M.assign_local (| + "code" , + M.get_field (| M.call (| + M.get_name (| globals, "get_account" |), + make_list [ + M.get_field (| M.get_name (| globals, "env" |), "state" |); + M.get_name (| globals, "target" |) + ], + make_dict [] + |), "code" |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.is (| + M.get_name (| globals, "code_address" |), + Constant.None_ + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "code_address" , + M.get_name (| globals, "target" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.raise (| Some (M.call (| + M.get_name (| globals, "AssertionError" |), + make_list [ + Constant.str "Target must be address or empty bytes" + ], + make_dict [] + |)) |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )) |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, "Message" |), + make_list [], + make_dict [] + |) + |) in + M.pure Constant.None_)). diff --git a/CoqOfPython/ethereum/dao_fork/vm/__init__.v b/CoqOfPython/ethereum/dao_fork/vm/__init__.v new file mode 100644 index 0000000..7a3276a --- /dev/null +++ b/CoqOfPython/ethereum/dao_fork/vm/__init__.v @@ -0,0 +1,138 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.dao_fork.vm.__init__". + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +The abstract computer which runs the code stored in an +`.fork_types.Account`. +". + +Axiom dataclasses_imports_dataclass : + IsImported globals "dataclasses" "dataclass". + +Axiom typing_imports_List : + IsImported globals "typing" "List". +Axiom typing_imports_Optional : + IsImported globals "typing" "Optional". +Axiom typing_imports_Set : + IsImported globals "typing" "Set". +Axiom typing_imports_Tuple : + IsImported globals "typing" "Tuple". +Axiom typing_imports_Union : + IsImported globals "typing" "Union". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_Bytes : + IsImported globals "ethereum.base_types" "Bytes". +Axiom ethereum_base_types_imports_Bytes0 : + IsImported globals "ethereum.base_types" "Bytes0". +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". + +Axiom ethereum_crypto_hash_imports_Hash32 : + IsImported globals "ethereum.crypto.hash" "Hash32". + +Axiom ethereum_dao_fork_blocks_imports_Log : + IsImported globals "ethereum.dao_fork.blocks" "Log". + +Axiom ethereum_dao_fork_fork_types_imports_Address : + IsImported globals "ethereum.dao_fork.fork_types" "Address". + +Axiom ethereum_dao_fork_state_imports_State : + IsImported globals "ethereum.dao_fork.state" "State". + +Definition __all__ : Value.t := M.run ltac:(M.monadic ( + make_tuple [ Constant.str "Environment"; Constant.str "Evm"; Constant.str "Message" ] +)). + +Definition Environment : Value.t := + builtins.make_klass + [] + [ + + ] + [ + + ]. + +Definition Message : Value.t := + builtins.make_klass + [] + [ + + ] + [ + + ]. + +Definition Evm : Value.t := + builtins.make_klass + [] + [ + + ] + [ + + ]. + +Definition incorporate_child_on_success : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm"; "child_evm" ] |) in + let _ := Constant.str " + Incorporate the state of a successful `child_evm` into the parent `evm`. + + Parameters + ---------- + evm : + The parent `EVM`. + child_evm : + The child evm to incorporate. + " in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "gas_left" |), + M.get_field (| M.get_name (| globals, "child_evm" |), "gas_left" |) + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "logs" |), + M.get_field (| M.get_name (| globals, "child_evm" |), "logs" |) + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "refund_counter" |), + M.get_field (| M.get_name (| globals, "child_evm" |), "refund_counter" |) + |) in + M.pure Constant.None_)). + +Definition incorporate_child_on_error : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm"; "child_evm" ] |) in + let _ := Constant.str " + Incorporate the state of an unsuccessful `child_evm` into the parent `evm`. + + Parameters + ---------- + evm : + The parent `EVM`. + child_evm : + The child evm to incorporate. + " in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "gas_left" |), + M.get_field (| M.get_name (| globals, "child_evm" |), "gas_left" |) + |) in + M.pure Constant.None_)). diff --git a/CoqOfPython/ethereum/dao_fork/vm/exceptions.v b/CoqOfPython/ethereum/dao_fork/vm/exceptions.v new file mode 100644 index 0000000..193cc22 --- /dev/null +++ b/CoqOfPython/ethereum/dao_fork/vm/exceptions.v @@ -0,0 +1,121 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.dao_fork.vm.exceptions". + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) Exceptions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Exceptions which cause the EVM to halt exceptionally. +". + +Axiom ethereum_exceptions_imports_EthereumException : + IsImported globals "ethereum.exceptions" "EthereumException". + +Definition ExceptionalHalt : Value.t := + builtins.make_klass + [(globals, "EthereumException")] + [ + + ] + [ + + ]. + +Definition StackUnderflowError : Value.t := + builtins.make_klass + [(globals, "ExceptionalHalt")] + [ + + ] + [ + + ]. + +Definition StackOverflowError : Value.t := + builtins.make_klass + [(globals, "ExceptionalHalt")] + [ + + ] + [ + + ]. + +Definition OutOfGasError : Value.t := + builtins.make_klass + [(globals, "ExceptionalHalt")] + [ + + ] + [ + + ]. + +Definition InvalidOpcode : Value.t := + builtins.make_klass + [(globals, "ExceptionalHalt")] + [ + + ] + [ + ( + "__init__", + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "self"; "code" ] |) in + let _ := M.call (| + M.get_field (| M.call (| + M.get_name (| globals, "super" |), + make_list [], + make_dict [] + |), "__init__" |), + make_list [ + M.get_name (| globals, "code" |) + ], + make_dict [] + |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, "self" |), "code" |), + M.get_name (| globals, "code" |) + |) in + M.pure Constant.None_)) + ) + ]. + +Definition InvalidJumpDestError : Value.t := + builtins.make_klass + [(globals, "ExceptionalHalt")] + [ + + ] + [ + + ]. + +Definition StackDepthLimitError : Value.t := + builtins.make_klass + [(globals, "ExceptionalHalt")] + [ + + ] + [ + + ]. + +Definition AddressCollision : Value.t := + builtins.make_klass + [(globals, "ExceptionalHalt")] + [ + + ] + [ + + ]. diff --git a/CoqOfPython/ethereum/dao_fork/vm/gas.v b/CoqOfPython/ethereum/dao_fork/vm/gas.v new file mode 100644 index 0000000..7739073 --- /dev/null +++ b/CoqOfPython/ethereum/dao_fork/vm/gas.v @@ -0,0 +1,852 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.dao_fork.vm.gas". + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) Gas +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +EVM gas constants and calculators. +". + +Axiom dataclasses_imports_dataclass : + IsImported globals "dataclasses" "dataclass". + +Axiom typing_imports_List : + IsImported globals "typing" "List". +Axiom typing_imports_Tuple : + IsImported globals "typing" "Tuple". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". + +Axiom ethereum_trace_imports_GasAndRefund : + IsImported globals "ethereum.trace" "GasAndRefund". +Axiom ethereum_trace_imports_evm_trace : + IsImported globals "ethereum.trace" "evm_trace". + +Axiom ethereum_utils_numeric_imports_ceil32 : + IsImported globals "ethereum.utils.numeric" "ceil32". + +Axiom ethereum_dao_fork_fork_types_imports_Address : + IsImported globals "ethereum.dao_fork.fork_types" "Address". + +Axiom ethereum_dao_fork_state_imports_State : + IsImported globals "ethereum.dao_fork.state" "State". +Axiom ethereum_dao_fork_state_imports_account_exists : + IsImported globals "ethereum.dao_fork.state" "account_exists". + +Axiom ethereum_dao_fork_vm_imports_Evm : + IsImported globals "ethereum.dao_fork.vm" "Evm". + +Axiom ethereum_dao_fork_vm_exceptions_imports_OutOfGasError : + IsImported globals "ethereum.dao_fork.vm.exceptions" "OutOfGasError". + +Definition GAS_JUMPDEST : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 1 + ], + make_dict [] + |) +)). + +Definition GAS_BASE : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 2 + ], + make_dict [] + |) +)). + +Definition GAS_VERY_LOW : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 3 + ], + make_dict [] + |) +)). + +Definition GAS_SLOAD : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 50 + ], + make_dict [] + |) +)). + +Definition GAS_STORAGE_SET : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 20000 + ], + make_dict [] + |) +)). + +Definition GAS_STORAGE_UPDATE : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 5000 + ], + make_dict [] + |) +)). + +Definition GAS_STORAGE_CLEAR_REFUND : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 15000 + ], + make_dict [] + |) +)). + +Definition GAS_LOW : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 5 + ], + make_dict [] + |) +)). + +Definition GAS_MID : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 8 + ], + make_dict [] + |) +)). + +Definition GAS_HIGH : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 10 + ], + make_dict [] + |) +)). + +Definition GAS_EXPONENTIATION : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 10 + ], + make_dict [] + |) +)). + +Definition GAS_EXPONENTIATION_PER_BYTE : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 10 + ], + make_dict [] + |) +)). + +Definition GAS_MEMORY : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 3 + ], + make_dict [] + |) +)). + +Definition GAS_KECCAK256 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 30 + ], + make_dict [] + |) +)). + +Definition GAS_KECCAK256_WORD : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 6 + ], + make_dict [] + |) +)). + +Definition GAS_COPY : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 3 + ], + make_dict [] + |) +)). + +Definition GAS_BLOCK_HASH : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 20 + ], + make_dict [] + |) +)). + +Definition GAS_EXTERNAL : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 20 + ], + make_dict [] + |) +)). + +Definition GAS_BALANCE : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 20 + ], + make_dict [] + |) +)). + +Definition GAS_LOG : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 375 + ], + make_dict [] + |) +)). + +Definition GAS_LOG_DATA : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 8 + ], + make_dict [] + |) +)). + +Definition GAS_LOG_TOPIC : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 375 + ], + make_dict [] + |) +)). + +Definition GAS_CREATE : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 32000 + ], + make_dict [] + |) +)). + +Definition GAS_CODE_DEPOSIT : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 200 + ], + make_dict [] + |) +)). + +Definition GAS_ZERO : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) +)). + +Definition GAS_CALL : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 40 + ], + make_dict [] + |) +)). + +Definition GAS_NEW_ACCOUNT : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 25000 + ], + make_dict [] + |) +)). + +Definition GAS_CALL_VALUE : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 9000 + ], + make_dict [] + |) +)). + +Definition GAS_CALL_STIPEND : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 2300 + ], + make_dict [] + |) +)). + +Definition REFUND_SELF_DESTRUCT : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 24000 + ], + make_dict [] + |) +)). + +Definition GAS_ECRECOVER : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 3000 + ], + make_dict [] + |) +)). + +Definition GAS_SHA256 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 60 + ], + make_dict [] + |) +)). + +Definition GAS_SHA256_WORD : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 12 + ], + make_dict [] + |) +)). + +Definition GAS_RIPEMD160 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 600 + ], + make_dict [] + |) +)). + +Definition GAS_RIPEMD160_WORD : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 120 + ], + make_dict [] + |) +)). + +Definition GAS_IDENTITY : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 15 + ], + make_dict [] + |) +)). + +Definition GAS_IDENTITY_WORD : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 3 + ], + make_dict [] + |) +)). + +Definition ExtendMemory : Value.t := + builtins.make_klass + [] + [ + + ] + [ + + ]. + +Definition MessageCallGas : Value.t := + builtins.make_klass + [] + [ + + ] + [ + + ]. + +Definition charge_gas : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm"; "amount" ] |) in + let _ := Constant.str " + Subtracts `amount` from `evm.gas_left`. + + Parameters + ---------- + evm : + The current EVM. + amount : + The amount of gas the current operation requires. + + " in + let _ := M.call (| + M.get_name (| globals, "evm_trace" |), + make_list [ + M.get_name (| globals, "evm" |); + M.call (| + M.get_name (| globals, "GasAndRefund" |), + make_list [ + M.get_name (| globals, "amount" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.lt (| + M.get_field (| M.get_name (| globals, "evm" |), "gas_left" |), + M.get_name (| globals, "amount" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, "OutOfGasError" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_op (| + BinOp.sub, + M.get_field (| M.get_name (| globals, "evm" |), "gas_left" |), + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + M.get_name (| globals, "amount" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_)). + +Definition calculate_memory_gas_cost : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "size_in_bytes" ] |) in + let _ := Constant.str " + Calculates the gas cost for allocating memory + to the smallest multiple of 32 bytes, + such that the allocated size is at least as big as the given size. + + Parameters + ---------- + size_in_bytes : + The size of the data in bytes. + + Returns + ------- + total_gas_cost : `ethereum.base_types.Uint` + The gas cost for storing data in memory. + " in + let _ := M.assign_local (| + "size_in_words" , + BinOp.floor_div (| + M.call (| + M.get_name (| globals, "ceil32" |), + make_list [ + M.get_name (| globals, "size_in_bytes" |) + ], + make_dict [] + |), + Constant.int 32 + |) + |) in + let _ := M.assign_local (| + "linear_cost" , + BinOp.mult (| + M.get_name (| globals, "size_in_words" |), + M.get_name (| globals, "GAS_MEMORY" |) + |) + |) in + let _ := M.assign_local (| + "quadratic_cost" , + BinOp.floor_div (| + BinOp.pow (| + M.get_name (| globals, "size_in_words" |), + Constant.int 2 + |), + Constant.int 512 + |) + |) in + let _ := M.assign_local (| + "total_gas_cost" , + BinOp.add (| + M.get_name (| globals, "linear_cost" |), + M.get_name (| globals, "quadratic_cost" |) + |) + |) in +(* At stmt: unsupported node type: Try *) + M.pure Constant.None_)). + +Definition calculate_gas_extend_memory : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "memory"; "extensions" ] |) in + let _ := Constant.str " + Calculates the gas amount to extend memory + + Parameters + ---------- + memory : + Memory contents of the EVM. + extensions: + List of extensions to be made to the memory. + Consists of a tuple of start position and size. + + Returns + ------- + extend_memory: `ExtendMemory` + " in + let _ := M.assign_local (| + "size_to_extend" , + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "to_be_paid" , + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "current_size" , + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_name (| globals, "memory" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := + M.for_ (| + make_tuple [ M.get_name (| globals, "start_position" |); M.get_name (| globals, "size" |) ], + M.get_name (| globals, "extensions" |), + ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, "size" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.continue (| |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "before_size" , + M.call (| + M.get_name (| globals, "ceil32" |), + make_list [ + M.get_name (| globals, "current_size" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "after_size" , + M.call (| + M.get_name (| globals, "ceil32" |), + make_list [ + BinOp.add (| + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.get_name (| globals, "start_position" |) + ], + make_dict [] + |), + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.get_name (| globals, "size" |) + ], + make_dict [] + |) + |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.lt_e (| + M.get_name (| globals, "after_size" |), + M.get_name (| globals, "before_size" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.continue (| |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_op_local (| + BinOp.add, + "size_to_extend", + BinOp.sub (| + M.get_name (| globals, "after_size" |), + M.get_name (| globals, "before_size" |) + |) + |) in + let _ := M.assign_local (| + "already_paid" , + M.call (| + M.get_name (| globals, "calculate_memory_gas_cost" |), + make_list [ + M.get_name (| globals, "before_size" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "total_cost" , + M.call (| + M.get_name (| globals, "calculate_memory_gas_cost" |), + make_list [ + M.get_name (| globals, "after_size" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_op_local (| + BinOp.add, + "to_be_paid", + BinOp.sub (| + M.get_name (| globals, "total_cost" |), + M.get_name (| globals, "already_paid" |) + |) + |) in + let _ := M.assign_local (| + "current_size" , + M.get_name (| globals, "after_size" |) + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, "ExtendMemory" |), + make_list [ + M.get_name (| globals, "to_be_paid" |); + M.get_name (| globals, "size_to_extend" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Definition calculate_message_call_gas : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "state"; "gas"; "to"; "value" ] |) in + let _ := Constant.str " + Calculates the gas amount for executing Opcodes `CALL` and `CALLCODE`. + + Parameters + ---------- + state : + The current state. + gas : + The amount of gas provided to the message-call. + to: + The address of the recipient account. + value: + The amount of `ETH` that needs to be transferred. + + Returns + ------- + message_call_gas: `MessageCallGas` + " in + let _ := M.assign_local (| + "create_gas_cost" , + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, "account_exists" |), + make_list [ + M.get_name (| globals, "state" |); + M.get_name (| globals, "to" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( +M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + (* else *) + )), ltac:(M.monadic ( +M.get_name (| globals, "GAS_NEW_ACCOUNT" |) + )) |) + |) in + let _ := M.assign_local (| + "transfer_gas_cost" , + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, "value" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( +M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + (* else *) + )), ltac:(M.monadic ( +M.get_name (| globals, "GAS_CALL_VALUE" |) + )) |) + |) in + let _ := M.assign_local (| + "cost" , + BinOp.add (| + BinOp.add (| + BinOp.add (| + M.get_name (| globals, "GAS_CALL" |), + M.get_name (| globals, "gas" |) + |), + M.get_name (| globals, "create_gas_cost" |) + |), + M.get_name (| globals, "transfer_gas_cost" |) + |) + |) in + let _ := M.assign_local (| + "stipend" , + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, "value" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( +M.get_name (| globals, "gas" |) + (* else *) + )), ltac:(M.monadic ( +BinOp.add (| + M.get_name (| globals, "GAS_CALL_STIPEND" |), + M.get_name (| globals, "gas" |) + |) + )) |) + |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, "MessageCallGas" |), + make_list [ + M.get_name (| globals, "cost" |); + M.get_name (| globals, "stipend" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). diff --git a/CoqOfPython/ethereum/dao_fork/vm/instructions/__init__.v b/CoqOfPython/ethereum/dao_fork/vm/instructions/__init__.v new file mode 100644 index 0000000..ca3f554 --- /dev/null +++ b/CoqOfPython/ethereum/dao_fork/vm/instructions/__init__.v @@ -0,0 +1,74 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.dao_fork.vm.instructions.__init__". + +Definition expr_1 : Value.t := + Constant.str " +EVM Instruction Encoding (Opcodes) +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Machine readable representations of EVM instructions, and a mapping to their +implementations. +". + +(* At top_level_stmt: unsupported node type: Import *) + +Axiom typing_imports_Callable : + IsImported globals "typing" "Callable". +Axiom typing_imports_Dict : + IsImported globals "typing" "Dict". + +Axiom ethereum_dao_fork_vm_instructions_imports_arithmetic : + IsImported globals "ethereum.dao_fork.vm.instructions" "arithmetic". + +Axiom ethereum_dao_fork_vm_instructions_imports_bitwise : + IsImported globals "ethereum.dao_fork.vm.instructions" "bitwise". + +Axiom ethereum_dao_fork_vm_instructions_imports_block : + IsImported globals "ethereum.dao_fork.vm.instructions" "block". + +Axiom ethereum_dao_fork_vm_instructions_imports_comparison : + IsImported globals "ethereum.dao_fork.vm.instructions" "comparison". + +Axiom ethereum_dao_fork_vm_instructions_imports_control_flow : + IsImported globals "ethereum.dao_fork.vm.instructions" "control_flow". + +Axiom ethereum_dao_fork_vm_instructions_imports_environment : + IsImported globals "ethereum.dao_fork.vm.instructions" "environment". + +Axiom ethereum_dao_fork_vm_instructions_imports_keccak : + IsImported globals "ethereum.dao_fork.vm.instructions" "keccak". + +Axiom ethereum_dao_fork_vm_instructions_imports_log : + IsImported globals "ethereum.dao_fork.vm.instructions" "log". + +Axiom ethereum_dao_fork_vm_instructions_imports_memory : + IsImported globals "ethereum.dao_fork.vm.instructions" "memory". + +Axiom ethereum_dao_fork_vm_instructions_imports_stack : + IsImported globals "ethereum.dao_fork.vm.instructions" "stack". + +Axiom ethereum_dao_fork_vm_instructions_imports_storage : + IsImported globals "ethereum.dao_fork.vm.instructions" "storage". + +Axiom ethereum_dao_fork_vm_instructions_imports_system : + IsImported globals "ethereum.dao_fork.vm.instructions" "system". + +Definition Ops : Value.t := + builtins.make_klass + [(* At base: unsupported node type: Attribute *)] + [ + + ] + [ + + ]. + +(* At top_level_stmt: unsupported node type: AnnAssign *) diff --git a/CoqOfPython/ethereum/dao_fork/vm/instructions/arithmetic.v b/CoqOfPython/ethereum/dao_fork/vm/instructions/arithmetic.v new file mode 100644 index 0000000..c64126f --- /dev/null +++ b/CoqOfPython/ethereum/dao_fork/vm/instructions/arithmetic.v @@ -0,0 +1,1220 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.dao_fork.vm.instructions.arithmetic". + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) Arithmetic Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM Arithmetic instructions. +". + +Axiom ethereum_base_types_imports_U255_CEIL_VALUE : + IsImported globals "ethereum.base_types" "U255_CEIL_VALUE". +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_U256_CEIL_VALUE : + IsImported globals "ethereum.base_types" "U256_CEIL_VALUE". +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". + +Axiom ethereum_utils_numeric_imports_get_sign : + IsImported globals "ethereum.utils.numeric" "get_sign". + +Axiom ethereum_dao_fork_vm_imports_Evm : + IsImported globals "ethereum.dao_fork.vm" "Evm". + +Axiom ethereum_dao_fork_vm_gas_imports_GAS_EXPONENTIATION : + IsImported globals "ethereum.dao_fork.vm.gas" "GAS_EXPONENTIATION". +Axiom ethereum_dao_fork_vm_gas_imports_GAS_EXPONENTIATION_PER_BYTE : + IsImported globals "ethereum.dao_fork.vm.gas" "GAS_EXPONENTIATION_PER_BYTE". +Axiom ethereum_dao_fork_vm_gas_imports_GAS_LOW : + IsImported globals "ethereum.dao_fork.vm.gas" "GAS_LOW". +Axiom ethereum_dao_fork_vm_gas_imports_GAS_MID : + IsImported globals "ethereum.dao_fork.vm.gas" "GAS_MID". +Axiom ethereum_dao_fork_vm_gas_imports_GAS_VERY_LOW : + IsImported globals "ethereum.dao_fork.vm.gas" "GAS_VERY_LOW". +Axiom ethereum_dao_fork_vm_gas_imports_charge_gas : + IsImported globals "ethereum.dao_fork.vm.gas" "charge_gas". + +Axiom ethereum_dao_fork_vm_stack_imports_pop : + IsImported globals "ethereum.dao_fork.vm.stack" "pop". +Axiom ethereum_dao_fork_vm_stack_imports_push : + IsImported globals "ethereum.dao_fork.vm.stack" "push". + +Definition add : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Adds the top two elements of the stack together, and pushes the result back + on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "x" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "y" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_VERY_LOW" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "result" , + M.call (| + M.get_field (| M.get_name (| globals, "x" |), "wrapping_add" |), + make_list [ + M.get_name (| globals, "y" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.get_name (| globals, "result" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition sub : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Subtracts the top two elements of the stack, and pushes the result back + on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "x" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "y" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_VERY_LOW" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "result" , + M.call (| + M.get_field (| M.get_name (| globals, "x" |), "wrapping_sub" |), + make_list [ + M.get_name (| globals, "y" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.get_name (| globals, "result" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition mul : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Multiply the top two elements of the stack, and pushes the result back + on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "x" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "y" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_LOW" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "result" , + M.call (| + M.get_field (| M.get_name (| globals, "x" |), "wrapping_mul" |), + make_list [ + M.get_name (| globals, "y" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.get_name (| globals, "result" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition div : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Integer division of the top two elements of the stack. Pushes the result + back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "dividend" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "divisor" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_LOW" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, "divisor" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "quotient" , + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "quotient" , + BinOp.floor_div (| + M.get_name (| globals, "dividend" |), + M.get_name (| globals, "divisor" |) + |) + |) in + M.pure Constant.None_ + )) |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.get_name (| globals, "quotient" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition sdiv : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Signed integer division of the top two elements of the stack. Pushes the + result back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "dividend" , + M.call (| + M.get_field (| M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |), "to_signed" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "divisor" , + M.call (| + M.get_field (| M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |), "to_signed" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_LOW" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, "divisor" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "quotient" , + Constant.int 0 + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + BoolOp.and (| + Compare.eq (| + M.get_name (| globals, "dividend" |), + UnOp.sub (| M.get_name (| globals, "U255_CEIL_VALUE" |) |) + |), + ltac:(M.monadic ( + Compare.eq (| + M.get_name (| globals, "divisor" |), + UnOp.sub (| Constant.int 1 |) + |) + )) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "quotient" , + UnOp.sub (| M.get_name (| globals, "U255_CEIL_VALUE" |) |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "sign" , + M.call (| + M.get_name (| globals, "get_sign" |), + make_list [ + BinOp.mult (| + M.get_name (| globals, "dividend" |), + M.get_name (| globals, "divisor" |) + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "quotient" , + BinOp.mult (| + M.get_name (| globals, "sign" |), + BinOp.floor_div (| + M.call (| + M.get_name (| globals, "abs" |), + make_list [ + M.get_name (| globals, "dividend" |) + ], + make_dict [] + |), + M.call (| + M.get_name (| globals, "abs" |), + make_list [ + M.get_name (| globals, "divisor" |) + ], + make_dict [] + |) + |) + |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )) |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.call (| + M.get_field (| M.get_name (| globals, "U256" |), "from_signed" |), + make_list [ + M.get_name (| globals, "quotient" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition mod_ : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Modulo remainder of the top two elements of the stack. Pushes the result + back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "x" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "y" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_LOW" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, "y" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "remainder" , + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "remainder" , + BinOp.mod_ (| + M.get_name (| globals, "x" |), + M.get_name (| globals, "y" |) + |) + |) in + M.pure Constant.None_ + )) |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.get_name (| globals, "remainder" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition smod : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Signed modulo remainder of the top two elements of the stack. Pushes the + result back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "x" , + M.call (| + M.get_field (| M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |), "to_signed" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "y" , + M.call (| + M.get_field (| M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |), "to_signed" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_LOW" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, "y" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "remainder" , + Constant.int 0 + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "remainder" , + BinOp.mult (| + M.call (| + M.get_name (| globals, "get_sign" |), + make_list [ + M.get_name (| globals, "x" |) + ], + make_dict [] + |), + BinOp.mod_ (| + M.call (| + M.get_name (| globals, "abs" |), + make_list [ + M.get_name (| globals, "x" |) + ], + make_dict [] + |), + M.call (| + M.get_name (| globals, "abs" |), + make_list [ + M.get_name (| globals, "y" |) + ], + make_dict [] + |) + |) + |) + |) in + M.pure Constant.None_ + )) |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.call (| + M.get_field (| M.get_name (| globals, "U256" |), "from_signed" |), + make_list [ + M.get_name (| globals, "remainder" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition addmod : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Modulo addition of the top 2 elements with the 3rd element. Pushes the + result back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "x" , + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "y" , + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "z" , + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_MID" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, "z" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "result" , + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "result" , + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + BinOp.mod_ (| + BinOp.add (| + M.get_name (| globals, "x" |), + M.get_name (| globals, "y" |) + |), + M.get_name (| globals, "z" |) + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + )) |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.get_name (| globals, "result" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition mulmod : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Modulo multiplication of the top 2 elements with the 3rd element. Pushes + the result back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "x" , + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "y" , + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "z" , + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_MID" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, "z" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "result" , + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "result" , + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + BinOp.mod_ (| + BinOp.mult (| + M.get_name (| globals, "x" |), + M.get_name (| globals, "y" |) + |), + M.get_name (| globals, "z" |) + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + )) |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.get_name (| globals, "result" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition exp : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Exponential operation of the top 2 elements. Pushes the result back on + the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "base" , + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "exponent" , + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "exponent_bits" , + M.call (| + M.get_field (| M.get_name (| globals, "exponent" |), "bit_length" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "exponent_bytes" , + BinOp.floor_div (| + BinOp.add (| + M.get_name (| globals, "exponent_bits" |), + Constant.int 7 + |), + Constant.int 8 + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + BinOp.add (| + M.get_name (| globals, "GAS_EXPONENTIATION" |), + BinOp.mult (| + M.get_name (| globals, "GAS_EXPONENTIATION_PER_BYTE" |), + M.get_name (| globals, "exponent_bytes" |) + |) + |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "result" , + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + M.call (| + M.get_name (| globals, "pow" |), + make_list [ + M.get_name (| globals, "base" |); + M.get_name (| globals, "exponent" |); + M.get_name (| globals, "U256_CEIL_VALUE" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.get_name (| globals, "result" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition signextend : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Sign extend operation. In other words, extend a signed number which + fits in N bytes to 32 bytes. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "byte_num" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "value" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_LOW" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.gt (| + M.get_name (| globals, "byte_num" |), + Constant.int 31 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "result" , + M.get_name (| globals, "value" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "value_bytes" , + M.call (| + M.get_name (| globals, "bytes" |), + make_list [ + M.call (| + M.get_field (| M.get_name (| globals, "value" |), "to_be_bytes32" |), + make_list [], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "value_bytes" , + M.slice (| + M.get_name (| globals, "value_bytes" |), + BinOp.sub (| + Constant.int 31, + M.call (| + M.get_name (| globals, "int" |), + make_list [ + M.get_name (| globals, "byte_num" |) + ], + make_dict [] + |) + |), + Constant.None_, + Constant.None_ + |) + |) in + let _ := M.assign_local (| + "sign_bit" , + BinOp.r_shift (| + M.get_subscript (| + M.get_name (| globals, "value_bytes" |), + Constant.int 0 + |), + Constant.int 7 + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, "sign_bit" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "result" , + M.call (| + M.get_field (| M.get_name (| globals, "U256" |), "from_be_bytes" |), + make_list [ + M.get_name (| globals, "value_bytes" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "num_bytes_prepend" , + BinOp.sub (| + Constant.int 32, + BinOp.add (| + M.get_name (| globals, "byte_num" |), + Constant.int 1 + |) + |) + |) in + let _ := M.assign_local (| + "result" , + M.call (| + M.get_field (| M.get_name (| globals, "U256" |), "from_be_bytes" |), + make_list [ + BinOp.add (| + M.call (| + M.get_name (| globals, "bytearray" |), + make_list [ + BinOp.mult (| + make_list [ + Constant.int 255 + ], + M.get_name (| globals, "num_bytes_prepend" |) + |) + ], + make_dict [] + |), + M.get_name (| globals, "value_bytes" |) + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )) |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.get_name (| globals, "result" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). diff --git a/CoqOfPython/ethereum/dao_fork/vm/instructions/bitwise.v b/CoqOfPython/ethereum/dao_fork/vm/instructions/bitwise.v new file mode 100644 index 0000000..fccfa0d --- /dev/null +++ b/CoqOfPython/ethereum/dao_fork/vm/instructions/bitwise.v @@ -0,0 +1,372 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.dao_fork.vm.instructions.bitwise". + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) Bitwise Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM bitwise instructions. +". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". + +Axiom ethereum_dao_fork_vm_imports_Evm : + IsImported globals "ethereum.dao_fork.vm" "Evm". + +Axiom ethereum_dao_fork_vm_gas_imports_GAS_VERY_LOW : + IsImported globals "ethereum.dao_fork.vm.gas" "GAS_VERY_LOW". +Axiom ethereum_dao_fork_vm_gas_imports_charge_gas : + IsImported globals "ethereum.dao_fork.vm.gas" "charge_gas". + +Axiom ethereum_dao_fork_vm_stack_imports_pop : + IsImported globals "ethereum.dao_fork.vm.stack" "pop". +Axiom ethereum_dao_fork_vm_stack_imports_push : + IsImported globals "ethereum.dao_fork.vm.stack" "push". + +Definition bitwise_and : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Bitwise AND operation of the top 2 elements of the stack. Pushes the + result back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "x" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "y" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_VERY_LOW" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + BinOp.bit_and (| + M.get_name (| globals, "x" |), + M.get_name (| globals, "y" |) + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition bitwise_or : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Bitwise OR operation of the top 2 elements of the stack. Pushes the + result back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "x" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "y" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_VERY_LOW" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + BinOp.bit_or (| + M.get_name (| globals, "x" |), + M.get_name (| globals, "y" |) + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition bitwise_xor : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Bitwise XOR operation of the top 2 elements of the stack. Pushes the + result back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "x" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "y" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_VERY_LOW" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + BinOp.bit_xor (| + M.get_name (| globals, "x" |), + M.get_name (| globals, "y" |) + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition bitwise_not : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Bitwise NOT operation of the top element of the stack. Pushes the + result back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "x" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_VERY_LOW" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + UnOp.invert (| M.get_name (| globals, "x" |) |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition get_byte : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + For a word (defined by next top element of the stack), retrieve the + Nth byte (0-indexed and defined by top element of stack) from the + left (most significant) to right (least significant). + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "byte_index" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "word" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_VERY_LOW" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.gt_e (| + M.get_name (| globals, "byte_index" |), + Constant.int 32 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "result" , + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "extra_bytes_to_right" , + BinOp.sub (| + Constant.int 31, + M.get_name (| globals, "byte_index" |) + |) + |) in + let _ := M.assign_local (| + "word" , + BinOp.r_shift (| + M.get_name (| globals, "word" |), + BinOp.mult (| + M.get_name (| globals, "extra_bytes_to_right" |), + Constant.int 8 + |) + |) + |) in + let _ := M.assign_local (| + "word" , + BinOp.bit_and (| + M.get_name (| globals, "word" |), + Constant.int 255 + |) + |) in + let _ := M.assign_local (| + "result" , + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + M.get_name (| globals, "word" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + )) |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.get_name (| globals, "result" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). diff --git a/CoqOfPython/ethereum/dao_fork/vm/instructions/block.v b/CoqOfPython/ethereum/dao_fork/vm/instructions/block.v new file mode 100644 index 0000000..5a65267 --- /dev/null +++ b/CoqOfPython/ethereum/dao_fork/vm/instructions/block.v @@ -0,0 +1,348 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.dao_fork.vm.instructions.block". + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) Block Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM block instructions. +". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". + +Axiom ethereum_dao_fork_vm_imports_Evm : + IsImported globals "ethereum.dao_fork.vm" "Evm". + +Axiom ethereum_dao_fork_vm_gas_imports_GAS_BASE : + IsImported globals "ethereum.dao_fork.vm.gas" "GAS_BASE". +Axiom ethereum_dao_fork_vm_gas_imports_GAS_BLOCK_HASH : + IsImported globals "ethereum.dao_fork.vm.gas" "GAS_BLOCK_HASH". +Axiom ethereum_dao_fork_vm_gas_imports_charge_gas : + IsImported globals "ethereum.dao_fork.vm.gas" "charge_gas". + +Axiom ethereum_dao_fork_vm_stack_imports_pop : + IsImported globals "ethereum.dao_fork.vm.stack" "pop". +Axiom ethereum_dao_fork_vm_stack_imports_push : + IsImported globals "ethereum.dao_fork.vm.stack" "push". + +Definition block_hash : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Push the hash of one of the 256 most recent complete blocks onto the + stack. The block number to hash is present at the top of the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "block_number" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_BLOCK_HASH" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + BoolOp.or (| + Compare.lt_e (| + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "env" |), "number" |), + M.get_name (| globals, "block_number" |) + |), + ltac:(M.monadic ( + Compare.gt (| + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "env" |), "number" |), + BinOp.add (| + M.get_name (| globals, "block_number" |), + Constant.int 256 + |) + |) + )) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "hash" , + Constant.bytes "00" + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "hash" , + M.get_subscript (| + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "env" |), "block_hashes" |), + UnOp.sub (| BinOp.sub (| + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "env" |), "number" |), + M.get_name (| globals, "block_number" |) + |) |) + |) + |) in + M.pure Constant.None_ + )) |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.call (| + M.get_field (| M.get_name (| globals, "U256" |), "from_be_bytes" |), + make_list [ + M.get_name (| globals, "hash" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition coinbase : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Push the current block's beneficiary address (address of the block miner) + onto the stack. + + Here the current block refers to the block in which the currently + executing transaction/call resides. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_BASE" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.call (| + M.get_field (| M.get_name (| globals, "U256" |), "from_be_bytes" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "env" |), "coinbase" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition timestamp : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Push the current block's timestamp onto the stack. Here the timestamp + being referred is actually the unix timestamp in seconds. + + Here the current block refers to the block in which the currently + executing transaction/call resides. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_BASE" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "env" |), "time" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition number : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Push the current block's number onto the stack. + + Here the current block refers to the block in which the currently + executing transaction/call resides. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_BASE" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "env" |), "number" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition difficulty : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Push the current block's difficulty onto the stack. + + Here the current block refers to the block in which the currently + executing transaction/call resides. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_BASE" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "env" |), "difficulty" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition gas_limit : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Push the current block's gas limit onto the stack. + + Here the current block refers to the block in which the currently + executing transaction/call resides. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_BASE" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "env" |), "gas_limit" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). diff --git a/CoqOfPython/ethereum/dao_fork/vm/instructions/comparison.v b/CoqOfPython/ethereum/dao_fork/vm/instructions/comparison.v new file mode 100644 index 0000000..48940ed --- /dev/null +++ b/CoqOfPython/ethereum/dao_fork/vm/instructions/comparison.v @@ -0,0 +1,452 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.dao_fork.vm.instructions.comparison". + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) Comparison Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM Comparison instructions. +". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". + +Axiom ethereum_dao_fork_vm_imports_Evm : + IsImported globals "ethereum.dao_fork.vm" "Evm". + +Axiom ethereum_dao_fork_vm_gas_imports_GAS_VERY_LOW : + IsImported globals "ethereum.dao_fork.vm.gas" "GAS_VERY_LOW". +Axiom ethereum_dao_fork_vm_gas_imports_charge_gas : + IsImported globals "ethereum.dao_fork.vm.gas" "charge_gas". + +Axiom ethereum_dao_fork_vm_stack_imports_pop : + IsImported globals "ethereum.dao_fork.vm.stack" "pop". +Axiom ethereum_dao_fork_vm_stack_imports_push : + IsImported globals "ethereum.dao_fork.vm.stack" "push". + +Definition less_than : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Checks if the top element is less than the next top element. Pushes the + result back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "left" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "right" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_VERY_LOW" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "result" , + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Compare.lt (| + M.get_name (| globals, "left" |), + M.get_name (| globals, "right" |) + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.get_name (| globals, "result" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition signed_less_than : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Signed less-than comparison. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "left" , + M.call (| + M.get_field (| M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |), "to_signed" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "right" , + M.call (| + M.get_field (| M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |), "to_signed" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_VERY_LOW" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "result" , + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Compare.lt (| + M.get_name (| globals, "left" |), + M.get_name (| globals, "right" |) + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.get_name (| globals, "result" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition greater_than : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Checks if the top element is greater than the next top element. Pushes + the result back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "left" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "right" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_VERY_LOW" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "result" , + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Compare.gt (| + M.get_name (| globals, "left" |), + M.get_name (| globals, "right" |) + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.get_name (| globals, "result" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition signed_greater_than : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Signed greater-than comparison. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "left" , + M.call (| + M.get_field (| M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |), "to_signed" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "right" , + M.call (| + M.get_field (| M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |), "to_signed" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_VERY_LOW" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "result" , + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Compare.gt (| + M.get_name (| globals, "left" |), + M.get_name (| globals, "right" |) + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.get_name (| globals, "result" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition equal : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Checks if the top element is equal to the next top element. Pushes + the result back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "left" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "right" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_VERY_LOW" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "result" , + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Compare.eq (| + M.get_name (| globals, "left" |), + M.get_name (| globals, "right" |) + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.get_name (| globals, "result" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition is_zero : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Checks if the top element is equal to 0. Pushes the result back on the + stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "x" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_VERY_LOW" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "result" , + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Compare.eq (| + M.get_name (| globals, "x" |), + Constant.int 0 + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.get_name (| globals, "result" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). diff --git a/CoqOfPython/ethereum/dao_fork/vm/instructions/control_flow.v b/CoqOfPython/ethereum/dao_fork/vm/instructions/control_flow.v new file mode 100644 index 0000000..2242d7f --- /dev/null +++ b/CoqOfPython/ethereum/dao_fork/vm/instructions/control_flow.v @@ -0,0 +1,350 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.dao_fork.vm.instructions.control_flow". + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) Control Flow Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM control flow instructions. +". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". + +Axiom ethereum_dao_fork_vm_gas_imports_GAS_BASE : + IsImported globals "ethereum.dao_fork.vm.gas" "GAS_BASE". +Axiom ethereum_dao_fork_vm_gas_imports_GAS_HIGH : + IsImported globals "ethereum.dao_fork.vm.gas" "GAS_HIGH". +Axiom ethereum_dao_fork_vm_gas_imports_GAS_JUMPDEST : + IsImported globals "ethereum.dao_fork.vm.gas" "GAS_JUMPDEST". +Axiom ethereum_dao_fork_vm_gas_imports_GAS_MID : + IsImported globals "ethereum.dao_fork.vm.gas" "GAS_MID". +Axiom ethereum_dao_fork_vm_gas_imports_charge_gas : + IsImported globals "ethereum.dao_fork.vm.gas" "charge_gas". + +Axiom ethereum_dao_fork_vm_imports_Evm : + IsImported globals "ethereum.dao_fork.vm" "Evm". + +Axiom ethereum_dao_fork_vm_exceptions_imports_InvalidJumpDestError : + IsImported globals "ethereum.dao_fork.vm.exceptions" "InvalidJumpDestError". + +Axiom ethereum_dao_fork_vm_stack_imports_pop : + IsImported globals "ethereum.dao_fork.vm.stack" "pop". +Axiom ethereum_dao_fork_vm_stack_imports_push : + IsImported globals "ethereum.dao_fork.vm.stack" "push". + +Definition stop : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Stop further execution of EVM code. + + Parameters + ---------- + evm : + The current EVM frame. + " in + let _ := M.pass (| |) in + let _ := M.pass (| |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, "evm" |), "running" |), + Constant.bool false + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition jump : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Alter the program counter to the location specified by the top of the + stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "jump_dest" , + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_MID" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.not_in (| + M.get_name (| globals, "jump_dest" |), + M.get_field (| M.get_name (| globals, "evm" |), "valid_jump_destinations" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, "InvalidJumpDestError" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.get_name (| globals, "jump_dest" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Definition jumpi : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Alter the program counter to the specified location if and only if a + condition is true. If the condition is not true, then the program counter + would increase only by 1. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "jump_dest" , + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "conditional_value" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_HIGH" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, "conditional_value" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "destination" , + BinOp.add (| + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + Compare.not_in (| + M.get_name (| globals, "jump_dest" |), + M.get_field (| M.get_name (| globals, "evm" |), "valid_jump_destinations" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, "InvalidJumpDestError" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "destination" , + M.get_name (| globals, "jump_dest" |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )) |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.get_name (| globals, "destination" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Definition pc : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Push onto the stack the value of the program counter after reaching the + current instruction and without increasing it for the next instruction. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_BASE" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "pc" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition gas_left : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Push the amount of available gas (including the corresponding reduction + for the cost of this instruction) onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_BASE" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "gas_left" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition jumpdest : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Mark a valid destination for jumps. This is a noop, present only + to be used by `JUMP` and `JUMPI` opcodes to verify that their jump is + valid. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_JUMPDEST" |) + ], + make_dict [] + |) in + let _ := M.pass (| |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). diff --git a/CoqOfPython/ethereum/dao_fork/vm/instructions/environment.v b/CoqOfPython/ethereum/dao_fork/vm/instructions/environment.v new file mode 100644 index 0000000..42b1678 --- /dev/null +++ b/CoqOfPython/ethereum/dao_fork/vm/instructions/environment.v @@ -0,0 +1,993 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.dao_fork.vm.instructions.environment". + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) Environmental Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM environment related instructions. +". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". + +Axiom ethereum_utils_numeric_imports_ceil32 : + IsImported globals "ethereum.utils.numeric" "ceil32". + +Axiom ethereum_dao_fork_state_imports_get_account : + IsImported globals "ethereum.dao_fork.state" "get_account". + +Axiom ethereum_dao_fork_utils_address_imports_to_address : + IsImported globals "ethereum.dao_fork.utils.address" "to_address". + +Axiom ethereum_dao_fork_vm_memory_imports_buffer_read : + IsImported globals "ethereum.dao_fork.vm.memory" "buffer_read". +Axiom ethereum_dao_fork_vm_memory_imports_memory_write : + IsImported globals "ethereum.dao_fork.vm.memory" "memory_write". + +Axiom ethereum_dao_fork_vm_imports_Evm : + IsImported globals "ethereum.dao_fork.vm" "Evm". + +Axiom ethereum_dao_fork_vm_gas_imports_GAS_BALANCE : + IsImported globals "ethereum.dao_fork.vm.gas" "GAS_BALANCE". +Axiom ethereum_dao_fork_vm_gas_imports_GAS_BASE : + IsImported globals "ethereum.dao_fork.vm.gas" "GAS_BASE". +Axiom ethereum_dao_fork_vm_gas_imports_GAS_COPY : + IsImported globals "ethereum.dao_fork.vm.gas" "GAS_COPY". +Axiom ethereum_dao_fork_vm_gas_imports_GAS_EXTERNAL : + IsImported globals "ethereum.dao_fork.vm.gas" "GAS_EXTERNAL". +Axiom ethereum_dao_fork_vm_gas_imports_GAS_VERY_LOW : + IsImported globals "ethereum.dao_fork.vm.gas" "GAS_VERY_LOW". +Axiom ethereum_dao_fork_vm_gas_imports_calculate_gas_extend_memory : + IsImported globals "ethereum.dao_fork.vm.gas" "calculate_gas_extend_memory". +Axiom ethereum_dao_fork_vm_gas_imports_charge_gas : + IsImported globals "ethereum.dao_fork.vm.gas" "charge_gas". + +Axiom ethereum_dao_fork_vm_stack_imports_pop : + IsImported globals "ethereum.dao_fork.vm.stack" "pop". +Axiom ethereum_dao_fork_vm_stack_imports_push : + IsImported globals "ethereum.dao_fork.vm.stack" "push". + +Definition address : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Pushes the address of the current executing account to the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_BASE" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.call (| + M.get_field (| M.get_name (| globals, "U256" |), "from_be_bytes" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "current_target" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition balance : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Pushes the balance of the given account onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "address" , + M.call (| + M.get_name (| globals, "to_address" |), + make_list [ + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_BALANCE" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "balance" , + M.get_field (| M.call (| + M.get_name (| globals, "get_account" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "env" |), "state" |); + M.get_name (| globals, "address" |) + ], + make_dict [] + |), "balance" |) + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.get_name (| globals, "balance" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition origin : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Pushes the address of the original transaction sender to the stack. + The origin address can only be an EOA. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_BASE" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.call (| + M.get_field (| M.get_name (| globals, "U256" |), "from_be_bytes" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "env" |), "origin" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition caller : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Pushes the address of the caller onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_BASE" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.call (| + M.get_field (| M.get_name (| globals, "U256" |), "from_be_bytes" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "caller" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition callvalue : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Push the value (in wei) sent with the call onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_BASE" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "value" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition calldataload : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Push a word (32 bytes) of the input data belonging to the current + environment onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "start_index" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_VERY_LOW" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "value" , + M.call (| + M.get_name (| globals, "buffer_read" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "data" |); + M.get_name (| globals, "start_index" |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 32 + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.call (| + M.get_field (| M.get_name (| globals, "U256" |), "from_be_bytes" |), + make_list [ + M.get_name (| globals, "value" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition calldatasize : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Push the size of input data in current environment onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_BASE" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "data" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition calldatacopy : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Copy a portion of the input data in current environment to memory. + + This will also expand the memory, in case that the memory is insufficient + to store the data. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "memory_start_index" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "data_start_index" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "size" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "words" , + BinOp.floor_div (| + M.call (| + M.get_name (| globals, "ceil32" |), + make_list [ + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.get_name (| globals, "size" |) + ], + make_dict [] + |) + ], + make_dict [] + |), + Constant.int 32 + |) + |) in + let _ := M.assign_local (| + "copy_gas_cost" , + BinOp.mult (| + M.get_name (| globals, "GAS_COPY" |), + M.get_name (| globals, "words" |) + |) + |) in + let _ := M.assign_local (| + "extend_memory" , + M.call (| + M.get_name (| globals, "calculate_gas_extend_memory" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "memory" |); + make_list [ + make_tuple [ M.get_name (| globals, "memory_start_index" |); M.get_name (| globals, "size" |) ] + ] + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + BinOp.add (| + BinOp.add (| + M.get_name (| globals, "GAS_VERY_LOW" |), + M.get_name (| globals, "copy_gas_cost" |) + |), + M.get_field (| M.get_name (| globals, "extend_memory" |), "cost" |) + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "memory" |), + BinOp.mult (| + Constant.bytes "00", + M.get_field (| M.get_name (| globals, "extend_memory" |), "expand_by" |) + |) + |) in + let _ := M.assign_local (| + "value" , + M.call (| + M.get_name (| globals, "buffer_read" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "data" |); + M.get_name (| globals, "data_start_index" |); + M.get_name (| globals, "size" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "memory_write" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "memory" |); + M.get_name (| globals, "memory_start_index" |); + M.get_name (| globals, "value" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition codesize : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Push the size of code running in current environment onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_BASE" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "code" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition codecopy : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Copy a portion of the code in current environment to memory. + + This will also expand the memory, in case that the memory is insufficient + to store the data. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "memory_start_index" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "code_start_index" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "size" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "words" , + BinOp.floor_div (| + M.call (| + M.get_name (| globals, "ceil32" |), + make_list [ + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.get_name (| globals, "size" |) + ], + make_dict [] + |) + ], + make_dict [] + |), + Constant.int 32 + |) + |) in + let _ := M.assign_local (| + "copy_gas_cost" , + BinOp.mult (| + M.get_name (| globals, "GAS_COPY" |), + M.get_name (| globals, "words" |) + |) + |) in + let _ := M.assign_local (| + "extend_memory" , + M.call (| + M.get_name (| globals, "calculate_gas_extend_memory" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "memory" |); + make_list [ + make_tuple [ M.get_name (| globals, "memory_start_index" |); M.get_name (| globals, "size" |) ] + ] + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + BinOp.add (| + BinOp.add (| + M.get_name (| globals, "GAS_VERY_LOW" |), + M.get_name (| globals, "copy_gas_cost" |) + |), + M.get_field (| M.get_name (| globals, "extend_memory" |), "cost" |) + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "memory" |), + BinOp.mult (| + Constant.bytes "00", + M.get_field (| M.get_name (| globals, "extend_memory" |), "expand_by" |) + |) + |) in + let _ := M.assign_local (| + "value" , + M.call (| + M.get_name (| globals, "buffer_read" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "code" |); + M.get_name (| globals, "code_start_index" |); + M.get_name (| globals, "size" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "memory_write" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "memory" |); + M.get_name (| globals, "memory_start_index" |); + M.get_name (| globals, "value" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition gasprice : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Push the gas price used in current environment onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_BASE" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "env" |), "gas_price" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition extcodesize : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Push the code size of a given account onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "address" , + M.call (| + M.get_name (| globals, "to_address" |), + make_list [ + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_EXTERNAL" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "codesize" , + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_field (| M.call (| + M.get_name (| globals, "get_account" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "env" |), "state" |); + M.get_name (| globals, "address" |) + ], + make_dict [] + |), "code" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.get_name (| globals, "codesize" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition extcodecopy : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Copy a portion of an account's code to memory. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "address" , + M.call (| + M.get_name (| globals, "to_address" |), + make_list [ + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_start_index" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "code_start_index" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "size" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "words" , + BinOp.floor_div (| + M.call (| + M.get_name (| globals, "ceil32" |), + make_list [ + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.get_name (| globals, "size" |) + ], + make_dict [] + |) + ], + make_dict [] + |), + Constant.int 32 + |) + |) in + let _ := M.assign_local (| + "copy_gas_cost" , + BinOp.mult (| + M.get_name (| globals, "GAS_COPY" |), + M.get_name (| globals, "words" |) + |) + |) in + let _ := M.assign_local (| + "extend_memory" , + M.call (| + M.get_name (| globals, "calculate_gas_extend_memory" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "memory" |); + make_list [ + make_tuple [ M.get_name (| globals, "memory_start_index" |); M.get_name (| globals, "size" |) ] + ] + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + BinOp.add (| + BinOp.add (| + M.get_name (| globals, "GAS_EXTERNAL" |), + M.get_name (| globals, "copy_gas_cost" |) + |), + M.get_field (| M.get_name (| globals, "extend_memory" |), "cost" |) + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "memory" |), + BinOp.mult (| + Constant.bytes "00", + M.get_field (| M.get_name (| globals, "extend_memory" |), "expand_by" |) + |) + |) in + let _ := M.assign_local (| + "code" , + M.get_field (| M.call (| + M.get_name (| globals, "get_account" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "env" |), "state" |); + M.get_name (| globals, "address" |) + ], + make_dict [] + |), "code" |) + |) in + let _ := M.assign_local (| + "value" , + M.call (| + M.get_name (| globals, "buffer_read" |), + make_list [ + M.get_name (| globals, "code" |); + M.get_name (| globals, "code_start_index" |); + M.get_name (| globals, "size" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "memory_write" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "memory" |); + M.get_name (| globals, "memory_start_index" |); + M.get_name (| globals, "value" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). diff --git a/CoqOfPython/ethereum/dao_fork/vm/instructions/keccak.v b/CoqOfPython/ethereum/dao_fork/vm/instructions/keccak.v new file mode 100644 index 0000000..3205868 --- /dev/null +++ b/CoqOfPython/ethereum/dao_fork/vm/instructions/keccak.v @@ -0,0 +1,188 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.dao_fork.vm.instructions.keccak". + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) Keccak Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM keccak instructions. +". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". + +Axiom ethereum_crypto_hash_imports_keccak256 : + IsImported globals "ethereum.crypto.hash" "keccak256". + +Axiom ethereum_utils_numeric_imports_ceil32 : + IsImported globals "ethereum.utils.numeric" "ceil32". + +Axiom ethereum_dao_fork_vm_imports_Evm : + IsImported globals "ethereum.dao_fork.vm" "Evm". + +Axiom ethereum_dao_fork_vm_gas_imports_GAS_KECCAK256 : + IsImported globals "ethereum.dao_fork.vm.gas" "GAS_KECCAK256". +Axiom ethereum_dao_fork_vm_gas_imports_GAS_KECCAK256_WORD : + IsImported globals "ethereum.dao_fork.vm.gas" "GAS_KECCAK256_WORD". +Axiom ethereum_dao_fork_vm_gas_imports_calculate_gas_extend_memory : + IsImported globals "ethereum.dao_fork.vm.gas" "calculate_gas_extend_memory". +Axiom ethereum_dao_fork_vm_gas_imports_charge_gas : + IsImported globals "ethereum.dao_fork.vm.gas" "charge_gas". + +Axiom ethereum_dao_fork_vm_memory_imports_memory_read_bytes : + IsImported globals "ethereum.dao_fork.vm.memory" "memory_read_bytes". + +Axiom ethereum_dao_fork_vm_stack_imports_pop : + IsImported globals "ethereum.dao_fork.vm.stack" "pop". +Axiom ethereum_dao_fork_vm_stack_imports_push : + IsImported globals "ethereum.dao_fork.vm.stack" "push". + +Definition keccak : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Pushes to the stack the Keccak-256 hash of a region of memory. + + This also expands the memory, in case the memory is insufficient to + access the data's memory location. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "memory_start_index" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "size" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "words" , + BinOp.floor_div (| + M.call (| + M.get_name (| globals, "ceil32" |), + make_list [ + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.get_name (| globals, "size" |) + ], + make_dict [] + |) + ], + make_dict [] + |), + Constant.int 32 + |) + |) in + let _ := M.assign_local (| + "word_gas_cost" , + BinOp.mult (| + M.get_name (| globals, "GAS_KECCAK256_WORD" |), + M.get_name (| globals, "words" |) + |) + |) in + let _ := M.assign_local (| + "extend_memory" , + M.call (| + M.get_name (| globals, "calculate_gas_extend_memory" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "memory" |); + make_list [ + make_tuple [ M.get_name (| globals, "memory_start_index" |); M.get_name (| globals, "size" |) ] + ] + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + BinOp.add (| + BinOp.add (| + M.get_name (| globals, "GAS_KECCAK256" |), + M.get_name (| globals, "word_gas_cost" |) + |), + M.get_field (| M.get_name (| globals, "extend_memory" |), "cost" |) + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "memory" |), + BinOp.mult (| + Constant.bytes "00", + M.get_field (| M.get_name (| globals, "extend_memory" |), "expand_by" |) + |) + |) in + let _ := M.assign_local (| + "data" , + M.call (| + M.get_name (| globals, "memory_read_bytes" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "memory" |); + M.get_name (| globals, "memory_start_index" |); + M.get_name (| globals, "size" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "hash" , + M.call (| + M.get_name (| globals, "keccak256" |), + make_list [ + M.get_name (| globals, "data" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.call (| + M.get_field (| M.get_name (| globals, "U256" |), "from_be_bytes" |), + make_list [ + M.get_name (| globals, "hash" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). diff --git a/CoqOfPython/ethereum/dao_fork/vm/instructions/log.v b/CoqOfPython/ethereum/dao_fork/vm/instructions/log.v new file mode 100644 index 0000000..47d5c73 --- /dev/null +++ b/CoqOfPython/ethereum/dao_fork/vm/instructions/log.v @@ -0,0 +1,242 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.dao_fork.vm.instructions.log". + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) Logging Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM logging instructions. +". + +Axiom functools_imports_partial : + IsImported globals "functools" "partial". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". + +Axiom ethereum_dao_fork_blocks_imports_Log : + IsImported globals "ethereum.dao_fork.blocks" "Log". + +Axiom ethereum_dao_fork_vm_imports_Evm : + IsImported globals "ethereum.dao_fork.vm" "Evm". + +Axiom ethereum_dao_fork_vm_gas_imports_GAS_LOG : + IsImported globals "ethereum.dao_fork.vm.gas" "GAS_LOG". +Axiom ethereum_dao_fork_vm_gas_imports_GAS_LOG_DATA : + IsImported globals "ethereum.dao_fork.vm.gas" "GAS_LOG_DATA". +Axiom ethereum_dao_fork_vm_gas_imports_GAS_LOG_TOPIC : + IsImported globals "ethereum.dao_fork.vm.gas" "GAS_LOG_TOPIC". +Axiom ethereum_dao_fork_vm_gas_imports_calculate_gas_extend_memory : + IsImported globals "ethereum.dao_fork.vm.gas" "calculate_gas_extend_memory". +Axiom ethereum_dao_fork_vm_gas_imports_charge_gas : + IsImported globals "ethereum.dao_fork.vm.gas" "charge_gas". + +Axiom ethereum_dao_fork_vm_memory_imports_memory_read_bytes : + IsImported globals "ethereum.dao_fork.vm.memory" "memory_read_bytes". + +Axiom ethereum_dao_fork_vm_stack_imports_pop : + IsImported globals "ethereum.dao_fork.vm.stack" "pop". + +Definition log_n : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm"; "num_topics" ] |) in + let _ := Constant.str " + Appends a log entry, having `num_topics` topics, to the evm logs. + + This will also expand the memory if the data (required by the log entry) + corresponding to the memory is not accessible. + + Parameters + ---------- + evm : + The current EVM frame. + num_topics : + The number of topics to be included in the log entry. + + " in + let _ := M.assign_local (| + "memory_start_index" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "size" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "topics" , + make_list [] + |) in + let _ := + M.for_ (| + M.get_name (| globals, "_" |), + M.call (| + M.get_name (| globals, "range" |), + make_list [ + M.get_name (| globals, "num_topics" |) + ], + make_dict [] + |), + ltac:(M.monadic ( + let _ := M.assign_local (| + "topic" , + M.call (| + M.get_field (| M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |), "to_be_bytes32" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_field (| M.get_name (| globals, "topics" |), "append" |), + make_list [ + M.get_name (| globals, "topic" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := M.assign_local (| + "extend_memory" , + M.call (| + M.get_name (| globals, "calculate_gas_extend_memory" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "memory" |); + make_list [ + make_tuple [ M.get_name (| globals, "memory_start_index" |); M.get_name (| globals, "size" |) ] + ] + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + BinOp.add (| + BinOp.add (| + BinOp.add (| + M.get_name (| globals, "GAS_LOG" |), + BinOp.mult (| + M.get_name (| globals, "GAS_LOG_DATA" |), + M.get_name (| globals, "size" |) + |) + |), + BinOp.mult (| + M.get_name (| globals, "GAS_LOG_TOPIC" |), + M.get_name (| globals, "num_topics" |) + |) + |), + M.get_field (| M.get_name (| globals, "extend_memory" |), "cost" |) + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "memory" |), + BinOp.mult (| + Constant.bytes "00", + M.get_field (| M.get_name (| globals, "extend_memory" |), "expand_by" |) + |) + |) in + let _ := M.assign_local (| + "log_entry" , + M.call (| + M.get_name (| globals, "Log" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, "evm" |), "logs" |), + BinOp.add (| + M.get_field (| M.get_name (| globals, "evm" |), "logs" |), + make_tuple [ M.get_name (| globals, "log_entry" |) ] + |) + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition log0 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "log_n" |) + ], + make_dict [] + |) +)). + +Definition log1 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "log_n" |) + ], + make_dict [] + |) +)). + +Definition log2 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "log_n" |) + ], + make_dict [] + |) +)). + +Definition log3 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "log_n" |) + ], + make_dict [] + |) +)). + +Definition log4 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "log_n" |) + ], + make_dict [] + |) +)). diff --git a/CoqOfPython/ethereum/dao_fork/vm/instructions/memory.v b/CoqOfPython/ethereum/dao_fork/vm/instructions/memory.v new file mode 100644 index 0000000..45dbf56 --- /dev/null +++ b/CoqOfPython/ethereum/dao_fork/vm/instructions/memory.v @@ -0,0 +1,393 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.dao_fork.vm.instructions.memory". + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) Memory Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM Memory instructions. +". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_Bytes : + IsImported globals "ethereum.base_types" "Bytes". + +Axiom ethereum_dao_fork_vm_imports_Evm : + IsImported globals "ethereum.dao_fork.vm" "Evm". + +Axiom ethereum_dao_fork_vm_gas_imports_GAS_BASE : + IsImported globals "ethereum.dao_fork.vm.gas" "GAS_BASE". +Axiom ethereum_dao_fork_vm_gas_imports_GAS_VERY_LOW : + IsImported globals "ethereum.dao_fork.vm.gas" "GAS_VERY_LOW". +Axiom ethereum_dao_fork_vm_gas_imports_calculate_gas_extend_memory : + IsImported globals "ethereum.dao_fork.vm.gas" "calculate_gas_extend_memory". +Axiom ethereum_dao_fork_vm_gas_imports_charge_gas : + IsImported globals "ethereum.dao_fork.vm.gas" "charge_gas". + +Axiom ethereum_dao_fork_vm_memory_imports_memory_read_bytes : + IsImported globals "ethereum.dao_fork.vm.memory" "memory_read_bytes". +Axiom ethereum_dao_fork_vm_memory_imports_memory_write : + IsImported globals "ethereum.dao_fork.vm.memory" "memory_write". + +Axiom ethereum_dao_fork_vm_stack_imports_pop : + IsImported globals "ethereum.dao_fork.vm.stack" "pop". +Axiom ethereum_dao_fork_vm_stack_imports_push : + IsImported globals "ethereum.dao_fork.vm.stack" "push". + +Definition mstore : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Stores a word to memory. + This also expands the memory, if the memory is + insufficient to store the word. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "start_position" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "value" , + M.call (| + M.get_field (| M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |), "to_be_bytes32" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "extend_memory" , + M.call (| + M.get_name (| globals, "calculate_gas_extend_memory" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "memory" |); + make_list [ + make_tuple [ M.get_name (| globals, "start_position" |); M.call (| + M.get_name (| globals, "U256" |), + make_list [ + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_name (| globals, "value" |) + ], + make_dict [] + |) + ], + make_dict [] + |) ] + ] + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + BinOp.add (| + M.get_name (| globals, "GAS_VERY_LOW" |), + M.get_field (| M.get_name (| globals, "extend_memory" |), "cost" |) + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "memory" |), + BinOp.mult (| + Constant.bytes "00", + M.get_field (| M.get_name (| globals, "extend_memory" |), "expand_by" |) + |) + |) in + let _ := M.call (| + M.get_name (| globals, "memory_write" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "memory" |); + M.get_name (| globals, "start_position" |); + M.get_name (| globals, "value" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition mstore8 : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Stores a byte to memory. + This also expands the memory, if the memory is + insufficient to store the word. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "start_position" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "value" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "extend_memory" , + M.call (| + M.get_name (| globals, "calculate_gas_extend_memory" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "memory" |); + make_list [ + make_tuple [ M.get_name (| globals, "start_position" |); M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 1 + ], + make_dict [] + |) ] + ] + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + BinOp.add (| + M.get_name (| globals, "GAS_VERY_LOW" |), + M.get_field (| M.get_name (| globals, "extend_memory" |), "cost" |) + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "memory" |), + BinOp.mult (| + Constant.bytes "00", + M.get_field (| M.get_name (| globals, "extend_memory" |), "expand_by" |) + |) + |) in + let _ := M.assign_local (| + "normalized_bytes_value" , + M.call (| + M.get_name (| globals, "Bytes" |), + make_list [ + make_list [ + BinOp.bit_and (| + M.get_name (| globals, "value" |), + Constant.int 255 + |) + ] + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "memory_write" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "memory" |); + M.get_name (| globals, "start_position" |); + M.get_name (| globals, "normalized_bytes_value" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition mload : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Load word from memory. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "start_position" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "extend_memory" , + M.call (| + M.get_name (| globals, "calculate_gas_extend_memory" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "memory" |); + make_list [ + make_tuple [ M.get_name (| globals, "start_position" |); M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 32 + ], + make_dict [] + |) ] + ] + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + BinOp.add (| + M.get_name (| globals, "GAS_VERY_LOW" |), + M.get_field (| M.get_name (| globals, "extend_memory" |), "cost" |) + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "memory" |), + BinOp.mult (| + Constant.bytes "00", + M.get_field (| M.get_name (| globals, "extend_memory" |), "expand_by" |) + |) + |) in + let _ := M.assign_local (| + "value" , + M.call (| + M.get_field (| M.get_name (| globals, "U256" |), "from_be_bytes" |), + make_list [ + M.call (| + M.get_name (| globals, "memory_read_bytes" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "memory" |); + M.get_name (| globals, "start_position" |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 32 + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.get_name (| globals, "value" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition msize : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Push the size of active memory in bytes onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_BASE" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "memory" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). diff --git a/CoqOfPython/ethereum/dao_fork/vm/instructions/stack.v b/CoqOfPython/ethereum/dao_fork/vm/instructions/stack.v new file mode 100644 index 0000000..2ee7ab3 --- /dev/null +++ b/CoqOfPython/ethereum/dao_fork/vm/instructions/stack.v @@ -0,0 +1,947 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.dao_fork.vm.instructions.stack". + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) Stack Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM stack related instructions. +". + +Axiom functools_imports_partial : + IsImported globals "functools" "partial". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". + +Axiom ethereum_utils_ensure_imports_ensure : + IsImported globals "ethereum.utils.ensure" "ensure". + +Axiom ethereum_dao_fork_vm_imports_Evm : + IsImported globals "ethereum.dao_fork.vm" "Evm". +Axiom ethereum_dao_fork_vm_imports_stack : + IsImported globals "ethereum.dao_fork.vm" "stack". + +Axiom ethereum_dao_fork_vm_exceptions_imports_StackUnderflowError : + IsImported globals "ethereum.dao_fork.vm.exceptions" "StackUnderflowError". + +Axiom ethereum_dao_fork_vm_gas_imports_GAS_BASE : + IsImported globals "ethereum.dao_fork.vm.gas" "GAS_BASE". +Axiom ethereum_dao_fork_vm_gas_imports_GAS_VERY_LOW : + IsImported globals "ethereum.dao_fork.vm.gas" "GAS_VERY_LOW". +Axiom ethereum_dao_fork_vm_gas_imports_charge_gas : + IsImported globals "ethereum.dao_fork.vm.gas" "charge_gas". + +Axiom ethereum_dao_fork_vm_memory_imports_buffer_read : + IsImported globals "ethereum.dao_fork.vm.memory" "buffer_read". + +Definition pop : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Remove item from stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.call (| + M.get_field (| M.get_name (| globals, "stack" |), "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_BASE" |) + ], + make_dict [] + |) in + let _ := M.pass (| |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition push_n : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm"; "num_bytes" ] |) in + let _ := Constant.str " + Pushes a N-byte immediate onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + num_bytes : + The number of immediate bytes to be read from the code and pushed to + the stack. + + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_VERY_LOW" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "data_to_push" , + M.call (| + M.get_field (| M.get_name (| globals, "U256" |), "from_be_bytes" |), + make_list [ + M.call (| + M.get_name (| globals, "buffer_read" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "code" |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + BinOp.add (| + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) + ], + make_dict [] + |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + M.get_name (| globals, "num_bytes" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_field (| M.get_name (| globals, "stack" |), "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.get_name (| globals, "data_to_push" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + BinOp.add (| + Constant.int 1, + M.get_name (| globals, "num_bytes" |) + |) + |) in + M.pure Constant.None_)). + +Definition dup_n : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm"; "item_number" ] |) in + let _ := Constant.str " + Duplicate the Nth stack item (from top of the stack) to the top of stack. + + Parameters + ---------- + evm : + The current EVM frame. + + item_number : + The stack item number (0-indexed from top of stack) to be duplicated + to the top of stack. + + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_VERY_LOW" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + Compare.lt (| + M.get_name (| globals, "item_number" |), + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |); + M.get_name (| globals, "StackUnderflowError" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "data_to_duplicate" , + M.get_subscript (| + M.get_field (| M.get_name (| globals, "evm" |), "stack" |), + BinOp.sub (| + BinOp.sub (| + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |), + Constant.int 1 + |), + M.get_name (| globals, "item_number" |) + |) + |) + |) in + let _ := M.call (| + M.get_field (| M.get_name (| globals, "stack" |), "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.get_name (| globals, "data_to_duplicate" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition swap_n : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm"; "item_number" ] |) in + let _ := Constant.str " + Swap the top and the `item_number` element of the stack, where + the top of the stack is position zero. + + If `item_number` is zero, this function does nothing (which should not be + possible, since there is no `SWAP0` instruction). + + Parameters + ---------- + evm : + The current EVM frame. + + item_number : + The stack item number (0-indexed from top of stack) to be swapped + with the top of stack element. + + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_VERY_LOW" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + Compare.lt (| + M.get_name (| globals, "item_number" |), + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |); + M.get_name (| globals, "StackUnderflowError" |) + ], + make_dict [] + |) in + let _ := M.assign (| + make_tuple [ M.get_subscript (| + M.get_field (| M.get_name (| globals, "evm" |), "stack" |), + UnOp.sub (| Constant.int 1 |) + |); M.get_subscript (| + M.get_field (| M.get_name (| globals, "evm" |), "stack" |), + BinOp.sub (| + UnOp.sub (| Constant.int 1 |), + M.get_name (| globals, "item_number" |) + |) + |) ], + make_tuple [ M.get_subscript (| + M.get_field (| M.get_name (| globals, "evm" |), "stack" |), + BinOp.sub (| + UnOp.sub (| Constant.int 1 |), + M.get_name (| globals, "item_number" |) + |) + |); M.get_subscript (| + M.get_field (| M.get_name (| globals, "evm" |), "stack" |), + UnOp.sub (| Constant.int 1 |) + |) ] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition push1 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push2 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push3 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push4 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push5 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push6 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push7 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push8 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push9 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push10 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push11 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push12 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push13 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push14 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push15 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push16 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push17 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push18 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push19 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push20 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push21 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push22 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push23 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push24 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push25 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push26 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push27 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push28 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push29 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push30 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push31 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push32 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "push_n" |) + ], + make_dict [] + |) +)). + +Definition dup1 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "dup_n" |) + ], + make_dict [] + |) +)). + +Definition dup2 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "dup_n" |) + ], + make_dict [] + |) +)). + +Definition dup3 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "dup_n" |) + ], + make_dict [] + |) +)). + +Definition dup4 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "dup_n" |) + ], + make_dict [] + |) +)). + +Definition dup5 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "dup_n" |) + ], + make_dict [] + |) +)). + +Definition dup6 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "dup_n" |) + ], + make_dict [] + |) +)). + +Definition dup7 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "dup_n" |) + ], + make_dict [] + |) +)). + +Definition dup8 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "dup_n" |) + ], + make_dict [] + |) +)). + +Definition dup9 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "dup_n" |) + ], + make_dict [] + |) +)). + +Definition dup10 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "dup_n" |) + ], + make_dict [] + |) +)). + +Definition dup11 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "dup_n" |) + ], + make_dict [] + |) +)). + +Definition dup12 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "dup_n" |) + ], + make_dict [] + |) +)). + +Definition dup13 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "dup_n" |) + ], + make_dict [] + |) +)). + +Definition dup14 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "dup_n" |) + ], + make_dict [] + |) +)). + +Definition dup15 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "dup_n" |) + ], + make_dict [] + |) +)). + +Definition dup16 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "dup_n" |) + ], + make_dict [] + |) +)). + +Definition swap1 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "swap_n" |) + ], + make_dict [] + |) +)). + +Definition swap2 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "swap_n" |) + ], + make_dict [] + |) +)). + +Definition swap3 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "swap_n" |) + ], + make_dict [] + |) +)). + +Definition swap4 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "swap_n" |) + ], + make_dict [] + |) +)). + +Definition swap5 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "swap_n" |) + ], + make_dict [] + |) +)). + +Definition swap6 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "swap_n" |) + ], + make_dict [] + |) +)). + +Definition swap7 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "swap_n" |) + ], + make_dict [] + |) +)). + +Definition swap8 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "swap_n" |) + ], + make_dict [] + |) +)). + +Definition swap9 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "swap_n" |) + ], + make_dict [] + |) +)). + +Definition swap10 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "swap_n" |) + ], + make_dict [] + |) +)). + +Definition swap11 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "swap_n" |) + ], + make_dict [] + |) +)). + +Definition swap12 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "swap_n" |) + ], + make_dict [] + |) +)). + +Definition swap13 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "swap_n" |) + ], + make_dict [] + |) +)). + +Definition swap14 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "swap_n" |) + ], + make_dict [] + |) +)). + +Definition swap15 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "swap_n" |) + ], + make_dict [] + |) +)). + +Definition swap16 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "swap_n" |) + ], + make_dict [] + |) +)). diff --git a/CoqOfPython/ethereum/dao_fork/vm/instructions/storage.v b/CoqOfPython/ethereum/dao_fork/vm/instructions/storage.v new file mode 100644 index 0000000..de11f5d --- /dev/null +++ b/CoqOfPython/ethereum/dao_fork/vm/instructions/storage.v @@ -0,0 +1,234 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.dao_fork.vm.instructions.storage". + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) Storage Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM storage related instructions. +". + +Axiom ethereum_dao_fork_state_imports_get_storage : + IsImported globals "ethereum.dao_fork.state" "get_storage". +Axiom ethereum_dao_fork_state_imports_set_storage : + IsImported globals "ethereum.dao_fork.state" "set_storage". + +Axiom ethereum_dao_fork_vm_imports_Evm : + IsImported globals "ethereum.dao_fork.vm" "Evm". + +Axiom ethereum_dao_fork_vm_gas_imports_GAS_SLOAD : + IsImported globals "ethereum.dao_fork.vm.gas" "GAS_SLOAD". +Axiom ethereum_dao_fork_vm_gas_imports_GAS_STORAGE_CLEAR_REFUND : + IsImported globals "ethereum.dao_fork.vm.gas" "GAS_STORAGE_CLEAR_REFUND". +Axiom ethereum_dao_fork_vm_gas_imports_GAS_STORAGE_SET : + IsImported globals "ethereum.dao_fork.vm.gas" "GAS_STORAGE_SET". +Axiom ethereum_dao_fork_vm_gas_imports_GAS_STORAGE_UPDATE : + IsImported globals "ethereum.dao_fork.vm.gas" "GAS_STORAGE_UPDATE". +Axiom ethereum_dao_fork_vm_gas_imports_charge_gas : + IsImported globals "ethereum.dao_fork.vm.gas" "charge_gas". + +Axiom ethereum_dao_fork_vm_stack_imports_pop : + IsImported globals "ethereum.dao_fork.vm.stack" "pop". +Axiom ethereum_dao_fork_vm_stack_imports_push : + IsImported globals "ethereum.dao_fork.vm.stack" "push". + +Definition sload : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Loads to the stack, the value corresponding to a certain key from the + storage of the current account. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "key" , + M.call (| + M.get_field (| M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |), "to_be_bytes32" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_SLOAD" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "value" , + M.call (| + M.get_name (| globals, "get_storage" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "env" |), "state" |); + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "current_target" |); + M.get_name (| globals, "key" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.get_name (| globals, "value" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition sstore : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Stores a value at a certain key in the current context's storage. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "key" , + M.call (| + M.get_field (| M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |), "to_be_bytes32" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "new_value" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "current_value" , + M.call (| + M.get_name (| globals, "get_storage" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "env" |), "state" |); + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "current_target" |); + M.get_name (| globals, "key" |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + BoolOp.and (| + Compare.not_eq (| + M.get_name (| globals, "new_value" |), + Constant.int 0 + |), + ltac:(M.monadic ( + Compare.eq (| + M.get_name (| globals, "current_value" |), + Constant.int 0 + |) + )) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "gas_cost" , + M.get_name (| globals, "GAS_STORAGE_SET" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "gas_cost" , + M.get_name (| globals, "GAS_STORAGE_UPDATE" |) + |) in + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + BoolOp.and (| + Compare.eq (| + M.get_name (| globals, "new_value" |), + Constant.int 0 + |), + ltac:(M.monadic ( + Compare.not_eq (| + M.get_name (| globals, "current_value" |), + Constant.int 0 + |) + )) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "refund_counter" |), + M.get_name (| globals, "GAS_STORAGE_CLEAR_REFUND" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "gas_cost" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "set_storage" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "env" |), "state" |); + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "current_target" |); + M.get_name (| globals, "key" |); + M.get_name (| globals, "new_value" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). diff --git a/CoqOfPython/ethereum/dao_fork/vm/instructions/system.v b/CoqOfPython/ethereum/dao_fork/vm/instructions/system.v new file mode 100644 index 0000000..47ad133 --- /dev/null +++ b/CoqOfPython/ethereum/dao_fork/vm/instructions/system.v @@ -0,0 +1,1384 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.dao_fork.vm.instructions.system". + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) System Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM system related instructions. +". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_Bytes0 : + IsImported globals "ethereum.base_types" "Bytes0". +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". + +Axiom ethereum_dao_fork_fork_types_imports_Address : + IsImported globals "ethereum.dao_fork.fork_types" "Address". + +Axiom ethereum_dao_fork_state_imports_account_has_code_or_nonce : + IsImported globals "ethereum.dao_fork.state" "account_has_code_or_nonce". +Axiom ethereum_dao_fork_state_imports_get_account : + IsImported globals "ethereum.dao_fork.state" "get_account". +Axiom ethereum_dao_fork_state_imports_increment_nonce : + IsImported globals "ethereum.dao_fork.state" "increment_nonce". +Axiom ethereum_dao_fork_state_imports_set_account_balance : + IsImported globals "ethereum.dao_fork.state" "set_account_balance". + +Axiom ethereum_dao_fork_utils_address_imports_compute_contract_address : + IsImported globals "ethereum.dao_fork.utils.address" "compute_contract_address". +Axiom ethereum_dao_fork_utils_address_imports_to_address : + IsImported globals "ethereum.dao_fork.utils.address" "to_address". + +Axiom ethereum_dao_fork_vm_imports_Evm : + IsImported globals "ethereum.dao_fork.vm" "Evm". +Axiom ethereum_dao_fork_vm_imports_Message : + IsImported globals "ethereum.dao_fork.vm" "Message". +Axiom ethereum_dao_fork_vm_imports_incorporate_child_on_error : + IsImported globals "ethereum.dao_fork.vm" "incorporate_child_on_error". +Axiom ethereum_dao_fork_vm_imports_incorporate_child_on_success : + IsImported globals "ethereum.dao_fork.vm" "incorporate_child_on_success". + +Axiom ethereum_dao_fork_vm_gas_imports_GAS_CALL : + IsImported globals "ethereum.dao_fork.vm.gas" "GAS_CALL". +Axiom ethereum_dao_fork_vm_gas_imports_GAS_CREATE : + IsImported globals "ethereum.dao_fork.vm.gas" "GAS_CREATE". +Axiom ethereum_dao_fork_vm_gas_imports_GAS_ZERO : + IsImported globals "ethereum.dao_fork.vm.gas" "GAS_ZERO". +Axiom ethereum_dao_fork_vm_gas_imports_REFUND_SELF_DESTRUCT : + IsImported globals "ethereum.dao_fork.vm.gas" "REFUND_SELF_DESTRUCT". +Axiom ethereum_dao_fork_vm_gas_imports_calculate_gas_extend_memory : + IsImported globals "ethereum.dao_fork.vm.gas" "calculate_gas_extend_memory". +Axiom ethereum_dao_fork_vm_gas_imports_calculate_message_call_gas : + IsImported globals "ethereum.dao_fork.vm.gas" "calculate_message_call_gas". +Axiom ethereum_dao_fork_vm_gas_imports_charge_gas : + IsImported globals "ethereum.dao_fork.vm.gas" "charge_gas". + +Axiom ethereum_dao_fork_vm_memory_imports_memory_read_bytes : + IsImported globals "ethereum.dao_fork.vm.memory" "memory_read_bytes". +Axiom ethereum_dao_fork_vm_memory_imports_memory_write : + IsImported globals "ethereum.dao_fork.vm.memory" "memory_write". + +Axiom ethereum_dao_fork_vm_stack_imports_pop : + IsImported globals "ethereum.dao_fork.vm.stack" "pop". +Axiom ethereum_dao_fork_vm_stack_imports_push : + IsImported globals "ethereum.dao_fork.vm.stack" "push". + +Definition create : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Creates a new account with associated code. + + Parameters + ---------- + evm : + The current EVM frame. + " in +(* At stmt: unsupported node type: ImportFrom *) + let _ := M.assign_local (| + "endowment" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_start_position" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_size" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "extend_memory" , + M.call (| + M.get_name (| globals, "calculate_gas_extend_memory" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "memory" |); + make_list [ + make_tuple [ M.get_name (| globals, "memory_start_position" |); M.get_name (| globals, "memory_size" |) ] + ] + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + BinOp.add (| + M.get_name (| globals, "GAS_CREATE" |), + M.get_field (| M.get_name (| globals, "extend_memory" |), "cost" |) + |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "create_message_gas" , + M.get_field (| M.get_name (| globals, "evm" |), "gas_left" |) + |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, "evm" |), "gas_left" |), + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "memory" |), + BinOp.mult (| + Constant.bytes "00", + M.get_field (| M.get_name (| globals, "extend_memory" |), "expand_by" |) + |) + |) in + let _ := M.assign_local (| + "sender_address" , + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "current_target" |) + |) in + let _ := M.assign_local (| + "sender" , + M.call (| + M.get_name (| globals, "get_account" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "env" |), "state" |); + M.get_name (| globals, "sender_address" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "contract_address" , + M.call (| + M.get_name (| globals, "compute_contract_address" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "current_target" |); + M.get_field (| M.call (| + M.get_name (| globals, "get_account" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "env" |), "state" |); + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "current_target" |) + ], + make_dict [] + |), "nonce" |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + BoolOp.or (| + Compare.lt (| + M.get_field (| M.get_name (| globals, "sender" |), "balance" |), + M.get_name (| globals, "endowment" |) + |), + ltac:(M.monadic ( + BoolOp.or (| + Compare.eq (| + M.get_field (| M.get_name (| globals, "sender" |), "nonce" |), + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + BinOp.sub (| + BinOp.pow (| + Constant.int 2, + Constant.int 64 + |), + Constant.int 1 + |) + ], + make_dict [] + |) + |), + ltac:(M.monadic ( + Compare.gt (| + BinOp.add (| + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "depth" |), + Constant.int 1 + |), + M.get_name (| globals, "STACK_DEPTH_LIMIT" |) + |) + )) + |) + )) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "gas_left" |), + M.get_name (| globals, "create_message_gas" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, "account_has_code_or_nonce" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "env" |), "state" |); + M.get_name (| globals, "contract_address" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, "increment_nonce" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "env" |), "state" |); + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "current_target" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + ], + make_dict [] + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "call_data" , + M.call (| + M.get_name (| globals, "memory_read_bytes" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "memory" |); + M.get_name (| globals, "memory_start_position" |); + M.get_name (| globals, "memory_size" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "increment_nonce" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "env" |), "state" |); + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "current_target" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "child_message" , + M.call (| + M.get_name (| globals, "Message" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "child_evm" , + M.call (| + M.get_name (| globals, "process_create_message" |), + make_list [ + M.get_name (| globals, "child_message" |); + M.get_field (| M.get_name (| globals, "evm" |), "env" |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + M.get_field (| M.get_name (| globals, "child_evm" |), "error" |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, "incorporate_child_on_error" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "child_evm" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + ], + make_dict [] + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, "incorporate_child_on_success" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "child_evm" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.call (| + M.get_field (| M.get_name (| globals, "U256" |), "from_be_bytes" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "child_evm" |), "message" |), "current_target" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )) |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition return_ : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Halts execution returning output data. + + Parameters + ---------- + evm : + The current EVM frame. + " in + let _ := M.assign_local (| + "memory_start_position" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_size" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "extend_memory" , + M.call (| + M.get_name (| globals, "calculate_gas_extend_memory" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "memory" |); + make_list [ + make_tuple [ M.get_name (| globals, "memory_start_position" |); M.get_name (| globals, "memory_size" |) ] + ] + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + BinOp.add (| + M.get_name (| globals, "GAS_ZERO" |), + M.get_field (| M.get_name (| globals, "extend_memory" |), "cost" |) + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "memory" |), + BinOp.mult (| + Constant.bytes "00", + M.get_field (| M.get_name (| globals, "extend_memory" |), "expand_by" |) + |) + |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, "evm" |), "output" |), + M.call (| + M.get_name (| globals, "memory_read_bytes" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "memory" |); + M.get_name (| globals, "memory_start_position" |); + M.get_name (| globals, "memory_size" |) + ], + make_dict [] + |) + |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, "evm" |), "running" |), + Constant.bool false + |) in + let _ := M.pass (| |) in + M.pure Constant.None_)). + +Definition generic_call : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm"; "gas"; "value"; "caller"; "to"; "code_address"; "should_transfer_value"; "memory_input_start_position"; "memory_input_size"; "memory_output_start_position"; "memory_output_size" ] |) in + let _ := Constant.str " + Perform the core logic of the `CALL*` family of opcodes. + " in +(* At stmt: unsupported node type: ImportFrom *) + let _ := + (* if *) + M.if_then_else (| + Compare.gt (| + BinOp.add (| + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "depth" |), + Constant.int 1 + |), + M.get_name (| globals, "STACK_DEPTH_LIMIT" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "gas_left" |), + M.get_name (| globals, "gas" |) + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.return_ (| + Constant.None_ + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "call_data" , + M.call (| + M.get_name (| globals, "memory_read_bytes" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "memory" |); + M.get_name (| globals, "memory_input_start_position" |); + M.get_name (| globals, "memory_input_size" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "code" , + M.get_field (| M.call (| + M.get_name (| globals, "get_account" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "env" |), "state" |); + M.get_name (| globals, "code_address" |) + ], + make_dict [] + |), "code" |) + |) in + let _ := M.assign_local (| + "child_message" , + M.call (| + M.get_name (| globals, "Message" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "child_evm" , + M.call (| + M.get_name (| globals, "process_message" |), + make_list [ + M.get_name (| globals, "child_message" |); + M.get_field (| M.get_name (| globals, "evm" |), "env" |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + M.get_field (| M.get_name (| globals, "child_evm" |), "error" |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, "incorporate_child_on_error" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "child_evm" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + ], + make_dict [] + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, "incorporate_child_on_success" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "child_evm" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 1 + ], + make_dict [] + |) + ], + make_dict [] + |) in + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "actual_output_size" , + M.call (| + M.get_name (| globals, "min" |), + make_list [ + M.get_name (| globals, "memory_output_size" |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_field (| M.get_name (| globals, "child_evm" |), "output" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "memory_write" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "memory" |); + M.get_name (| globals, "memory_output_start_position" |); + M.slice (| + M.get_field (| M.get_name (| globals, "child_evm" |), "output" |), + Constant.None_, + M.get_name (| globals, "actual_output_size" |), + Constant.None_ + |) + ], + make_dict [] + |) in + M.pure Constant.None_)). + +Definition call : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Message-call into an account. + + Parameters + ---------- + evm : + The current EVM frame. + " in + let _ := M.assign_local (| + "gas" , + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "to" , + M.call (| + M.get_name (| globals, "to_address" |), + make_list [ + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "value" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_input_start_position" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_input_size" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_output_start_position" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_output_size" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "extend_memory" , + M.call (| + M.get_name (| globals, "calculate_gas_extend_memory" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "memory" |); + make_list [ + make_tuple [ M.get_name (| globals, "memory_input_start_position" |); M.get_name (| globals, "memory_input_size" |) ]; + make_tuple [ M.get_name (| globals, "memory_output_start_position" |); M.get_name (| globals, "memory_output_size" |) ] + ] + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "message_call_gas" , + M.call (| + M.get_name (| globals, "calculate_message_call_gas" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "env" |), "state" |); + M.get_name (| globals, "gas" |); + M.get_name (| globals, "to" |); + M.get_name (| globals, "value" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + BinOp.add (| + M.get_field (| M.get_name (| globals, "message_call_gas" |), "cost" |), + M.get_field (| M.get_name (| globals, "extend_memory" |), "cost" |) + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "memory" |), + BinOp.mult (| + Constant.bytes "00", + M.get_field (| M.get_name (| globals, "extend_memory" |), "expand_by" |) + |) + |) in + let _ := M.assign_local (| + "sender_balance" , + M.get_field (| M.call (| + M.get_name (| globals, "get_account" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "env" |), "state" |); + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "current_target" |) + ], + make_dict [] + |), "balance" |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.lt (| + M.get_name (| globals, "sender_balance" |), + M.get_name (| globals, "value" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "gas_left" |), + M.get_field (| M.get_name (| globals, "message_call_gas" |), "stipend" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, "generic_call" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_field (| M.get_name (| globals, "message_call_gas" |), "stipend" |); + M.get_name (| globals, "value" |); + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "current_target" |); + M.get_name (| globals, "to" |); + M.get_name (| globals, "to" |); + Constant.bool true; + M.get_name (| globals, "memory_input_start_position" |); + M.get_name (| globals, "memory_input_size" |); + M.get_name (| globals, "memory_output_start_position" |); + M.get_name (| globals, "memory_output_size" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + )) |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition callcode : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Message-call into this account with alternative account’s code. + + Parameters + ---------- + evm : + The current EVM frame. + " in + let _ := M.assign_local (| + "gas" , + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "code_address" , + M.call (| + M.get_name (| globals, "to_address" |), + make_list [ + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "value" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_input_start_position" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_input_size" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_output_start_position" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_output_size" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "to" , + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "current_target" |) + |) in + let _ := M.assign_local (| + "extend_memory" , + M.call (| + M.get_name (| globals, "calculate_gas_extend_memory" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "memory" |); + make_list [ + make_tuple [ M.get_name (| globals, "memory_input_start_position" |); M.get_name (| globals, "memory_input_size" |) ]; + make_tuple [ M.get_name (| globals, "memory_output_start_position" |); M.get_name (| globals, "memory_output_size" |) ] + ] + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "message_call_gas" , + M.call (| + M.get_name (| globals, "calculate_message_call_gas" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "env" |), "state" |); + M.get_name (| globals, "gas" |); + M.get_name (| globals, "to" |); + M.get_name (| globals, "value" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + BinOp.add (| + M.get_field (| M.get_name (| globals, "message_call_gas" |), "cost" |), + M.get_field (| M.get_name (| globals, "extend_memory" |), "cost" |) + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "memory" |), + BinOp.mult (| + Constant.bytes "00", + M.get_field (| M.get_name (| globals, "extend_memory" |), "expand_by" |) + |) + |) in + let _ := M.assign_local (| + "sender_balance" , + M.get_field (| M.call (| + M.get_name (| globals, "get_account" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "env" |), "state" |); + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "current_target" |) + ], + make_dict [] + |), "balance" |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.lt (| + M.get_name (| globals, "sender_balance" |), + M.get_name (| globals, "value" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "gas_left" |), + M.get_field (| M.get_name (| globals, "message_call_gas" |), "stipend" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, "generic_call" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_field (| M.get_name (| globals, "message_call_gas" |), "stipend" |); + M.get_name (| globals, "value" |); + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "current_target" |); + M.get_name (| globals, "to" |); + M.get_name (| globals, "code_address" |); + Constant.bool true; + M.get_name (| globals, "memory_input_start_position" |); + M.get_name (| globals, "memory_input_size" |); + M.get_name (| globals, "memory_output_start_position" |); + M.get_name (| globals, "memory_output_size" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + )) |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition selfdestruct : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Halt execution and register account for later deletion. + + Parameters + ---------- + evm : + The current EVM frame. + " in + let _ := M.assign_local (| + "beneficiary" , + M.call (| + M.get_name (| globals, "to_address" |), + make_list [ + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "gas_cost" , + M.get_name (| globals, "GAS_ZERO" |) + |) in + let _ := M.assign_local (| + "originator" , + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "current_target" |) + |) in + let _ := M.assign_local (| + "refunded_accounts" , + M.get_field (| M.get_name (| globals, "evm" |), "accounts_to_delete" |) + |) in + let _ := M.assign_local (| + "parent_evm" , + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "parent_evm" |) + |) in + let _ := + M.while (| + Compare.is_not (| + M.get_name (| globals, "parent_evm" |), + Constant.None_ + |), + ltac:(M.monadic ( + let _ := M.call (| + M.get_field (| M.get_name (| globals, "refunded_accounts" |), "update" |), + make_list [ + M.get_field (| M.get_name (| globals, "parent_evm" |), "accounts_to_delete" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "parent_evm" , + M.get_field (| M.get_field (| M.get_name (| globals, "parent_evm" |), "message" |), "parent_evm" |) + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.not_in (| + M.get_name (| globals, "originator" |), + M.get_name (| globals, "refunded_accounts" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "refund_counter" |), + M.get_name (| globals, "REFUND_SELF_DESTRUCT" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "gas_cost" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "beneficiary_balance" , + M.get_field (| M.call (| + M.get_name (| globals, "get_account" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "env" |), "state" |); + M.get_name (| globals, "beneficiary" |) + ], + make_dict [] + |), "balance" |) + |) in + let _ := M.assign_local (| + "originator_balance" , + M.get_field (| M.call (| + M.get_name (| globals, "get_account" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "env" |), "state" |); + M.get_name (| globals, "originator" |) + ], + make_dict [] + |), "balance" |) + |) in + let _ := M.call (| + M.get_name (| globals, "set_account_balance" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "env" |), "state" |); + M.get_name (| globals, "beneficiary" |); + BinOp.add (| + M.get_name (| globals, "beneficiary_balance" |), + M.get_name (| globals, "originator_balance" |) + |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "set_account_balance" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "env" |), "state" |); + M.get_name (| globals, "originator" |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "accounts_to_delete" |), "add" |), + make_list [ + M.get_name (| globals, "originator" |) + ], + make_dict [] + |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, "evm" |), "running" |), + Constant.bool false + |) in + let _ := M.pass (| |) in + M.pure Constant.None_)). + +Definition delegatecall : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Message-call into an account. + + Parameters + ---------- + evm : + The current EVM frame. + " in + let _ := M.assign_local (| + "gas" , + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "code_address" , + M.call (| + M.get_name (| globals, "to_address" |), + make_list [ + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_input_start_position" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_input_size" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_output_start_position" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_output_size" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "extend_memory" , + M.call (| + M.get_name (| globals, "calculate_gas_extend_memory" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "memory" |); + make_list [ + make_tuple [ M.get_name (| globals, "memory_input_start_position" |); M.get_name (| globals, "memory_input_size" |) ]; + make_tuple [ M.get_name (| globals, "memory_output_start_position" |); M.get_name (| globals, "memory_output_size" |) ] + ] + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + BinOp.add (| + BinOp.add (| + M.get_name (| globals, "GAS_CALL" |), + M.get_name (| globals, "gas" |) + |), + M.get_field (| M.get_name (| globals, "extend_memory" |), "cost" |) + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "memory" |), + BinOp.mult (| + Constant.bytes "00", + M.get_field (| M.get_name (| globals, "extend_memory" |), "expand_by" |) + |) + |) in + let _ := M.call (| + M.get_name (| globals, "generic_call" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "gas" |); + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "value" |); + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "caller" |); + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "current_target" |); + M.get_name (| globals, "code_address" |); + Constant.bool false; + M.get_name (| globals, "memory_input_start_position" |); + M.get_name (| globals, "memory_input_size" |); + M.get_name (| globals, "memory_output_start_position" |); + M.get_name (| globals, "memory_output_size" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). diff --git a/CoqOfPython/ethereum/dao_fork/vm/interpreter.v b/CoqOfPython/ethereum/dao_fork/vm/interpreter.v new file mode 100644 index 0000000..1a01d75 --- /dev/null +++ b/CoqOfPython/ethereum/dao_fork/vm/interpreter.v @@ -0,0 +1,570 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.dao_fork.vm.interpreter". + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) Interpreter +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +A straightforward interpreter that executes EVM code. +". + +Axiom dataclasses_imports_dataclass : + IsImported globals "dataclasses" "dataclass". + +Axiom typing_imports_Optional : + IsImported globals "typing" "Optional". +Axiom typing_imports_Set : + IsImported globals "typing" "Set". +Axiom typing_imports_Tuple : + IsImported globals "typing" "Tuple". +Axiom typing_imports_Union : + IsImported globals "typing" "Union". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_Bytes0 : + IsImported globals "ethereum.base_types" "Bytes0". +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". + +Axiom ethereum_trace_imports_EvmStop : + IsImported globals "ethereum.trace" "EvmStop". +Axiom ethereum_trace_imports_OpEnd : + IsImported globals "ethereum.trace" "OpEnd". +Axiom ethereum_trace_imports_OpException : + IsImported globals "ethereum.trace" "OpException". +Axiom ethereum_trace_imports_OpStart : + IsImported globals "ethereum.trace" "OpStart". +Axiom ethereum_trace_imports_PrecompileEnd : + IsImported globals "ethereum.trace" "PrecompileEnd". +Axiom ethereum_trace_imports_PrecompileStart : + IsImported globals "ethereum.trace" "PrecompileStart". +Axiom ethereum_trace_imports_TransactionEnd : + IsImported globals "ethereum.trace" "TransactionEnd". +Axiom ethereum_trace_imports_evm_trace : + IsImported globals "ethereum.trace" "evm_trace". + +Axiom ethereum_dao_fork_blocks_imports_Log : + IsImported globals "ethereum.dao_fork.blocks" "Log". + +Axiom ethereum_dao_fork_fork_types_imports_Address : + IsImported globals "ethereum.dao_fork.fork_types" "Address". + +Axiom ethereum_dao_fork_state_imports_account_has_code_or_nonce : + IsImported globals "ethereum.dao_fork.state" "account_has_code_or_nonce". +Axiom ethereum_dao_fork_state_imports_begin_transaction : + IsImported globals "ethereum.dao_fork.state" "begin_transaction". +Axiom ethereum_dao_fork_state_imports_commit_transaction : + IsImported globals "ethereum.dao_fork.state" "commit_transaction". +Axiom ethereum_dao_fork_state_imports_move_ether : + IsImported globals "ethereum.dao_fork.state" "move_ether". +Axiom ethereum_dao_fork_state_imports_rollback_transaction : + IsImported globals "ethereum.dao_fork.state" "rollback_transaction". +Axiom ethereum_dao_fork_state_imports_set_code : + IsImported globals "ethereum.dao_fork.state" "set_code". +Axiom ethereum_dao_fork_state_imports_touch_account : + IsImported globals "ethereum.dao_fork.state" "touch_account". + +Axiom ethereum_dao_fork_vm_imports_Message : + IsImported globals "ethereum.dao_fork.vm" "Message". + +Axiom ethereum_dao_fork_vm_gas_imports_GAS_CODE_DEPOSIT : + IsImported globals "ethereum.dao_fork.vm.gas" "GAS_CODE_DEPOSIT". +Axiom ethereum_dao_fork_vm_gas_imports_charge_gas : + IsImported globals "ethereum.dao_fork.vm.gas" "charge_gas". + +Axiom ethereum_dao_fork_vm_precompiled_contracts_mapping_imports_PRE_COMPILED_CONTRACTS : + IsImported globals "ethereum.dao_fork.vm.precompiled_contracts.mapping" "PRE_COMPILED_CONTRACTS". + +Axiom ethereum_dao_fork_vm_imports_Environment : + IsImported globals "ethereum.dao_fork.vm" "Environment". +Axiom ethereum_dao_fork_vm_imports_Evm : + IsImported globals "ethereum.dao_fork.vm" "Evm". + +Axiom ethereum_dao_fork_vm_exceptions_imports_AddressCollision : + IsImported globals "ethereum.dao_fork.vm.exceptions" "AddressCollision". +Axiom ethereum_dao_fork_vm_exceptions_imports_ExceptionalHalt : + IsImported globals "ethereum.dao_fork.vm.exceptions" "ExceptionalHalt". +Axiom ethereum_dao_fork_vm_exceptions_imports_InvalidOpcode : + IsImported globals "ethereum.dao_fork.vm.exceptions" "InvalidOpcode". +Axiom ethereum_dao_fork_vm_exceptions_imports_StackDepthLimitError : + IsImported globals "ethereum.dao_fork.vm.exceptions" "StackDepthLimitError". + +Axiom ethereum_dao_fork_vm_instructions_imports_Ops : + IsImported globals "ethereum.dao_fork.vm.instructions" "Ops". +Axiom ethereum_dao_fork_vm_instructions_imports_op_implementation : + IsImported globals "ethereum.dao_fork.vm.instructions" "op_implementation". + +Axiom ethereum_dao_fork_vm_runtime_imports_get_valid_jump_destinations : + IsImported globals "ethereum.dao_fork.vm.runtime" "get_valid_jump_destinations". + +Definition STACK_DEPTH_LIMIT : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 1024 + ], + make_dict [] + |) +)). + +Definition MessageCallOutput : Value.t := + builtins.make_klass + [] + [ + + ] + [ + + ]. + +Definition process_message_call : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "message"; "env" ] |) in + let _ := Constant.str " + If `message.current` is empty then it creates a smart contract + else it executes a call from the `message.caller` to the `message.target`. + + Parameters + ---------- + message : + Transaction specific items. + + env : + External items required for EVM execution. + + Returns + ------- + output : `MessageCallOutput` + Output of the message call + " in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_field (| M.get_name (| globals, "message" |), "target" |), + M.call (| + M.get_name (| globals, "Bytes0" |), + make_list [ + Constant.bytes "" + ], + make_dict [] + |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "is_collision" , + M.call (| + M.get_name (| globals, "account_has_code_or_nonce" |), + make_list [ + M.get_field (| M.get_name (| globals, "env" |), "state" |); + M.get_field (| M.get_name (| globals, "message" |), "current_target" |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + M.get_name (| globals, "is_collision" |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + M.call (| + M.get_name (| globals, "MessageCallOutput" |), + make_list [ + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |); + M.call (| + M.get_name (| globals, "tuple" |), + make_list [], + make_dict [] + |); + M.call (| + M.get_name (| globals, "set" |), + make_list [], + make_dict [] + |); + M.call (| + M.get_name (| globals, "AddressCollision" |), + make_list [], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "evm" , + M.call (| + M.get_name (| globals, "process_create_message" |), + make_list [ + M.get_name (| globals, "message" |); + M.get_name (| globals, "env" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "evm" , + M.call (| + M.get_name (| globals, "process_message" |), + make_list [ + M.get_name (| globals, "message" |); + M.get_name (| globals, "env" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + M.get_field (| M.get_name (| globals, "evm" |), "error" |), + (* then *) + ltac:(M.monadic ( +(* At stmt: unsupported node type: AnnAssign *) + let _ := M.assign_local (| + "accounts_to_delete" , + M.call (| + M.get_name (| globals, "set" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "refund_counter" , + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "logs" , + M.get_field (| M.get_name (| globals, "evm" |), "logs" |) + |) in + let _ := M.assign_local (| + "accounts_to_delete" , + M.get_field (| M.get_name (| globals, "evm" |), "accounts_to_delete" |) + |) in + let _ := M.assign_local (| + "refund_counter" , + M.get_field (| M.get_name (| globals, "evm" |), "refund_counter" |) + |) in + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "tx_end" , + M.call (| + M.get_name (| globals, "TransactionEnd" |), + make_list [ + BinOp.sub (| + M.get_field (| M.get_name (| globals, "message" |), "gas" |), + M.get_field (| M.get_name (| globals, "evm" |), "gas_left" |) + |); + M.get_field (| M.get_name (| globals, "evm" |), "output" |); + M.get_field (| M.get_name (| globals, "evm" |), "error" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "evm_trace" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "tx_end" |) + ], + make_dict [] + |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, "MessageCallOutput" |), + make_list [], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Definition process_create_message : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "message"; "env" ] |) in + let _ := Constant.str " + Executes a call to create a smart contract. + + Parameters + ---------- + message : + Transaction specific items. + env : + External items required for EVM execution. + + Returns + ------- + evm: :py:class:`~ethereum.dao_fork.vm.Evm` + Items containing execution specific objects. + " in + let _ := M.call (| + M.get_name (| globals, "begin_transaction" |), + make_list [ + M.get_field (| M.get_name (| globals, "env" |), "state" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "evm" , + M.call (| + M.get_name (| globals, "process_message" |), + make_list [ + M.get_name (| globals, "message" |); + M.get_name (| globals, "env" |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + UnOp.not (| M.get_field (| M.get_name (| globals, "evm" |), "error" |) |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "contract_code" , + M.get_field (| M.get_name (| globals, "evm" |), "output" |) + |) in + let _ := M.assign_local (| + "contract_code_gas" , + BinOp.mult (| + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_name (| globals, "contract_code" |) + ], + make_dict [] + |), + M.get_name (| globals, "GAS_CODE_DEPOSIT" |) + |) + |) in +(* At stmt: unsupported node type: Try *) + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, "rollback_transaction" |), + make_list [ + M.get_field (| M.get_name (| globals, "env" |), "state" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + )) |) in + let _ := M.return_ (| + M.get_name (| globals, "evm" |) + |) in + M.pure Constant.None_)). + +Definition process_message : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "message"; "env" ] |) in + let _ := Constant.str " + Executes a call to create a smart contract. + + Parameters + ---------- + message : + Transaction specific items. + env : + External items required for EVM execution. + + Returns + ------- + evm: :py:class:`~ethereum.dao_fork.vm.Evm` + Items containing execution specific objects + " in + let _ := + (* if *) + M.if_then_else (| + Compare.gt (| + M.get_field (| M.get_name (| globals, "message" |), "depth" |), + M.get_name (| globals, "STACK_DEPTH_LIMIT" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.call (| + M.get_name (| globals, "StackDepthLimitError" |), + make_list [ + Constant.str "Stack depth limit reached" + ], + make_dict [] + |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.call (| + M.get_name (| globals, "begin_transaction" |), + make_list [ + M.get_field (| M.get_name (| globals, "env" |), "state" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "touch_account" |), + make_list [ + M.get_field (| M.get_name (| globals, "env" |), "state" |); + M.get_field (| M.get_name (| globals, "message" |), "current_target" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + BoolOp.and (| + M.get_field (| M.get_name (| globals, "message" |), "should_transfer_value" |), + ltac:(M.monadic ( + Compare.not_eq (| + M.get_field (| M.get_name (| globals, "message" |), "value" |), + Constant.int 0 + |) + )) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, "move_ether" |), + make_list [ + M.get_field (| M.get_name (| globals, "env" |), "state" |); + M.get_field (| M.get_name (| globals, "message" |), "caller" |); + M.get_field (| M.get_name (| globals, "message" |), "current_target" |); + M.get_field (| M.get_name (| globals, "message" |), "value" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "evm" , + M.call (| + M.get_name (| globals, "execute_code" |), + make_list [ + M.get_name (| globals, "message" |); + M.get_name (| globals, "env" |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + M.get_field (| M.get_name (| globals, "evm" |), "error" |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, "rollback_transaction" |), + make_list [ + M.get_field (| M.get_name (| globals, "env" |), "state" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, "commit_transaction" |), + make_list [ + M.get_field (| M.get_name (| globals, "env" |), "state" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + )) |) in + let _ := M.return_ (| + M.get_name (| globals, "evm" |) + |) in + M.pure Constant.None_)). + +Definition execute_code : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "message"; "env" ] |) in + let _ := Constant.str " + Executes bytecode present in the `message`. + + Parameters + ---------- + message : + Transaction specific items. + env : + External items required for EVM execution. + + Returns + ------- + evm: `ethereum.vm.EVM` + Items containing execution specific objects + " in + let _ := M.assign_local (| + "code" , + M.get_field (| M.get_name (| globals, "message" |), "code" |) + |) in + let _ := M.assign_local (| + "valid_jump_destinations" , + M.call (| + M.get_name (| globals, "get_valid_jump_destinations" |), + make_list [ + M.get_name (| globals, "code" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "evm" , + M.call (| + M.get_name (| globals, "Evm" |), + make_list [], + make_dict [] + |) + |) in +(* At stmt: unsupported node type: Try *) + let _ := M.return_ (| + M.get_name (| globals, "evm" |) + |) in + M.pure Constant.None_)). diff --git a/CoqOfPython/ethereum/dao_fork/vm/memory.v b/CoqOfPython/ethereum/dao_fork/vm/memory.v new file mode 100644 index 0000000..d512649 --- /dev/null +++ b/CoqOfPython/ethereum/dao_fork/vm/memory.v @@ -0,0 +1,166 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.dao_fork.vm.memory". + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) Memory +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +EVM memory operations. +". + +Axiom ethereum_utils_byte_imports_right_pad_zero_bytes : + IsImported globals "ethereum.utils.byte" "right_pad_zero_bytes". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_Bytes : + IsImported globals "ethereum.base_types" "Bytes". +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". + +Definition memory_write : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "memory"; "start_position"; "value" ] |) in + let _ := Constant.str " + Writes to memory. + + Parameters + ---------- + memory : + Memory contents of the EVM. + start_position : + Starting pointer to the memory. + value : + Data to write to memory. + " in + let _ := M.assign (| + M.slice (| + M.get_name (| globals, "memory" |), + M.get_name (| globals, "start_position" |), + BinOp.add (| + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.get_name (| globals, "start_position" |) + ], + make_dict [] + |), + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_name (| globals, "value" |) + ], + make_dict [] + |) + |), + Constant.None_ + |), + M.get_name (| globals, "value" |) + |) in + M.pure Constant.None_)). + +Definition memory_read_bytes : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "memory"; "start_position"; "size" ] |) in + let _ := Constant.str " + Read bytes from memory. + + Parameters + ---------- + memory : + Memory contents of the EVM. + start_position : + Starting pointer to the memory. + size : + Size of the data that needs to be read from `start_position`. + + Returns + ------- + data_bytes : + Data read from memory. + " in + let _ := M.return_ (| + M.slice (| + M.get_name (| globals, "memory" |), + M.get_name (| globals, "start_position" |), + BinOp.add (| + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.get_name (| globals, "start_position" |) + ], + make_dict [] + |), + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.get_name (| globals, "size" |) + ], + make_dict [] + |) + |), + Constant.None_ + |) + |) in + M.pure Constant.None_)). + +Definition buffer_read : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "buffer"; "start_position"; "size" ] |) in + let _ := Constant.str " + Read bytes from a buffer. Padding with zeros if necessary. + + Parameters + ---------- + buffer : + Memory contents of the EVM. + start_position : + Starting pointer to the memory. + size : + Size of the data that needs to be read from `start_position`. + + Returns + ------- + data_bytes : + Data read from memory. + " in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, "right_pad_zero_bytes" |), + make_list [ + M.slice (| + M.get_name (| globals, "buffer" |), + M.get_name (| globals, "start_position" |), + BinOp.add (| + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.get_name (| globals, "start_position" |) + ], + make_dict [] + |), + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.get_name (| globals, "size" |) + ], + make_dict [] + |) + |), + Constant.None_ + |); + M.get_name (| globals, "size" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). diff --git a/CoqOfPython/ethereum/dao_fork/vm/precompiled_contracts/__init__.v b/CoqOfPython/ethereum/dao_fork/vm/precompiled_contracts/__init__.v new file mode 100644 index 0000000..a28f1e8 --- /dev/null +++ b/CoqOfPython/ethereum/dao_fork/vm/precompiled_contracts/__init__.v @@ -0,0 +1,66 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.dao_fork.vm.precompiled_contracts.__init__". + +Definition expr_1 : Value.t := + Constant.str " +Precompiled Contract Addresses +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Addresses of precompiled contracts and mappings to their +implementations. +". + +Axiom ethereum_dao_fork_utils_hexadecimal_imports_hex_to_address : + IsImported globals "ethereum.dao_fork.utils.hexadecimal" "hex_to_address". + +Definition __all__ : Value.t := M.run ltac:(M.monadic ( + make_tuple [ Constant.str "ECRECOVER_ADDRESS"; Constant.str "SHA256_ADDRESS"; Constant.str "RIPEMD160_ADDRESS"; Constant.str "IDENTITY_ADDRESS" ] +)). + +Definition ECRECOVER_ADDRESS : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "hex_to_address" |), + make_list [ + Constant.str "0x01" + ], + make_dict [] + |) +)). + +Definition SHA256_ADDRESS : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "hex_to_address" |), + make_list [ + Constant.str "0x02" + ], + make_dict [] + |) +)). + +Definition RIPEMD160_ADDRESS : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "hex_to_address" |), + make_list [ + Constant.str "0x03" + ], + make_dict [] + |) +)). + +Definition IDENTITY_ADDRESS : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "hex_to_address" |), + make_list [ + Constant.str "0x04" + ], + make_dict [] + |) +)). diff --git a/CoqOfPython/ethereum/dao_fork/vm/precompiled_contracts/ecrecover.v b/CoqOfPython/ethereum/dao_fork/vm/precompiled_contracts/ecrecover.v new file mode 100644 index 0000000..0c4b624 --- /dev/null +++ b/CoqOfPython/ethereum/dao_fork/vm/precompiled_contracts/ecrecover.v @@ -0,0 +1,301 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.dao_fork.vm.precompiled_contracts.ecrecover". + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) ECRECOVER PRECOMPILED CONTRACT +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementation of the ECRECOVER precompiled contract. +". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". + +Axiom ethereum_crypto_elliptic_curve_imports_SECP256K1N : + IsImported globals "ethereum.crypto.elliptic_curve" "SECP256K1N". +Axiom ethereum_crypto_elliptic_curve_imports_secp256k1_recover : + IsImported globals "ethereum.crypto.elliptic_curve" "secp256k1_recover". + +Axiom ethereum_crypto_hash_imports_Hash32 : + IsImported globals "ethereum.crypto.hash" "Hash32". +Axiom ethereum_crypto_hash_imports_keccak256 : + IsImported globals "ethereum.crypto.hash" "keccak256". + +Axiom ethereum_utils_byte_imports_left_pad_zero_bytes : + IsImported globals "ethereum.utils.byte" "left_pad_zero_bytes". + +Axiom ethereum_dao_fork_vm_imports_Evm : + IsImported globals "ethereum.dao_fork.vm" "Evm". + +Axiom ethereum_dao_fork_vm_gas_imports_GAS_ECRECOVER : + IsImported globals "ethereum.dao_fork.vm.gas" "GAS_ECRECOVER". +Axiom ethereum_dao_fork_vm_gas_imports_charge_gas : + IsImported globals "ethereum.dao_fork.vm.gas" "charge_gas". + +Axiom ethereum_dao_fork_vm_memory_imports_buffer_read : + IsImported globals "ethereum.dao_fork.vm.memory" "buffer_read". + +Definition ecrecover : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Decrypts the address using elliptic curve DSA recovery mechanism and writes + the address to output. + + Parameters + ---------- + evm : + The current EVM frame. + " in + let _ := M.assign_local (| + "data" , + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "data" |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_ECRECOVER" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "message_hash_bytes" , + M.call (| + M.get_name (| globals, "buffer_read" |), + make_list [ + M.get_name (| globals, "data" |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 32 + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "message_hash" , + M.call (| + M.get_name (| globals, "Hash32" |), + make_list [ + M.get_name (| globals, "message_hash_bytes" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "v" , + M.call (| + M.get_field (| M.get_name (| globals, "U256" |), "from_be_bytes" |), + make_list [ + M.call (| + M.get_name (| globals, "buffer_read" |), + make_list [ + M.get_name (| globals, "data" |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 32 + ], + make_dict [] + |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 32 + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "r" , + M.call (| + M.get_field (| M.get_name (| globals, "U256" |), "from_be_bytes" |), + make_list [ + M.call (| + M.get_name (| globals, "buffer_read" |), + make_list [ + M.get_name (| globals, "data" |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 64 + ], + make_dict [] + |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 32 + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "s" , + M.call (| + M.get_field (| M.get_name (| globals, "U256" |), "from_be_bytes" |), + make_list [ + M.call (| + M.get_name (| globals, "buffer_read" |), + make_list [ + M.get_name (| globals, "data" |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 96 + ], + make_dict [] + |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 32 + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + BoolOp.and (| + Compare.not_eq (| + M.get_name (| globals, "v" |), + Constant.int 27 + |), + ltac:(M.monadic ( + Compare.not_eq (| + M.get_name (| globals, "v" |), + Constant.int 28 + |) + )) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + Constant.None_ + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + BoolOp.or (| + Compare.gt_e (| + Constant.int 0, + M.get_name (| globals, "r" |) + |), + ltac:(M.monadic ( + Compare.gt_e (| + M.get_name (| globals, "r" |), + M.get_name (| globals, "SECP256K1N" |) + |) + )) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + Constant.None_ + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + BoolOp.or (| + Compare.gt_e (| + Constant.int 0, + M.get_name (| globals, "s" |) + |), + ltac:(M.monadic ( + Compare.gt_e (| + M.get_name (| globals, "s" |), + M.get_name (| globals, "SECP256K1N" |) + |) + )) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + Constant.None_ + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in +(* At stmt: unsupported node type: Try *) + let _ := M.assign_local (| + "address" , + M.slice (| + M.call (| + M.get_name (| globals, "keccak256" |), + make_list [ + M.get_name (| globals, "public_key" |) + ], + make_dict [] + |), + Constant.int 12, + Constant.int 32, + Constant.None_ + |) + |) in + let _ := M.assign_local (| + "padded_address" , + M.call (| + M.get_name (| globals, "left_pad_zero_bytes" |), + make_list [ + M.get_name (| globals, "address" |); + Constant.int 32 + ], + make_dict [] + |) + |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, "evm" |), "output" |), + M.get_name (| globals, "padded_address" |) + |) in + M.pure Constant.None_)). diff --git a/CoqOfPython/ethereum/dao_fork/vm/precompiled_contracts/identity.v b/CoqOfPython/ethereum/dao_fork/vm/precompiled_contracts/identity.v new file mode 100644 index 0000000..4b71893 --- /dev/null +++ b/CoqOfPython/ethereum/dao_fork/vm/precompiled_contracts/identity.v @@ -0,0 +1,94 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.dao_fork.vm.precompiled_contracts.identity". + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) IDENTITY PRECOMPILED CONTRACT +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementation of the `IDENTITY` precompiled contract. +". + +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". + +Axiom ethereum_utils_numeric_imports_ceil32 : + IsImported globals "ethereum.utils.numeric" "ceil32". + +Axiom ethereum_dao_fork_vm_imports_Evm : + IsImported globals "ethereum.dao_fork.vm" "Evm". + +Axiom ethereum_dao_fork_vm_gas_imports_GAS_IDENTITY : + IsImported globals "ethereum.dao_fork.vm.gas" "GAS_IDENTITY". +Axiom ethereum_dao_fork_vm_gas_imports_GAS_IDENTITY_WORD : + IsImported globals "ethereum.dao_fork.vm.gas" "GAS_IDENTITY_WORD". +Axiom ethereum_dao_fork_vm_gas_imports_charge_gas : + IsImported globals "ethereum.dao_fork.vm.gas" "charge_gas". + +Definition identity : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Writes the message data to output. + + Parameters + ---------- + evm : + The current EVM frame. + " in + let _ := M.assign_local (| + "data" , + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "data" |) + |) in + let _ := M.assign_local (| + "word_count" , + BinOp.floor_div (| + M.call (| + M.get_name (| globals, "ceil32" |), + make_list [ + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_name (| globals, "data" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |), + Constant.int 32 + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + BinOp.add (| + M.get_name (| globals, "GAS_IDENTITY" |), + BinOp.mult (| + M.get_name (| globals, "GAS_IDENTITY_WORD" |), + M.get_name (| globals, "word_count" |) + |) + |) + ], + make_dict [] + |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, "evm" |), "output" |), + M.get_name (| globals, "data" |) + |) in + M.pure Constant.None_)). diff --git a/CoqOfPython/ethereum/dao_fork/vm/precompiled_contracts/mapping.v b/CoqOfPython/ethereum/dao_fork/vm/precompiled_contracts/mapping.v new file mode 100644 index 0000000..b94fbd8 --- /dev/null +++ b/CoqOfPython/ethereum/dao_fork/vm/precompiled_contracts/mapping.v @@ -0,0 +1,49 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.dao_fork.vm.precompiled_contracts.mapping". + +Definition expr_1 : Value.t := + Constant.str " +Precompiled Contract Addresses +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Mapping of precompiled contracts their implementations. +". + +Axiom typing_imports_Callable : + IsImported globals "typing" "Callable". +Axiom typing_imports_Dict : + IsImported globals "typing" "Dict". + +Axiom ethereum_dao_fork_fork_types_imports_Address : + IsImported globals "ethereum.dao_fork.fork_types" "Address". + +Axiom ethereum_dao_fork_vm_precompiled_contracts_imports_ECRECOVER_ADDRESS : + IsImported globals "ethereum.dao_fork.vm.precompiled_contracts" "ECRECOVER_ADDRESS". +Axiom ethereum_dao_fork_vm_precompiled_contracts_imports_IDENTITY_ADDRESS : + IsImported globals "ethereum.dao_fork.vm.precompiled_contracts" "IDENTITY_ADDRESS". +Axiom ethereum_dao_fork_vm_precompiled_contracts_imports_RIPEMD160_ADDRESS : + IsImported globals "ethereum.dao_fork.vm.precompiled_contracts" "RIPEMD160_ADDRESS". +Axiom ethereum_dao_fork_vm_precompiled_contracts_imports_SHA256_ADDRESS : + IsImported globals "ethereum.dao_fork.vm.precompiled_contracts" "SHA256_ADDRESS". + +Axiom ethereum_dao_fork_vm_precompiled_contracts_ecrecover_imports_ecrecover : + IsImported globals "ethereum.dao_fork.vm.precompiled_contracts.ecrecover" "ecrecover". + +Axiom ethereum_dao_fork_vm_precompiled_contracts_identity_imports_identity : + IsImported globals "ethereum.dao_fork.vm.precompiled_contracts.identity" "identity". + +Axiom ethereum_dao_fork_vm_precompiled_contracts_ripemd160_imports_ripemd160 : + IsImported globals "ethereum.dao_fork.vm.precompiled_contracts.ripemd160" "ripemd160". + +Axiom ethereum_dao_fork_vm_precompiled_contracts_sha256_imports_sha256 : + IsImported globals "ethereum.dao_fork.vm.precompiled_contracts.sha256" "sha256". + +(* At top_level_stmt: unsupported node type: AnnAssign *) diff --git a/CoqOfPython/ethereum/dao_fork/vm/precompiled_contracts/ripemd160.v b/CoqOfPython/ethereum/dao_fork/vm/precompiled_contracts/ripemd160.v new file mode 100644 index 0000000..39c8265 --- /dev/null +++ b/CoqOfPython/ethereum/dao_fork/vm/precompiled_contracts/ripemd160.v @@ -0,0 +1,125 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.dao_fork.vm.precompiled_contracts.ripemd160". + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) RIPEMD160 PRECOMPILED CONTRACT +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementation of the `RIPEMD160` precompiled contract. +". + +(* At top_level_stmt: unsupported node type: Import *) + +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". + +Axiom ethereum_utils_byte_imports_left_pad_zero_bytes : + IsImported globals "ethereum.utils.byte" "left_pad_zero_bytes". + +Axiom ethereum_utils_numeric_imports_ceil32 : + IsImported globals "ethereum.utils.numeric" "ceil32". + +Axiom ethereum_dao_fork_vm_imports_Evm : + IsImported globals "ethereum.dao_fork.vm" "Evm". + +Axiom ethereum_dao_fork_vm_gas_imports_GAS_RIPEMD160 : + IsImported globals "ethereum.dao_fork.vm.gas" "GAS_RIPEMD160". +Axiom ethereum_dao_fork_vm_gas_imports_GAS_RIPEMD160_WORD : + IsImported globals "ethereum.dao_fork.vm.gas" "GAS_RIPEMD160_WORD". +Axiom ethereum_dao_fork_vm_gas_imports_charge_gas : + IsImported globals "ethereum.dao_fork.vm.gas" "charge_gas". + +Definition ripemd160 : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Writes the ripemd160 hash to output. + + Parameters + ---------- + evm : + The current EVM frame. + " in + let _ := M.assign_local (| + "data" , + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "data" |) + |) in + let _ := M.assign_local (| + "word_count" , + BinOp.floor_div (| + M.call (| + M.get_name (| globals, "ceil32" |), + make_list [ + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_name (| globals, "data" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |), + Constant.int 32 + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + BinOp.add (| + M.get_name (| globals, "GAS_RIPEMD160" |), + BinOp.mult (| + M.get_name (| globals, "GAS_RIPEMD160_WORD" |), + M.get_name (| globals, "word_count" |) + |) + |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "hash_bytes" , + M.call (| + M.get_field (| M.call (| + M.get_field (| M.get_name (| globals, "hashlib" |), "new" |), + make_list [ + Constant.str "ripemd160"; + M.get_name (| globals, "data" |) + ], + make_dict [] + |), "digest" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "padded_hash" , + M.call (| + M.get_name (| globals, "left_pad_zero_bytes" |), + make_list [ + M.get_name (| globals, "hash_bytes" |); + Constant.int 32 + ], + make_dict [] + |) + |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, "evm" |), "output" |), + M.get_name (| globals, "padded_hash" |) + |) in + M.pure Constant.None_)). diff --git a/CoqOfPython/ethereum/dao_fork/vm/precompiled_contracts/sha256.v b/CoqOfPython/ethereum/dao_fork/vm/precompiled_contracts/sha256.v new file mode 100644 index 0000000..69f489f --- /dev/null +++ b/CoqOfPython/ethereum/dao_fork/vm/precompiled_contracts/sha256.v @@ -0,0 +1,106 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.dao_fork.vm.precompiled_contracts.sha256". + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) SHA256 PRECOMPILED CONTRACT +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementation of the `SHA256` precompiled contract. +". + +(* At top_level_stmt: unsupported node type: Import *) + +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". + +Axiom ethereum_utils_numeric_imports_ceil32 : + IsImported globals "ethereum.utils.numeric" "ceil32". + +Axiom ethereum_dao_fork_vm_imports_Evm : + IsImported globals "ethereum.dao_fork.vm" "Evm". + +Axiom ethereum_dao_fork_vm_gas_imports_GAS_SHA256 : + IsImported globals "ethereum.dao_fork.vm.gas" "GAS_SHA256". +Axiom ethereum_dao_fork_vm_gas_imports_GAS_SHA256_WORD : + IsImported globals "ethereum.dao_fork.vm.gas" "GAS_SHA256_WORD". +Axiom ethereum_dao_fork_vm_gas_imports_charge_gas : + IsImported globals "ethereum.dao_fork.vm.gas" "charge_gas". + +Definition sha256 : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Writes the sha256 hash to output. + + Parameters + ---------- + evm : + The current EVM frame. + " in + let _ := M.assign_local (| + "data" , + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "data" |) + |) in + let _ := M.assign_local (| + "word_count" , + BinOp.floor_div (| + M.call (| + M.get_name (| globals, "ceil32" |), + make_list [ + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_name (| globals, "data" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |), + Constant.int 32 + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + BinOp.add (| + M.get_name (| globals, "GAS_SHA256" |), + BinOp.mult (| + M.get_name (| globals, "GAS_SHA256_WORD" |), + M.get_name (| globals, "word_count" |) + |) + |) + ], + make_dict [] + |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, "evm" |), "output" |), + M.call (| + M.get_field (| M.call (| + M.get_field (| M.get_name (| globals, "hashlib" |), "sha256" |), + make_list [ + M.get_name (| globals, "data" |) + ], + make_dict [] + |), "digest" |), + make_list [], + make_dict [] + |) + |) in + M.pure Constant.None_)). diff --git a/CoqOfPython/ethereum/dao_fork/vm/runtime.v b/CoqOfPython/ethereum/dao_fork/vm/runtime.v new file mode 100644 index 0000000..9c619f3 --- /dev/null +++ b/CoqOfPython/ethereum/dao_fork/vm/runtime.v @@ -0,0 +1,157 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.dao_fork.vm.runtime". + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) Runtime Operations +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Runtime related operations used while executing EVM code. +". + +Axiom typing_imports_Set : + IsImported globals "typing" "Set". + +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". + +Axiom ethereum_dao_fork_vm_instructions_imports_Ops : + IsImported globals "ethereum.dao_fork.vm.instructions" "Ops". + +Definition get_valid_jump_destinations : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "code" ] |) in + let _ := Constant.str " + Analyze the evm code to obtain the set of valid jump destinations. + + Valid jump destinations are defined as follows: + * The jump destination is less than the length of the code. + * The jump destination should have the `JUMPDEST` opcode (0x5B). + * The jump destination shouldn't be part of the data corresponding to + `PUSH-N` opcodes. + + Note - Jump destinations are 0-indexed. + + Parameters + ---------- + code : + The EVM code which is to be executed. + + Returns + ------- + valid_jump_destinations: `Set[Uint]` + The set of valid jump destinations in the code. + " in + let _ := M.assign_local (| + "valid_jump_destinations" , + M.call (| + M.get_name (| globals, "set" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "pc" , + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + |) in + let _ := + M.while (| + Compare.lt (| + M.get_name (| globals, "pc" |), + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_name (| globals, "code" |) + ], + make_dict [] + |) + |), + ltac:(M.monadic ( +(* At stmt: unsupported node type: Try *) + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, "current_opcode" |), + M.get_field (| M.get_name (| globals, "Ops" |), "JUMPDEST" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_field (| M.get_name (| globals, "valid_jump_destinations" |), "add" |), + make_list [ + M.get_name (| globals, "pc" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + BoolOp.and (| + Compare.lt_e (| + M.get_field (| M.get_field (| M.get_name (| globals, "Ops" |), "PUSH1" |), "value" |), + M.get_field (| M.get_name (| globals, "current_opcode" |), "value" |) + |), + ltac:(M.monadic ( + Compare.lt_e (| + M.get_field (| M.get_name (| globals, "current_opcode" |), "value" |), + M.get_field (| M.get_field (| M.get_name (| globals, "Ops" |), "PUSH32" |), "value" |) + |) + )) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "push_data_size" , + BinOp.add (| + BinOp.sub (| + M.get_field (| M.get_name (| globals, "current_opcode" |), "value" |), + M.get_field (| M.get_field (| M.get_name (| globals, "Ops" |), "PUSH1" |), "value" |) + |), + Constant.int 1 + |) + |) in + let _ := M.assign_op_local (| + BinOp.add, + "pc", + M.get_name (| globals, "push_data_size" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )) |) in + let _ := M.assign_op_local (| + BinOp.add, + "pc", + Constant.int 1 + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := M.return_ (| + M.get_name (| globals, "valid_jump_destinations" |) + |) in + M.pure Constant.None_)). diff --git a/CoqOfPython/ethereum/dao_fork/vm/stack.v b/CoqOfPython/ethereum/dao_fork/vm/stack.v new file mode 100644 index 0000000..b8cc90b --- /dev/null +++ b/CoqOfPython/ethereum/dao_fork/vm/stack.v @@ -0,0 +1,123 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.dao_fork.vm.stack". + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) Stack +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementation of the stack operators for the EVM. +". + +Axiom typing_imports_List : + IsImported globals "typing" "List". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". + +Axiom ethereum_dao_fork_vm_exceptions_imports_StackOverflowError : + IsImported globals "ethereum.dao_fork.vm.exceptions" "StackOverflowError". +Axiom ethereum_dao_fork_vm_exceptions_imports_StackUnderflowError : + IsImported globals "ethereum.dao_fork.vm.exceptions" "StackUnderflowError". + +Definition pop : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "stack" ] |) in + let _ := Constant.str " + Pops the top item off of `stack`. + + Parameters + ---------- + stack : + EVM stack. + + Returns + ------- + value : `U256` + The top element on the stack. + + " in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_name (| globals, "stack" |) + ], + make_dict [] + |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, "StackUnderflowError" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.return_ (| + M.call (| + M.get_field (| M.get_name (| globals, "stack" |), "pop" |), + make_list [], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Definition push : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "stack"; "value" ] |) in + let _ := Constant.str " + Pushes `value` onto `stack`. + + Parameters + ---------- + stack : + EVM stack. + + value : + Item to be pushed onto `stack`. + + " in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_name (| globals, "stack" |) + ], + make_dict [] + |), + Constant.int 1024 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, "StackOverflowError" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.return_ (| + M.call (| + M.get_field (| M.get_name (| globals, "stack" |), "append" |), + make_list [ + M.get_name (| globals, "value" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). diff --git a/CoqOfPython/ethereum/ethash.v b/CoqOfPython/ethereum/ethash.v new file mode 100644 index 0000000..59371c7 --- /dev/null +++ b/CoqOfPython/ethereum/ethash.v @@ -0,0 +1,1220 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.ethash". + +Definition expr_1 : Value.t := + Constant.str " +Ethash is a proof-of-work algorithm designed to be [ASIC] resistant through +[memory hardness][mem-hard]. + +To achieve memory hardness, computing Ethash requires access to subsets of a +large structure. The particular subsets chosen are based on the nonce and block +header, while the set itself is changed every [`epoch`]. + +At a high level, the Ethash algorithm is as follows: + +1. Create a **seed** value, generated with [`generate_seed`] and based on the + preceding block numbers. +1. From the seed, compute a pseudorandom **cache** with [`generate_cache`]. +1. From the cache, generate a **dataset** with [`generate_dataset`]. The + dataset grows over time based on [`DATASET_EPOCH_GROWTH_SIZE`]. +1. Miners hash slices of the dataset together, which is where the memory + hardness is introduced. Verification of the proof-of-work only requires the + cache to be able to recompute a much smaller subset of the full dataset. + +[`DATASET_EPOCH_GROWTH_SIZE`]: ref:ethereum.ethash.DATASET_EPOCH_GROWTH_SIZE +[`generate_dataset`]: ref:ethereum.ethash.generate_dataset +[`generate_cache`]: ref:ethereum.ethash.generate_cache +[`generate_seed`]: ref:ethereum.ethash.generate_seed +[`epoch`]: ref:ethereum.ethash.epoch +[ASIC]: https://en.wikipedia.org/wiki/Application-specific_integrated_circuit +[mem-hard]: https://en.wikipedia.org/wiki/Memory-hard_function +". + +Axiom typing_imports_Callable : + IsImported globals "typing" "Callable". +Axiom typing_imports_Tuple : + IsImported globals "typing" "Tuple". +Axiom typing_imports_Union : + IsImported globals "typing" "Union". + +Axiom ethereum_base_types_imports_U32 : + IsImported globals "ethereum.base_types" "U32". +Axiom ethereum_base_types_imports_Bytes8 : + IsImported globals "ethereum.base_types" "Bytes8". +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". + +Axiom ethereum_crypto_hash_imports_Hash32 : + IsImported globals "ethereum.crypto.hash" "Hash32". +Axiom ethereum_crypto_hash_imports_Hash64 : + IsImported globals "ethereum.crypto.hash" "Hash64". +Axiom ethereum_crypto_hash_imports_keccak256 : + IsImported globals "ethereum.crypto.hash" "keccak256". +Axiom ethereum_crypto_hash_imports_keccak512 : + IsImported globals "ethereum.crypto.hash" "keccak512". + +Axiom ethereum_utils_numeric_imports_is_prime : + IsImported globals "ethereum.utils.numeric" "is_prime". +Axiom ethereum_utils_numeric_imports_le_bytes_to_uint32_sequence : + IsImported globals "ethereum.utils.numeric" "le_bytes_to_uint32_sequence". +Axiom ethereum_utils_numeric_imports_le_uint32_sequence_to_bytes : + IsImported globals "ethereum.utils.numeric" "le_uint32_sequence_to_bytes". +Axiom ethereum_utils_numeric_imports_le_uint32_sequence_to_uint : + IsImported globals "ethereum.utils.numeric" "le_uint32_sequence_to_uint". + +Definition EPOCH_SIZE : Value.t := M.run ltac:(M.monadic ( + Constant.int 30000 +)). + +Definition expr_41 : Value.t := + Constant.str " +Number of blocks before a dataset needs to be regenerated (known as an +""epoch"".) See [`epoch`]. + +[`epoch`]: ref:ethereum.ethash.epoch +". + +Definition INITIAL_CACHE_SIZE : Value.t := M.run ltac:(M.monadic ( + BinOp.pow (| + Constant.int 2, + Constant.int 24 + |) +)). + +Definition expr_49 : Value.t := + Constant.str " +Size of the cache (in bytes) during the first epoch. Each subsequent epoch's +cache roughly grows by [`CACHE_EPOCH_GROWTH_SIZE`] bytes. See [`cache_size`]. + +[`CACHE_EPOCH_GROWTH_SIZE`]: ref:ethereum.ethash.CACHE_EPOCH_GROWTH_SIZE +[`cache_size`]: ref:ethereum.ethash.cache_size +". + +Definition CACHE_EPOCH_GROWTH_SIZE : Value.t := M.run ltac:(M.monadic ( + BinOp.pow (| + Constant.int 2, + Constant.int 17 + |) +)). + +Definition expr_58 : Value.t := + Constant.str " +After the first epoch, the cache size grows by roughly this amount. See +[`cache_size`]. + +[`cache_size`]: ref:ethereum.ethash.cache_size +". + +Definition INITIAL_DATASET_SIZE : Value.t := M.run ltac:(M.monadic ( + BinOp.pow (| + Constant.int 2, + Constant.int 30 + |) +)). + +Definition expr_66 : Value.t := + Constant.str " +Size of the dataset (in bytes) during the first epoch. Each subsequent epoch's +dataset roughly grows by [`DATASET_EPOCH_GROWTH_SIZE`] bytes. See +[`dataset_size`]. + +[`DATASET_EPOCH_GROWTH_SIZE`]: ref:ethereum.ethash.DATASET_EPOCH_GROWTH_SIZE +[`dataset_size`]: ref:ethereum.ethash.dataset_size +". + +Definition DATASET_EPOCH_GROWTH_SIZE : Value.t := M.run ltac:(M.monadic ( + BinOp.pow (| + Constant.int 2, + Constant.int 23 + |) +)). + +Definition expr_76 : Value.t := + Constant.str " +After the first epoch, the dataset size grows by roughly this amount. See +[`dataset_size`]. + +[`dataset_size`]: ref:ethereum.ethash.dataset_size +". + +Definition HASH_BYTES : Value.t := M.run ltac:(M.monadic ( + Constant.int 64 +)). + +Definition expr_84 : Value.t := + Constant.str " +Length of a hash, in bytes. +". + +Definition MIX_BYTES : Value.t := M.run ltac:(M.monadic ( + Constant.int 128 +)). + +Definition expr_89 : Value.t := + Constant.str " +Width of mix, in bytes. See [`generate_dataset_item`]. + +[`generate_dataset_item`]: ref:ethereum.ethash.generate_dataset_item +". + +Definition CACHE_ROUNDS : Value.t := M.run ltac:(M.monadic ( + Constant.int 3 +)). + +Definition expr_96 : Value.t := + Constant.str " +Number of times to repeat the [`keccak512`] step while generating the hash. See +[`generate_cache`]. + +[`keccak512`]: ref:ethereum.crypto.hash.keccak512 +[`generate_cache`]: ref:ethereum.ethash.generate_cache +". + +Definition DATASET_PARENTS : Value.t := M.run ltac:(M.monadic ( + Constant.int 256 +)). + +Definition expr_105 : Value.t := + Constant.str " +Number of parents of each dataset element. See [`generate_dataset_item`]. + +[`generate_dataset_item`]: ref:ethereum.ethash.generate_dataset_item +". + +Definition HASHIMOTO_ACCESSES : Value.t := M.run ltac:(M.monadic ( + Constant.int 64 +)). + +Definition expr_112 : Value.t := + Constant.str " +Number of accesses in the [`hashimoto`] loop. + +[`hashimoto`]: ref:ethereum.ethash.hashimoto +". + +Definition epoch : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "block_number" ] |) in + let _ := Constant.str " + Obtain the epoch number to which the block identified by `block_number` + belongs. The first epoch is numbered zero. + + An Ethash epoch is a fixed number of blocks ([`EPOCH_SIZE`]) long, during + which the dataset remains constant. At the end of each epoch, the dataset + is generated anew. See [`generate_dataset`]. + + [`EPOCH_SIZE`]: ref:ethereum.ethash.EPOCH_SIZE + [`generate_dataset`]: ref:ethereum.ethash.generate_dataset + " in + let _ := M.return_ (| + BinOp.floor_div (| + M.get_name (| globals, "block_number" |), + M.get_name (| globals, "EPOCH_SIZE" |) + |) + |) in + M.pure Constant.None_)). + +Definition cache_size : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "block_number" ] |) in + let _ := Constant.str " + Obtain the cache size (in bytes) of the epoch to which `block_number` + belongs. + + See [`INITIAL_CACHE_SIZE`] and [`CACHE_EPOCH_GROWTH_SIZE`] for the initial + size and linear growth rate, respectively. The cache is generated in + [`generate_cache`]. + + The actual cache size is smaller than simply multiplying + `CACHE_EPOCH_GROWTH_SIZE` by the epoch number to minimize the risk of + unintended cyclic behavior. It is defined as the highest prime number below + what linear growth would calculate. + + [`INITIAL_CACHE_SIZE`]: ref:ethereum.ethash.INITIAL_CACHE_SIZE + [`CACHE_EPOCH_GROWTH_SIZE`]: ref:ethereum.ethash.CACHE_EPOCH_GROWTH_SIZE + [`generate_cache`]: ref:ethereum.ethash.generate_cache + " in + let _ := M.assign_local (| + "size" , + BinOp.add (| + M.get_name (| globals, "INITIAL_CACHE_SIZE" |), + BinOp.mult (| + M.get_name (| globals, "CACHE_EPOCH_GROWTH_SIZE" |), + M.call (| + M.get_name (| globals, "epoch" |), + make_list [ + M.get_name (| globals, "block_number" |) + ], + make_dict [] + |) + |) + |) + |) in + let _ := M.assign_op_local (| + BinOp.sub, + "size", + M.get_name (| globals, "HASH_BYTES" |) + |) in + let _ := + M.while (| + UnOp.not (| M.call (| + M.get_name (| globals, "is_prime" |), + make_list [ + BinOp.floor_div (| + M.get_name (| globals, "size" |), + M.get_name (| globals, "HASH_BYTES" |) + |) + ], + make_dict [] + |) |), + ltac:(M.monadic ( + let _ := M.assign_op_local (| + BinOp.sub, + "size", + BinOp.mult (| + Constant.int 2, + M.get_name (| globals, "HASH_BYTES" |) + |) + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := M.return_ (| + M.get_name (| globals, "size" |) + |) in + M.pure Constant.None_)). + +Definition dataset_size : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "block_number" ] |) in + let _ := Constant.str " + Obtain the dataset size (in bytes) of the epoch to which `block_number` + belongs. + + See [`INITIAL_DATASET_SIZE`] and [`DATASET_EPOCH_GROWTH_SIZE`][ds] for the + initial size and linear growth rate, respectively. The complete dataset is + generated in [`generate_dataset`], while the slices used in verification + are generated in [`generate_dataset_item`]. + + The actual dataset size is smaller than simply multiplying + `DATASET_EPOCH_GROWTH_SIZE` by the epoch number to minimize the risk of + unintended cyclic behavior. It is defined as the highest prime number below + what linear growth would calculate. + + [`INITIAL_DATASET_SIZE`]: ref:ethereum.ethash.INITIAL_DATASET_SIZE + [ds]: ref:ethereum.ethash.DATASET_EPOCH_GROWTH_SIZE + [`generate_dataset`]: ref:ethereum.ethash.generate_dataset + [`generate_dataset_item`]: ref:ethereum.ethash.generate_dataset_item + " in + let _ := M.assign_local (| + "size" , + BinOp.add (| + M.get_name (| globals, "INITIAL_DATASET_SIZE" |), + BinOp.mult (| + M.get_name (| globals, "DATASET_EPOCH_GROWTH_SIZE" |), + M.call (| + M.get_name (| globals, "epoch" |), + make_list [ + M.get_name (| globals, "block_number" |) + ], + make_dict [] + |) + |) + |) + |) in + let _ := M.assign_op_local (| + BinOp.sub, + "size", + M.get_name (| globals, "MIX_BYTES" |) + |) in + let _ := + M.while (| + UnOp.not (| M.call (| + M.get_name (| globals, "is_prime" |), + make_list [ + BinOp.floor_div (| + M.get_name (| globals, "size" |), + M.get_name (| globals, "MIX_BYTES" |) + |) + ], + make_dict [] + |) |), + ltac:(M.monadic ( + let _ := M.assign_op_local (| + BinOp.sub, + "size", + BinOp.mult (| + Constant.int 2, + M.get_name (| globals, "MIX_BYTES" |) + |) + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := M.return_ (| + M.get_name (| globals, "size" |) + |) in + M.pure Constant.None_)). + +Definition generate_seed : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "block_number" ] |) in + let _ := Constant.str " + Obtain the cache generation seed for the block identified by + `block_number`. See [`generate_cache`]. + + [`generate_cache`]: ref:ethereum.ethash.generate_cache + " in + let _ := M.assign_local (| + "epoch_number" , + M.call (| + M.get_name (| globals, "epoch" |), + make_list [ + M.get_name (| globals, "block_number" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "seed" , + BinOp.mult (| + Constant.bytes "00", + Constant.int 32 + |) + |) in + let _ := + M.while (| + Compare.not_eq (| + M.get_name (| globals, "epoch_number" |), + Constant.int 0 + |), + ltac:(M.monadic ( + let _ := M.assign_local (| + "seed" , + M.call (| + M.get_name (| globals, "keccak256" |), + make_list [ + M.get_name (| globals, "seed" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_op_local (| + BinOp.sub, + "epoch_number", + Constant.int 1 + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, "Hash32" |), + make_list [ + M.get_name (| globals, "seed" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Definition generate_cache : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "block_number" ] |) in + let _ := Constant.str " + Generate the cache for the block identified by `block_number`. See + [`generate_dataset`] for how the cache is used. + + The cache is generated in two steps: filling the array with a chain of + [`keccak512`] hashes, then running two rounds of Sergio Demian Lerner's + [RandMemoHash] on those bytes. + + [`keccak512`]: ref:ethereum.crypto.hash.keccak512 + [`generate_dataset`]: ref:ethereum.ethash.generate_dataset + [RandMemoHash]: http://www.hashcash.org/papers/memohash.pdf + " in + let _ := M.assign_local (| + "seed" , + M.call (| + M.get_name (| globals, "generate_seed" |), + make_list [ + M.get_name (| globals, "block_number" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "cache_size_bytes" , + M.call (| + M.get_name (| globals, "cache_size" |), + make_list [ + M.get_name (| globals, "block_number" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "cache_size_words" , + BinOp.floor_div (| + M.get_name (| globals, "cache_size_bytes" |), + M.get_name (| globals, "HASH_BYTES" |) + |) + |) in + let _ := M.assign_local (| + "cache" , + make_list [ + M.call (| + M.get_name (| globals, "keccak512" |), + make_list [ + M.get_name (| globals, "seed" |) + ], + make_dict [] + |) + ] + |) in + let _ := + M.for_ (| + M.get_name (| globals, "index" |), + M.call (| + M.get_name (| globals, "range" |), + make_list [ + Constant.int 1; + M.get_name (| globals, "cache_size_words" |) + ], + make_dict [] + |), + ltac:(M.monadic ( + let _ := M.assign_local (| + "cache_item" , + M.call (| + M.get_name (| globals, "keccak512" |), + make_list [ + M.get_subscript (| + M.get_name (| globals, "cache" |), + BinOp.sub (| + M.get_name (| globals, "index" |), + Constant.int 1 + |) + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_field (| M.get_name (| globals, "cache" |), "append" |), + make_list [ + M.get_name (| globals, "cache_item" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := + M.for_ (| + M.get_name (| globals, "_" |), + M.call (| + M.get_name (| globals, "range" |), + make_list [ + M.get_name (| globals, "CACHE_ROUNDS" |) + ], + make_dict [] + |), + ltac:(M.monadic ( + let _ := + M.for_ (| + M.get_name (| globals, "index" |), + M.call (| + M.get_name (| globals, "range" |), + make_list [ + M.get_name (| globals, "cache_size_words" |) + ], + make_dict [] + |), + ltac:(M.monadic ( + let _ := M.assign_local (| + "first_cache_item" , + M.get_subscript (| + M.get_name (| globals, "cache" |), + BinOp.mod_ (| + BinOp.add (| + BinOp.sub (| + M.get_name (| globals, "index" |), + Constant.int 1 + |), + M.call (| + M.get_name (| globals, "int" |), + make_list [ + M.get_name (| globals, "cache_size_words" |) + ], + make_dict [] + |) + |), + M.get_name (| globals, "cache_size_words" |) + |) + |) + |) in + let _ := M.assign_local (| + "second_cache_item" , + M.get_subscript (| + M.get_name (| globals, "cache" |), + BinOp.mod_ (| + M.call (| + M.get_field (| M.get_name (| globals, "U32" |), "from_le_bytes" |), + make_list [ + M.slice (| + M.get_subscript (| + M.get_name (| globals, "cache" |), + M.get_name (| globals, "index" |) + |), + Constant.int 0, + Constant.int 4, + Constant.None_ + |) + ], + make_dict [] + |), + M.get_name (| globals, "cache_size_words" |) + |) + |) + |) in + let _ := M.assign_local (| + "result" , + M.call (| + M.get_name (| globals, "bytes" |), + make_list [ + Constant.str "(* At expr: unsupported node type: ListComp *)" + ], + make_dict [] + |) + |) in + let _ := M.assign (| + M.get_subscript (| + M.get_name (| globals, "cache" |), + M.get_name (| globals, "index" |) + |), + M.call (| + M.get_name (| globals, "keccak512" |), + make_list [ + M.get_name (| globals, "result" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, "tuple" |), + make_list [ + Constant.str "(* At expr: unsupported node type: GeneratorExp *)" + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Definition fnv : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "a"; "b" ] |) in + let _ := Constant.str " + A non-associative substitute for XOR, inspired by the [FNV] hash by Fowler, + Noll, and Vo. See [`fnv_hash`], [`generate_dataset_item`], and + [`hashimoto`]. + + Note that here we multiply the prime with the full 32-bit input, in + contrast with the [FNV-1] spec which multiplies the prime with one byte + (octet) in turn. + + [`hashimoto`]: ref:ethereum.ethash.hashimoto + [`generate_dataset_item`]: ref:ethereum.ethash.generate_dataset_item + [`fnv_hash`]: ref:ethereum.ethash.fnv_hash + [FNV]: https://w.wiki/XKZ + [FNV-1]: http://www.isthe.com/chongo/tech/comp/fnv/#FNV-1 + " in + let _ := M.assign_local (| + "result" , + BinOp.bit_and (| + BinOp.bit_xor (| + BinOp.mult (| + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.get_name (| globals, "a" |) + ], + make_dict [] + |), + Constant.int 16777619 + |), + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.get_name (| globals, "b" |) + ], + make_dict [] + |) + |), + M.get_field (| M.get_name (| globals, "U32" |), "MAX_VALUE" |) + |) + |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, "U32" |), + make_list [ + M.get_name (| globals, "result" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Definition fnv_hash : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "mix_integers"; "data" ] |) in + let _ := Constant.str " + Combines `data` into `mix_integers` using [`fnv`]. See [`hashimoto`] and + [`generate_dataset_item`]. + + [`hashimoto`]: ref:ethereum.ethash.hashimoto + [`generate_dataset_item`]: ref:ethereum.ethash.generate_dataset_item + [`fnv`]: ref:ethereum.ethash.fnv + " in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, "tuple" |), + make_list [ + Constant.str "(* At expr: unsupported node type: GeneratorExp *)" + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Definition generate_dataset_item : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "cache"; "index" ] |) in + let _ := Constant.str " + Generate a particular dataset item 0-indexed by `index` by hashing + pseudorandomly-selected entries from `cache` together. See [`fnv`] and + [`fnv_hash`] for the digest function, [`generate_cache`] for generating + `cache`, and [`generate_dataset`] for the full dataset generation + algorithm. + + [`fnv`]: ref:ethereum.ethash.fnv + [`fnv_hash`]: ref:ethereum.ethash.fnv_hash + [`generate_dataset`]: ref:ethereum.ethash.generate_dataset + [`generate_cache`]: ref:ethereum.ethash.generate_cache + " in + let _ := M.assign_local (| + "mix" , + M.call (| + M.get_name (| globals, "keccak512" |), + make_list [ + M.call (| + M.get_field (| BinOp.bit_xor (| + M.call (| + M.get_name (| globals, "le_uint32_sequence_to_uint" |), + make_list [ + M.get_subscript (| + M.get_name (| globals, "cache" |), + BinOp.mod_ (| + M.get_name (| globals, "index" |), + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_name (| globals, "cache" |) + ], + make_dict [] + |) + |) + |) + ], + make_dict [] + |), + M.get_name (| globals, "index" |) + |), "to_le_bytes" |), + make_list [], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "mix_integers" , + M.call (| + M.get_name (| globals, "le_bytes_to_uint32_sequence" |), + make_list [ + M.get_name (| globals, "mix" |) + ], + make_dict [] + |) + |) in + let _ := + M.for_ (| + M.get_name (| globals, "j" |), + M.call (| + M.get_name (| globals, "range" |), + make_list [ + M.get_name (| globals, "DATASET_PARENTS" |) + ], + make_dict [] + |), + ltac:(M.monadic ( +(* At stmt: unsupported node type: AnnAssign *) + let _ := M.assign_local (| + "cache_index" , + BinOp.mod_ (| + M.call (| + M.get_name (| globals, "fnv" |), + make_list [ + BinOp.bit_xor (| + M.get_name (| globals, "index" |), + M.get_name (| globals, "j" |) + |); + M.get_name (| globals, "mix_word" |) + ], + make_dict [] + |), + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_name (| globals, "cache" |) + ], + make_dict [] + |) + |) + |) in + let _ := M.assign_local (| + "parent" , + M.get_subscript (| + M.get_name (| globals, "cache" |), + M.get_name (| globals, "cache_index" |) + |) + |) in + let _ := M.assign_local (| + "mix_integers" , + M.call (| + M.get_name (| globals, "fnv_hash" |), + make_list [ + M.get_name (| globals, "mix_integers" |); + M.get_name (| globals, "parent" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := M.assign_local (| + "mix" , + M.call (| + M.get_name (| globals, "Hash64" |), + make_list [ + M.call (| + M.get_name (| globals, "le_uint32_sequence_to_bytes" |), + make_list [ + M.get_name (| globals, "mix_integers" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, "keccak512" |), + make_list [ + M.get_name (| globals, "mix" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Definition generate_dataset : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "block_number" ] |) in + let _ := Constant.str " + Generate the full dataset for the block identified by `block_number`. + + This function is present only for demonstration purposes. It is not used + while validating blocks. + " in +(* At stmt: unsupported node type: AnnAssign *) +(* At stmt: unsupported node type: AnnAssign *) + let _ := M.return_ (| + M.call (| + M.get_name (| globals, "tuple" |), + make_list [ + Constant.str "(* At expr: unsupported node type: GeneratorExp *)" + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Definition hashimoto : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "header_hash"; "nonce"; "dataset_size"; "fetch_dataset_item" ] |) in + let _ := Constant.str " + Obtain the mix digest and the final value for a header, by aggregating + data from the full dataset. + + #### Parameters + + - `header_hash` is a valid [RLP hash] of a block header. + - `nonce` is the propagated nonce for the given block. + - `dataset_size` is the size of the dataset. See [`dataset_size`]. + - `fetch_dataset_item` is a function that retrieves a specific dataset item + based on its index. + + #### Returns + + - The mix digest generated from the header hash and propagated nonce. + - The final result obtained which will be checked for leading zeros (in + byte representation) in correspondence with the block difficulty. + + [RLP hash]: ref:ethereum.rlp.rlp_hash + [`dataset_size`]: ref:ethereum.ethash.dataset_size + " in + let _ := M.assign_local (| + "nonce_le" , + M.call (| + M.get_name (| globals, "bytes" |), + make_list [ + M.call (| + M.get_name (| globals, "reversed" |), + make_list [ + M.get_name (| globals, "nonce" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "seed_hash" , + M.call (| + M.get_name (| globals, "keccak512" |), + make_list [ + BinOp.add (| + M.get_name (| globals, "header_hash" |), + M.get_name (| globals, "nonce_le" |) + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "seed_head" , + M.call (| + M.get_field (| M.get_name (| globals, "U32" |), "from_le_bytes" |), + make_list [ + M.slice (| + M.get_name (| globals, "seed_hash" |), + Constant.None_, + Constant.int 4, + Constant.None_ + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "rows" , + BinOp.floor_div (| + M.get_name (| globals, "dataset_size" |), + Constant.int 128 + |) + |) in + let _ := M.assign_local (| + "mix" , + BinOp.mult (| + M.call (| + M.get_name (| globals, "le_bytes_to_uint32_sequence" |), + make_list [ + M.get_name (| globals, "seed_hash" |) + ], + make_dict [] + |), + BinOp.floor_div (| + M.get_name (| globals, "MIX_BYTES" |), + M.get_name (| globals, "HASH_BYTES" |) + |) + |) + |) in + let _ := + M.for_ (| + M.get_name (| globals, "i" |), + M.call (| + M.get_name (| globals, "range" |), + make_list [ + M.get_name (| globals, "HASHIMOTO_ACCESSES" |) + ], + make_dict [] + |), + ltac:(M.monadic ( +(* At stmt: unsupported node type: AnnAssign *) + let _ := M.assign_local (| + "parent" , + BinOp.mod_ (| + M.call (| + M.get_name (| globals, "fnv" |), + make_list [ + BinOp.bit_xor (| + M.get_name (| globals, "i" |), + M.get_name (| globals, "seed_head" |) + |); + M.get_subscript (| + M.get_name (| globals, "mix" |), + BinOp.mod_ (| + M.get_name (| globals, "i" |), + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_name (| globals, "mix" |) + ], + make_dict [] + |) + |) + |) + ], + make_dict [] + |), + M.get_name (| globals, "rows" |) + |) + |) in + let _ := + M.for_ (| + M.get_name (| globals, "j" |), + M.call (| + M.get_name (| globals, "range" |), + make_list [ + BinOp.floor_div (| + M.get_name (| globals, "MIX_BYTES" |), + M.get_name (| globals, "HASH_BYTES" |) + |) + ], + make_dict [] + |), + ltac:(M.monadic ( + let _ := M.assign_op_local (| + BinOp.add, + "new_data", + M.call (| + M.get_name (| globals, "fetch_dataset_item" |), + make_list [ + BinOp.add (| + BinOp.mult (| + Constant.int 2, + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.get_name (| globals, "parent" |) + ], + make_dict [] + |) + |), + M.get_name (| globals, "j" |) + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := M.assign_local (| + "mix" , + M.call (| + M.get_name (| globals, "fnv_hash" |), + make_list [ + M.get_name (| globals, "mix" |); + M.get_name (| globals, "new_data" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := M.assign_local (| + "compressed_mix" , + make_list [] + |) in + let _ := + M.for_ (| + M.get_name (| globals, "i" |), + M.call (| + M.get_name (| globals, "range" |), + make_list [ + Constant.int 0; + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_name (| globals, "mix" |) + ], + make_dict [] + |); + Constant.int 4 + ], + make_dict [] + |), + ltac:(M.monadic ( + let _ := M.call (| + M.get_field (| M.get_name (| globals, "compressed_mix" |), "append" |), + make_list [ + M.call (| + M.get_name (| globals, "fnv" |), + make_list [ + M.call (| + M.get_name (| globals, "fnv" |), + make_list [ + M.call (| + M.get_name (| globals, "fnv" |), + make_list [ + M.get_subscript (| + M.get_name (| globals, "mix" |), + M.get_name (| globals, "i" |) + |); + M.get_subscript (| + M.get_name (| globals, "mix" |), + BinOp.add (| + M.get_name (| globals, "i" |), + Constant.int 1 + |) + |) + ], + make_dict [] + |); + M.get_subscript (| + M.get_name (| globals, "mix" |), + BinOp.add (| + M.get_name (| globals, "i" |), + Constant.int 2 + |) + |) + ], + make_dict [] + |); + M.get_subscript (| + M.get_name (| globals, "mix" |), + BinOp.add (| + M.get_name (| globals, "i" |), + Constant.int 3 + |) + |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := M.assign_local (| + "mix_digest" , + M.call (| + M.get_name (| globals, "le_uint32_sequence_to_bytes" |), + make_list [ + M.get_name (| globals, "compressed_mix" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "result" , + M.call (| + M.get_name (| globals, "keccak256" |), + make_list [ + BinOp.add (| + M.get_name (| globals, "seed_hash" |), + M.get_name (| globals, "mix_digest" |) + |) + ], + make_dict [] + |) + |) in + let _ := M.return_ (| + make_tuple [ M.get_name (| globals, "mix_digest" |); M.get_name (| globals, "result" |) ] + |) in + M.pure Constant.None_)). + +Definition hashimoto_light : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "header_hash"; "nonce"; "cache"; "dataset_size" ] |) in + let _ := Constant.str " + Run the [`hashimoto`] algorithm by generating dataset item using the cache + instead of loading the full dataset into main memory. + + #### Parameters + + - `header_hash` is a valid [RLP hash] of a block header. + - `nonce` is the propagated nonce for the given block. + - `cache` is the cache generated by [`generate_cache`]. + - `dataset_size` is the size of the dataset. See [`dataset_size`]. + + #### Returns + + - The mix digest generated from the header hash and propagated nonce. + - The final result obtained which will be checked for leading zeros (in + byte representation) in correspondence with the block difficulty. + + [RLP hash]: ref:ethereum.rlp.rlp_hash + [`dataset_size`]: ref:ethereum.ethash.dataset_size + [`generate_cache`]: ref:ethereum.ethash.generate_cache + [`hashimoto`]: ref:ethereum.ethash.hashimoto + " in +(* At stmt: unsupported node type: FunctionDef *) + let _ := M.return_ (| + M.call (| + M.get_name (| globals, "hashimoto" |), + make_list [ + M.get_name (| globals, "header_hash" |); + M.get_name (| globals, "nonce" |); + M.get_name (| globals, "dataset_size" |); + M.get_name (| globals, "fetch_dataset_item" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). diff --git a/CoqOfPython/ethereum/exceptions.v b/CoqOfPython/ethereum/exceptions.v new file mode 100644 index 0000000..275bc32 --- /dev/null +++ b/CoqOfPython/ethereum/exceptions.v @@ -0,0 +1,58 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.exceptions". + +Definition expr_1 : Value.t := + Constant.str " +Exceptions +^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +The Ethereum specification exception classes. +". + +Definition EthereumException : Value.t := + builtins.make_klass + [(globals, "Exception")] + [ + + ] + [ + + ]. + +Definition InvalidBlock : Value.t := + builtins.make_klass + [(globals, "EthereumException")] + [ + + ] + [ + + ]. + +Definition RLPDecodingError : Value.t := + builtins.make_klass + [(globals, "InvalidBlock")] + [ + + ] + [ + + ]. + +Definition RLPEncodingError : Value.t := + builtins.make_klass + [(globals, "EthereumException")] + [ + + ] + [ + + ]. diff --git a/CoqOfPython/ethereum/fork_criteria.v b/CoqOfPython/ethereum/fork_criteria.v new file mode 100644 index 0000000..b4e814f --- /dev/null +++ b/CoqOfPython/ethereum/fork_criteria.v @@ -0,0 +1,273 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.fork_criteria". + +Definition expr_1 : Value.t := + Constant.str " +Fork Criteria +^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Classes for specifying criteria for Mainnet forks. +". + +(* At top_level_stmt: unsupported node type: Import *) + +Axiom abc_imports_ABC : + IsImported globals "abc" "ABC". +Axiom abc_imports_abstractmethod : + IsImported globals "abc" "abstractmethod". + +Axiom typing_imports_Final : + IsImported globals "typing" "Final". +Axiom typing_imports_Tuple : + IsImported globals "typing" "Tuple". + +Definition ForkCriteria : Value.t := + builtins.make_klass + [(globals, "ABC")] + [ + + ] + [ + ( + "__eq__", + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "self"; "other" ] |) in + let _ := Constant.str " + Equality for fork criteria. + " in + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, "isinstance" |), + make_list [ + M.get_name (| globals, "other" |); + M.get_name (| globals, "ForkCriteria" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + Compare.eq (| + M.get_field (| M.get_name (| globals, "self" |), "_internal" |), + M.get_field (| M.get_name (| globals, "other" |), "_internal" |) + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.return_ (| + M.get_name (| globals, "NotImplemented" |) + |) in + M.pure Constant.None_)) + ); + ( + "__lt__", + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "self"; "other" ] |) in + let _ := Constant.str " + Ordering for fork criteria. Block number forks are before timestamp + forks and scheduled forks are before unscheduled forks. + " in + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, "isinstance" |), + make_list [ + M.get_name (| globals, "other" |); + M.get_name (| globals, "ForkCriteria" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + Compare.lt (| + M.get_field (| M.get_name (| globals, "self" |), "_internal" |), + M.get_field (| M.get_name (| globals, "other" |), "_internal" |) + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.return_ (| + M.get_name (| globals, "NotImplemented" |) + |) in + M.pure Constant.None_)) + ); + ( + "__hash__", + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "self" ] |) in + let _ := Constant.str " + `ForkCriteria` is hashable, so it can be stored in dictionaries. + " in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, "hash" |), + make_list [ + M.get_field (| M.get_name (| globals, "self" |), "_internal" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)) + ) + ]. + +Definition ByBlockNumber : Value.t := + builtins.make_klass + [(globals, "ForkCriteria")] + [ + + ] + [ + ( + "__init__", + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "self"; "block_number" ] |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, "self" |), "_internal" |), + make_tuple [ M.get_field (| M.get_name (| globals, "ForkCriteria" |), "BLOCK_NUMBER" |); M.get_name (| globals, "block_number" |) ] + |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, "self" |), "block_number" |), + M.get_name (| globals, "block_number" |) + |) in + M.pure Constant.None_)) + ); + ( + "check", + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "self"; "block_number"; "timestamp" ] |) in + let _ := Constant.str " + Check whether the block number has been reached. + " in + let _ := M.return_ (| + Compare.gt_e (| + M.get_name (| globals, "block_number" |), + M.get_field (| M.get_name (| globals, "self" |), "block_number" |) + |) + |) in + M.pure Constant.None_)) + ); + ( + "__repr__", + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "self" ] |) in + let _ := Constant.str " + String representation of this object. + " in + let _ := M.return_ (| + Constant.str "(* At expr: unsupported node type: JoinedStr *)" + |) in + M.pure Constant.None_)) + ) + ]. + +Definition ByTimestamp : Value.t := + builtins.make_klass + [(globals, "ForkCriteria")] + [ + + ] + [ + ( + "__init__", + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "self"; "timestamp" ] |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, "self" |), "_internal" |), + make_tuple [ M.get_field (| M.get_name (| globals, "ForkCriteria" |), "TIMESTAMP" |); M.get_name (| globals, "timestamp" |) ] + |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, "self" |), "timestamp" |), + M.get_name (| globals, "timestamp" |) + |) in + M.pure Constant.None_)) + ); + ( + "check", + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "self"; "block_number"; "timestamp" ] |) in + let _ := Constant.str " + Check whether the timestamp has been reached. + " in + let _ := M.return_ (| + Compare.gt_e (| + M.get_name (| globals, "timestamp" |), + M.get_field (| M.get_name (| globals, "self" |), "timestamp" |) + |) + |) in + M.pure Constant.None_)) + ); + ( + "__repr__", + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "self" ] |) in + let _ := Constant.str " + String representation of this object. + " in + let _ := M.return_ (| + Constant.str "(* At expr: unsupported node type: JoinedStr *)" + |) in + M.pure Constant.None_)) + ) + ]. + +Definition Unscheduled : Value.t := + builtins.make_klass + [(globals, "ForkCriteria")] + [ + + ] + [ + ( + "__init__", + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "self" ] |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, "self" |), "_internal" |), + make_tuple [ M.get_field (| M.get_name (| globals, "ForkCriteria" |), "UNSCHEDULED" |); Constant.int 0 ] + |) in + M.pure Constant.None_)) + ); + ( + "check", + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "self"; "block_number"; "timestamp" ] |) in + let _ := Constant.str " + Unscheduled forks never occur. + " in + let _ := M.return_ (| + Constant.bool false + |) in + M.pure Constant.None_)) + ); + ( + "__repr__", + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "self" ] |) in + let _ := Constant.str " + String representation of this object. + " in + let _ := M.return_ (| + Constant.str "Unscheduled()" + |) in + M.pure Constant.None_)) + ) + ]. diff --git a/CoqOfPython/ethereum/frontier/__init__.v b/CoqOfPython/ethereum/frontier/__init__.v new file mode 100644 index 0000000..e30d7e8 --- /dev/null +++ b/CoqOfPython/ethereum/frontier/__init__.v @@ -0,0 +1,21 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.frontier.__init__". + +Definition expr_1 : Value.t := + Constant.str " +Frontier is the first production-ready iteration of the Ethereum protocol. +". + +Axiom ethereum_fork_criteria_imports_ByBlockNumber : + IsImported globals "ethereum.fork_criteria" "ByBlockNumber". + +Definition FORK_CRITERIA : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "ByBlockNumber" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) +)). diff --git a/CoqOfPython/ethereum/frontier/blocks.v b/CoqOfPython/ethereum/frontier/blocks.v new file mode 100644 index 0000000..69e273c --- /dev/null +++ b/CoqOfPython/ethereum/frontier/blocks.v @@ -0,0 +1,87 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.frontier.blocks". + +Definition expr_1 : Value.t := + Constant.str " +A `Block` is a single link in the chain that is Ethereum. Each `Block` contains +a `Header` and zero or more transactions. Each `Header` contains associated +metadata like the block number, parent block hash, and how much gas was +consumed by its transactions. + +Together, these blocks form a cryptographically secure journal recording the +history of all state transitions that have happened since the genesis of the +chain. +". + +Axiom dataclasses_imports_dataclass : + IsImported globals "dataclasses" "dataclass". + +Axiom typing_imports_Tuple : + IsImported globals "typing" "Tuple". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_Bytes : + IsImported globals "ethereum.base_types" "Bytes". +Axiom ethereum_base_types_imports_Bytes8 : + IsImported globals "ethereum.base_types" "Bytes8". +Axiom ethereum_base_types_imports_Bytes32 : + IsImported globals "ethereum.base_types" "Bytes32". +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". +Axiom ethereum_base_types_imports_slotted_freezable : + IsImported globals "ethereum.base_types" "slotted_freezable". + +Axiom ethereum_crypto_hash_imports_Hash32 : + IsImported globals "ethereum.crypto.hash" "Hash32". + +Axiom ethereum_frontier_fork_types_imports_Address : + IsImported globals "ethereum.frontier.fork_types" "Address". +Axiom ethereum_frontier_fork_types_imports_Bloom : + IsImported globals "ethereum.frontier.fork_types" "Bloom". +Axiom ethereum_frontier_fork_types_imports_Root : + IsImported globals "ethereum.frontier.fork_types" "Root". + +Axiom ethereum_frontier_transactions_imports_Transaction : + IsImported globals "ethereum.frontier.transactions" "Transaction". + +Definition Header : Value.t := + builtins.make_klass + [] + [ + + ] + [ + + ]. + +Definition Block : Value.t := + builtins.make_klass + [] + [ + + ] + [ + + ]. + +Definition Log : Value.t := + builtins.make_klass + [] + [ + + ] + [ + + ]. + +Definition Receipt : Value.t := + builtins.make_klass + [] + [ + + ] + [ + + ]. diff --git a/CoqOfPython/ethereum/frontier/bloom.v b/CoqOfPython/ethereum/frontier/bloom.v new file mode 100644 index 0000000..c2d4fc3 --- /dev/null +++ b/CoqOfPython/ethereum/frontier/bloom.v @@ -0,0 +1,207 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.frontier.bloom". + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Logs Bloom +^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +This modules defines functions for calculating bloom filters of logs. For the +general theory of bloom filters see e.g. `Wikipedia +`_. Bloom filters are used to allow +for efficient searching of logs by address and/or topic, by rapidly +eliminating blocks and receipts from their search. +". + +Axiom typing_imports_Tuple : + IsImported globals "typing" "Tuple". + +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". + +Axiom ethereum_crypto_hash_imports_keccak256 : + IsImported globals "ethereum.crypto.hash" "keccak256". + +Axiom ethereum_frontier_blocks_imports_Log : + IsImported globals "ethereum.frontier.blocks" "Log". + +Axiom ethereum_frontier_fork_types_imports_Bloom : + IsImported globals "ethereum.frontier.fork_types" "Bloom". + +Definition add_to_bloom : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "bloom"; "bloom_entry" ] |) in + let _ := Constant.str " + Add a bloom entry to the bloom filter (`bloom`). + + The number of hash functions used is 3. They are calculated by taking the + least significant 11 bits from the first 3 16-bit words of the + `keccak_256()` hash of `bloom_entry`. + + Parameters + ---------- + bloom : + The bloom filter. + bloom_entry : + An entry which is to be added to bloom filter. + " in + let _ := M.assign_local (| + "hash" , + M.call (| + M.get_name (| globals, "keccak256" |), + make_list [ + M.get_name (| globals, "bloom_entry" |) + ], + make_dict [] + |) + |) in + let _ := + M.for_ (| + M.get_name (| globals, "idx" |), + make_tuple [ Constant.int 0; Constant.int 2; Constant.int 4 ], + ltac:(M.monadic ( + let _ := M.assign_local (| + "bit_to_set" , + BinOp.bit_and (| + M.call (| + M.get_field (| M.get_name (| globals, "Uint" |), "from_be_bytes" |), + make_list [ + M.slice (| + M.get_name (| globals, "hash" |), + M.get_name (| globals, "idx" |), + BinOp.add (| + M.get_name (| globals, "idx" |), + Constant.int 2 + |), + Constant.None_ + |) + ], + make_dict [] + |), + Constant.int 2047 + |) + |) in + let _ := M.assign_local (| + "bit_index" , + BinOp.sub (| + Constant.int 2047, + M.get_name (| globals, "bit_to_set" |) + |) + |) in + let _ := M.assign_local (| + "byte_index" , + BinOp.floor_div (| + M.get_name (| globals, "bit_index" |), + Constant.int 8 + |) + |) in + let _ := M.assign_local (| + "bit_value" , + BinOp.l_shift (| + Constant.int 1, + BinOp.sub (| + Constant.int 7, + BinOp.mod_ (| + M.get_name (| globals, "bit_index" |), + Constant.int 8 + |) + |) + |) + |) in + let _ := M.assign (| + M.get_subscript (| + M.get_name (| globals, "bloom" |), + M.get_name (| globals, "byte_index" |) + |), + BinOp.bit_or (| + M.get_subscript (| + M.get_name (| globals, "bloom" |), + M.get_name (| globals, "byte_index" |) + |), + M.get_name (| globals, "bit_value" |) + |) + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + M.pure Constant.None_)). + +Definition logs_bloom : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "logs" ] |) in + let _ := Constant.str " + Obtain the logs bloom from a list of log entries. + + The address and each topic of a log are added to the bloom filter. + + Parameters + ---------- + logs : + List of logs for which the logs bloom is to be obtained. + + Returns + ------- + logs_bloom : `Bloom` + The logs bloom obtained which is 256 bytes with some bits set as per + the caller address and the log topics. + " in +(* At stmt: unsupported node type: AnnAssign *) + let _ := + M.for_ (| + M.get_name (| globals, "log" |), + M.get_name (| globals, "logs" |), + ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, "add_to_bloom" |), + make_list [ + M.get_name (| globals, "bloom" |); + M.get_field (| M.get_name (| globals, "log" |), "address" |) + ], + make_dict [] + |) in + let _ := + M.for_ (| + M.get_name (| globals, "topic" |), + M.get_field (| M.get_name (| globals, "log" |), "topics" |), + ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, "add_to_bloom" |), + make_list [ + M.get_name (| globals, "bloom" |); + M.get_name (| globals, "topic" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, "Bloom" |), + make_list [ + M.get_name (| globals, "bloom" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). diff --git a/CoqOfPython/ethereum/frontier/fork.v b/CoqOfPython/ethereum/frontier/fork.v new file mode 100644 index 0000000..ca8bfdb --- /dev/null +++ b/CoqOfPython/ethereum/frontier/fork.v @@ -0,0 +1,2368 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.frontier.fork". + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Specification +^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Entry point for the Ethereum specification. +". + +Axiom dataclasses_imports_dataclass : + IsImported globals "dataclasses" "dataclass". + +Axiom typing_imports_List : + IsImported globals "typing" "List". +Axiom typing_imports_Optional : + IsImported globals "typing" "Optional". +Axiom typing_imports_Set : + IsImported globals "typing" "Set". +Axiom typing_imports_Tuple : + IsImported globals "typing" "Tuple". + +Axiom ethereum_crypto_elliptic_curve_imports_SECP256K1N : + IsImported globals "ethereum.crypto.elliptic_curve" "SECP256K1N". +Axiom ethereum_crypto_elliptic_curve_imports_secp256k1_recover : + IsImported globals "ethereum.crypto.elliptic_curve" "secp256k1_recover". + +Axiom ethereum_crypto_hash_imports_Hash32 : + IsImported globals "ethereum.crypto.hash" "Hash32". +Axiom ethereum_crypto_hash_imports_keccak256 : + IsImported globals "ethereum.crypto.hash" "keccak256". + +Axiom ethereum_ethash_imports_dataset_size : + IsImported globals "ethereum.ethash" "dataset_size". +Axiom ethereum_ethash_imports_generate_cache : + IsImported globals "ethereum.ethash" "generate_cache". +Axiom ethereum_ethash_imports_hashimoto_light : + IsImported globals "ethereum.ethash" "hashimoto_light". + +Axiom ethereum_exceptions_imports_InvalidBlock : + IsImported globals "ethereum.exceptions" "InvalidBlock". + +Axiom ethereum_utils_ensure_imports_ensure : + IsImported globals "ethereum.utils.ensure" "ensure". + +Axiom ethereum_imports_rlp : + IsImported globals "ethereum" "rlp". + +Axiom ethereum_base_types_imports_U64 : + IsImported globals "ethereum.base_types" "U64". +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_U256_CEIL_VALUE : + IsImported globals "ethereum.base_types" "U256_CEIL_VALUE". +Axiom ethereum_base_types_imports_Bytes : + IsImported globals "ethereum.base_types" "Bytes". +Axiom ethereum_base_types_imports_Bytes32 : + IsImported globals "ethereum.base_types" "Bytes32". +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". + +Axiom ethereum_frontier_imports_vm : + IsImported globals "ethereum.frontier" "vm". + +Axiom ethereum_frontier_blocks_imports_Block : + IsImported globals "ethereum.frontier.blocks" "Block". +Axiom ethereum_frontier_blocks_imports_Header : + IsImported globals "ethereum.frontier.blocks" "Header". +Axiom ethereum_frontier_blocks_imports_Log : + IsImported globals "ethereum.frontier.blocks" "Log". +Axiom ethereum_frontier_blocks_imports_Receipt : + IsImported globals "ethereum.frontier.blocks" "Receipt". + +Axiom ethereum_frontier_bloom_imports_logs_bloom : + IsImported globals "ethereum.frontier.bloom" "logs_bloom". + +Axiom ethereum_frontier_fork_types_imports_Address : + IsImported globals "ethereum.frontier.fork_types" "Address". +Axiom ethereum_frontier_fork_types_imports_Bloom : + IsImported globals "ethereum.frontier.fork_types" "Bloom". +Axiom ethereum_frontier_fork_types_imports_Root : + IsImported globals "ethereum.frontier.fork_types" "Root". + +Axiom ethereum_frontier_state_imports_State : + IsImported globals "ethereum.frontier.state" "State". +Axiom ethereum_frontier_state_imports_create_ether : + IsImported globals "ethereum.frontier.state" "create_ether". +Axiom ethereum_frontier_state_imports_destroy_account : + IsImported globals "ethereum.frontier.state" "destroy_account". +Axiom ethereum_frontier_state_imports_get_account : + IsImported globals "ethereum.frontier.state" "get_account". +Axiom ethereum_frontier_state_imports_increment_nonce : + IsImported globals "ethereum.frontier.state" "increment_nonce". +Axiom ethereum_frontier_state_imports_set_account_balance : + IsImported globals "ethereum.frontier.state" "set_account_balance". +Axiom ethereum_frontier_state_imports_state_root : + IsImported globals "ethereum.frontier.state" "state_root". + +Axiom ethereum_frontier_transactions_imports_TX_BASE_COST : + IsImported globals "ethereum.frontier.transactions" "TX_BASE_COST". +Axiom ethereum_frontier_transactions_imports_TX_DATA_COST_PER_NON_ZERO : + IsImported globals "ethereum.frontier.transactions" "TX_DATA_COST_PER_NON_ZERO". +Axiom ethereum_frontier_transactions_imports_TX_DATA_COST_PER_ZERO : + IsImported globals "ethereum.frontier.transactions" "TX_DATA_COST_PER_ZERO". +Axiom ethereum_frontier_transactions_imports_Transaction : + IsImported globals "ethereum.frontier.transactions" "Transaction". + +Axiom ethereum_frontier_trie_imports_Trie : + IsImported globals "ethereum.frontier.trie" "Trie". +Axiom ethereum_frontier_trie_imports_root : + IsImported globals "ethereum.frontier.trie" "root". +Axiom ethereum_frontier_trie_imports_trie_set : + IsImported globals "ethereum.frontier.trie" "trie_set". + +Axiom ethereum_frontier_utils_message_imports_prepare_message : + IsImported globals "ethereum.frontier.utils.message" "prepare_message". + +Axiom ethereum_frontier_vm_interpreter_imports_process_message_call : + IsImported globals "ethereum.frontier.vm.interpreter" "process_message_call". + +Definition BLOCK_REWARD : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + BinOp.mult (| + Constant.int 5, + BinOp.pow (| + Constant.int 10, + Constant.int 18 + |) + |) + ], + make_dict [] + |) +)). + +Definition GAS_LIMIT_ADJUSTMENT_FACTOR : Value.t := M.run ltac:(M.monadic ( + Constant.int 1024 +)). + +Definition GAS_LIMIT_MINIMUM : Value.t := M.run ltac:(M.monadic ( + Constant.int 5000 +)). + +Definition MINIMUM_DIFFICULTY : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 131072 + ], + make_dict [] + |) +)). + +Definition MAX_OMMER_DEPTH : Value.t := M.run ltac:(M.monadic ( + Constant.int 6 +)). + +Definition BlockChain : Value.t := + builtins.make_klass + [] + [ + + ] + [ + + ]. + +Definition apply_fork : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "old" ] |) in + let _ := Constant.str " + Transforms the state from the previous hard fork (`old`) into the block + chain object for this hard fork and returns it. + + When forks need to implement an irregular state transition, this function + is used to handle the irregularity. See the :ref:`DAO Fork ` for + an example. + + Parameters + ---------- + old : + Previous block chain object. + + Returns + ------- + new : `BlockChain` + Upgraded block chain object for this hard fork. + " in + let _ := M.return_ (| + M.get_name (| globals, "old" |) + |) in + M.pure Constant.None_)). + +Definition get_last_256_block_hashes : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "chain" ] |) in + let _ := Constant.str " + Obtain the list of hashes of the previous 256 blocks in order of + increasing block number. + + This function will return less hashes for the first 256 blocks. + + The ``BLOCKHASH`` opcode needs to access the latest hashes on the chain, + therefore this function retrieves them. + + Parameters + ---------- + chain : + History and current state. + + Returns + ------- + recent_block_hashes : `List[Hash32]` + Hashes of the recent 256 blocks in order of increasing block number. + " in + let _ := M.assign_local (| + "recent_blocks" , + M.slice (| + M.get_field (| M.get_name (| globals, "chain" |), "blocks" |), + UnOp.sub (| Constant.int 255 |), + Constant.None_, + Constant.None_ + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_name (| globals, "recent_blocks" |) + ], + make_dict [] + |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + make_list [] + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "recent_block_hashes" , + make_list [] + |) in + let _ := + M.for_ (| + M.get_name (| globals, "block" |), + M.get_name (| globals, "recent_blocks" |), + ltac:(M.monadic ( + let _ := M.assign_local (| + "prev_block_hash" , + M.get_field (| M.get_field (| M.get_name (| globals, "block" |), "header" |), "parent_hash" |) + |) in + let _ := M.call (| + M.get_field (| M.get_name (| globals, "recent_block_hashes" |), "append" |), + make_list [ + M.get_name (| globals, "prev_block_hash" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := M.assign_local (| + "most_recent_block_hash" , + M.call (| + M.get_name (| globals, "keccak256" |), + make_list [ + M.call (| + M.get_field (| M.get_name (| globals, "rlp" |), "encode" |), + make_list [ + M.get_field (| M.get_subscript (| + M.get_name (| globals, "recent_blocks" |), + UnOp.sub (| Constant.int 1 |) + |), "header" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_field (| M.get_name (| globals, "recent_block_hashes" |), "append" |), + make_list [ + M.get_name (| globals, "most_recent_block_hash" |) + ], + make_dict [] + |) in + let _ := M.return_ (| + M.get_name (| globals, "recent_block_hashes" |) + |) in + M.pure Constant.None_)). + +Definition state_transition : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "chain"; "block" ] |) in + let _ := Constant.str " + Attempts to apply a block to an existing block chain. + + All parts of the block's contents need to be verified before being added + to the chain. Blocks are verified by ensuring that the contents of the + block make logical sense with the contents of the parent block. The + information in the block's header must also match the corresponding + information in the block. + + To implement Ethereum, in theory clients are only required to store the + most recent 255 blocks of the chain since as far as execution is + concerned, only those blocks are accessed. Practically, however, clients + should store more blocks to handle reorgs. + + Parameters + ---------- + chain : + History and current state. + block : + Block to apply to `chain`. + " in + let _ := M.assign_local (| + "parent_header" , + M.get_field (| M.get_subscript (| + M.get_field (| M.get_name (| globals, "chain" |), "blocks" |), + UnOp.sub (| Constant.int 1 |) + |), "header" |) + |) in + let _ := M.call (| + M.get_name (| globals, "validate_header" |), + make_list [ + M.get_field (| M.get_name (| globals, "block" |), "header" |); + M.get_name (| globals, "parent_header" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "validate_ommers" |), + make_list [ + M.get_field (| M.get_name (| globals, "block" |), "ommers" |); + M.get_field (| M.get_name (| globals, "block" |), "header" |); + M.get_name (| globals, "chain" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "apply_body_output" , + M.call (| + M.get_name (| globals, "apply_body" |), + make_list [ + M.get_field (| M.get_name (| globals, "chain" |), "state" |); + M.call (| + M.get_name (| globals, "get_last_256_block_hashes" |), + make_list [ + M.get_name (| globals, "chain" |) + ], + make_dict [] + |); + M.get_field (| M.get_field (| M.get_name (| globals, "block" |), "header" |), "coinbase" |); + M.get_field (| M.get_field (| M.get_name (| globals, "block" |), "header" |), "number" |); + M.get_field (| M.get_field (| M.get_name (| globals, "block" |), "header" |), "gas_limit" |); + M.get_field (| M.get_field (| M.get_name (| globals, "block" |), "header" |), "timestamp" |); + M.get_field (| M.get_field (| M.get_name (| globals, "block" |), "header" |), "difficulty" |); + M.get_field (| M.get_name (| globals, "block" |), "transactions" |); + M.get_field (| M.get_name (| globals, "block" |), "ommers" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + Compare.eq (| + M.get_field (| M.get_name (| globals, "apply_body_output" |), "block_gas_used" |), + M.get_field (| M.get_field (| M.get_name (| globals, "block" |), "header" |), "gas_used" |) + |); + M.get_name (| globals, "InvalidBlock" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + Compare.eq (| + M.get_field (| M.get_name (| globals, "apply_body_output" |), "transactions_root" |), + M.get_field (| M.get_field (| M.get_name (| globals, "block" |), "header" |), "transactions_root" |) + |); + M.get_name (| globals, "InvalidBlock" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + Compare.eq (| + M.get_field (| M.get_name (| globals, "apply_body_output" |), "state_root" |), + M.get_field (| M.get_field (| M.get_name (| globals, "block" |), "header" |), "state_root" |) + |); + M.get_name (| globals, "InvalidBlock" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + Compare.eq (| + M.get_field (| M.get_name (| globals, "apply_body_output" |), "receipt_root" |), + M.get_field (| M.get_field (| M.get_name (| globals, "block" |), "header" |), "receipt_root" |) + |); + M.get_name (| globals, "InvalidBlock" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + Compare.eq (| + M.get_field (| M.get_name (| globals, "apply_body_output" |), "block_logs_bloom" |), + M.get_field (| M.get_field (| M.get_name (| globals, "block" |), "header" |), "bloom" |) + |); + M.get_name (| globals, "InvalidBlock" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, "chain" |), "blocks" |), "append" |), + make_list [ + M.get_name (| globals, "block" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.gt (| + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_field (| M.get_name (| globals, "chain" |), "blocks" |) + ], + make_dict [] + |), + Constant.int 255 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign (| + M.get_field (| M.get_name (| globals, "chain" |), "blocks" |), + M.slice (| + M.get_field (| M.get_name (| globals, "chain" |), "blocks" |), + UnOp.sub (| Constant.int 255 |), + Constant.None_, + Constant.None_ + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + M.pure Constant.None_)). + +Definition validate_header : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "header"; "parent_header" ] |) in + let _ := Constant.str " + Verifies a block header. + + In order to consider a block's header valid, the logic for the + quantities in the header should match the logic for the block itself. + For example the header timestamp should be greater than the block's parent + timestamp because the block was created *after* the parent block. + Additionally, the block's number should be directly following the parent + block's number since it is the next block in the sequence. + + Parameters + ---------- + header : + Header to check for correctness. + parent_header : + Parent Header of the header to check for correctness + " in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + Compare.gt (| + M.get_field (| M.get_name (| globals, "header" |), "timestamp" |), + M.get_field (| M.get_name (| globals, "parent_header" |), "timestamp" |) + |); + M.get_name (| globals, "InvalidBlock" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + Compare.eq (| + M.get_field (| M.get_name (| globals, "header" |), "number" |), + BinOp.add (| + M.get_field (| M.get_name (| globals, "parent_header" |), "number" |), + Constant.int 1 + |) + |); + M.get_name (| globals, "InvalidBlock" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + M.call (| + M.get_name (| globals, "check_gas_limit" |), + make_list [ + M.get_field (| M.get_name (| globals, "header" |), "gas_limit" |); + M.get_field (| M.get_name (| globals, "parent_header" |), "gas_limit" |) + ], + make_dict [] + |); + M.get_name (| globals, "InvalidBlock" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + Compare.lt_e (| + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_field (| M.get_name (| globals, "header" |), "extra_data" |) + ], + make_dict [] + |), + Constant.int 32 + |); + M.get_name (| globals, "InvalidBlock" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "block_difficulty" , + M.call (| + M.get_name (| globals, "calculate_block_difficulty" |), + make_list [ + M.get_field (| M.get_name (| globals, "header" |), "number" |); + M.get_field (| M.get_name (| globals, "header" |), "timestamp" |); + M.get_field (| M.get_name (| globals, "parent_header" |), "timestamp" |); + M.get_field (| M.get_name (| globals, "parent_header" |), "difficulty" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + Compare.eq (| + M.get_field (| M.get_name (| globals, "header" |), "difficulty" |), + M.get_name (| globals, "block_difficulty" |) + |); + M.get_name (| globals, "InvalidBlock" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "block_parent_hash" , + M.call (| + M.get_name (| globals, "keccak256" |), + make_list [ + M.call (| + M.get_field (| M.get_name (| globals, "rlp" |), "encode" |), + make_list [ + M.get_name (| globals, "parent_header" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + Compare.eq (| + M.get_field (| M.get_name (| globals, "header" |), "parent_hash" |), + M.get_name (| globals, "block_parent_hash" |) + |); + M.get_name (| globals, "InvalidBlock" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "validate_proof_of_work" |), + make_list [ + M.get_name (| globals, "header" |) + ], + make_dict [] + |) in + M.pure Constant.None_)). + +Definition generate_header_hash_for_pow : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "header" ] |) in + let _ := Constant.str " + Generate rlp hash of the header which is to be used for Proof-of-Work + verification. + + In other words, the PoW artefacts `mix_digest` and `nonce` are ignored + while calculating this hash. + + A particular PoW is valid for a single hash, that hash is computed by + this function. The `nonce` and `mix_digest` are omitted from this hash + because they are being changed by miners in their search for a sufficient + proof-of-work. + + Parameters + ---------- + header : + The header object for which the hash is to be generated. + + Returns + ------- + hash : `Hash32` + The PoW valid rlp hash of the passed in header. + " in + let _ := M.assign_local (| + "header_data_without_pow_artefacts" , + make_list [ + M.get_field (| M.get_name (| globals, "header" |), "parent_hash" |); + M.get_field (| M.get_name (| globals, "header" |), "ommers_hash" |); + M.get_field (| M.get_name (| globals, "header" |), "coinbase" |); + M.get_field (| M.get_name (| globals, "header" |), "state_root" |); + M.get_field (| M.get_name (| globals, "header" |), "transactions_root" |); + M.get_field (| M.get_name (| globals, "header" |), "receipt_root" |); + M.get_field (| M.get_name (| globals, "header" |), "bloom" |); + M.get_field (| M.get_name (| globals, "header" |), "difficulty" |); + M.get_field (| M.get_name (| globals, "header" |), "number" |); + M.get_field (| M.get_name (| globals, "header" |), "gas_limit" |); + M.get_field (| M.get_name (| globals, "header" |), "gas_used" |); + M.get_field (| M.get_name (| globals, "header" |), "timestamp" |); + M.get_field (| M.get_name (| globals, "header" |), "extra_data" |) + ] + |) in + let _ := M.return_ (| + M.call (| + M.get_field (| M.get_name (| globals, "rlp" |), "rlp_hash" |), + make_list [ + M.get_name (| globals, "header_data_without_pow_artefacts" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Definition validate_proof_of_work : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "header" ] |) in + let _ := Constant.str " + Validates the Proof of Work constraints. + + In order to verify that a miner's proof-of-work is valid for a block, a + ``mix-digest`` and ``result`` are calculated using the ``hashimoto_light`` + hash function. The mix digest is a hash of the header and the nonce that + is passed through and it confirms whether or not proof-of-work was done + on the correct block. The result is the actual hash value of the block. + + Parameters + ---------- + header : + Header of interest. + " in + let _ := M.assign_local (| + "header_hash" , + M.call (| + M.get_name (| globals, "generate_header_hash_for_pow" |), + make_list [ + M.get_name (| globals, "header" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "cache" , + M.call (| + M.get_name (| globals, "generate_cache" |), + make_list [ + M.get_field (| M.get_name (| globals, "header" |), "number" |) + ], + make_dict [] + |) + |) in + let _ := M.assign (| + make_tuple [ M.get_name (| globals, "mix_digest" |); M.get_name (| globals, "result" |) ], + M.call (| + M.get_name (| globals, "hashimoto_light" |), + make_list [ + M.get_name (| globals, "header_hash" |); + M.get_field (| M.get_name (| globals, "header" |), "nonce" |); + M.get_name (| globals, "cache" |); + M.call (| + M.get_name (| globals, "dataset_size" |), + make_list [ + M.get_field (| M.get_name (| globals, "header" |), "number" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + Compare.eq (| + M.get_name (| globals, "mix_digest" |), + M.get_field (| M.get_name (| globals, "header" |), "mix_digest" |) + |); + M.get_name (| globals, "InvalidBlock" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + Compare.lt_e (| + M.call (| + M.get_field (| M.get_name (| globals, "Uint" |), "from_be_bytes" |), + make_list [ + M.get_name (| globals, "result" |) + ], + make_dict [] + |), + BinOp.floor_div (| + M.get_name (| globals, "U256_CEIL_VALUE" |), + M.get_field (| M.get_name (| globals, "header" |), "difficulty" |) + |) + |); + M.get_name (| globals, "InvalidBlock" |) + ], + make_dict [] + |) in + M.pure Constant.None_)). + +Definition check_transaction : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "tx"; "gas_available" ] |) in + let _ := Constant.str " + Check if the transaction is includable in the block. + + Parameters + ---------- + tx : + The transaction. + gas_available : + The gas remaining in the block. + + Returns + ------- + sender_address : + The sender of the transaction. + + Raises + ------ + InvalidBlock : + If the transaction is not includable. + " in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + Compare.lt_e (| + M.get_field (| M.get_name (| globals, "tx" |), "gas" |), + M.get_name (| globals, "gas_available" |) + |); + M.get_name (| globals, "InvalidBlock" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "sender_address" , + M.call (| + M.get_name (| globals, "recover_sender" |), + make_list [ + M.get_name (| globals, "tx" |) + ], + make_dict [] + |) + |) in + let _ := M.return_ (| + M.get_name (| globals, "sender_address" |) + |) in + M.pure Constant.None_)). + +Definition make_receipt : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "tx"; "post_state"; "cumulative_gas_used"; "logs" ] |) in + let _ := Constant.str " + Make the receipt for a transaction that was executed. + + Parameters + ---------- + tx : + The executed transaction. + post_state : + The state root immediately after this transaction. + cumulative_gas_used : + The total gas used so far in the block after the transaction was + executed. + logs : + The logs produced by the transaction. + + Returns + ------- + receipt : + The receipt for the transaction. + " in + let _ := M.assign_local (| + "receipt" , + M.call (| + M.get_name (| globals, "Receipt" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.return_ (| + M.get_name (| globals, "receipt" |) + |) in + M.pure Constant.None_)). + +Definition ApplyBodyOutput : Value.t := + builtins.make_klass + [] + [ + + ] + [ + + ]. + +Definition apply_body : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "state"; "block_hashes"; "coinbase"; "block_number"; "block_gas_limit"; "block_time"; "block_difficulty"; "transactions"; "ommers" ] |) in + let _ := Constant.str " + Executes a block. + + Many of the contents of a block are stored in data structures called + tries. There is a transactions trie which is similar to a ledger of the + transactions stored in the current block. There is also a receipts trie + which stores the results of executing a transaction, like the post state + and gas used. This function creates and executes the block that is to be + added to the chain. + + Parameters + ---------- + state : + Current account state. + block_hashes : + List of hashes of the previous 256 blocks in the order of + increasing block number. + coinbase : + Address of account which receives block reward and transaction fees. + block_number : + Position of the block within the chain. + block_gas_limit : + Initial amount of gas available for execution in this block. + block_time : + Time the block was produced, measured in seconds since the epoch. + block_difficulty : + Difficulty of the block. + transactions : + Transactions included in the block. + ommers : + Headers of ancestor blocks which are not direct parents (formerly + uncles.) + + Returns + ------- + apply_body_output : `ApplyBodyOutput` + Output of applying the block body to the state. + " in + let _ := M.assign_local (| + "gas_available" , + M.get_name (| globals, "block_gas_limit" |) + |) in +(* At stmt: unsupported node type: AnnAssign *) +(* At stmt: unsupported node type: AnnAssign *) +(* At stmt: unsupported node type: AnnAssign *) + let _ := + M.for_ (| + make_tuple [ M.get_name (| globals, "i" |); M.get_name (| globals, "tx" |) ], + M.call (| + M.get_name (| globals, "enumerate" |), + make_list [ + M.get_name (| globals, "transactions" |) + ], + make_dict [] + |), + ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, "trie_set" |), + make_list [ + M.get_name (| globals, "transactions_trie" |); + M.call (| + M.get_field (| M.get_name (| globals, "rlp" |), "encode" |), + make_list [ + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.get_name (| globals, "i" |) + ], + make_dict [] + |) + ], + make_dict [] + |); + M.get_name (| globals, "tx" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "sender_address" , + M.call (| + M.get_name (| globals, "check_transaction" |), + make_list [ + M.get_name (| globals, "tx" |); + M.get_name (| globals, "gas_available" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "env" , + M.call (| + M.get_field (| M.get_name (| globals, "vm" |), "Environment" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.assign (| + make_tuple [ M.get_name (| globals, "gas_used" |); M.get_name (| globals, "logs" |) ], + M.call (| + M.get_name (| globals, "process_transaction" |), + make_list [ + M.get_name (| globals, "env" |); + M.get_name (| globals, "tx" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_op_local (| + BinOp.sub, + "gas_available", + M.get_name (| globals, "gas_used" |) + |) in + let _ := M.assign_local (| + "receipt" , + M.call (| + M.get_name (| globals, "make_receipt" |), + make_list [ + M.get_name (| globals, "tx" |); + M.call (| + M.get_name (| globals, "state_root" |), + make_list [ + M.get_name (| globals, "state" |) + ], + make_dict [] + |); + BinOp.sub (| + M.get_name (| globals, "block_gas_limit" |), + M.get_name (| globals, "gas_available" |) + |); + M.get_name (| globals, "logs" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "trie_set" |), + make_list [ + M.get_name (| globals, "receipts_trie" |); + M.call (| + M.get_field (| M.get_name (| globals, "rlp" |), "encode" |), + make_list [ + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.get_name (| globals, "i" |) + ], + make_dict [] + |) + ], + make_dict [] + |); + M.get_name (| globals, "receipt" |) + ], + make_dict [] + |) in + let _ := M.assign_op_local (| + BinOp.add, + "block_logs", + M.get_name (| globals, "logs" |) + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := M.call (| + M.get_name (| globals, "pay_rewards" |), + make_list [ + M.get_name (| globals, "state" |); + M.get_name (| globals, "block_number" |); + M.get_name (| globals, "coinbase" |); + M.get_name (| globals, "ommers" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "block_gas_used" , + BinOp.sub (| + M.get_name (| globals, "block_gas_limit" |), + M.get_name (| globals, "gas_available" |) + |) + |) in + let _ := M.assign_local (| + "block_logs_bloom" , + M.call (| + M.get_name (| globals, "logs_bloom" |), + make_list [ + M.get_name (| globals, "block_logs" |) + ], + make_dict [] + |) + |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, "ApplyBodyOutput" |), + make_list [ + M.get_name (| globals, "block_gas_used" |); + M.call (| + M.get_name (| globals, "root" |), + make_list [ + M.get_name (| globals, "transactions_trie" |) + ], + make_dict [] + |); + M.call (| + M.get_name (| globals, "root" |), + make_list [ + M.get_name (| globals, "receipts_trie" |) + ], + make_dict [] + |); + M.get_name (| globals, "block_logs_bloom" |); + M.call (| + M.get_name (| globals, "state_root" |), + make_list [ + M.get_name (| globals, "state" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Definition validate_ommers : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "ommers"; "block_header"; "chain" ] |) in + let _ := Constant.str " + Validates the ommers mentioned in the block. + + An ommer block is a block that wasn't canonically added to the + blockchain because it wasn't validated as fast as the canonical block + but was mined at the same time. + + To be considered valid, the ommers must adhere to the rules defined in + the Ethereum protocol. The maximum amount of ommers is 2 per block and + there cannot be duplicate ommers in a block. Many of the other ommer + constraints are listed in the in-line comments of this function. + + Parameters + ---------- + ommers : + List of ommers mentioned in the current block. + block_header: + The header of current block. + chain : + History and current state. + " in + let _ := M.assign_local (| + "block_hash" , + M.call (| + M.get_field (| M.get_name (| globals, "rlp" |), "rlp_hash" |), + make_list [ + M.get_name (| globals, "block_header" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + Compare.eq (| + M.call (| + M.get_field (| M.get_name (| globals, "rlp" |), "rlp_hash" |), + make_list [ + M.get_name (| globals, "ommers" |) + ], + make_dict [] + |), + M.get_field (| M.get_name (| globals, "block_header" |), "ommers_hash" |) + |); + M.get_name (| globals, "InvalidBlock" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_name (| globals, "ommers" |) + ], + make_dict [] + |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + Constant.None_ + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + M.for_ (| + M.get_name (| globals, "ommer" |), + M.get_name (| globals, "ommers" |), + ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + BoolOp.and (| + Compare.lt_e (| + Constant.int 1, + M.get_field (| M.get_name (| globals, "ommer" |), "number" |) + |), + ltac:(M.monadic ( + Compare.lt (| + M.get_field (| M.get_name (| globals, "ommer" |), "number" |), + M.get_field (| M.get_name (| globals, "block_header" |), "number" |) + |) + )) + |); + M.get_name (| globals, "InvalidBlock" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "ommer_parent_header" , + M.get_field (| M.get_subscript (| + M.get_field (| M.get_name (| globals, "chain" |), "blocks" |), + BinOp.sub (| + UnOp.sub (| BinOp.sub (| + M.get_field (| M.get_name (| globals, "block_header" |), "number" |), + M.get_field (| M.get_name (| globals, "ommer" |), "number" |) + |) |), + Constant.int 1 + |) + |), "header" |) + |) in + let _ := M.call (| + M.get_name (| globals, "validate_header" |), + make_list [ + M.get_name (| globals, "ommer" |); + M.get_name (| globals, "ommer_parent_header" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + Compare.lt_e (| + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_name (| globals, "ommers" |) + ], + make_dict [] + |), + Constant.int 2 + |); + M.get_name (| globals, "InvalidBlock" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "ommers_hashes" , + Constant.str "(* At expr: unsupported node type: ListComp *)" + |) in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + Compare.eq (| + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_name (| globals, "ommers_hashes" |) + ], + make_dict [] + |), + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.call (| + M.get_name (| globals, "set" |), + make_list [ + M.get_name (| globals, "ommers_hashes" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |); + M.get_name (| globals, "InvalidBlock" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "recent_canonical_blocks" , + M.slice (| + M.get_field (| M.get_name (| globals, "chain" |), "blocks" |), + UnOp.sub (| BinOp.add (| + M.get_name (| globals, "MAX_OMMER_DEPTH" |), + Constant.int 1 + |) |), + Constant.None_, + Constant.None_ + |) + |) in + let _ := M.assign_local (| + "recent_canonical_block_hashes" , + Constant.str "(* At expr: unsupported node type: SetComp *)" + |) in +(* At stmt: unsupported node type: AnnAssign *) + let _ := + M.for_ (| + M.get_name (| globals, "block" |), + M.get_name (| globals, "recent_canonical_blocks" |), + ltac:(M.monadic ( + let _ := M.assign_local (| + "recent_ommers_hashes" , + M.call (| + M.get_field (| M.get_name (| globals, "recent_ommers_hashes" |), "union" |), + make_list [ + Constant.str "(* At expr: unsupported node type: SetComp *)" + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := + M.for_ (| + make_tuple [ M.get_name (| globals, "ommer_index" |); M.get_name (| globals, "ommer" |) ], + M.call (| + M.get_name (| globals, "enumerate" |), + make_list [ + M.get_name (| globals, "ommers" |) + ], + make_dict [] + |), + ltac:(M.monadic ( + let _ := M.assign_local (| + "ommer_hash" , + M.get_subscript (| + M.get_name (| globals, "ommers_hashes" |), + M.get_name (| globals, "ommer_index" |) + |) + |) in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + Compare.not_eq (| + M.get_name (| globals, "ommer_hash" |), + M.get_name (| globals, "block_hash" |) + |); + M.get_name (| globals, "InvalidBlock" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + Compare.not_in (| + M.get_name (| globals, "ommer_hash" |), + M.get_name (| globals, "recent_canonical_block_hashes" |) + |); + M.get_name (| globals, "InvalidBlock" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + Compare.not_in (| + M.get_name (| globals, "ommer_hash" |), + M.get_name (| globals, "recent_ommers_hashes" |) + |); + M.get_name (| globals, "InvalidBlock" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "ommer_age" , + BinOp.sub (| + M.get_field (| M.get_name (| globals, "block_header" |), "number" |), + M.get_field (| M.get_name (| globals, "ommer" |), "number" |) + |) + |) in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + BoolOp.and (| + Compare.lt_e (| + Constant.int 1, + M.get_name (| globals, "ommer_age" |) + |), + ltac:(M.monadic ( + Compare.lt_e (| + M.get_name (| globals, "ommer_age" |), + M.get_name (| globals, "MAX_OMMER_DEPTH" |) + |) + )) + |); + M.get_name (| globals, "InvalidBlock" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + Compare.in_ (| + M.get_field (| M.get_name (| globals, "ommer" |), "parent_hash" |), + M.get_name (| globals, "recent_canonical_block_hashes" |) + |); + M.get_name (| globals, "InvalidBlock" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + Compare.not_eq (| + M.get_field (| M.get_name (| globals, "ommer" |), "parent_hash" |), + M.get_field (| M.get_name (| globals, "block_header" |), "parent_hash" |) + |); + M.get_name (| globals, "InvalidBlock" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + M.pure Constant.None_)). + +Definition pay_rewards : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "state"; "block_number"; "coinbase"; "ommers" ] |) in + let _ := Constant.str " + Pay rewards to the block miner as well as the ommers miners. + + The miner of the canonical block is rewarded with the predetermined + block reward, ``BLOCK_REWARD``, plus a variable award based off of the + number of ommer blocks that were mined around the same time, and included + in the canonical block's header. An ommer block is a block that wasn't + added to the canonical blockchain because it wasn't validated as fast as + the accepted block but was mined at the same time. Although not all blocks + that are mined are added to the canonical chain, miners are still paid a + reward for their efforts. This reward is called an ommer reward and is + calculated based on the number associated with the ommer block that they + mined. + + Parameters + ---------- + state : + Current account state. + block_number : + Position of the block within the chain. + coinbase : + Address of account which receives block reward and transaction fees. + ommers : + List of ommers mentioned in the current block. + " in + let _ := M.assign_local (| + "miner_reward" , + BinOp.add (| + M.get_name (| globals, "BLOCK_REWARD" |), + BinOp.mult (| + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_name (| globals, "ommers" |) + ], + make_dict [] + |), + BinOp.floor_div (| + M.get_name (| globals, "BLOCK_REWARD" |), + Constant.int 32 + |) + |) + |) + |) in + let _ := M.call (| + M.get_name (| globals, "create_ether" |), + make_list [ + M.get_name (| globals, "state" |); + M.get_name (| globals, "coinbase" |); + M.get_name (| globals, "miner_reward" |) + ], + make_dict [] + |) in + let _ := + M.for_ (| + M.get_name (| globals, "ommer" |), + M.get_name (| globals, "ommers" |), + ltac:(M.monadic ( + let _ := M.assign_local (| + "ommer_age" , + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + BinOp.sub (| + M.get_name (| globals, "block_number" |), + M.get_field (| M.get_name (| globals, "ommer" |), "number" |) + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "ommer_miner_reward" , + BinOp.floor_div (| + BinOp.mult (| + BinOp.sub (| + Constant.int 8, + M.get_name (| globals, "ommer_age" |) + |), + M.get_name (| globals, "BLOCK_REWARD" |) + |), + Constant.int 8 + |) + |) in + let _ := M.call (| + M.get_name (| globals, "create_ether" |), + make_list [ + M.get_name (| globals, "state" |); + M.get_field (| M.get_name (| globals, "ommer" |), "coinbase" |); + M.get_name (| globals, "ommer_miner_reward" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + M.pure Constant.None_)). + +Definition process_transaction : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "env"; "tx" ] |) in + let _ := Constant.str " + Execute a transaction against the provided environment. + + This function processes the actions needed to execute a transaction. + It decrements the sender's account after calculating the gas fee and + refunds them the proper amount after execution. Calling contracts, + deploying code, and incrementing nonces are all examples of actions that + happen within this function or from a call made within this function. + + Accounts that are marked for deletion are processed and destroyed after + execution. + + Parameters + ---------- + env : + Environment for the Ethereum Virtual Machine. + tx : + Transaction to execute. + + Returns + ------- + gas_left : `ethereum.base_types.U256` + Remaining gas after execution. + logs : `Tuple[ethereum.blocks.Log, ...]` + Logs generated during execution. + " in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + M.call (| + M.get_name (| globals, "validate_transaction" |), + make_list [ + M.get_name (| globals, "tx" |) + ], + make_dict [] + |); + M.get_name (| globals, "InvalidBlock" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "sender" , + M.get_field (| M.get_name (| globals, "env" |), "origin" |) + |) in + let _ := M.assign_local (| + "sender_account" , + M.call (| + M.get_name (| globals, "get_account" |), + make_list [ + M.get_field (| M.get_name (| globals, "env" |), "state" |); + M.get_name (| globals, "sender" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "gas_fee" , + BinOp.mult (| + M.get_field (| M.get_name (| globals, "tx" |), "gas" |), + M.get_field (| M.get_name (| globals, "tx" |), "gas_price" |) + |) + |) in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + Compare.eq (| + M.get_field (| M.get_name (| globals, "sender_account" |), "nonce" |), + M.get_field (| M.get_name (| globals, "tx" |), "nonce" |) + |); + M.get_name (| globals, "InvalidBlock" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + Compare.gt_e (| + M.get_field (| M.get_name (| globals, "sender_account" |), "balance" |), + BinOp.add (| + M.get_name (| globals, "gas_fee" |), + M.get_field (| M.get_name (| globals, "tx" |), "value" |) + |) + |); + M.get_name (| globals, "InvalidBlock" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + Compare.eq (| + M.get_field (| M.get_name (| globals, "sender_account" |), "code" |), + M.call (| + M.get_name (| globals, "bytearray" |), + make_list [], + make_dict [] + |) + |); + M.get_name (| globals, "InvalidBlock" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "gas" , + BinOp.sub (| + M.get_field (| M.get_name (| globals, "tx" |), "gas" |), + M.call (| + M.get_name (| globals, "calculate_intrinsic_cost" |), + make_list [ + M.get_name (| globals, "tx" |) + ], + make_dict [] + |) + |) + |) in + let _ := M.call (| + M.get_name (| globals, "increment_nonce" |), + make_list [ + M.get_field (| M.get_name (| globals, "env" |), "state" |); + M.get_name (| globals, "sender" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "sender_balance_after_gas_fee" , + BinOp.sub (| + M.get_field (| M.get_name (| globals, "sender_account" |), "balance" |), + M.get_name (| globals, "gas_fee" |) + |) + |) in + let _ := M.call (| + M.get_name (| globals, "set_account_balance" |), + make_list [ + M.get_field (| M.get_name (| globals, "env" |), "state" |); + M.get_name (| globals, "sender" |); + M.get_name (| globals, "sender_balance_after_gas_fee" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "message" , + M.call (| + M.get_name (| globals, "prepare_message" |), + make_list [ + M.get_name (| globals, "sender" |); + M.get_field (| M.get_name (| globals, "tx" |), "to" |); + M.get_field (| M.get_name (| globals, "tx" |), "value" |); + M.get_field (| M.get_name (| globals, "tx" |), "data" |); + M.get_name (| globals, "gas" |); + M.get_name (| globals, "env" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "output" , + M.call (| + M.get_name (| globals, "process_message_call" |), + make_list [ + M.get_name (| globals, "message" |); + M.get_name (| globals, "env" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "gas_used" , + BinOp.sub (| + M.get_field (| M.get_name (| globals, "tx" |), "gas" |), + M.get_field (| M.get_name (| globals, "output" |), "gas_left" |) + |) + |) in + let _ := M.assign_local (| + "gas_refund" , + M.call (| + M.get_name (| globals, "min" |), + make_list [ + BinOp.floor_div (| + M.get_name (| globals, "gas_used" |), + Constant.int 2 + |); + M.get_field (| M.get_name (| globals, "output" |), "refund_counter" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "gas_refund_amount" , + BinOp.mult (| + BinOp.add (| + M.get_field (| M.get_name (| globals, "output" |), "gas_left" |), + M.get_name (| globals, "gas_refund" |) + |), + M.get_field (| M.get_name (| globals, "tx" |), "gas_price" |) + |) + |) in + let _ := M.assign_local (| + "transaction_fee" , + BinOp.mult (| + BinOp.sub (| + BinOp.sub (| + M.get_field (| M.get_name (| globals, "tx" |), "gas" |), + M.get_field (| M.get_name (| globals, "output" |), "gas_left" |) + |), + M.get_name (| globals, "gas_refund" |) + |), + M.get_field (| M.get_name (| globals, "tx" |), "gas_price" |) + |) + |) in + let _ := M.assign_local (| + "total_gas_used" , + BinOp.sub (| + M.get_name (| globals, "gas_used" |), + M.get_name (| globals, "gas_refund" |) + |) + |) in + let _ := M.assign_local (| + "sender_balance_after_refund" , + BinOp.add (| + M.get_field (| M.call (| + M.get_name (| globals, "get_account" |), + make_list [ + M.get_field (| M.get_name (| globals, "env" |), "state" |); + M.get_name (| globals, "sender" |) + ], + make_dict [] + |), "balance" |), + M.get_name (| globals, "gas_refund_amount" |) + |) + |) in + let _ := M.call (| + M.get_name (| globals, "set_account_balance" |), + make_list [ + M.get_field (| M.get_name (| globals, "env" |), "state" |); + M.get_name (| globals, "sender" |); + M.get_name (| globals, "sender_balance_after_refund" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "coinbase_balance_after_mining_fee" , + BinOp.add (| + M.get_field (| M.call (| + M.get_name (| globals, "get_account" |), + make_list [ + M.get_field (| M.get_name (| globals, "env" |), "state" |); + M.get_field (| M.get_name (| globals, "env" |), "coinbase" |) + ], + make_dict [] + |), "balance" |), + M.get_name (| globals, "transaction_fee" |) + |) + |) in + let _ := M.call (| + M.get_name (| globals, "set_account_balance" |), + make_list [ + M.get_field (| M.get_name (| globals, "env" |), "state" |); + M.get_field (| M.get_name (| globals, "env" |), "coinbase" |); + M.get_name (| globals, "coinbase_balance_after_mining_fee" |) + ], + make_dict [] + |) in + let _ := + M.for_ (| + M.get_name (| globals, "address" |), + M.get_field (| M.get_name (| globals, "output" |), "accounts_to_delete" |), + ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, "destroy_account" |), + make_list [ + M.get_field (| M.get_name (| globals, "env" |), "state" |); + M.get_name (| globals, "address" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := M.return_ (| + make_tuple [ M.get_name (| globals, "total_gas_used" |); M.get_field (| M.get_name (| globals, "output" |), "logs" |) ] + |) in + M.pure Constant.None_)). + +Definition validate_transaction : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "tx" ] |) in + let _ := Constant.str " + Verifies a transaction. + + The gas in a transaction gets used to pay for the intrinsic cost of + operations, therefore if there is insufficient gas then it would not + be possible to execute a transaction and it will be declared invalid. + + Additionally, the nonce of a transaction must not equal or exceed the + limit defined in `EIP-2681 `_. + In practice, defining the limit as ``2**64-1`` has no impact because + sending ``2**64-1`` transactions is improbable. It's not strictly + impossible though, ``2**64-1`` transactions is the entire capacity of the + Ethereum blockchain at 2022 gas limits for a little over 22 years. + + Parameters + ---------- + tx : + Transaction to validate. + + Returns + ------- + verified : `bool` + True if the transaction can be executed, or False otherwise. + " in + let _ := M.return_ (| + BoolOp.and (| + Compare.lt_e (| + M.call (| + M.get_name (| globals, "calculate_intrinsic_cost" |), + make_list [ + M.get_name (| globals, "tx" |) + ], + make_dict [] + |), + M.get_field (| M.get_name (| globals, "tx" |), "gas" |) + |), + ltac:(M.monadic ( + Compare.lt (| + M.get_field (| M.get_name (| globals, "tx" |), "nonce" |), + BinOp.sub (| + BinOp.pow (| + Constant.int 2, + Constant.int 64 + |), + Constant.int 1 + |) + |) + )) + |) + |) in + M.pure Constant.None_)). + +Definition calculate_intrinsic_cost : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "tx" ] |) in + let _ := Constant.str " + Calculates the gas that is charged before execution is started. + + The intrinsic cost of the transaction is charged before execution has + begun. Functions/operations in the EVM cost money to execute so this + intrinsic cost is for the operations that need to be paid for as part of + the transaction. Data transfer, for example, is part of this intrinsic + cost. It costs ether to send data over the wire and that ether is + accounted for in the intrinsic cost calculated in this function. This + intrinsic cost must be calculated and paid for before execution in order + for all operations to be implemented. + + Parameters + ---------- + tx : + Transaction to compute the intrinsic cost of. + + Returns + ------- + verified : `ethereum.base_types.Uint` + The intrinsic cost of the transaction. + " in + let _ := M.assign_local (| + "data_cost" , + Constant.int 0 + |) in + let _ := + M.for_ (| + M.get_name (| globals, "byte" |), + M.get_field (| M.get_name (| globals, "tx" |), "data" |), + ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, "byte" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_op_local (| + BinOp.add, + "data_cost", + M.get_name (| globals, "TX_DATA_COST_PER_ZERO" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_op_local (| + BinOp.add, + "data_cost", + M.get_name (| globals, "TX_DATA_COST_PER_NON_ZERO" |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + BinOp.add (| + M.get_name (| globals, "TX_BASE_COST" |), + M.get_name (| globals, "data_cost" |) + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Definition recover_sender : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "tx" ] |) in + let _ := Constant.str " + Extracts the sender address from a transaction. + + The v, r, and s values are the three parts that make up the signature + of a transaction. In order to recover the sender of a transaction the two + components needed are the signature (``v``, ``r``, and ``s``) and the + signing hash of the transaction. The sender's public key can be obtained + with these two values and therefore the sender address can be retrieved. + + Parameters + ---------- + tx : + Transaction of interest. + + Returns + ------- + sender : `ethereum.fork_types.Address` + The address of the account that signed the transaction. + " in + let _ := M.assign (| + make_tuple [ M.get_name (| globals, "v" |); M.get_name (| globals, "r" |); M.get_name (| globals, "s" |) ], + make_tuple [ M.get_field (| M.get_name (| globals, "tx" |), "v" |); M.get_field (| M.get_name (| globals, "tx" |), "r" |); M.get_field (| M.get_name (| globals, "tx" |), "s" |) ] + |) in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + BoolOp.or (| + Compare.eq (| + M.get_name (| globals, "v" |), + Constant.int 27 + |), + ltac:(M.monadic ( + Compare.eq (| + M.get_name (| globals, "v" |), + Constant.int 28 + |) + )) + |); + M.get_name (| globals, "InvalidBlock" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + BoolOp.and (| + Compare.lt (| + Constant.int 0, + M.get_name (| globals, "r" |) + |), + ltac:(M.monadic ( + Compare.lt (| + M.get_name (| globals, "r" |), + M.get_name (| globals, "SECP256K1N" |) + |) + )) + |); + M.get_name (| globals, "InvalidBlock" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + BoolOp.and (| + Compare.lt (| + Constant.int 0, + M.get_name (| globals, "s" |) + |), + ltac:(M.monadic ( + Compare.lt (| + M.get_name (| globals, "s" |), + M.get_name (| globals, "SECP256K1N" |) + |) + )) + |); + M.get_name (| globals, "InvalidBlock" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "public_key" , + M.call (| + M.get_name (| globals, "secp256k1_recover" |), + make_list [ + M.get_name (| globals, "r" |); + M.get_name (| globals, "s" |); + BinOp.sub (| + M.get_name (| globals, "v" |), + Constant.int 27 + |); + M.call (| + M.get_name (| globals, "signing_hash" |), + make_list [ + M.get_name (| globals, "tx" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, "Address" |), + make_list [ + M.slice (| + M.call (| + M.get_name (| globals, "keccak256" |), + make_list [ + M.get_name (| globals, "public_key" |) + ], + make_dict [] + |), + Constant.int 12, + Constant.int 32, + Constant.None_ + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Definition signing_hash : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "tx" ] |) in + let _ := Constant.str " + Compute the hash of a transaction used in the signature. + + The values that are used to compute the signing hash set the rules for a + transaction. For example, signing over the gas sets a limit for the + amount of money that is allowed to be pulled out of the sender's account. + + Parameters + ---------- + tx : + Transaction of interest. + + Returns + ------- + hash : `ethereum.crypto.hash.Hash32` + Hash of the transaction. + " in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, "keccak256" |), + make_list [ + M.call (| + M.get_field (| M.get_name (| globals, "rlp" |), "encode" |), + make_list [ + make_tuple [ M.get_field (| M.get_name (| globals, "tx" |), "nonce" |); M.get_field (| M.get_name (| globals, "tx" |), "gas_price" |); M.get_field (| M.get_name (| globals, "tx" |), "gas" |); M.get_field (| M.get_name (| globals, "tx" |), "to" |); M.get_field (| M.get_name (| globals, "tx" |), "value" |); M.get_field (| M.get_name (| globals, "tx" |), "data" |) ] + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Definition compute_header_hash : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "header" ] |) in + let _ := Constant.str " + Computes the hash of a block header. + + The header hash of a block is the canonical hash that is used to refer + to a specific block and completely distinguishes a block from another. + + ``keccak256`` is a function that produces a 256 bit hash of any input. + It also takes in any number of bytes as an input and produces a single + hash for them. A hash is a completely unique output for a single input. + So an input corresponds to one unique hash that can be used to identify + the input exactly. + + Prior to using the ``keccak256`` hash function, the header must be + encoded using the Recursive-Length Prefix. See :ref:`rlp`. + RLP encoding the header converts it into a space-efficient format that + allows for easy transfer of data between nodes. The purpose of RLP is to + encode arbitrarily nested arrays of binary data, and RLP is the primary + encoding method used to serialize objects in Ethereum's execution layer. + The only purpose of RLP is to encode structure; encoding specific data + types (e.g. strings, floats) is left up to higher-order protocols. + + Parameters + ---------- + header : + Header of interest. + + Returns + ------- + hash : `ethereum.crypto.hash.Hash32` + Hash of the header. + " in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, "keccak256" |), + make_list [ + M.call (| + M.get_field (| M.get_name (| globals, "rlp" |), "encode" |), + make_list [ + M.get_name (| globals, "header" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Definition check_gas_limit : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "gas_limit"; "parent_gas_limit" ] |) in + let _ := Constant.str " + Validates the gas limit for a block. + + The bounds of the gas limit, ``max_adjustment_delta``, is set as the + quotient of the parent block's gas limit and the + ``GAS_LIMIT_ADJUSTMENT_FACTOR``. Therefore, if the gas limit that is + passed through as a parameter is greater than or equal to the *sum* of + the parent's gas and the adjustment delta then the limit for gas is too + high and fails this function's check. Similarly, if the limit is less + than or equal to the *difference* of the parent's gas and the adjustment + delta *or* the predefined ``GAS_LIMIT_MINIMUM`` then this function's + check fails because the gas limit doesn't allow for a sufficient or + reasonable amount of gas to be used on a block. + + Parameters + ---------- + gas_limit : + Gas limit to validate. + + parent_gas_limit : + Gas limit of the parent block. + + Returns + ------- + check : `bool` + True if gas limit constraints are satisfied, False otherwise. + " in + let _ := M.assign_local (| + "max_adjustment_delta" , + BinOp.floor_div (| + M.get_name (| globals, "parent_gas_limit" |), + M.get_name (| globals, "GAS_LIMIT_ADJUSTMENT_FACTOR" |) + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.gt_e (| + M.get_name (| globals, "gas_limit" |), + BinOp.add (| + M.get_name (| globals, "parent_gas_limit" |), + M.get_name (| globals, "max_adjustment_delta" |) + |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + Constant.bool false + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + Compare.lt_e (| + M.get_name (| globals, "gas_limit" |), + BinOp.sub (| + M.get_name (| globals, "parent_gas_limit" |), + M.get_name (| globals, "max_adjustment_delta" |) + |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + Constant.bool false + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + Compare.lt (| + M.get_name (| globals, "gas_limit" |), + M.get_name (| globals, "GAS_LIMIT_MINIMUM" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + Constant.bool false + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.return_ (| + Constant.bool true + |) in + M.pure Constant.None_)). + +Definition calculate_block_difficulty : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "block_number"; "block_timestamp"; "parent_timestamp"; "parent_difficulty" ] |) in + let _ := Constant.str " + Computes difficulty of a block using its header and + parent header. + + The difficulty of a block is determined by the time the block was + created after its parent. If a block's timestamp is more than 13 + seconds after its parent block then its difficulty is set as the + difference between the parent's difficulty and the + ``max_adjustment_delta``. Otherwise, if the time between parent and + child blocks is too small (under 13 seconds) then, to avoid mass + forking, the block's difficulty is set to the sum of the delta and + the parent's difficulty. + + Parameters + ---------- + block_number : + Block number of the block. + block_timestamp : + Timestamp of the block. + parent_timestamp : + Timestamp of the parent block. + parent_difficulty : + difficulty of the parent block. + + Returns + ------- + difficulty : `ethereum.base_types.Uint` + Computed difficulty for a block. + " in + let _ := M.assign_local (| + "max_adjustment_delta" , + BinOp.floor_div (| + M.get_name (| globals, "parent_difficulty" |), + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 2048 + ], + make_dict [] + |) + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.lt (| + M.get_name (| globals, "block_timestamp" |), + BinOp.add (| + M.get_name (| globals, "parent_timestamp" |), + Constant.int 13 + |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "difficulty" , + BinOp.add (| + M.get_name (| globals, "parent_difficulty" |), + M.get_name (| globals, "max_adjustment_delta" |) + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "difficulty" , + BinOp.sub (| + M.get_name (| globals, "parent_difficulty" |), + M.get_name (| globals, "max_adjustment_delta" |) + |) + |) in + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "num_bomb_periods" , + BinOp.sub (| + BinOp.floor_div (| + M.call (| + M.get_name (| globals, "int" |), + make_list [ + M.get_name (| globals, "block_number" |) + ], + make_dict [] + |), + Constant.int 100000 + |), + Constant.int 2 + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.gt_e (| + M.get_name (| globals, "num_bomb_periods" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_op_local (| + BinOp.add, + "difficulty", + BinOp.pow (| + Constant.int 2, + M.get_name (| globals, "num_bomb_periods" |) + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, "max" |), + make_list [ + M.get_name (| globals, "difficulty" |); + M.get_name (| globals, "MINIMUM_DIFFICULTY" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). diff --git a/CoqOfPython/ethereum/frontier/fork_types.v b/CoqOfPython/ethereum/frontier/fork_types.v new file mode 100644 index 0000000..1b8eb64 --- /dev/null +++ b/CoqOfPython/ethereum/frontier/fork_types.v @@ -0,0 +1,98 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.frontier.fork_types". + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Types +^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Types re-used throughout the specification, which are specific to Ethereum. +". + +Axiom dataclasses_imports_dataclass : + IsImported globals "dataclasses" "dataclass". + +Axiom ethereum_imports_rlp : + IsImported globals "ethereum" "rlp". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_Bytes : + IsImported globals "ethereum.base_types" "Bytes". +Axiom ethereum_base_types_imports_Bytes20 : + IsImported globals "ethereum.base_types" "Bytes20". +Axiom ethereum_base_types_imports_Bytes256 : + IsImported globals "ethereum.base_types" "Bytes256". +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". +Axiom ethereum_base_types_imports_slotted_freezable : + IsImported globals "ethereum.base_types" "slotted_freezable". + +Axiom ethereum_crypto_hash_imports_Hash32 : + IsImported globals "ethereum.crypto.hash" "Hash32". +Axiom ethereum_crypto_hash_imports_keccak256 : + IsImported globals "ethereum.crypto.hash" "keccak256". + +Definition Address : Value.t := M.run ltac:(M.monadic ( + M.get_name (| globals, "Bytes20" |) +)). + +Definition Root : Value.t := M.run ltac:(M.monadic ( + M.get_name (| globals, "Hash32" |) +)). + +Definition Bloom : Value.t := M.run ltac:(M.monadic ( + M.get_name (| globals, "Bytes256" |) +)). + +Definition Account : Value.t := + builtins.make_klass + [] + [ + + ] + [ + + ]. + +Definition EMPTY_ACCOUNT : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Account" |), + make_list [], + make_dict [] + |) +)). + +Definition encode_account : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "raw_account_data"; "storage_root" ] |) in + let _ := Constant.str " + Encode `Account` dataclass. + + Storage is not stored in the `Account` dataclass, so `Accounts` cannot be + encoded with providing a storage root. + " in + let _ := M.return_ (| + M.call (| + M.get_field (| M.get_name (| globals, "rlp" |), "encode" |), + make_list [ + make_tuple [ M.get_field (| M.get_name (| globals, "raw_account_data" |), "nonce" |); M.get_field (| M.get_name (| globals, "raw_account_data" |), "balance" |); M.get_name (| globals, "storage_root" |); M.call (| + M.get_name (| globals, "keccak256" |), + make_list [ + M.get_field (| M.get_name (| globals, "raw_account_data" |), "code" |) + ], + make_dict [] + |) ] + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). diff --git a/CoqOfPython/ethereum/frontier/state.v b/CoqOfPython/ethereum/frontier/state.v new file mode 100644 index 0000000..4e111a2 --- /dev/null +++ b/CoqOfPython/ethereum/frontier/state.v @@ -0,0 +1,906 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.frontier.state". + +Definition expr_1 : Value.t := + Constant.str " +State +^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +The state contains all information that is preserved between transactions. + +It consists of a main account trie and storage tries for each contract. + +There is a distinction between an account that does not exist and +`EMPTY_ACCOUNT`. +". + +Axiom dataclasses_imports_dataclass : + IsImported globals "dataclasses" "dataclass". +Axiom dataclasses_imports_field : + IsImported globals "dataclasses" "field". + +Axiom typing_imports_Callable : + IsImported globals "typing" "Callable". +Axiom typing_imports_Dict : + IsImported globals "typing" "Dict". +Axiom typing_imports_List : + IsImported globals "typing" "List". +Axiom typing_imports_Optional : + IsImported globals "typing" "Optional". +Axiom typing_imports_Tuple : + IsImported globals "typing" "Tuple". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_Bytes : + IsImported globals "ethereum.base_types" "Bytes". +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". +Axiom ethereum_base_types_imports_modify : + IsImported globals "ethereum.base_types" "modify". + +Axiom ethereum_utils_ensure_imports_ensure : + IsImported globals "ethereum.utils.ensure" "ensure". + +Axiom ethereum_frontier_fork_types_imports_EMPTY_ACCOUNT : + IsImported globals "ethereum.frontier.fork_types" "EMPTY_ACCOUNT". +Axiom ethereum_frontier_fork_types_imports_Account : + IsImported globals "ethereum.frontier.fork_types" "Account". +Axiom ethereum_frontier_fork_types_imports_Address : + IsImported globals "ethereum.frontier.fork_types" "Address". +Axiom ethereum_frontier_fork_types_imports_Root : + IsImported globals "ethereum.frontier.fork_types" "Root". + +Axiom ethereum_frontier_trie_imports_EMPTY_TRIE_ROOT : + IsImported globals "ethereum.frontier.trie" "EMPTY_TRIE_ROOT". +Axiom ethereum_frontier_trie_imports_Trie : + IsImported globals "ethereum.frontier.trie" "Trie". +Axiom ethereum_frontier_trie_imports_copy_trie : + IsImported globals "ethereum.frontier.trie" "copy_trie". +Axiom ethereum_frontier_trie_imports_root : + IsImported globals "ethereum.frontier.trie" "root". +Axiom ethereum_frontier_trie_imports_trie_get : + IsImported globals "ethereum.frontier.trie" "trie_get". +Axiom ethereum_frontier_trie_imports_trie_set : + IsImported globals "ethereum.frontier.trie" "trie_set". + +Definition State : Value.t := + builtins.make_klass + [] + [ + + ] + [ + + ]. + +Definition close_state : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "state" ] |) in + let _ := Constant.str " + Free resources held by the state. Used by optimized implementations to + release file descriptors. + " in + let _ := M.delete (| M.get_field (| M.get_name (| globals, "state" |), "_main_trie" |) |) in + let _ := M.delete (| M.get_field (| M.get_name (| globals, "state" |), "_storage_tries" |) |) in + let _ := M.delete (| M.get_field (| M.get_name (| globals, "state" |), "_snapshots" |) |) in + M.pure Constant.None_)). + +Definition begin_transaction : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "state" ] |) in + let _ := Constant.str " + Start a state transaction. + + Transactions are entirely implicit and can be nested. It is not possible to + calculate the state root during a transaction. + + Parameters + ---------- + state : State + The state. + " in + let _ := M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, "state" |), "_snapshots" |), "append" |), + make_list [ + make_tuple [ M.call (| + M.get_name (| globals, "copy_trie" |), + make_list [ + M.get_field (| M.get_name (| globals, "state" |), "_main_trie" |) + ], + make_dict [] + |); Constant.str "(* At expr: unsupported node type: DictComp *)" ] + ], + make_dict [] + |) in + M.pure Constant.None_)). + +Definition commit_transaction : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "state" ] |) in + let _ := Constant.str " + Commit a state transaction. + + Parameters + ---------- + state : State + The state. + " in + let _ := M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, "state" |), "_snapshots" |), "pop" |), + make_list [], + make_dict [] + |) in + M.pure Constant.None_)). + +Definition rollback_transaction : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "state" ] |) in + let _ := Constant.str " + Rollback a state transaction, resetting the state to the point when the + corresponding `start_transaction()` call was made. + + Parameters + ---------- + state : State + The state. + " in + let _ := M.assign (| + make_tuple [ M.get_field (| M.get_name (| globals, "state" |), "_main_trie" |); M.get_field (| M.get_name (| globals, "state" |), "_storage_tries" |) ], + M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, "state" |), "_snapshots" |), "pop" |), + make_list [], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Definition get_account : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "state"; "address" ] |) in + let _ := Constant.str " + Get the `Account` object at an address. Returns `EMPTY_ACCOUNT` if there + is no account at the address. + + Use `get_account_optional()` if you care about the difference between a + non-existent account and `EMPTY_ACCOUNT`. + + Parameters + ---------- + state: `State` + The state + address : `Address` + Address to lookup. + + Returns + ------- + account : `Account` + Account at address. + " in + let _ := M.assign_local (| + "account" , + M.call (| + M.get_name (| globals, "get_account_optional" |), + make_list [ + M.get_name (| globals, "state" |); + M.get_name (| globals, "address" |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, "isinstance" |), + make_list [ + M.get_name (| globals, "account" |); + M.get_name (| globals, "Account" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + M.get_name (| globals, "account" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.return_ (| + M.get_name (| globals, "EMPTY_ACCOUNT" |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_)). + +Definition get_account_optional : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "state"; "address" ] |) in + let _ := Constant.str " + Get the `Account` object at an address. Returns `None` (rather than + `EMPTY_ACCOUNT`) if there is no account at the address. + + Parameters + ---------- + state: `State` + The state + address : `Address` + Address to lookup. + + Returns + ------- + account : `Account` + Account at address. + " in + let _ := M.assign_local (| + "account" , + M.call (| + M.get_name (| globals, "trie_get" |), + make_list [ + M.get_field (| M.get_name (| globals, "state" |), "_main_trie" |); + M.get_name (| globals, "address" |) + ], + make_dict [] + |) + |) in + let _ := M.return_ (| + M.get_name (| globals, "account" |) + |) in + M.pure Constant.None_)). + +Definition set_account : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "state"; "address"; "account" ] |) in + let _ := Constant.str " + Set the `Account` object at an address. Setting to `None` deletes + the account (but not its storage, see `destroy_account()`). + + Parameters + ---------- + state: `State` + The state + address : `Address` + Address to set. + account : `Account` + Account to set at address. + " in + let _ := M.call (| + M.get_name (| globals, "trie_set" |), + make_list [ + M.get_field (| M.get_name (| globals, "state" |), "_main_trie" |); + M.get_name (| globals, "address" |); + M.get_name (| globals, "account" |) + ], + make_dict [] + |) in + M.pure Constant.None_)). + +Definition destroy_account : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "state"; "address" ] |) in + let _ := Constant.str " + Completely remove the account at `address` and all of its storage. + + This function is made available exclusively for the `SELFDESTRUCT` + opcode. It is expected that `SELFDESTRUCT` will be disabled in a future + hardfork and this function will be removed. + + Parameters + ---------- + state: `State` + The state + address : `Address` + Address of account to destroy. + " in + let _ := M.call (| + M.get_name (| globals, "destroy_storage" |), + make_list [ + M.get_name (| globals, "state" |); + M.get_name (| globals, "address" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "set_account" |), + make_list [ + M.get_name (| globals, "state" |); + M.get_name (| globals, "address" |); + Constant.None_ + ], + make_dict [] + |) in + M.pure Constant.None_)). + +Definition destroy_storage : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "state"; "address" ] |) in + let _ := Constant.str " + Completely remove the storage at `address`. + + Parameters + ---------- + state: `State` + The state + address : `Address` + Address of account whose storage is to be deleted. + " in + let _ := + (* if *) + M.if_then_else (| + Compare.in_ (| + M.get_name (| globals, "address" |), + M.get_field (| M.get_name (| globals, "state" |), "_storage_tries" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.delete (| M.get_subscript (| + M.get_field (| M.get_name (| globals, "state" |), "_storage_tries" |), + M.get_name (| globals, "address" |) + |) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + M.pure Constant.None_)). + +Definition get_storage : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "state"; "address"; "key" ] |) in + let _ := Constant.str " + Get a value at a storage key on an account. Returns `U256(0)` if the + storage key has not been set previously. + + Parameters + ---------- + state: `State` + The state + address : `Address` + Address of the account. + key : `Bytes` + Key to lookup. + + Returns + ------- + value : `U256` + Value at the key. + " in + let _ := M.assign_local (| + "trie" , + M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, "state" |), "_storage_tries" |), "get" |), + make_list [ + M.get_name (| globals, "address" |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.is (| + M.get_name (| globals, "trie" |), + Constant.None_ + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "value" , + M.call (| + M.get_name (| globals, "trie_get" |), + make_list [ + M.get_name (| globals, "trie" |); + M.get_name (| globals, "key" |) + ], + make_dict [] + |) + |) in + let _ := M.assert (| M.call (| + M.get_name (| globals, "isinstance" |), + make_list [ + M.get_name (| globals, "value" |); + M.get_name (| globals, "U256" |) + ], + make_dict [] + |) |) in + let _ := M.return_ (| + M.get_name (| globals, "value" |) + |) in + M.pure Constant.None_)). + +Definition set_storage : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "state"; "address"; "key"; "value" ] |) in + let _ := Constant.str " + Set a value at a storage key on an account. Setting to `U256(0)` deletes + the key. + + Parameters + ---------- + state: `State` + The state + address : `Address` + Address of the account. + key : `Bytes` + Key to set. + value : `U256` + Value to set at the key. + " in + let _ := M.assert (| Compare.is_not (| + M.call (| + M.get_name (| globals, "trie_get" |), + make_list [ + M.get_field (| M.get_name (| globals, "state" |), "_main_trie" |); + M.get_name (| globals, "address" |) + ], + make_dict [] + |), + Constant.None_ + |) |) in + let _ := M.assign_local (| + "trie" , + M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, "state" |), "_storage_tries" |), "get" |), + make_list [ + M.get_name (| globals, "address" |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.is (| + M.get_name (| globals, "trie" |), + Constant.None_ + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "trie" , + M.call (| + M.get_name (| globals, "Trie" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.assign (| + M.get_subscript (| + M.get_field (| M.get_name (| globals, "state" |), "_storage_tries" |), + M.get_name (| globals, "address" |) + |), + M.get_name (| globals, "trie" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.call (| + M.get_name (| globals, "trie_set" |), + make_list [ + M.get_name (| globals, "trie" |); + M.get_name (| globals, "key" |); + M.get_name (| globals, "value" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_field (| M.get_name (| globals, "trie" |), "_data" |), + Constant.str "(* At expr: unsupported node type: Dict *)" + |), + (* then *) + ltac:(M.monadic ( + let _ := M.delete (| M.get_subscript (| + M.get_field (| M.get_name (| globals, "state" |), "_storage_tries" |), + M.get_name (| globals, "address" |) + |) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + M.pure Constant.None_)). + +Definition storage_root : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "state"; "address" ] |) in + let _ := Constant.str " + Calculate the storage root of an account. + + Parameters + ---------- + state: + The state + address : + Address of the account. + + Returns + ------- + root : `Root` + Storage root of the account. + " in + let _ := M.assert (| UnOp.not (| M.get_field (| M.get_name (| globals, "state" |), "_snapshots" |) |) |) in + let _ := + (* if *) + M.if_then_else (| + Compare.in_ (| + M.get_name (| globals, "address" |), + M.get_field (| M.get_name (| globals, "state" |), "_storage_tries" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + M.call (| + M.get_name (| globals, "root" |), + make_list [ + M.get_subscript (| + M.get_field (| M.get_name (| globals, "state" |), "_storage_tries" |), + M.get_name (| globals, "address" |) + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.return_ (| + M.get_name (| globals, "EMPTY_TRIE_ROOT" |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_)). + +Definition state_root : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "state" ] |) in + let _ := Constant.str " + Calculate the state root. + + Parameters + ---------- + state: + The current state. + + Returns + ------- + root : `Root` + The state root. + " in + let _ := M.assert (| UnOp.not (| M.get_field (| M.get_name (| globals, "state" |), "_snapshots" |) |) |) in +(* At stmt: unsupported node type: FunctionDef *) + let _ := M.return_ (| + M.call (| + M.get_name (| globals, "root" |), + make_list [ + M.get_field (| M.get_name (| globals, "state" |), "_main_trie" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Definition account_exists : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "state"; "address" ] |) in + let _ := Constant.str " + Checks if an account exists in the state trie + + Parameters + ---------- + state: + The state + address: + Address of the account that needs to be checked. + + Returns + ------- + account_exists : `bool` + True if account exists in the state trie, False otherwise + " in + let _ := M.return_ (| + Compare.is_not (| + M.call (| + M.get_name (| globals, "get_account_optional" |), + make_list [ + M.get_name (| globals, "state" |); + M.get_name (| globals, "address" |) + ], + make_dict [] + |), + Constant.None_ + |) + |) in + M.pure Constant.None_)). + +Definition account_has_code_or_nonce : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "state"; "address" ] |) in + let _ := Constant.str " + Checks if an account has non zero nonce or non empty code + + Parameters + ---------- + state: + The state + address: + Address of the account that needs to be checked. + + Returns + ------- + has_code_or_nonce : `bool` + True if if an account has non zero nonce or non empty code, + False otherwise. + " in + let _ := M.assign_local (| + "account" , + M.call (| + M.get_name (| globals, "get_account" |), + make_list [ + M.get_name (| globals, "state" |); + M.get_name (| globals, "address" |) + ], + make_dict [] + |) + |) in + let _ := M.return_ (| + BoolOp.or (| + Compare.not_eq (| + M.get_field (| M.get_name (| globals, "account" |), "nonce" |), + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + |), + ltac:(M.monadic ( + Compare.not_eq (| + M.get_field (| M.get_name (| globals, "account" |), "code" |), + Constant.bytes "" + |) + )) + |) + |) in + M.pure Constant.None_)). + +Definition modify_state : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "state"; "address"; "f" ] |) in + let _ := Constant.str " + Modify an `Account` in the `State`. + " in + let _ := M.call (| + M.get_name (| globals, "set_account" |), + make_list [ + M.get_name (| globals, "state" |); + M.get_name (| globals, "address" |); + M.call (| + M.get_name (| globals, "modify" |), + make_list [ + M.call (| + M.get_name (| globals, "get_account" |), + make_list [ + M.get_name (| globals, "state" |); + M.get_name (| globals, "address" |) + ], + make_dict [] + |); + M.get_name (| globals, "f" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + M.pure Constant.None_)). + +Definition move_ether : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "state"; "sender_address"; "recipient_address"; "amount" ] |) in + let _ := Constant.str " + Move funds between accounts. + " in +(* At stmt: unsupported node type: FunctionDef *) +(* At stmt: unsupported node type: FunctionDef *) + let _ := M.call (| + M.get_name (| globals, "modify_state" |), + make_list [ + M.get_name (| globals, "state" |); + M.get_name (| globals, "sender_address" |); + M.get_name (| globals, "reduce_sender_balance" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "modify_state" |), + make_list [ + M.get_name (| globals, "state" |); + M.get_name (| globals, "recipient_address" |); + M.get_name (| globals, "increase_recipient_balance" |) + ], + make_dict [] + |) in + M.pure Constant.None_)). + +Definition set_account_balance : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "state"; "address"; "amount" ] |) in + let _ := Constant.str " + Sets the balance of an account. + + Parameters + ---------- + state: + The current state. + + address: + Address of the account whose nonce needs to be incremented. + + amount: + The amount that needs to set in balance. + " in +(* At stmt: unsupported node type: FunctionDef *) + let _ := M.call (| + M.get_name (| globals, "modify_state" |), + make_list [ + M.get_name (| globals, "state" |); + M.get_name (| globals, "address" |); + M.get_name (| globals, "set_balance" |) + ], + make_dict [] + |) in + M.pure Constant.None_)). + +Definition touch_account : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "state"; "address" ] |) in + let _ := Constant.str " + Initializes an account to state. + + Parameters + ---------- + state: + The current state. + + address: + The address of the account that need to initialised. + " in + let _ := + (* if *) + M.if_then_else (| + UnOp.not (| M.call (| + M.get_name (| globals, "account_exists" |), + make_list [ + M.get_name (| globals, "state" |); + M.get_name (| globals, "address" |) + ], + make_dict [] + |) |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, "set_account" |), + make_list [ + M.get_name (| globals, "state" |); + M.get_name (| globals, "address" |); + M.get_name (| globals, "EMPTY_ACCOUNT" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + M.pure Constant.None_)). + +Definition increment_nonce : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "state"; "address" ] |) in + let _ := Constant.str " + Increments the nonce of an account. + + Parameters + ---------- + state: + The current state. + + address: + Address of the account whose nonce needs to be incremented. + " in +(* At stmt: unsupported node type: FunctionDef *) + let _ := M.call (| + M.get_name (| globals, "modify_state" |), + make_list [ + M.get_name (| globals, "state" |); + M.get_name (| globals, "address" |); + M.get_name (| globals, "increase_nonce" |) + ], + make_dict [] + |) in + M.pure Constant.None_)). + +Definition set_code : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "state"; "address"; "code" ] |) in + let _ := Constant.str " + Sets Account code. + + Parameters + ---------- + state: + The current state. + + address: + Address of the account whose code needs to be update. + + code: + The bytecode that needs to be set. + " in +(* At stmt: unsupported node type: FunctionDef *) + let _ := M.call (| + M.get_name (| globals, "modify_state" |), + make_list [ + M.get_name (| globals, "state" |); + M.get_name (| globals, "address" |); + M.get_name (| globals, "write_code" |) + ], + make_dict [] + |) in + M.pure Constant.None_)). + +Definition create_ether : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "state"; "address"; "amount" ] |) in + let _ := Constant.str " + Add newly created ether to an account. + + Parameters + ---------- + state: + The current state. + address: + Address of the account to which ether is added. + amount: + The amount of ether to be added to the account of interest. + " in +(* At stmt: unsupported node type: FunctionDef *) + let _ := M.call (| + M.get_name (| globals, "modify_state" |), + make_list [ + M.get_name (| globals, "state" |); + M.get_name (| globals, "address" |); + M.get_name (| globals, "increase_balance" |) + ], + make_dict [] + |) in + M.pure Constant.None_)). diff --git a/CoqOfPython/ethereum/frontier/transactions.v b/CoqOfPython/ethereum/frontier/transactions.v new file mode 100644 index 0000000..1c30efa --- /dev/null +++ b/CoqOfPython/ethereum/frontier/transactions.v @@ -0,0 +1,52 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.frontier.transactions". + +Definition expr_1 : Value.t := + Constant.str " +Transactions are atomic units of work created externally to Ethereum and +submitted to be executed. If Ethereum is viewed as a state machine, +transactions are the events that move between states. +". + +Axiom dataclasses_imports_dataclass : + IsImported globals "dataclasses" "dataclass". + +Axiom typing_imports_Union : + IsImported globals "typing" "Union". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_Bytes : + IsImported globals "ethereum.base_types" "Bytes". +Axiom ethereum_base_types_imports_Bytes0 : + IsImported globals "ethereum.base_types" "Bytes0". +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". +Axiom ethereum_base_types_imports_slotted_freezable : + IsImported globals "ethereum.base_types" "slotted_freezable". + +Axiom ethereum_frontier_fork_types_imports_Address : + IsImported globals "ethereum.frontier.fork_types" "Address". + +Definition TX_BASE_COST : Value.t := M.run ltac:(M.monadic ( + Constant.int 21000 +)). + +Definition TX_DATA_COST_PER_NON_ZERO : Value.t := M.run ltac:(M.monadic ( + Constant.int 68 +)). + +Definition TX_DATA_COST_PER_ZERO : Value.t := M.run ltac:(M.monadic ( + Constant.int 4 +)). + +Definition Transaction : Value.t := + builtins.make_klass + [] + [ + + ] + [ + + ]. diff --git a/CoqOfPython/ethereum/frontier/trie.v b/CoqOfPython/ethereum/frontier/trie.v new file mode 100644 index 0000000..f92e8c5 --- /dev/null +++ b/CoqOfPython/ethereum/frontier/trie.v @@ -0,0 +1,1583 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.frontier.trie". + +Definition expr_1 : Value.t := + Constant.str " +State Trie +^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +The state trie is the structure responsible for storing +`.fork_types.Account` objects. +". + +(* At top_level_stmt: unsupported node type: Import *) + +Axiom dataclasses_imports_dataclass : + IsImported globals "dataclasses" "dataclass". +Axiom dataclasses_imports_field : + IsImported globals "dataclasses" "field". + +Axiom typing_imports_Callable : + IsImported globals "typing" "Callable". +Axiom typing_imports_Dict : + IsImported globals "typing" "Dict". +Axiom typing_imports_Generic : + IsImported globals "typing" "Generic". +Axiom typing_imports_List : + IsImported globals "typing" "List". +Axiom typing_imports_Mapping : + IsImported globals "typing" "Mapping". +Axiom typing_imports_MutableMapping : + IsImported globals "typing" "MutableMapping". +Axiom typing_imports_Optional : + IsImported globals "typing" "Optional". +Axiom typing_imports_Sequence : + IsImported globals "typing" "Sequence". +Axiom typing_imports_TypeVar : + IsImported globals "typing" "TypeVar". +Axiom typing_imports_Union : + IsImported globals "typing" "Union". +Axiom typing_imports_cast : + IsImported globals "typing" "cast". + +Axiom ethereum_crypto_hash_imports_keccak256 : + IsImported globals "ethereum.crypto.hash" "keccak256". + +Axiom ethereum_utils_ensure_imports_ensure : + IsImported globals "ethereum.utils.ensure" "ensure". + +Axiom ethereum_utils_hexadecimal_imports_hex_to_bytes : + IsImported globals "ethereum.utils.hexadecimal" "hex_to_bytes". + +Axiom ethereum_imports_rlp : + IsImported globals "ethereum" "rlp". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_Bytes : + IsImported globals "ethereum.base_types" "Bytes". +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". +Axiom ethereum_base_types_imports_slotted_freezable : + IsImported globals "ethereum.base_types" "slotted_freezable". + +Axiom ethereum_frontier_blocks_imports_Receipt : + IsImported globals "ethereum.frontier.blocks" "Receipt". + +Axiom ethereum_frontier_fork_types_imports_Account : + IsImported globals "ethereum.frontier.fork_types" "Account". +Axiom ethereum_frontier_fork_types_imports_Address : + IsImported globals "ethereum.frontier.fork_types" "Address". +Axiom ethereum_frontier_fork_types_imports_Root : + IsImported globals "ethereum.frontier.fork_types" "Root". +Axiom ethereum_frontier_fork_types_imports_encode_account : + IsImported globals "ethereum.frontier.fork_types" "encode_account". + +Axiom ethereum_frontier_transactions_imports_Transaction : + IsImported globals "ethereum.frontier.transactions" "Transaction". + +Definition EMPTY_TRIE_ROOT : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Root" |), + make_list [ + M.call (| + M.get_name (| globals, "hex_to_bytes" |), + make_list [ + Constant.str "56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421" + ], + make_dict [] + |) + ], + make_dict [] + |) +)). + +Definition Node : Value.t := M.run ltac:(M.monadic ( + M.get_subscript (| + M.get_name (| globals, "Union" |), + make_tuple [ M.get_name (| globals, "Account" |); M.get_name (| globals, "Bytes" |); M.get_name (| globals, "Transaction" |); M.get_name (| globals, "Receipt" |); M.get_name (| globals, "Uint" |); M.get_name (| globals, "U256" |); Constant.None_ ] + |) +)). + +Definition K : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "TypeVar" |), + make_list [ + Constant.str "K" + ], + make_dict [] + |) +)). + +Definition V : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "TypeVar" |), + make_list [ + Constant.str "V"; + M.get_subscript (| + M.get_name (| globals, "Optional" |), + M.get_name (| globals, "Account" |) + |); + M.get_subscript (| + M.get_name (| globals, "Optional" |), + M.get_name (| globals, "Bytes" |) + |); + M.get_name (| globals, "Bytes" |); + M.get_subscript (| + M.get_name (| globals, "Optional" |), + M.get_name (| globals, "Transaction" |) + |); + M.get_subscript (| + M.get_name (| globals, "Optional" |), + M.get_name (| globals, "Receipt" |) + |); + M.get_name (| globals, "Uint" |); + M.get_name (| globals, "U256" |) + ], + make_dict [] + |) +)). + +Definition LeafNode : Value.t := + builtins.make_klass + [] + [ + + ] + [ + + ]. + +Definition ExtensionNode : Value.t := + builtins.make_klass + [] + [ + + ] + [ + + ]. + +Definition BranchNode : Value.t := + builtins.make_klass + [] + [ + + ] + [ + + ]. + +Definition InternalNode : Value.t := M.run ltac:(M.monadic ( + M.get_subscript (| + M.get_name (| globals, "Union" |), + make_tuple [ M.get_name (| globals, "LeafNode" |); M.get_name (| globals, "ExtensionNode" |); M.get_name (| globals, "BranchNode" |) ] + |) +)). + +Definition encode_internal_node : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "node" ] |) in + let _ := Constant.str " + Encodes a Merkle Trie node into its RLP form. The RLP will then be + serialized into a `Bytes` and hashed unless it is less that 32 bytes + when serialized. + + This function also accepts `None`, representing the absence of a node, + which is encoded to `b""""`. + + Parameters + ---------- + node : Optional[InternalNode] + The node to encode. + + Returns + ------- + encoded : `rlp.RLP` + The node encoded as RLP. + " in +(* At stmt: unsupported node type: AnnAssign *) + let _ := + (* if *) + M.if_then_else (| + Compare.is (| + M.get_name (| globals, "node" |), + Constant.None_ + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "unencoded" , + Constant.bytes "" + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, "isinstance" |), + make_list [ + M.get_name (| globals, "node" |); + M.get_name (| globals, "LeafNode" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "unencoded" , + make_tuple [ M.call (| + M.get_name (| globals, "nibble_list_to_compact" |), + make_list [ + M.get_field (| M.get_name (| globals, "node" |), "rest_of_key" |); + Constant.bool true + ], + make_dict [] + |); M.get_field (| M.get_name (| globals, "node" |), "value" |) ] + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, "isinstance" |), + make_list [ + M.get_name (| globals, "node" |); + M.get_name (| globals, "ExtensionNode" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "unencoded" , + make_tuple [ M.call (| + M.get_name (| globals, "nibble_list_to_compact" |), + make_list [ + M.get_field (| M.get_name (| globals, "node" |), "key_segment" |); + Constant.bool false + ], + make_dict [] + |); M.get_field (| M.get_name (| globals, "node" |), "subnode" |) ] + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, "isinstance" |), + make_list [ + M.get_name (| globals, "node" |); + M.get_name (| globals, "BranchNode" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "unencoded" , + BinOp.add (| + M.get_field (| M.get_name (| globals, "node" |), "subnodes" |), + make_list [ + M.get_field (| M.get_name (| globals, "node" |), "value" |) + ] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.raise (| Some (M.call (| + M.get_name (| globals, "AssertionError" |), + make_list [ + Constant.str "(* At expr: unsupported node type: JoinedStr *)" + ], + make_dict [] + |)) |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "encoded" , + M.call (| + M.get_field (| M.get_name (| globals, "rlp" |), "encode" |), + make_list [ + M.get_name (| globals, "unencoded" |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.lt (| + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_name (| globals, "encoded" |) + ], + make_dict [] + |), + Constant.int 32 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + M.get_name (| globals, "unencoded" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.return_ (| + M.call (| + M.get_name (| globals, "keccak256" |), + make_list [ + M.get_name (| globals, "encoded" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_)). + +Definition encode_node : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "node"; "storage_root" ] |) in + let _ := Constant.str " + Encode a Node for storage in the Merkle Trie. + + Currently mostly an unimplemented stub. + " in + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, "isinstance" |), + make_list [ + M.get_name (| globals, "node" |); + M.get_name (| globals, "Account" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assert (| Compare.is_not (| + M.get_name (| globals, "storage_root" |), + Constant.None_ + |) |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, "encode_account" |), + make_list [ + M.get_name (| globals, "node" |); + M.get_name (| globals, "storage_root" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, "isinstance" |), + make_list [ + M.get_name (| globals, "node" |); + make_tuple [ M.get_name (| globals, "Transaction" |); M.get_name (| globals, "Receipt" |); M.get_name (| globals, "U256" |) ] + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + M.call (| + M.get_field (| M.get_name (| globals, "rlp" |), "encode" |), + make_list [ + M.call (| + M.get_name (| globals, "cast" |), + make_list [ + M.get_field (| M.get_name (| globals, "rlp" |), "RLP" |); + M.get_name (| globals, "node" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, "isinstance" |), + make_list [ + M.get_name (| globals, "node" |); + M.get_name (| globals, "Bytes" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + M.get_name (| globals, "node" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.raise (| Some (M.call (| + M.get_name (| globals, "AssertionError" |), + make_list [ + Constant.str "(* At expr: unsupported node type: JoinedStr *)" + ], + make_dict [] + |)) |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_)). + +Definition Trie : Value.t := + builtins.make_klass + [(* At base: unsupported node type: Subscript *)] + [ + + ] + [ + + ]. + +Definition copy_trie : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "trie" ] |) in + let _ := Constant.str " + Create a copy of `trie`. Since only frozen objects may be stored in tries, + the contents are reused. + + Parameters + ---------- + trie: `Trie` + Trie to copy. + + Returns + ------- + new_trie : `Trie[K, V]` + A copy of the trie. + " in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, "Trie" |), + make_list [ + M.get_field (| M.get_name (| globals, "trie" |), "secured" |); + M.get_field (| M.get_name (| globals, "trie" |), "default" |); + M.call (| + M.get_field (| M.get_name (| globals, "copy" |), "copy" |), + make_list [ + M.get_field (| M.get_name (| globals, "trie" |), "_data" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Definition trie_set : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "trie"; "key"; "value" ] |) in + let _ := Constant.str " + Stores an item in a Merkle Trie. + + This method deletes the key if `value == trie.default`, because the Merkle + Trie represents the default value by omitting it from the trie. + + Parameters + ---------- + trie: `Trie` + Trie to store in. + key : `Bytes` + Key to lookup. + value : `V` + Node to insert at `key`. + " in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, "value" |), + M.get_field (| M.get_name (| globals, "trie" |), "default" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + Compare.in_ (| + M.get_name (| globals, "key" |), + M.get_field (| M.get_name (| globals, "trie" |), "_data" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.delete (| M.get_subscript (| + M.get_field (| M.get_name (| globals, "trie" |), "_data" |), + M.get_name (| globals, "key" |) + |) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign (| + M.get_subscript (| + M.get_field (| M.get_name (| globals, "trie" |), "_data" |), + M.get_name (| globals, "key" |) + |), + M.get_name (| globals, "value" |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_)). + +Definition trie_get : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "trie"; "key" ] |) in + let _ := Constant.str " + Gets an item from the Merkle Trie. + + This method returns `trie.default` if the key is missing. + + Parameters + ---------- + trie: + Trie to lookup in. + key : + Key to lookup. + + Returns + ------- + node : `V` + Node at `key` in the trie. + " in + let _ := M.return_ (| + M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, "trie" |), "_data" |), "get" |), + make_list [ + M.get_name (| globals, "key" |); + M.get_field (| M.get_name (| globals, "trie" |), "default" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Definition common_prefix_length : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "a"; "b" ] |) in + let _ := Constant.str " + Find the longest common prefix of two sequences. + " in + let _ := + M.for_ (| + M.get_name (| globals, "i" |), + M.call (| + M.get_name (| globals, "range" |), + make_list [ + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_name (| globals, "a" |) + ], + make_dict [] + |) + ], + make_dict [] + |), + ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + BoolOp.or (| + Compare.gt_e (| + M.get_name (| globals, "i" |), + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_name (| globals, "b" |) + ], + make_dict [] + |) + |), + ltac:(M.monadic ( + Compare.not_eq (| + M.get_subscript (| + M.get_name (| globals, "a" |), + M.get_name (| globals, "i" |) + |), + M.get_subscript (| + M.get_name (| globals, "b" |), + M.get_name (| globals, "i" |) + |) + |) + )) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + M.get_name (| globals, "i" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_name (| globals, "a" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Definition nibble_list_to_compact : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "x"; "is_leaf" ] |) in + let _ := Constant.str " + Compresses nibble-list into a standard byte array with a flag. + + A nibble-list is a list of byte values no greater than `15`. The flag is + encoded in high nibble of the highest byte. The flag nibble can be broken + down into two two-bit flags. + + Highest nibble:: + + +---+---+----------+--------+ + | _ | _ | is_leaf | parity | + +---+---+----------+--------+ + 3 2 1 0 + + + The lowest bit of the nibble encodes the parity of the length of the + remaining nibbles -- `0` when even and `1` when odd. The second lowest bit + is used to distinguish leaf and extension nodes. The other two bits are not + used. + + Parameters + ---------- + x : + Array of nibbles. + is_leaf : + True if this is part of a leaf node, or false if it is an extension + node. + + Returns + ------- + compressed : `bytearray` + Compact byte array. + " in + let _ := M.assign_local (| + "compact" , + M.call (| + M.get_name (| globals, "bytearray" |), + make_list [], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + BinOp.mod_ (| + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_name (| globals, "x" |) + ], + make_dict [] + |), + Constant.int 2 + |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_field (| M.get_name (| globals, "compact" |), "append" |), + make_list [ + BinOp.mult (| + Constant.int 16, + BinOp.mult (| + Constant.int 2, + M.get_name (| globals, "is_leaf" |) + |) + |) + ], + make_dict [] + |) in + let _ := + M.for_ (| + M.get_name (| globals, "i" |), + M.call (| + M.get_name (| globals, "range" |), + make_list [ + Constant.int 0; + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_name (| globals, "x" |) + ], + make_dict [] + |); + Constant.int 2 + ], + make_dict [] + |), + ltac:(M.monadic ( + let _ := M.call (| + M.get_field (| M.get_name (| globals, "compact" |), "append" |), + make_list [ + BinOp.add (| + BinOp.mult (| + Constant.int 16, + M.get_subscript (| + M.get_name (| globals, "x" |), + M.get_name (| globals, "i" |) + |) + |), + M.get_subscript (| + M.get_name (| globals, "x" |), + BinOp.add (| + M.get_name (| globals, "i" |), + Constant.int 1 + |) + |) + |) + ], + make_dict [] + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.call (| + M.get_field (| M.get_name (| globals, "compact" |), "append" |), + make_list [ + BinOp.add (| + BinOp.mult (| + Constant.int 16, + BinOp.add (| + BinOp.mult (| + Constant.int 2, + M.get_name (| globals, "is_leaf" |) + |), + Constant.int 1 + |) + |), + M.get_subscript (| + M.get_name (| globals, "x" |), + Constant.int 0 + |) + |) + ], + make_dict [] + |) in + let _ := + M.for_ (| + M.get_name (| globals, "i" |), + M.call (| + M.get_name (| globals, "range" |), + make_list [ + Constant.int 1; + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_name (| globals, "x" |) + ], + make_dict [] + |); + Constant.int 2 + ], + make_dict [] + |), + ltac:(M.monadic ( + let _ := M.call (| + M.get_field (| M.get_name (| globals, "compact" |), "append" |), + make_list [ + BinOp.add (| + BinOp.mult (| + Constant.int 16, + M.get_subscript (| + M.get_name (| globals, "x" |), + M.get_name (| globals, "i" |) + |) + |), + M.get_subscript (| + M.get_name (| globals, "x" |), + BinOp.add (| + M.get_name (| globals, "i" |), + Constant.int 1 + |) + |) + |) + ], + make_dict [] + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + M.pure Constant.None_ + )) |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, "Bytes" |), + make_list [ + M.get_name (| globals, "compact" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Definition bytes_to_nibble_list : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "bytes_" ] |) in + let _ := Constant.str " + Converts a `Bytes` into to a sequence of nibbles (bytes with value < 16). + + Parameters + ---------- + bytes_: + The `Bytes` to convert. + + Returns + ------- + nibble_list : `Bytes` + The `Bytes` in nibble-list format. + " in + let _ := M.assign_local (| + "nibble_list" , + M.call (| + M.get_name (| globals, "bytearray" |), + make_list [ + BinOp.mult (| + Constant.int 2, + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_name (| globals, "bytes_" |) + ], + make_dict [] + |) + |) + ], + make_dict [] + |) + |) in + let _ := + M.for_ (| + make_tuple [ M.get_name (| globals, "byte_index" |); M.get_name (| globals, "byte" |) ], + M.call (| + M.get_name (| globals, "enumerate" |), + make_list [ + M.get_name (| globals, "bytes_" |) + ], + make_dict [] + |), + ltac:(M.monadic ( + let _ := M.assign (| + M.get_subscript (| + M.get_name (| globals, "nibble_list" |), + BinOp.mult (| + M.get_name (| globals, "byte_index" |), + Constant.int 2 + |) + |), + BinOp.r_shift (| + BinOp.bit_and (| + M.get_name (| globals, "byte" |), + Constant.int 240 + |), + Constant.int 4 + |) + |) in + let _ := M.assign (| + M.get_subscript (| + M.get_name (| globals, "nibble_list" |), + BinOp.add (| + BinOp.mult (| + M.get_name (| globals, "byte_index" |), + Constant.int 2 + |), + Constant.int 1 + |) + |), + BinOp.bit_and (| + M.get_name (| globals, "byte" |), + Constant.int 15 + |) + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, "Bytes" |), + make_list [ + M.get_name (| globals, "nibble_list" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Definition _prepare_trie : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "trie"; "get_storage_root" ] |) in + let _ := Constant.str " + Prepares the trie for root calculation. Removes values that are empty, + hashes the keys (if `secured == True`) and encodes all the nodes. + + Parameters + ---------- + trie : + The `Trie` to prepare. + get_storage_root : + Function to get the storage root of an account. Needed to encode + `Account` objects. + + Returns + ------- + out : `Mapping[ethereum.base_types.Bytes, Node]` + Object with keys mapped to nibble-byte form. + " in +(* At stmt: unsupported node type: AnnAssign *) + let _ := + M.for_ (| + make_tuple [ M.get_name (| globals, "preimage" |); M.get_name (| globals, "value" |) ], + M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, "trie" |), "_data" |), "items" |), + make_list [], + make_dict [] + |), + ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, "isinstance" |), + make_list [ + M.get_name (| globals, "value" |); + M.get_name (| globals, "Account" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assert (| Compare.is_not (| + M.get_name (| globals, "get_storage_root" |), + Constant.None_ + |) |) in + let _ := M.assign_local (| + "address" , + M.call (| + M.get_name (| globals, "Address" |), + make_list [ + M.get_name (| globals, "preimage" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "encoded_value" , + M.call (| + M.get_name (| globals, "encode_node" |), + make_list [ + M.get_name (| globals, "value" |); + M.call (| + M.get_name (| globals, "get_storage_root" |), + make_list [ + M.get_name (| globals, "address" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "encoded_value" , + M.call (| + M.get_name (| globals, "encode_node" |), + make_list [ + M.get_name (| globals, "value" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + )) |) in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + Compare.not_eq (| + M.get_name (| globals, "encoded_value" |), + Constant.bytes "" + |); + M.get_name (| globals, "AssertionError" |) + ], + make_dict [] + |) in +(* At stmt: unsupported node type: AnnAssign *) + let _ := + (* if *) + M.if_then_else (| + M.get_field (| M.get_name (| globals, "trie" |), "secured" |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "key" , + M.call (| + M.get_name (| globals, "keccak256" |), + make_list [ + M.get_name (| globals, "preimage" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "key" , + M.get_name (| globals, "preimage" |) + |) in + M.pure Constant.None_ + )) |) in + let _ := M.assign (| + M.get_subscript (| + M.get_name (| globals, "mapped" |), + M.call (| + M.get_name (| globals, "bytes_to_nibble_list" |), + make_list [ + M.get_name (| globals, "key" |) + ], + make_dict [] + |) + |), + M.get_name (| globals, "encoded_value" |) + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := M.return_ (| + M.get_name (| globals, "mapped" |) + |) in + M.pure Constant.None_)). + +Definition root : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "trie"; "get_storage_root" ] |) in + let _ := Constant.str " + Computes the root of a modified merkle patricia trie (MPT). + + Parameters + ---------- + trie : + `Trie` to get the root of. + get_storage_root : + Function to get the storage root of an account. Needed to encode + `Account` objects. + + + Returns + ------- + root : `.fork_types.Root` + MPT root of the underlying key-value pairs. + " in + let _ := M.assign_local (| + "obj" , + M.call (| + M.get_name (| globals, "_prepare_trie" |), + make_list [ + M.get_name (| globals, "trie" |); + M.get_name (| globals, "get_storage_root" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "root_node" , + M.call (| + M.get_name (| globals, "encode_internal_node" |), + make_list [ + M.call (| + M.get_name (| globals, "patricialize" |), + make_list [ + M.get_name (| globals, "obj" |); + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.lt (| + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.call (| + M.get_field (| M.get_name (| globals, "rlp" |), "encode" |), + make_list [ + M.get_name (| globals, "root_node" |) + ], + make_dict [] + |) + ], + make_dict [] + |), + Constant.int 32 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + M.call (| + M.get_name (| globals, "keccak256" |), + make_list [ + M.call (| + M.get_field (| M.get_name (| globals, "rlp" |), "encode" |), + make_list [ + M.get_name (| globals, "root_node" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assert (| M.call (| + M.get_name (| globals, "isinstance" |), + make_list [ + M.get_name (| globals, "root_node" |); + M.get_name (| globals, "Bytes" |) + ], + make_dict [] + |) |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, "Root" |), + make_list [ + M.get_name (| globals, "root_node" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_)). + +Definition patricialize : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "obj"; "level" ] |) in + let _ := Constant.str " + Structural composition function. + + Used to recursively patricialize and merkleize a dictionary. Includes + memoization of the tree structure and hashes. + + Parameters + ---------- + obj : + Underlying trie key-value pairs, with keys in nibble-list format. + level : + Current trie level. + + Returns + ------- + node : `ethereum.base_types.Bytes` + Root node of `obj`. + " in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_name (| globals, "obj" |) + ], + make_dict [] + |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + Constant.None_ + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "arbitrary_key" , + M.call (| + M.get_name (| globals, "next" |), + make_list [ + M.call (| + M.get_name (| globals, "iter" |), + make_list [ + M.get_name (| globals, "obj" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_name (| globals, "obj" |) + ], + make_dict [] + |), + Constant.int 1 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "leaf" , + M.call (| + M.get_name (| globals, "LeafNode" |), + make_list [ + M.slice (| + M.get_name (| globals, "arbitrary_key" |), + M.get_name (| globals, "level" |), + Constant.None_, + Constant.None_ + |); + M.get_subscript (| + M.get_name (| globals, "obj" |), + M.get_name (| globals, "arbitrary_key" |) + |) + ], + make_dict [] + |) + |) in + let _ := M.return_ (| + M.get_name (| globals, "leaf" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "substring" , + M.slice (| + M.get_name (| globals, "arbitrary_key" |), + M.get_name (| globals, "level" |), + Constant.None_, + Constant.None_ + |) + |) in + let _ := M.assign_local (| + "prefix_length" , + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_name (| globals, "substring" |) + ], + make_dict [] + |) + |) in + let _ := + M.for_ (| + M.get_name (| globals, "key" |), + M.get_name (| globals, "obj" |), + ltac:(M.monadic ( + let _ := M.assign_local (| + "prefix_length" , + M.call (| + M.get_name (| globals, "min" |), + make_list [ + M.get_name (| globals, "prefix_length" |); + M.call (| + M.get_name (| globals, "common_prefix_length" |), + make_list [ + M.get_name (| globals, "substring" |); + M.slice (| + M.get_name (| globals, "key" |), + M.get_name (| globals, "level" |), + Constant.None_, + Constant.None_ + |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, "prefix_length" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.break (| |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.gt (| + M.get_name (| globals, "prefix_length" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "prefix" , + M.slice (| + M.get_name (| globals, "arbitrary_key" |), + M.get_name (| globals, "level" |), + BinOp.add (| + M.get_name (| globals, "level" |), + M.get_name (| globals, "prefix_length" |) + |), + Constant.None_ + |) + |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, "ExtensionNode" |), + make_list [ + M.get_name (| globals, "prefix" |); + M.call (| + M.get_name (| globals, "encode_internal_node" |), + make_list [ + M.call (| + M.get_name (| globals, "patricialize" |), + make_list [ + M.get_name (| globals, "obj" |); + BinOp.add (| + M.get_name (| globals, "level" |), + M.get_name (| globals, "prefix_length" |) + |) + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in +(* At stmt: unsupported node type: AnnAssign *) + let _ := + M.for_ (| + M.get_name (| globals, "_" |), + M.call (| + M.get_name (| globals, "range" |), + make_list [ + Constant.int 16 + ], + make_dict [] + |), + ltac:(M.monadic ( + let _ := M.call (| + M.get_field (| M.get_name (| globals, "branches" |), "append" |), + make_list [ + Constant.str "(* At expr: unsupported node type: Dict *)" + ], + make_dict [] + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := M.assign_local (| + "value" , + Constant.bytes "" + |) in + let _ := + M.for_ (| + M.get_name (| globals, "key" |), + M.get_name (| globals, "obj" |), + ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_name (| globals, "key" |) + ], + make_dict [] + |), + M.get_name (| globals, "level" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, "isinstance" |), + make_list [ + M.get_subscript (| + M.get_name (| globals, "obj" |), + M.get_name (| globals, "key" |) + |); + make_tuple [ M.get_name (| globals, "Account" |); M.get_name (| globals, "Receipt" |); M.get_name (| globals, "Uint" |) ] + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, "AssertionError" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "value" , + M.get_subscript (| + M.get_name (| globals, "obj" |), + M.get_name (| globals, "key" |) + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign (| + M.get_subscript (| + M.get_subscript (| + M.get_name (| globals, "branches" |), + M.get_subscript (| + M.get_name (| globals, "key" |), + M.get_name (| globals, "level" |) + |) + |), + M.get_name (| globals, "key" |) + |), + M.get_subscript (| + M.get_name (| globals, "obj" |), + M.get_name (| globals, "key" |) + |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, "BranchNode" |), + make_list [ + Constant.str "(* At expr: unsupported node type: ListComp *)"; + M.get_name (| globals, "value" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). diff --git a/CoqOfPython/ethereum/frontier/utils/__init__.v b/CoqOfPython/ethereum/frontier/utils/__init__.v new file mode 100644 index 0000000..0506f75 --- /dev/null +++ b/CoqOfPython/ethereum/frontier/utils/__init__.v @@ -0,0 +1,8 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.frontier.utils.__init__". + +Definition expr_1 : Value.t := + Constant.str " +Utility functions unique to this particular fork. +". diff --git a/CoqOfPython/ethereum/frontier/utils/address.v b/CoqOfPython/ethereum/frontier/utils/address.v new file mode 100644 index 0000000..2fdbc8d --- /dev/null +++ b/CoqOfPython/ethereum/frontier/utils/address.v @@ -0,0 +1,143 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.frontier.utils.address". + +Definition expr_1 : Value.t := + Constant.str " +Hardfork Utility Functions For Addresses +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Address specific functions used in this frontier version of specification. +". + +Axiom typing_imports_Union : + IsImported globals "typing" "Union". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". + +Axiom ethereum_crypto_hash_imports_keccak256 : + IsImported globals "ethereum.crypto.hash" "keccak256". + +Axiom ethereum_utils_byte_imports_left_pad_zero_bytes : + IsImported globals "ethereum.utils.byte" "left_pad_zero_bytes". + +Axiom ethereum_imports_rlp : + IsImported globals "ethereum" "rlp". + +Axiom ethereum_frontier_fork_types_imports_Address : + IsImported globals "ethereum.frontier.fork_types" "Address". + +Definition to_address : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "data" ] |) in + let _ := Constant.str " + Convert a Uint or U256 value to a valid address (20 bytes). + + Parameters + ---------- + data : + The string to be converted to bytes. + + Returns + ------- + address : `Address` + The obtained address. + " in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, "Address" |), + make_list [ + M.slice (| + M.call (| + M.get_field (| M.get_name (| globals, "data" |), "to_be_bytes32" |), + make_list [], + make_dict [] + |), + UnOp.sub (| Constant.int 20 |), + Constant.None_, + Constant.None_ + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Definition compute_contract_address : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "address"; "nonce" ] |) in + let _ := Constant.str " + Computes address of the new account that needs to be created. + + Parameters + ---------- + address : + The address of the account that wants to create the new account. + nonce : + The transaction count of the account that wants to create the new + account. + + Returns + ------- + address: `ethereum.frontier.fork_types.Address` + The computed address of the new account. + " in + let _ := M.assign_local (| + "computed_address" , + M.call (| + M.get_name (| globals, "keccak256" |), + make_list [ + M.call (| + M.get_field (| M.get_name (| globals, "rlp" |), "encode" |), + make_list [ + make_list [ + M.get_name (| globals, "address" |); + M.get_name (| globals, "nonce" |) + ] + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "canonical_address" , + M.slice (| + M.get_name (| globals, "computed_address" |), + UnOp.sub (| Constant.int 20 |), + Constant.None_, + Constant.None_ + |) + |) in + let _ := M.assign_local (| + "padded_address" , + M.call (| + M.get_name (| globals, "left_pad_zero_bytes" |), + make_list [ + M.get_name (| globals, "canonical_address" |); + Constant.int 20 + ], + make_dict [] + |) + |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, "Address" |), + make_list [ + M.get_name (| globals, "padded_address" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). diff --git a/CoqOfPython/ethereum/frontier/utils/hexadecimal.v b/CoqOfPython/ethereum/frontier/utils/hexadecimal.v new file mode 100644 index 0000000..865d427 --- /dev/null +++ b/CoqOfPython/ethereum/frontier/utils/hexadecimal.v @@ -0,0 +1,153 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.frontier.utils.hexadecimal". + +Definition expr_1 : Value.t := + Constant.str " +Utility Functions For Hexadecimal Strings +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Hexadecimal utility functions used in this specification, specific to Frontier +types. +". + +Axiom ethereum_utils_hexadecimal_imports_remove_hex_prefix : + IsImported globals "ethereum.utils.hexadecimal" "remove_hex_prefix". + +Axiom ethereum_frontier_fork_types_imports_Address : + IsImported globals "ethereum.frontier.fork_types" "Address". +Axiom ethereum_frontier_fork_types_imports_Bloom : + IsImported globals "ethereum.frontier.fork_types" "Bloom". +Axiom ethereum_frontier_fork_types_imports_Root : + IsImported globals "ethereum.frontier.fork_types" "Root". + +Definition hex_to_root : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "hex_string" ] |) in + let _ := Constant.str " + Convert hex string to trie root. + + Parameters + ---------- + hex_string : + The hexadecimal string to be converted to trie root. + + Returns + ------- + root : `Root` + Trie root obtained from the given hexadecimal string. + " in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, "Root" |), + make_list [ + M.call (| + M.get_field (| M.get_name (| globals, "bytes" |), "fromhex" |), + make_list [ + M.call (| + M.get_name (| globals, "remove_hex_prefix" |), + make_list [ + M.get_name (| globals, "hex_string" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Definition hex_to_bloom : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "hex_string" ] |) in + let _ := Constant.str " + Convert hex string to bloom. + + Parameters + ---------- + hex_string : + The hexadecimal string to be converted to bloom. + + Returns + ------- + bloom : `Bloom` + Bloom obtained from the given hexadecimal string. + " in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, "Bloom" |), + make_list [ + M.call (| + M.get_field (| M.get_name (| globals, "bytes" |), "fromhex" |), + make_list [ + M.call (| + M.get_name (| globals, "remove_hex_prefix" |), + make_list [ + M.get_name (| globals, "hex_string" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Definition hex_to_address : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "hex_string" ] |) in + let _ := Constant.str " + Convert hex string to Address (20 bytes). + + Parameters + ---------- + hex_string : + The hexadecimal string to be converted to Address. + + Returns + ------- + address : `Address` + The address obtained from the given hexadecimal string. + " in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, "Address" |), + make_list [ + M.call (| + M.get_field (| M.get_name (| globals, "bytes" |), "fromhex" |), + make_list [ + M.call (| + M.get_field (| M.call (| + M.get_name (| globals, "remove_hex_prefix" |), + make_list [ + M.get_name (| globals, "hex_string" |) + ], + make_dict [] + |), "rjust" |), + make_list [ + Constant.int 40; + Constant.str "0" + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). diff --git a/CoqOfPython/ethereum/frontier/utils/message.v b/CoqOfPython/ethereum/frontier/utils/message.v new file mode 100644 index 0000000..6d47416 --- /dev/null +++ b/CoqOfPython/ethereum/frontier/utils/message.v @@ -0,0 +1,206 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.frontier.utils.message". + +Definition expr_1 : Value.t := + Constant.str " +Hardfork Utility Functions For The Message Data-structure +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Message specific functions used in this frontier version of specification. +". + +Axiom typing_imports_Optional : + IsImported globals "typing" "Optional". +Axiom typing_imports_Union : + IsImported globals "typing" "Union". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_Bytes : + IsImported globals "ethereum.base_types" "Bytes". +Axiom ethereum_base_types_imports_Bytes0 : + IsImported globals "ethereum.base_types" "Bytes0". +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". + +Axiom ethereum_frontier_fork_types_imports_Address : + IsImported globals "ethereum.frontier.fork_types" "Address". + +Axiom ethereum_frontier_state_imports_get_account : + IsImported globals "ethereum.frontier.state" "get_account". + +Axiom ethereum_frontier_vm_imports_Environment : + IsImported globals "ethereum.frontier.vm" "Environment". +Axiom ethereum_frontier_vm_imports_Message : + IsImported globals "ethereum.frontier.vm" "Message". + +Axiom ethereum_frontier_utils_address_imports_compute_contract_address : + IsImported globals "ethereum.frontier.utils.address" "compute_contract_address". + +Definition prepare_message : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "caller"; "target"; "value"; "data"; "gas"; "env"; "code_address" ] |) in + let _ := Constant.str " + Execute a transaction against the provided environment. + + Parameters + ---------- + caller : + Address which initiated the transaction + target : + Address whose code will be executed + value : + Value to be transferred. + data : + Array of bytes provided to the code in `target`. + gas : + Gas provided for the code in `target`. + env : + Environment for the Ethereum Virtual Machine. + code_address : + This is usually same as the `target` address except when an alternative + accounts code needs to be executed. + eg. `CALLCODE` calling a precompile. + + Returns + ------- + message: `ethereum.frontier.vm.Message` + Items containing contract creation or message call specific data. + " in + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, "isinstance" |), + make_list [ + M.get_name (| globals, "target" |); + M.get_name (| globals, "Bytes0" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "current_target" , + M.call (| + M.get_name (| globals, "compute_contract_address" |), + make_list [ + M.get_name (| globals, "caller" |); + BinOp.sub (| + M.get_field (| M.call (| + M.get_name (| globals, "get_account" |), + make_list [ + M.get_field (| M.get_name (| globals, "env" |), "state" |); + M.get_name (| globals, "caller" |) + ], + make_dict [] + |), "nonce" |), + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 1 + ], + make_dict [] + |) + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "msg_data" , + M.call (| + M.get_name (| globals, "Bytes" |), + make_list [ + Constant.bytes "" + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "code" , + M.get_name (| globals, "data" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, "isinstance" |), + make_list [ + M.get_name (| globals, "target" |); + M.get_name (| globals, "Address" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "current_target" , + M.get_name (| globals, "target" |) + |) in + let _ := M.assign_local (| + "msg_data" , + M.get_name (| globals, "data" |) + |) in + let _ := M.assign_local (| + "code" , + M.get_field (| M.call (| + M.get_name (| globals, "get_account" |), + make_list [ + M.get_field (| M.get_name (| globals, "env" |), "state" |); + M.get_name (| globals, "target" |) + ], + make_dict [] + |), "code" |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.is (| + M.get_name (| globals, "code_address" |), + Constant.None_ + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "code_address" , + M.get_name (| globals, "target" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.raise (| Some (M.call (| + M.get_name (| globals, "AssertionError" |), + make_list [ + Constant.str "Target must be address or empty bytes" + ], + make_dict [] + |)) |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )) |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, "Message" |), + make_list [], + make_dict [] + |) + |) in + M.pure Constant.None_)). diff --git a/CoqOfPython/ethereum/frontier/vm/__init__.v b/CoqOfPython/ethereum/frontier/vm/__init__.v new file mode 100644 index 0000000..2c943a9 --- /dev/null +++ b/CoqOfPython/ethereum/frontier/vm/__init__.v @@ -0,0 +1,145 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.frontier.vm.__init__". + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +The abstract computer which runs the code stored in an +`.fork_types.Account`. +". + +Axiom dataclasses_imports_dataclass : + IsImported globals "dataclasses" "dataclass". + +Axiom typing_imports_List : + IsImported globals "typing" "List". +Axiom typing_imports_Optional : + IsImported globals "typing" "Optional". +Axiom typing_imports_Set : + IsImported globals "typing" "Set". +Axiom typing_imports_Tuple : + IsImported globals "typing" "Tuple". +Axiom typing_imports_Union : + IsImported globals "typing" "Union". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_Bytes : + IsImported globals "ethereum.base_types" "Bytes". +Axiom ethereum_base_types_imports_Bytes0 : + IsImported globals "ethereum.base_types" "Bytes0". +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". + +Axiom ethereum_crypto_hash_imports_Hash32 : + IsImported globals "ethereum.crypto.hash" "Hash32". + +Axiom ethereum_frontier_blocks_imports_Log : + IsImported globals "ethereum.frontier.blocks" "Log". + +Axiom ethereum_frontier_fork_types_imports_Address : + IsImported globals "ethereum.frontier.fork_types" "Address". + +Axiom ethereum_frontier_state_imports_State : + IsImported globals "ethereum.frontier.state" "State". + +Definition __all__ : Value.t := M.run ltac:(M.monadic ( + make_tuple [ Constant.str "Environment"; Constant.str "Evm"; Constant.str "Message" ] +)). + +Definition Environment : Value.t := + builtins.make_klass + [] + [ + + ] + [ + + ]. + +Definition Message : Value.t := + builtins.make_klass + [] + [ + + ] + [ + + ]. + +Definition Evm : Value.t := + builtins.make_klass + [] + [ + + ] + [ + + ]. + +Definition incorporate_child_on_success : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm"; "child_evm" ] |) in + let _ := Constant.str " + Incorporate the state of a successful `child_evm` into the parent `evm`. + + Parameters + ---------- + evm : + The parent `EVM`. + child_evm : + The child evm to incorporate. + " in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "gas_left" |), + M.get_field (| M.get_name (| globals, "child_evm" |), "gas_left" |) + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "logs" |), + M.get_field (| M.get_name (| globals, "child_evm" |), "logs" |) + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "refund_counter" |), + M.get_field (| M.get_name (| globals, "child_evm" |), "refund_counter" |) + |) in + let _ := M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "accounts_to_delete" |), "update" |), + make_list [ + M.get_field (| M.get_name (| globals, "child_evm" |), "accounts_to_delete" |) + ], + make_dict [] + |) in + M.pure Constant.None_)). + +Definition incorporate_child_on_error : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm"; "child_evm" ] |) in + let _ := Constant.str " + Incorporate the state of an unsuccessful `child_evm` into the parent `evm`. + + Parameters + ---------- + evm : + The parent `EVM`. + child_evm : + The child evm to incorporate. + " in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "gas_left" |), + M.get_field (| M.get_name (| globals, "child_evm" |), "gas_left" |) + |) in + M.pure Constant.None_)). diff --git a/CoqOfPython/ethereum/frontier/vm/exceptions.v b/CoqOfPython/ethereum/frontier/vm/exceptions.v new file mode 100644 index 0000000..f744f16 --- /dev/null +++ b/CoqOfPython/ethereum/frontier/vm/exceptions.v @@ -0,0 +1,121 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.frontier.vm.exceptions". + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) Exceptions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Exceptions which cause the EVM to halt exceptionally. +". + +Axiom ethereum_exceptions_imports_EthereumException : + IsImported globals "ethereum.exceptions" "EthereumException". + +Definition ExceptionalHalt : Value.t := + builtins.make_klass + [(globals, "EthereumException")] + [ + + ] + [ + + ]. + +Definition StackUnderflowError : Value.t := + builtins.make_klass + [(globals, "ExceptionalHalt")] + [ + + ] + [ + + ]. + +Definition StackOverflowError : Value.t := + builtins.make_klass + [(globals, "ExceptionalHalt")] + [ + + ] + [ + + ]. + +Definition OutOfGasError : Value.t := + builtins.make_klass + [(globals, "ExceptionalHalt")] + [ + + ] + [ + + ]. + +Definition InvalidOpcode : Value.t := + builtins.make_klass + [(globals, "ExceptionalHalt")] + [ + + ] + [ + ( + "__init__", + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "self"; "code" ] |) in + let _ := M.call (| + M.get_field (| M.call (| + M.get_name (| globals, "super" |), + make_list [], + make_dict [] + |), "__init__" |), + make_list [ + M.get_name (| globals, "code" |) + ], + make_dict [] + |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, "self" |), "code" |), + M.get_name (| globals, "code" |) + |) in + M.pure Constant.None_)) + ) + ]. + +Definition InvalidJumpDestError : Value.t := + builtins.make_klass + [(globals, "ExceptionalHalt")] + [ + + ] + [ + + ]. + +Definition StackDepthLimitError : Value.t := + builtins.make_klass + [(globals, "ExceptionalHalt")] + [ + + ] + [ + + ]. + +Definition AddressCollision : Value.t := + builtins.make_klass + [(globals, "ExceptionalHalt")] + [ + + ] + [ + + ]. diff --git a/CoqOfPython/ethereum/frontier/vm/gas.v b/CoqOfPython/ethereum/frontier/vm/gas.v new file mode 100644 index 0000000..5e3fe66 --- /dev/null +++ b/CoqOfPython/ethereum/frontier/vm/gas.v @@ -0,0 +1,852 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.frontier.vm.gas". + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) Gas +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +EVM gas constants and calculators. +". + +Axiom dataclasses_imports_dataclass : + IsImported globals "dataclasses" "dataclass". + +Axiom typing_imports_List : + IsImported globals "typing" "List". +Axiom typing_imports_Tuple : + IsImported globals "typing" "Tuple". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". + +Axiom ethereum_trace_imports_GasAndRefund : + IsImported globals "ethereum.trace" "GasAndRefund". +Axiom ethereum_trace_imports_evm_trace : + IsImported globals "ethereum.trace" "evm_trace". + +Axiom ethereum_utils_numeric_imports_ceil32 : + IsImported globals "ethereum.utils.numeric" "ceil32". + +Axiom ethereum_frontier_fork_types_imports_Address : + IsImported globals "ethereum.frontier.fork_types" "Address". + +Axiom ethereum_frontier_state_imports_State : + IsImported globals "ethereum.frontier.state" "State". +Axiom ethereum_frontier_state_imports_account_exists : + IsImported globals "ethereum.frontier.state" "account_exists". + +Axiom ethereum_frontier_vm_imports_Evm : + IsImported globals "ethereum.frontier.vm" "Evm". + +Axiom ethereum_frontier_vm_exceptions_imports_OutOfGasError : + IsImported globals "ethereum.frontier.vm.exceptions" "OutOfGasError". + +Definition GAS_JUMPDEST : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 1 + ], + make_dict [] + |) +)). + +Definition GAS_BASE : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 2 + ], + make_dict [] + |) +)). + +Definition GAS_VERY_LOW : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 3 + ], + make_dict [] + |) +)). + +Definition GAS_SLOAD : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 50 + ], + make_dict [] + |) +)). + +Definition GAS_STORAGE_SET : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 20000 + ], + make_dict [] + |) +)). + +Definition GAS_STORAGE_UPDATE : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 5000 + ], + make_dict [] + |) +)). + +Definition GAS_STORAGE_CLEAR_REFUND : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 15000 + ], + make_dict [] + |) +)). + +Definition GAS_LOW : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 5 + ], + make_dict [] + |) +)). + +Definition GAS_MID : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 8 + ], + make_dict [] + |) +)). + +Definition GAS_HIGH : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 10 + ], + make_dict [] + |) +)). + +Definition GAS_EXPONENTIATION : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 10 + ], + make_dict [] + |) +)). + +Definition GAS_EXPONENTIATION_PER_BYTE : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 10 + ], + make_dict [] + |) +)). + +Definition GAS_MEMORY : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 3 + ], + make_dict [] + |) +)). + +Definition GAS_KECCAK256 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 30 + ], + make_dict [] + |) +)). + +Definition GAS_KECCAK256_WORD : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 6 + ], + make_dict [] + |) +)). + +Definition GAS_COPY : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 3 + ], + make_dict [] + |) +)). + +Definition GAS_BLOCK_HASH : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 20 + ], + make_dict [] + |) +)). + +Definition GAS_EXTERNAL : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 20 + ], + make_dict [] + |) +)). + +Definition GAS_BALANCE : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 20 + ], + make_dict [] + |) +)). + +Definition GAS_LOG : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 375 + ], + make_dict [] + |) +)). + +Definition GAS_LOG_DATA : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 8 + ], + make_dict [] + |) +)). + +Definition GAS_LOG_TOPIC : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 375 + ], + make_dict [] + |) +)). + +Definition GAS_CREATE : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 32000 + ], + make_dict [] + |) +)). + +Definition GAS_CODE_DEPOSIT : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 200 + ], + make_dict [] + |) +)). + +Definition GAS_ZERO : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) +)). + +Definition GAS_CALL : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 40 + ], + make_dict [] + |) +)). + +Definition GAS_NEW_ACCOUNT : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 25000 + ], + make_dict [] + |) +)). + +Definition GAS_CALL_VALUE : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 9000 + ], + make_dict [] + |) +)). + +Definition GAS_CALL_STIPEND : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 2300 + ], + make_dict [] + |) +)). + +Definition REFUND_SELF_DESTRUCT : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 24000 + ], + make_dict [] + |) +)). + +Definition GAS_ECRECOVER : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 3000 + ], + make_dict [] + |) +)). + +Definition GAS_SHA256 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 60 + ], + make_dict [] + |) +)). + +Definition GAS_SHA256_WORD : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 12 + ], + make_dict [] + |) +)). + +Definition GAS_RIPEMD160 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 600 + ], + make_dict [] + |) +)). + +Definition GAS_RIPEMD160_WORD : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 120 + ], + make_dict [] + |) +)). + +Definition GAS_IDENTITY : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 15 + ], + make_dict [] + |) +)). + +Definition GAS_IDENTITY_WORD : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 3 + ], + make_dict [] + |) +)). + +Definition ExtendMemory : Value.t := + builtins.make_klass + [] + [ + + ] + [ + + ]. + +Definition MessageCallGas : Value.t := + builtins.make_klass + [] + [ + + ] + [ + + ]. + +Definition charge_gas : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm"; "amount" ] |) in + let _ := Constant.str " + Subtracts `amount` from `evm.gas_left`. + + Parameters + ---------- + evm : + The current EVM. + amount : + The amount of gas the current operation requires. + + " in + let _ := M.call (| + M.get_name (| globals, "evm_trace" |), + make_list [ + M.get_name (| globals, "evm" |); + M.call (| + M.get_name (| globals, "GasAndRefund" |), + make_list [ + M.get_name (| globals, "amount" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.lt (| + M.get_field (| M.get_name (| globals, "evm" |), "gas_left" |), + M.get_name (| globals, "amount" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, "OutOfGasError" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_op (| + BinOp.sub, + M.get_field (| M.get_name (| globals, "evm" |), "gas_left" |), + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + M.get_name (| globals, "amount" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_)). + +Definition calculate_memory_gas_cost : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "size_in_bytes" ] |) in + let _ := Constant.str " + Calculates the gas cost for allocating memory + to the smallest multiple of 32 bytes, + such that the allocated size is at least as big as the given size. + + Parameters + ---------- + size_in_bytes : + The size of the data in bytes. + + Returns + ------- + total_gas_cost : `ethereum.base_types.Uint` + The gas cost for storing data in memory. + " in + let _ := M.assign_local (| + "size_in_words" , + BinOp.floor_div (| + M.call (| + M.get_name (| globals, "ceil32" |), + make_list [ + M.get_name (| globals, "size_in_bytes" |) + ], + make_dict [] + |), + Constant.int 32 + |) + |) in + let _ := M.assign_local (| + "linear_cost" , + BinOp.mult (| + M.get_name (| globals, "size_in_words" |), + M.get_name (| globals, "GAS_MEMORY" |) + |) + |) in + let _ := M.assign_local (| + "quadratic_cost" , + BinOp.floor_div (| + BinOp.pow (| + M.get_name (| globals, "size_in_words" |), + Constant.int 2 + |), + Constant.int 512 + |) + |) in + let _ := M.assign_local (| + "total_gas_cost" , + BinOp.add (| + M.get_name (| globals, "linear_cost" |), + M.get_name (| globals, "quadratic_cost" |) + |) + |) in +(* At stmt: unsupported node type: Try *) + M.pure Constant.None_)). + +Definition calculate_gas_extend_memory : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "memory"; "extensions" ] |) in + let _ := Constant.str " + Calculates the gas amount to extend memory + + Parameters + ---------- + memory : + Memory contents of the EVM. + extensions: + List of extensions to be made to the memory. + Consists of a tuple of start position and size. + + Returns + ------- + extend_memory: `ExtendMemory` + " in + let _ := M.assign_local (| + "size_to_extend" , + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "to_be_paid" , + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "current_size" , + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_name (| globals, "memory" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := + M.for_ (| + make_tuple [ M.get_name (| globals, "start_position" |); M.get_name (| globals, "size" |) ], + M.get_name (| globals, "extensions" |), + ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, "size" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.continue (| |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "before_size" , + M.call (| + M.get_name (| globals, "ceil32" |), + make_list [ + M.get_name (| globals, "current_size" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "after_size" , + M.call (| + M.get_name (| globals, "ceil32" |), + make_list [ + BinOp.add (| + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.get_name (| globals, "start_position" |) + ], + make_dict [] + |), + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.get_name (| globals, "size" |) + ], + make_dict [] + |) + |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.lt_e (| + M.get_name (| globals, "after_size" |), + M.get_name (| globals, "before_size" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.continue (| |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_op_local (| + BinOp.add, + "size_to_extend", + BinOp.sub (| + M.get_name (| globals, "after_size" |), + M.get_name (| globals, "before_size" |) + |) + |) in + let _ := M.assign_local (| + "already_paid" , + M.call (| + M.get_name (| globals, "calculate_memory_gas_cost" |), + make_list [ + M.get_name (| globals, "before_size" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "total_cost" , + M.call (| + M.get_name (| globals, "calculate_memory_gas_cost" |), + make_list [ + M.get_name (| globals, "after_size" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_op_local (| + BinOp.add, + "to_be_paid", + BinOp.sub (| + M.get_name (| globals, "total_cost" |), + M.get_name (| globals, "already_paid" |) + |) + |) in + let _ := M.assign_local (| + "current_size" , + M.get_name (| globals, "after_size" |) + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, "ExtendMemory" |), + make_list [ + M.get_name (| globals, "to_be_paid" |); + M.get_name (| globals, "size_to_extend" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Definition calculate_message_call_gas : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "state"; "gas"; "to"; "value" ] |) in + let _ := Constant.str " + Calculates the gas amount for executing Opcodes `CALL` and `CALLCODE`. + + Parameters + ---------- + state : + The current state. + gas : + The amount of gas provided to the message-call. + to: + The address of the recipient account. + value: + The amount of `ETH` that needs to be transferred. + + Returns + ------- + message_call_gas: `MessageCallGas` + " in + let _ := M.assign_local (| + "create_gas_cost" , + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, "account_exists" |), + make_list [ + M.get_name (| globals, "state" |); + M.get_name (| globals, "to" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( +M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + (* else *) + )), ltac:(M.monadic ( +M.get_name (| globals, "GAS_NEW_ACCOUNT" |) + )) |) + |) in + let _ := M.assign_local (| + "transfer_gas_cost" , + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, "value" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( +M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + (* else *) + )), ltac:(M.monadic ( +M.get_name (| globals, "GAS_CALL_VALUE" |) + )) |) + |) in + let _ := M.assign_local (| + "cost" , + BinOp.add (| + BinOp.add (| + BinOp.add (| + M.get_name (| globals, "GAS_CALL" |), + M.get_name (| globals, "gas" |) + |), + M.get_name (| globals, "create_gas_cost" |) + |), + M.get_name (| globals, "transfer_gas_cost" |) + |) + |) in + let _ := M.assign_local (| + "stipend" , + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, "value" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( +M.get_name (| globals, "gas" |) + (* else *) + )), ltac:(M.monadic ( +BinOp.add (| + M.get_name (| globals, "GAS_CALL_STIPEND" |), + M.get_name (| globals, "gas" |) + |) + )) |) + |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, "MessageCallGas" |), + make_list [ + M.get_name (| globals, "cost" |); + M.get_name (| globals, "stipend" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). diff --git a/CoqOfPython/ethereum/frontier/vm/instructions/__init__.v b/CoqOfPython/ethereum/frontier/vm/instructions/__init__.v new file mode 100644 index 0000000..b95c8d5 --- /dev/null +++ b/CoqOfPython/ethereum/frontier/vm/instructions/__init__.v @@ -0,0 +1,74 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.frontier.vm.instructions.__init__". + +Definition expr_1 : Value.t := + Constant.str " +EVM Instruction Encoding (Opcodes) +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Machine readable representations of EVM instructions, and a mapping to their +implementations. +". + +(* At top_level_stmt: unsupported node type: Import *) + +Axiom typing_imports_Callable : + IsImported globals "typing" "Callable". +Axiom typing_imports_Dict : + IsImported globals "typing" "Dict". + +Axiom ethereum_frontier_vm_instructions_imports_arithmetic : + IsImported globals "ethereum.frontier.vm.instructions" "arithmetic". + +Axiom ethereum_frontier_vm_instructions_imports_bitwise : + IsImported globals "ethereum.frontier.vm.instructions" "bitwise". + +Axiom ethereum_frontier_vm_instructions_imports_block : + IsImported globals "ethereum.frontier.vm.instructions" "block". + +Axiom ethereum_frontier_vm_instructions_imports_comparison : + IsImported globals "ethereum.frontier.vm.instructions" "comparison". + +Axiom ethereum_frontier_vm_instructions_imports_control_flow : + IsImported globals "ethereum.frontier.vm.instructions" "control_flow". + +Axiom ethereum_frontier_vm_instructions_imports_environment : + IsImported globals "ethereum.frontier.vm.instructions" "environment". + +Axiom ethereum_frontier_vm_instructions_imports_keccak : + IsImported globals "ethereum.frontier.vm.instructions" "keccak". + +Axiom ethereum_frontier_vm_instructions_imports_log : + IsImported globals "ethereum.frontier.vm.instructions" "log". + +Axiom ethereum_frontier_vm_instructions_imports_memory : + IsImported globals "ethereum.frontier.vm.instructions" "memory". + +Axiom ethereum_frontier_vm_instructions_imports_stack : + IsImported globals "ethereum.frontier.vm.instructions" "stack". + +Axiom ethereum_frontier_vm_instructions_imports_storage : + IsImported globals "ethereum.frontier.vm.instructions" "storage". + +Axiom ethereum_frontier_vm_instructions_imports_system : + IsImported globals "ethereum.frontier.vm.instructions" "system". + +Definition Ops : Value.t := + builtins.make_klass + [(* At base: unsupported node type: Attribute *)] + [ + + ] + [ + + ]. + +(* At top_level_stmt: unsupported node type: AnnAssign *) diff --git a/CoqOfPython/ethereum/frontier/vm/instructions/arithmetic.v b/CoqOfPython/ethereum/frontier/vm/instructions/arithmetic.v new file mode 100644 index 0000000..542e2ad --- /dev/null +++ b/CoqOfPython/ethereum/frontier/vm/instructions/arithmetic.v @@ -0,0 +1,1220 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.frontier.vm.instructions.arithmetic". + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) Arithmetic Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM Arithmetic instructions. +". + +Axiom ethereum_base_types_imports_U255_CEIL_VALUE : + IsImported globals "ethereum.base_types" "U255_CEIL_VALUE". +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_U256_CEIL_VALUE : + IsImported globals "ethereum.base_types" "U256_CEIL_VALUE". +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". + +Axiom ethereum_utils_numeric_imports_get_sign : + IsImported globals "ethereum.utils.numeric" "get_sign". + +Axiom ethereum_frontier_vm_imports_Evm : + IsImported globals "ethereum.frontier.vm" "Evm". + +Axiom ethereum_frontier_vm_gas_imports_GAS_EXPONENTIATION : + IsImported globals "ethereum.frontier.vm.gas" "GAS_EXPONENTIATION". +Axiom ethereum_frontier_vm_gas_imports_GAS_EXPONENTIATION_PER_BYTE : + IsImported globals "ethereum.frontier.vm.gas" "GAS_EXPONENTIATION_PER_BYTE". +Axiom ethereum_frontier_vm_gas_imports_GAS_LOW : + IsImported globals "ethereum.frontier.vm.gas" "GAS_LOW". +Axiom ethereum_frontier_vm_gas_imports_GAS_MID : + IsImported globals "ethereum.frontier.vm.gas" "GAS_MID". +Axiom ethereum_frontier_vm_gas_imports_GAS_VERY_LOW : + IsImported globals "ethereum.frontier.vm.gas" "GAS_VERY_LOW". +Axiom ethereum_frontier_vm_gas_imports_charge_gas : + IsImported globals "ethereum.frontier.vm.gas" "charge_gas". + +Axiom ethereum_frontier_vm_stack_imports_pop : + IsImported globals "ethereum.frontier.vm.stack" "pop". +Axiom ethereum_frontier_vm_stack_imports_push : + IsImported globals "ethereum.frontier.vm.stack" "push". + +Definition add : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Adds the top two elements of the stack together, and pushes the result back + on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "x" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "y" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_VERY_LOW" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "result" , + M.call (| + M.get_field (| M.get_name (| globals, "x" |), "wrapping_add" |), + make_list [ + M.get_name (| globals, "y" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.get_name (| globals, "result" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition sub : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Subtracts the top two elements of the stack, and pushes the result back + on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "x" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "y" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_VERY_LOW" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "result" , + M.call (| + M.get_field (| M.get_name (| globals, "x" |), "wrapping_sub" |), + make_list [ + M.get_name (| globals, "y" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.get_name (| globals, "result" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition mul : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Multiply the top two elements of the stack, and pushes the result back + on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "x" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "y" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_LOW" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "result" , + M.call (| + M.get_field (| M.get_name (| globals, "x" |), "wrapping_mul" |), + make_list [ + M.get_name (| globals, "y" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.get_name (| globals, "result" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition div : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Integer division of the top two elements of the stack. Pushes the result + back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "dividend" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "divisor" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_LOW" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, "divisor" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "quotient" , + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "quotient" , + BinOp.floor_div (| + M.get_name (| globals, "dividend" |), + M.get_name (| globals, "divisor" |) + |) + |) in + M.pure Constant.None_ + )) |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.get_name (| globals, "quotient" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition sdiv : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Signed integer division of the top two elements of the stack. Pushes the + result back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "dividend" , + M.call (| + M.get_field (| M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |), "to_signed" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "divisor" , + M.call (| + M.get_field (| M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |), "to_signed" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_LOW" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, "divisor" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "quotient" , + Constant.int 0 + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + BoolOp.and (| + Compare.eq (| + M.get_name (| globals, "dividend" |), + UnOp.sub (| M.get_name (| globals, "U255_CEIL_VALUE" |) |) + |), + ltac:(M.monadic ( + Compare.eq (| + M.get_name (| globals, "divisor" |), + UnOp.sub (| Constant.int 1 |) + |) + )) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "quotient" , + UnOp.sub (| M.get_name (| globals, "U255_CEIL_VALUE" |) |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "sign" , + M.call (| + M.get_name (| globals, "get_sign" |), + make_list [ + BinOp.mult (| + M.get_name (| globals, "dividend" |), + M.get_name (| globals, "divisor" |) + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "quotient" , + BinOp.mult (| + M.get_name (| globals, "sign" |), + BinOp.floor_div (| + M.call (| + M.get_name (| globals, "abs" |), + make_list [ + M.get_name (| globals, "dividend" |) + ], + make_dict [] + |), + M.call (| + M.get_name (| globals, "abs" |), + make_list [ + M.get_name (| globals, "divisor" |) + ], + make_dict [] + |) + |) + |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )) |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.call (| + M.get_field (| M.get_name (| globals, "U256" |), "from_signed" |), + make_list [ + M.get_name (| globals, "quotient" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition mod_ : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Modulo remainder of the top two elements of the stack. Pushes the result + back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "x" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "y" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_LOW" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, "y" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "remainder" , + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "remainder" , + BinOp.mod_ (| + M.get_name (| globals, "x" |), + M.get_name (| globals, "y" |) + |) + |) in + M.pure Constant.None_ + )) |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.get_name (| globals, "remainder" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition smod : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Signed modulo remainder of the top two elements of the stack. Pushes the + result back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "x" , + M.call (| + M.get_field (| M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |), "to_signed" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "y" , + M.call (| + M.get_field (| M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |), "to_signed" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_LOW" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, "y" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "remainder" , + Constant.int 0 + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "remainder" , + BinOp.mult (| + M.call (| + M.get_name (| globals, "get_sign" |), + make_list [ + M.get_name (| globals, "x" |) + ], + make_dict [] + |), + BinOp.mod_ (| + M.call (| + M.get_name (| globals, "abs" |), + make_list [ + M.get_name (| globals, "x" |) + ], + make_dict [] + |), + M.call (| + M.get_name (| globals, "abs" |), + make_list [ + M.get_name (| globals, "y" |) + ], + make_dict [] + |) + |) + |) + |) in + M.pure Constant.None_ + )) |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.call (| + M.get_field (| M.get_name (| globals, "U256" |), "from_signed" |), + make_list [ + M.get_name (| globals, "remainder" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition addmod : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Modulo addition of the top 2 elements with the 3rd element. Pushes the + result back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "x" , + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "y" , + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "z" , + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_MID" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, "z" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "result" , + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "result" , + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + BinOp.mod_ (| + BinOp.add (| + M.get_name (| globals, "x" |), + M.get_name (| globals, "y" |) + |), + M.get_name (| globals, "z" |) + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + )) |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.get_name (| globals, "result" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition mulmod : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Modulo multiplication of the top 2 elements with the 3rd element. Pushes + the result back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "x" , + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "y" , + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "z" , + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_MID" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, "z" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "result" , + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "result" , + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + BinOp.mod_ (| + BinOp.mult (| + M.get_name (| globals, "x" |), + M.get_name (| globals, "y" |) + |), + M.get_name (| globals, "z" |) + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + )) |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.get_name (| globals, "result" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition exp : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Exponential operation of the top 2 elements. Pushes the result back on + the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "base" , + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "exponent" , + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "exponent_bits" , + M.call (| + M.get_field (| M.get_name (| globals, "exponent" |), "bit_length" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "exponent_bytes" , + BinOp.floor_div (| + BinOp.add (| + M.get_name (| globals, "exponent_bits" |), + Constant.int 7 + |), + Constant.int 8 + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + BinOp.add (| + M.get_name (| globals, "GAS_EXPONENTIATION" |), + BinOp.mult (| + M.get_name (| globals, "GAS_EXPONENTIATION_PER_BYTE" |), + M.get_name (| globals, "exponent_bytes" |) + |) + |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "result" , + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + M.call (| + M.get_name (| globals, "pow" |), + make_list [ + M.get_name (| globals, "base" |); + M.get_name (| globals, "exponent" |); + M.get_name (| globals, "U256_CEIL_VALUE" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.get_name (| globals, "result" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition signextend : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Sign extend operation. In other words, extend a signed number which + fits in N bytes to 32 bytes. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "byte_num" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "value" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_LOW" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.gt (| + M.get_name (| globals, "byte_num" |), + Constant.int 31 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "result" , + M.get_name (| globals, "value" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "value_bytes" , + M.call (| + M.get_name (| globals, "bytes" |), + make_list [ + M.call (| + M.get_field (| M.get_name (| globals, "value" |), "to_be_bytes32" |), + make_list [], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "value_bytes" , + M.slice (| + M.get_name (| globals, "value_bytes" |), + BinOp.sub (| + Constant.int 31, + M.call (| + M.get_name (| globals, "int" |), + make_list [ + M.get_name (| globals, "byte_num" |) + ], + make_dict [] + |) + |), + Constant.None_, + Constant.None_ + |) + |) in + let _ := M.assign_local (| + "sign_bit" , + BinOp.r_shift (| + M.get_subscript (| + M.get_name (| globals, "value_bytes" |), + Constant.int 0 + |), + Constant.int 7 + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, "sign_bit" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "result" , + M.call (| + M.get_field (| M.get_name (| globals, "U256" |), "from_be_bytes" |), + make_list [ + M.get_name (| globals, "value_bytes" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "num_bytes_prepend" , + BinOp.sub (| + Constant.int 32, + BinOp.add (| + M.get_name (| globals, "byte_num" |), + Constant.int 1 + |) + |) + |) in + let _ := M.assign_local (| + "result" , + M.call (| + M.get_field (| M.get_name (| globals, "U256" |), "from_be_bytes" |), + make_list [ + BinOp.add (| + M.call (| + M.get_name (| globals, "bytearray" |), + make_list [ + BinOp.mult (| + make_list [ + Constant.int 255 + ], + M.get_name (| globals, "num_bytes_prepend" |) + |) + ], + make_dict [] + |), + M.get_name (| globals, "value_bytes" |) + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )) |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.get_name (| globals, "result" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). diff --git a/CoqOfPython/ethereum/frontier/vm/instructions/bitwise.v b/CoqOfPython/ethereum/frontier/vm/instructions/bitwise.v new file mode 100644 index 0000000..f568271 --- /dev/null +++ b/CoqOfPython/ethereum/frontier/vm/instructions/bitwise.v @@ -0,0 +1,372 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.frontier.vm.instructions.bitwise". + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) Bitwise Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM bitwise instructions. +". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". + +Axiom ethereum_frontier_vm_imports_Evm : + IsImported globals "ethereum.frontier.vm" "Evm". + +Axiom ethereum_frontier_vm_gas_imports_GAS_VERY_LOW : + IsImported globals "ethereum.frontier.vm.gas" "GAS_VERY_LOW". +Axiom ethereum_frontier_vm_gas_imports_charge_gas : + IsImported globals "ethereum.frontier.vm.gas" "charge_gas". + +Axiom ethereum_frontier_vm_stack_imports_pop : + IsImported globals "ethereum.frontier.vm.stack" "pop". +Axiom ethereum_frontier_vm_stack_imports_push : + IsImported globals "ethereum.frontier.vm.stack" "push". + +Definition bitwise_and : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Bitwise AND operation of the top 2 elements of the stack. Pushes the + result back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "x" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "y" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_VERY_LOW" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + BinOp.bit_and (| + M.get_name (| globals, "x" |), + M.get_name (| globals, "y" |) + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition bitwise_or : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Bitwise OR operation of the top 2 elements of the stack. Pushes the + result back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "x" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "y" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_VERY_LOW" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + BinOp.bit_or (| + M.get_name (| globals, "x" |), + M.get_name (| globals, "y" |) + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition bitwise_xor : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Bitwise XOR operation of the top 2 elements of the stack. Pushes the + result back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "x" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "y" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_VERY_LOW" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + BinOp.bit_xor (| + M.get_name (| globals, "x" |), + M.get_name (| globals, "y" |) + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition bitwise_not : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Bitwise NOT operation of the top element of the stack. Pushes the + result back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "x" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_VERY_LOW" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + UnOp.invert (| M.get_name (| globals, "x" |) |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition get_byte : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + For a word (defined by next top element of the stack), retrieve the + Nth byte (0-indexed and defined by top element of stack) from the + left (most significant) to right (least significant). + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "byte_index" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "word" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_VERY_LOW" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.gt_e (| + M.get_name (| globals, "byte_index" |), + Constant.int 32 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "result" , + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "extra_bytes_to_right" , + BinOp.sub (| + Constant.int 31, + M.get_name (| globals, "byte_index" |) + |) + |) in + let _ := M.assign_local (| + "word" , + BinOp.r_shift (| + M.get_name (| globals, "word" |), + BinOp.mult (| + M.get_name (| globals, "extra_bytes_to_right" |), + Constant.int 8 + |) + |) + |) in + let _ := M.assign_local (| + "word" , + BinOp.bit_and (| + M.get_name (| globals, "word" |), + Constant.int 255 + |) + |) in + let _ := M.assign_local (| + "result" , + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + M.get_name (| globals, "word" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + )) |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.get_name (| globals, "result" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). diff --git a/CoqOfPython/ethereum/frontier/vm/instructions/block.v b/CoqOfPython/ethereum/frontier/vm/instructions/block.v new file mode 100644 index 0000000..cbcd26a --- /dev/null +++ b/CoqOfPython/ethereum/frontier/vm/instructions/block.v @@ -0,0 +1,348 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.frontier.vm.instructions.block". + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) Block Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM block instructions. +". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". + +Axiom ethereum_frontier_vm_imports_Evm : + IsImported globals "ethereum.frontier.vm" "Evm". + +Axiom ethereum_frontier_vm_gas_imports_GAS_BASE : + IsImported globals "ethereum.frontier.vm.gas" "GAS_BASE". +Axiom ethereum_frontier_vm_gas_imports_GAS_BLOCK_HASH : + IsImported globals "ethereum.frontier.vm.gas" "GAS_BLOCK_HASH". +Axiom ethereum_frontier_vm_gas_imports_charge_gas : + IsImported globals "ethereum.frontier.vm.gas" "charge_gas". + +Axiom ethereum_frontier_vm_stack_imports_pop : + IsImported globals "ethereum.frontier.vm.stack" "pop". +Axiom ethereum_frontier_vm_stack_imports_push : + IsImported globals "ethereum.frontier.vm.stack" "push". + +Definition block_hash : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Push the hash of one of the 256 most recent complete blocks onto the + stack. The block number to hash is present at the top of the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "block_number" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_BLOCK_HASH" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + BoolOp.or (| + Compare.lt_e (| + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "env" |), "number" |), + M.get_name (| globals, "block_number" |) + |), + ltac:(M.monadic ( + Compare.gt (| + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "env" |), "number" |), + BinOp.add (| + M.get_name (| globals, "block_number" |), + Constant.int 256 + |) + |) + )) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "hash" , + Constant.bytes "00" + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "hash" , + M.get_subscript (| + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "env" |), "block_hashes" |), + UnOp.sub (| BinOp.sub (| + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "env" |), "number" |), + M.get_name (| globals, "block_number" |) + |) |) + |) + |) in + M.pure Constant.None_ + )) |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.call (| + M.get_field (| M.get_name (| globals, "U256" |), "from_be_bytes" |), + make_list [ + M.get_name (| globals, "hash" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition coinbase : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Push the current block's beneficiary address (address of the block miner) + onto the stack. + + Here the current block refers to the block in which the currently + executing transaction/call resides. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_BASE" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.call (| + M.get_field (| M.get_name (| globals, "U256" |), "from_be_bytes" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "env" |), "coinbase" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition timestamp : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Push the current block's timestamp onto the stack. Here the timestamp + being referred is actually the unix timestamp in seconds. + + Here the current block refers to the block in which the currently + executing transaction/call resides. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_BASE" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "env" |), "time" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition number : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Push the current block's number onto the stack. + + Here the current block refers to the block in which the currently + executing transaction/call resides. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_BASE" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "env" |), "number" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition difficulty : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Push the current block's difficulty onto the stack. + + Here the current block refers to the block in which the currently + executing transaction/call resides. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_BASE" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "env" |), "difficulty" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition gas_limit : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Push the current block's gas limit onto the stack. + + Here the current block refers to the block in which the currently + executing transaction/call resides. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_BASE" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "env" |), "gas_limit" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). diff --git a/CoqOfPython/ethereum/frontier/vm/instructions/comparison.v b/CoqOfPython/ethereum/frontier/vm/instructions/comparison.v new file mode 100644 index 0000000..8c59240 --- /dev/null +++ b/CoqOfPython/ethereum/frontier/vm/instructions/comparison.v @@ -0,0 +1,452 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.frontier.vm.instructions.comparison". + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) Comparison Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM Comparison instructions. +". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". + +Axiom ethereum_frontier_vm_imports_Evm : + IsImported globals "ethereum.frontier.vm" "Evm". + +Axiom ethereum_frontier_vm_gas_imports_GAS_VERY_LOW : + IsImported globals "ethereum.frontier.vm.gas" "GAS_VERY_LOW". +Axiom ethereum_frontier_vm_gas_imports_charge_gas : + IsImported globals "ethereum.frontier.vm.gas" "charge_gas". + +Axiom ethereum_frontier_vm_stack_imports_pop : + IsImported globals "ethereum.frontier.vm.stack" "pop". +Axiom ethereum_frontier_vm_stack_imports_push : + IsImported globals "ethereum.frontier.vm.stack" "push". + +Definition less_than : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Checks if the top element is less than the next top element. Pushes the + result back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "left" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "right" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_VERY_LOW" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "result" , + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Compare.lt (| + M.get_name (| globals, "left" |), + M.get_name (| globals, "right" |) + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.get_name (| globals, "result" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition signed_less_than : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Signed less-than comparison. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "left" , + M.call (| + M.get_field (| M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |), "to_signed" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "right" , + M.call (| + M.get_field (| M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |), "to_signed" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_VERY_LOW" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "result" , + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Compare.lt (| + M.get_name (| globals, "left" |), + M.get_name (| globals, "right" |) + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.get_name (| globals, "result" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition greater_than : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Checks if the top element is greater than the next top element. Pushes + the result back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "left" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "right" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_VERY_LOW" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "result" , + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Compare.gt (| + M.get_name (| globals, "left" |), + M.get_name (| globals, "right" |) + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.get_name (| globals, "result" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition signed_greater_than : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Signed greater-than comparison. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "left" , + M.call (| + M.get_field (| M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |), "to_signed" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "right" , + M.call (| + M.get_field (| M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |), "to_signed" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_VERY_LOW" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "result" , + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Compare.gt (| + M.get_name (| globals, "left" |), + M.get_name (| globals, "right" |) + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.get_name (| globals, "result" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition equal : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Checks if the top element is equal to the next top element. Pushes + the result back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "left" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "right" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_VERY_LOW" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "result" , + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Compare.eq (| + M.get_name (| globals, "left" |), + M.get_name (| globals, "right" |) + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.get_name (| globals, "result" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition is_zero : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Checks if the top element is equal to 0. Pushes the result back on the + stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "x" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_VERY_LOW" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "result" , + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Compare.eq (| + M.get_name (| globals, "x" |), + Constant.int 0 + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.get_name (| globals, "result" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). diff --git a/CoqOfPython/ethereum/frontier/vm/instructions/control_flow.v b/CoqOfPython/ethereum/frontier/vm/instructions/control_flow.v new file mode 100644 index 0000000..ce039f3 --- /dev/null +++ b/CoqOfPython/ethereum/frontier/vm/instructions/control_flow.v @@ -0,0 +1,350 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.frontier.vm.instructions.control_flow". + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) Control Flow Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM control flow instructions. +". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". + +Axiom ethereum_frontier_vm_gas_imports_GAS_BASE : + IsImported globals "ethereum.frontier.vm.gas" "GAS_BASE". +Axiom ethereum_frontier_vm_gas_imports_GAS_HIGH : + IsImported globals "ethereum.frontier.vm.gas" "GAS_HIGH". +Axiom ethereum_frontier_vm_gas_imports_GAS_JUMPDEST : + IsImported globals "ethereum.frontier.vm.gas" "GAS_JUMPDEST". +Axiom ethereum_frontier_vm_gas_imports_GAS_MID : + IsImported globals "ethereum.frontier.vm.gas" "GAS_MID". +Axiom ethereum_frontier_vm_gas_imports_charge_gas : + IsImported globals "ethereum.frontier.vm.gas" "charge_gas". + +Axiom ethereum_frontier_vm_imports_Evm : + IsImported globals "ethereum.frontier.vm" "Evm". + +Axiom ethereum_frontier_vm_exceptions_imports_InvalidJumpDestError : + IsImported globals "ethereum.frontier.vm.exceptions" "InvalidJumpDestError". + +Axiom ethereum_frontier_vm_stack_imports_pop : + IsImported globals "ethereum.frontier.vm.stack" "pop". +Axiom ethereum_frontier_vm_stack_imports_push : + IsImported globals "ethereum.frontier.vm.stack" "push". + +Definition stop : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Stop further execution of EVM code. + + Parameters + ---------- + evm : + The current EVM frame. + " in + let _ := M.pass (| |) in + let _ := M.pass (| |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, "evm" |), "running" |), + Constant.bool false + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition jump : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Alter the program counter to the location specified by the top of the + stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "jump_dest" , + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_MID" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.not_in (| + M.get_name (| globals, "jump_dest" |), + M.get_field (| M.get_name (| globals, "evm" |), "valid_jump_destinations" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, "InvalidJumpDestError" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.get_name (| globals, "jump_dest" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Definition jumpi : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Alter the program counter to the specified location if and only if a + condition is true. If the condition is not true, then the program counter + would increase only by 1. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "jump_dest" , + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "conditional_value" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_HIGH" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, "conditional_value" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "destination" , + BinOp.add (| + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + Compare.not_in (| + M.get_name (| globals, "jump_dest" |), + M.get_field (| M.get_name (| globals, "evm" |), "valid_jump_destinations" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, "InvalidJumpDestError" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "destination" , + M.get_name (| globals, "jump_dest" |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )) |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.get_name (| globals, "destination" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Definition pc : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Push onto the stack the value of the program counter after reaching the + current instruction and without increasing it for the next instruction. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_BASE" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "pc" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition gas_left : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Push the amount of available gas (including the corresponding reduction + for the cost of this instruction) onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_BASE" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "gas_left" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition jumpdest : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Mark a valid destination for jumps. This is a noop, present only + to be used by `JUMP` and `JUMPI` opcodes to verify that their jump is + valid. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_JUMPDEST" |) + ], + make_dict [] + |) in + let _ := M.pass (| |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). diff --git a/CoqOfPython/ethereum/frontier/vm/instructions/environment.v b/CoqOfPython/ethereum/frontier/vm/instructions/environment.v new file mode 100644 index 0000000..2ed9e35 --- /dev/null +++ b/CoqOfPython/ethereum/frontier/vm/instructions/environment.v @@ -0,0 +1,993 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.frontier.vm.instructions.environment". + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) Environmental Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM environment related instructions. +". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". + +Axiom ethereum_utils_numeric_imports_ceil32 : + IsImported globals "ethereum.utils.numeric" "ceil32". + +Axiom ethereum_frontier_state_imports_get_account : + IsImported globals "ethereum.frontier.state" "get_account". + +Axiom ethereum_frontier_utils_address_imports_to_address : + IsImported globals "ethereum.frontier.utils.address" "to_address". + +Axiom ethereum_frontier_vm_memory_imports_buffer_read : + IsImported globals "ethereum.frontier.vm.memory" "buffer_read". +Axiom ethereum_frontier_vm_memory_imports_memory_write : + IsImported globals "ethereum.frontier.vm.memory" "memory_write". + +Axiom ethereum_frontier_vm_imports_Evm : + IsImported globals "ethereum.frontier.vm" "Evm". + +Axiom ethereum_frontier_vm_gas_imports_GAS_BALANCE : + IsImported globals "ethereum.frontier.vm.gas" "GAS_BALANCE". +Axiom ethereum_frontier_vm_gas_imports_GAS_BASE : + IsImported globals "ethereum.frontier.vm.gas" "GAS_BASE". +Axiom ethereum_frontier_vm_gas_imports_GAS_COPY : + IsImported globals "ethereum.frontier.vm.gas" "GAS_COPY". +Axiom ethereum_frontier_vm_gas_imports_GAS_EXTERNAL : + IsImported globals "ethereum.frontier.vm.gas" "GAS_EXTERNAL". +Axiom ethereum_frontier_vm_gas_imports_GAS_VERY_LOW : + IsImported globals "ethereum.frontier.vm.gas" "GAS_VERY_LOW". +Axiom ethereum_frontier_vm_gas_imports_calculate_gas_extend_memory : + IsImported globals "ethereum.frontier.vm.gas" "calculate_gas_extend_memory". +Axiom ethereum_frontier_vm_gas_imports_charge_gas : + IsImported globals "ethereum.frontier.vm.gas" "charge_gas". + +Axiom ethereum_frontier_vm_stack_imports_pop : + IsImported globals "ethereum.frontier.vm.stack" "pop". +Axiom ethereum_frontier_vm_stack_imports_push : + IsImported globals "ethereum.frontier.vm.stack" "push". + +Definition address : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Pushes the address of the current executing account to the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_BASE" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.call (| + M.get_field (| M.get_name (| globals, "U256" |), "from_be_bytes" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "current_target" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition balance : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Pushes the balance of the given account onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "address" , + M.call (| + M.get_name (| globals, "to_address" |), + make_list [ + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_BALANCE" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "balance" , + M.get_field (| M.call (| + M.get_name (| globals, "get_account" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "env" |), "state" |); + M.get_name (| globals, "address" |) + ], + make_dict [] + |), "balance" |) + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.get_name (| globals, "balance" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition origin : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Pushes the address of the original transaction sender to the stack. + The origin address can only be an EOA. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_BASE" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.call (| + M.get_field (| M.get_name (| globals, "U256" |), "from_be_bytes" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "env" |), "origin" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition caller : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Pushes the address of the caller onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_BASE" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.call (| + M.get_field (| M.get_name (| globals, "U256" |), "from_be_bytes" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "caller" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition callvalue : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Push the value (in wei) sent with the call onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_BASE" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "value" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition calldataload : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Push a word (32 bytes) of the input data belonging to the current + environment onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "start_index" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_VERY_LOW" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "value" , + M.call (| + M.get_name (| globals, "buffer_read" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "data" |); + M.get_name (| globals, "start_index" |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 32 + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.call (| + M.get_field (| M.get_name (| globals, "U256" |), "from_be_bytes" |), + make_list [ + M.get_name (| globals, "value" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition calldatasize : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Push the size of input data in current environment onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_BASE" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "data" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition calldatacopy : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Copy a portion of the input data in current environment to memory. + + This will also expand the memory, in case that the memory is insufficient + to store the data. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "memory_start_index" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "data_start_index" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "size" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "words" , + BinOp.floor_div (| + M.call (| + M.get_name (| globals, "ceil32" |), + make_list [ + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.get_name (| globals, "size" |) + ], + make_dict [] + |) + ], + make_dict [] + |), + Constant.int 32 + |) + |) in + let _ := M.assign_local (| + "copy_gas_cost" , + BinOp.mult (| + M.get_name (| globals, "GAS_COPY" |), + M.get_name (| globals, "words" |) + |) + |) in + let _ := M.assign_local (| + "extend_memory" , + M.call (| + M.get_name (| globals, "calculate_gas_extend_memory" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "memory" |); + make_list [ + make_tuple [ M.get_name (| globals, "memory_start_index" |); M.get_name (| globals, "size" |) ] + ] + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + BinOp.add (| + BinOp.add (| + M.get_name (| globals, "GAS_VERY_LOW" |), + M.get_name (| globals, "copy_gas_cost" |) + |), + M.get_field (| M.get_name (| globals, "extend_memory" |), "cost" |) + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "memory" |), + BinOp.mult (| + Constant.bytes "00", + M.get_field (| M.get_name (| globals, "extend_memory" |), "expand_by" |) + |) + |) in + let _ := M.assign_local (| + "value" , + M.call (| + M.get_name (| globals, "buffer_read" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "data" |); + M.get_name (| globals, "data_start_index" |); + M.get_name (| globals, "size" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "memory_write" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "memory" |); + M.get_name (| globals, "memory_start_index" |); + M.get_name (| globals, "value" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition codesize : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Push the size of code running in current environment onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_BASE" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "code" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition codecopy : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Copy a portion of the code in current environment to memory. + + This will also expand the memory, in case that the memory is insufficient + to store the data. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "memory_start_index" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "code_start_index" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "size" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "words" , + BinOp.floor_div (| + M.call (| + M.get_name (| globals, "ceil32" |), + make_list [ + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.get_name (| globals, "size" |) + ], + make_dict [] + |) + ], + make_dict [] + |), + Constant.int 32 + |) + |) in + let _ := M.assign_local (| + "copy_gas_cost" , + BinOp.mult (| + M.get_name (| globals, "GAS_COPY" |), + M.get_name (| globals, "words" |) + |) + |) in + let _ := M.assign_local (| + "extend_memory" , + M.call (| + M.get_name (| globals, "calculate_gas_extend_memory" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "memory" |); + make_list [ + make_tuple [ M.get_name (| globals, "memory_start_index" |); M.get_name (| globals, "size" |) ] + ] + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + BinOp.add (| + BinOp.add (| + M.get_name (| globals, "GAS_VERY_LOW" |), + M.get_name (| globals, "copy_gas_cost" |) + |), + M.get_field (| M.get_name (| globals, "extend_memory" |), "cost" |) + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "memory" |), + BinOp.mult (| + Constant.bytes "00", + M.get_field (| M.get_name (| globals, "extend_memory" |), "expand_by" |) + |) + |) in + let _ := M.assign_local (| + "value" , + M.call (| + M.get_name (| globals, "buffer_read" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "code" |); + M.get_name (| globals, "code_start_index" |); + M.get_name (| globals, "size" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "memory_write" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "memory" |); + M.get_name (| globals, "memory_start_index" |); + M.get_name (| globals, "value" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition gasprice : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Push the gas price used in current environment onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_BASE" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "env" |), "gas_price" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition extcodesize : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Push the code size of a given account onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "address" , + M.call (| + M.get_name (| globals, "to_address" |), + make_list [ + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_EXTERNAL" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "codesize" , + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_field (| M.call (| + M.get_name (| globals, "get_account" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "env" |), "state" |); + M.get_name (| globals, "address" |) + ], + make_dict [] + |), "code" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.get_name (| globals, "codesize" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition extcodecopy : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Copy a portion of an account's code to memory. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "address" , + M.call (| + M.get_name (| globals, "to_address" |), + make_list [ + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_start_index" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "code_start_index" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "size" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "words" , + BinOp.floor_div (| + M.call (| + M.get_name (| globals, "ceil32" |), + make_list [ + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.get_name (| globals, "size" |) + ], + make_dict [] + |) + ], + make_dict [] + |), + Constant.int 32 + |) + |) in + let _ := M.assign_local (| + "copy_gas_cost" , + BinOp.mult (| + M.get_name (| globals, "GAS_COPY" |), + M.get_name (| globals, "words" |) + |) + |) in + let _ := M.assign_local (| + "extend_memory" , + M.call (| + M.get_name (| globals, "calculate_gas_extend_memory" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "memory" |); + make_list [ + make_tuple [ M.get_name (| globals, "memory_start_index" |); M.get_name (| globals, "size" |) ] + ] + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + BinOp.add (| + BinOp.add (| + M.get_name (| globals, "GAS_EXTERNAL" |), + M.get_name (| globals, "copy_gas_cost" |) + |), + M.get_field (| M.get_name (| globals, "extend_memory" |), "cost" |) + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "memory" |), + BinOp.mult (| + Constant.bytes "00", + M.get_field (| M.get_name (| globals, "extend_memory" |), "expand_by" |) + |) + |) in + let _ := M.assign_local (| + "code" , + M.get_field (| M.call (| + M.get_name (| globals, "get_account" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "env" |), "state" |); + M.get_name (| globals, "address" |) + ], + make_dict [] + |), "code" |) + |) in + let _ := M.assign_local (| + "value" , + M.call (| + M.get_name (| globals, "buffer_read" |), + make_list [ + M.get_name (| globals, "code" |); + M.get_name (| globals, "code_start_index" |); + M.get_name (| globals, "size" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "memory_write" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "memory" |); + M.get_name (| globals, "memory_start_index" |); + M.get_name (| globals, "value" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). diff --git a/CoqOfPython/ethereum/frontier/vm/instructions/keccak.v b/CoqOfPython/ethereum/frontier/vm/instructions/keccak.v new file mode 100644 index 0000000..393213b --- /dev/null +++ b/CoqOfPython/ethereum/frontier/vm/instructions/keccak.v @@ -0,0 +1,188 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.frontier.vm.instructions.keccak". + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) Keccak Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM keccak instructions. +". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". + +Axiom ethereum_crypto_hash_imports_keccak256 : + IsImported globals "ethereum.crypto.hash" "keccak256". + +Axiom ethereum_utils_numeric_imports_ceil32 : + IsImported globals "ethereum.utils.numeric" "ceil32". + +Axiom ethereum_frontier_vm_imports_Evm : + IsImported globals "ethereum.frontier.vm" "Evm". + +Axiom ethereum_frontier_vm_gas_imports_GAS_KECCAK256 : + IsImported globals "ethereum.frontier.vm.gas" "GAS_KECCAK256". +Axiom ethereum_frontier_vm_gas_imports_GAS_KECCAK256_WORD : + IsImported globals "ethereum.frontier.vm.gas" "GAS_KECCAK256_WORD". +Axiom ethereum_frontier_vm_gas_imports_calculate_gas_extend_memory : + IsImported globals "ethereum.frontier.vm.gas" "calculate_gas_extend_memory". +Axiom ethereum_frontier_vm_gas_imports_charge_gas : + IsImported globals "ethereum.frontier.vm.gas" "charge_gas". + +Axiom ethereum_frontier_vm_memory_imports_memory_read_bytes : + IsImported globals "ethereum.frontier.vm.memory" "memory_read_bytes". + +Axiom ethereum_frontier_vm_stack_imports_pop : + IsImported globals "ethereum.frontier.vm.stack" "pop". +Axiom ethereum_frontier_vm_stack_imports_push : + IsImported globals "ethereum.frontier.vm.stack" "push". + +Definition keccak : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Pushes to the stack the Keccak-256 hash of a region of memory. + + This also expands the memory, in case the memory is insufficient to + access the data's memory location. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "memory_start_index" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "size" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "words" , + BinOp.floor_div (| + M.call (| + M.get_name (| globals, "ceil32" |), + make_list [ + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.get_name (| globals, "size" |) + ], + make_dict [] + |) + ], + make_dict [] + |), + Constant.int 32 + |) + |) in + let _ := M.assign_local (| + "word_gas_cost" , + BinOp.mult (| + M.get_name (| globals, "GAS_KECCAK256_WORD" |), + M.get_name (| globals, "words" |) + |) + |) in + let _ := M.assign_local (| + "extend_memory" , + M.call (| + M.get_name (| globals, "calculate_gas_extend_memory" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "memory" |); + make_list [ + make_tuple [ M.get_name (| globals, "memory_start_index" |); M.get_name (| globals, "size" |) ] + ] + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + BinOp.add (| + BinOp.add (| + M.get_name (| globals, "GAS_KECCAK256" |), + M.get_name (| globals, "word_gas_cost" |) + |), + M.get_field (| M.get_name (| globals, "extend_memory" |), "cost" |) + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "memory" |), + BinOp.mult (| + Constant.bytes "00", + M.get_field (| M.get_name (| globals, "extend_memory" |), "expand_by" |) + |) + |) in + let _ := M.assign_local (| + "data" , + M.call (| + M.get_name (| globals, "memory_read_bytes" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "memory" |); + M.get_name (| globals, "memory_start_index" |); + M.get_name (| globals, "size" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "hash" , + M.call (| + M.get_name (| globals, "keccak256" |), + make_list [ + M.get_name (| globals, "data" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.call (| + M.get_field (| M.get_name (| globals, "U256" |), "from_be_bytes" |), + make_list [ + M.get_name (| globals, "hash" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). diff --git a/CoqOfPython/ethereum/frontier/vm/instructions/log.v b/CoqOfPython/ethereum/frontier/vm/instructions/log.v new file mode 100644 index 0000000..f675d8d --- /dev/null +++ b/CoqOfPython/ethereum/frontier/vm/instructions/log.v @@ -0,0 +1,242 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.frontier.vm.instructions.log". + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) Logging Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM logging instructions. +". + +Axiom functools_imports_partial : + IsImported globals "functools" "partial". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". + +Axiom ethereum_frontier_blocks_imports_Log : + IsImported globals "ethereum.frontier.blocks" "Log". + +Axiom ethereum_frontier_vm_imports_Evm : + IsImported globals "ethereum.frontier.vm" "Evm". + +Axiom ethereum_frontier_vm_gas_imports_GAS_LOG : + IsImported globals "ethereum.frontier.vm.gas" "GAS_LOG". +Axiom ethereum_frontier_vm_gas_imports_GAS_LOG_DATA : + IsImported globals "ethereum.frontier.vm.gas" "GAS_LOG_DATA". +Axiom ethereum_frontier_vm_gas_imports_GAS_LOG_TOPIC : + IsImported globals "ethereum.frontier.vm.gas" "GAS_LOG_TOPIC". +Axiom ethereum_frontier_vm_gas_imports_calculate_gas_extend_memory : + IsImported globals "ethereum.frontier.vm.gas" "calculate_gas_extend_memory". +Axiom ethereum_frontier_vm_gas_imports_charge_gas : + IsImported globals "ethereum.frontier.vm.gas" "charge_gas". + +Axiom ethereum_frontier_vm_memory_imports_memory_read_bytes : + IsImported globals "ethereum.frontier.vm.memory" "memory_read_bytes". + +Axiom ethereum_frontier_vm_stack_imports_pop : + IsImported globals "ethereum.frontier.vm.stack" "pop". + +Definition log_n : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm"; "num_topics" ] |) in + let _ := Constant.str " + Appends a log entry, having `num_topics` topics, to the evm logs. + + This will also expand the memory if the data (required by the log entry) + corresponding to the memory is not accessible. + + Parameters + ---------- + evm : + The current EVM frame. + num_topics : + The number of topics to be included in the log entry. + + " in + let _ := M.assign_local (| + "memory_start_index" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "size" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "topics" , + make_list [] + |) in + let _ := + M.for_ (| + M.get_name (| globals, "_" |), + M.call (| + M.get_name (| globals, "range" |), + make_list [ + M.get_name (| globals, "num_topics" |) + ], + make_dict [] + |), + ltac:(M.monadic ( + let _ := M.assign_local (| + "topic" , + M.call (| + M.get_field (| M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |), "to_be_bytes32" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_field (| M.get_name (| globals, "topics" |), "append" |), + make_list [ + M.get_name (| globals, "topic" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := M.assign_local (| + "extend_memory" , + M.call (| + M.get_name (| globals, "calculate_gas_extend_memory" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "memory" |); + make_list [ + make_tuple [ M.get_name (| globals, "memory_start_index" |); M.get_name (| globals, "size" |) ] + ] + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + BinOp.add (| + BinOp.add (| + BinOp.add (| + M.get_name (| globals, "GAS_LOG" |), + BinOp.mult (| + M.get_name (| globals, "GAS_LOG_DATA" |), + M.get_name (| globals, "size" |) + |) + |), + BinOp.mult (| + M.get_name (| globals, "GAS_LOG_TOPIC" |), + M.get_name (| globals, "num_topics" |) + |) + |), + M.get_field (| M.get_name (| globals, "extend_memory" |), "cost" |) + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "memory" |), + BinOp.mult (| + Constant.bytes "00", + M.get_field (| M.get_name (| globals, "extend_memory" |), "expand_by" |) + |) + |) in + let _ := M.assign_local (| + "log_entry" , + M.call (| + M.get_name (| globals, "Log" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, "evm" |), "logs" |), + BinOp.add (| + M.get_field (| M.get_name (| globals, "evm" |), "logs" |), + make_tuple [ M.get_name (| globals, "log_entry" |) ] + |) + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition log0 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "log_n" |) + ], + make_dict [] + |) +)). + +Definition log1 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "log_n" |) + ], + make_dict [] + |) +)). + +Definition log2 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "log_n" |) + ], + make_dict [] + |) +)). + +Definition log3 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "log_n" |) + ], + make_dict [] + |) +)). + +Definition log4 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "log_n" |) + ], + make_dict [] + |) +)). diff --git a/CoqOfPython/ethereum/frontier/vm/instructions/memory.v b/CoqOfPython/ethereum/frontier/vm/instructions/memory.v new file mode 100644 index 0000000..56c03a2 --- /dev/null +++ b/CoqOfPython/ethereum/frontier/vm/instructions/memory.v @@ -0,0 +1,393 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.frontier.vm.instructions.memory". + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) Memory Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM Memory instructions. +". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_Bytes : + IsImported globals "ethereum.base_types" "Bytes". + +Axiom ethereum_frontier_vm_imports_Evm : + IsImported globals "ethereum.frontier.vm" "Evm". + +Axiom ethereum_frontier_vm_gas_imports_GAS_BASE : + IsImported globals "ethereum.frontier.vm.gas" "GAS_BASE". +Axiom ethereum_frontier_vm_gas_imports_GAS_VERY_LOW : + IsImported globals "ethereum.frontier.vm.gas" "GAS_VERY_LOW". +Axiom ethereum_frontier_vm_gas_imports_calculate_gas_extend_memory : + IsImported globals "ethereum.frontier.vm.gas" "calculate_gas_extend_memory". +Axiom ethereum_frontier_vm_gas_imports_charge_gas : + IsImported globals "ethereum.frontier.vm.gas" "charge_gas". + +Axiom ethereum_frontier_vm_memory_imports_memory_read_bytes : + IsImported globals "ethereum.frontier.vm.memory" "memory_read_bytes". +Axiom ethereum_frontier_vm_memory_imports_memory_write : + IsImported globals "ethereum.frontier.vm.memory" "memory_write". + +Axiom ethereum_frontier_vm_stack_imports_pop : + IsImported globals "ethereum.frontier.vm.stack" "pop". +Axiom ethereum_frontier_vm_stack_imports_push : + IsImported globals "ethereum.frontier.vm.stack" "push". + +Definition mstore : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Stores a word to memory. + This also expands the memory, if the memory is + insufficient to store the word. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "start_position" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "value" , + M.call (| + M.get_field (| M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |), "to_be_bytes32" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "extend_memory" , + M.call (| + M.get_name (| globals, "calculate_gas_extend_memory" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "memory" |); + make_list [ + make_tuple [ M.get_name (| globals, "start_position" |); M.call (| + M.get_name (| globals, "U256" |), + make_list [ + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_name (| globals, "value" |) + ], + make_dict [] + |) + ], + make_dict [] + |) ] + ] + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + BinOp.add (| + M.get_name (| globals, "GAS_VERY_LOW" |), + M.get_field (| M.get_name (| globals, "extend_memory" |), "cost" |) + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "memory" |), + BinOp.mult (| + Constant.bytes "00", + M.get_field (| M.get_name (| globals, "extend_memory" |), "expand_by" |) + |) + |) in + let _ := M.call (| + M.get_name (| globals, "memory_write" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "memory" |); + M.get_name (| globals, "start_position" |); + M.get_name (| globals, "value" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition mstore8 : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Stores a byte to memory. + This also expands the memory, if the memory is + insufficient to store the word. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "start_position" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "value" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "extend_memory" , + M.call (| + M.get_name (| globals, "calculate_gas_extend_memory" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "memory" |); + make_list [ + make_tuple [ M.get_name (| globals, "start_position" |); M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 1 + ], + make_dict [] + |) ] + ] + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + BinOp.add (| + M.get_name (| globals, "GAS_VERY_LOW" |), + M.get_field (| M.get_name (| globals, "extend_memory" |), "cost" |) + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "memory" |), + BinOp.mult (| + Constant.bytes "00", + M.get_field (| M.get_name (| globals, "extend_memory" |), "expand_by" |) + |) + |) in + let _ := M.assign_local (| + "normalized_bytes_value" , + M.call (| + M.get_name (| globals, "Bytes" |), + make_list [ + make_list [ + BinOp.bit_and (| + M.get_name (| globals, "value" |), + Constant.int 255 + |) + ] + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "memory_write" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "memory" |); + M.get_name (| globals, "start_position" |); + M.get_name (| globals, "normalized_bytes_value" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition mload : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Load word from memory. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "start_position" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "extend_memory" , + M.call (| + M.get_name (| globals, "calculate_gas_extend_memory" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "memory" |); + make_list [ + make_tuple [ M.get_name (| globals, "start_position" |); M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 32 + ], + make_dict [] + |) ] + ] + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + BinOp.add (| + M.get_name (| globals, "GAS_VERY_LOW" |), + M.get_field (| M.get_name (| globals, "extend_memory" |), "cost" |) + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "memory" |), + BinOp.mult (| + Constant.bytes "00", + M.get_field (| M.get_name (| globals, "extend_memory" |), "expand_by" |) + |) + |) in + let _ := M.assign_local (| + "value" , + M.call (| + M.get_field (| M.get_name (| globals, "U256" |), "from_be_bytes" |), + make_list [ + M.call (| + M.get_name (| globals, "memory_read_bytes" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "memory" |); + M.get_name (| globals, "start_position" |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 32 + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.get_name (| globals, "value" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition msize : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Push the size of active memory in bytes onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_BASE" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "memory" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). diff --git a/CoqOfPython/ethereum/frontier/vm/instructions/stack.v b/CoqOfPython/ethereum/frontier/vm/instructions/stack.v new file mode 100644 index 0000000..18ec37d --- /dev/null +++ b/CoqOfPython/ethereum/frontier/vm/instructions/stack.v @@ -0,0 +1,947 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.frontier.vm.instructions.stack". + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) Stack Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM stack related instructions. +". + +Axiom functools_imports_partial : + IsImported globals "functools" "partial". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". + +Axiom ethereum_utils_ensure_imports_ensure : + IsImported globals "ethereum.utils.ensure" "ensure". + +Axiom ethereum_frontier_vm_imports_Evm : + IsImported globals "ethereum.frontier.vm" "Evm". +Axiom ethereum_frontier_vm_imports_stack : + IsImported globals "ethereum.frontier.vm" "stack". + +Axiom ethereum_frontier_vm_exceptions_imports_StackUnderflowError : + IsImported globals "ethereum.frontier.vm.exceptions" "StackUnderflowError". + +Axiom ethereum_frontier_vm_gas_imports_GAS_BASE : + IsImported globals "ethereum.frontier.vm.gas" "GAS_BASE". +Axiom ethereum_frontier_vm_gas_imports_GAS_VERY_LOW : + IsImported globals "ethereum.frontier.vm.gas" "GAS_VERY_LOW". +Axiom ethereum_frontier_vm_gas_imports_charge_gas : + IsImported globals "ethereum.frontier.vm.gas" "charge_gas". + +Axiom ethereum_frontier_vm_memory_imports_buffer_read : + IsImported globals "ethereum.frontier.vm.memory" "buffer_read". + +Definition pop : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Remove item from stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.call (| + M.get_field (| M.get_name (| globals, "stack" |), "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_BASE" |) + ], + make_dict [] + |) in + let _ := M.pass (| |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition push_n : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm"; "num_bytes" ] |) in + let _ := Constant.str " + Pushes a N-byte immediate onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + num_bytes : + The number of immediate bytes to be read from the code and pushed to + the stack. + + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_VERY_LOW" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "data_to_push" , + M.call (| + M.get_field (| M.get_name (| globals, "U256" |), "from_be_bytes" |), + make_list [ + M.call (| + M.get_name (| globals, "buffer_read" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "code" |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + BinOp.add (| + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) + ], + make_dict [] + |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + M.get_name (| globals, "num_bytes" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_field (| M.get_name (| globals, "stack" |), "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.get_name (| globals, "data_to_push" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + BinOp.add (| + Constant.int 1, + M.get_name (| globals, "num_bytes" |) + |) + |) in + M.pure Constant.None_)). + +Definition dup_n : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm"; "item_number" ] |) in + let _ := Constant.str " + Duplicate the Nth stack item (from top of the stack) to the top of stack. + + Parameters + ---------- + evm : + The current EVM frame. + + item_number : + The stack item number (0-indexed from top of stack) to be duplicated + to the top of stack. + + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_VERY_LOW" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + Compare.lt (| + M.get_name (| globals, "item_number" |), + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |); + M.get_name (| globals, "StackUnderflowError" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "data_to_duplicate" , + M.get_subscript (| + M.get_field (| M.get_name (| globals, "evm" |), "stack" |), + BinOp.sub (| + BinOp.sub (| + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |), + Constant.int 1 + |), + M.get_name (| globals, "item_number" |) + |) + |) + |) in + let _ := M.call (| + M.get_field (| M.get_name (| globals, "stack" |), "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.get_name (| globals, "data_to_duplicate" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition swap_n : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm"; "item_number" ] |) in + let _ := Constant.str " + Swap the top and the `item_number` element of the stack, where + the top of the stack is position zero. + + If `item_number` is zero, this function does nothing (which should not be + possible, since there is no `SWAP0` instruction). + + Parameters + ---------- + evm : + The current EVM frame. + + item_number : + The stack item number (0-indexed from top of stack) to be swapped + with the top of stack element. + + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_VERY_LOW" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + Compare.lt (| + M.get_name (| globals, "item_number" |), + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |); + M.get_name (| globals, "StackUnderflowError" |) + ], + make_dict [] + |) in + let _ := M.assign (| + make_tuple [ M.get_subscript (| + M.get_field (| M.get_name (| globals, "evm" |), "stack" |), + UnOp.sub (| Constant.int 1 |) + |); M.get_subscript (| + M.get_field (| M.get_name (| globals, "evm" |), "stack" |), + BinOp.sub (| + UnOp.sub (| Constant.int 1 |), + M.get_name (| globals, "item_number" |) + |) + |) ], + make_tuple [ M.get_subscript (| + M.get_field (| M.get_name (| globals, "evm" |), "stack" |), + BinOp.sub (| + UnOp.sub (| Constant.int 1 |), + M.get_name (| globals, "item_number" |) + |) + |); M.get_subscript (| + M.get_field (| M.get_name (| globals, "evm" |), "stack" |), + UnOp.sub (| Constant.int 1 |) + |) ] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition push1 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push2 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push3 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push4 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push5 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push6 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push7 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push8 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push9 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push10 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push11 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push12 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push13 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push14 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push15 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push16 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push17 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push18 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push19 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push20 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push21 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push22 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push23 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push24 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push25 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push26 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push27 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push28 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push29 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push30 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push31 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push32 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "push_n" |) + ], + make_dict [] + |) +)). + +Definition dup1 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "dup_n" |) + ], + make_dict [] + |) +)). + +Definition dup2 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "dup_n" |) + ], + make_dict [] + |) +)). + +Definition dup3 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "dup_n" |) + ], + make_dict [] + |) +)). + +Definition dup4 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "dup_n" |) + ], + make_dict [] + |) +)). + +Definition dup5 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "dup_n" |) + ], + make_dict [] + |) +)). + +Definition dup6 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "dup_n" |) + ], + make_dict [] + |) +)). + +Definition dup7 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "dup_n" |) + ], + make_dict [] + |) +)). + +Definition dup8 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "dup_n" |) + ], + make_dict [] + |) +)). + +Definition dup9 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "dup_n" |) + ], + make_dict [] + |) +)). + +Definition dup10 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "dup_n" |) + ], + make_dict [] + |) +)). + +Definition dup11 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "dup_n" |) + ], + make_dict [] + |) +)). + +Definition dup12 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "dup_n" |) + ], + make_dict [] + |) +)). + +Definition dup13 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "dup_n" |) + ], + make_dict [] + |) +)). + +Definition dup14 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "dup_n" |) + ], + make_dict [] + |) +)). + +Definition dup15 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "dup_n" |) + ], + make_dict [] + |) +)). + +Definition dup16 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "dup_n" |) + ], + make_dict [] + |) +)). + +Definition swap1 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "swap_n" |) + ], + make_dict [] + |) +)). + +Definition swap2 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "swap_n" |) + ], + make_dict [] + |) +)). + +Definition swap3 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "swap_n" |) + ], + make_dict [] + |) +)). + +Definition swap4 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "swap_n" |) + ], + make_dict [] + |) +)). + +Definition swap5 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "swap_n" |) + ], + make_dict [] + |) +)). + +Definition swap6 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "swap_n" |) + ], + make_dict [] + |) +)). + +Definition swap7 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "swap_n" |) + ], + make_dict [] + |) +)). + +Definition swap8 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "swap_n" |) + ], + make_dict [] + |) +)). + +Definition swap9 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "swap_n" |) + ], + make_dict [] + |) +)). + +Definition swap10 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "swap_n" |) + ], + make_dict [] + |) +)). + +Definition swap11 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "swap_n" |) + ], + make_dict [] + |) +)). + +Definition swap12 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "swap_n" |) + ], + make_dict [] + |) +)). + +Definition swap13 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "swap_n" |) + ], + make_dict [] + |) +)). + +Definition swap14 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "swap_n" |) + ], + make_dict [] + |) +)). + +Definition swap15 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "swap_n" |) + ], + make_dict [] + |) +)). + +Definition swap16 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "swap_n" |) + ], + make_dict [] + |) +)). diff --git a/CoqOfPython/ethereum/frontier/vm/instructions/storage.v b/CoqOfPython/ethereum/frontier/vm/instructions/storage.v new file mode 100644 index 0000000..754b34a --- /dev/null +++ b/CoqOfPython/ethereum/frontier/vm/instructions/storage.v @@ -0,0 +1,234 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.frontier.vm.instructions.storage". + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) Storage Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM storage related instructions. +". + +Axiom ethereum_frontier_state_imports_get_storage : + IsImported globals "ethereum.frontier.state" "get_storage". +Axiom ethereum_frontier_state_imports_set_storage : + IsImported globals "ethereum.frontier.state" "set_storage". + +Axiom ethereum_frontier_vm_imports_Evm : + IsImported globals "ethereum.frontier.vm" "Evm". + +Axiom ethereum_frontier_vm_gas_imports_GAS_SLOAD : + IsImported globals "ethereum.frontier.vm.gas" "GAS_SLOAD". +Axiom ethereum_frontier_vm_gas_imports_GAS_STORAGE_CLEAR_REFUND : + IsImported globals "ethereum.frontier.vm.gas" "GAS_STORAGE_CLEAR_REFUND". +Axiom ethereum_frontier_vm_gas_imports_GAS_STORAGE_SET : + IsImported globals "ethereum.frontier.vm.gas" "GAS_STORAGE_SET". +Axiom ethereum_frontier_vm_gas_imports_GAS_STORAGE_UPDATE : + IsImported globals "ethereum.frontier.vm.gas" "GAS_STORAGE_UPDATE". +Axiom ethereum_frontier_vm_gas_imports_charge_gas : + IsImported globals "ethereum.frontier.vm.gas" "charge_gas". + +Axiom ethereum_frontier_vm_stack_imports_pop : + IsImported globals "ethereum.frontier.vm.stack" "pop". +Axiom ethereum_frontier_vm_stack_imports_push : + IsImported globals "ethereum.frontier.vm.stack" "push". + +Definition sload : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Loads to the stack, the value corresponding to a certain key from the + storage of the current account. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "key" , + M.call (| + M.get_field (| M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |), "to_be_bytes32" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_SLOAD" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "value" , + M.call (| + M.get_name (| globals, "get_storage" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "env" |), "state" |); + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "current_target" |); + M.get_name (| globals, "key" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.get_name (| globals, "value" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition sstore : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Stores a value at a certain key in the current context's storage. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "key" , + M.call (| + M.get_field (| M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |), "to_be_bytes32" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "new_value" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "current_value" , + M.call (| + M.get_name (| globals, "get_storage" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "env" |), "state" |); + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "current_target" |); + M.get_name (| globals, "key" |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + BoolOp.and (| + Compare.not_eq (| + M.get_name (| globals, "new_value" |), + Constant.int 0 + |), + ltac:(M.monadic ( + Compare.eq (| + M.get_name (| globals, "current_value" |), + Constant.int 0 + |) + )) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "gas_cost" , + M.get_name (| globals, "GAS_STORAGE_SET" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "gas_cost" , + M.get_name (| globals, "GAS_STORAGE_UPDATE" |) + |) in + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + BoolOp.and (| + Compare.eq (| + M.get_name (| globals, "new_value" |), + Constant.int 0 + |), + ltac:(M.monadic ( + Compare.not_eq (| + M.get_name (| globals, "current_value" |), + Constant.int 0 + |) + )) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "refund_counter" |), + M.get_name (| globals, "GAS_STORAGE_CLEAR_REFUND" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "gas_cost" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "set_storage" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "env" |), "state" |); + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "current_target" |); + M.get_name (| globals, "key" |); + M.get_name (| globals, "new_value" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). diff --git a/CoqOfPython/ethereum/frontier/vm/instructions/system.v b/CoqOfPython/ethereum/frontier/vm/instructions/system.v new file mode 100644 index 0000000..35a1fee --- /dev/null +++ b/CoqOfPython/ethereum/frontier/vm/instructions/system.v @@ -0,0 +1,1237 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.frontier.vm.instructions.system". + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) System Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM system related instructions. +". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_Bytes0 : + IsImported globals "ethereum.base_types" "Bytes0". +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". + +Axiom ethereum_frontier_fork_types_imports_Address : + IsImported globals "ethereum.frontier.fork_types" "Address". + +Axiom ethereum_frontier_state_imports_account_has_code_or_nonce : + IsImported globals "ethereum.frontier.state" "account_has_code_or_nonce". +Axiom ethereum_frontier_state_imports_get_account : + IsImported globals "ethereum.frontier.state" "get_account". +Axiom ethereum_frontier_state_imports_increment_nonce : + IsImported globals "ethereum.frontier.state" "increment_nonce". +Axiom ethereum_frontier_state_imports_set_account_balance : + IsImported globals "ethereum.frontier.state" "set_account_balance". + +Axiom ethereum_frontier_utils_address_imports_compute_contract_address : + IsImported globals "ethereum.frontier.utils.address" "compute_contract_address". +Axiom ethereum_frontier_utils_address_imports_to_address : + IsImported globals "ethereum.frontier.utils.address" "to_address". + +Axiom ethereum_frontier_vm_imports_Evm : + IsImported globals "ethereum.frontier.vm" "Evm". +Axiom ethereum_frontier_vm_imports_Message : + IsImported globals "ethereum.frontier.vm" "Message". +Axiom ethereum_frontier_vm_imports_incorporate_child_on_error : + IsImported globals "ethereum.frontier.vm" "incorporate_child_on_error". +Axiom ethereum_frontier_vm_imports_incorporate_child_on_success : + IsImported globals "ethereum.frontier.vm" "incorporate_child_on_success". + +Axiom ethereum_frontier_vm_gas_imports_GAS_CREATE : + IsImported globals "ethereum.frontier.vm.gas" "GAS_CREATE". +Axiom ethereum_frontier_vm_gas_imports_GAS_ZERO : + IsImported globals "ethereum.frontier.vm.gas" "GAS_ZERO". +Axiom ethereum_frontier_vm_gas_imports_REFUND_SELF_DESTRUCT : + IsImported globals "ethereum.frontier.vm.gas" "REFUND_SELF_DESTRUCT". +Axiom ethereum_frontier_vm_gas_imports_calculate_gas_extend_memory : + IsImported globals "ethereum.frontier.vm.gas" "calculate_gas_extend_memory". +Axiom ethereum_frontier_vm_gas_imports_calculate_message_call_gas : + IsImported globals "ethereum.frontier.vm.gas" "calculate_message_call_gas". +Axiom ethereum_frontier_vm_gas_imports_charge_gas : + IsImported globals "ethereum.frontier.vm.gas" "charge_gas". + +Axiom ethereum_frontier_vm_memory_imports_memory_read_bytes : + IsImported globals "ethereum.frontier.vm.memory" "memory_read_bytes". +Axiom ethereum_frontier_vm_memory_imports_memory_write : + IsImported globals "ethereum.frontier.vm.memory" "memory_write". + +Axiom ethereum_frontier_vm_stack_imports_pop : + IsImported globals "ethereum.frontier.vm.stack" "pop". +Axiom ethereum_frontier_vm_stack_imports_push : + IsImported globals "ethereum.frontier.vm.stack" "push". + +Definition create : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Creates a new account with associated code. + + Parameters + ---------- + evm : + The current EVM frame. + " in +(* At stmt: unsupported node type: ImportFrom *) + let _ := M.assign_local (| + "endowment" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_start_position" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_size" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "extend_memory" , + M.call (| + M.get_name (| globals, "calculate_gas_extend_memory" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "memory" |); + make_list [ + make_tuple [ M.get_name (| globals, "memory_start_position" |); M.get_name (| globals, "memory_size" |) ] + ] + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + BinOp.add (| + M.get_name (| globals, "GAS_CREATE" |), + M.get_field (| M.get_name (| globals, "extend_memory" |), "cost" |) + |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "create_message_gas" , + M.get_field (| M.get_name (| globals, "evm" |), "gas_left" |) + |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, "evm" |), "gas_left" |), + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "memory" |), + BinOp.mult (| + Constant.bytes "00", + M.get_field (| M.get_name (| globals, "extend_memory" |), "expand_by" |) + |) + |) in + let _ := M.assign_local (| + "sender_address" , + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "current_target" |) + |) in + let _ := M.assign_local (| + "sender" , + M.call (| + M.get_name (| globals, "get_account" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "env" |), "state" |); + M.get_name (| globals, "sender_address" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "contract_address" , + M.call (| + M.get_name (| globals, "compute_contract_address" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "current_target" |); + M.get_field (| M.call (| + M.get_name (| globals, "get_account" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "env" |), "state" |); + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "current_target" |) + ], + make_dict [] + |), "nonce" |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + BoolOp.or (| + Compare.lt (| + M.get_field (| M.get_name (| globals, "sender" |), "balance" |), + M.get_name (| globals, "endowment" |) + |), + ltac:(M.monadic ( + BoolOp.or (| + Compare.eq (| + M.get_field (| M.get_name (| globals, "sender" |), "nonce" |), + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + BinOp.sub (| + BinOp.pow (| + Constant.int 2, + Constant.int 64 + |), + Constant.int 1 + |) + ], + make_dict [] + |) + |), + ltac:(M.monadic ( + Compare.gt (| + BinOp.add (| + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "depth" |), + Constant.int 1 + |), + M.get_name (| globals, "STACK_DEPTH_LIMIT" |) + |) + )) + |) + )) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "gas_left" |), + M.get_name (| globals, "create_message_gas" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, "account_has_code_or_nonce" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "env" |), "state" |); + M.get_name (| globals, "contract_address" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, "increment_nonce" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "env" |), "state" |); + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "current_target" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + ], + make_dict [] + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "call_data" , + M.call (| + M.get_name (| globals, "memory_read_bytes" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "memory" |); + M.get_name (| globals, "memory_start_position" |); + M.get_name (| globals, "memory_size" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "increment_nonce" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "env" |), "state" |); + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "current_target" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "child_message" , + M.call (| + M.get_name (| globals, "Message" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "child_evm" , + M.call (| + M.get_name (| globals, "process_create_message" |), + make_list [ + M.get_name (| globals, "child_message" |); + M.get_field (| M.get_name (| globals, "evm" |), "env" |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + M.get_field (| M.get_name (| globals, "child_evm" |), "error" |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, "incorporate_child_on_error" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "child_evm" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + ], + make_dict [] + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, "incorporate_child_on_success" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "child_evm" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.call (| + M.get_field (| M.get_name (| globals, "U256" |), "from_be_bytes" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "child_evm" |), "message" |), "current_target" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )) |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition return_ : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Halts execution returning output data. + + Parameters + ---------- + evm : + The current EVM frame. + " in + let _ := M.assign_local (| + "memory_start_position" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_size" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "extend_memory" , + M.call (| + M.get_name (| globals, "calculate_gas_extend_memory" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "memory" |); + make_list [ + make_tuple [ M.get_name (| globals, "memory_start_position" |); M.get_name (| globals, "memory_size" |) ] + ] + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + BinOp.add (| + M.get_name (| globals, "GAS_ZERO" |), + M.get_field (| M.get_name (| globals, "extend_memory" |), "cost" |) + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "memory" |), + BinOp.mult (| + Constant.bytes "00", + M.get_field (| M.get_name (| globals, "extend_memory" |), "expand_by" |) + |) + |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, "evm" |), "output" |), + M.call (| + M.get_name (| globals, "memory_read_bytes" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "memory" |); + M.get_name (| globals, "memory_start_position" |); + M.get_name (| globals, "memory_size" |) + ], + make_dict [] + |) + |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, "evm" |), "running" |), + Constant.bool false + |) in + let _ := M.pass (| |) in + M.pure Constant.None_)). + +Definition generic_call : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm"; "gas"; "value"; "caller"; "to"; "code_address"; "memory_input_start_position"; "memory_input_size"; "memory_output_start_position"; "memory_output_size" ] |) in + let _ := Constant.str " + Perform the core logic of the `CALL*` family of opcodes. + " in +(* At stmt: unsupported node type: ImportFrom *) + let _ := + (* if *) + M.if_then_else (| + Compare.gt (| + BinOp.add (| + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "depth" |), + Constant.int 1 + |), + M.get_name (| globals, "STACK_DEPTH_LIMIT" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "gas_left" |), + M.get_name (| globals, "gas" |) + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.return_ (| + Constant.None_ + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "call_data" , + M.call (| + M.get_name (| globals, "memory_read_bytes" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "memory" |); + M.get_name (| globals, "memory_input_start_position" |); + M.get_name (| globals, "memory_input_size" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "code" , + M.get_field (| M.call (| + M.get_name (| globals, "get_account" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "env" |), "state" |); + M.get_name (| globals, "code_address" |) + ], + make_dict [] + |), "code" |) + |) in + let _ := M.assign_local (| + "child_message" , + M.call (| + M.get_name (| globals, "Message" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "child_evm" , + M.call (| + M.get_name (| globals, "process_message" |), + make_list [ + M.get_name (| globals, "child_message" |); + M.get_field (| M.get_name (| globals, "evm" |), "env" |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + M.get_field (| M.get_name (| globals, "child_evm" |), "error" |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, "incorporate_child_on_error" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "child_evm" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + ], + make_dict [] + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, "incorporate_child_on_success" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "child_evm" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 1 + ], + make_dict [] + |) + ], + make_dict [] + |) in + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "actual_output_size" , + M.call (| + M.get_name (| globals, "min" |), + make_list [ + M.get_name (| globals, "memory_output_size" |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_field (| M.get_name (| globals, "child_evm" |), "output" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "memory_write" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "memory" |); + M.get_name (| globals, "memory_output_start_position" |); + M.slice (| + M.get_field (| M.get_name (| globals, "child_evm" |), "output" |), + Constant.None_, + M.get_name (| globals, "actual_output_size" |), + Constant.None_ + |) + ], + make_dict [] + |) in + M.pure Constant.None_)). + +Definition call : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Message-call into an account. + + Parameters + ---------- + evm : + The current EVM frame. + " in + let _ := M.assign_local (| + "gas" , + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "to" , + M.call (| + M.get_name (| globals, "to_address" |), + make_list [ + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "value" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_input_start_position" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_input_size" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_output_start_position" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_output_size" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "extend_memory" , + M.call (| + M.get_name (| globals, "calculate_gas_extend_memory" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "memory" |); + make_list [ + make_tuple [ M.get_name (| globals, "memory_input_start_position" |); M.get_name (| globals, "memory_input_size" |) ]; + make_tuple [ M.get_name (| globals, "memory_output_start_position" |); M.get_name (| globals, "memory_output_size" |) ] + ] + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "message_call_gas" , + M.call (| + M.get_name (| globals, "calculate_message_call_gas" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "env" |), "state" |); + M.get_name (| globals, "gas" |); + M.get_name (| globals, "to" |); + M.get_name (| globals, "value" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + BinOp.add (| + M.get_field (| M.get_name (| globals, "message_call_gas" |), "cost" |), + M.get_field (| M.get_name (| globals, "extend_memory" |), "cost" |) + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "memory" |), + BinOp.mult (| + Constant.bytes "00", + M.get_field (| M.get_name (| globals, "extend_memory" |), "expand_by" |) + |) + |) in + let _ := M.assign_local (| + "sender_balance" , + M.get_field (| M.call (| + M.get_name (| globals, "get_account" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "env" |), "state" |); + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "current_target" |) + ], + make_dict [] + |), "balance" |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.lt (| + M.get_name (| globals, "sender_balance" |), + M.get_name (| globals, "value" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "gas_left" |), + M.get_field (| M.get_name (| globals, "message_call_gas" |), "stipend" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, "generic_call" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_field (| M.get_name (| globals, "message_call_gas" |), "stipend" |); + M.get_name (| globals, "value" |); + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "current_target" |); + M.get_name (| globals, "to" |); + M.get_name (| globals, "to" |); + M.get_name (| globals, "memory_input_start_position" |); + M.get_name (| globals, "memory_input_size" |); + M.get_name (| globals, "memory_output_start_position" |); + M.get_name (| globals, "memory_output_size" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + )) |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition callcode : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Message-call into this account with alternative account’s code. + + Parameters + ---------- + evm : + The current EVM frame. + " in + let _ := M.assign_local (| + "gas" , + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "code_address" , + M.call (| + M.get_name (| globals, "to_address" |), + make_list [ + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "value" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_input_start_position" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_input_size" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_output_start_position" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_output_size" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "to" , + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "current_target" |) + |) in + let _ := M.assign_local (| + "extend_memory" , + M.call (| + M.get_name (| globals, "calculate_gas_extend_memory" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "memory" |); + make_list [ + make_tuple [ M.get_name (| globals, "memory_input_start_position" |); M.get_name (| globals, "memory_input_size" |) ]; + make_tuple [ M.get_name (| globals, "memory_output_start_position" |); M.get_name (| globals, "memory_output_size" |) ] + ] + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "message_call_gas" , + M.call (| + M.get_name (| globals, "calculate_message_call_gas" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "env" |), "state" |); + M.get_name (| globals, "gas" |); + M.get_name (| globals, "to" |); + M.get_name (| globals, "value" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + BinOp.add (| + M.get_field (| M.get_name (| globals, "message_call_gas" |), "cost" |), + M.get_field (| M.get_name (| globals, "extend_memory" |), "cost" |) + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "memory" |), + BinOp.mult (| + Constant.bytes "00", + M.get_field (| M.get_name (| globals, "extend_memory" |), "expand_by" |) + |) + |) in + let _ := M.assign_local (| + "sender_balance" , + M.get_field (| M.call (| + M.get_name (| globals, "get_account" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "env" |), "state" |); + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "current_target" |) + ], + make_dict [] + |), "balance" |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.lt (| + M.get_name (| globals, "sender_balance" |), + M.get_name (| globals, "value" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "gas_left" |), + M.get_field (| M.get_name (| globals, "message_call_gas" |), "stipend" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, "generic_call" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_field (| M.get_name (| globals, "message_call_gas" |), "stipend" |); + M.get_name (| globals, "value" |); + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "current_target" |); + M.get_name (| globals, "to" |); + M.get_name (| globals, "code_address" |); + M.get_name (| globals, "memory_input_start_position" |); + M.get_name (| globals, "memory_input_size" |); + M.get_name (| globals, "memory_output_start_position" |); + M.get_name (| globals, "memory_output_size" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + )) |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition selfdestruct : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Halt execution and register account for later deletion. + + Parameters + ---------- + evm : + The current EVM frame. + " in + let _ := M.assign_local (| + "beneficiary" , + M.call (| + M.get_name (| globals, "to_address" |), + make_list [ + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "gas_cost" , + M.get_name (| globals, "GAS_ZERO" |) + |) in + let _ := M.assign_local (| + "originator" , + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "current_target" |) + |) in + let _ := M.assign_local (| + "refunded_accounts" , + M.get_field (| M.get_name (| globals, "evm" |), "accounts_to_delete" |) + |) in + let _ := M.assign_local (| + "parent_evm" , + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "parent_evm" |) + |) in + let _ := + M.while (| + Compare.is_not (| + M.get_name (| globals, "parent_evm" |), + Constant.None_ + |), + ltac:(M.monadic ( + let _ := M.call (| + M.get_field (| M.get_name (| globals, "refunded_accounts" |), "update" |), + make_list [ + M.get_field (| M.get_name (| globals, "parent_evm" |), "accounts_to_delete" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "parent_evm" , + M.get_field (| M.get_field (| M.get_name (| globals, "parent_evm" |), "message" |), "parent_evm" |) + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.not_in (| + M.get_name (| globals, "originator" |), + M.get_name (| globals, "refunded_accounts" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "refund_counter" |), + M.get_name (| globals, "REFUND_SELF_DESTRUCT" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "gas_cost" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "beneficiary_balance" , + M.get_field (| M.call (| + M.get_name (| globals, "get_account" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "env" |), "state" |); + M.get_name (| globals, "beneficiary" |) + ], + make_dict [] + |), "balance" |) + |) in + let _ := M.assign_local (| + "originator_balance" , + M.get_field (| M.call (| + M.get_name (| globals, "get_account" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "env" |), "state" |); + M.get_name (| globals, "originator" |) + ], + make_dict [] + |), "balance" |) + |) in + let _ := M.call (| + M.get_name (| globals, "set_account_balance" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "env" |), "state" |); + M.get_name (| globals, "beneficiary" |); + BinOp.add (| + M.get_name (| globals, "beneficiary_balance" |), + M.get_name (| globals, "originator_balance" |) + |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "set_account_balance" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "env" |), "state" |); + M.get_name (| globals, "originator" |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "accounts_to_delete" |), "add" |), + make_list [ + M.get_name (| globals, "originator" |) + ], + make_dict [] + |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, "evm" |), "running" |), + Constant.bool false + |) in + let _ := M.pass (| |) in + M.pure Constant.None_)). diff --git a/CoqOfPython/ethereum/frontier/vm/interpreter.v b/CoqOfPython/ethereum/frontier/vm/interpreter.v new file mode 100644 index 0000000..e1d892f --- /dev/null +++ b/CoqOfPython/ethereum/frontier/vm/interpreter.v @@ -0,0 +1,580 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.frontier.vm.interpreter". + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) Interpreter +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +A straightforward interpreter that executes EVM code. +". + +Axiom dataclasses_imports_dataclass : + IsImported globals "dataclasses" "dataclass". + +Axiom typing_imports_Optional : + IsImported globals "typing" "Optional". +Axiom typing_imports_Set : + IsImported globals "typing" "Set". +Axiom typing_imports_Tuple : + IsImported globals "typing" "Tuple". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_Bytes0 : + IsImported globals "ethereum.base_types" "Bytes0". +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". + +Axiom ethereum_trace_imports_EvmStop : + IsImported globals "ethereum.trace" "EvmStop". +Axiom ethereum_trace_imports_OpEnd : + IsImported globals "ethereum.trace" "OpEnd". +Axiom ethereum_trace_imports_OpException : + IsImported globals "ethereum.trace" "OpException". +Axiom ethereum_trace_imports_OpStart : + IsImported globals "ethereum.trace" "OpStart". +Axiom ethereum_trace_imports_PrecompileEnd : + IsImported globals "ethereum.trace" "PrecompileEnd". +Axiom ethereum_trace_imports_PrecompileStart : + IsImported globals "ethereum.trace" "PrecompileStart". +Axiom ethereum_trace_imports_TransactionEnd : + IsImported globals "ethereum.trace" "TransactionEnd". +Axiom ethereum_trace_imports_evm_trace : + IsImported globals "ethereum.trace" "evm_trace". + +Axiom ethereum_frontier_blocks_imports_Log : + IsImported globals "ethereum.frontier.blocks" "Log". + +Axiom ethereum_frontier_fork_types_imports_Address : + IsImported globals "ethereum.frontier.fork_types" "Address". + +Axiom ethereum_frontier_state_imports_account_has_code_or_nonce : + IsImported globals "ethereum.frontier.state" "account_has_code_or_nonce". +Axiom ethereum_frontier_state_imports_begin_transaction : + IsImported globals "ethereum.frontier.state" "begin_transaction". +Axiom ethereum_frontier_state_imports_commit_transaction : + IsImported globals "ethereum.frontier.state" "commit_transaction". +Axiom ethereum_frontier_state_imports_destroy_storage : + IsImported globals "ethereum.frontier.state" "destroy_storage". +Axiom ethereum_frontier_state_imports_move_ether : + IsImported globals "ethereum.frontier.state" "move_ether". +Axiom ethereum_frontier_state_imports_rollback_transaction : + IsImported globals "ethereum.frontier.state" "rollback_transaction". +Axiom ethereum_frontier_state_imports_set_code : + IsImported globals "ethereum.frontier.state" "set_code". +Axiom ethereum_frontier_state_imports_touch_account : + IsImported globals "ethereum.frontier.state" "touch_account". + +Axiom ethereum_frontier_vm_imports_Message : + IsImported globals "ethereum.frontier.vm" "Message". + +Axiom ethereum_frontier_vm_gas_imports_GAS_CODE_DEPOSIT : + IsImported globals "ethereum.frontier.vm.gas" "GAS_CODE_DEPOSIT". +Axiom ethereum_frontier_vm_gas_imports_charge_gas : + IsImported globals "ethereum.frontier.vm.gas" "charge_gas". + +Axiom ethereum_frontier_vm_precompiled_contracts_mapping_imports_PRE_COMPILED_CONTRACTS : + IsImported globals "ethereum.frontier.vm.precompiled_contracts.mapping" "PRE_COMPILED_CONTRACTS". + +Axiom ethereum_frontier_vm_imports_Environment : + IsImported globals "ethereum.frontier.vm" "Environment". +Axiom ethereum_frontier_vm_imports_Evm : + IsImported globals "ethereum.frontier.vm" "Evm". + +Axiom ethereum_frontier_vm_exceptions_imports_AddressCollision : + IsImported globals "ethereum.frontier.vm.exceptions" "AddressCollision". +Axiom ethereum_frontier_vm_exceptions_imports_ExceptionalHalt : + IsImported globals "ethereum.frontier.vm.exceptions" "ExceptionalHalt". +Axiom ethereum_frontier_vm_exceptions_imports_InvalidOpcode : + IsImported globals "ethereum.frontier.vm.exceptions" "InvalidOpcode". +Axiom ethereum_frontier_vm_exceptions_imports_StackDepthLimitError : + IsImported globals "ethereum.frontier.vm.exceptions" "StackDepthLimitError". + +Axiom ethereum_frontier_vm_instructions_imports_Ops : + IsImported globals "ethereum.frontier.vm.instructions" "Ops". +Axiom ethereum_frontier_vm_instructions_imports_op_implementation : + IsImported globals "ethereum.frontier.vm.instructions" "op_implementation". + +Axiom ethereum_frontier_vm_runtime_imports_get_valid_jump_destinations : + IsImported globals "ethereum.frontier.vm.runtime" "get_valid_jump_destinations". + +Definition STACK_DEPTH_LIMIT : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 1024 + ], + make_dict [] + |) +)). + +Definition MessageCallOutput : Value.t := + builtins.make_klass + [] + [ + + ] + [ + + ]. + +Definition process_message_call : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "message"; "env" ] |) in + let _ := Constant.str " + If `message.current` is empty then it creates a smart contract + else it executes a call from the `message.caller` to the `message.target`. + + Parameters + ---------- + message : + Transaction specific items. + + env : + External items required for EVM execution. + + Returns + ------- + output : `MessageCallOutput` + Output of the message call + " in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_field (| M.get_name (| globals, "message" |), "target" |), + M.call (| + M.get_name (| globals, "Bytes0" |), + make_list [ + Constant.bytes "" + ], + make_dict [] + |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "is_collision" , + M.call (| + M.get_name (| globals, "account_has_code_or_nonce" |), + make_list [ + M.get_field (| M.get_name (| globals, "env" |), "state" |); + M.get_field (| M.get_name (| globals, "message" |), "current_target" |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + M.get_name (| globals, "is_collision" |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + M.call (| + M.get_name (| globals, "MessageCallOutput" |), + make_list [ + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |); + M.call (| + M.get_name (| globals, "tuple" |), + make_list [], + make_dict [] + |); + M.call (| + M.get_name (| globals, "set" |), + make_list [], + make_dict [] + |); + M.call (| + M.get_name (| globals, "AddressCollision" |), + make_list [], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "evm" , + M.call (| + M.get_name (| globals, "process_create_message" |), + make_list [ + M.get_name (| globals, "message" |); + M.get_name (| globals, "env" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "evm" , + M.call (| + M.get_name (| globals, "process_message" |), + make_list [ + M.get_name (| globals, "message" |); + M.get_name (| globals, "env" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + M.get_field (| M.get_name (| globals, "evm" |), "error" |), + (* then *) + ltac:(M.monadic ( +(* At stmt: unsupported node type: AnnAssign *) + let _ := M.assign_local (| + "accounts_to_delete" , + M.call (| + M.get_name (| globals, "set" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "refund_counter" , + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "logs" , + M.get_field (| M.get_name (| globals, "evm" |), "logs" |) + |) in + let _ := M.assign_local (| + "accounts_to_delete" , + M.get_field (| M.get_name (| globals, "evm" |), "accounts_to_delete" |) + |) in + let _ := M.assign_local (| + "refund_counter" , + M.get_field (| M.get_name (| globals, "evm" |), "refund_counter" |) + |) in + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "tx_end" , + M.call (| + M.get_name (| globals, "TransactionEnd" |), + make_list [ + BinOp.sub (| + M.get_field (| M.get_name (| globals, "message" |), "gas" |), + M.get_field (| M.get_name (| globals, "evm" |), "gas_left" |) + |); + M.get_field (| M.get_name (| globals, "evm" |), "output" |); + M.get_field (| M.get_name (| globals, "evm" |), "error" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "evm_trace" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "tx_end" |) + ], + make_dict [] + |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, "MessageCallOutput" |), + make_list [], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Definition process_create_message : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "message"; "env" ] |) in + let _ := Constant.str " + Executes a call to create a smart contract. + + Parameters + ---------- + message : + Transaction specific items. + env : + External items required for EVM execution. + + Returns + ------- + evm: :py:class:`~ethereum.frontier.vm.Evm` + Items containing execution specific objects. + " in + let _ := M.call (| + M.get_name (| globals, "begin_transaction" |), + make_list [ + M.get_field (| M.get_name (| globals, "env" |), "state" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "destroy_storage" |), + make_list [ + M.get_field (| M.get_name (| globals, "env" |), "state" |); + M.get_field (| M.get_name (| globals, "message" |), "current_target" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "evm" , + M.call (| + M.get_name (| globals, "process_message" |), + make_list [ + M.get_name (| globals, "message" |); + M.get_name (| globals, "env" |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + UnOp.not (| M.get_field (| M.get_name (| globals, "evm" |), "error" |) |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "contract_code" , + M.get_field (| M.get_name (| globals, "evm" |), "output" |) + |) in + let _ := M.assign_local (| + "contract_code_gas" , + BinOp.mult (| + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_name (| globals, "contract_code" |) + ], + make_dict [] + |), + M.get_name (| globals, "GAS_CODE_DEPOSIT" |) + |) + |) in +(* At stmt: unsupported node type: Try *) + let _ := M.call (| + M.get_name (| globals, "commit_transaction" |), + make_list [ + M.get_field (| M.get_name (| globals, "env" |), "state" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, "rollback_transaction" |), + make_list [ + M.get_field (| M.get_name (| globals, "env" |), "state" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + )) |) in + let _ := M.return_ (| + M.get_name (| globals, "evm" |) + |) in + M.pure Constant.None_)). + +Definition process_message : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "message"; "env" ] |) in + let _ := Constant.str " + Executes a call to create a smart contract. + + Parameters + ---------- + message : + Transaction specific items. + env : + External items required for EVM execution. + + Returns + ------- + evm: :py:class:`~ethereum.frontier.vm.Evm` + Items containing execution specific objects + " in + let _ := + (* if *) + M.if_then_else (| + Compare.gt (| + M.get_field (| M.get_name (| globals, "message" |), "depth" |), + M.get_name (| globals, "STACK_DEPTH_LIMIT" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.call (| + M.get_name (| globals, "StackDepthLimitError" |), + make_list [ + Constant.str "Stack depth limit reached" + ], + make_dict [] + |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.call (| + M.get_name (| globals, "begin_transaction" |), + make_list [ + M.get_field (| M.get_name (| globals, "env" |), "state" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "touch_account" |), + make_list [ + M.get_field (| M.get_name (| globals, "env" |), "state" |); + M.get_field (| M.get_name (| globals, "message" |), "current_target" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.not_eq (| + M.get_field (| M.get_name (| globals, "message" |), "value" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, "move_ether" |), + make_list [ + M.get_field (| M.get_name (| globals, "env" |), "state" |); + M.get_field (| M.get_name (| globals, "message" |), "caller" |); + M.get_field (| M.get_name (| globals, "message" |), "current_target" |); + M.get_field (| M.get_name (| globals, "message" |), "value" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "evm" , + M.call (| + M.get_name (| globals, "execute_code" |), + make_list [ + M.get_name (| globals, "message" |); + M.get_name (| globals, "env" |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + M.get_field (| M.get_name (| globals, "evm" |), "error" |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, "rollback_transaction" |), + make_list [ + M.get_field (| M.get_name (| globals, "env" |), "state" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, "commit_transaction" |), + make_list [ + M.get_field (| M.get_name (| globals, "env" |), "state" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + )) |) in + let _ := M.return_ (| + M.get_name (| globals, "evm" |) + |) in + M.pure Constant.None_)). + +Definition execute_code : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "message"; "env" ] |) in + let _ := Constant.str " + Executes bytecode present in the `message`. + + Parameters + ---------- + message : + Transaction specific items. + env : + External items required for EVM execution. + + Returns + ------- + evm: `ethereum.vm.EVM` + Items containing execution specific objects + " in + let _ := M.assign_local (| + "code" , + M.get_field (| M.get_name (| globals, "message" |), "code" |) + |) in + let _ := M.assign_local (| + "valid_jump_destinations" , + M.call (| + M.get_name (| globals, "get_valid_jump_destinations" |), + make_list [ + M.get_name (| globals, "code" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "evm" , + M.call (| + M.get_name (| globals, "Evm" |), + make_list [], + make_dict [] + |) + |) in +(* At stmt: unsupported node type: Try *) + let _ := M.return_ (| + M.get_name (| globals, "evm" |) + |) in + M.pure Constant.None_)). diff --git a/CoqOfPython/ethereum/frontier/vm/memory.v b/CoqOfPython/ethereum/frontier/vm/memory.v new file mode 100644 index 0000000..be21aab --- /dev/null +++ b/CoqOfPython/ethereum/frontier/vm/memory.v @@ -0,0 +1,166 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.frontier.vm.memory". + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) Memory +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +EVM memory operations. +". + +Axiom ethereum_utils_byte_imports_right_pad_zero_bytes : + IsImported globals "ethereum.utils.byte" "right_pad_zero_bytes". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_Bytes : + IsImported globals "ethereum.base_types" "Bytes". +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". + +Definition memory_write : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "memory"; "start_position"; "value" ] |) in + let _ := Constant.str " + Writes to memory. + + Parameters + ---------- + memory : + Memory contents of the EVM. + start_position : + Starting pointer to the memory. + value : + Data to write to memory. + " in + let _ := M.assign (| + M.slice (| + M.get_name (| globals, "memory" |), + M.get_name (| globals, "start_position" |), + BinOp.add (| + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.get_name (| globals, "start_position" |) + ], + make_dict [] + |), + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_name (| globals, "value" |) + ], + make_dict [] + |) + |), + Constant.None_ + |), + M.get_name (| globals, "value" |) + |) in + M.pure Constant.None_)). + +Definition memory_read_bytes : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "memory"; "start_position"; "size" ] |) in + let _ := Constant.str " + Read bytes from memory. + + Parameters + ---------- + memory : + Memory contents of the EVM. + start_position : + Starting pointer to the memory. + size : + Size of the data that needs to be read from `start_position`. + + Returns + ------- + data_bytes : + Data read from memory. + " in + let _ := M.return_ (| + M.slice (| + M.get_name (| globals, "memory" |), + M.get_name (| globals, "start_position" |), + BinOp.add (| + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.get_name (| globals, "start_position" |) + ], + make_dict [] + |), + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.get_name (| globals, "size" |) + ], + make_dict [] + |) + |), + Constant.None_ + |) + |) in + M.pure Constant.None_)). + +Definition buffer_read : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "buffer"; "start_position"; "size" ] |) in + let _ := Constant.str " + Read bytes from a buffer. Padding with zeros if necessary. + + Parameters + ---------- + buffer : + Memory contents of the EVM. + start_position : + Starting pointer to the memory. + size : + Size of the data that needs to be read from `start_position`. + + Returns + ------- + data_bytes : + Data read from memory. + " in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, "right_pad_zero_bytes" |), + make_list [ + M.slice (| + M.get_name (| globals, "buffer" |), + M.get_name (| globals, "start_position" |), + BinOp.add (| + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.get_name (| globals, "start_position" |) + ], + make_dict [] + |), + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.get_name (| globals, "size" |) + ], + make_dict [] + |) + |), + Constant.None_ + |); + M.get_name (| globals, "size" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). diff --git a/CoqOfPython/ethereum/frontier/vm/precompiled_contracts/__init__.v b/CoqOfPython/ethereum/frontier/vm/precompiled_contracts/__init__.v new file mode 100644 index 0000000..34b3b7b --- /dev/null +++ b/CoqOfPython/ethereum/frontier/vm/precompiled_contracts/__init__.v @@ -0,0 +1,66 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.frontier.vm.precompiled_contracts.__init__". + +Definition expr_1 : Value.t := + Constant.str " +Precompiled Contract Addresses +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Addresses of precompiled contracts and mappings to their +implementations. +". + +Axiom ethereum_frontier_utils_hexadecimal_imports_hex_to_address : + IsImported globals "ethereum.frontier.utils.hexadecimal" "hex_to_address". + +Definition __all__ : Value.t := M.run ltac:(M.monadic ( + make_tuple [ Constant.str "ECRECOVER_ADDRESS"; Constant.str "SHA256_ADDRESS"; Constant.str "RIPEMD160_ADDRESS"; Constant.str "IDENTITY_ADDRESS" ] +)). + +Definition ECRECOVER_ADDRESS : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "hex_to_address" |), + make_list [ + Constant.str "0x01" + ], + make_dict [] + |) +)). + +Definition SHA256_ADDRESS : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "hex_to_address" |), + make_list [ + Constant.str "0x02" + ], + make_dict [] + |) +)). + +Definition RIPEMD160_ADDRESS : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "hex_to_address" |), + make_list [ + Constant.str "0x03" + ], + make_dict [] + |) +)). + +Definition IDENTITY_ADDRESS : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "hex_to_address" |), + make_list [ + Constant.str "0x04" + ], + make_dict [] + |) +)). diff --git a/CoqOfPython/ethereum/frontier/vm/precompiled_contracts/ecrecover.v b/CoqOfPython/ethereum/frontier/vm/precompiled_contracts/ecrecover.v new file mode 100644 index 0000000..6f8de26 --- /dev/null +++ b/CoqOfPython/ethereum/frontier/vm/precompiled_contracts/ecrecover.v @@ -0,0 +1,301 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.frontier.vm.precompiled_contracts.ecrecover". + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) ECRECOVER PRECOMPILED CONTRACT +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementation of the ECRECOVER precompiled contract. +". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". + +Axiom ethereum_crypto_elliptic_curve_imports_SECP256K1N : + IsImported globals "ethereum.crypto.elliptic_curve" "SECP256K1N". +Axiom ethereum_crypto_elliptic_curve_imports_secp256k1_recover : + IsImported globals "ethereum.crypto.elliptic_curve" "secp256k1_recover". + +Axiom ethereum_crypto_hash_imports_Hash32 : + IsImported globals "ethereum.crypto.hash" "Hash32". +Axiom ethereum_crypto_hash_imports_keccak256 : + IsImported globals "ethereum.crypto.hash" "keccak256". + +Axiom ethereum_utils_byte_imports_left_pad_zero_bytes : + IsImported globals "ethereum.utils.byte" "left_pad_zero_bytes". + +Axiom ethereum_frontier_vm_imports_Evm : + IsImported globals "ethereum.frontier.vm" "Evm". + +Axiom ethereum_frontier_vm_gas_imports_GAS_ECRECOVER : + IsImported globals "ethereum.frontier.vm.gas" "GAS_ECRECOVER". +Axiom ethereum_frontier_vm_gas_imports_charge_gas : + IsImported globals "ethereum.frontier.vm.gas" "charge_gas". + +Axiom ethereum_frontier_vm_memory_imports_buffer_read : + IsImported globals "ethereum.frontier.vm.memory" "buffer_read". + +Definition ecrecover : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Decrypts the address using elliptic curve DSA recovery mechanism and writes + the address to output. + + Parameters + ---------- + evm : + The current EVM frame. + " in + let _ := M.assign_local (| + "data" , + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "data" |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_ECRECOVER" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "message_hash_bytes" , + M.call (| + M.get_name (| globals, "buffer_read" |), + make_list [ + M.get_name (| globals, "data" |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 32 + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "message_hash" , + M.call (| + M.get_name (| globals, "Hash32" |), + make_list [ + M.get_name (| globals, "message_hash_bytes" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "v" , + M.call (| + M.get_field (| M.get_name (| globals, "U256" |), "from_be_bytes" |), + make_list [ + M.call (| + M.get_name (| globals, "buffer_read" |), + make_list [ + M.get_name (| globals, "data" |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 32 + ], + make_dict [] + |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 32 + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "r" , + M.call (| + M.get_field (| M.get_name (| globals, "U256" |), "from_be_bytes" |), + make_list [ + M.call (| + M.get_name (| globals, "buffer_read" |), + make_list [ + M.get_name (| globals, "data" |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 64 + ], + make_dict [] + |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 32 + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "s" , + M.call (| + M.get_field (| M.get_name (| globals, "U256" |), "from_be_bytes" |), + make_list [ + M.call (| + M.get_name (| globals, "buffer_read" |), + make_list [ + M.get_name (| globals, "data" |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 96 + ], + make_dict [] + |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 32 + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + BoolOp.and (| + Compare.not_eq (| + M.get_name (| globals, "v" |), + Constant.int 27 + |), + ltac:(M.monadic ( + Compare.not_eq (| + M.get_name (| globals, "v" |), + Constant.int 28 + |) + )) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + Constant.None_ + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + BoolOp.or (| + Compare.gt_e (| + Constant.int 0, + M.get_name (| globals, "r" |) + |), + ltac:(M.monadic ( + Compare.gt_e (| + M.get_name (| globals, "r" |), + M.get_name (| globals, "SECP256K1N" |) + |) + )) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + Constant.None_ + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + BoolOp.or (| + Compare.gt_e (| + Constant.int 0, + M.get_name (| globals, "s" |) + |), + ltac:(M.monadic ( + Compare.gt_e (| + M.get_name (| globals, "s" |), + M.get_name (| globals, "SECP256K1N" |) + |) + )) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + Constant.None_ + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in +(* At stmt: unsupported node type: Try *) + let _ := M.assign_local (| + "address" , + M.slice (| + M.call (| + M.get_name (| globals, "keccak256" |), + make_list [ + M.get_name (| globals, "public_key" |) + ], + make_dict [] + |), + Constant.int 12, + Constant.int 32, + Constant.None_ + |) + |) in + let _ := M.assign_local (| + "padded_address" , + M.call (| + M.get_name (| globals, "left_pad_zero_bytes" |), + make_list [ + M.get_name (| globals, "address" |); + Constant.int 32 + ], + make_dict [] + |) + |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, "evm" |), "output" |), + M.get_name (| globals, "padded_address" |) + |) in + M.pure Constant.None_)). diff --git a/CoqOfPython/ethereum/frontier/vm/precompiled_contracts/identity.v b/CoqOfPython/ethereum/frontier/vm/precompiled_contracts/identity.v new file mode 100644 index 0000000..ff7bb79 --- /dev/null +++ b/CoqOfPython/ethereum/frontier/vm/precompiled_contracts/identity.v @@ -0,0 +1,94 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.frontier.vm.precompiled_contracts.identity". + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) IDENTITY PRECOMPILED CONTRACT +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementation of the `IDENTITY` precompiled contract. +". + +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". + +Axiom ethereum_utils_numeric_imports_ceil32 : + IsImported globals "ethereum.utils.numeric" "ceil32". + +Axiom ethereum_frontier_vm_imports_Evm : + IsImported globals "ethereum.frontier.vm" "Evm". + +Axiom ethereum_frontier_vm_gas_imports_GAS_IDENTITY : + IsImported globals "ethereum.frontier.vm.gas" "GAS_IDENTITY". +Axiom ethereum_frontier_vm_gas_imports_GAS_IDENTITY_WORD : + IsImported globals "ethereum.frontier.vm.gas" "GAS_IDENTITY_WORD". +Axiom ethereum_frontier_vm_gas_imports_charge_gas : + IsImported globals "ethereum.frontier.vm.gas" "charge_gas". + +Definition identity : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Writes the message data to output. + + Parameters + ---------- + evm : + The current EVM frame. + " in + let _ := M.assign_local (| + "data" , + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "data" |) + |) in + let _ := M.assign_local (| + "word_count" , + BinOp.floor_div (| + M.call (| + M.get_name (| globals, "ceil32" |), + make_list [ + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_name (| globals, "data" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |), + Constant.int 32 + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + BinOp.add (| + M.get_name (| globals, "GAS_IDENTITY" |), + BinOp.mult (| + M.get_name (| globals, "GAS_IDENTITY_WORD" |), + M.get_name (| globals, "word_count" |) + |) + |) + ], + make_dict [] + |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, "evm" |), "output" |), + M.get_name (| globals, "data" |) + |) in + M.pure Constant.None_)). diff --git a/CoqOfPython/ethereum/frontier/vm/precompiled_contracts/mapping.v b/CoqOfPython/ethereum/frontier/vm/precompiled_contracts/mapping.v new file mode 100644 index 0000000..f2f606e --- /dev/null +++ b/CoqOfPython/ethereum/frontier/vm/precompiled_contracts/mapping.v @@ -0,0 +1,49 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.frontier.vm.precompiled_contracts.mapping". + +Definition expr_1 : Value.t := + Constant.str " +Precompiled Contract Addresses +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Mapping of precompiled contracts their implementations. +". + +Axiom typing_imports_Callable : + IsImported globals "typing" "Callable". +Axiom typing_imports_Dict : + IsImported globals "typing" "Dict". + +Axiom ethereum_frontier_fork_types_imports_Address : + IsImported globals "ethereum.frontier.fork_types" "Address". + +Axiom ethereum_frontier_vm_precompiled_contracts_imports_ECRECOVER_ADDRESS : + IsImported globals "ethereum.frontier.vm.precompiled_contracts" "ECRECOVER_ADDRESS". +Axiom ethereum_frontier_vm_precompiled_contracts_imports_IDENTITY_ADDRESS : + IsImported globals "ethereum.frontier.vm.precompiled_contracts" "IDENTITY_ADDRESS". +Axiom ethereum_frontier_vm_precompiled_contracts_imports_RIPEMD160_ADDRESS : + IsImported globals "ethereum.frontier.vm.precompiled_contracts" "RIPEMD160_ADDRESS". +Axiom ethereum_frontier_vm_precompiled_contracts_imports_SHA256_ADDRESS : + IsImported globals "ethereum.frontier.vm.precompiled_contracts" "SHA256_ADDRESS". + +Axiom ethereum_frontier_vm_precompiled_contracts_ecrecover_imports_ecrecover : + IsImported globals "ethereum.frontier.vm.precompiled_contracts.ecrecover" "ecrecover". + +Axiom ethereum_frontier_vm_precompiled_contracts_identity_imports_identity : + IsImported globals "ethereum.frontier.vm.precompiled_contracts.identity" "identity". + +Axiom ethereum_frontier_vm_precompiled_contracts_ripemd160_imports_ripemd160 : + IsImported globals "ethereum.frontier.vm.precompiled_contracts.ripemd160" "ripemd160". + +Axiom ethereum_frontier_vm_precompiled_contracts_sha256_imports_sha256 : + IsImported globals "ethereum.frontier.vm.precompiled_contracts.sha256" "sha256". + +(* At top_level_stmt: unsupported node type: AnnAssign *) diff --git a/CoqOfPython/ethereum/frontier/vm/precompiled_contracts/ripemd160.v b/CoqOfPython/ethereum/frontier/vm/precompiled_contracts/ripemd160.v new file mode 100644 index 0000000..3f3bbd6 --- /dev/null +++ b/CoqOfPython/ethereum/frontier/vm/precompiled_contracts/ripemd160.v @@ -0,0 +1,125 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.frontier.vm.precompiled_contracts.ripemd160". + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) RIPEMD160 PRECOMPILED CONTRACT +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementation of the `RIPEMD160` precompiled contract. +". + +(* At top_level_stmt: unsupported node type: Import *) + +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". + +Axiom ethereum_utils_byte_imports_left_pad_zero_bytes : + IsImported globals "ethereum.utils.byte" "left_pad_zero_bytes". + +Axiom ethereum_utils_numeric_imports_ceil32 : + IsImported globals "ethereum.utils.numeric" "ceil32". + +Axiom ethereum_frontier_vm_imports_Evm : + IsImported globals "ethereum.frontier.vm" "Evm". + +Axiom ethereum_frontier_vm_gas_imports_GAS_RIPEMD160 : + IsImported globals "ethereum.frontier.vm.gas" "GAS_RIPEMD160". +Axiom ethereum_frontier_vm_gas_imports_GAS_RIPEMD160_WORD : + IsImported globals "ethereum.frontier.vm.gas" "GAS_RIPEMD160_WORD". +Axiom ethereum_frontier_vm_gas_imports_charge_gas : + IsImported globals "ethereum.frontier.vm.gas" "charge_gas". + +Definition ripemd160 : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Writes the ripemd160 hash to output. + + Parameters + ---------- + evm : + The current EVM frame. + " in + let _ := M.assign_local (| + "data" , + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "data" |) + |) in + let _ := M.assign_local (| + "word_count" , + BinOp.floor_div (| + M.call (| + M.get_name (| globals, "ceil32" |), + make_list [ + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_name (| globals, "data" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |), + Constant.int 32 + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + BinOp.add (| + M.get_name (| globals, "GAS_RIPEMD160" |), + BinOp.mult (| + M.get_name (| globals, "GAS_RIPEMD160_WORD" |), + M.get_name (| globals, "word_count" |) + |) + |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "hash_bytes" , + M.call (| + M.get_field (| M.call (| + M.get_field (| M.get_name (| globals, "hashlib" |), "new" |), + make_list [ + Constant.str "ripemd160"; + M.get_name (| globals, "data" |) + ], + make_dict [] + |), "digest" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "padded_hash" , + M.call (| + M.get_name (| globals, "left_pad_zero_bytes" |), + make_list [ + M.get_name (| globals, "hash_bytes" |); + Constant.int 32 + ], + make_dict [] + |) + |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, "evm" |), "output" |), + M.get_name (| globals, "padded_hash" |) + |) in + M.pure Constant.None_)). diff --git a/CoqOfPython/ethereum/frontier/vm/precompiled_contracts/sha256.v b/CoqOfPython/ethereum/frontier/vm/precompiled_contracts/sha256.v new file mode 100644 index 0000000..e72a688 --- /dev/null +++ b/CoqOfPython/ethereum/frontier/vm/precompiled_contracts/sha256.v @@ -0,0 +1,106 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.frontier.vm.precompiled_contracts.sha256". + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) SHA256 PRECOMPILED CONTRACT +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementation of the `SHA256` precompiled contract. +". + +(* At top_level_stmt: unsupported node type: Import *) + +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". + +Axiom ethereum_utils_numeric_imports_ceil32 : + IsImported globals "ethereum.utils.numeric" "ceil32". + +Axiom ethereum_frontier_vm_imports_Evm : + IsImported globals "ethereum.frontier.vm" "Evm". + +Axiom ethereum_frontier_vm_gas_imports_GAS_SHA256 : + IsImported globals "ethereum.frontier.vm.gas" "GAS_SHA256". +Axiom ethereum_frontier_vm_gas_imports_GAS_SHA256_WORD : + IsImported globals "ethereum.frontier.vm.gas" "GAS_SHA256_WORD". +Axiom ethereum_frontier_vm_gas_imports_charge_gas : + IsImported globals "ethereum.frontier.vm.gas" "charge_gas". + +Definition sha256 : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Writes the sha256 hash to output. + + Parameters + ---------- + evm : + The current EVM frame. + " in + let _ := M.assign_local (| + "data" , + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "data" |) + |) in + let _ := M.assign_local (| + "word_count" , + BinOp.floor_div (| + M.call (| + M.get_name (| globals, "ceil32" |), + make_list [ + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_name (| globals, "data" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |), + Constant.int 32 + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + BinOp.add (| + M.get_name (| globals, "GAS_SHA256" |), + BinOp.mult (| + M.get_name (| globals, "GAS_SHA256_WORD" |), + M.get_name (| globals, "word_count" |) + |) + |) + ], + make_dict [] + |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, "evm" |), "output" |), + M.call (| + M.get_field (| M.call (| + M.get_field (| M.get_name (| globals, "hashlib" |), "sha256" |), + make_list [ + M.get_name (| globals, "data" |) + ], + make_dict [] + |), "digest" |), + make_list [], + make_dict [] + |) + |) in + M.pure Constant.None_)). diff --git a/CoqOfPython/ethereum/frontier/vm/runtime.v b/CoqOfPython/ethereum/frontier/vm/runtime.v new file mode 100644 index 0000000..316e3e2 --- /dev/null +++ b/CoqOfPython/ethereum/frontier/vm/runtime.v @@ -0,0 +1,157 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.frontier.vm.runtime". + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) Runtime Operations +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Runtime related operations used while executing EVM code. +". + +Axiom typing_imports_Set : + IsImported globals "typing" "Set". + +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". + +Axiom ethereum_frontier_vm_instructions_imports_Ops : + IsImported globals "ethereum.frontier.vm.instructions" "Ops". + +Definition get_valid_jump_destinations : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "code" ] |) in + let _ := Constant.str " + Analyze the evm code to obtain the set of valid jump destinations. + + Valid jump destinations are defined as follows: + * The jump destination is less than the length of the code. + * The jump destination should have the `JUMPDEST` opcode (0x5B). + * The jump destination shouldn't be part of the data corresponding to + `PUSH-N` opcodes. + + Note - Jump destinations are 0-indexed. + + Parameters + ---------- + code : + The EVM code which is to be executed. + + Returns + ------- + valid_jump_destinations: `Set[Uint]` + The set of valid jump destinations in the code. + " in + let _ := M.assign_local (| + "valid_jump_destinations" , + M.call (| + M.get_name (| globals, "set" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "pc" , + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + |) in + let _ := + M.while (| + Compare.lt (| + M.get_name (| globals, "pc" |), + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_name (| globals, "code" |) + ], + make_dict [] + |) + |), + ltac:(M.monadic ( +(* At stmt: unsupported node type: Try *) + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, "current_opcode" |), + M.get_field (| M.get_name (| globals, "Ops" |), "JUMPDEST" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_field (| M.get_name (| globals, "valid_jump_destinations" |), "add" |), + make_list [ + M.get_name (| globals, "pc" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + BoolOp.and (| + Compare.lt_e (| + M.get_field (| M.get_field (| M.get_name (| globals, "Ops" |), "PUSH1" |), "value" |), + M.get_field (| M.get_name (| globals, "current_opcode" |), "value" |) + |), + ltac:(M.monadic ( + Compare.lt_e (| + M.get_field (| M.get_name (| globals, "current_opcode" |), "value" |), + M.get_field (| M.get_field (| M.get_name (| globals, "Ops" |), "PUSH32" |), "value" |) + |) + )) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "push_data_size" , + BinOp.add (| + BinOp.sub (| + M.get_field (| M.get_name (| globals, "current_opcode" |), "value" |), + M.get_field (| M.get_field (| M.get_name (| globals, "Ops" |), "PUSH1" |), "value" |) + |), + Constant.int 1 + |) + |) in + let _ := M.assign_op_local (| + BinOp.add, + "pc", + M.get_name (| globals, "push_data_size" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )) |) in + let _ := M.assign_op_local (| + BinOp.add, + "pc", + Constant.int 1 + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := M.return_ (| + M.get_name (| globals, "valid_jump_destinations" |) + |) in + M.pure Constant.None_)). diff --git a/CoqOfPython/ethereum/frontier/vm/stack.v b/CoqOfPython/ethereum/frontier/vm/stack.v new file mode 100644 index 0000000..875e1e7 --- /dev/null +++ b/CoqOfPython/ethereum/frontier/vm/stack.v @@ -0,0 +1,123 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.frontier.vm.stack". + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) Stack +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementation of the stack operators for the EVM. +". + +Axiom typing_imports_List : + IsImported globals "typing" "List". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". + +Axiom ethereum_frontier_vm_exceptions_imports_StackOverflowError : + IsImported globals "ethereum.frontier.vm.exceptions" "StackOverflowError". +Axiom ethereum_frontier_vm_exceptions_imports_StackUnderflowError : + IsImported globals "ethereum.frontier.vm.exceptions" "StackUnderflowError". + +Definition pop : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "stack" ] |) in + let _ := Constant.str " + Pops the top item off of `stack`. + + Parameters + ---------- + stack : + EVM stack. + + Returns + ------- + value : `U256` + The top element on the stack. + + " in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_name (| globals, "stack" |) + ], + make_dict [] + |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, "StackUnderflowError" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.return_ (| + M.call (| + M.get_field (| M.get_name (| globals, "stack" |), "pop" |), + make_list [], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Definition push : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "stack"; "value" ] |) in + let _ := Constant.str " + Pushes `value` onto `stack`. + + Parameters + ---------- + stack : + EVM stack. + + value : + Item to be pushed onto `stack`. + + " in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_name (| globals, "stack" |) + ], + make_dict [] + |), + Constant.int 1024 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, "StackOverflowError" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.return_ (| + M.call (| + M.get_field (| M.get_name (| globals, "stack" |), "append" |), + make_list [ + M.get_name (| globals, "value" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). diff --git a/CoqOfPython/ethereum/genesis.v b/CoqOfPython/ethereum/genesis.v new file mode 100644 index 0000000..cd70564 --- /dev/null +++ b/CoqOfPython/ethereum/genesis.v @@ -0,0 +1,481 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.genesis". + +Definition expr_1 : Value.t := + Constant.str " +Genesis Configuration +^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Functionalities and entities to obtain the genesis configurations for +different chains. +". + +(* At top_level_stmt: unsupported node type: Import *) + +(* At top_level_stmt: unsupported node type: Import *) + +Axiom dataclasses_imports_dataclass : + IsImported globals "dataclasses" "dataclass". + +Axiom typing_imports_Any : + IsImported globals "typing" "Any". +Axiom typing_imports_Dict : + IsImported globals "typing" "Dict". +Axiom typing_imports_cast : + IsImported globals "typing" "cast". + +Axiom ethereum_imports_rlp : + IsImported globals "ethereum" "rlp". + +Axiom ethereum_base_types_imports_U64 : + IsImported globals "ethereum.base_types" "U64". +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_Bytes : + IsImported globals "ethereum.base_types" "Bytes". +Axiom ethereum_base_types_imports_Bytes8 : + IsImported globals "ethereum.base_types" "Bytes8". +Axiom ethereum_base_types_imports_Bytes20 : + IsImported globals "ethereum.base_types" "Bytes20". +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". +Axiom ethereum_base_types_imports_slotted_freezable : + IsImported globals "ethereum.base_types" "slotted_freezable". + +Axiom ethereum_utils_hexadecimal_imports_hex_to_bytes : + IsImported globals "ethereum.utils.hexadecimal" "hex_to_bytes". +Axiom ethereum_utils_hexadecimal_imports_hex_to_bytes8 : + IsImported globals "ethereum.utils.hexadecimal" "hex_to_bytes8". +Axiom ethereum_utils_hexadecimal_imports_hex_to_bytes32 : + IsImported globals "ethereum.utils.hexadecimal" "hex_to_bytes32". +Axiom ethereum_utils_hexadecimal_imports_hex_to_u256 : + IsImported globals "ethereum.utils.hexadecimal" "hex_to_u256". +Axiom ethereum_utils_hexadecimal_imports_hex_to_uint : + IsImported globals "ethereum.utils.hexadecimal" "hex_to_uint". + +Definition Address : Value.t := M.run ltac:(M.monadic ( + M.get_name (| globals, "Bytes20" |) +)). + +Definition GenesisConfiguration : Value.t := + builtins.make_klass + [] + [ + + ] + [ + + ]. + +Definition get_genesis_configuration : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "genesis_file" ] |) in + let _ := Constant.str " + Obtain the genesis configuration from the given genesis json file. + + The genesis file should be present in the `assets` directory. + + Parameters + ---------- + genesis_file : + The json file which contains the parameters for the genesis block + and the pre-sale allocation data. + + Returns + ------- + configuration : `GenesisConfiguration` + The genesis configuration obtained from the json genesis file. + " in + let _ := M.assign_local (| + "genesis_str_data" , + M.call (| + M.get_field (| M.call (| + M.get_name (| globals, "cast" |), + make_list [ + M.get_name (| globals, "bytes" |); + M.call (| + M.get_field (| M.get_name (| globals, "pkgutil" |), "get_data" |), + make_list [ + Constant.str "ethereum"; + Constant.str "(* At expr: unsupported node type: JoinedStr *)" + ], + make_dict [] + |) + ], + make_dict [] + |), "decode" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "genesis_data" , + M.call (| + M.get_field (| M.get_name (| globals, "json" |), "loads" |), + make_list [ + M.get_name (| globals, "genesis_str_data" |) + ], + make_dict [] + |) + |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, "GenesisConfiguration" |), + make_list [], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Definition hex_or_base_10_str_to_u256 : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "balance" ] |) in + let _ := Constant.str " + The genesis format can have balances and timestamps as either base 10 + numbers or 0x prefixed hex. This function supports both. + " in + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_field (| M.get_name (| globals, "balance" |), "startswith" |), + make_list [ + Constant.str "0x" + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + M.call (| + M.get_name (| globals, "hex_to_u256" |), + make_list [ + M.get_name (| globals, "balance" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.return_ (| + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + M.call (| + M.get_name (| globals, "int" |), + make_list [ + M.get_name (| globals, "balance" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_)). + +Definition add_genesis_block : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "hardfork"; "chain"; "genesis" ] |) in + let _ := Constant.str " + Adds the genesis block to an empty blockchain. + + The genesis block is an entirely sui generis block (unique) that is not + governed by the general rules applying to all other Ethereum blocks. + Instead, the only consensus requirement is that it must be identical to + the block added by this function. + + The mainnet genesis configuration was originally created using the + `mk_genesis_block.py` script. It is long since defunct, but is still + available at https://github.com/ethereum/genesis_block_generator. + + The initial state is populated with balances based on the Ethereum presale + that happened on the Bitcoin blockchain. Additional Ether worth 1.98% of + the presale was given to the foundation. + + The `state_root` is set to the root of the initial state. The `gas_limit` + and `difficulty` are set to suitable starting values. In particular the + low gas limit made sending transactions impossible in the early stages of + Frontier. + + The `nonce` field is `0x42` referencing Douglas Adams' ""HitchHiker's Guide + to the Galaxy"". + + The `extra_data` field contains the hash of block `1028201` on + the pre-launch Olympus testnet. The creation of block `1028201` on Olympus + marked the ""starting gun"" for Ethereum block creation. Including its hash + in the genesis block ensured a fair launch of the Ethereum mining process. + + The remaining fields are set to appropriate default values. + + On testnets the genesis configuration usually allocates 1 wei to addresses + `0x00` to `0xFF` to avoid edgecases around precompiles being created or + cleared (by EIP 161). + + Parameters + ---------- + hardfork: + The module containing the initial hardfork + chain : + An empty `Blockchain` object. + genesis : + The genesis configuration to use. + " in + let _ := + M.for_ (| + make_tuple [ M.get_name (| globals, "address" |); M.get_name (| globals, "account" |) ], + M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, "genesis" |), "initial_accounts" |), "items" |), + make_list [], + make_dict [] + |), + ltac:(M.monadic ( + let _ := M.assign_local (| + "address" , + M.call (| + M.get_field (| M.get_field (| M.get_field (| M.get_name (| globals, "hardfork" |), "utils" |), "hexadecimal" |), "hex_to_address" |), + make_list [ + M.get_name (| globals, "address" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, "hardfork" |), "state" |), "set_account" |), + make_list [ + M.get_field (| M.get_name (| globals, "chain" |), "state" |); + M.get_name (| globals, "address" |); + M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, "hardfork" |), "fork_types" |), "Account" |), + make_list [ + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, "int" |), + make_list [ + M.call (| + M.get_field (| M.get_name (| globals, "account" |), "get" |), + make_list [ + Constant.str "nonce"; + Constant.str "0" + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |); + M.call (| + M.get_name (| globals, "hex_or_base_10_str_to_u256" |), + make_list [ + M.call (| + M.get_field (| M.get_name (| globals, "account" |), "get" |), + make_list [ + Constant.str "balance"; + Constant.int 0 + ], + make_dict [] + |) + ], + make_dict [] + |); + M.call (| + M.get_name (| globals, "hex_to_bytes" |), + make_list [ + M.call (| + M.get_field (| M.get_name (| globals, "account" |), "get" |), + make_list [ + Constant.str "code"; + Constant.str "0x" + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := + M.for_ (| + make_tuple [ M.get_name (| globals, "key" |); M.get_name (| globals, "value" |) ], + M.call (| + M.get_field (| M.call (| + M.get_field (| M.get_name (| globals, "account" |), "get" |), + make_list [ + Constant.str "storage"; + Constant.str "(* At expr: unsupported node type: Dict *)" + ], + make_dict [] + |), "items" |), + make_list [], + make_dict [] + |), + ltac:(M.monadic ( + let _ := M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, "hardfork" |), "state" |), "set_storage" |), + make_list [ + M.get_field (| M.get_name (| globals, "chain" |), "state" |); + M.get_name (| globals, "address" |); + M.call (| + M.get_name (| globals, "hex_to_bytes32" |), + make_list [ + M.get_name (| globals, "key" |) + ], + make_dict [] + |); + M.call (| + M.get_name (| globals, "hex_to_uint" |), + make_list [ + M.get_name (| globals, "value" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := M.assign_local (| + "fields" , + Constant.str "(* At expr: unsupported node type: Dict *)" + |) in + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, "hasattr" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "hardfork" |), "blocks" |), "Header" |); + Constant.str "mix_digest" + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign (| + M.get_subscript (| + M.get_name (| globals, "fields" |), + Constant.str "mix_digest" + |), + M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, "hardfork" |), "fork_types" |), "Hash32" |), + make_list [ + BinOp.mult (| + Constant.bytes "00", + Constant.int 32 + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign (| + M.get_subscript (| + M.get_name (| globals, "fields" |), + Constant.str "prev_randao" + |), + M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, "hardfork" |), "fork_types" |), "Hash32" |), + make_list [ + BinOp.mult (| + Constant.bytes "00", + Constant.int 32 + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, "hasattr" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "hardfork" |), "blocks" |), "Header" |); + Constant.str "base_fee_per_gas" + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign (| + M.get_subscript (| + M.get_name (| globals, "fields" |), + Constant.str "base_fee_per_gas" + |), + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + BinOp.pow (| + Constant.int 10, + Constant.int 9 + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "genesis_header" , + M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, "hardfork" |), "blocks" |), "Header" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "genesis_block" , + M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, "hardfork" |), "blocks" |), "Block" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, "chain" |), "blocks" |), "append" |), + make_list [ + M.get_name (| globals, "genesis_block" |) + ], + make_dict [] + |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, "chain" |), "chain_id" |), + M.get_field (| M.get_name (| globals, "genesis" |), "chain_id" |) + |) in + M.pure Constant.None_)). diff --git a/CoqOfPython/ethereum/gray_glacier/__init__.v b/CoqOfPython/ethereum/gray_glacier/__init__.v new file mode 100644 index 0000000..214f63d --- /dev/null +++ b/CoqOfPython/ethereum/gray_glacier/__init__.v @@ -0,0 +1,22 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.gray_glacier.__init__". + +Definition expr_1 : Value.t := + Constant.str " +The Gray Glacier fork delays the difficulty bomb. There are no other changes +in this fork. +". + +Axiom ethereum_fork_criteria_imports_ByBlockNumber : + IsImported globals "ethereum.fork_criteria" "ByBlockNumber". + +Definition FORK_CRITERIA : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "ByBlockNumber" |), + make_list [ + Constant.int 15050000 + ], + make_dict [] + |) +)). diff --git a/CoqOfPython/ethereum/gray_glacier/blocks.v b/CoqOfPython/ethereum/gray_glacier/blocks.v new file mode 100644 index 0000000..04f7678 --- /dev/null +++ b/CoqOfPython/ethereum/gray_glacier/blocks.v @@ -0,0 +1,89 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.gray_glacier.blocks". + +Definition expr_1 : Value.t := + Constant.str " +A `Block` is a single link in the chain that is Ethereum. Each `Block` contains +a `Header` and zero or more transactions. Each `Header` contains associated +metadata like the block number, parent block hash, and how much gas was +consumed by its transactions. + +Together, these blocks form a cryptographically secure journal recording the +history of all state transitions that have happened since the genesis of the +chain. +". + +Axiom dataclasses_imports_dataclass : + IsImported globals "dataclasses" "dataclass". + +Axiom typing_imports_Tuple : + IsImported globals "typing" "Tuple". +Axiom typing_imports_Union : + IsImported globals "typing" "Union". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_Bytes : + IsImported globals "ethereum.base_types" "Bytes". +Axiom ethereum_base_types_imports_Bytes8 : + IsImported globals "ethereum.base_types" "Bytes8". +Axiom ethereum_base_types_imports_Bytes32 : + IsImported globals "ethereum.base_types" "Bytes32". +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". +Axiom ethereum_base_types_imports_slotted_freezable : + IsImported globals "ethereum.base_types" "slotted_freezable". + +Axiom ethereum_crypto_hash_imports_Hash32 : + IsImported globals "ethereum.crypto.hash" "Hash32". + +Axiom ethereum_gray_glacier_fork_types_imports_Address : + IsImported globals "ethereum.gray_glacier.fork_types" "Address". +Axiom ethereum_gray_glacier_fork_types_imports_Bloom : + IsImported globals "ethereum.gray_glacier.fork_types" "Bloom". +Axiom ethereum_gray_glacier_fork_types_imports_Root : + IsImported globals "ethereum.gray_glacier.fork_types" "Root". + +Axiom ethereum_gray_glacier_transactions_imports_LegacyTransaction : + IsImported globals "ethereum.gray_glacier.transactions" "LegacyTransaction". + +Definition Header : Value.t := + builtins.make_klass + [] + [ + + ] + [ + + ]. + +Definition Block : Value.t := + builtins.make_klass + [] + [ + + ] + [ + + ]. + +Definition Log : Value.t := + builtins.make_klass + [] + [ + + ] + [ + + ]. + +Definition Receipt : Value.t := + builtins.make_klass + [] + [ + + ] + [ + + ]. diff --git a/CoqOfPython/ethereum/gray_glacier/bloom.v b/CoqOfPython/ethereum/gray_glacier/bloom.v new file mode 100644 index 0000000..d2b450d --- /dev/null +++ b/CoqOfPython/ethereum/gray_glacier/bloom.v @@ -0,0 +1,207 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.gray_glacier.bloom". + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Logs Bloom +^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +This modules defines functions for calculating bloom filters of logs. For the +general theory of bloom filters see e.g. `Wikipedia +`_. Bloom filters are used to allow +for efficient searching of logs by address and/or topic, by rapidly +eliminating blocks and receipts from their search. +". + +Axiom typing_imports_Tuple : + IsImported globals "typing" "Tuple". + +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". + +Axiom ethereum_crypto_hash_imports_keccak256 : + IsImported globals "ethereum.crypto.hash" "keccak256". + +Axiom ethereum_gray_glacier_blocks_imports_Log : + IsImported globals "ethereum.gray_glacier.blocks" "Log". + +Axiom ethereum_gray_glacier_fork_types_imports_Bloom : + IsImported globals "ethereum.gray_glacier.fork_types" "Bloom". + +Definition add_to_bloom : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "bloom"; "bloom_entry" ] |) in + let _ := Constant.str " + Add a bloom entry to the bloom filter (`bloom`). + + The number of hash functions used is 3. They are calculated by taking the + least significant 11 bits from the first 3 16-bit words of the + `keccak_256()` hash of `bloom_entry`. + + Parameters + ---------- + bloom : + The bloom filter. + bloom_entry : + An entry which is to be added to bloom filter. + " in + let _ := M.assign_local (| + "hash" , + M.call (| + M.get_name (| globals, "keccak256" |), + make_list [ + M.get_name (| globals, "bloom_entry" |) + ], + make_dict [] + |) + |) in + let _ := + M.for_ (| + M.get_name (| globals, "idx" |), + make_tuple [ Constant.int 0; Constant.int 2; Constant.int 4 ], + ltac:(M.monadic ( + let _ := M.assign_local (| + "bit_to_set" , + BinOp.bit_and (| + M.call (| + M.get_field (| M.get_name (| globals, "Uint" |), "from_be_bytes" |), + make_list [ + M.slice (| + M.get_name (| globals, "hash" |), + M.get_name (| globals, "idx" |), + BinOp.add (| + M.get_name (| globals, "idx" |), + Constant.int 2 + |), + Constant.None_ + |) + ], + make_dict [] + |), + Constant.int 2047 + |) + |) in + let _ := M.assign_local (| + "bit_index" , + BinOp.sub (| + Constant.int 2047, + M.get_name (| globals, "bit_to_set" |) + |) + |) in + let _ := M.assign_local (| + "byte_index" , + BinOp.floor_div (| + M.get_name (| globals, "bit_index" |), + Constant.int 8 + |) + |) in + let _ := M.assign_local (| + "bit_value" , + BinOp.l_shift (| + Constant.int 1, + BinOp.sub (| + Constant.int 7, + BinOp.mod_ (| + M.get_name (| globals, "bit_index" |), + Constant.int 8 + |) + |) + |) + |) in + let _ := M.assign (| + M.get_subscript (| + M.get_name (| globals, "bloom" |), + M.get_name (| globals, "byte_index" |) + |), + BinOp.bit_or (| + M.get_subscript (| + M.get_name (| globals, "bloom" |), + M.get_name (| globals, "byte_index" |) + |), + M.get_name (| globals, "bit_value" |) + |) + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + M.pure Constant.None_)). + +Definition logs_bloom : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "logs" ] |) in + let _ := Constant.str " + Obtain the logs bloom from a list of log entries. + + The address and each topic of a log are added to the bloom filter. + + Parameters + ---------- + logs : + List of logs for which the logs bloom is to be obtained. + + Returns + ------- + logs_bloom : `Bloom` + The logs bloom obtained which is 256 bytes with some bits set as per + the caller address and the log topics. + " in +(* At stmt: unsupported node type: AnnAssign *) + let _ := + M.for_ (| + M.get_name (| globals, "log" |), + M.get_name (| globals, "logs" |), + ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, "add_to_bloom" |), + make_list [ + M.get_name (| globals, "bloom" |); + M.get_field (| M.get_name (| globals, "log" |), "address" |) + ], + make_dict [] + |) in + let _ := + M.for_ (| + M.get_name (| globals, "topic" |), + M.get_field (| M.get_name (| globals, "log" |), "topics" |), + ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, "add_to_bloom" |), + make_list [ + M.get_name (| globals, "bloom" |); + M.get_name (| globals, "topic" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, "Bloom" |), + make_list [ + M.get_name (| globals, "bloom" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). diff --git a/CoqOfPython/ethereum/gray_glacier/fork.v b/CoqOfPython/ethereum/gray_glacier/fork.v new file mode 100644 index 0000000..0bd20df --- /dev/null +++ b/CoqOfPython/ethereum/gray_glacier/fork.v @@ -0,0 +1,3353 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.gray_glacier.fork". + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Specification +^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Entry point for the Ethereum specification. +". + +Axiom dataclasses_imports_dataclass : + IsImported globals "dataclasses" "dataclass". + +Axiom typing_imports_List : + IsImported globals "typing" "List". +Axiom typing_imports_Optional : + IsImported globals "typing" "Optional". +Axiom typing_imports_Set : + IsImported globals "typing" "Set". +Axiom typing_imports_Tuple : + IsImported globals "typing" "Tuple". +Axiom typing_imports_Union : + IsImported globals "typing" "Union". + +Axiom ethereum_base_types_imports_Bytes0 : + IsImported globals "ethereum.base_types" "Bytes0". + +Axiom ethereum_crypto_elliptic_curve_imports_SECP256K1N : + IsImported globals "ethereum.crypto.elliptic_curve" "SECP256K1N". +Axiom ethereum_crypto_elliptic_curve_imports_secp256k1_recover : + IsImported globals "ethereum.crypto.elliptic_curve" "secp256k1_recover". + +Axiom ethereum_crypto_hash_imports_Hash32 : + IsImported globals "ethereum.crypto.hash" "Hash32". +Axiom ethereum_crypto_hash_imports_keccak256 : + IsImported globals "ethereum.crypto.hash" "keccak256". + +Axiom ethereum_ethash_imports_dataset_size : + IsImported globals "ethereum.ethash" "dataset_size". +Axiom ethereum_ethash_imports_generate_cache : + IsImported globals "ethereum.ethash" "generate_cache". +Axiom ethereum_ethash_imports_hashimoto_light : + IsImported globals "ethereum.ethash" "hashimoto_light". + +Axiom ethereum_exceptions_imports_InvalidBlock : + IsImported globals "ethereum.exceptions" "InvalidBlock". + +Axiom ethereum_utils_ensure_imports_ensure : + IsImported globals "ethereum.utils.ensure" "ensure". + +Axiom ethereum_imports_rlp : + IsImported globals "ethereum" "rlp". + +Axiom ethereum_base_types_imports_U64 : + IsImported globals "ethereum.base_types" "U64". +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_U256_CEIL_VALUE : + IsImported globals "ethereum.base_types" "U256_CEIL_VALUE". +Axiom ethereum_base_types_imports_Bytes : + IsImported globals "ethereum.base_types" "Bytes". +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". + +Axiom ethereum_gray_glacier_imports_vm : + IsImported globals "ethereum.gray_glacier" "vm". + +Axiom ethereum_gray_glacier_blocks_imports_Block : + IsImported globals "ethereum.gray_glacier.blocks" "Block". +Axiom ethereum_gray_glacier_blocks_imports_Header : + IsImported globals "ethereum.gray_glacier.blocks" "Header". +Axiom ethereum_gray_glacier_blocks_imports_Log : + IsImported globals "ethereum.gray_glacier.blocks" "Log". +Axiom ethereum_gray_glacier_blocks_imports_Receipt : + IsImported globals "ethereum.gray_glacier.blocks" "Receipt". + +Axiom ethereum_gray_glacier_bloom_imports_logs_bloom : + IsImported globals "ethereum.gray_glacier.bloom" "logs_bloom". + +Axiom ethereum_gray_glacier_fork_types_imports_Address : + IsImported globals "ethereum.gray_glacier.fork_types" "Address". +Axiom ethereum_gray_glacier_fork_types_imports_Bloom : + IsImported globals "ethereum.gray_glacier.fork_types" "Bloom". +Axiom ethereum_gray_glacier_fork_types_imports_Root : + IsImported globals "ethereum.gray_glacier.fork_types" "Root". + +Axiom ethereum_gray_glacier_state_imports_State : + IsImported globals "ethereum.gray_glacier.state" "State". +Axiom ethereum_gray_glacier_state_imports_account_exists_and_is_empty : + IsImported globals "ethereum.gray_glacier.state" "account_exists_and_is_empty". +Axiom ethereum_gray_glacier_state_imports_create_ether : + IsImported globals "ethereum.gray_glacier.state" "create_ether". +Axiom ethereum_gray_glacier_state_imports_destroy_account : + IsImported globals "ethereum.gray_glacier.state" "destroy_account". +Axiom ethereum_gray_glacier_state_imports_get_account : + IsImported globals "ethereum.gray_glacier.state" "get_account". +Axiom ethereum_gray_glacier_state_imports_increment_nonce : + IsImported globals "ethereum.gray_glacier.state" "increment_nonce". +Axiom ethereum_gray_glacier_state_imports_set_account_balance : + IsImported globals "ethereum.gray_glacier.state" "set_account_balance". +Axiom ethereum_gray_glacier_state_imports_state_root : + IsImported globals "ethereum.gray_glacier.state" "state_root". + +Axiom ethereum_gray_glacier_transactions_imports_TX_ACCESS_LIST_ADDRESS_COST : + IsImported globals "ethereum.gray_glacier.transactions" "TX_ACCESS_LIST_ADDRESS_COST". +Axiom ethereum_gray_glacier_transactions_imports_TX_ACCESS_LIST_STORAGE_KEY_COST : + IsImported globals "ethereum.gray_glacier.transactions" "TX_ACCESS_LIST_STORAGE_KEY_COST". +Axiom ethereum_gray_glacier_transactions_imports_TX_BASE_COST : + IsImported globals "ethereum.gray_glacier.transactions" "TX_BASE_COST". +Axiom ethereum_gray_glacier_transactions_imports_TX_CREATE_COST : + IsImported globals "ethereum.gray_glacier.transactions" "TX_CREATE_COST". +Axiom ethereum_gray_glacier_transactions_imports_TX_DATA_COST_PER_NON_ZERO : + IsImported globals "ethereum.gray_glacier.transactions" "TX_DATA_COST_PER_NON_ZERO". +Axiom ethereum_gray_glacier_transactions_imports_TX_DATA_COST_PER_ZERO : + IsImported globals "ethereum.gray_glacier.transactions" "TX_DATA_COST_PER_ZERO". +Axiom ethereum_gray_glacier_transactions_imports_AccessListTransaction : + IsImported globals "ethereum.gray_glacier.transactions" "AccessListTransaction". +Axiom ethereum_gray_glacier_transactions_imports_FeeMarketTransaction : + IsImported globals "ethereum.gray_glacier.transactions" "FeeMarketTransaction". +Axiom ethereum_gray_glacier_transactions_imports_LegacyTransaction : + IsImported globals "ethereum.gray_glacier.transactions" "LegacyTransaction". +Axiom ethereum_gray_glacier_transactions_imports_Transaction : + IsImported globals "ethereum.gray_glacier.transactions" "Transaction". +Axiom ethereum_gray_glacier_transactions_imports_decode_transaction : + IsImported globals "ethereum.gray_glacier.transactions" "decode_transaction". +Axiom ethereum_gray_glacier_transactions_imports_encode_transaction : + IsImported globals "ethereum.gray_glacier.transactions" "encode_transaction". + +Axiom ethereum_gray_glacier_trie_imports_Trie : + IsImported globals "ethereum.gray_glacier.trie" "Trie". +Axiom ethereum_gray_glacier_trie_imports_root : + IsImported globals "ethereum.gray_glacier.trie" "root". +Axiom ethereum_gray_glacier_trie_imports_trie_set : + IsImported globals "ethereum.gray_glacier.trie" "trie_set". + +Axiom ethereum_gray_glacier_utils_message_imports_prepare_message : + IsImported globals "ethereum.gray_glacier.utils.message" "prepare_message". + +Axiom ethereum_gray_glacier_vm_interpreter_imports_process_message_call : + IsImported globals "ethereum.gray_glacier.vm.interpreter" "process_message_call". + +Definition BLOCK_REWARD : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + BinOp.mult (| + Constant.int 2, + BinOp.pow (| + Constant.int 10, + Constant.int 18 + |) + |) + ], + make_dict [] + |) +)). + +Definition BASE_FEE_MAX_CHANGE_DENOMINATOR : Value.t := M.run ltac:(M.monadic ( + Constant.int 8 +)). + +Definition ELASTICITY_MULTIPLIER : Value.t := M.run ltac:(M.monadic ( + Constant.int 2 +)). + +Definition GAS_LIMIT_ADJUSTMENT_FACTOR : Value.t := M.run ltac:(M.monadic ( + Constant.int 1024 +)). + +Definition GAS_LIMIT_MINIMUM : Value.t := M.run ltac:(M.monadic ( + Constant.int 5000 +)). + +Definition MINIMUM_DIFFICULTY : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 131072 + ], + make_dict [] + |) +)). + +Definition MAX_OMMER_DEPTH : Value.t := M.run ltac:(M.monadic ( + Constant.int 6 +)). + +Definition BOMB_DELAY_BLOCKS : Value.t := M.run ltac:(M.monadic ( + Constant.int 11400000 +)). + +Definition EMPTY_OMMER_HASH : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "keccak256" |), + make_list [ + M.call (| + M.get_field (| M.get_name (| globals, "rlp" |), "encode" |), + make_list [ + make_list [] + ], + make_dict [] + |) + ], + make_dict [] + |) +)). + +Definition BlockChain : Value.t := + builtins.make_klass + [] + [ + + ] + [ + + ]. + +Definition apply_fork : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "old" ] |) in + let _ := Constant.str " + Transforms the state from the previous hard fork (`old`) into the block + chain object for this hard fork and returns it. + + When forks need to implement an irregular state transition, this function + is used to handle the irregularity. See the :ref:`DAO Fork ` for + an example. + + Parameters + ---------- + old : + Previous block chain object. + + Returns + ------- + new : `BlockChain` + Upgraded block chain object for this hard fork. + " in + let _ := M.return_ (| + M.get_name (| globals, "old" |) + |) in + M.pure Constant.None_)). + +Definition get_last_256_block_hashes : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "chain" ] |) in + let _ := Constant.str " + Obtain the list of hashes of the previous 256 blocks in order of + increasing block number. + + This function will return less hashes for the first 256 blocks. + + The ``BLOCKHASH`` opcode needs to access the latest hashes on the chain, + therefore this function retrieves them. + + Parameters + ---------- + chain : + History and current state. + + Returns + ------- + recent_block_hashes : `List[Hash32]` + Hashes of the recent 256 blocks in order of increasing block number. + " in + let _ := M.assign_local (| + "recent_blocks" , + M.slice (| + M.get_field (| M.get_name (| globals, "chain" |), "blocks" |), + UnOp.sub (| Constant.int 255 |), + Constant.None_, + Constant.None_ + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_name (| globals, "recent_blocks" |) + ], + make_dict [] + |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + make_list [] + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "recent_block_hashes" , + make_list [] + |) in + let _ := + M.for_ (| + M.get_name (| globals, "block" |), + M.get_name (| globals, "recent_blocks" |), + ltac:(M.monadic ( + let _ := M.assign_local (| + "prev_block_hash" , + M.get_field (| M.get_field (| M.get_name (| globals, "block" |), "header" |), "parent_hash" |) + |) in + let _ := M.call (| + M.get_field (| M.get_name (| globals, "recent_block_hashes" |), "append" |), + make_list [ + M.get_name (| globals, "prev_block_hash" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := M.assign_local (| + "most_recent_block_hash" , + M.call (| + M.get_name (| globals, "keccak256" |), + make_list [ + M.call (| + M.get_field (| M.get_name (| globals, "rlp" |), "encode" |), + make_list [ + M.get_field (| M.get_subscript (| + M.get_name (| globals, "recent_blocks" |), + UnOp.sub (| Constant.int 1 |) + |), "header" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_field (| M.get_name (| globals, "recent_block_hashes" |), "append" |), + make_list [ + M.get_name (| globals, "most_recent_block_hash" |) + ], + make_dict [] + |) in + let _ := M.return_ (| + M.get_name (| globals, "recent_block_hashes" |) + |) in + M.pure Constant.None_)). + +Definition state_transition : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "chain"; "block" ] |) in + let _ := Constant.str " + Attempts to apply a block to an existing block chain. + + All parts of the block's contents need to be verified before being added + to the chain. Blocks are verified by ensuring that the contents of the + block make logical sense with the contents of the parent block. The + information in the block's header must also match the corresponding + information in the block. + + To implement Ethereum, in theory clients are only required to store the + most recent 255 blocks of the chain since as far as execution is + concerned, only those blocks are accessed. Practically, however, clients + should store more blocks to handle reorgs. + + Parameters + ---------- + chain : + History and current state. + block : + Block to apply to `chain`. + " in + let _ := M.assign_local (| + "parent_header" , + M.get_field (| M.get_subscript (| + M.get_field (| M.get_name (| globals, "chain" |), "blocks" |), + UnOp.sub (| Constant.int 1 |) + |), "header" |) + |) in + let _ := M.call (| + M.get_name (| globals, "validate_header" |), + make_list [ + M.get_field (| M.get_name (| globals, "block" |), "header" |); + M.get_name (| globals, "parent_header" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "validate_ommers" |), + make_list [ + M.get_field (| M.get_name (| globals, "block" |), "ommers" |); + M.get_field (| M.get_name (| globals, "block" |), "header" |); + M.get_name (| globals, "chain" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "apply_body_output" , + M.call (| + M.get_name (| globals, "apply_body" |), + make_list [ + M.get_field (| M.get_name (| globals, "chain" |), "state" |); + M.call (| + M.get_name (| globals, "get_last_256_block_hashes" |), + make_list [ + M.get_name (| globals, "chain" |) + ], + make_dict [] + |); + M.get_field (| M.get_field (| M.get_name (| globals, "block" |), "header" |), "coinbase" |); + M.get_field (| M.get_field (| M.get_name (| globals, "block" |), "header" |), "number" |); + M.get_field (| M.get_field (| M.get_name (| globals, "block" |), "header" |), "base_fee_per_gas" |); + M.get_field (| M.get_field (| M.get_name (| globals, "block" |), "header" |), "gas_limit" |); + M.get_field (| M.get_field (| M.get_name (| globals, "block" |), "header" |), "timestamp" |); + M.get_field (| M.get_field (| M.get_name (| globals, "block" |), "header" |), "difficulty" |); + M.get_field (| M.get_name (| globals, "block" |), "transactions" |); + M.get_field (| M.get_name (| globals, "block" |), "ommers" |); + M.get_field (| M.get_name (| globals, "chain" |), "chain_id" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + Compare.eq (| + M.get_field (| M.get_name (| globals, "apply_body_output" |), "block_gas_used" |), + M.get_field (| M.get_field (| M.get_name (| globals, "block" |), "header" |), "gas_used" |) + |); + M.get_name (| globals, "InvalidBlock" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + Compare.eq (| + M.get_field (| M.get_name (| globals, "apply_body_output" |), "transactions_root" |), + M.get_field (| M.get_field (| M.get_name (| globals, "block" |), "header" |), "transactions_root" |) + |); + M.get_name (| globals, "InvalidBlock" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + Compare.eq (| + M.get_field (| M.get_name (| globals, "apply_body_output" |), "state_root" |), + M.get_field (| M.get_field (| M.get_name (| globals, "block" |), "header" |), "state_root" |) + |); + M.get_name (| globals, "InvalidBlock" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + Compare.eq (| + M.get_field (| M.get_name (| globals, "apply_body_output" |), "receipt_root" |), + M.get_field (| M.get_field (| M.get_name (| globals, "block" |), "header" |), "receipt_root" |) + |); + M.get_name (| globals, "InvalidBlock" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + Compare.eq (| + M.get_field (| M.get_name (| globals, "apply_body_output" |), "block_logs_bloom" |), + M.get_field (| M.get_field (| M.get_name (| globals, "block" |), "header" |), "bloom" |) + |); + M.get_name (| globals, "InvalidBlock" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, "chain" |), "blocks" |), "append" |), + make_list [ + M.get_name (| globals, "block" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.gt (| + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_field (| M.get_name (| globals, "chain" |), "blocks" |) + ], + make_dict [] + |), + Constant.int 255 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign (| + M.get_field (| M.get_name (| globals, "chain" |), "blocks" |), + M.slice (| + M.get_field (| M.get_name (| globals, "chain" |), "blocks" |), + UnOp.sub (| Constant.int 255 |), + Constant.None_, + Constant.None_ + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + M.pure Constant.None_)). + +Definition calculate_base_fee_per_gas : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "block_gas_limit"; "parent_gas_limit"; "parent_gas_used"; "parent_base_fee_per_gas" ] |) in + let _ := Constant.str " + Calculates the base fee per gas for the block. + + Parameters + ---------- + block_gas_limit : + Gas limit of the block for which the base fee is being calculated. + parent_gas_limit : + Gas limit of the parent block. + parent_gas_used : + Gas used in the parent block. + parent_base_fee_per_gas : + Base fee per gas of the parent block. + + Returns + ------- + base_fee_per_gas : `Uint` + Base fee per gas for the block. + " in + let _ := M.assign_local (| + "parent_gas_target" , + BinOp.floor_div (| + M.get_name (| globals, "parent_gas_limit" |), + M.get_name (| globals, "ELASTICITY_MULTIPLIER" |) + |) + |) in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + M.call (| + M.get_name (| globals, "check_gas_limit" |), + make_list [ + M.get_name (| globals, "block_gas_limit" |); + M.get_name (| globals, "parent_gas_limit" |) + ], + make_dict [] + |); + M.get_name (| globals, "InvalidBlock" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, "parent_gas_used" |), + M.get_name (| globals, "parent_gas_target" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "expected_base_fee_per_gas" , + M.get_name (| globals, "parent_base_fee_per_gas" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + Compare.gt (| + M.get_name (| globals, "parent_gas_used" |), + M.get_name (| globals, "parent_gas_target" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "gas_used_delta" , + BinOp.sub (| + M.get_name (| globals, "parent_gas_used" |), + M.get_name (| globals, "parent_gas_target" |) + |) + |) in + let _ := M.assign_local (| + "parent_fee_gas_delta" , + BinOp.mult (| + M.get_name (| globals, "parent_base_fee_per_gas" |), + M.get_name (| globals, "gas_used_delta" |) + |) + |) in + let _ := M.assign_local (| + "target_fee_gas_delta" , + BinOp.floor_div (| + M.get_name (| globals, "parent_fee_gas_delta" |), + M.get_name (| globals, "parent_gas_target" |) + |) + |) in + let _ := M.assign_local (| + "base_fee_per_gas_delta" , + M.call (| + M.get_name (| globals, "max" |), + make_list [ + BinOp.floor_div (| + M.get_name (| globals, "target_fee_gas_delta" |), + M.get_name (| globals, "BASE_FEE_MAX_CHANGE_DENOMINATOR" |) + |); + Constant.int 1 + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "expected_base_fee_per_gas" , + BinOp.add (| + M.get_name (| globals, "parent_base_fee_per_gas" |), + M.get_name (| globals, "base_fee_per_gas_delta" |) + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "gas_used_delta" , + BinOp.sub (| + M.get_name (| globals, "parent_gas_target" |), + M.get_name (| globals, "parent_gas_used" |) + |) + |) in + let _ := M.assign_local (| + "parent_fee_gas_delta" , + BinOp.mult (| + M.get_name (| globals, "parent_base_fee_per_gas" |), + M.get_name (| globals, "gas_used_delta" |) + |) + |) in + let _ := M.assign_local (| + "target_fee_gas_delta" , + BinOp.floor_div (| + M.get_name (| globals, "parent_fee_gas_delta" |), + M.get_name (| globals, "parent_gas_target" |) + |) + |) in + let _ := M.assign_local (| + "base_fee_per_gas_delta" , + BinOp.floor_div (| + M.get_name (| globals, "target_fee_gas_delta" |), + M.get_name (| globals, "BASE_FEE_MAX_CHANGE_DENOMINATOR" |) + |) + |) in + let _ := M.assign_local (| + "expected_base_fee_per_gas" , + BinOp.sub (| + M.get_name (| globals, "parent_base_fee_per_gas" |), + M.get_name (| globals, "base_fee_per_gas_delta" |) + |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )) |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.get_name (| globals, "expected_base_fee_per_gas" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Definition validate_header : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "header"; "parent_header" ] |) in + let _ := Constant.str " + Verifies a block header. + + In order to consider a block's header valid, the logic for the + quantities in the header should match the logic for the block itself. + For example the header timestamp should be greater than the block's parent + timestamp because the block was created *after* the parent block. + Additionally, the block's number should be directly following the parent + block's number since it is the next block in the sequence. + + Parameters + ---------- + header : + Header to check for correctness. + parent_header : + Parent Header of the header to check for correctness + " in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + Compare.lt_e (| + M.get_field (| M.get_name (| globals, "header" |), "gas_used" |), + M.get_field (| M.get_name (| globals, "header" |), "gas_limit" |) + |); + M.get_name (| globals, "InvalidBlock" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "expected_base_fee_per_gas" , + M.call (| + M.get_name (| globals, "calculate_base_fee_per_gas" |), + make_list [ + M.get_field (| M.get_name (| globals, "header" |), "gas_limit" |); + M.get_field (| M.get_name (| globals, "parent_header" |), "gas_limit" |); + M.get_field (| M.get_name (| globals, "parent_header" |), "gas_used" |); + M.get_field (| M.get_name (| globals, "parent_header" |), "base_fee_per_gas" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + Compare.eq (| + M.get_name (| globals, "expected_base_fee_per_gas" |), + M.get_field (| M.get_name (| globals, "header" |), "base_fee_per_gas" |) + |); + M.get_name (| globals, "InvalidBlock" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "parent_has_ommers" , + Compare.not_eq (| + M.get_field (| M.get_name (| globals, "parent_header" |), "ommers_hash" |), + M.get_name (| globals, "EMPTY_OMMER_HASH" |) + |) + |) in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + Compare.gt (| + M.get_field (| M.get_name (| globals, "header" |), "timestamp" |), + M.get_field (| M.get_name (| globals, "parent_header" |), "timestamp" |) + |); + M.get_name (| globals, "InvalidBlock" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + Compare.eq (| + M.get_field (| M.get_name (| globals, "header" |), "number" |), + BinOp.add (| + M.get_field (| M.get_name (| globals, "parent_header" |), "number" |), + Constant.int 1 + |) + |); + M.get_name (| globals, "InvalidBlock" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + Compare.lt_e (| + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_field (| M.get_name (| globals, "header" |), "extra_data" |) + ], + make_dict [] + |), + Constant.int 32 + |); + M.get_name (| globals, "InvalidBlock" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "block_difficulty" , + M.call (| + M.get_name (| globals, "calculate_block_difficulty" |), + make_list [ + M.get_field (| M.get_name (| globals, "header" |), "number" |); + M.get_field (| M.get_name (| globals, "header" |), "timestamp" |); + M.get_field (| M.get_name (| globals, "parent_header" |), "timestamp" |); + M.get_field (| M.get_name (| globals, "parent_header" |), "difficulty" |); + M.get_name (| globals, "parent_has_ommers" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + Compare.eq (| + M.get_field (| M.get_name (| globals, "header" |), "difficulty" |), + M.get_name (| globals, "block_difficulty" |) + |); + M.get_name (| globals, "InvalidBlock" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "block_parent_hash" , + M.call (| + M.get_name (| globals, "keccak256" |), + make_list [ + M.call (| + M.get_field (| M.get_name (| globals, "rlp" |), "encode" |), + make_list [ + M.get_name (| globals, "parent_header" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + Compare.eq (| + M.get_field (| M.get_name (| globals, "header" |), "parent_hash" |), + M.get_name (| globals, "block_parent_hash" |) + |); + M.get_name (| globals, "InvalidBlock" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "validate_proof_of_work" |), + make_list [ + M.get_name (| globals, "header" |) + ], + make_dict [] + |) in + M.pure Constant.None_)). + +Definition generate_header_hash_for_pow : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "header" ] |) in + let _ := Constant.str " + Generate rlp hash of the header which is to be used for Proof-of-Work + verification. + + In other words, the PoW artefacts `mix_digest` and `nonce` are ignored + while calculating this hash. + + A particular PoW is valid for a single hash, that hash is computed by + this function. The `nonce` and `mix_digest` are omitted from this hash + because they are being changed by miners in their search for a sufficient + proof-of-work. + + Parameters + ---------- + header : + The header object for which the hash is to be generated. + + Returns + ------- + hash : `Hash32` + The PoW valid rlp hash of the passed in header. + " in + let _ := M.assign_local (| + "header_data_without_pow_artefacts" , + make_list [ + M.get_field (| M.get_name (| globals, "header" |), "parent_hash" |); + M.get_field (| M.get_name (| globals, "header" |), "ommers_hash" |); + M.get_field (| M.get_name (| globals, "header" |), "coinbase" |); + M.get_field (| M.get_name (| globals, "header" |), "state_root" |); + M.get_field (| M.get_name (| globals, "header" |), "transactions_root" |); + M.get_field (| M.get_name (| globals, "header" |), "receipt_root" |); + M.get_field (| M.get_name (| globals, "header" |), "bloom" |); + M.get_field (| M.get_name (| globals, "header" |), "difficulty" |); + M.get_field (| M.get_name (| globals, "header" |), "number" |); + M.get_field (| M.get_name (| globals, "header" |), "gas_limit" |); + M.get_field (| M.get_name (| globals, "header" |), "gas_used" |); + M.get_field (| M.get_name (| globals, "header" |), "timestamp" |); + M.get_field (| M.get_name (| globals, "header" |), "extra_data" |); + M.get_field (| M.get_name (| globals, "header" |), "base_fee_per_gas" |) + ] + |) in + let _ := M.return_ (| + M.call (| + M.get_field (| M.get_name (| globals, "rlp" |), "rlp_hash" |), + make_list [ + M.get_name (| globals, "header_data_without_pow_artefacts" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Definition validate_proof_of_work : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "header" ] |) in + let _ := Constant.str " + Validates the Proof of Work constraints. + + In order to verify that a miner's proof-of-work is valid for a block, a + ``mix-digest`` and ``result`` are calculated using the ``hashimoto_light`` + hash function. The mix digest is a hash of the header and the nonce that + is passed through and it confirms whether or not proof-of-work was done + on the correct block. The result is the actual hash value of the block. + + Parameters + ---------- + header : + Header of interest. + " in + let _ := M.assign_local (| + "header_hash" , + M.call (| + M.get_name (| globals, "generate_header_hash_for_pow" |), + make_list [ + M.get_name (| globals, "header" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "cache" , + M.call (| + M.get_name (| globals, "generate_cache" |), + make_list [ + M.get_field (| M.get_name (| globals, "header" |), "number" |) + ], + make_dict [] + |) + |) in + let _ := M.assign (| + make_tuple [ M.get_name (| globals, "mix_digest" |); M.get_name (| globals, "result" |) ], + M.call (| + M.get_name (| globals, "hashimoto_light" |), + make_list [ + M.get_name (| globals, "header_hash" |); + M.get_field (| M.get_name (| globals, "header" |), "nonce" |); + M.get_name (| globals, "cache" |); + M.call (| + M.get_name (| globals, "dataset_size" |), + make_list [ + M.get_field (| M.get_name (| globals, "header" |), "number" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + Compare.eq (| + M.get_name (| globals, "mix_digest" |), + M.get_field (| M.get_name (| globals, "header" |), "mix_digest" |) + |); + M.get_name (| globals, "InvalidBlock" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + Compare.lt_e (| + M.call (| + M.get_field (| M.get_name (| globals, "Uint" |), "from_be_bytes" |), + make_list [ + M.get_name (| globals, "result" |) + ], + make_dict [] + |), + BinOp.floor_div (| + M.get_name (| globals, "U256_CEIL_VALUE" |), + M.get_field (| M.get_name (| globals, "header" |), "difficulty" |) + |) + |); + M.get_name (| globals, "InvalidBlock" |) + ], + make_dict [] + |) in + M.pure Constant.None_)). + +Definition check_transaction : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "tx"; "base_fee_per_gas"; "gas_available"; "chain_id" ] |) in + let _ := Constant.str " + Check if the transaction is includable in the block. + + Parameters + ---------- + tx : + The transaction. + base_fee_per_gas : + The block base fee. + gas_available : + The gas remaining in the block. + chain_id : + The ID of the current chain. + + Returns + ------- + sender_address : + The sender of the transaction. + effective_gas_price : + The price to charge for gas when the transaction is executed. + + Raises + ------ + InvalidBlock : + If the transaction is not includable. + " in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + Compare.lt_e (| + M.get_field (| M.get_name (| globals, "tx" |), "gas" |), + M.get_name (| globals, "gas_available" |) + |); + M.get_name (| globals, "InvalidBlock" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "sender_address" , + M.call (| + M.get_name (| globals, "recover_sender" |), + make_list [ + M.get_name (| globals, "chain_id" |); + M.get_name (| globals, "tx" |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, "isinstance" |), + make_list [ + M.get_name (| globals, "tx" |); + M.get_name (| globals, "FeeMarketTransaction" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + Compare.gt_e (| + M.get_field (| M.get_name (| globals, "tx" |), "max_fee_per_gas" |), + M.get_field (| M.get_name (| globals, "tx" |), "max_priority_fee_per_gas" |) + |); + M.get_name (| globals, "InvalidBlock" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + Compare.gt_e (| + M.get_field (| M.get_name (| globals, "tx" |), "max_fee_per_gas" |), + M.get_name (| globals, "base_fee_per_gas" |) + |); + M.get_name (| globals, "InvalidBlock" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "priority_fee_per_gas" , + M.call (| + M.get_name (| globals, "min" |), + make_list [ + M.get_field (| M.get_name (| globals, "tx" |), "max_priority_fee_per_gas" |); + BinOp.sub (| + M.get_field (| M.get_name (| globals, "tx" |), "max_fee_per_gas" |), + M.get_name (| globals, "base_fee_per_gas" |) + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "effective_gas_price" , + BinOp.add (| + M.get_name (| globals, "priority_fee_per_gas" |), + M.get_name (| globals, "base_fee_per_gas" |) + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + Compare.gt_e (| + M.get_field (| M.get_name (| globals, "tx" |), "gas_price" |), + M.get_name (| globals, "base_fee_per_gas" |) + |); + M.get_name (| globals, "InvalidBlock" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "effective_gas_price" , + M.get_field (| M.get_name (| globals, "tx" |), "gas_price" |) + |) in + M.pure Constant.None_ + )) |) in + let _ := M.return_ (| + make_tuple [ M.get_name (| globals, "sender_address" |); M.get_name (| globals, "effective_gas_price" |) ] + |) in + M.pure Constant.None_)). + +Definition make_receipt : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "tx"; "error"; "cumulative_gas_used"; "logs" ] |) in + let _ := Constant.str " + Make the receipt for a transaction that was executed. + + Parameters + ---------- + tx : + The executed transaction. + error : + Error in the top level frame of the transaction, if any. + cumulative_gas_used : + The total gas used so far in the block after the transaction was + executed. + logs : + The logs produced by the transaction. + + Returns + ------- + receipt : + The receipt for the transaction. + " in + let _ := M.assign_local (| + "receipt" , + M.call (| + M.get_name (| globals, "Receipt" |), + make_list [], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, "isinstance" |), + make_list [ + M.get_name (| globals, "tx" |); + M.get_name (| globals, "AccessListTransaction" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + BinOp.add (| + Constant.bytes "01", + M.call (| + M.get_field (| M.get_name (| globals, "rlp" |), "encode" |), + make_list [ + M.get_name (| globals, "receipt" |) + ], + make_dict [] + |) + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, "isinstance" |), + make_list [ + M.get_name (| globals, "tx" |); + M.get_name (| globals, "FeeMarketTransaction" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + BinOp.add (| + Constant.bytes "02", + M.call (| + M.get_field (| M.get_name (| globals, "rlp" |), "encode" |), + make_list [ + M.get_name (| globals, "receipt" |) + ], + make_dict [] + |) + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.return_ (| + M.get_name (| globals, "receipt" |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_)). + +Definition ApplyBodyOutput : Value.t := + builtins.make_klass + [] + [ + + ] + [ + + ]. + +Definition apply_body : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "state"; "block_hashes"; "coinbase"; "block_number"; "base_fee_per_gas"; "block_gas_limit"; "block_time"; "block_difficulty"; "transactions"; "ommers"; "chain_id" ] |) in + let _ := Constant.str " + Executes a block. + + Many of the contents of a block are stored in data structures called + tries. There is a transactions trie which is similar to a ledger of the + transactions stored in the current block. There is also a receipts trie + which stores the results of executing a transaction, like the post state + and gas used. This function creates and executes the block that is to be + added to the chain. + + Parameters + ---------- + state : + Current account state. + block_hashes : + List of hashes of the previous 256 blocks in the order of + increasing block number. + coinbase : + Address of account which receives block reward and transaction fees. + block_number : + Position of the block within the chain. + base_fee_per_gas : + Base fee per gas of within the block. + block_gas_limit : + Initial amount of gas available for execution in this block. + block_time : + Time the block was produced, measured in seconds since the epoch. + block_difficulty : + Difficulty of the block. + transactions : + Transactions included in the block. + ommers : + Headers of ancestor blocks which are not direct parents (formerly + uncles.) + chain_id : + ID of the executing chain. + + Returns + ------- + apply_body_output : `ApplyBodyOutput` + Output of applying the block body to the state. + " in + let _ := M.assign_local (| + "gas_available" , + M.get_name (| globals, "block_gas_limit" |) + |) in +(* At stmt: unsupported node type: AnnAssign *) +(* At stmt: unsupported node type: AnnAssign *) +(* At stmt: unsupported node type: AnnAssign *) + let _ := + M.for_ (| + make_tuple [ M.get_name (| globals, "i" |); M.get_name (| globals, "tx" |) ], + M.call (| + M.get_name (| globals, "enumerate" |), + make_list [ + M.call (| + M.get_name (| globals, "map" |), + make_list [ + M.get_name (| globals, "decode_transaction" |); + M.get_name (| globals, "transactions" |) + ], + make_dict [] + |) + ], + make_dict [] + |), + ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, "trie_set" |), + make_list [ + M.get_name (| globals, "transactions_trie" |); + M.call (| + M.get_field (| M.get_name (| globals, "rlp" |), "encode" |), + make_list [ + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.get_name (| globals, "i" |) + ], + make_dict [] + |) + ], + make_dict [] + |); + M.call (| + M.get_name (| globals, "encode_transaction" |), + make_list [ + M.get_name (| globals, "tx" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign (| + make_tuple [ M.get_name (| globals, "sender_address" |); M.get_name (| globals, "effective_gas_price" |) ], + M.call (| + M.get_name (| globals, "check_transaction" |), + make_list [ + M.get_name (| globals, "tx" |); + M.get_name (| globals, "base_fee_per_gas" |); + M.get_name (| globals, "gas_available" |); + M.get_name (| globals, "chain_id" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "env" , + M.call (| + M.get_field (| M.get_name (| globals, "vm" |), "Environment" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.assign (| + make_tuple [ M.get_name (| globals, "gas_used" |); M.get_name (| globals, "logs" |); M.get_name (| globals, "error" |) ], + M.call (| + M.get_name (| globals, "process_transaction" |), + make_list [ + M.get_name (| globals, "env" |); + M.get_name (| globals, "tx" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_op_local (| + BinOp.sub, + "gas_available", + M.get_name (| globals, "gas_used" |) + |) in + let _ := M.assign_local (| + "receipt" , + M.call (| + M.get_name (| globals, "make_receipt" |), + make_list [ + M.get_name (| globals, "tx" |); + M.get_name (| globals, "error" |); + BinOp.sub (| + M.get_name (| globals, "block_gas_limit" |), + M.get_name (| globals, "gas_available" |) + |); + M.get_name (| globals, "logs" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "trie_set" |), + make_list [ + M.get_name (| globals, "receipts_trie" |); + M.call (| + M.get_field (| M.get_name (| globals, "rlp" |), "encode" |), + make_list [ + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.get_name (| globals, "i" |) + ], + make_dict [] + |) + ], + make_dict [] + |); + M.get_name (| globals, "receipt" |) + ], + make_dict [] + |) in + let _ := M.assign_op_local (| + BinOp.add, + "block_logs", + M.get_name (| globals, "logs" |) + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := M.call (| + M.get_name (| globals, "pay_rewards" |), + make_list [ + M.get_name (| globals, "state" |); + M.get_name (| globals, "block_number" |); + M.get_name (| globals, "coinbase" |); + M.get_name (| globals, "ommers" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "block_gas_used" , + BinOp.sub (| + M.get_name (| globals, "block_gas_limit" |), + M.get_name (| globals, "gas_available" |) + |) + |) in + let _ := M.assign_local (| + "block_logs_bloom" , + M.call (| + M.get_name (| globals, "logs_bloom" |), + make_list [ + M.get_name (| globals, "block_logs" |) + ], + make_dict [] + |) + |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, "ApplyBodyOutput" |), + make_list [ + M.get_name (| globals, "block_gas_used" |); + M.call (| + M.get_name (| globals, "root" |), + make_list [ + M.get_name (| globals, "transactions_trie" |) + ], + make_dict [] + |); + M.call (| + M.get_name (| globals, "root" |), + make_list [ + M.get_name (| globals, "receipts_trie" |) + ], + make_dict [] + |); + M.get_name (| globals, "block_logs_bloom" |); + M.call (| + M.get_name (| globals, "state_root" |), + make_list [ + M.get_name (| globals, "state" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Definition validate_ommers : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "ommers"; "block_header"; "chain" ] |) in + let _ := Constant.str " + Validates the ommers mentioned in the block. + + An ommer block is a block that wasn't canonically added to the + blockchain because it wasn't validated as fast as the canonical block + but was mined at the same time. + + To be considered valid, the ommers must adhere to the rules defined in + the Ethereum protocol. The maximum amount of ommers is 2 per block and + there cannot be duplicate ommers in a block. Many of the other ommer + constraints are listed in the in-line comments of this function. + + Parameters + ---------- + ommers : + List of ommers mentioned in the current block. + block_header: + The header of current block. + chain : + History and current state. + " in + let _ := M.assign_local (| + "block_hash" , + M.call (| + M.get_field (| M.get_name (| globals, "rlp" |), "rlp_hash" |), + make_list [ + M.get_name (| globals, "block_header" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + Compare.eq (| + M.call (| + M.get_field (| M.get_name (| globals, "rlp" |), "rlp_hash" |), + make_list [ + M.get_name (| globals, "ommers" |) + ], + make_dict [] + |), + M.get_field (| M.get_name (| globals, "block_header" |), "ommers_hash" |) + |); + M.get_name (| globals, "InvalidBlock" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_name (| globals, "ommers" |) + ], + make_dict [] + |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + Constant.None_ + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + M.for_ (| + M.get_name (| globals, "ommer" |), + M.get_name (| globals, "ommers" |), + ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + BoolOp.and (| + Compare.lt_e (| + Constant.int 1, + M.get_field (| M.get_name (| globals, "ommer" |), "number" |) + |), + ltac:(M.monadic ( + Compare.lt (| + M.get_field (| M.get_name (| globals, "ommer" |), "number" |), + M.get_field (| M.get_name (| globals, "block_header" |), "number" |) + |) + )) + |); + M.get_name (| globals, "InvalidBlock" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "ommer_parent_header" , + M.get_field (| M.get_subscript (| + M.get_field (| M.get_name (| globals, "chain" |), "blocks" |), + BinOp.sub (| + UnOp.sub (| BinOp.sub (| + M.get_field (| M.get_name (| globals, "block_header" |), "number" |), + M.get_field (| M.get_name (| globals, "ommer" |), "number" |) + |) |), + Constant.int 1 + |) + |), "header" |) + |) in + let _ := M.call (| + M.get_name (| globals, "validate_header" |), + make_list [ + M.get_name (| globals, "ommer" |); + M.get_name (| globals, "ommer_parent_header" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + Compare.lt_e (| + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_name (| globals, "ommers" |) + ], + make_dict [] + |), + Constant.int 2 + |); + M.get_name (| globals, "InvalidBlock" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "ommers_hashes" , + Constant.str "(* At expr: unsupported node type: ListComp *)" + |) in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + Compare.eq (| + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_name (| globals, "ommers_hashes" |) + ], + make_dict [] + |), + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.call (| + M.get_name (| globals, "set" |), + make_list [ + M.get_name (| globals, "ommers_hashes" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |); + M.get_name (| globals, "InvalidBlock" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "recent_canonical_blocks" , + M.slice (| + M.get_field (| M.get_name (| globals, "chain" |), "blocks" |), + UnOp.sub (| BinOp.add (| + M.get_name (| globals, "MAX_OMMER_DEPTH" |), + Constant.int 1 + |) |), + Constant.None_, + Constant.None_ + |) + |) in + let _ := M.assign_local (| + "recent_canonical_block_hashes" , + Constant.str "(* At expr: unsupported node type: SetComp *)" + |) in +(* At stmt: unsupported node type: AnnAssign *) + let _ := + M.for_ (| + M.get_name (| globals, "block" |), + M.get_name (| globals, "recent_canonical_blocks" |), + ltac:(M.monadic ( + let _ := M.assign_local (| + "recent_ommers_hashes" , + M.call (| + M.get_field (| M.get_name (| globals, "recent_ommers_hashes" |), "union" |), + make_list [ + Constant.str "(* At expr: unsupported node type: SetComp *)" + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := + M.for_ (| + make_tuple [ M.get_name (| globals, "ommer_index" |); M.get_name (| globals, "ommer" |) ], + M.call (| + M.get_name (| globals, "enumerate" |), + make_list [ + M.get_name (| globals, "ommers" |) + ], + make_dict [] + |), + ltac:(M.monadic ( + let _ := M.assign_local (| + "ommer_hash" , + M.get_subscript (| + M.get_name (| globals, "ommers_hashes" |), + M.get_name (| globals, "ommer_index" |) + |) + |) in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + Compare.not_eq (| + M.get_name (| globals, "ommer_hash" |), + M.get_name (| globals, "block_hash" |) + |); + M.get_name (| globals, "InvalidBlock" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + Compare.not_in (| + M.get_name (| globals, "ommer_hash" |), + M.get_name (| globals, "recent_canonical_block_hashes" |) + |); + M.get_name (| globals, "InvalidBlock" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + Compare.not_in (| + M.get_name (| globals, "ommer_hash" |), + M.get_name (| globals, "recent_ommers_hashes" |) + |); + M.get_name (| globals, "InvalidBlock" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "ommer_age" , + BinOp.sub (| + M.get_field (| M.get_name (| globals, "block_header" |), "number" |), + M.get_field (| M.get_name (| globals, "ommer" |), "number" |) + |) + |) in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + BoolOp.and (| + Compare.lt_e (| + Constant.int 1, + M.get_name (| globals, "ommer_age" |) + |), + ltac:(M.monadic ( + Compare.lt_e (| + M.get_name (| globals, "ommer_age" |), + M.get_name (| globals, "MAX_OMMER_DEPTH" |) + |) + )) + |); + M.get_name (| globals, "InvalidBlock" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + Compare.in_ (| + M.get_field (| M.get_name (| globals, "ommer" |), "parent_hash" |), + M.get_name (| globals, "recent_canonical_block_hashes" |) + |); + M.get_name (| globals, "InvalidBlock" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + Compare.not_eq (| + M.get_field (| M.get_name (| globals, "ommer" |), "parent_hash" |), + M.get_field (| M.get_name (| globals, "block_header" |), "parent_hash" |) + |); + M.get_name (| globals, "InvalidBlock" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + M.pure Constant.None_)). + +Definition pay_rewards : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "state"; "block_number"; "coinbase"; "ommers" ] |) in + let _ := Constant.str " + Pay rewards to the block miner as well as the ommers miners. + + The miner of the canonical block is rewarded with the predetermined + block reward, ``BLOCK_REWARD``, plus a variable award based off of the + number of ommer blocks that were mined around the same time, and included + in the canonical block's header. An ommer block is a block that wasn't + added to the canonical blockchain because it wasn't validated as fast as + the accepted block but was mined at the same time. Although not all blocks + that are mined are added to the canonical chain, miners are still paid a + reward for their efforts. This reward is called an ommer reward and is + calculated based on the number associated with the ommer block that they + mined. + + Parameters + ---------- + state : + Current account state. + block_number : + Position of the block within the chain. + coinbase : + Address of account which receives block reward and transaction fees. + ommers : + List of ommers mentioned in the current block. + " in + let _ := M.assign_local (| + "miner_reward" , + BinOp.add (| + M.get_name (| globals, "BLOCK_REWARD" |), + BinOp.mult (| + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_name (| globals, "ommers" |) + ], + make_dict [] + |), + BinOp.floor_div (| + M.get_name (| globals, "BLOCK_REWARD" |), + Constant.int 32 + |) + |) + |) + |) in + let _ := M.call (| + M.get_name (| globals, "create_ether" |), + make_list [ + M.get_name (| globals, "state" |); + M.get_name (| globals, "coinbase" |); + M.get_name (| globals, "miner_reward" |) + ], + make_dict [] + |) in + let _ := + M.for_ (| + M.get_name (| globals, "ommer" |), + M.get_name (| globals, "ommers" |), + ltac:(M.monadic ( + let _ := M.assign_local (| + "ommer_age" , + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + BinOp.sub (| + M.get_name (| globals, "block_number" |), + M.get_field (| M.get_name (| globals, "ommer" |), "number" |) + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "ommer_miner_reward" , + BinOp.floor_div (| + BinOp.mult (| + BinOp.sub (| + Constant.int 8, + M.get_name (| globals, "ommer_age" |) + |), + M.get_name (| globals, "BLOCK_REWARD" |) + |), + Constant.int 8 + |) + |) in + let _ := M.call (| + M.get_name (| globals, "create_ether" |), + make_list [ + M.get_name (| globals, "state" |); + M.get_field (| M.get_name (| globals, "ommer" |), "coinbase" |); + M.get_name (| globals, "ommer_miner_reward" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + M.pure Constant.None_)). + +Definition process_transaction : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "env"; "tx" ] |) in + let _ := Constant.str " + Execute a transaction against the provided environment. + + This function processes the actions needed to execute a transaction. + It decrements the sender's account after calculating the gas fee and + refunds them the proper amount after execution. Calling contracts, + deploying code, and incrementing nonces are all examples of actions that + happen within this function or from a call made within this function. + + Accounts that are marked for deletion are processed and destroyed after + execution. + + Parameters + ---------- + env : + Environment for the Ethereum Virtual Machine. + tx : + Transaction to execute. + + Returns + ------- + gas_left : `ethereum.base_types.U256` + Remaining gas after execution. + logs : `Tuple[ethereum.blocks.Log, ...]` + Logs generated during execution. + " in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + M.call (| + M.get_name (| globals, "validate_transaction" |), + make_list [ + M.get_name (| globals, "tx" |) + ], + make_dict [] + |); + M.get_name (| globals, "InvalidBlock" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "sender" , + M.get_field (| M.get_name (| globals, "env" |), "origin" |) + |) in + let _ := M.assign_local (| + "sender_account" , + M.call (| + M.get_name (| globals, "get_account" |), + make_list [ + M.get_field (| M.get_name (| globals, "env" |), "state" |); + M.get_name (| globals, "sender" |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, "isinstance" |), + make_list [ + M.get_name (| globals, "tx" |); + M.get_name (| globals, "FeeMarketTransaction" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "max_gas_fee" , + BinOp.mult (| + M.get_field (| M.get_name (| globals, "tx" |), "gas" |), + M.get_field (| M.get_name (| globals, "tx" |), "max_fee_per_gas" |) + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "max_gas_fee" , + BinOp.mult (| + M.get_field (| M.get_name (| globals, "tx" |), "gas" |), + M.get_field (| M.get_name (| globals, "tx" |), "gas_price" |) + |) + |) in + M.pure Constant.None_ + )) |) in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + Compare.eq (| + M.get_field (| M.get_name (| globals, "sender_account" |), "nonce" |), + M.get_field (| M.get_name (| globals, "tx" |), "nonce" |) + |); + M.get_name (| globals, "InvalidBlock" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + Compare.gt_e (| + M.get_field (| M.get_name (| globals, "sender_account" |), "balance" |), + BinOp.add (| + M.get_name (| globals, "max_gas_fee" |), + M.get_field (| M.get_name (| globals, "tx" |), "value" |) + |) + |); + M.get_name (| globals, "InvalidBlock" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + Compare.eq (| + M.get_field (| M.get_name (| globals, "sender_account" |), "code" |), + M.call (| + M.get_name (| globals, "bytearray" |), + make_list [], + make_dict [] + |) + |); + M.get_name (| globals, "InvalidBlock" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "effective_gas_fee" , + BinOp.mult (| + M.get_field (| M.get_name (| globals, "tx" |), "gas" |), + M.get_field (| M.get_name (| globals, "env" |), "gas_price" |) + |) + |) in + let _ := M.assign_local (| + "gas" , + BinOp.sub (| + M.get_field (| M.get_name (| globals, "tx" |), "gas" |), + M.call (| + M.get_name (| globals, "calculate_intrinsic_cost" |), + make_list [ + M.get_name (| globals, "tx" |) + ], + make_dict [] + |) + |) + |) in + let _ := M.call (| + M.get_name (| globals, "increment_nonce" |), + make_list [ + M.get_field (| M.get_name (| globals, "env" |), "state" |); + M.get_name (| globals, "sender" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "sender_balance_after_gas_fee" , + BinOp.sub (| + M.get_field (| M.get_name (| globals, "sender_account" |), "balance" |), + M.get_name (| globals, "effective_gas_fee" |) + |) + |) in + let _ := M.call (| + M.get_name (| globals, "set_account_balance" |), + make_list [ + M.get_field (| M.get_name (| globals, "env" |), "state" |); + M.get_name (| globals, "sender" |); + M.get_name (| globals, "sender_balance_after_gas_fee" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "preaccessed_addresses" , + M.call (| + M.get_name (| globals, "set" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "preaccessed_storage_keys" , + M.call (| + M.get_name (| globals, "set" |), + make_list [], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, "isinstance" |), + make_list [ + M.get_name (| globals, "tx" |); + make_tuple [ M.get_name (| globals, "AccessListTransaction" |); M.get_name (| globals, "FeeMarketTransaction" |) ] + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := + M.for_ (| + make_tuple [ M.get_name (| globals, "address" |); M.get_name (| globals, "keys" |) ], + M.get_field (| M.get_name (| globals, "tx" |), "access_list" |), + ltac:(M.monadic ( + let _ := M.call (| + M.get_field (| M.get_name (| globals, "preaccessed_addresses" |), "add" |), + make_list [ + M.get_name (| globals, "address" |) + ], + make_dict [] + |) in + let _ := + M.for_ (| + M.get_name (| globals, "key" |), + M.get_name (| globals, "keys" |), + ltac:(M.monadic ( + let _ := M.call (| + M.get_field (| M.get_name (| globals, "preaccessed_storage_keys" |), "add" |), + make_list [ + make_tuple [ M.get_name (| globals, "address" |); M.get_name (| globals, "key" |) ] + ], + make_dict [] + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "message" , + M.call (| + M.get_name (| globals, "prepare_message" |), + make_list [ + M.get_name (| globals, "sender" |); + M.get_field (| M.get_name (| globals, "tx" |), "to" |); + M.get_field (| M.get_name (| globals, "tx" |), "value" |); + M.get_field (| M.get_name (| globals, "tx" |), "data" |); + M.get_name (| globals, "gas" |); + M.get_name (| globals, "env" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "output" , + M.call (| + M.get_name (| globals, "process_message_call" |), + make_list [ + M.get_name (| globals, "message" |); + M.get_name (| globals, "env" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "gas_used" , + BinOp.sub (| + M.get_field (| M.get_name (| globals, "tx" |), "gas" |), + M.get_field (| M.get_name (| globals, "output" |), "gas_left" |) + |) + |) in + let _ := M.assign_local (| + "gas_refund" , + M.call (| + M.get_name (| globals, "min" |), + make_list [ + BinOp.floor_div (| + M.get_name (| globals, "gas_used" |), + Constant.int 5 + |); + M.get_field (| M.get_name (| globals, "output" |), "refund_counter" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "gas_refund_amount" , + BinOp.mult (| + BinOp.add (| + M.get_field (| M.get_name (| globals, "output" |), "gas_left" |), + M.get_name (| globals, "gas_refund" |) + |), + M.get_field (| M.get_name (| globals, "env" |), "gas_price" |) + |) + |) in + let _ := M.assign_local (| + "priority_fee_per_gas" , + BinOp.sub (| + M.get_field (| M.get_name (| globals, "env" |), "gas_price" |), + M.get_field (| M.get_name (| globals, "env" |), "base_fee_per_gas" |) + |) + |) in + let _ := M.assign_local (| + "transaction_fee" , + BinOp.mult (| + BinOp.sub (| + BinOp.sub (| + M.get_field (| M.get_name (| globals, "tx" |), "gas" |), + M.get_field (| M.get_name (| globals, "output" |), "gas_left" |) + |), + M.get_name (| globals, "gas_refund" |) + |), + M.get_name (| globals, "priority_fee_per_gas" |) + |) + |) in + let _ := M.assign_local (| + "total_gas_used" , + BinOp.sub (| + M.get_name (| globals, "gas_used" |), + M.get_name (| globals, "gas_refund" |) + |) + |) in + let _ := M.assign_local (| + "sender_balance_after_refund" , + BinOp.add (| + M.get_field (| M.call (| + M.get_name (| globals, "get_account" |), + make_list [ + M.get_field (| M.get_name (| globals, "env" |), "state" |); + M.get_name (| globals, "sender" |) + ], + make_dict [] + |), "balance" |), + M.get_name (| globals, "gas_refund_amount" |) + |) + |) in + let _ := M.call (| + M.get_name (| globals, "set_account_balance" |), + make_list [ + M.get_field (| M.get_name (| globals, "env" |), "state" |); + M.get_name (| globals, "sender" |); + M.get_name (| globals, "sender_balance_after_refund" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "coinbase_balance_after_mining_fee" , + BinOp.add (| + M.get_field (| M.call (| + M.get_name (| globals, "get_account" |), + make_list [ + M.get_field (| M.get_name (| globals, "env" |), "state" |); + M.get_field (| M.get_name (| globals, "env" |), "coinbase" |) + ], + make_dict [] + |), "balance" |), + M.get_name (| globals, "transaction_fee" |) + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.not_eq (| + M.get_name (| globals, "coinbase_balance_after_mining_fee" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, "set_account_balance" |), + make_list [ + M.get_field (| M.get_name (| globals, "env" |), "state" |); + M.get_field (| M.get_name (| globals, "env" |), "coinbase" |); + M.get_name (| globals, "coinbase_balance_after_mining_fee" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, "account_exists_and_is_empty" |), + make_list [ + M.get_field (| M.get_name (| globals, "env" |), "state" |); + M.get_field (| M.get_name (| globals, "env" |), "coinbase" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, "destroy_account" |), + make_list [ + M.get_field (| M.get_name (| globals, "env" |), "state" |); + M.get_field (| M.get_name (| globals, "env" |), "coinbase" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )) |) in + let _ := + M.for_ (| + M.get_name (| globals, "address" |), + M.get_field (| M.get_name (| globals, "output" |), "accounts_to_delete" |), + ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, "destroy_account" |), + make_list [ + M.get_field (| M.get_name (| globals, "env" |), "state" |); + M.get_name (| globals, "address" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := + M.for_ (| + M.get_name (| globals, "address" |), + M.get_field (| M.get_name (| globals, "output" |), "touched_accounts" |), + ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, "account_exists_and_is_empty" |), + make_list [ + M.get_field (| M.get_name (| globals, "env" |), "state" |); + M.get_name (| globals, "address" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, "destroy_account" |), + make_list [ + M.get_field (| M.get_name (| globals, "env" |), "state" |); + M.get_name (| globals, "address" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := M.return_ (| + make_tuple [ M.get_name (| globals, "total_gas_used" |); M.get_field (| M.get_name (| globals, "output" |), "logs" |); M.get_field (| M.get_name (| globals, "output" |), "error" |) ] + |) in + M.pure Constant.None_)). + +Definition validate_transaction : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "tx" ] |) in + let _ := Constant.str " + Verifies a transaction. + + The gas in a transaction gets used to pay for the intrinsic cost of + operations, therefore if there is insufficient gas then it would not + be possible to execute a transaction and it will be declared invalid. + + Additionally, the nonce of a transaction must not equal or exceed the + limit defined in `EIP-2681 `_. + In practice, defining the limit as ``2**64-1`` has no impact because + sending ``2**64-1`` transactions is improbable. It's not strictly + impossible though, ``2**64-1`` transactions is the entire capacity of the + Ethereum blockchain at 2022 gas limits for a little over 22 years. + + Parameters + ---------- + tx : + Transaction to validate. + + Returns + ------- + verified : `bool` + True if the transaction can be executed, or False otherwise. + " in + let _ := M.return_ (| + BoolOp.and (| + Compare.lt_e (| + M.call (| + M.get_name (| globals, "calculate_intrinsic_cost" |), + make_list [ + M.get_name (| globals, "tx" |) + ], + make_dict [] + |), + M.get_field (| M.get_name (| globals, "tx" |), "gas" |) + |), + ltac:(M.monadic ( + Compare.lt (| + M.get_field (| M.get_name (| globals, "tx" |), "nonce" |), + BinOp.sub (| + BinOp.pow (| + Constant.int 2, + Constant.int 64 + |), + Constant.int 1 + |) + |) + )) + |) + |) in + M.pure Constant.None_)). + +Definition calculate_intrinsic_cost : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "tx" ] |) in + let _ := Constant.str " + Calculates the gas that is charged before execution is started. + + The intrinsic cost of the transaction is charged before execution has + begun. Functions/operations in the EVM cost money to execute so this + intrinsic cost is for the operations that need to be paid for as part of + the transaction. Data transfer, for example, is part of this intrinsic + cost. It costs ether to send data over the wire and that ether is + accounted for in the intrinsic cost calculated in this function. This + intrinsic cost must be calculated and paid for before execution in order + for all operations to be implemented. + + Parameters + ---------- + tx : + Transaction to compute the intrinsic cost of. + + Returns + ------- + verified : `ethereum.base_types.Uint` + The intrinsic cost of the transaction. + " in + let _ := M.assign_local (| + "data_cost" , + Constant.int 0 + |) in + let _ := + M.for_ (| + M.get_name (| globals, "byte" |), + M.get_field (| M.get_name (| globals, "tx" |), "data" |), + ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, "byte" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_op_local (| + BinOp.add, + "data_cost", + M.get_name (| globals, "TX_DATA_COST_PER_ZERO" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_op_local (| + BinOp.add, + "data_cost", + M.get_name (| globals, "TX_DATA_COST_PER_NON_ZERO" |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_field (| M.get_name (| globals, "tx" |), "to" |), + M.call (| + M.get_name (| globals, "Bytes0" |), + make_list [ + Constant.bytes "" + ], + make_dict [] + |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "create_cost" , + M.get_name (| globals, "TX_CREATE_COST" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "create_cost" , + Constant.int 0 + |) in + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "access_list_cost" , + Constant.int 0 + |) in + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, "isinstance" |), + make_list [ + M.get_name (| globals, "tx" |); + make_tuple [ M.get_name (| globals, "AccessListTransaction" |); M.get_name (| globals, "FeeMarketTransaction" |) ] + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := + M.for_ (| + make_tuple [ M.get_name (| globals, "_address" |); M.get_name (| globals, "keys" |) ], + M.get_field (| M.get_name (| globals, "tx" |), "access_list" |), + ltac:(M.monadic ( + let _ := M.assign_op_local (| + BinOp.add, + "access_list_cost", + M.get_name (| globals, "TX_ACCESS_LIST_ADDRESS_COST" |) + |) in + let _ := M.assign_op_local (| + BinOp.add, + "access_list_cost", + BinOp.mult (| + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_name (| globals, "keys" |) + ], + make_dict [] + |), + M.get_name (| globals, "TX_ACCESS_LIST_STORAGE_KEY_COST" |) + |) + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + BinOp.add (| + BinOp.add (| + BinOp.add (| + M.get_name (| globals, "TX_BASE_COST" |), + M.get_name (| globals, "data_cost" |) + |), + M.get_name (| globals, "create_cost" |) + |), + M.get_name (| globals, "access_list_cost" |) + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Definition recover_sender : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "chain_id"; "tx" ] |) in + let _ := Constant.str " + Extracts the sender address from a transaction. + + The v, r, and s values are the three parts that make up the signature + of a transaction. In order to recover the sender of a transaction the two + components needed are the signature (``v``, ``r``, and ``s``) and the + signing hash of the transaction. The sender's public key can be obtained + with these two values and therefore the sender address can be retrieved. + + Parameters + ---------- + tx : + Transaction of interest. + chain_id : + ID of the executing chain. + + Returns + ------- + sender : `ethereum.fork_types.Address` + The address of the account that signed the transaction. + " in + let _ := M.assign (| + make_tuple [ M.get_name (| globals, "r" |); M.get_name (| globals, "s" |) ], + make_tuple [ M.get_field (| M.get_name (| globals, "tx" |), "r" |); M.get_field (| M.get_name (| globals, "tx" |), "s" |) ] + |) in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + BoolOp.and (| + Compare.lt (| + Constant.int 0, + M.get_name (| globals, "r" |) + |), + ltac:(M.monadic ( + Compare.lt (| + M.get_name (| globals, "r" |), + M.get_name (| globals, "SECP256K1N" |) + |) + )) + |); + M.get_name (| globals, "InvalidBlock" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + BoolOp.and (| + Compare.lt (| + Constant.int 0, + M.get_name (| globals, "s" |) + |), + ltac:(M.monadic ( + Compare.lt_e (| + M.get_name (| globals, "s" |), + BinOp.floor_div (| + M.get_name (| globals, "SECP256K1N" |), + Constant.int 2 + |) + |) + )) + |); + M.get_name (| globals, "InvalidBlock" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, "isinstance" |), + make_list [ + M.get_name (| globals, "tx" |); + M.get_name (| globals, "LegacyTransaction" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "v" , + M.get_field (| M.get_name (| globals, "tx" |), "v" |) + |) in + let _ := + (* if *) + M.if_then_else (| + BoolOp.or (| + Compare.eq (| + M.get_name (| globals, "v" |), + Constant.int 27 + |), + ltac:(M.monadic ( + Compare.eq (| + M.get_name (| globals, "v" |), + Constant.int 28 + |) + )) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "public_key" , + M.call (| + M.get_name (| globals, "secp256k1_recover" |), + make_list [ + M.get_name (| globals, "r" |); + M.get_name (| globals, "s" |); + BinOp.sub (| + M.get_name (| globals, "v" |), + Constant.int 27 + |); + M.call (| + M.get_name (| globals, "signing_hash_pre155" |), + make_list [ + M.get_name (| globals, "tx" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + BoolOp.or (| + Compare.eq (| + M.get_name (| globals, "v" |), + BinOp.add (| + Constant.int 35, + BinOp.mult (| + M.get_name (| globals, "chain_id" |), + Constant.int 2 + |) + |) + |), + ltac:(M.monadic ( + Compare.eq (| + M.get_name (| globals, "v" |), + BinOp.add (| + Constant.int 36, + BinOp.mult (| + M.get_name (| globals, "chain_id" |), + Constant.int 2 + |) + |) + |) + )) + |); + M.get_name (| globals, "InvalidBlock" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "public_key" , + M.call (| + M.get_name (| globals, "secp256k1_recover" |), + make_list [ + M.get_name (| globals, "r" |); + M.get_name (| globals, "s" |); + BinOp.sub (| + BinOp.sub (| + M.get_name (| globals, "v" |), + Constant.int 35 + |), + BinOp.mult (| + M.get_name (| globals, "chain_id" |), + Constant.int 2 + |) + |); + M.call (| + M.get_name (| globals, "signing_hash_155" |), + make_list [ + M.get_name (| globals, "tx" |); + M.get_name (| globals, "chain_id" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, "isinstance" |), + make_list [ + M.get_name (| globals, "tx" |); + M.get_name (| globals, "AccessListTransaction" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "public_key" , + M.call (| + M.get_name (| globals, "secp256k1_recover" |), + make_list [ + M.get_name (| globals, "r" |); + M.get_name (| globals, "s" |); + M.get_field (| M.get_name (| globals, "tx" |), "y_parity" |); + M.call (| + M.get_name (| globals, "signing_hash_2930" |), + make_list [ + M.get_name (| globals, "tx" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, "isinstance" |), + make_list [ + M.get_name (| globals, "tx" |); + M.get_name (| globals, "FeeMarketTransaction" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "public_key" , + M.call (| + M.get_name (| globals, "secp256k1_recover" |), + make_list [ + M.get_name (| globals, "r" |); + M.get_name (| globals, "s" |); + M.get_field (| M.get_name (| globals, "tx" |), "y_parity" |); + M.call (| + M.get_name (| globals, "signing_hash_1559" |), + make_list [ + M.get_name (| globals, "tx" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )) |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, "Address" |), + make_list [ + M.slice (| + M.call (| + M.get_name (| globals, "keccak256" |), + make_list [ + M.get_name (| globals, "public_key" |) + ], + make_dict [] + |), + Constant.int 12, + Constant.int 32, + Constant.None_ + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Definition signing_hash_pre155 : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "tx" ] |) in + let _ := Constant.str " + Compute the hash of a transaction used in a legacy (pre EIP 155) signature. + + Parameters + ---------- + tx : + Transaction of interest. + + Returns + ------- + hash : `ethereum.crypto.hash.Hash32` + Hash of the transaction. + " in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, "keccak256" |), + make_list [ + M.call (| + M.get_field (| M.get_name (| globals, "rlp" |), "encode" |), + make_list [ + make_tuple [ M.get_field (| M.get_name (| globals, "tx" |), "nonce" |); M.get_field (| M.get_name (| globals, "tx" |), "gas_price" |); M.get_field (| M.get_name (| globals, "tx" |), "gas" |); M.get_field (| M.get_name (| globals, "tx" |), "to" |); M.get_field (| M.get_name (| globals, "tx" |), "value" |); M.get_field (| M.get_name (| globals, "tx" |), "data" |) ] + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Definition signing_hash_155 : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "tx"; "chain_id" ] |) in + let _ := Constant.str " + Compute the hash of a transaction used in a EIP 155 signature. + + Parameters + ---------- + tx : + Transaction of interest. + chain_id : + The id of the current chain. + + Returns + ------- + hash : `ethereum.crypto.hash.Hash32` + Hash of the transaction. + " in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, "keccak256" |), + make_list [ + M.call (| + M.get_field (| M.get_name (| globals, "rlp" |), "encode" |), + make_list [ + make_tuple [ M.get_field (| M.get_name (| globals, "tx" |), "nonce" |); M.get_field (| M.get_name (| globals, "tx" |), "gas_price" |); M.get_field (| M.get_name (| globals, "tx" |), "gas" |); M.get_field (| M.get_name (| globals, "tx" |), "to" |); M.get_field (| M.get_name (| globals, "tx" |), "value" |); M.get_field (| M.get_name (| globals, "tx" |), "data" |); M.get_name (| globals, "chain_id" |); M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |); M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) ] + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Definition signing_hash_2930 : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "tx" ] |) in + let _ := Constant.str " + Compute the hash of a transaction used in a EIP 2930 signature. + + Parameters + ---------- + tx : + Transaction of interest. + + Returns + ------- + hash : `ethereum.crypto.hash.Hash32` + Hash of the transaction. + " in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, "keccak256" |), + make_list [ + BinOp.add (| + Constant.bytes "01", + M.call (| + M.get_field (| M.get_name (| globals, "rlp" |), "encode" |), + make_list [ + make_tuple [ M.get_field (| M.get_name (| globals, "tx" |), "chain_id" |); M.get_field (| M.get_name (| globals, "tx" |), "nonce" |); M.get_field (| M.get_name (| globals, "tx" |), "gas_price" |); M.get_field (| M.get_name (| globals, "tx" |), "gas" |); M.get_field (| M.get_name (| globals, "tx" |), "to" |); M.get_field (| M.get_name (| globals, "tx" |), "value" |); M.get_field (| M.get_name (| globals, "tx" |), "data" |); M.get_field (| M.get_name (| globals, "tx" |), "access_list" |) ] + ], + make_dict [] + |) + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Definition signing_hash_1559 : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "tx" ] |) in + let _ := Constant.str " + Compute the hash of a transaction used in a EIP 1559 signature. + + Parameters + ---------- + tx : + Transaction of interest. + + Returns + ------- + hash : `ethereum.crypto.hash.Hash32` + Hash of the transaction. + " in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, "keccak256" |), + make_list [ + BinOp.add (| + Constant.bytes "02", + M.call (| + M.get_field (| M.get_name (| globals, "rlp" |), "encode" |), + make_list [ + make_tuple [ M.get_field (| M.get_name (| globals, "tx" |), "chain_id" |); M.get_field (| M.get_name (| globals, "tx" |), "nonce" |); M.get_field (| M.get_name (| globals, "tx" |), "max_priority_fee_per_gas" |); M.get_field (| M.get_name (| globals, "tx" |), "max_fee_per_gas" |); M.get_field (| M.get_name (| globals, "tx" |), "gas" |); M.get_field (| M.get_name (| globals, "tx" |), "to" |); M.get_field (| M.get_name (| globals, "tx" |), "value" |); M.get_field (| M.get_name (| globals, "tx" |), "data" |); M.get_field (| M.get_name (| globals, "tx" |), "access_list" |) ] + ], + make_dict [] + |) + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Definition compute_header_hash : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "header" ] |) in + let _ := Constant.str " + Computes the hash of a block header. + + The header hash of a block is the canonical hash that is used to refer + to a specific block and completely distinguishes a block from another. + + ``keccak256`` is a function that produces a 256 bit hash of any input. + It also takes in any number of bytes as an input and produces a single + hash for them. A hash is a completely unique output for a single input. + So an input corresponds to one unique hash that can be used to identify + the input exactly. + + Prior to using the ``keccak256`` hash function, the header must be + encoded using the Recursive-Length Prefix. See :ref:`rlp`. + RLP encoding the header converts it into a space-efficient format that + allows for easy transfer of data between nodes. The purpose of RLP is to + encode arbitrarily nested arrays of binary data, and RLP is the primary + encoding method used to serialize objects in Ethereum's execution layer. + The only purpose of RLP is to encode structure; encoding specific data + types (e.g. strings, floats) is left up to higher-order protocols. + + Parameters + ---------- + header : + Header of interest. + + Returns + ------- + hash : `ethereum.crypto.hash.Hash32` + Hash of the header. + " in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, "keccak256" |), + make_list [ + M.call (| + M.get_field (| M.get_name (| globals, "rlp" |), "encode" |), + make_list [ + M.get_name (| globals, "header" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Definition check_gas_limit : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "gas_limit"; "parent_gas_limit" ] |) in + let _ := Constant.str " + Validates the gas limit for a block. + + The bounds of the gas limit, ``max_adjustment_delta``, is set as the + quotient of the parent block's gas limit and the + ``GAS_LIMIT_ADJUSTMENT_FACTOR``. Therefore, if the gas limit that is + passed through as a parameter is greater than or equal to the *sum* of + the parent's gas and the adjustment delta then the limit for gas is too + high and fails this function's check. Similarly, if the limit is less + than or equal to the *difference* of the parent's gas and the adjustment + delta *or* the predefined ``GAS_LIMIT_MINIMUM`` then this function's + check fails because the gas limit doesn't allow for a sufficient or + reasonable amount of gas to be used on a block. + + Parameters + ---------- + gas_limit : + Gas limit to validate. + + parent_gas_limit : + Gas limit of the parent block. + + Returns + ------- + check : `bool` + True if gas limit constraints are satisfied, False otherwise. + " in + let _ := M.assign_local (| + "max_adjustment_delta" , + BinOp.floor_div (| + M.get_name (| globals, "parent_gas_limit" |), + M.get_name (| globals, "GAS_LIMIT_ADJUSTMENT_FACTOR" |) + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.gt_e (| + M.get_name (| globals, "gas_limit" |), + BinOp.add (| + M.get_name (| globals, "parent_gas_limit" |), + M.get_name (| globals, "max_adjustment_delta" |) + |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + Constant.bool false + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + Compare.lt_e (| + M.get_name (| globals, "gas_limit" |), + BinOp.sub (| + M.get_name (| globals, "parent_gas_limit" |), + M.get_name (| globals, "max_adjustment_delta" |) + |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + Constant.bool false + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + Compare.lt (| + M.get_name (| globals, "gas_limit" |), + M.get_name (| globals, "GAS_LIMIT_MINIMUM" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + Constant.bool false + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.return_ (| + Constant.bool true + |) in + M.pure Constant.None_)). + +Definition calculate_block_difficulty : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "block_number"; "block_timestamp"; "parent_timestamp"; "parent_difficulty"; "parent_has_ommers" ] |) in + let _ := Constant.str " + Computes difficulty of a block using its header and parent header. + + The difficulty is determined by the time the block was created after its + parent. The ``offset`` is calculated using the parent block's difficulty, + ``parent_difficulty``, and the timestamp between blocks. This offset is + then added to the parent difficulty and is stored as the ``difficulty`` + variable. If the time between the block and its parent is too short, the + offset will result in a positive number thus making the sum of + ``parent_difficulty`` and ``offset`` to be a greater value in order to + avoid mass forking. But, if the time is long enough, then the offset + results in a negative value making the block less difficult than + its parent. + + The base standard for a block's difficulty is the predefined value + set for the genesis block since it has no parent. So, a block + can't be less difficult than the genesis block, therefore each block's + difficulty is set to the maximum value between the calculated + difficulty and the ``GENESIS_DIFFICULTY``. + + Parameters + ---------- + block_number : + Block number of the block. + block_timestamp : + Timestamp of the block. + parent_timestamp : + Timestamp of the parent block. + parent_difficulty : + difficulty of the parent block. + parent_has_ommers: + does the parent have ommers. + + Returns + ------- + difficulty : `ethereum.base_types.Uint` + Computed difficulty for a block. + " in + let _ := M.assign_local (| + "offset" , + BinOp.mult (| + BinOp.floor_div (| + M.call (| + M.get_name (| globals, "int" |), + make_list [ + M.get_name (| globals, "parent_difficulty" |) + ], + make_dict [] + |), + Constant.int 2048 + |), + M.call (| + M.get_name (| globals, "max" |), + make_list [ + BinOp.sub (| + (* if *) + M.if_then_else (| + M.get_name (| globals, "parent_has_ommers" |), + (* then *) + ltac:(M.monadic ( +Constant.int 2 + (* else *) + )), ltac:(M.monadic ( +Constant.int 1 + )) |), + BinOp.floor_div (| + M.call (| + M.get_name (| globals, "int" |), + make_list [ + BinOp.sub (| + M.get_name (| globals, "block_timestamp" |), + M.get_name (| globals, "parent_timestamp" |) + |) + ], + make_dict [] + |), + Constant.int 9 + |) + |); + UnOp.sub (| Constant.int 99 |) + ], + make_dict [] + |) + |) + |) in + let _ := M.assign_local (| + "difficulty" , + BinOp.add (| + M.call (| + M.get_name (| globals, "int" |), + make_list [ + M.get_name (| globals, "parent_difficulty" |) + ], + make_dict [] + |), + M.get_name (| globals, "offset" |) + |) + |) in + let _ := M.assign_local (| + "num_bomb_periods" , + BinOp.sub (| + BinOp.floor_div (| + BinOp.sub (| + M.call (| + M.get_name (| globals, "int" |), + make_list [ + M.get_name (| globals, "block_number" |) + ], + make_dict [] + |), + M.get_name (| globals, "BOMB_DELAY_BLOCKS" |) + |), + Constant.int 100000 + |), + Constant.int 2 + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.gt_e (| + M.get_name (| globals, "num_bomb_periods" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_op_local (| + BinOp.add, + "difficulty", + BinOp.pow (| + Constant.int 2, + M.get_name (| globals, "num_bomb_periods" |) + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, "max" |), + make_list [ + M.get_name (| globals, "difficulty" |); + M.get_name (| globals, "MINIMUM_DIFFICULTY" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). diff --git a/CoqOfPython/ethereum/gray_glacier/fork_types.v b/CoqOfPython/ethereum/gray_glacier/fork_types.v new file mode 100644 index 0000000..b0a58e8 --- /dev/null +++ b/CoqOfPython/ethereum/gray_glacier/fork_types.v @@ -0,0 +1,98 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.gray_glacier.fork_types". + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Types +^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Types re-used throughout the specification, which are specific to Ethereum. +". + +Axiom dataclasses_imports_dataclass : + IsImported globals "dataclasses" "dataclass". + +Axiom ethereum_imports_rlp : + IsImported globals "ethereum" "rlp". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_Bytes : + IsImported globals "ethereum.base_types" "Bytes". +Axiom ethereum_base_types_imports_Bytes20 : + IsImported globals "ethereum.base_types" "Bytes20". +Axiom ethereum_base_types_imports_Bytes256 : + IsImported globals "ethereum.base_types" "Bytes256". +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". +Axiom ethereum_base_types_imports_slotted_freezable : + IsImported globals "ethereum.base_types" "slotted_freezable". + +Axiom ethereum_crypto_hash_imports_Hash32 : + IsImported globals "ethereum.crypto.hash" "Hash32". +Axiom ethereum_crypto_hash_imports_keccak256 : + IsImported globals "ethereum.crypto.hash" "keccak256". + +Definition Address : Value.t := M.run ltac:(M.monadic ( + M.get_name (| globals, "Bytes20" |) +)). + +Definition Root : Value.t := M.run ltac:(M.monadic ( + M.get_name (| globals, "Hash32" |) +)). + +Definition Bloom : Value.t := M.run ltac:(M.monadic ( + M.get_name (| globals, "Bytes256" |) +)). + +Definition Account : Value.t := + builtins.make_klass + [] + [ + + ] + [ + + ]. + +Definition EMPTY_ACCOUNT : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Account" |), + make_list [], + make_dict [] + |) +)). + +Definition encode_account : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "raw_account_data"; "storage_root" ] |) in + let _ := Constant.str " + Encode `Account` dataclass. + + Storage is not stored in the `Account` dataclass, so `Accounts` cannot be + encoded with providing a storage root. + " in + let _ := M.return_ (| + M.call (| + M.get_field (| M.get_name (| globals, "rlp" |), "encode" |), + make_list [ + make_tuple [ M.get_field (| M.get_name (| globals, "raw_account_data" |), "nonce" |); M.get_field (| M.get_name (| globals, "raw_account_data" |), "balance" |); M.get_name (| globals, "storage_root" |); M.call (| + M.get_name (| globals, "keccak256" |), + make_list [ + M.get_field (| M.get_name (| globals, "raw_account_data" |), "code" |) + ], + make_dict [] + |) ] + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). diff --git a/CoqOfPython/ethereum/gray_glacier/state.v b/CoqOfPython/ethereum/gray_glacier/state.v new file mode 100644 index 0000000..8cde655 --- /dev/null +++ b/CoqOfPython/ethereum/gray_glacier/state.v @@ -0,0 +1,1279 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.gray_glacier.state". + +Definition expr_1 : Value.t := + Constant.str " +State +^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +The state contains all information that is preserved between transactions. + +It consists of a main account trie and storage tries for each contract. + +There is a distinction between an account that does not exist and +`EMPTY_ACCOUNT`. +". + +Axiom dataclasses_imports_dataclass : + IsImported globals "dataclasses" "dataclass". +Axiom dataclasses_imports_field : + IsImported globals "dataclasses" "field". + +Axiom typing_imports_Callable : + IsImported globals "typing" "Callable". +Axiom typing_imports_Dict : + IsImported globals "typing" "Dict". +Axiom typing_imports_List : + IsImported globals "typing" "List". +Axiom typing_imports_Optional : + IsImported globals "typing" "Optional". +Axiom typing_imports_Set : + IsImported globals "typing" "Set". +Axiom typing_imports_Tuple : + IsImported globals "typing" "Tuple". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_Bytes : + IsImported globals "ethereum.base_types" "Bytes". +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". +Axiom ethereum_base_types_imports_modify : + IsImported globals "ethereum.base_types" "modify". + +Axiom ethereum_utils_ensure_imports_ensure : + IsImported globals "ethereum.utils.ensure" "ensure". + +Axiom ethereum_gray_glacier_fork_types_imports_EMPTY_ACCOUNT : + IsImported globals "ethereum.gray_glacier.fork_types" "EMPTY_ACCOUNT". +Axiom ethereum_gray_glacier_fork_types_imports_Account : + IsImported globals "ethereum.gray_glacier.fork_types" "Account". +Axiom ethereum_gray_glacier_fork_types_imports_Address : + IsImported globals "ethereum.gray_glacier.fork_types" "Address". +Axiom ethereum_gray_glacier_fork_types_imports_Root : + IsImported globals "ethereum.gray_glacier.fork_types" "Root". + +Axiom ethereum_gray_glacier_trie_imports_EMPTY_TRIE_ROOT : + IsImported globals "ethereum.gray_glacier.trie" "EMPTY_TRIE_ROOT". +Axiom ethereum_gray_glacier_trie_imports_Trie : + IsImported globals "ethereum.gray_glacier.trie" "Trie". +Axiom ethereum_gray_glacier_trie_imports_copy_trie : + IsImported globals "ethereum.gray_glacier.trie" "copy_trie". +Axiom ethereum_gray_glacier_trie_imports_root : + IsImported globals "ethereum.gray_glacier.trie" "root". +Axiom ethereum_gray_glacier_trie_imports_trie_get : + IsImported globals "ethereum.gray_glacier.trie" "trie_get". +Axiom ethereum_gray_glacier_trie_imports_trie_set : + IsImported globals "ethereum.gray_glacier.trie" "trie_set". + +Definition State : Value.t := + builtins.make_klass + [] + [ + + ] + [ + + ]. + +Definition close_state : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "state" ] |) in + let _ := Constant.str " + Free resources held by the state. Used by optimized implementations to + release file descriptors. + " in + let _ := M.delete (| M.get_field (| M.get_name (| globals, "state" |), "_main_trie" |) |) in + let _ := M.delete (| M.get_field (| M.get_name (| globals, "state" |), "_storage_tries" |) |) in + let _ := M.delete (| M.get_field (| M.get_name (| globals, "state" |), "_snapshots" |) |) in + let _ := M.delete (| M.get_field (| M.get_name (| globals, "state" |), "_created_accounts" |) |) in + M.pure Constant.None_)). + +Definition begin_transaction : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "state" ] |) in + let _ := Constant.str " + Start a state transaction. + + Transactions are entirely implicit and can be nested. It is not possible to + calculate the state root during a transaction. + + Parameters + ---------- + state : State + The state. + " in + let _ := M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, "state" |), "_snapshots" |), "append" |), + make_list [ + make_tuple [ M.call (| + M.get_name (| globals, "copy_trie" |), + make_list [ + M.get_field (| M.get_name (| globals, "state" |), "_main_trie" |) + ], + make_dict [] + |); Constant.str "(* At expr: unsupported node type: DictComp *)" ] + ], + make_dict [] + |) in + M.pure Constant.None_)). + +Definition commit_transaction : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "state" ] |) in + let _ := Constant.str " + Commit a state transaction. + + Parameters + ---------- + state : State + The state. + " in + let _ := M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, "state" |), "_snapshots" |), "pop" |), + make_list [], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + UnOp.not (| M.get_field (| M.get_name (| globals, "state" |), "_snapshots" |) |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, "state" |), "_created_accounts" |), "clear" |), + make_list [], + make_dict [] + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + M.pure Constant.None_)). + +Definition rollback_transaction : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "state" ] |) in + let _ := Constant.str " + Rollback a state transaction, resetting the state to the point when the + corresponding `start_transaction()` call was made. + + Parameters + ---------- + state : State + The state. + " in + let _ := M.assign (| + make_tuple [ M.get_field (| M.get_name (| globals, "state" |), "_main_trie" |); M.get_field (| M.get_name (| globals, "state" |), "_storage_tries" |) ], + M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, "state" |), "_snapshots" |), "pop" |), + make_list [], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + UnOp.not (| M.get_field (| M.get_name (| globals, "state" |), "_snapshots" |) |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, "state" |), "_created_accounts" |), "clear" |), + make_list [], + make_dict [] + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + M.pure Constant.None_)). + +Definition get_account : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "state"; "address" ] |) in + let _ := Constant.str " + Get the `Account` object at an address. Returns `EMPTY_ACCOUNT` if there + is no account at the address. + + Use `get_account_optional()` if you care about the difference between a + non-existent account and `EMPTY_ACCOUNT`. + + Parameters + ---------- + state: `State` + The state + address : `Address` + Address to lookup. + + Returns + ------- + account : `Account` + Account at address. + " in + let _ := M.assign_local (| + "account" , + M.call (| + M.get_name (| globals, "get_account_optional" |), + make_list [ + M.get_name (| globals, "state" |); + M.get_name (| globals, "address" |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, "isinstance" |), + make_list [ + M.get_name (| globals, "account" |); + M.get_name (| globals, "Account" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + M.get_name (| globals, "account" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.return_ (| + M.get_name (| globals, "EMPTY_ACCOUNT" |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_)). + +Definition get_account_optional : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "state"; "address" ] |) in + let _ := Constant.str " + Get the `Account` object at an address. Returns `None` (rather than + `EMPTY_ACCOUNT`) if there is no account at the address. + + Parameters + ---------- + state: `State` + The state + address : `Address` + Address to lookup. + + Returns + ------- + account : `Account` + Account at address. + " in + let _ := M.assign_local (| + "account" , + M.call (| + M.get_name (| globals, "trie_get" |), + make_list [ + M.get_field (| M.get_name (| globals, "state" |), "_main_trie" |); + M.get_name (| globals, "address" |) + ], + make_dict [] + |) + |) in + let _ := M.return_ (| + M.get_name (| globals, "account" |) + |) in + M.pure Constant.None_)). + +Definition set_account : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "state"; "address"; "account" ] |) in + let _ := Constant.str " + Set the `Account` object at an address. Setting to `None` deletes + the account (but not its storage, see `destroy_account()`). + + Parameters + ---------- + state: `State` + The state + address : `Address` + Address to set. + account : `Account` + Account to set at address. + " in + let _ := M.call (| + M.get_name (| globals, "trie_set" |), + make_list [ + M.get_field (| M.get_name (| globals, "state" |), "_main_trie" |); + M.get_name (| globals, "address" |); + M.get_name (| globals, "account" |) + ], + make_dict [] + |) in + M.pure Constant.None_)). + +Definition destroy_account : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "state"; "address" ] |) in + let _ := Constant.str " + Completely remove the account at `address` and all of its storage. + + This function is made available exclusively for the `SELFDESTRUCT` + opcode. It is expected that `SELFDESTRUCT` will be disabled in a future + hardfork and this function will be removed. + + Parameters + ---------- + state: `State` + The state + address : `Address` + Address of account to destroy. + " in + let _ := M.call (| + M.get_name (| globals, "destroy_storage" |), + make_list [ + M.get_name (| globals, "state" |); + M.get_name (| globals, "address" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "set_account" |), + make_list [ + M.get_name (| globals, "state" |); + M.get_name (| globals, "address" |); + Constant.None_ + ], + make_dict [] + |) in + M.pure Constant.None_)). + +Definition destroy_storage : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "state"; "address" ] |) in + let _ := Constant.str " + Completely remove the storage at `address`. + + Parameters + ---------- + state: `State` + The state + address : `Address` + Address of account whose storage is to be deleted. + " in + let _ := + (* if *) + M.if_then_else (| + Compare.in_ (| + M.get_name (| globals, "address" |), + M.get_field (| M.get_name (| globals, "state" |), "_storage_tries" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.delete (| M.get_subscript (| + M.get_field (| M.get_name (| globals, "state" |), "_storage_tries" |), + M.get_name (| globals, "address" |) + |) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + M.pure Constant.None_)). + +Definition mark_account_created : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "state"; "address" ] |) in + let _ := Constant.str " + Mark an account as having been created in the current transaction. + This information is used by `get_storage_original()` to handle an obscure + edgecase. + + The marker is not removed even if the account creation reverts. Since the + account cannot have had code prior to its creation and can't call + `get_storage_original()`, this is harmless. + + Parameters + ---------- + state: `State` + The state + address : `Address` + Address of the account that has been created. + " in + let _ := M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, "state" |), "_created_accounts" |), "add" |), + make_list [ + M.get_name (| globals, "address" |) + ], + make_dict [] + |) in + M.pure Constant.None_)). + +Definition get_storage : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "state"; "address"; "key" ] |) in + let _ := Constant.str " + Get a value at a storage key on an account. Returns `U256(0)` if the + storage key has not been set previously. + + Parameters + ---------- + state: `State` + The state + address : `Address` + Address of the account. + key : `Bytes` + Key to lookup. + + Returns + ------- + value : `U256` + Value at the key. + " in + let _ := M.assign_local (| + "trie" , + M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, "state" |), "_storage_tries" |), "get" |), + make_list [ + M.get_name (| globals, "address" |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.is (| + M.get_name (| globals, "trie" |), + Constant.None_ + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "value" , + M.call (| + M.get_name (| globals, "trie_get" |), + make_list [ + M.get_name (| globals, "trie" |); + M.get_name (| globals, "key" |) + ], + make_dict [] + |) + |) in + let _ := M.assert (| M.call (| + M.get_name (| globals, "isinstance" |), + make_list [ + M.get_name (| globals, "value" |); + M.get_name (| globals, "U256" |) + ], + make_dict [] + |) |) in + let _ := M.return_ (| + M.get_name (| globals, "value" |) + |) in + M.pure Constant.None_)). + +Definition set_storage : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "state"; "address"; "key"; "value" ] |) in + let _ := Constant.str " + Set a value at a storage key on an account. Setting to `U256(0)` deletes + the key. + + Parameters + ---------- + state: `State` + The state + address : `Address` + Address of the account. + key : `Bytes` + Key to set. + value : `U256` + Value to set at the key. + " in + let _ := M.assert (| Compare.is_not (| + M.call (| + M.get_name (| globals, "trie_get" |), + make_list [ + M.get_field (| M.get_name (| globals, "state" |), "_main_trie" |); + M.get_name (| globals, "address" |) + ], + make_dict [] + |), + Constant.None_ + |) |) in + let _ := M.assign_local (| + "trie" , + M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, "state" |), "_storage_tries" |), "get" |), + make_list [ + M.get_name (| globals, "address" |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.is (| + M.get_name (| globals, "trie" |), + Constant.None_ + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "trie" , + M.call (| + M.get_name (| globals, "Trie" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.assign (| + M.get_subscript (| + M.get_field (| M.get_name (| globals, "state" |), "_storage_tries" |), + M.get_name (| globals, "address" |) + |), + M.get_name (| globals, "trie" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.call (| + M.get_name (| globals, "trie_set" |), + make_list [ + M.get_name (| globals, "trie" |); + M.get_name (| globals, "key" |); + M.get_name (| globals, "value" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_field (| M.get_name (| globals, "trie" |), "_data" |), + Constant.str "(* At expr: unsupported node type: Dict *)" + |), + (* then *) + ltac:(M.monadic ( + let _ := M.delete (| M.get_subscript (| + M.get_field (| M.get_name (| globals, "state" |), "_storage_tries" |), + M.get_name (| globals, "address" |) + |) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + M.pure Constant.None_)). + +Definition storage_root : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "state"; "address" ] |) in + let _ := Constant.str " + Calculate the storage root of an account. + + Parameters + ---------- + state: + The state + address : + Address of the account. + + Returns + ------- + root : `Root` + Storage root of the account. + " in + let _ := M.assert (| UnOp.not (| M.get_field (| M.get_name (| globals, "state" |), "_snapshots" |) |) |) in + let _ := + (* if *) + M.if_then_else (| + Compare.in_ (| + M.get_name (| globals, "address" |), + M.get_field (| M.get_name (| globals, "state" |), "_storage_tries" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + M.call (| + M.get_name (| globals, "root" |), + make_list [ + M.get_subscript (| + M.get_field (| M.get_name (| globals, "state" |), "_storage_tries" |), + M.get_name (| globals, "address" |) + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.return_ (| + M.get_name (| globals, "EMPTY_TRIE_ROOT" |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_)). + +Definition state_root : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "state" ] |) in + let _ := Constant.str " + Calculate the state root. + + Parameters + ---------- + state: + The current state. + + Returns + ------- + root : `Root` + The state root. + " in + let _ := M.assert (| UnOp.not (| M.get_field (| M.get_name (| globals, "state" |), "_snapshots" |) |) |) in +(* At stmt: unsupported node type: FunctionDef *) + let _ := M.return_ (| + M.call (| + M.get_name (| globals, "root" |), + make_list [ + M.get_field (| M.get_name (| globals, "state" |), "_main_trie" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Definition account_exists : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "state"; "address" ] |) in + let _ := Constant.str " + Checks if an account exists in the state trie + + Parameters + ---------- + state: + The state + address: + Address of the account that needs to be checked. + + Returns + ------- + account_exists : `bool` + True if account exists in the state trie, False otherwise + " in + let _ := M.return_ (| + Compare.is_not (| + M.call (| + M.get_name (| globals, "get_account_optional" |), + make_list [ + M.get_name (| globals, "state" |); + M.get_name (| globals, "address" |) + ], + make_dict [] + |), + Constant.None_ + |) + |) in + M.pure Constant.None_)). + +Definition account_has_code_or_nonce : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "state"; "address" ] |) in + let _ := Constant.str " + Checks if an account has non zero nonce or non empty code + + Parameters + ---------- + state: + The state + address: + Address of the account that needs to be checked. + + Returns + ------- + has_code_or_nonce : `bool` + True if if an account has non zero nonce or non empty code, + False otherwise. + " in + let _ := M.assign_local (| + "account" , + M.call (| + M.get_name (| globals, "get_account" |), + make_list [ + M.get_name (| globals, "state" |); + M.get_name (| globals, "address" |) + ], + make_dict [] + |) + |) in + let _ := M.return_ (| + BoolOp.or (| + Compare.not_eq (| + M.get_field (| M.get_name (| globals, "account" |), "nonce" |), + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + |), + ltac:(M.monadic ( + Compare.not_eq (| + M.get_field (| M.get_name (| globals, "account" |), "code" |), + Constant.bytes "" + |) + )) + |) + |) in + M.pure Constant.None_)). + +Definition is_account_empty : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "state"; "address" ] |) in + let _ := Constant.str " + Checks if an account has zero nonce, empty code and zero balance. + + Parameters + ---------- + state: + The state + address: + Address of the account that needs to be checked. + + Returns + ------- + is_empty : `bool` + True if if an account has zero nonce, empty code and zero balance, + False otherwise. + " in + let _ := M.assign_local (| + "account" , + M.call (| + M.get_name (| globals, "get_account" |), + make_list [ + M.get_name (| globals, "state" |); + M.get_name (| globals, "address" |) + ], + make_dict [] + |) + |) in + let _ := M.return_ (| + BoolOp.and (| + Compare.eq (| + M.get_field (| M.get_name (| globals, "account" |), "nonce" |), + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + |), + ltac:(M.monadic ( + BoolOp.and (| + Compare.eq (| + M.get_field (| M.get_name (| globals, "account" |), "code" |), + Constant.bytes "" + |), + ltac:(M.monadic ( + Compare.eq (| + M.get_field (| M.get_name (| globals, "account" |), "balance" |), + Constant.int 0 + |) + )) + |) + )) + |) + |) in + M.pure Constant.None_)). + +Definition account_exists_and_is_empty : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "state"; "address" ] |) in + let _ := Constant.str " + Checks if an account exists and has zero nonce, empty code and zero + balance. + + Parameters + ---------- + state: + The state + address: + Address of the account that needs to be checked. + + Returns + ------- + exists_and_is_empty : `bool` + True if an account exists and has zero nonce, empty code and zero + balance, False otherwise. + " in + let _ := M.assign_local (| + "account" , + M.call (| + M.get_name (| globals, "get_account_optional" |), + make_list [ + M.get_name (| globals, "state" |); + M.get_name (| globals, "address" |) + ], + make_dict [] + |) + |) in + let _ := M.return_ (| + BoolOp.and (| + Compare.is_not (| + M.get_name (| globals, "account" |), + Constant.None_ + |), + ltac:(M.monadic ( + BoolOp.and (| + Compare.eq (| + M.get_field (| M.get_name (| globals, "account" |), "nonce" |), + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + |), + ltac:(M.monadic ( + BoolOp.and (| + Compare.eq (| + M.get_field (| M.get_name (| globals, "account" |), "code" |), + Constant.bytes "" + |), + ltac:(M.monadic ( + Compare.eq (| + M.get_field (| M.get_name (| globals, "account" |), "balance" |), + Constant.int 0 + |) + )) + |) + )) + |) + )) + |) + |) in + M.pure Constant.None_)). + +Definition is_account_alive : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "state"; "address" ] |) in + let _ := Constant.str " + Check whether is an account is both in the state and non empty. + + Parameters + ---------- + state: + The state + address: + Address of the account that needs to be checked. + + Returns + ------- + is_alive : `bool` + True if the account is alive. + " in + let _ := M.assign_local (| + "account" , + M.call (| + M.get_name (| globals, "get_account_optional" |), + make_list [ + M.get_name (| globals, "state" |); + M.get_name (| globals, "address" |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.is (| + M.get_name (| globals, "account" |), + Constant.None_ + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + Constant.bool false + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.return_ (| + UnOp.not (| BoolOp.and (| + Compare.eq (| + M.get_field (| M.get_name (| globals, "account" |), "nonce" |), + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + |), + ltac:(M.monadic ( + BoolOp.and (| + Compare.eq (| + M.get_field (| M.get_name (| globals, "account" |), "code" |), + Constant.bytes "" + |), + ltac:(M.monadic ( + Compare.eq (| + M.get_field (| M.get_name (| globals, "account" |), "balance" |), + Constant.int 0 + |) + )) + |) + )) + |) |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_)). + +Definition modify_state : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "state"; "address"; "f" ] |) in + let _ := Constant.str " + Modify an `Account` in the `State`. + " in + let _ := M.call (| + M.get_name (| globals, "set_account" |), + make_list [ + M.get_name (| globals, "state" |); + M.get_name (| globals, "address" |); + M.call (| + M.get_name (| globals, "modify" |), + make_list [ + M.call (| + M.get_name (| globals, "get_account" |), + make_list [ + M.get_name (| globals, "state" |); + M.get_name (| globals, "address" |) + ], + make_dict [] + |); + M.get_name (| globals, "f" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + M.pure Constant.None_)). + +Definition move_ether : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "state"; "sender_address"; "recipient_address"; "amount" ] |) in + let _ := Constant.str " + Move funds between accounts. + " in +(* At stmt: unsupported node type: FunctionDef *) +(* At stmt: unsupported node type: FunctionDef *) + let _ := M.call (| + M.get_name (| globals, "modify_state" |), + make_list [ + M.get_name (| globals, "state" |); + M.get_name (| globals, "sender_address" |); + M.get_name (| globals, "reduce_sender_balance" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "modify_state" |), + make_list [ + M.get_name (| globals, "state" |); + M.get_name (| globals, "recipient_address" |); + M.get_name (| globals, "increase_recipient_balance" |) + ], + make_dict [] + |) in + M.pure Constant.None_)). + +Definition set_account_balance : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "state"; "address"; "amount" ] |) in + let _ := Constant.str " + Sets the balance of an account. + + Parameters + ---------- + state: + The current state. + + address: + Address of the account whose nonce needs to be incremented. + + amount: + The amount that needs to set in balance. + " in +(* At stmt: unsupported node type: FunctionDef *) + let _ := M.call (| + M.get_name (| globals, "modify_state" |), + make_list [ + M.get_name (| globals, "state" |); + M.get_name (| globals, "address" |); + M.get_name (| globals, "set_balance" |) + ], + make_dict [] + |) in + M.pure Constant.None_)). + +Definition touch_account : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "state"; "address" ] |) in + let _ := Constant.str " + Initializes an account to state. + + Parameters + ---------- + state: + The current state. + + address: + The address of the account that need to initialised. + " in + let _ := + (* if *) + M.if_then_else (| + UnOp.not (| M.call (| + M.get_name (| globals, "account_exists" |), + make_list [ + M.get_name (| globals, "state" |); + M.get_name (| globals, "address" |) + ], + make_dict [] + |) |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, "set_account" |), + make_list [ + M.get_name (| globals, "state" |); + M.get_name (| globals, "address" |); + M.get_name (| globals, "EMPTY_ACCOUNT" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + M.pure Constant.None_)). + +Definition increment_nonce : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "state"; "address" ] |) in + let _ := Constant.str " + Increments the nonce of an account. + + Parameters + ---------- + state: + The current state. + + address: + Address of the account whose nonce needs to be incremented. + " in +(* At stmt: unsupported node type: FunctionDef *) + let _ := M.call (| + M.get_name (| globals, "modify_state" |), + make_list [ + M.get_name (| globals, "state" |); + M.get_name (| globals, "address" |); + M.get_name (| globals, "increase_nonce" |) + ], + make_dict [] + |) in + M.pure Constant.None_)). + +Definition set_code : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "state"; "address"; "code" ] |) in + let _ := Constant.str " + Sets Account code. + + Parameters + ---------- + state: + The current state. + + address: + Address of the account whose code needs to be update. + + code: + The bytecode that needs to be set. + " in +(* At stmt: unsupported node type: FunctionDef *) + let _ := M.call (| + M.get_name (| globals, "modify_state" |), + make_list [ + M.get_name (| globals, "state" |); + M.get_name (| globals, "address" |); + M.get_name (| globals, "write_code" |) + ], + make_dict [] + |) in + M.pure Constant.None_)). + +Definition create_ether : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "state"; "address"; "amount" ] |) in + let _ := Constant.str " + Add newly created ether to an account. + + Parameters + ---------- + state: + The current state. + address: + Address of the account to which ether is added. + amount: + The amount of ether to be added to the account of interest. + " in +(* At stmt: unsupported node type: FunctionDef *) + let _ := M.call (| + M.get_name (| globals, "modify_state" |), + make_list [ + M.get_name (| globals, "state" |); + M.get_name (| globals, "address" |); + M.get_name (| globals, "increase_balance" |) + ], + make_dict [] + |) in + M.pure Constant.None_)). + +Definition get_storage_original : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "state"; "address"; "key" ] |) in + let _ := Constant.str " + Get the original value in a storage slot i.e. the value before the current + transaction began. This function reads the value from the snapshots taken + before executing the transaction. + + Parameters + ---------- + state: + The current state. + address: + Address of the account to read the value from. + key: + Key of the storage slot. + " in + let _ := + (* if *) + M.if_then_else (| + Compare.in_ (| + M.get_name (| globals, "address" |), + M.get_field (| M.get_name (| globals, "state" |), "_created_accounts" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign (| + make_tuple [ M.get_name (| globals, "_" |); M.get_name (| globals, "original_trie" |) ], + M.get_subscript (| + M.get_field (| M.get_name (| globals, "state" |), "_snapshots" |), + Constant.int 0 + |) + |) in + let _ := M.assign_local (| + "original_account_trie" , + M.call (| + M.get_field (| M.get_name (| globals, "original_trie" |), "get" |), + make_list [ + M.get_name (| globals, "address" |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.is (| + M.get_name (| globals, "original_account_trie" |), + Constant.None_ + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "original_value" , + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "original_value" , + M.call (| + M.get_name (| globals, "trie_get" |), + make_list [ + M.get_name (| globals, "original_account_trie" |); + M.get_name (| globals, "key" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + )) |) in + let _ := M.assert (| M.call (| + M.get_name (| globals, "isinstance" |), + make_list [ + M.get_name (| globals, "original_value" |); + M.get_name (| globals, "U256" |) + ], + make_dict [] + |) |) in + let _ := M.return_ (| + M.get_name (| globals, "original_value" |) + |) in + M.pure Constant.None_)). diff --git a/CoqOfPython/ethereum/gray_glacier/transactions.v b/CoqOfPython/ethereum/gray_glacier/transactions.v new file mode 100644 index 0000000..3fb1a1b --- /dev/null +++ b/CoqOfPython/ethereum/gray_glacier/transactions.v @@ -0,0 +1,293 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.gray_glacier.transactions". + +Definition expr_1 : Value.t := + Constant.str " +Transactions are atomic units of work created externally to Ethereum and +submitted to be executed. If Ethereum is viewed as a state machine, +transactions are the events that move between states. +". + +Axiom dataclasses_imports_dataclass : + IsImported globals "dataclasses" "dataclass". + +Axiom typing_imports_Tuple : + IsImported globals "typing" "Tuple". +Axiom typing_imports_Union : + IsImported globals "typing" "Union". + +Axiom ethereum_imports_rlp : + IsImported globals "ethereum" "rlp". + +Axiom ethereum_base_types_imports_U64 : + IsImported globals "ethereum.base_types" "U64". +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_Bytes : + IsImported globals "ethereum.base_types" "Bytes". +Axiom ethereum_base_types_imports_Bytes0 : + IsImported globals "ethereum.base_types" "Bytes0". +Axiom ethereum_base_types_imports_Bytes32 : + IsImported globals "ethereum.base_types" "Bytes32". +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". +Axiom ethereum_base_types_imports_slotted_freezable : + IsImported globals "ethereum.base_types" "slotted_freezable". + +Axiom ethereum_exceptions_imports_InvalidBlock : + IsImported globals "ethereum.exceptions" "InvalidBlock". + +Axiom ethereum_gray_glacier_fork_types_imports_Address : + IsImported globals "ethereum.gray_glacier.fork_types" "Address". + +Definition TX_BASE_COST : Value.t := M.run ltac:(M.monadic ( + Constant.int 21000 +)). + +Definition TX_DATA_COST_PER_NON_ZERO : Value.t := M.run ltac:(M.monadic ( + Constant.int 16 +)). + +Definition TX_DATA_COST_PER_ZERO : Value.t := M.run ltac:(M.monadic ( + Constant.int 4 +)). + +Definition TX_CREATE_COST : Value.t := M.run ltac:(M.monadic ( + Constant.int 32000 +)). + +Definition TX_ACCESS_LIST_ADDRESS_COST : Value.t := M.run ltac:(M.monadic ( + Constant.int 2400 +)). + +Definition TX_ACCESS_LIST_STORAGE_KEY_COST : Value.t := M.run ltac:(M.monadic ( + Constant.int 1900 +)). + +Definition LegacyTransaction : Value.t := + builtins.make_klass + [] + [ + + ] + [ + + ]. + +Definition AccessListTransaction : Value.t := + builtins.make_klass + [] + [ + + ] + [ + + ]. + +Definition FeeMarketTransaction : Value.t := + builtins.make_klass + [] + [ + + ] + [ + + ]. + +Definition Transaction : Value.t := M.run ltac:(M.monadic ( + M.get_subscript (| + M.get_name (| globals, "Union" |), + make_tuple [ M.get_name (| globals, "LegacyTransaction" |); M.get_name (| globals, "AccessListTransaction" |); M.get_name (| globals, "FeeMarketTransaction" |) ] + |) +)). + +Definition encode_transaction : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "tx" ] |) in + let _ := Constant.str " + Encode a transaction. Needed because non-legacy transactions aren't RLP. + " in + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, "isinstance" |), + make_list [ + M.get_name (| globals, "tx" |); + M.get_name (| globals, "LegacyTransaction" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + M.get_name (| globals, "tx" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, "isinstance" |), + make_list [ + M.get_name (| globals, "tx" |); + M.get_name (| globals, "AccessListTransaction" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + BinOp.add (| + Constant.bytes "01", + M.call (| + M.get_field (| M.get_name (| globals, "rlp" |), "encode" |), + make_list [ + M.get_name (| globals, "tx" |) + ], + make_dict [] + |) + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, "isinstance" |), + make_list [ + M.get_name (| globals, "tx" |); + M.get_name (| globals, "FeeMarketTransaction" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + BinOp.add (| + Constant.bytes "02", + M.call (| + M.get_field (| M.get_name (| globals, "rlp" |), "encode" |), + make_list [ + M.get_name (| globals, "tx" |) + ], + make_dict [] + |) + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.raise (| Some (M.call (| + M.get_name (| globals, "Exception" |), + make_list [ + Constant.str "(* At expr: unsupported node type: JoinedStr *)" + ], + make_dict [] + |)) |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_)). + +Definition decode_transaction : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "tx" ] |) in + let _ := Constant.str " + Decode a transaction. Needed because non-legacy transactions aren't RLP. + " in + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, "isinstance" |), + make_list [ + M.get_name (| globals, "tx" |); + M.get_name (| globals, "Bytes" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_subscript (| + M.get_name (| globals, "tx" |), + Constant.int 0 + |), + Constant.int 1 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + M.call (| + M.get_field (| M.get_name (| globals, "rlp" |), "decode_to" |), + make_list [ + M.get_name (| globals, "AccessListTransaction" |); + M.slice (| + M.get_name (| globals, "tx" |), + Constant.int 1, + Constant.None_, + Constant.None_ + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_subscript (| + M.get_name (| globals, "tx" |), + Constant.int 0 + |), + Constant.int 2 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + M.call (| + M.get_field (| M.get_name (| globals, "rlp" |), "decode_to" |), + make_list [ + M.get_name (| globals, "FeeMarketTransaction" |); + M.slice (| + M.get_name (| globals, "tx" |), + Constant.int 1, + Constant.None_, + Constant.None_ + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, "InvalidBlock" |)) |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.return_ (| + M.get_name (| globals, "tx" |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_)). diff --git a/CoqOfPython/ethereum/gray_glacier/trie.v b/CoqOfPython/ethereum/gray_glacier/trie.v new file mode 100644 index 0000000..8b795d8 --- /dev/null +++ b/CoqOfPython/ethereum/gray_glacier/trie.v @@ -0,0 +1,1595 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.gray_glacier.trie". + +Definition expr_1 : Value.t := + Constant.str " +State Trie +^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +The state trie is the structure responsible for storing +`.fork_types.Account` objects. +". + +(* At top_level_stmt: unsupported node type: Import *) + +Axiom dataclasses_imports_dataclass : + IsImported globals "dataclasses" "dataclass". +Axiom dataclasses_imports_field : + IsImported globals "dataclasses" "field". + +Axiom typing_imports_Callable : + IsImported globals "typing" "Callable". +Axiom typing_imports_Dict : + IsImported globals "typing" "Dict". +Axiom typing_imports_Generic : + IsImported globals "typing" "Generic". +Axiom typing_imports_List : + IsImported globals "typing" "List". +Axiom typing_imports_Mapping : + IsImported globals "typing" "Mapping". +Axiom typing_imports_MutableMapping : + IsImported globals "typing" "MutableMapping". +Axiom typing_imports_Optional : + IsImported globals "typing" "Optional". +Axiom typing_imports_Sequence : + IsImported globals "typing" "Sequence". +Axiom typing_imports_TypeVar : + IsImported globals "typing" "TypeVar". +Axiom typing_imports_Union : + IsImported globals "typing" "Union". +Axiom typing_imports_cast : + IsImported globals "typing" "cast". + +Axiom ethereum_arrow_glacier_imports_trie : + IsImported globals "ethereum.arrow_glacier" "trie". + +Axiom ethereum_crypto_hash_imports_keccak256 : + IsImported globals "ethereum.crypto.hash" "keccak256". + +Axiom ethereum_utils_ensure_imports_ensure : + IsImported globals "ethereum.utils.ensure" "ensure". + +Axiom ethereum_utils_hexadecimal_imports_hex_to_bytes : + IsImported globals "ethereum.utils.hexadecimal" "hex_to_bytes". + +Axiom ethereum_imports_rlp : + IsImported globals "ethereum" "rlp". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_Bytes : + IsImported globals "ethereum.base_types" "Bytes". +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". +Axiom ethereum_base_types_imports_slotted_freezable : + IsImported globals "ethereum.base_types" "slotted_freezable". + +Axiom ethereum_gray_glacier_blocks_imports_Receipt : + IsImported globals "ethereum.gray_glacier.blocks" "Receipt". + +Axiom ethereum_gray_glacier_fork_types_imports_Account : + IsImported globals "ethereum.gray_glacier.fork_types" "Account". +Axiom ethereum_gray_glacier_fork_types_imports_Address : + IsImported globals "ethereum.gray_glacier.fork_types" "Address". +Axiom ethereum_gray_glacier_fork_types_imports_Root : + IsImported globals "ethereum.gray_glacier.fork_types" "Root". +Axiom ethereum_gray_glacier_fork_types_imports_encode_account : + IsImported globals "ethereum.gray_glacier.fork_types" "encode_account". + +Axiom ethereum_gray_glacier_transactions_imports_LegacyTransaction : + IsImported globals "ethereum.gray_glacier.transactions" "LegacyTransaction". + +Definition EMPTY_TRIE_ROOT : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Root" |), + make_list [ + M.call (| + M.get_name (| globals, "hex_to_bytes" |), + make_list [ + Constant.str "56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421" + ], + make_dict [] + |) + ], + make_dict [] + |) +)). + +Definition Node : Value.t := M.run ltac:(M.monadic ( + M.get_subscript (| + M.get_name (| globals, "Union" |), + make_tuple [ M.get_name (| globals, "Account" |); M.get_name (| globals, "Bytes" |); M.get_name (| globals, "LegacyTransaction" |); M.get_name (| globals, "Receipt" |); M.get_name (| globals, "Uint" |); M.get_name (| globals, "U256" |); Constant.None_ ] + |) +)). + +Definition K : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "TypeVar" |), + make_list [ + Constant.str "K" + ], + make_dict [] + |) +)). + +Definition V : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "TypeVar" |), + make_list [ + Constant.str "V"; + M.get_subscript (| + M.get_name (| globals, "Optional" |), + M.get_name (| globals, "Account" |) + |); + M.get_subscript (| + M.get_name (| globals, "Optional" |), + M.get_name (| globals, "Bytes" |) + |); + M.get_name (| globals, "Bytes" |); + M.get_subscript (| + M.get_name (| globals, "Optional" |), + M.get_subscript (| + M.get_name (| globals, "Union" |), + make_tuple [ M.get_name (| globals, "LegacyTransaction" |); M.get_name (| globals, "Bytes" |) ] + |) + |); + M.get_subscript (| + M.get_name (| globals, "Optional" |), + M.get_subscript (| + M.get_name (| globals, "Union" |), + make_tuple [ M.get_name (| globals, "Receipt" |); M.get_name (| globals, "Bytes" |) ] + |) + |); + M.get_name (| globals, "Uint" |); + M.get_name (| globals, "U256" |) + ], + make_dict [] + |) +)). + +Definition LeafNode : Value.t := + builtins.make_klass + [] + [ + + ] + [ + + ]. + +Definition ExtensionNode : Value.t := + builtins.make_klass + [] + [ + + ] + [ + + ]. + +Definition BranchNode : Value.t := + builtins.make_klass + [] + [ + + ] + [ + + ]. + +Definition InternalNode : Value.t := M.run ltac:(M.monadic ( + M.get_subscript (| + M.get_name (| globals, "Union" |), + make_tuple [ M.get_name (| globals, "LeafNode" |); M.get_name (| globals, "ExtensionNode" |); M.get_name (| globals, "BranchNode" |) ] + |) +)). + +Definition encode_internal_node : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "node" ] |) in + let _ := Constant.str " + Encodes a Merkle Trie node into its RLP form. The RLP will then be + serialized into a `Bytes` and hashed unless it is less that 32 bytes + when serialized. + + This function also accepts `None`, representing the absence of a node, + which is encoded to `b""""`. + + Parameters + ---------- + node : Optional[InternalNode] + The node to encode. + + Returns + ------- + encoded : `rlp.RLP` + The node encoded as RLP. + " in +(* At stmt: unsupported node type: AnnAssign *) + let _ := + (* if *) + M.if_then_else (| + Compare.is (| + M.get_name (| globals, "node" |), + Constant.None_ + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "unencoded" , + Constant.bytes "" + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, "isinstance" |), + make_list [ + M.get_name (| globals, "node" |); + M.get_name (| globals, "LeafNode" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "unencoded" , + make_tuple [ M.call (| + M.get_name (| globals, "nibble_list_to_compact" |), + make_list [ + M.get_field (| M.get_name (| globals, "node" |), "rest_of_key" |); + Constant.bool true + ], + make_dict [] + |); M.get_field (| M.get_name (| globals, "node" |), "value" |) ] + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, "isinstance" |), + make_list [ + M.get_name (| globals, "node" |); + M.get_name (| globals, "ExtensionNode" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "unencoded" , + make_tuple [ M.call (| + M.get_name (| globals, "nibble_list_to_compact" |), + make_list [ + M.get_field (| M.get_name (| globals, "node" |), "key_segment" |); + Constant.bool false + ], + make_dict [] + |); M.get_field (| M.get_name (| globals, "node" |), "subnode" |) ] + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, "isinstance" |), + make_list [ + M.get_name (| globals, "node" |); + M.get_name (| globals, "BranchNode" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "unencoded" , + BinOp.add (| + M.get_field (| M.get_name (| globals, "node" |), "subnodes" |), + make_list [ + M.get_field (| M.get_name (| globals, "node" |), "value" |) + ] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.raise (| Some (M.call (| + M.get_name (| globals, "AssertionError" |), + make_list [ + Constant.str "(* At expr: unsupported node type: JoinedStr *)" + ], + make_dict [] + |)) |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "encoded" , + M.call (| + M.get_field (| M.get_name (| globals, "rlp" |), "encode" |), + make_list [ + M.get_name (| globals, "unencoded" |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.lt (| + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_name (| globals, "encoded" |) + ], + make_dict [] + |), + Constant.int 32 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + M.get_name (| globals, "unencoded" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.return_ (| + M.call (| + M.get_name (| globals, "keccak256" |), + make_list [ + M.get_name (| globals, "encoded" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_)). + +Definition encode_node : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "node"; "storage_root" ] |) in + let _ := Constant.str " + Encode a Node for storage in the Merkle Trie. + + Currently mostly an unimplemented stub. + " in + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, "isinstance" |), + make_list [ + M.get_name (| globals, "node" |); + M.get_name (| globals, "Account" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assert (| Compare.is_not (| + M.get_name (| globals, "storage_root" |), + Constant.None_ + |) |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, "encode_account" |), + make_list [ + M.get_name (| globals, "node" |); + M.get_name (| globals, "storage_root" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, "isinstance" |), + make_list [ + M.get_name (| globals, "node" |); + make_tuple [ M.get_name (| globals, "LegacyTransaction" |); M.get_name (| globals, "Receipt" |); M.get_name (| globals, "U256" |) ] + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + M.call (| + M.get_field (| M.get_name (| globals, "rlp" |), "encode" |), + make_list [ + M.call (| + M.get_name (| globals, "cast" |), + make_list [ + M.get_field (| M.get_name (| globals, "rlp" |), "RLP" |); + M.get_name (| globals, "node" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, "isinstance" |), + make_list [ + M.get_name (| globals, "node" |); + M.get_name (| globals, "Bytes" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + M.get_name (| globals, "node" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.return_ (| + M.call (| + M.get_field (| M.get_name (| globals, "previous_trie" |), "encode_node" |), + make_list [ + M.get_name (| globals, "node" |); + M.get_name (| globals, "storage_root" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_)). + +Definition Trie : Value.t := + builtins.make_klass + [(* At base: unsupported node type: Subscript *)] + [ + + ] + [ + + ]. + +Definition copy_trie : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "trie" ] |) in + let _ := Constant.str " + Create a copy of `trie`. Since only frozen objects may be stored in tries, + the contents are reused. + + Parameters + ---------- + trie: `Trie` + Trie to copy. + + Returns + ------- + new_trie : `Trie[K, V]` + A copy of the trie. + " in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, "Trie" |), + make_list [ + M.get_field (| M.get_name (| globals, "trie" |), "secured" |); + M.get_field (| M.get_name (| globals, "trie" |), "default" |); + M.call (| + M.get_field (| M.get_name (| globals, "copy" |), "copy" |), + make_list [ + M.get_field (| M.get_name (| globals, "trie" |), "_data" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Definition trie_set : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "trie"; "key"; "value" ] |) in + let _ := Constant.str " + Stores an item in a Merkle Trie. + + This method deletes the key if `value == trie.default`, because the Merkle + Trie represents the default value by omitting it from the trie. + + Parameters + ---------- + trie: `Trie` + Trie to store in. + key : `Bytes` + Key to lookup. + value : `V` + Node to insert at `key`. + " in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, "value" |), + M.get_field (| M.get_name (| globals, "trie" |), "default" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + Compare.in_ (| + M.get_name (| globals, "key" |), + M.get_field (| M.get_name (| globals, "trie" |), "_data" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.delete (| M.get_subscript (| + M.get_field (| M.get_name (| globals, "trie" |), "_data" |), + M.get_name (| globals, "key" |) + |) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign (| + M.get_subscript (| + M.get_field (| M.get_name (| globals, "trie" |), "_data" |), + M.get_name (| globals, "key" |) + |), + M.get_name (| globals, "value" |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_)). + +Definition trie_get : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "trie"; "key" ] |) in + let _ := Constant.str " + Gets an item from the Merkle Trie. + + This method returns `trie.default` if the key is missing. + + Parameters + ---------- + trie: + Trie to lookup in. + key : + Key to lookup. + + Returns + ------- + node : `V` + Node at `key` in the trie. + " in + let _ := M.return_ (| + M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, "trie" |), "_data" |), "get" |), + make_list [ + M.get_name (| globals, "key" |); + M.get_field (| M.get_name (| globals, "trie" |), "default" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Definition common_prefix_length : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "a"; "b" ] |) in + let _ := Constant.str " + Find the longest common prefix of two sequences. + " in + let _ := + M.for_ (| + M.get_name (| globals, "i" |), + M.call (| + M.get_name (| globals, "range" |), + make_list [ + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_name (| globals, "a" |) + ], + make_dict [] + |) + ], + make_dict [] + |), + ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + BoolOp.or (| + Compare.gt_e (| + M.get_name (| globals, "i" |), + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_name (| globals, "b" |) + ], + make_dict [] + |) + |), + ltac:(M.monadic ( + Compare.not_eq (| + M.get_subscript (| + M.get_name (| globals, "a" |), + M.get_name (| globals, "i" |) + |), + M.get_subscript (| + M.get_name (| globals, "b" |), + M.get_name (| globals, "i" |) + |) + |) + )) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + M.get_name (| globals, "i" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_name (| globals, "a" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Definition nibble_list_to_compact : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "x"; "is_leaf" ] |) in + let _ := Constant.str " + Compresses nibble-list into a standard byte array with a flag. + + A nibble-list is a list of byte values no greater than `15`. The flag is + encoded in high nibble of the highest byte. The flag nibble can be broken + down into two two-bit flags. + + Highest nibble:: + + +---+---+----------+--------+ + | _ | _ | is_leaf | parity | + +---+---+----------+--------+ + 3 2 1 0 + + + The lowest bit of the nibble encodes the parity of the length of the + remaining nibbles -- `0` when even and `1` when odd. The second lowest bit + is used to distinguish leaf and extension nodes. The other two bits are not + used. + + Parameters + ---------- + x : + Array of nibbles. + is_leaf : + True if this is part of a leaf node, or false if it is an extension + node. + + Returns + ------- + compressed : `bytearray` + Compact byte array. + " in + let _ := M.assign_local (| + "compact" , + M.call (| + M.get_name (| globals, "bytearray" |), + make_list [], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + BinOp.mod_ (| + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_name (| globals, "x" |) + ], + make_dict [] + |), + Constant.int 2 + |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_field (| M.get_name (| globals, "compact" |), "append" |), + make_list [ + BinOp.mult (| + Constant.int 16, + BinOp.mult (| + Constant.int 2, + M.get_name (| globals, "is_leaf" |) + |) + |) + ], + make_dict [] + |) in + let _ := + M.for_ (| + M.get_name (| globals, "i" |), + M.call (| + M.get_name (| globals, "range" |), + make_list [ + Constant.int 0; + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_name (| globals, "x" |) + ], + make_dict [] + |); + Constant.int 2 + ], + make_dict [] + |), + ltac:(M.monadic ( + let _ := M.call (| + M.get_field (| M.get_name (| globals, "compact" |), "append" |), + make_list [ + BinOp.add (| + BinOp.mult (| + Constant.int 16, + M.get_subscript (| + M.get_name (| globals, "x" |), + M.get_name (| globals, "i" |) + |) + |), + M.get_subscript (| + M.get_name (| globals, "x" |), + BinOp.add (| + M.get_name (| globals, "i" |), + Constant.int 1 + |) + |) + |) + ], + make_dict [] + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.call (| + M.get_field (| M.get_name (| globals, "compact" |), "append" |), + make_list [ + BinOp.add (| + BinOp.mult (| + Constant.int 16, + BinOp.add (| + BinOp.mult (| + Constant.int 2, + M.get_name (| globals, "is_leaf" |) + |), + Constant.int 1 + |) + |), + M.get_subscript (| + M.get_name (| globals, "x" |), + Constant.int 0 + |) + |) + ], + make_dict [] + |) in + let _ := + M.for_ (| + M.get_name (| globals, "i" |), + M.call (| + M.get_name (| globals, "range" |), + make_list [ + Constant.int 1; + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_name (| globals, "x" |) + ], + make_dict [] + |); + Constant.int 2 + ], + make_dict [] + |), + ltac:(M.monadic ( + let _ := M.call (| + M.get_field (| M.get_name (| globals, "compact" |), "append" |), + make_list [ + BinOp.add (| + BinOp.mult (| + Constant.int 16, + M.get_subscript (| + M.get_name (| globals, "x" |), + M.get_name (| globals, "i" |) + |) + |), + M.get_subscript (| + M.get_name (| globals, "x" |), + BinOp.add (| + M.get_name (| globals, "i" |), + Constant.int 1 + |) + |) + |) + ], + make_dict [] + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + M.pure Constant.None_ + )) |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, "Bytes" |), + make_list [ + M.get_name (| globals, "compact" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Definition bytes_to_nibble_list : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "bytes_" ] |) in + let _ := Constant.str " + Converts a `Bytes` into to a sequence of nibbles (bytes with value < 16). + + Parameters + ---------- + bytes_: + The `Bytes` to convert. + + Returns + ------- + nibble_list : `Bytes` + The `Bytes` in nibble-list format. + " in + let _ := M.assign_local (| + "nibble_list" , + M.call (| + M.get_name (| globals, "bytearray" |), + make_list [ + BinOp.mult (| + Constant.int 2, + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_name (| globals, "bytes_" |) + ], + make_dict [] + |) + |) + ], + make_dict [] + |) + |) in + let _ := + M.for_ (| + make_tuple [ M.get_name (| globals, "byte_index" |); M.get_name (| globals, "byte" |) ], + M.call (| + M.get_name (| globals, "enumerate" |), + make_list [ + M.get_name (| globals, "bytes_" |) + ], + make_dict [] + |), + ltac:(M.monadic ( + let _ := M.assign (| + M.get_subscript (| + M.get_name (| globals, "nibble_list" |), + BinOp.mult (| + M.get_name (| globals, "byte_index" |), + Constant.int 2 + |) + |), + BinOp.r_shift (| + BinOp.bit_and (| + M.get_name (| globals, "byte" |), + Constant.int 240 + |), + Constant.int 4 + |) + |) in + let _ := M.assign (| + M.get_subscript (| + M.get_name (| globals, "nibble_list" |), + BinOp.add (| + BinOp.mult (| + M.get_name (| globals, "byte_index" |), + Constant.int 2 + |), + Constant.int 1 + |) + |), + BinOp.bit_and (| + M.get_name (| globals, "byte" |), + Constant.int 15 + |) + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, "Bytes" |), + make_list [ + M.get_name (| globals, "nibble_list" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Definition _prepare_trie : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "trie"; "get_storage_root" ] |) in + let _ := Constant.str " + Prepares the trie for root calculation. Removes values that are empty, + hashes the keys (if `secured == True`) and encodes all the nodes. + + Parameters + ---------- + trie : + The `Trie` to prepare. + get_storage_root : + Function to get the storage root of an account. Needed to encode + `Account` objects. + + Returns + ------- + out : `Mapping[ethereum.base_types.Bytes, Node]` + Object with keys mapped to nibble-byte form. + " in +(* At stmt: unsupported node type: AnnAssign *) + let _ := + M.for_ (| + make_tuple [ M.get_name (| globals, "preimage" |); M.get_name (| globals, "value" |) ], + M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, "trie" |), "_data" |), "items" |), + make_list [], + make_dict [] + |), + ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, "isinstance" |), + make_list [ + M.get_name (| globals, "value" |); + M.get_name (| globals, "Account" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assert (| Compare.is_not (| + M.get_name (| globals, "get_storage_root" |), + Constant.None_ + |) |) in + let _ := M.assign_local (| + "address" , + M.call (| + M.get_name (| globals, "Address" |), + make_list [ + M.get_name (| globals, "preimage" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "encoded_value" , + M.call (| + M.get_name (| globals, "encode_node" |), + make_list [ + M.get_name (| globals, "value" |); + M.call (| + M.get_name (| globals, "get_storage_root" |), + make_list [ + M.get_name (| globals, "address" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "encoded_value" , + M.call (| + M.get_name (| globals, "encode_node" |), + make_list [ + M.get_name (| globals, "value" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + )) |) in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + Compare.not_eq (| + M.get_name (| globals, "encoded_value" |), + Constant.bytes "" + |); + M.get_name (| globals, "AssertionError" |) + ], + make_dict [] + |) in +(* At stmt: unsupported node type: AnnAssign *) + let _ := + (* if *) + M.if_then_else (| + M.get_field (| M.get_name (| globals, "trie" |), "secured" |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "key" , + M.call (| + M.get_name (| globals, "keccak256" |), + make_list [ + M.get_name (| globals, "preimage" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "key" , + M.get_name (| globals, "preimage" |) + |) in + M.pure Constant.None_ + )) |) in + let _ := M.assign (| + M.get_subscript (| + M.get_name (| globals, "mapped" |), + M.call (| + M.get_name (| globals, "bytes_to_nibble_list" |), + make_list [ + M.get_name (| globals, "key" |) + ], + make_dict [] + |) + |), + M.get_name (| globals, "encoded_value" |) + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := M.return_ (| + M.get_name (| globals, "mapped" |) + |) in + M.pure Constant.None_)). + +Definition root : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "trie"; "get_storage_root" ] |) in + let _ := Constant.str " + Computes the root of a modified merkle patricia trie (MPT). + + Parameters + ---------- + trie : + `Trie` to get the root of. + get_storage_root : + Function to get the storage root of an account. Needed to encode + `Account` objects. + + + Returns + ------- + root : `.fork_types.Root` + MPT root of the underlying key-value pairs. + " in + let _ := M.assign_local (| + "obj" , + M.call (| + M.get_name (| globals, "_prepare_trie" |), + make_list [ + M.get_name (| globals, "trie" |); + M.get_name (| globals, "get_storage_root" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "root_node" , + M.call (| + M.get_name (| globals, "encode_internal_node" |), + make_list [ + M.call (| + M.get_name (| globals, "patricialize" |), + make_list [ + M.get_name (| globals, "obj" |); + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.lt (| + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.call (| + M.get_field (| M.get_name (| globals, "rlp" |), "encode" |), + make_list [ + M.get_name (| globals, "root_node" |) + ], + make_dict [] + |) + ], + make_dict [] + |), + Constant.int 32 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + M.call (| + M.get_name (| globals, "keccak256" |), + make_list [ + M.call (| + M.get_field (| M.get_name (| globals, "rlp" |), "encode" |), + make_list [ + M.get_name (| globals, "root_node" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assert (| M.call (| + M.get_name (| globals, "isinstance" |), + make_list [ + M.get_name (| globals, "root_node" |); + M.get_name (| globals, "Bytes" |) + ], + make_dict [] + |) |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, "Root" |), + make_list [ + M.get_name (| globals, "root_node" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_)). + +Definition patricialize : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "obj"; "level" ] |) in + let _ := Constant.str " + Structural composition function. + + Used to recursively patricialize and merkleize a dictionary. Includes + memoization of the tree structure and hashes. + + Parameters + ---------- + obj : + Underlying trie key-value pairs, with keys in nibble-list format. + level : + Current trie level. + + Returns + ------- + node : `ethereum.base_types.Bytes` + Root node of `obj`. + " in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_name (| globals, "obj" |) + ], + make_dict [] + |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + Constant.None_ + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "arbitrary_key" , + M.call (| + M.get_name (| globals, "next" |), + make_list [ + M.call (| + M.get_name (| globals, "iter" |), + make_list [ + M.get_name (| globals, "obj" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_name (| globals, "obj" |) + ], + make_dict [] + |), + Constant.int 1 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "leaf" , + M.call (| + M.get_name (| globals, "LeafNode" |), + make_list [ + M.slice (| + M.get_name (| globals, "arbitrary_key" |), + M.get_name (| globals, "level" |), + Constant.None_, + Constant.None_ + |); + M.get_subscript (| + M.get_name (| globals, "obj" |), + M.get_name (| globals, "arbitrary_key" |) + |) + ], + make_dict [] + |) + |) in + let _ := M.return_ (| + M.get_name (| globals, "leaf" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "substring" , + M.slice (| + M.get_name (| globals, "arbitrary_key" |), + M.get_name (| globals, "level" |), + Constant.None_, + Constant.None_ + |) + |) in + let _ := M.assign_local (| + "prefix_length" , + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_name (| globals, "substring" |) + ], + make_dict [] + |) + |) in + let _ := + M.for_ (| + M.get_name (| globals, "key" |), + M.get_name (| globals, "obj" |), + ltac:(M.monadic ( + let _ := M.assign_local (| + "prefix_length" , + M.call (| + M.get_name (| globals, "min" |), + make_list [ + M.get_name (| globals, "prefix_length" |); + M.call (| + M.get_name (| globals, "common_prefix_length" |), + make_list [ + M.get_name (| globals, "substring" |); + M.slice (| + M.get_name (| globals, "key" |), + M.get_name (| globals, "level" |), + Constant.None_, + Constant.None_ + |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, "prefix_length" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.break (| |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.gt (| + M.get_name (| globals, "prefix_length" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "prefix" , + M.slice (| + M.get_name (| globals, "arbitrary_key" |), + M.get_name (| globals, "level" |), + BinOp.add (| + M.get_name (| globals, "level" |), + M.get_name (| globals, "prefix_length" |) + |), + Constant.None_ + |) + |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, "ExtensionNode" |), + make_list [ + M.get_name (| globals, "prefix" |); + M.call (| + M.get_name (| globals, "encode_internal_node" |), + make_list [ + M.call (| + M.get_name (| globals, "patricialize" |), + make_list [ + M.get_name (| globals, "obj" |); + BinOp.add (| + M.get_name (| globals, "level" |), + M.get_name (| globals, "prefix_length" |) + |) + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in +(* At stmt: unsupported node type: AnnAssign *) + let _ := + M.for_ (| + M.get_name (| globals, "_" |), + M.call (| + M.get_name (| globals, "range" |), + make_list [ + Constant.int 16 + ], + make_dict [] + |), + ltac:(M.monadic ( + let _ := M.call (| + M.get_field (| M.get_name (| globals, "branches" |), "append" |), + make_list [ + Constant.str "(* At expr: unsupported node type: Dict *)" + ], + make_dict [] + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := M.assign_local (| + "value" , + Constant.bytes "" + |) in + let _ := + M.for_ (| + M.get_name (| globals, "key" |), + M.get_name (| globals, "obj" |), + ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_name (| globals, "key" |) + ], + make_dict [] + |), + M.get_name (| globals, "level" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, "isinstance" |), + make_list [ + M.get_subscript (| + M.get_name (| globals, "obj" |), + M.get_name (| globals, "key" |) + |); + make_tuple [ M.get_name (| globals, "Account" |); M.get_name (| globals, "Receipt" |); M.get_name (| globals, "Uint" |) ] + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, "AssertionError" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "value" , + M.get_subscript (| + M.get_name (| globals, "obj" |), + M.get_name (| globals, "key" |) + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign (| + M.get_subscript (| + M.get_subscript (| + M.get_name (| globals, "branches" |), + M.get_subscript (| + M.get_name (| globals, "key" |), + M.get_name (| globals, "level" |) + |) + |), + M.get_name (| globals, "key" |) + |), + M.get_subscript (| + M.get_name (| globals, "obj" |), + M.get_name (| globals, "key" |) + |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, "BranchNode" |), + make_list [ + Constant.str "(* At expr: unsupported node type: ListComp *)"; + M.get_name (| globals, "value" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). diff --git a/CoqOfPython/ethereum/gray_glacier/utils/__init__.v b/CoqOfPython/ethereum/gray_glacier/utils/__init__.v new file mode 100644 index 0000000..180ce26 --- /dev/null +++ b/CoqOfPython/ethereum/gray_glacier/utils/__init__.v @@ -0,0 +1,8 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.gray_glacier.utils.__init__". + +Definition expr_1 : Value.t := + Constant.str " +Utility functions unique to this particular fork. +". diff --git a/CoqOfPython/ethereum/gray_glacier/utils/address.v b/CoqOfPython/ethereum/gray_glacier/utils/address.v new file mode 100644 index 0000000..a7dbc7d --- /dev/null +++ b/CoqOfPython/ethereum/gray_glacier/utils/address.v @@ -0,0 +1,227 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.gray_glacier.utils.address". + +Definition expr_1 : Value.t := + Constant.str " +Hardfork Utility Functions For Addresses +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Address specific functions used in this gray_glacier version of +specification. +". + +Axiom typing_imports_Union : + IsImported globals "typing" "Union". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_Bytes32 : + IsImported globals "ethereum.base_types" "Bytes32". +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". + +Axiom ethereum_crypto_hash_imports_keccak256 : + IsImported globals "ethereum.crypto.hash" "keccak256". + +Axiom ethereum_utils_byte_imports_left_pad_zero_bytes : + IsImported globals "ethereum.utils.byte" "left_pad_zero_bytes". + +Axiom ethereum_imports_rlp : + IsImported globals "ethereum" "rlp". + +Axiom ethereum_gray_glacier_fork_types_imports_Address : + IsImported globals "ethereum.gray_glacier.fork_types" "Address". + +Definition to_address : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "data" ] |) in + let _ := Constant.str " + Convert a Uint or U256 value to a valid address (20 bytes). + + Parameters + ---------- + data : + The string to be converted to bytes. + + Returns + ------- + address : `Address` + The obtained address. + " in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, "Address" |), + make_list [ + M.slice (| + M.call (| + M.get_field (| M.get_name (| globals, "data" |), "to_be_bytes32" |), + make_list [], + make_dict [] + |), + UnOp.sub (| Constant.int 20 |), + Constant.None_, + Constant.None_ + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Definition compute_contract_address : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "address"; "nonce" ] |) in + let _ := Constant.str " + Computes address of the new account that needs to be created. + + Parameters + ---------- + address : + The address of the account that wants to create the new account. + nonce : + The transaction count of the account that wants to create the new + account. + + Returns + ------- + address: `Address` + The computed address of the new account. + " in + let _ := M.assign_local (| + "computed_address" , + M.call (| + M.get_name (| globals, "keccak256" |), + make_list [ + M.call (| + M.get_field (| M.get_name (| globals, "rlp" |), "encode" |), + make_list [ + make_list [ + M.get_name (| globals, "address" |); + M.get_name (| globals, "nonce" |) + ] + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "canonical_address" , + M.slice (| + M.get_name (| globals, "computed_address" |), + UnOp.sub (| Constant.int 20 |), + Constant.None_, + Constant.None_ + |) + |) in + let _ := M.assign_local (| + "padded_address" , + M.call (| + M.get_name (| globals, "left_pad_zero_bytes" |), + make_list [ + M.get_name (| globals, "canonical_address" |); + Constant.int 20 + ], + make_dict [] + |) + |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, "Address" |), + make_list [ + M.get_name (| globals, "padded_address" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Definition compute_create2_contract_address : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "address"; "salt"; "call_data" ] |) in + let _ := Constant.str " + Computes address of the new account that needs to be created, which is + based on the sender address, salt and the call data as well. + + Parameters + ---------- + address : + The address of the account that wants to create the new account. + salt : + Address generation salt. + call_data : + The code of the new account which is to be created. + + Returns + ------- + address: `ethereum.gray_glacier.fork_types.Address` + The computed address of the new account. + " in + let _ := M.assign_local (| + "preimage" , + BinOp.add (| + BinOp.add (| + BinOp.add (| + Constant.bytes "ff", + M.get_name (| globals, "address" |) + |), + M.get_name (| globals, "salt" |) + |), + M.call (| + M.get_name (| globals, "keccak256" |), + make_list [ + M.get_name (| globals, "call_data" |) + ], + make_dict [] + |) + |) + |) in + let _ := M.assign_local (| + "computed_address" , + M.call (| + M.get_name (| globals, "keccak256" |), + make_list [ + M.get_name (| globals, "preimage" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "canonical_address" , + M.slice (| + M.get_name (| globals, "computed_address" |), + UnOp.sub (| Constant.int 20 |), + Constant.None_, + Constant.None_ + |) + |) in + let _ := M.assign_local (| + "padded_address" , + M.call (| + M.get_name (| globals, "left_pad_zero_bytes" |), + make_list [ + M.get_name (| globals, "canonical_address" |); + Constant.int 20 + ], + make_dict [] + |) + |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, "Address" |), + make_list [ + M.get_name (| globals, "padded_address" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). diff --git a/CoqOfPython/ethereum/gray_glacier/utils/hexadecimal.v b/CoqOfPython/ethereum/gray_glacier/utils/hexadecimal.v new file mode 100644 index 0000000..3ad2857 --- /dev/null +++ b/CoqOfPython/ethereum/gray_glacier/utils/hexadecimal.v @@ -0,0 +1,153 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.gray_glacier.utils.hexadecimal". + +Definition expr_1 : Value.t := + Constant.str " +Utility Functions For Hexadecimal Strings +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Hexadecimal utility functions used in this specification, specific to +Gray Glacier types. +". + +Axiom ethereum_utils_hexadecimal_imports_remove_hex_prefix : + IsImported globals "ethereum.utils.hexadecimal" "remove_hex_prefix". + +Axiom ethereum_gray_glacier_fork_types_imports_Address : + IsImported globals "ethereum.gray_glacier.fork_types" "Address". +Axiom ethereum_gray_glacier_fork_types_imports_Bloom : + IsImported globals "ethereum.gray_glacier.fork_types" "Bloom". +Axiom ethereum_gray_glacier_fork_types_imports_Root : + IsImported globals "ethereum.gray_glacier.fork_types" "Root". + +Definition hex_to_root : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "hex_string" ] |) in + let _ := Constant.str " + Convert hex string to trie root. + + Parameters + ---------- + hex_string : + The hexadecimal string to be converted to trie root. + + Returns + ------- + root : `Root` + Trie root obtained from the given hexadecimal string. + " in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, "Root" |), + make_list [ + M.call (| + M.get_field (| M.get_name (| globals, "bytes" |), "fromhex" |), + make_list [ + M.call (| + M.get_name (| globals, "remove_hex_prefix" |), + make_list [ + M.get_name (| globals, "hex_string" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Definition hex_to_bloom : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "hex_string" ] |) in + let _ := Constant.str " + Convert hex string to bloom. + + Parameters + ---------- + hex_string : + The hexadecimal string to be converted to bloom. + + Returns + ------- + bloom : `Bloom` + Bloom obtained from the given hexadecimal string. + " in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, "Bloom" |), + make_list [ + M.call (| + M.get_field (| M.get_name (| globals, "bytes" |), "fromhex" |), + make_list [ + M.call (| + M.get_name (| globals, "remove_hex_prefix" |), + make_list [ + M.get_name (| globals, "hex_string" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Definition hex_to_address : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "hex_string" ] |) in + let _ := Constant.str " + Convert hex string to Address (20 bytes). + + Parameters + ---------- + hex_string : + The hexadecimal string to be converted to Address. + + Returns + ------- + address : `Address` + The address obtained from the given hexadecimal string. + " in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, "Address" |), + make_list [ + M.call (| + M.get_field (| M.get_name (| globals, "bytes" |), "fromhex" |), + make_list [ + M.call (| + M.get_field (| M.call (| + M.get_name (| globals, "remove_hex_prefix" |), + make_list [ + M.get_name (| globals, "hex_string" |) + ], + make_dict [] + |), "rjust" |), + make_list [ + Constant.int 40; + Constant.str "0" + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). diff --git a/CoqOfPython/ethereum/gray_glacier/utils/message.v b/CoqOfPython/ethereum/gray_glacier/utils/message.v new file mode 100644 index 0000000..c2728e8 --- /dev/null +++ b/CoqOfPython/ethereum/gray_glacier/utils/message.v @@ -0,0 +1,266 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.gray_glacier.utils.message". + +Definition expr_1 : Value.t := + Constant.str " +Hardfork Utility Functions For The Message Data-structure +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Message specific functions used in this gray_glacier version of +specification. +". + +Axiom typing_imports_FrozenSet : + IsImported globals "typing" "FrozenSet". +Axiom typing_imports_Optional : + IsImported globals "typing" "Optional". +Axiom typing_imports_Tuple : + IsImported globals "typing" "Tuple". +Axiom typing_imports_Union : + IsImported globals "typing" "Union". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_Bytes : + IsImported globals "ethereum.base_types" "Bytes". +Axiom ethereum_base_types_imports_Bytes0 : + IsImported globals "ethereum.base_types" "Bytes0". +Axiom ethereum_base_types_imports_Bytes32 : + IsImported globals "ethereum.base_types" "Bytes32". +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". + +Axiom ethereum_gray_glacier_fork_types_imports_Address : + IsImported globals "ethereum.gray_glacier.fork_types" "Address". + +Axiom ethereum_gray_glacier_state_imports_get_account : + IsImported globals "ethereum.gray_glacier.state" "get_account". + +Axiom ethereum_gray_glacier_vm_imports_Environment : + IsImported globals "ethereum.gray_glacier.vm" "Environment". +Axiom ethereum_gray_glacier_vm_imports_Message : + IsImported globals "ethereum.gray_glacier.vm" "Message". + +Axiom ethereum_gray_glacier_vm_precompiled_contracts_mapping_imports_PRE_COMPILED_CONTRACTS : + IsImported globals "ethereum.gray_glacier.vm.precompiled_contracts.mapping" "PRE_COMPILED_CONTRACTS". + +Axiom ethereum_gray_glacier_utils_address_imports_compute_contract_address : + IsImported globals "ethereum.gray_glacier.utils.address" "compute_contract_address". + +Definition prepare_message : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "caller"; "target"; "value"; "data"; "gas"; "env"; "code_address"; "should_transfer_value"; "is_static"; "preaccessed_addresses"; "preaccessed_storage_keys" ] |) in + let _ := Constant.str " + Execute a transaction against the provided environment. + + Parameters + ---------- + caller : + Address which initiated the transaction + target : + Address whose code will be executed + value : + Value to be transferred. + data : + Array of bytes provided to the code in `target`. + gas : + Gas provided for the code in `target`. + env : + Environment for the Ethereum Virtual Machine. + code_address : + This is usually same as the `target` address except when an alternative + accounts code needs to be executed. + eg. `CALLCODE` calling a precompile. + should_transfer_value : + if True ETH should be transferred while executing a message call. + is_static: + if True then it prevents all state-changing operations from being + executed. + preaccessed_addresses: + Addresses that should be marked as accessed prior to the message call + preaccessed_storage_keys: + Storage keys that should be marked as accessed prior to the message + call + + Returns + ------- + message: `ethereum.gray_glacier.vm.Message` + Items containing contract creation or message call specific data. + " in + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, "isinstance" |), + make_list [ + M.get_name (| globals, "target" |); + M.get_name (| globals, "Bytes0" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "current_target" , + M.call (| + M.get_name (| globals, "compute_contract_address" |), + make_list [ + M.get_name (| globals, "caller" |); + BinOp.sub (| + M.get_field (| M.call (| + M.get_name (| globals, "get_account" |), + make_list [ + M.get_field (| M.get_name (| globals, "env" |), "state" |); + M.get_name (| globals, "caller" |) + ], + make_dict [] + |), "nonce" |), + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 1 + ], + make_dict [] + |) + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "msg_data" , + M.call (| + M.get_name (| globals, "Bytes" |), + make_list [ + Constant.bytes "" + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "code" , + M.get_name (| globals, "data" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, "isinstance" |), + make_list [ + M.get_name (| globals, "target" |); + M.get_name (| globals, "Address" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "current_target" , + M.get_name (| globals, "target" |) + |) in + let _ := M.assign_local (| + "msg_data" , + M.get_name (| globals, "data" |) + |) in + let _ := M.assign_local (| + "code" , + M.get_field (| M.call (| + M.get_name (| globals, "get_account" |), + make_list [ + M.get_field (| M.get_name (| globals, "env" |), "state" |); + M.get_name (| globals, "target" |) + ], + make_dict [] + |), "code" |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.is (| + M.get_name (| globals, "code_address" |), + Constant.None_ + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "code_address" , + M.get_name (| globals, "target" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.raise (| Some (M.call (| + M.get_name (| globals, "AssertionError" |), + make_list [ + Constant.str "Target must be address or empty bytes" + ], + make_dict [] + |)) |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "accessed_addresses" , + M.call (| + M.get_name (| globals, "set" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_field (| M.get_name (| globals, "accessed_addresses" |), "add" |), + make_list [ + M.get_name (| globals, "current_target" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_field (| M.get_name (| globals, "accessed_addresses" |), "add" |), + make_list [ + M.get_name (| globals, "caller" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_field (| M.get_name (| globals, "accessed_addresses" |), "update" |), + make_list [ + M.call (| + M.get_field (| M.get_name (| globals, "PRE_COMPILED_CONTRACTS" |), "keys" |), + make_list [], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_field (| M.get_name (| globals, "accessed_addresses" |), "update" |), + make_list [ + M.get_name (| globals, "preaccessed_addresses" |) + ], + make_dict [] + |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, "Message" |), + make_list [], + make_dict [] + |) + |) in + M.pure Constant.None_)). diff --git a/CoqOfPython/ethereum/gray_glacier/vm/__init__.v b/CoqOfPython/ethereum/gray_glacier/vm/__init__.v new file mode 100644 index 0000000..085ff3e --- /dev/null +++ b/CoqOfPython/ethereum/gray_glacier/vm/__init__.v @@ -0,0 +1,260 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.gray_glacier.vm.__init__". + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +The abstract computer which runs the code stored in an +`.fork_types.Account`. +". + +Axiom dataclasses_imports_dataclass : + IsImported globals "dataclasses" "dataclass". + +Axiom typing_imports_List : + IsImported globals "typing" "List". +Axiom typing_imports_Optional : + IsImported globals "typing" "Optional". +Axiom typing_imports_Set : + IsImported globals "typing" "Set". +Axiom typing_imports_Tuple : + IsImported globals "typing" "Tuple". +Axiom typing_imports_Union : + IsImported globals "typing" "Union". + +Axiom ethereum_base_types_imports_U64 : + IsImported globals "ethereum.base_types" "U64". +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_Bytes : + IsImported globals "ethereum.base_types" "Bytes". +Axiom ethereum_base_types_imports_Bytes0 : + IsImported globals "ethereum.base_types" "Bytes0". +Axiom ethereum_base_types_imports_Bytes32 : + IsImported globals "ethereum.base_types" "Bytes32". +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". + +Axiom ethereum_crypto_hash_imports_Hash32 : + IsImported globals "ethereum.crypto.hash" "Hash32". + +Axiom ethereum_gray_glacier_blocks_imports_Log : + IsImported globals "ethereum.gray_glacier.blocks" "Log". + +Axiom ethereum_gray_glacier_fork_types_imports_Address : + IsImported globals "ethereum.gray_glacier.fork_types" "Address". + +Axiom ethereum_gray_glacier_state_imports_State : + IsImported globals "ethereum.gray_glacier.state" "State". +Axiom ethereum_gray_glacier_state_imports_account_exists_and_is_empty : + IsImported globals "ethereum.gray_glacier.state" "account_exists_and_is_empty". + +Axiom ethereum_gray_glacier_vm_precompiled_contracts_imports_RIPEMD160_ADDRESS : + IsImported globals "ethereum.gray_glacier.vm.precompiled_contracts" "RIPEMD160_ADDRESS". + +Definition __all__ : Value.t := M.run ltac:(M.monadic ( + make_tuple [ Constant.str "Environment"; Constant.str "Evm"; Constant.str "Message" ] +)). + +Definition Environment : Value.t := + builtins.make_klass + [] + [ + + ] + [ + + ]. + +Definition Message : Value.t := + builtins.make_klass + [] + [ + + ] + [ + + ]. + +Definition Evm : Value.t := + builtins.make_klass + [] + [ + + ] + [ + + ]. + +Definition incorporate_child_on_success : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm"; "child_evm" ] |) in + let _ := Constant.str " + Incorporate the state of a successful `child_evm` into the parent `evm`. + + Parameters + ---------- + evm : + The parent `EVM`. + child_evm : + The child evm to incorporate. + " in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "gas_left" |), + M.get_field (| M.get_name (| globals, "child_evm" |), "gas_left" |) + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "logs" |), + M.get_field (| M.get_name (| globals, "child_evm" |), "logs" |) + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "refund_counter" |), + M.get_field (| M.get_name (| globals, "child_evm" |), "refund_counter" |) + |) in + let _ := M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "accounts_to_delete" |), "update" |), + make_list [ + M.get_field (| M.get_name (| globals, "child_evm" |), "accounts_to_delete" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "touched_accounts" |), "update" |), + make_list [ + M.get_field (| M.get_name (| globals, "child_evm" |), "touched_accounts" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, "account_exists_and_is_empty" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "env" |), "state" |); + M.get_field (| M.get_field (| M.get_name (| globals, "child_evm" |), "message" |), "current_target" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "touched_accounts" |), "add" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "child_evm" |), "message" |), "current_target" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "accessed_addresses" |), "update" |), + make_list [ + M.get_field (| M.get_name (| globals, "child_evm" |), "accessed_addresses" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "accessed_storage_keys" |), "update" |), + make_list [ + M.get_field (| M.get_name (| globals, "child_evm" |), "accessed_storage_keys" |) + ], + make_dict [] + |) in + M.pure Constant.None_)). + +Definition incorporate_child_on_error : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm"; "child_evm" ] |) in + let _ := Constant.str " + Incorporate the state of an unsuccessful `child_evm` into the parent `evm`. + + Parameters + ---------- + evm : + The parent `EVM`. + child_evm : + The child evm to incorporate. + " in + let _ := + (* if *) + M.if_then_else (| + Compare.in_ (| + M.get_name (| globals, "RIPEMD160_ADDRESS" |), + M.get_field (| M.get_name (| globals, "child_evm" |), "touched_accounts" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "touched_accounts" |), "add" |), + make_list [ + M.get_name (| globals, "RIPEMD160_ADDRESS" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_field (| M.get_field (| M.get_name (| globals, "child_evm" |), "message" |), "current_target" |), + M.get_name (| globals, "RIPEMD160_ADDRESS" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, "account_exists_and_is_empty" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "env" |), "state" |); + M.get_field (| M.get_field (| M.get_name (| globals, "child_evm" |), "message" |), "current_target" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "touched_accounts" |), "add" |), + make_list [ + M.get_name (| globals, "RIPEMD160_ADDRESS" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "gas_left" |), + M.get_field (| M.get_name (| globals, "child_evm" |), "gas_left" |) + |) in + M.pure Constant.None_)). diff --git a/CoqOfPython/ethereum/gray_glacier/vm/exceptions.v b/CoqOfPython/ethereum/gray_glacier/vm/exceptions.v new file mode 100644 index 0000000..3eab002 --- /dev/null +++ b/CoqOfPython/ethereum/gray_glacier/vm/exceptions.v @@ -0,0 +1,171 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.gray_glacier.vm.exceptions". + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) Exceptions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Exceptions which cause the EVM to halt exceptionally. +". + +Axiom ethereum_exceptions_imports_EthereumException : + IsImported globals "ethereum.exceptions" "EthereumException". + +Definition ExceptionalHalt : Value.t := + builtins.make_klass + [(globals, "EthereumException")] + [ + + ] + [ + + ]. + +Definition Revert : Value.t := + builtins.make_klass + [(globals, "EthereumException")] + [ + + ] + [ + + ]. + +Definition StackUnderflowError : Value.t := + builtins.make_klass + [(globals, "ExceptionalHalt")] + [ + + ] + [ + + ]. + +Definition StackOverflowError : Value.t := + builtins.make_klass + [(globals, "ExceptionalHalt")] + [ + + ] + [ + + ]. + +Definition OutOfGasError : Value.t := + builtins.make_klass + [(globals, "ExceptionalHalt")] + [ + + ] + [ + + ]. + +Definition InvalidOpcode : Value.t := + builtins.make_klass + [(globals, "ExceptionalHalt")] + [ + + ] + [ + ( + "__init__", + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "self"; "code" ] |) in + let _ := M.call (| + M.get_field (| M.call (| + M.get_name (| globals, "super" |), + make_list [], + make_dict [] + |), "__init__" |), + make_list [ + M.get_name (| globals, "code" |) + ], + make_dict [] + |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, "self" |), "code" |), + M.get_name (| globals, "code" |) + |) in + M.pure Constant.None_)) + ) + ]. + +Definition InvalidJumpDestError : Value.t := + builtins.make_klass + [(globals, "ExceptionalHalt")] + [ + + ] + [ + + ]. + +Definition StackDepthLimitError : Value.t := + builtins.make_klass + [(globals, "ExceptionalHalt")] + [ + + ] + [ + + ]. + +Definition WriteInStaticContext : Value.t := + builtins.make_klass + [(globals, "ExceptionalHalt")] + [ + + ] + [ + + ]. + +Definition OutOfBoundsRead : Value.t := + builtins.make_klass + [(globals, "ExceptionalHalt")] + [ + + ] + [ + + ]. + +Definition InvalidParameter : Value.t := + builtins.make_klass + [(globals, "ExceptionalHalt")] + [ + + ] + [ + + ]. + +Definition InvalidContractPrefix : Value.t := + builtins.make_klass + [(globals, "ExceptionalHalt")] + [ + + ] + [ + + ]. + +Definition AddressCollision : Value.t := + builtins.make_klass + [(globals, "ExceptionalHalt")] + [ + + ] + [ + + ]. diff --git a/CoqOfPython/ethereum/gray_glacier/vm/gas.v b/CoqOfPython/ethereum/gray_glacier/vm/gas.v new file mode 100644 index 0000000..a6dcb12 --- /dev/null +++ b/CoqOfPython/ethereum/gray_glacier/vm/gas.v @@ -0,0 +1,912 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.gray_glacier.vm.gas". + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) Gas +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +EVM gas constants and calculators. +". + +Axiom dataclasses_imports_dataclass : + IsImported globals "dataclasses" "dataclass". + +Axiom typing_imports_List : + IsImported globals "typing" "List". +Axiom typing_imports_Tuple : + IsImported globals "typing" "Tuple". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". + +Axiom ethereum_trace_imports_GasAndRefund : + IsImported globals "ethereum.trace" "GasAndRefund". +Axiom ethereum_trace_imports_evm_trace : + IsImported globals "ethereum.trace" "evm_trace". + +Axiom ethereum_utils_numeric_imports_ceil32 : + IsImported globals "ethereum.utils.numeric" "ceil32". + +Axiom ethereum_gray_glacier_vm_imports_Evm : + IsImported globals "ethereum.gray_glacier.vm" "Evm". + +Axiom ethereum_gray_glacier_vm_exceptions_imports_OutOfGasError : + IsImported globals "ethereum.gray_glacier.vm.exceptions" "OutOfGasError". + +Definition GAS_JUMPDEST : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 1 + ], + make_dict [] + |) +)). + +Definition GAS_BASE : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 2 + ], + make_dict [] + |) +)). + +Definition GAS_VERY_LOW : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 3 + ], + make_dict [] + |) +)). + +Definition GAS_STORAGE_SET : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 20000 + ], + make_dict [] + |) +)). + +Definition GAS_STORAGE_UPDATE : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 5000 + ], + make_dict [] + |) +)). + +Definition GAS_STORAGE_CLEAR_REFUND : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 4800 + ], + make_dict [] + |) +)). + +Definition GAS_LOW : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 5 + ], + make_dict [] + |) +)). + +Definition GAS_MID : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 8 + ], + make_dict [] + |) +)). + +Definition GAS_HIGH : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 10 + ], + make_dict [] + |) +)). + +Definition GAS_EXPONENTIATION : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 10 + ], + make_dict [] + |) +)). + +Definition GAS_EXPONENTIATION_PER_BYTE : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 50 + ], + make_dict [] + |) +)). + +Definition GAS_MEMORY : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 3 + ], + make_dict [] + |) +)). + +Definition GAS_KECCAK256 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 30 + ], + make_dict [] + |) +)). + +Definition GAS_KECCAK256_WORD : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 6 + ], + make_dict [] + |) +)). + +Definition GAS_COPY : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 3 + ], + make_dict [] + |) +)). + +Definition GAS_BLOCK_HASH : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 20 + ], + make_dict [] + |) +)). + +Definition GAS_LOG : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 375 + ], + make_dict [] + |) +)). + +Definition GAS_LOG_DATA : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 8 + ], + make_dict [] + |) +)). + +Definition GAS_LOG_TOPIC : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 375 + ], + make_dict [] + |) +)). + +Definition GAS_CREATE : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 32000 + ], + make_dict [] + |) +)). + +Definition GAS_CODE_DEPOSIT : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 200 + ], + make_dict [] + |) +)). + +Definition GAS_ZERO : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) +)). + +Definition GAS_NEW_ACCOUNT : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 25000 + ], + make_dict [] + |) +)). + +Definition GAS_CALL_VALUE : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 9000 + ], + make_dict [] + |) +)). + +Definition GAS_CALL_STIPEND : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 2300 + ], + make_dict [] + |) +)). + +Definition GAS_SELF_DESTRUCT : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 5000 + ], + make_dict [] + |) +)). + +Definition GAS_SELF_DESTRUCT_NEW_ACCOUNT : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 25000 + ], + make_dict [] + |) +)). + +Definition GAS_ECRECOVER : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 3000 + ], + make_dict [] + |) +)). + +Definition GAS_SHA256 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 60 + ], + make_dict [] + |) +)). + +Definition GAS_SHA256_WORD : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 12 + ], + make_dict [] + |) +)). + +Definition GAS_RIPEMD160 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 600 + ], + make_dict [] + |) +)). + +Definition GAS_RIPEMD160_WORD : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 120 + ], + make_dict [] + |) +)). + +Definition GAS_IDENTITY : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 15 + ], + make_dict [] + |) +)). + +Definition GAS_IDENTITY_WORD : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 3 + ], + make_dict [] + |) +)). + +Definition GAS_RETURN_DATA_COPY : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 3 + ], + make_dict [] + |) +)). + +Definition GAS_FAST_STEP : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 5 + ], + make_dict [] + |) +)). + +Definition GAS_BLAKE2_PER_ROUND : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 1 + ], + make_dict [] + |) +)). + +Definition GAS_COLD_SLOAD : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 2100 + ], + make_dict [] + |) +)). + +Definition GAS_COLD_ACCOUNT_ACCESS : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 2600 + ], + make_dict [] + |) +)). + +Definition GAS_WARM_ACCESS : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 100 + ], + make_dict [] + |) +)). + +Definition ExtendMemory : Value.t := + builtins.make_klass + [] + [ + + ] + [ + + ]. + +Definition MessageCallGas : Value.t := + builtins.make_klass + [] + [ + + ] + [ + + ]. + +Definition charge_gas : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm"; "amount" ] |) in + let _ := Constant.str " + Subtracts `amount` from `evm.gas_left`. + + Parameters + ---------- + evm : + The current EVM. + amount : + The amount of gas the current operation requires. + + " in + let _ := M.call (| + M.get_name (| globals, "evm_trace" |), + make_list [ + M.get_name (| globals, "evm" |); + M.call (| + M.get_name (| globals, "GasAndRefund" |), + make_list [ + M.get_name (| globals, "amount" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.lt (| + M.get_field (| M.get_name (| globals, "evm" |), "gas_left" |), + M.get_name (| globals, "amount" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, "OutOfGasError" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_op (| + BinOp.sub, + M.get_field (| M.get_name (| globals, "evm" |), "gas_left" |), + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + M.get_name (| globals, "amount" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_)). + +Definition calculate_memory_gas_cost : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "size_in_bytes" ] |) in + let _ := Constant.str " + Calculates the gas cost for allocating memory + to the smallest multiple of 32 bytes, + such that the allocated size is at least as big as the given size. + + Parameters + ---------- + size_in_bytes : + The size of the data in bytes. + + Returns + ------- + total_gas_cost : `ethereum.base_types.Uint` + The gas cost for storing data in memory. + " in + let _ := M.assign_local (| + "size_in_words" , + BinOp.floor_div (| + M.call (| + M.get_name (| globals, "ceil32" |), + make_list [ + M.get_name (| globals, "size_in_bytes" |) + ], + make_dict [] + |), + Constant.int 32 + |) + |) in + let _ := M.assign_local (| + "linear_cost" , + BinOp.mult (| + M.get_name (| globals, "size_in_words" |), + M.get_name (| globals, "GAS_MEMORY" |) + |) + |) in + let _ := M.assign_local (| + "quadratic_cost" , + BinOp.floor_div (| + BinOp.pow (| + M.get_name (| globals, "size_in_words" |), + Constant.int 2 + |), + Constant.int 512 + |) + |) in + let _ := M.assign_local (| + "total_gas_cost" , + BinOp.add (| + M.get_name (| globals, "linear_cost" |), + M.get_name (| globals, "quadratic_cost" |) + |) + |) in +(* At stmt: unsupported node type: Try *) + M.pure Constant.None_)). + +Definition calculate_gas_extend_memory : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "memory"; "extensions" ] |) in + let _ := Constant.str " + Calculates the gas amount to extend memory + + Parameters + ---------- + memory : + Memory contents of the EVM. + extensions: + List of extensions to be made to the memory. + Consists of a tuple of start position and size. + + Returns + ------- + extend_memory: `ExtendMemory` + " in + let _ := M.assign_local (| + "size_to_extend" , + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "to_be_paid" , + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "current_size" , + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_name (| globals, "memory" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := + M.for_ (| + make_tuple [ M.get_name (| globals, "start_position" |); M.get_name (| globals, "size" |) ], + M.get_name (| globals, "extensions" |), + ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, "size" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.continue (| |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "before_size" , + M.call (| + M.get_name (| globals, "ceil32" |), + make_list [ + M.get_name (| globals, "current_size" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "after_size" , + M.call (| + M.get_name (| globals, "ceil32" |), + make_list [ + BinOp.add (| + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.get_name (| globals, "start_position" |) + ], + make_dict [] + |), + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.get_name (| globals, "size" |) + ], + make_dict [] + |) + |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.lt_e (| + M.get_name (| globals, "after_size" |), + M.get_name (| globals, "before_size" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.continue (| |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_op_local (| + BinOp.add, + "size_to_extend", + BinOp.sub (| + M.get_name (| globals, "after_size" |), + M.get_name (| globals, "before_size" |) + |) + |) in + let _ := M.assign_local (| + "already_paid" , + M.call (| + M.get_name (| globals, "calculate_memory_gas_cost" |), + make_list [ + M.get_name (| globals, "before_size" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "total_cost" , + M.call (| + M.get_name (| globals, "calculate_memory_gas_cost" |), + make_list [ + M.get_name (| globals, "after_size" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_op_local (| + BinOp.add, + "to_be_paid", + BinOp.sub (| + M.get_name (| globals, "total_cost" |), + M.get_name (| globals, "already_paid" |) + |) + |) in + let _ := M.assign_local (| + "current_size" , + M.get_name (| globals, "after_size" |) + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, "ExtendMemory" |), + make_list [ + M.get_name (| globals, "to_be_paid" |); + M.get_name (| globals, "size_to_extend" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Definition calculate_message_call_gas : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "value"; "gas"; "gas_left"; "memory_cost"; "extra_gas"; "call_stipend" ] |) in + let _ := Constant.str " + Calculates the MessageCallGas (cost and stipend) for + executing call Opcodes. + + Parameters + ---------- + value: + The amount of `ETH` that needs to be transferred. + gas : + The amount of gas provided to the message-call. + gas_left : + The amount of gas left in the current frame. + memory_cost : + The amount needed to extend the memory in the current frame. + extra_gas : + The amount of gas needed for transferring value + creating a new + account inside a message call. + call_stipend : + The amount of stipend provided to a message call to execute code while + transferring value(ETH). + + Returns + ------- + message_call_gas: `MessageCallGas` + " in + let _ := M.assign_local (| + "call_stipend" , + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, "value" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( +M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + (* else *) + )), ltac:(M.monadic ( +M.get_name (| globals, "call_stipend" |) + )) |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.lt (| + M.get_name (| globals, "gas_left" |), + BinOp.add (| + M.get_name (| globals, "extra_gas" |), + M.get_name (| globals, "memory_cost" |) + |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + M.call (| + M.get_name (| globals, "MessageCallGas" |), + make_list [ + BinOp.add (| + M.get_name (| globals, "gas" |), + M.get_name (| globals, "extra_gas" |) + |); + BinOp.add (| + M.get_name (| globals, "gas" |), + M.get_name (| globals, "call_stipend" |) + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "gas" , + M.call (| + M.get_name (| globals, "min" |), + make_list [ + M.get_name (| globals, "gas" |); + M.call (| + M.get_name (| globals, "max_message_call_gas" |), + make_list [ + BinOp.sub (| + BinOp.sub (| + M.get_name (| globals, "gas_left" |), + M.get_name (| globals, "memory_cost" |) + |), + M.get_name (| globals, "extra_gas" |) + |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, "MessageCallGas" |), + make_list [ + BinOp.add (| + M.get_name (| globals, "gas" |), + M.get_name (| globals, "extra_gas" |) + |); + BinOp.add (| + M.get_name (| globals, "gas" |), + M.get_name (| globals, "call_stipend" |) + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Definition max_message_call_gas : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "gas" ] |) in + let _ := Constant.str " + Calculates the maximum gas that is allowed for making a message call + + Parameters + ---------- + gas : + The amount of gas provided to the message-call. + + Returns + ------- + max_allowed_message_call_gas: `ethereum.base_types.Uint` + The maximum gas allowed for making the message-call. + " in + let _ := M.return_ (| + BinOp.sub (| + M.get_name (| globals, "gas" |), + BinOp.floor_div (| + M.get_name (| globals, "gas" |), + Constant.int 64 + |) + |) + |) in + M.pure Constant.None_)). diff --git a/CoqOfPython/ethereum/gray_glacier/vm/instructions/__init__.v b/CoqOfPython/ethereum/gray_glacier/vm/instructions/__init__.v new file mode 100644 index 0000000..a505398 --- /dev/null +++ b/CoqOfPython/ethereum/gray_glacier/vm/instructions/__init__.v @@ -0,0 +1,74 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.gray_glacier.vm.instructions.__init__". + +Definition expr_1 : Value.t := + Constant.str " +EVM Instruction Encoding (Opcodes) +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Machine readable representations of EVM instructions, and a mapping to their +implementations. +". + +(* At top_level_stmt: unsupported node type: Import *) + +Axiom typing_imports_Callable : + IsImported globals "typing" "Callable". +Axiom typing_imports_Dict : + IsImported globals "typing" "Dict". + +Axiom ethereum_gray_glacier_vm_instructions_imports_arithmetic : + IsImported globals "ethereum.gray_glacier.vm.instructions" "arithmetic". + +Axiom ethereum_gray_glacier_vm_instructions_imports_bitwise : + IsImported globals "ethereum.gray_glacier.vm.instructions" "bitwise". + +Axiom ethereum_gray_glacier_vm_instructions_imports_block : + IsImported globals "ethereum.gray_glacier.vm.instructions" "block". + +Axiom ethereum_gray_glacier_vm_instructions_imports_comparison : + IsImported globals "ethereum.gray_glacier.vm.instructions" "comparison". + +Axiom ethereum_gray_glacier_vm_instructions_imports_control_flow : + IsImported globals "ethereum.gray_glacier.vm.instructions" "control_flow". + +Axiom ethereum_gray_glacier_vm_instructions_imports_environment : + IsImported globals "ethereum.gray_glacier.vm.instructions" "environment". + +Axiom ethereum_gray_glacier_vm_instructions_imports_keccak : + IsImported globals "ethereum.gray_glacier.vm.instructions" "keccak". + +Axiom ethereum_gray_glacier_vm_instructions_imports_log : + IsImported globals "ethereum.gray_glacier.vm.instructions" "log". + +Axiom ethereum_gray_glacier_vm_instructions_imports_memory : + IsImported globals "ethereum.gray_glacier.vm.instructions" "memory". + +Axiom ethereum_gray_glacier_vm_instructions_imports_stack : + IsImported globals "ethereum.gray_glacier.vm.instructions" "stack". + +Axiom ethereum_gray_glacier_vm_instructions_imports_storage : + IsImported globals "ethereum.gray_glacier.vm.instructions" "storage". + +Axiom ethereum_gray_glacier_vm_instructions_imports_system : + IsImported globals "ethereum.gray_glacier.vm.instructions" "system". + +Definition Ops : Value.t := + builtins.make_klass + [(* At base: unsupported node type: Attribute *)] + [ + + ] + [ + + ]. + +(* At top_level_stmt: unsupported node type: AnnAssign *) diff --git a/CoqOfPython/ethereum/gray_glacier/vm/instructions/arithmetic.v b/CoqOfPython/ethereum/gray_glacier/vm/instructions/arithmetic.v new file mode 100644 index 0000000..d4d5eed --- /dev/null +++ b/CoqOfPython/ethereum/gray_glacier/vm/instructions/arithmetic.v @@ -0,0 +1,1220 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.gray_glacier.vm.instructions.arithmetic". + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) Arithmetic Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM Arithmetic instructions. +". + +Axiom ethereum_base_types_imports_U255_CEIL_VALUE : + IsImported globals "ethereum.base_types" "U255_CEIL_VALUE". +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_U256_CEIL_VALUE : + IsImported globals "ethereum.base_types" "U256_CEIL_VALUE". +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". + +Axiom ethereum_utils_numeric_imports_get_sign : + IsImported globals "ethereum.utils.numeric" "get_sign". + +Axiom ethereum_gray_glacier_vm_imports_Evm : + IsImported globals "ethereum.gray_glacier.vm" "Evm". + +Axiom ethereum_gray_glacier_vm_gas_imports_GAS_EXPONENTIATION : + IsImported globals "ethereum.gray_glacier.vm.gas" "GAS_EXPONENTIATION". +Axiom ethereum_gray_glacier_vm_gas_imports_GAS_EXPONENTIATION_PER_BYTE : + IsImported globals "ethereum.gray_glacier.vm.gas" "GAS_EXPONENTIATION_PER_BYTE". +Axiom ethereum_gray_glacier_vm_gas_imports_GAS_LOW : + IsImported globals "ethereum.gray_glacier.vm.gas" "GAS_LOW". +Axiom ethereum_gray_glacier_vm_gas_imports_GAS_MID : + IsImported globals "ethereum.gray_glacier.vm.gas" "GAS_MID". +Axiom ethereum_gray_glacier_vm_gas_imports_GAS_VERY_LOW : + IsImported globals "ethereum.gray_glacier.vm.gas" "GAS_VERY_LOW". +Axiom ethereum_gray_glacier_vm_gas_imports_charge_gas : + IsImported globals "ethereum.gray_glacier.vm.gas" "charge_gas". + +Axiom ethereum_gray_glacier_vm_stack_imports_pop : + IsImported globals "ethereum.gray_glacier.vm.stack" "pop". +Axiom ethereum_gray_glacier_vm_stack_imports_push : + IsImported globals "ethereum.gray_glacier.vm.stack" "push". + +Definition add : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Adds the top two elements of the stack together, and pushes the result back + on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "x" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "y" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_VERY_LOW" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "result" , + M.call (| + M.get_field (| M.get_name (| globals, "x" |), "wrapping_add" |), + make_list [ + M.get_name (| globals, "y" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.get_name (| globals, "result" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition sub : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Subtracts the top two elements of the stack, and pushes the result back + on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "x" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "y" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_VERY_LOW" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "result" , + M.call (| + M.get_field (| M.get_name (| globals, "x" |), "wrapping_sub" |), + make_list [ + M.get_name (| globals, "y" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.get_name (| globals, "result" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition mul : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Multiply the top two elements of the stack, and pushes the result back + on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "x" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "y" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_LOW" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "result" , + M.call (| + M.get_field (| M.get_name (| globals, "x" |), "wrapping_mul" |), + make_list [ + M.get_name (| globals, "y" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.get_name (| globals, "result" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition div : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Integer division of the top two elements of the stack. Pushes the result + back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "dividend" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "divisor" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_LOW" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, "divisor" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "quotient" , + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "quotient" , + BinOp.floor_div (| + M.get_name (| globals, "dividend" |), + M.get_name (| globals, "divisor" |) + |) + |) in + M.pure Constant.None_ + )) |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.get_name (| globals, "quotient" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition sdiv : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Signed integer division of the top two elements of the stack. Pushes the + result back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "dividend" , + M.call (| + M.get_field (| M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |), "to_signed" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "divisor" , + M.call (| + M.get_field (| M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |), "to_signed" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_LOW" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, "divisor" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "quotient" , + Constant.int 0 + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + BoolOp.and (| + Compare.eq (| + M.get_name (| globals, "dividend" |), + UnOp.sub (| M.get_name (| globals, "U255_CEIL_VALUE" |) |) + |), + ltac:(M.monadic ( + Compare.eq (| + M.get_name (| globals, "divisor" |), + UnOp.sub (| Constant.int 1 |) + |) + )) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "quotient" , + UnOp.sub (| M.get_name (| globals, "U255_CEIL_VALUE" |) |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "sign" , + M.call (| + M.get_name (| globals, "get_sign" |), + make_list [ + BinOp.mult (| + M.get_name (| globals, "dividend" |), + M.get_name (| globals, "divisor" |) + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "quotient" , + BinOp.mult (| + M.get_name (| globals, "sign" |), + BinOp.floor_div (| + M.call (| + M.get_name (| globals, "abs" |), + make_list [ + M.get_name (| globals, "dividend" |) + ], + make_dict [] + |), + M.call (| + M.get_name (| globals, "abs" |), + make_list [ + M.get_name (| globals, "divisor" |) + ], + make_dict [] + |) + |) + |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )) |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.call (| + M.get_field (| M.get_name (| globals, "U256" |), "from_signed" |), + make_list [ + M.get_name (| globals, "quotient" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition mod_ : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Modulo remainder of the top two elements of the stack. Pushes the result + back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "x" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "y" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_LOW" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, "y" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "remainder" , + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "remainder" , + BinOp.mod_ (| + M.get_name (| globals, "x" |), + M.get_name (| globals, "y" |) + |) + |) in + M.pure Constant.None_ + )) |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.get_name (| globals, "remainder" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition smod : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Signed modulo remainder of the top two elements of the stack. Pushes the + result back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "x" , + M.call (| + M.get_field (| M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |), "to_signed" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "y" , + M.call (| + M.get_field (| M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |), "to_signed" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_LOW" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, "y" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "remainder" , + Constant.int 0 + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "remainder" , + BinOp.mult (| + M.call (| + M.get_name (| globals, "get_sign" |), + make_list [ + M.get_name (| globals, "x" |) + ], + make_dict [] + |), + BinOp.mod_ (| + M.call (| + M.get_name (| globals, "abs" |), + make_list [ + M.get_name (| globals, "x" |) + ], + make_dict [] + |), + M.call (| + M.get_name (| globals, "abs" |), + make_list [ + M.get_name (| globals, "y" |) + ], + make_dict [] + |) + |) + |) + |) in + M.pure Constant.None_ + )) |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.call (| + M.get_field (| M.get_name (| globals, "U256" |), "from_signed" |), + make_list [ + M.get_name (| globals, "remainder" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition addmod : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Modulo addition of the top 2 elements with the 3rd element. Pushes the + result back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "x" , + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "y" , + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "z" , + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_MID" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, "z" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "result" , + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "result" , + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + BinOp.mod_ (| + BinOp.add (| + M.get_name (| globals, "x" |), + M.get_name (| globals, "y" |) + |), + M.get_name (| globals, "z" |) + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + )) |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.get_name (| globals, "result" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition mulmod : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Modulo multiplication of the top 2 elements with the 3rd element. Pushes + the result back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "x" , + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "y" , + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "z" , + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_MID" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, "z" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "result" , + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "result" , + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + BinOp.mod_ (| + BinOp.mult (| + M.get_name (| globals, "x" |), + M.get_name (| globals, "y" |) + |), + M.get_name (| globals, "z" |) + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + )) |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.get_name (| globals, "result" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition exp : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Exponential operation of the top 2 elements. Pushes the result back on + the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "base" , + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "exponent" , + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "exponent_bits" , + M.call (| + M.get_field (| M.get_name (| globals, "exponent" |), "bit_length" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "exponent_bytes" , + BinOp.floor_div (| + BinOp.add (| + M.get_name (| globals, "exponent_bits" |), + Constant.int 7 + |), + Constant.int 8 + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + BinOp.add (| + M.get_name (| globals, "GAS_EXPONENTIATION" |), + BinOp.mult (| + M.get_name (| globals, "GAS_EXPONENTIATION_PER_BYTE" |), + M.get_name (| globals, "exponent_bytes" |) + |) + |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "result" , + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + M.call (| + M.get_name (| globals, "pow" |), + make_list [ + M.get_name (| globals, "base" |); + M.get_name (| globals, "exponent" |); + M.get_name (| globals, "U256_CEIL_VALUE" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.get_name (| globals, "result" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition signextend : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Sign extend operation. In other words, extend a signed number which + fits in N bytes to 32 bytes. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "byte_num" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "value" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_LOW" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.gt (| + M.get_name (| globals, "byte_num" |), + Constant.int 31 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "result" , + M.get_name (| globals, "value" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "value_bytes" , + M.call (| + M.get_name (| globals, "bytes" |), + make_list [ + M.call (| + M.get_field (| M.get_name (| globals, "value" |), "to_be_bytes32" |), + make_list [], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "value_bytes" , + M.slice (| + M.get_name (| globals, "value_bytes" |), + BinOp.sub (| + Constant.int 31, + M.call (| + M.get_name (| globals, "int" |), + make_list [ + M.get_name (| globals, "byte_num" |) + ], + make_dict [] + |) + |), + Constant.None_, + Constant.None_ + |) + |) in + let _ := M.assign_local (| + "sign_bit" , + BinOp.r_shift (| + M.get_subscript (| + M.get_name (| globals, "value_bytes" |), + Constant.int 0 + |), + Constant.int 7 + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, "sign_bit" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "result" , + M.call (| + M.get_field (| M.get_name (| globals, "U256" |), "from_be_bytes" |), + make_list [ + M.get_name (| globals, "value_bytes" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "num_bytes_prepend" , + BinOp.sub (| + Constant.int 32, + BinOp.add (| + M.get_name (| globals, "byte_num" |), + Constant.int 1 + |) + |) + |) in + let _ := M.assign_local (| + "result" , + M.call (| + M.get_field (| M.get_name (| globals, "U256" |), "from_be_bytes" |), + make_list [ + BinOp.add (| + M.call (| + M.get_name (| globals, "bytearray" |), + make_list [ + BinOp.mult (| + make_list [ + Constant.int 255 + ], + M.get_name (| globals, "num_bytes_prepend" |) + |) + ], + make_dict [] + |), + M.get_name (| globals, "value_bytes" |) + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )) |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.get_name (| globals, "result" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). diff --git a/CoqOfPython/ethereum/gray_glacier/vm/instructions/bitwise.v b/CoqOfPython/ethereum/gray_glacier/vm/instructions/bitwise.v new file mode 100644 index 0000000..c580c05 --- /dev/null +++ b/CoqOfPython/ethereum/gray_glacier/vm/instructions/bitwise.v @@ -0,0 +1,666 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.gray_glacier.vm.instructions.bitwise". + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) Bitwise Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM bitwise instructions. +". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_U256_CEIL_VALUE : + IsImported globals "ethereum.base_types" "U256_CEIL_VALUE". + +Axiom ethereum_gray_glacier_vm_imports_Evm : + IsImported globals "ethereum.gray_glacier.vm" "Evm". + +Axiom ethereum_gray_glacier_vm_gas_imports_GAS_VERY_LOW : + IsImported globals "ethereum.gray_glacier.vm.gas" "GAS_VERY_LOW". +Axiom ethereum_gray_glacier_vm_gas_imports_charge_gas : + IsImported globals "ethereum.gray_glacier.vm.gas" "charge_gas". + +Axiom ethereum_gray_glacier_vm_stack_imports_pop : + IsImported globals "ethereum.gray_glacier.vm.stack" "pop". +Axiom ethereum_gray_glacier_vm_stack_imports_push : + IsImported globals "ethereum.gray_glacier.vm.stack" "push". + +Definition bitwise_and : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Bitwise AND operation of the top 2 elements of the stack. Pushes the + result back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "x" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "y" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_VERY_LOW" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + BinOp.bit_and (| + M.get_name (| globals, "x" |), + M.get_name (| globals, "y" |) + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition bitwise_or : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Bitwise OR operation of the top 2 elements of the stack. Pushes the + result back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "x" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "y" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_VERY_LOW" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + BinOp.bit_or (| + M.get_name (| globals, "x" |), + M.get_name (| globals, "y" |) + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition bitwise_xor : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Bitwise XOR operation of the top 2 elements of the stack. Pushes the + result back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "x" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "y" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_VERY_LOW" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + BinOp.bit_xor (| + M.get_name (| globals, "x" |), + M.get_name (| globals, "y" |) + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition bitwise_not : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Bitwise NOT operation of the top element of the stack. Pushes the + result back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "x" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_VERY_LOW" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + UnOp.invert (| M.get_name (| globals, "x" |) |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition get_byte : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + For a word (defined by next top element of the stack), retrieve the + Nth byte (0-indexed and defined by top element of stack) from the + left (most significant) to right (least significant). + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "byte_index" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "word" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_VERY_LOW" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.gt_e (| + M.get_name (| globals, "byte_index" |), + Constant.int 32 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "result" , + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "extra_bytes_to_right" , + BinOp.sub (| + Constant.int 31, + M.get_name (| globals, "byte_index" |) + |) + |) in + let _ := M.assign_local (| + "word" , + BinOp.r_shift (| + M.get_name (| globals, "word" |), + BinOp.mult (| + M.get_name (| globals, "extra_bytes_to_right" |), + Constant.int 8 + |) + |) + |) in + let _ := M.assign_local (| + "word" , + BinOp.bit_and (| + M.get_name (| globals, "word" |), + Constant.int 255 + |) + |) in + let _ := M.assign_local (| + "result" , + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + M.get_name (| globals, "word" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + )) |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.get_name (| globals, "result" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition bitwise_shl : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Logical shift left (SHL) operation of the top 2 elements of the stack. + Pushes the result back on the stack. + Parameters + ---------- + evm : + The current EVM frame. + " in + let _ := M.assign_local (| + "shift" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "value" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_VERY_LOW" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.lt (| + M.get_name (| globals, "shift" |), + Constant.int 256 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "result" , + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + BinOp.mod_ (| + BinOp.l_shift (| + M.get_name (| globals, "value" |), + M.get_name (| globals, "shift" |) + |), + M.get_name (| globals, "U256_CEIL_VALUE" |) + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "result" , + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + )) |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.get_name (| globals, "result" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition bitwise_shr : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Logical shift right (SHR) operation of the top 2 elements of the stack. + Pushes the result back on the stack. + Parameters + ---------- + evm : + The current EVM frame. + " in + let _ := M.assign_local (| + "shift" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "value" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_VERY_LOW" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.lt (| + M.get_name (| globals, "shift" |), + Constant.int 256 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "result" , + BinOp.r_shift (| + M.get_name (| globals, "value" |), + M.get_name (| globals, "shift" |) + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "result" , + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + )) |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.get_name (| globals, "result" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition bitwise_sar : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Arithmetic shift right (SAR) operation of the top 2 elements of the stack. + Pushes the result back on the stack. + Parameters + ---------- + evm : + The current EVM frame. + " in + let _ := M.assign_local (| + "shift" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "signed_value" , + M.call (| + M.get_field (| M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |), "to_signed" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_VERY_LOW" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.lt (| + M.get_name (| globals, "shift" |), + Constant.int 256 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "result" , + M.call (| + M.get_field (| M.get_name (| globals, "U256" |), "from_signed" |), + make_list [ + BinOp.r_shift (| + M.get_name (| globals, "signed_value" |), + M.get_name (| globals, "shift" |) + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + Compare.gt_e (| + M.get_name (| globals, "signed_value" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "result" , + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "result" , + M.get_field (| M.get_name (| globals, "U256" |), "MAX_VALUE" |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )) |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.get_name (| globals, "result" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). diff --git a/CoqOfPython/ethereum/gray_glacier/vm/instructions/block.v b/CoqOfPython/ethereum/gray_glacier/vm/instructions/block.v new file mode 100644 index 0000000..1b25dc5 --- /dev/null +++ b/CoqOfPython/ethereum/gray_glacier/vm/instructions/block.v @@ -0,0 +1,390 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.gray_glacier.vm.instructions.block". + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) Block Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM block instructions. +". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". + +Axiom ethereum_gray_glacier_vm_imports_Evm : + IsImported globals "ethereum.gray_glacier.vm" "Evm". + +Axiom ethereum_gray_glacier_vm_gas_imports_GAS_BASE : + IsImported globals "ethereum.gray_glacier.vm.gas" "GAS_BASE". +Axiom ethereum_gray_glacier_vm_gas_imports_GAS_BLOCK_HASH : + IsImported globals "ethereum.gray_glacier.vm.gas" "GAS_BLOCK_HASH". +Axiom ethereum_gray_glacier_vm_gas_imports_charge_gas : + IsImported globals "ethereum.gray_glacier.vm.gas" "charge_gas". + +Axiom ethereum_gray_glacier_vm_stack_imports_pop : + IsImported globals "ethereum.gray_glacier.vm.stack" "pop". +Axiom ethereum_gray_glacier_vm_stack_imports_push : + IsImported globals "ethereum.gray_glacier.vm.stack" "push". + +Definition block_hash : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Push the hash of one of the 256 most recent complete blocks onto the + stack. The block number to hash is present at the top of the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "block_number" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_BLOCK_HASH" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + BoolOp.or (| + Compare.lt_e (| + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "env" |), "number" |), + M.get_name (| globals, "block_number" |) + |), + ltac:(M.monadic ( + Compare.gt (| + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "env" |), "number" |), + BinOp.add (| + M.get_name (| globals, "block_number" |), + Constant.int 256 + |) + |) + )) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "hash" , + Constant.bytes "00" + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "hash" , + M.get_subscript (| + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "env" |), "block_hashes" |), + UnOp.sub (| BinOp.sub (| + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "env" |), "number" |), + M.get_name (| globals, "block_number" |) + |) |) + |) + |) in + M.pure Constant.None_ + )) |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.call (| + M.get_field (| M.get_name (| globals, "U256" |), "from_be_bytes" |), + make_list [ + M.get_name (| globals, "hash" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition coinbase : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Push the current block's beneficiary address (address of the block miner) + onto the stack. + + Here the current block refers to the block in which the currently + executing transaction/call resides. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_BASE" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.call (| + M.get_field (| M.get_name (| globals, "U256" |), "from_be_bytes" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "env" |), "coinbase" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition timestamp : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Push the current block's timestamp onto the stack. Here the timestamp + being referred is actually the unix timestamp in seconds. + + Here the current block refers to the block in which the currently + executing transaction/call resides. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_BASE" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "env" |), "time" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition number : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Push the current block's number onto the stack. + + Here the current block refers to the block in which the currently + executing transaction/call resides. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_BASE" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "env" |), "number" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition difficulty : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Push the current block's difficulty onto the stack. + + Here the current block refers to the block in which the currently + executing transaction/call resides. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_BASE" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "env" |), "difficulty" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition gas_limit : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Push the current block's gas limit onto the stack. + + Here the current block refers to the block in which the currently + executing transaction/call resides. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_BASE" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "env" |), "gas_limit" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition chain_id : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Push the chain id onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_BASE" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "env" |), "chain_id" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). diff --git a/CoqOfPython/ethereum/gray_glacier/vm/instructions/comparison.v b/CoqOfPython/ethereum/gray_glacier/vm/instructions/comparison.v new file mode 100644 index 0000000..64165db --- /dev/null +++ b/CoqOfPython/ethereum/gray_glacier/vm/instructions/comparison.v @@ -0,0 +1,452 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.gray_glacier.vm.instructions.comparison". + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) Comparison Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM Comparison instructions. +". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". + +Axiom ethereum_gray_glacier_vm_imports_Evm : + IsImported globals "ethereum.gray_glacier.vm" "Evm". + +Axiom ethereum_gray_glacier_vm_gas_imports_GAS_VERY_LOW : + IsImported globals "ethereum.gray_glacier.vm.gas" "GAS_VERY_LOW". +Axiom ethereum_gray_glacier_vm_gas_imports_charge_gas : + IsImported globals "ethereum.gray_glacier.vm.gas" "charge_gas". + +Axiom ethereum_gray_glacier_vm_stack_imports_pop : + IsImported globals "ethereum.gray_glacier.vm.stack" "pop". +Axiom ethereum_gray_glacier_vm_stack_imports_push : + IsImported globals "ethereum.gray_glacier.vm.stack" "push". + +Definition less_than : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Checks if the top element is less than the next top element. Pushes the + result back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "left" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "right" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_VERY_LOW" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "result" , + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Compare.lt (| + M.get_name (| globals, "left" |), + M.get_name (| globals, "right" |) + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.get_name (| globals, "result" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition signed_less_than : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Signed less-than comparison. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "left" , + M.call (| + M.get_field (| M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |), "to_signed" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "right" , + M.call (| + M.get_field (| M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |), "to_signed" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_VERY_LOW" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "result" , + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Compare.lt (| + M.get_name (| globals, "left" |), + M.get_name (| globals, "right" |) + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.get_name (| globals, "result" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition greater_than : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Checks if the top element is greater than the next top element. Pushes + the result back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "left" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "right" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_VERY_LOW" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "result" , + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Compare.gt (| + M.get_name (| globals, "left" |), + M.get_name (| globals, "right" |) + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.get_name (| globals, "result" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition signed_greater_than : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Signed greater-than comparison. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "left" , + M.call (| + M.get_field (| M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |), "to_signed" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "right" , + M.call (| + M.get_field (| M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |), "to_signed" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_VERY_LOW" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "result" , + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Compare.gt (| + M.get_name (| globals, "left" |), + M.get_name (| globals, "right" |) + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.get_name (| globals, "result" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition equal : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Checks if the top element is equal to the next top element. Pushes + the result back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "left" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "right" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_VERY_LOW" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "result" , + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Compare.eq (| + M.get_name (| globals, "left" |), + M.get_name (| globals, "right" |) + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.get_name (| globals, "result" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition is_zero : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Checks if the top element is equal to 0. Pushes the result back on the + stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "x" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_VERY_LOW" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "result" , + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Compare.eq (| + M.get_name (| globals, "x" |), + Constant.int 0 + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.get_name (| globals, "result" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). diff --git a/CoqOfPython/ethereum/gray_glacier/vm/instructions/control_flow.v b/CoqOfPython/ethereum/gray_glacier/vm/instructions/control_flow.v new file mode 100644 index 0000000..0438b4c --- /dev/null +++ b/CoqOfPython/ethereum/gray_glacier/vm/instructions/control_flow.v @@ -0,0 +1,350 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.gray_glacier.vm.instructions.control_flow". + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) Control Flow Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM control flow instructions. +". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". + +Axiom ethereum_gray_glacier_vm_gas_imports_GAS_BASE : + IsImported globals "ethereum.gray_glacier.vm.gas" "GAS_BASE". +Axiom ethereum_gray_glacier_vm_gas_imports_GAS_HIGH : + IsImported globals "ethereum.gray_glacier.vm.gas" "GAS_HIGH". +Axiom ethereum_gray_glacier_vm_gas_imports_GAS_JUMPDEST : + IsImported globals "ethereum.gray_glacier.vm.gas" "GAS_JUMPDEST". +Axiom ethereum_gray_glacier_vm_gas_imports_GAS_MID : + IsImported globals "ethereum.gray_glacier.vm.gas" "GAS_MID". +Axiom ethereum_gray_glacier_vm_gas_imports_charge_gas : + IsImported globals "ethereum.gray_glacier.vm.gas" "charge_gas". + +Axiom ethereum_gray_glacier_vm_imports_Evm : + IsImported globals "ethereum.gray_glacier.vm" "Evm". + +Axiom ethereum_gray_glacier_vm_exceptions_imports_InvalidJumpDestError : + IsImported globals "ethereum.gray_glacier.vm.exceptions" "InvalidJumpDestError". + +Axiom ethereum_gray_glacier_vm_stack_imports_pop : + IsImported globals "ethereum.gray_glacier.vm.stack" "pop". +Axiom ethereum_gray_glacier_vm_stack_imports_push : + IsImported globals "ethereum.gray_glacier.vm.stack" "push". + +Definition stop : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Stop further execution of EVM code. + + Parameters + ---------- + evm : + The current EVM frame. + " in + let _ := M.pass (| |) in + let _ := M.pass (| |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, "evm" |), "running" |), + Constant.bool false + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition jump : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Alter the program counter to the location specified by the top of the + stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "jump_dest" , + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_MID" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.not_in (| + M.get_name (| globals, "jump_dest" |), + M.get_field (| M.get_name (| globals, "evm" |), "valid_jump_destinations" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, "InvalidJumpDestError" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.get_name (| globals, "jump_dest" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Definition jumpi : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Alter the program counter to the specified location if and only if a + condition is true. If the condition is not true, then the program counter + would increase only by 1. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "jump_dest" , + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "conditional_value" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_HIGH" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, "conditional_value" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "destination" , + BinOp.add (| + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + Compare.not_in (| + M.get_name (| globals, "jump_dest" |), + M.get_field (| M.get_name (| globals, "evm" |), "valid_jump_destinations" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, "InvalidJumpDestError" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "destination" , + M.get_name (| globals, "jump_dest" |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )) |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.get_name (| globals, "destination" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Definition pc : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Push onto the stack the value of the program counter after reaching the + current instruction and without increasing it for the next instruction. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_BASE" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "pc" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition gas_left : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Push the amount of available gas (including the corresponding reduction + for the cost of this instruction) onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_BASE" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "gas_left" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition jumpdest : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Mark a valid destination for jumps. This is a noop, present only + to be used by `JUMP` and `JUMPI` opcodes to verify that their jump is + valid. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_JUMPDEST" |) + ], + make_dict [] + |) in + let _ := M.pass (| |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). diff --git a/CoqOfPython/ethereum/gray_glacier/vm/instructions/environment.v b/CoqOfPython/ethereum/gray_glacier/vm/instructions/environment.v new file mode 100644 index 0000000..13a017d --- /dev/null +++ b/CoqOfPython/ethereum/gray_glacier/vm/instructions/environment.v @@ -0,0 +1,1529 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.gray_glacier.vm.instructions.environment". + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) Environmental Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM environment related instructions. +". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". + +Axiom ethereum_crypto_hash_imports_keccak256 : + IsImported globals "ethereum.crypto.hash" "keccak256". + +Axiom ethereum_utils_ensure_imports_ensure : + IsImported globals "ethereum.utils.ensure" "ensure". + +Axiom ethereum_utils_numeric_imports_ceil32 : + IsImported globals "ethereum.utils.numeric" "ceil32". + +Axiom ethereum_gray_glacier_fork_types_imports_EMPTY_ACCOUNT : + IsImported globals "ethereum.gray_glacier.fork_types" "EMPTY_ACCOUNT". + +Axiom ethereum_gray_glacier_state_imports_get_account : + IsImported globals "ethereum.gray_glacier.state" "get_account". + +Axiom ethereum_gray_glacier_utils_address_imports_to_address : + IsImported globals "ethereum.gray_glacier.utils.address" "to_address". + +Axiom ethereum_gray_glacier_vm_memory_imports_buffer_read : + IsImported globals "ethereum.gray_glacier.vm.memory" "buffer_read". +Axiom ethereum_gray_glacier_vm_memory_imports_memory_write : + IsImported globals "ethereum.gray_glacier.vm.memory" "memory_write". + +Axiom ethereum_gray_glacier_vm_imports_Evm : + IsImported globals "ethereum.gray_glacier.vm" "Evm". + +Axiom ethereum_gray_glacier_vm_exceptions_imports_OutOfBoundsRead : + IsImported globals "ethereum.gray_glacier.vm.exceptions" "OutOfBoundsRead". + +Axiom ethereum_gray_glacier_vm_gas_imports_GAS_BASE : + IsImported globals "ethereum.gray_glacier.vm.gas" "GAS_BASE". +Axiom ethereum_gray_glacier_vm_gas_imports_GAS_COLD_ACCOUNT_ACCESS : + IsImported globals "ethereum.gray_glacier.vm.gas" "GAS_COLD_ACCOUNT_ACCESS". +Axiom ethereum_gray_glacier_vm_gas_imports_GAS_COPY : + IsImported globals "ethereum.gray_glacier.vm.gas" "GAS_COPY". +Axiom ethereum_gray_glacier_vm_gas_imports_GAS_FAST_STEP : + IsImported globals "ethereum.gray_glacier.vm.gas" "GAS_FAST_STEP". +Axiom ethereum_gray_glacier_vm_gas_imports_GAS_RETURN_DATA_COPY : + IsImported globals "ethereum.gray_glacier.vm.gas" "GAS_RETURN_DATA_COPY". +Axiom ethereum_gray_glacier_vm_gas_imports_GAS_VERY_LOW : + IsImported globals "ethereum.gray_glacier.vm.gas" "GAS_VERY_LOW". +Axiom ethereum_gray_glacier_vm_gas_imports_GAS_WARM_ACCESS : + IsImported globals "ethereum.gray_glacier.vm.gas" "GAS_WARM_ACCESS". +Axiom ethereum_gray_glacier_vm_gas_imports_calculate_gas_extend_memory : + IsImported globals "ethereum.gray_glacier.vm.gas" "calculate_gas_extend_memory". +Axiom ethereum_gray_glacier_vm_gas_imports_charge_gas : + IsImported globals "ethereum.gray_glacier.vm.gas" "charge_gas". + +Axiom ethereum_gray_glacier_vm_stack_imports_pop : + IsImported globals "ethereum.gray_glacier.vm.stack" "pop". +Axiom ethereum_gray_glacier_vm_stack_imports_push : + IsImported globals "ethereum.gray_glacier.vm.stack" "push". + +Definition address : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Pushes the address of the current executing account to the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_BASE" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.call (| + M.get_field (| M.get_name (| globals, "U256" |), "from_be_bytes" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "current_target" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition balance : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Pushes the balance of the given account onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "address" , + M.call (| + M.get_name (| globals, "to_address" |), + make_list [ + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.in_ (| + M.get_name (| globals, "address" |), + M.get_field (| M.get_name (| globals, "evm" |), "accessed_addresses" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_WARM_ACCESS" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "accessed_addresses" |), "add" |), + make_list [ + M.get_name (| globals, "address" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_COLD_ACCOUNT_ACCESS" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "balance" , + M.get_field (| M.call (| + M.get_name (| globals, "get_account" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "env" |), "state" |); + M.get_name (| globals, "address" |) + ], + make_dict [] + |), "balance" |) + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.get_name (| globals, "balance" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition origin : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Pushes the address of the original transaction sender to the stack. + The origin address can only be an EOA. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_BASE" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.call (| + M.get_field (| M.get_name (| globals, "U256" |), "from_be_bytes" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "env" |), "origin" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition caller : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Pushes the address of the caller onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_BASE" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.call (| + M.get_field (| M.get_name (| globals, "U256" |), "from_be_bytes" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "caller" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition callvalue : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Push the value (in wei) sent with the call onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_BASE" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "value" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition calldataload : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Push a word (32 bytes) of the input data belonging to the current + environment onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "start_index" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_VERY_LOW" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "value" , + M.call (| + M.get_name (| globals, "buffer_read" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "data" |); + M.get_name (| globals, "start_index" |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 32 + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.call (| + M.get_field (| M.get_name (| globals, "U256" |), "from_be_bytes" |), + make_list [ + M.get_name (| globals, "value" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition calldatasize : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Push the size of input data in current environment onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_BASE" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "data" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition calldatacopy : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Copy a portion of the input data in current environment to memory. + + This will also expand the memory, in case that the memory is insufficient + to store the data. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "memory_start_index" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "data_start_index" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "size" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "words" , + BinOp.floor_div (| + M.call (| + M.get_name (| globals, "ceil32" |), + make_list [ + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.get_name (| globals, "size" |) + ], + make_dict [] + |) + ], + make_dict [] + |), + Constant.int 32 + |) + |) in + let _ := M.assign_local (| + "copy_gas_cost" , + BinOp.mult (| + M.get_name (| globals, "GAS_COPY" |), + M.get_name (| globals, "words" |) + |) + |) in + let _ := M.assign_local (| + "extend_memory" , + M.call (| + M.get_name (| globals, "calculate_gas_extend_memory" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "memory" |); + make_list [ + make_tuple [ M.get_name (| globals, "memory_start_index" |); M.get_name (| globals, "size" |) ] + ] + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + BinOp.add (| + BinOp.add (| + M.get_name (| globals, "GAS_VERY_LOW" |), + M.get_name (| globals, "copy_gas_cost" |) + |), + M.get_field (| M.get_name (| globals, "extend_memory" |), "cost" |) + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "memory" |), + BinOp.mult (| + Constant.bytes "00", + M.get_field (| M.get_name (| globals, "extend_memory" |), "expand_by" |) + |) + |) in + let _ := M.assign_local (| + "value" , + M.call (| + M.get_name (| globals, "buffer_read" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "data" |); + M.get_name (| globals, "data_start_index" |); + M.get_name (| globals, "size" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "memory_write" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "memory" |); + M.get_name (| globals, "memory_start_index" |); + M.get_name (| globals, "value" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition codesize : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Push the size of code running in current environment onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_BASE" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "code" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition codecopy : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Copy a portion of the code in current environment to memory. + + This will also expand the memory, in case that the memory is insufficient + to store the data. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "memory_start_index" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "code_start_index" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "size" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "words" , + BinOp.floor_div (| + M.call (| + M.get_name (| globals, "ceil32" |), + make_list [ + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.get_name (| globals, "size" |) + ], + make_dict [] + |) + ], + make_dict [] + |), + Constant.int 32 + |) + |) in + let _ := M.assign_local (| + "copy_gas_cost" , + BinOp.mult (| + M.get_name (| globals, "GAS_COPY" |), + M.get_name (| globals, "words" |) + |) + |) in + let _ := M.assign_local (| + "extend_memory" , + M.call (| + M.get_name (| globals, "calculate_gas_extend_memory" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "memory" |); + make_list [ + make_tuple [ M.get_name (| globals, "memory_start_index" |); M.get_name (| globals, "size" |) ] + ] + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + BinOp.add (| + BinOp.add (| + M.get_name (| globals, "GAS_VERY_LOW" |), + M.get_name (| globals, "copy_gas_cost" |) + |), + M.get_field (| M.get_name (| globals, "extend_memory" |), "cost" |) + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "memory" |), + BinOp.mult (| + Constant.bytes "00", + M.get_field (| M.get_name (| globals, "extend_memory" |), "expand_by" |) + |) + |) in + let _ := M.assign_local (| + "value" , + M.call (| + M.get_name (| globals, "buffer_read" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "code" |); + M.get_name (| globals, "code_start_index" |); + M.get_name (| globals, "size" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "memory_write" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "memory" |); + M.get_name (| globals, "memory_start_index" |); + M.get_name (| globals, "value" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition gasprice : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Push the gas price used in current environment onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_BASE" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "env" |), "gas_price" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition extcodesize : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Push the code size of a given account onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "address" , + M.call (| + M.get_name (| globals, "to_address" |), + make_list [ + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.in_ (| + M.get_name (| globals, "address" |), + M.get_field (| M.get_name (| globals, "evm" |), "accessed_addresses" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_WARM_ACCESS" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "accessed_addresses" |), "add" |), + make_list [ + M.get_name (| globals, "address" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_COLD_ACCOUNT_ACCESS" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "codesize" , + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_field (| M.call (| + M.get_name (| globals, "get_account" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "env" |), "state" |); + M.get_name (| globals, "address" |) + ], + make_dict [] + |), "code" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.get_name (| globals, "codesize" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition extcodecopy : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Copy a portion of an account's code to memory. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "address" , + M.call (| + M.get_name (| globals, "to_address" |), + make_list [ + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_start_index" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "code_start_index" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "size" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "words" , + BinOp.floor_div (| + M.call (| + M.get_name (| globals, "ceil32" |), + make_list [ + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.get_name (| globals, "size" |) + ], + make_dict [] + |) + ], + make_dict [] + |), + Constant.int 32 + |) + |) in + let _ := M.assign_local (| + "copy_gas_cost" , + BinOp.mult (| + M.get_name (| globals, "GAS_COPY" |), + M.get_name (| globals, "words" |) + |) + |) in + let _ := M.assign_local (| + "extend_memory" , + M.call (| + M.get_name (| globals, "calculate_gas_extend_memory" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "memory" |); + make_list [ + make_tuple [ M.get_name (| globals, "memory_start_index" |); M.get_name (| globals, "size" |) ] + ] + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.in_ (| + M.get_name (| globals, "address" |), + M.get_field (| M.get_name (| globals, "evm" |), "accessed_addresses" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + BinOp.add (| + BinOp.add (| + M.get_name (| globals, "GAS_WARM_ACCESS" |), + M.get_name (| globals, "copy_gas_cost" |) + |), + M.get_field (| M.get_name (| globals, "extend_memory" |), "cost" |) + |) + ], + make_dict [] + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "accessed_addresses" |), "add" |), + make_list [ + M.get_name (| globals, "address" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + BinOp.add (| + BinOp.add (| + M.get_name (| globals, "GAS_COLD_ACCOUNT_ACCESS" |), + M.get_name (| globals, "copy_gas_cost" |) + |), + M.get_field (| M.get_name (| globals, "extend_memory" |), "cost" |) + |) + ], + make_dict [] + |) in + M.pure Constant.None_ + )) |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "memory" |), + BinOp.mult (| + Constant.bytes "00", + M.get_field (| M.get_name (| globals, "extend_memory" |), "expand_by" |) + |) + |) in + let _ := M.assign_local (| + "code" , + M.get_field (| M.call (| + M.get_name (| globals, "get_account" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "env" |), "state" |); + M.get_name (| globals, "address" |) + ], + make_dict [] + |), "code" |) + |) in + let _ := M.assign_local (| + "value" , + M.call (| + M.get_name (| globals, "buffer_read" |), + make_list [ + M.get_name (| globals, "code" |); + M.get_name (| globals, "code_start_index" |); + M.get_name (| globals, "size" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "memory_write" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "memory" |); + M.get_name (| globals, "memory_start_index" |); + M.get_name (| globals, "value" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition returndatasize : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Pushes the size of the return data buffer onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_BASE" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "return_data" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition returndatacopy : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Copies data from the return data buffer code to memory + + Parameters + ---------- + evm : + The current EVM frame. + " in + let _ := M.assign_local (| + "memory_start_index" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "return_data_start_position" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "size" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "words" , + BinOp.floor_div (| + M.call (| + M.get_name (| globals, "ceil32" |), + make_list [ + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.get_name (| globals, "size" |) + ], + make_dict [] + |) + ], + make_dict [] + |), + Constant.int 32 + |) + |) in + let _ := M.assign_local (| + "copy_gas_cost" , + BinOp.mult (| + M.get_name (| globals, "GAS_RETURN_DATA_COPY" |), + M.get_name (| globals, "words" |) + |) + |) in + let _ := M.assign_local (| + "extend_memory" , + M.call (| + M.get_name (| globals, "calculate_gas_extend_memory" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "memory" |); + make_list [ + make_tuple [ M.get_name (| globals, "memory_start_index" |); M.get_name (| globals, "size" |) ] + ] + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + BinOp.add (| + BinOp.add (| + M.get_name (| globals, "GAS_VERY_LOW" |), + M.get_name (| globals, "copy_gas_cost" |) + |), + M.get_field (| M.get_name (| globals, "extend_memory" |), "cost" |) + |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + Compare.lt_e (| + BinOp.add (| + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.get_name (| globals, "return_data_start_position" |) + ], + make_dict [] + |), + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.get_name (| globals, "size" |) + ], + make_dict [] + |) + |), + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "return_data" |) + ], + make_dict [] + |) + |); + M.get_name (| globals, "OutOfBoundsRead" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "memory" |), + BinOp.mult (| + Constant.bytes "00", + M.get_field (| M.get_name (| globals, "extend_memory" |), "expand_by" |) + |) + |) in + let _ := M.assign_local (| + "value" , + M.slice (| + M.get_field (| M.get_name (| globals, "evm" |), "return_data" |), + M.get_name (| globals, "return_data_start_position" |), + BinOp.add (| + M.get_name (| globals, "return_data_start_position" |), + M.get_name (| globals, "size" |) + |), + Constant.None_ + |) + |) in + let _ := M.call (| + M.get_name (| globals, "memory_write" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "memory" |); + M.get_name (| globals, "memory_start_index" |); + M.get_name (| globals, "value" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition extcodehash : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Returns the keccak256 hash of a contract’s bytecode + Parameters + ---------- + evm : + The current EVM frame. + " in + let _ := M.assign_local (| + "address" , + M.call (| + M.get_name (| globals, "to_address" |), + make_list [ + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.in_ (| + M.get_name (| globals, "address" |), + M.get_field (| M.get_name (| globals, "evm" |), "accessed_addresses" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_WARM_ACCESS" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "accessed_addresses" |), "add" |), + make_list [ + M.get_name (| globals, "address" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_COLD_ACCOUNT_ACCESS" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "account" , + M.call (| + M.get_name (| globals, "get_account" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "env" |), "state" |); + M.get_name (| globals, "address" |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, "account" |), + M.get_name (| globals, "EMPTY_ACCOUNT" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "codehash" , + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "codehash" , + M.call (| + M.get_field (| M.get_name (| globals, "U256" |), "from_be_bytes" |), + make_list [ + M.call (| + M.get_name (| globals, "keccak256" |), + make_list [ + M.get_field (| M.get_name (| globals, "account" |), "code" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + )) |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.get_name (| globals, "codehash" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition self_balance : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Pushes the balance of the current address to the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_FAST_STEP" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "balance" , + M.get_field (| M.call (| + M.get_name (| globals, "get_account" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "env" |), "state" |); + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "current_target" |) + ], + make_dict [] + |), "balance" |) + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.get_name (| globals, "balance" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition base_fee : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Pushes the base fee of the current block on to the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_BASE" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "env" |), "base_fee_per_gas" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). diff --git a/CoqOfPython/ethereum/gray_glacier/vm/instructions/keccak.v b/CoqOfPython/ethereum/gray_glacier/vm/instructions/keccak.v new file mode 100644 index 0000000..a82edc7 --- /dev/null +++ b/CoqOfPython/ethereum/gray_glacier/vm/instructions/keccak.v @@ -0,0 +1,188 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.gray_glacier.vm.instructions.keccak". + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) Keccak Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM keccak instructions. +". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". + +Axiom ethereum_crypto_hash_imports_keccak256 : + IsImported globals "ethereum.crypto.hash" "keccak256". + +Axiom ethereum_utils_numeric_imports_ceil32 : + IsImported globals "ethereum.utils.numeric" "ceil32". + +Axiom ethereum_gray_glacier_vm_imports_Evm : + IsImported globals "ethereum.gray_glacier.vm" "Evm". + +Axiom ethereum_gray_glacier_vm_gas_imports_GAS_KECCAK256 : + IsImported globals "ethereum.gray_glacier.vm.gas" "GAS_KECCAK256". +Axiom ethereum_gray_glacier_vm_gas_imports_GAS_KECCAK256_WORD : + IsImported globals "ethereum.gray_glacier.vm.gas" "GAS_KECCAK256_WORD". +Axiom ethereum_gray_glacier_vm_gas_imports_calculate_gas_extend_memory : + IsImported globals "ethereum.gray_glacier.vm.gas" "calculate_gas_extend_memory". +Axiom ethereum_gray_glacier_vm_gas_imports_charge_gas : + IsImported globals "ethereum.gray_glacier.vm.gas" "charge_gas". + +Axiom ethereum_gray_glacier_vm_memory_imports_memory_read_bytes : + IsImported globals "ethereum.gray_glacier.vm.memory" "memory_read_bytes". + +Axiom ethereum_gray_glacier_vm_stack_imports_pop : + IsImported globals "ethereum.gray_glacier.vm.stack" "pop". +Axiom ethereum_gray_glacier_vm_stack_imports_push : + IsImported globals "ethereum.gray_glacier.vm.stack" "push". + +Definition keccak : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Pushes to the stack the Keccak-256 hash of a region of memory. + + This also expands the memory, in case the memory is insufficient to + access the data's memory location. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "memory_start_index" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "size" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "words" , + BinOp.floor_div (| + M.call (| + M.get_name (| globals, "ceil32" |), + make_list [ + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.get_name (| globals, "size" |) + ], + make_dict [] + |) + ], + make_dict [] + |), + Constant.int 32 + |) + |) in + let _ := M.assign_local (| + "word_gas_cost" , + BinOp.mult (| + M.get_name (| globals, "GAS_KECCAK256_WORD" |), + M.get_name (| globals, "words" |) + |) + |) in + let _ := M.assign_local (| + "extend_memory" , + M.call (| + M.get_name (| globals, "calculate_gas_extend_memory" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "memory" |); + make_list [ + make_tuple [ M.get_name (| globals, "memory_start_index" |); M.get_name (| globals, "size" |) ] + ] + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + BinOp.add (| + BinOp.add (| + M.get_name (| globals, "GAS_KECCAK256" |), + M.get_name (| globals, "word_gas_cost" |) + |), + M.get_field (| M.get_name (| globals, "extend_memory" |), "cost" |) + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "memory" |), + BinOp.mult (| + Constant.bytes "00", + M.get_field (| M.get_name (| globals, "extend_memory" |), "expand_by" |) + |) + |) in + let _ := M.assign_local (| + "data" , + M.call (| + M.get_name (| globals, "memory_read_bytes" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "memory" |); + M.get_name (| globals, "memory_start_index" |); + M.get_name (| globals, "size" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "hash" , + M.call (| + M.get_name (| globals, "keccak256" |), + make_list [ + M.get_name (| globals, "data" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.call (| + M.get_field (| M.get_name (| globals, "U256" |), "from_be_bytes" |), + make_list [ + M.get_name (| globals, "hash" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). diff --git a/CoqOfPython/ethereum/gray_glacier/vm/instructions/log.v b/CoqOfPython/ethereum/gray_glacier/vm/instructions/log.v new file mode 100644 index 0000000..6e41a53 --- /dev/null +++ b/CoqOfPython/ethereum/gray_glacier/vm/instructions/log.v @@ -0,0 +1,256 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.gray_glacier.vm.instructions.log". + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) Logging Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM logging instructions. +". + +Axiom functools_imports_partial : + IsImported globals "functools" "partial". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". + +Axiom ethereum_utils_ensure_imports_ensure : + IsImported globals "ethereum.utils.ensure" "ensure". + +Axiom ethereum_gray_glacier_blocks_imports_Log : + IsImported globals "ethereum.gray_glacier.blocks" "Log". + +Axiom ethereum_gray_glacier_vm_imports_Evm : + IsImported globals "ethereum.gray_glacier.vm" "Evm". + +Axiom ethereum_gray_glacier_vm_exceptions_imports_WriteInStaticContext : + IsImported globals "ethereum.gray_glacier.vm.exceptions" "WriteInStaticContext". + +Axiom ethereum_gray_glacier_vm_gas_imports_GAS_LOG : + IsImported globals "ethereum.gray_glacier.vm.gas" "GAS_LOG". +Axiom ethereum_gray_glacier_vm_gas_imports_GAS_LOG_DATA : + IsImported globals "ethereum.gray_glacier.vm.gas" "GAS_LOG_DATA". +Axiom ethereum_gray_glacier_vm_gas_imports_GAS_LOG_TOPIC : + IsImported globals "ethereum.gray_glacier.vm.gas" "GAS_LOG_TOPIC". +Axiom ethereum_gray_glacier_vm_gas_imports_calculate_gas_extend_memory : + IsImported globals "ethereum.gray_glacier.vm.gas" "calculate_gas_extend_memory". +Axiom ethereum_gray_glacier_vm_gas_imports_charge_gas : + IsImported globals "ethereum.gray_glacier.vm.gas" "charge_gas". + +Axiom ethereum_gray_glacier_vm_memory_imports_memory_read_bytes : + IsImported globals "ethereum.gray_glacier.vm.memory" "memory_read_bytes". + +Axiom ethereum_gray_glacier_vm_stack_imports_pop : + IsImported globals "ethereum.gray_glacier.vm.stack" "pop". + +Definition log_n : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm"; "num_topics" ] |) in + let _ := Constant.str " + Appends a log entry, having `num_topics` topics, to the evm logs. + + This will also expand the memory if the data (required by the log entry) + corresponding to the memory is not accessible. + + Parameters + ---------- + evm : + The current EVM frame. + num_topics : + The number of topics to be included in the log entry. + + " in + let _ := M.assign_local (| + "memory_start_index" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "size" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "topics" , + make_list [] + |) in + let _ := + M.for_ (| + M.get_name (| globals, "_" |), + M.call (| + M.get_name (| globals, "range" |), + make_list [ + M.get_name (| globals, "num_topics" |) + ], + make_dict [] + |), + ltac:(M.monadic ( + let _ := M.assign_local (| + "topic" , + M.call (| + M.get_field (| M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |), "to_be_bytes32" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_field (| M.get_name (| globals, "topics" |), "append" |), + make_list [ + M.get_name (| globals, "topic" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := M.assign_local (| + "extend_memory" , + M.call (| + M.get_name (| globals, "calculate_gas_extend_memory" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "memory" |); + make_list [ + make_tuple [ M.get_name (| globals, "memory_start_index" |); M.get_name (| globals, "size" |) ] + ] + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + BinOp.add (| + BinOp.add (| + BinOp.add (| + M.get_name (| globals, "GAS_LOG" |), + BinOp.mult (| + M.get_name (| globals, "GAS_LOG_DATA" |), + M.get_name (| globals, "size" |) + |) + |), + BinOp.mult (| + M.get_name (| globals, "GAS_LOG_TOPIC" |), + M.get_name (| globals, "num_topics" |) + |) + |), + M.get_field (| M.get_name (| globals, "extend_memory" |), "cost" |) + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "memory" |), + BinOp.mult (| + Constant.bytes "00", + M.get_field (| M.get_name (| globals, "extend_memory" |), "expand_by" |) + |) + |) in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + UnOp.not (| M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "is_static" |) |); + M.get_name (| globals, "WriteInStaticContext" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "log_entry" , + M.call (| + M.get_name (| globals, "Log" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, "evm" |), "logs" |), + BinOp.add (| + M.get_field (| M.get_name (| globals, "evm" |), "logs" |), + make_tuple [ M.get_name (| globals, "log_entry" |) ] + |) + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition log0 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "log_n" |) + ], + make_dict [] + |) +)). + +Definition log1 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "log_n" |) + ], + make_dict [] + |) +)). + +Definition log2 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "log_n" |) + ], + make_dict [] + |) +)). + +Definition log3 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "log_n" |) + ], + make_dict [] + |) +)). + +Definition log4 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "log_n" |) + ], + make_dict [] + |) +)). diff --git a/CoqOfPython/ethereum/gray_glacier/vm/instructions/memory.v b/CoqOfPython/ethereum/gray_glacier/vm/instructions/memory.v new file mode 100644 index 0000000..1516f1c --- /dev/null +++ b/CoqOfPython/ethereum/gray_glacier/vm/instructions/memory.v @@ -0,0 +1,393 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.gray_glacier.vm.instructions.memory". + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) Memory Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM Memory instructions. +". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_Bytes : + IsImported globals "ethereum.base_types" "Bytes". + +Axiom ethereum_gray_glacier_vm_imports_Evm : + IsImported globals "ethereum.gray_glacier.vm" "Evm". + +Axiom ethereum_gray_glacier_vm_gas_imports_GAS_BASE : + IsImported globals "ethereum.gray_glacier.vm.gas" "GAS_BASE". +Axiom ethereum_gray_glacier_vm_gas_imports_GAS_VERY_LOW : + IsImported globals "ethereum.gray_glacier.vm.gas" "GAS_VERY_LOW". +Axiom ethereum_gray_glacier_vm_gas_imports_calculate_gas_extend_memory : + IsImported globals "ethereum.gray_glacier.vm.gas" "calculate_gas_extend_memory". +Axiom ethereum_gray_glacier_vm_gas_imports_charge_gas : + IsImported globals "ethereum.gray_glacier.vm.gas" "charge_gas". + +Axiom ethereum_gray_glacier_vm_memory_imports_memory_read_bytes : + IsImported globals "ethereum.gray_glacier.vm.memory" "memory_read_bytes". +Axiom ethereum_gray_glacier_vm_memory_imports_memory_write : + IsImported globals "ethereum.gray_glacier.vm.memory" "memory_write". + +Axiom ethereum_gray_glacier_vm_stack_imports_pop : + IsImported globals "ethereum.gray_glacier.vm.stack" "pop". +Axiom ethereum_gray_glacier_vm_stack_imports_push : + IsImported globals "ethereum.gray_glacier.vm.stack" "push". + +Definition mstore : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Stores a word to memory. + This also expands the memory, if the memory is + insufficient to store the word. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "start_position" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "value" , + M.call (| + M.get_field (| M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |), "to_be_bytes32" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "extend_memory" , + M.call (| + M.get_name (| globals, "calculate_gas_extend_memory" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "memory" |); + make_list [ + make_tuple [ M.get_name (| globals, "start_position" |); M.call (| + M.get_name (| globals, "U256" |), + make_list [ + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_name (| globals, "value" |) + ], + make_dict [] + |) + ], + make_dict [] + |) ] + ] + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + BinOp.add (| + M.get_name (| globals, "GAS_VERY_LOW" |), + M.get_field (| M.get_name (| globals, "extend_memory" |), "cost" |) + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "memory" |), + BinOp.mult (| + Constant.bytes "00", + M.get_field (| M.get_name (| globals, "extend_memory" |), "expand_by" |) + |) + |) in + let _ := M.call (| + M.get_name (| globals, "memory_write" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "memory" |); + M.get_name (| globals, "start_position" |); + M.get_name (| globals, "value" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition mstore8 : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Stores a byte to memory. + This also expands the memory, if the memory is + insufficient to store the word. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "start_position" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "value" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "extend_memory" , + M.call (| + M.get_name (| globals, "calculate_gas_extend_memory" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "memory" |); + make_list [ + make_tuple [ M.get_name (| globals, "start_position" |); M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 1 + ], + make_dict [] + |) ] + ] + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + BinOp.add (| + M.get_name (| globals, "GAS_VERY_LOW" |), + M.get_field (| M.get_name (| globals, "extend_memory" |), "cost" |) + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "memory" |), + BinOp.mult (| + Constant.bytes "00", + M.get_field (| M.get_name (| globals, "extend_memory" |), "expand_by" |) + |) + |) in + let _ := M.assign_local (| + "normalized_bytes_value" , + M.call (| + M.get_name (| globals, "Bytes" |), + make_list [ + make_list [ + BinOp.bit_and (| + M.get_name (| globals, "value" |), + Constant.int 255 + |) + ] + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "memory_write" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "memory" |); + M.get_name (| globals, "start_position" |); + M.get_name (| globals, "normalized_bytes_value" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition mload : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Load word from memory. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "start_position" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "extend_memory" , + M.call (| + M.get_name (| globals, "calculate_gas_extend_memory" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "memory" |); + make_list [ + make_tuple [ M.get_name (| globals, "start_position" |); M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 32 + ], + make_dict [] + |) ] + ] + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + BinOp.add (| + M.get_name (| globals, "GAS_VERY_LOW" |), + M.get_field (| M.get_name (| globals, "extend_memory" |), "cost" |) + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "memory" |), + BinOp.mult (| + Constant.bytes "00", + M.get_field (| M.get_name (| globals, "extend_memory" |), "expand_by" |) + |) + |) in + let _ := M.assign_local (| + "value" , + M.call (| + M.get_field (| M.get_name (| globals, "U256" |), "from_be_bytes" |), + make_list [ + M.call (| + M.get_name (| globals, "memory_read_bytes" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "memory" |); + M.get_name (| globals, "start_position" |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 32 + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.get_name (| globals, "value" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition msize : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Push the size of active memory in bytes onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_BASE" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "memory" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). diff --git a/CoqOfPython/ethereum/gray_glacier/vm/instructions/stack.v b/CoqOfPython/ethereum/gray_glacier/vm/instructions/stack.v new file mode 100644 index 0000000..c680a10 --- /dev/null +++ b/CoqOfPython/ethereum/gray_glacier/vm/instructions/stack.v @@ -0,0 +1,947 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.gray_glacier.vm.instructions.stack". + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) Stack Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM stack related instructions. +". + +Axiom functools_imports_partial : + IsImported globals "functools" "partial". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". + +Axiom ethereum_utils_ensure_imports_ensure : + IsImported globals "ethereum.utils.ensure" "ensure". + +Axiom ethereum_gray_glacier_vm_imports_Evm : + IsImported globals "ethereum.gray_glacier.vm" "Evm". +Axiom ethereum_gray_glacier_vm_imports_stack : + IsImported globals "ethereum.gray_glacier.vm" "stack". + +Axiom ethereum_gray_glacier_vm_exceptions_imports_StackUnderflowError : + IsImported globals "ethereum.gray_glacier.vm.exceptions" "StackUnderflowError". + +Axiom ethereum_gray_glacier_vm_gas_imports_GAS_BASE : + IsImported globals "ethereum.gray_glacier.vm.gas" "GAS_BASE". +Axiom ethereum_gray_glacier_vm_gas_imports_GAS_VERY_LOW : + IsImported globals "ethereum.gray_glacier.vm.gas" "GAS_VERY_LOW". +Axiom ethereum_gray_glacier_vm_gas_imports_charge_gas : + IsImported globals "ethereum.gray_glacier.vm.gas" "charge_gas". + +Axiom ethereum_gray_glacier_vm_memory_imports_buffer_read : + IsImported globals "ethereum.gray_glacier.vm.memory" "buffer_read". + +Definition pop : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Remove item from stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.call (| + M.get_field (| M.get_name (| globals, "stack" |), "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_BASE" |) + ], + make_dict [] + |) in + let _ := M.pass (| |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition push_n : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm"; "num_bytes" ] |) in + let _ := Constant.str " + Pushes a N-byte immediate onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + num_bytes : + The number of immediate bytes to be read from the code and pushed to + the stack. + + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_VERY_LOW" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "data_to_push" , + M.call (| + M.get_field (| M.get_name (| globals, "U256" |), "from_be_bytes" |), + make_list [ + M.call (| + M.get_name (| globals, "buffer_read" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "code" |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + BinOp.add (| + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) + ], + make_dict [] + |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + M.get_name (| globals, "num_bytes" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_field (| M.get_name (| globals, "stack" |), "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.get_name (| globals, "data_to_push" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + BinOp.add (| + Constant.int 1, + M.get_name (| globals, "num_bytes" |) + |) + |) in + M.pure Constant.None_)). + +Definition dup_n : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm"; "item_number" ] |) in + let _ := Constant.str " + Duplicate the Nth stack item (from top of the stack) to the top of stack. + + Parameters + ---------- + evm : + The current EVM frame. + + item_number : + The stack item number (0-indexed from top of stack) to be duplicated + to the top of stack. + + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_VERY_LOW" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + Compare.lt (| + M.get_name (| globals, "item_number" |), + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |); + M.get_name (| globals, "StackUnderflowError" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "data_to_duplicate" , + M.get_subscript (| + M.get_field (| M.get_name (| globals, "evm" |), "stack" |), + BinOp.sub (| + BinOp.sub (| + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |), + Constant.int 1 + |), + M.get_name (| globals, "item_number" |) + |) + |) + |) in + let _ := M.call (| + M.get_field (| M.get_name (| globals, "stack" |), "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.get_name (| globals, "data_to_duplicate" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition swap_n : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm"; "item_number" ] |) in + let _ := Constant.str " + Swap the top and the `item_number` element of the stack, where + the top of the stack is position zero. + + If `item_number` is zero, this function does nothing (which should not be + possible, since there is no `SWAP0` instruction). + + Parameters + ---------- + evm : + The current EVM frame. + + item_number : + The stack item number (0-indexed from top of stack) to be swapped + with the top of stack element. + + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_VERY_LOW" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + Compare.lt (| + M.get_name (| globals, "item_number" |), + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |); + M.get_name (| globals, "StackUnderflowError" |) + ], + make_dict [] + |) in + let _ := M.assign (| + make_tuple [ M.get_subscript (| + M.get_field (| M.get_name (| globals, "evm" |), "stack" |), + UnOp.sub (| Constant.int 1 |) + |); M.get_subscript (| + M.get_field (| M.get_name (| globals, "evm" |), "stack" |), + BinOp.sub (| + UnOp.sub (| Constant.int 1 |), + M.get_name (| globals, "item_number" |) + |) + |) ], + make_tuple [ M.get_subscript (| + M.get_field (| M.get_name (| globals, "evm" |), "stack" |), + BinOp.sub (| + UnOp.sub (| Constant.int 1 |), + M.get_name (| globals, "item_number" |) + |) + |); M.get_subscript (| + M.get_field (| M.get_name (| globals, "evm" |), "stack" |), + UnOp.sub (| Constant.int 1 |) + |) ] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition push1 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push2 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push3 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push4 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push5 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push6 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push7 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push8 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push9 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push10 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push11 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push12 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push13 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push14 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push15 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push16 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push17 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push18 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push19 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push20 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push21 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push22 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push23 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push24 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push25 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push26 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push27 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push28 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push29 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push30 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push31 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push32 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "push_n" |) + ], + make_dict [] + |) +)). + +Definition dup1 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "dup_n" |) + ], + make_dict [] + |) +)). + +Definition dup2 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "dup_n" |) + ], + make_dict [] + |) +)). + +Definition dup3 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "dup_n" |) + ], + make_dict [] + |) +)). + +Definition dup4 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "dup_n" |) + ], + make_dict [] + |) +)). + +Definition dup5 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "dup_n" |) + ], + make_dict [] + |) +)). + +Definition dup6 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "dup_n" |) + ], + make_dict [] + |) +)). + +Definition dup7 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "dup_n" |) + ], + make_dict [] + |) +)). + +Definition dup8 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "dup_n" |) + ], + make_dict [] + |) +)). + +Definition dup9 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "dup_n" |) + ], + make_dict [] + |) +)). + +Definition dup10 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "dup_n" |) + ], + make_dict [] + |) +)). + +Definition dup11 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "dup_n" |) + ], + make_dict [] + |) +)). + +Definition dup12 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "dup_n" |) + ], + make_dict [] + |) +)). + +Definition dup13 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "dup_n" |) + ], + make_dict [] + |) +)). + +Definition dup14 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "dup_n" |) + ], + make_dict [] + |) +)). + +Definition dup15 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "dup_n" |) + ], + make_dict [] + |) +)). + +Definition dup16 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "dup_n" |) + ], + make_dict [] + |) +)). + +Definition swap1 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "swap_n" |) + ], + make_dict [] + |) +)). + +Definition swap2 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "swap_n" |) + ], + make_dict [] + |) +)). + +Definition swap3 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "swap_n" |) + ], + make_dict [] + |) +)). + +Definition swap4 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "swap_n" |) + ], + make_dict [] + |) +)). + +Definition swap5 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "swap_n" |) + ], + make_dict [] + |) +)). + +Definition swap6 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "swap_n" |) + ], + make_dict [] + |) +)). + +Definition swap7 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "swap_n" |) + ], + make_dict [] + |) +)). + +Definition swap8 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "swap_n" |) + ], + make_dict [] + |) +)). + +Definition swap9 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "swap_n" |) + ], + make_dict [] + |) +)). + +Definition swap10 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "swap_n" |) + ], + make_dict [] + |) +)). + +Definition swap11 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "swap_n" |) + ], + make_dict [] + |) +)). + +Definition swap12 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "swap_n" |) + ], + make_dict [] + |) +)). + +Definition swap13 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "swap_n" |) + ], + make_dict [] + |) +)). + +Definition swap14 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "swap_n" |) + ], + make_dict [] + |) +)). + +Definition swap15 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "swap_n" |) + ], + make_dict [] + |) +)). + +Definition swap16 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "swap_n" |) + ], + make_dict [] + |) +)). diff --git a/CoqOfPython/ethereum/gray_glacier/vm/instructions/storage.v b/CoqOfPython/ethereum/gray_glacier/vm/instructions/storage.v new file mode 100644 index 0000000..81cda0d --- /dev/null +++ b/CoqOfPython/ethereum/gray_glacier/vm/instructions/storage.v @@ -0,0 +1,491 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.gray_glacier.vm.instructions.storage". + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) Storage Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM storage related instructions. +". + +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". + +Axiom ethereum_utils_ensure_imports_ensure : + IsImported globals "ethereum.utils.ensure" "ensure". + +Axiom ethereum_gray_glacier_state_imports_get_storage : + IsImported globals "ethereum.gray_glacier.state" "get_storage". +Axiom ethereum_gray_glacier_state_imports_get_storage_original : + IsImported globals "ethereum.gray_glacier.state" "get_storage_original". +Axiom ethereum_gray_glacier_state_imports_set_storage : + IsImported globals "ethereum.gray_glacier.state" "set_storage". + +Axiom ethereum_gray_glacier_vm_imports_Evm : + IsImported globals "ethereum.gray_glacier.vm" "Evm". + +Axiom ethereum_gray_glacier_vm_exceptions_imports_OutOfGasError : + IsImported globals "ethereum.gray_glacier.vm.exceptions" "OutOfGasError". +Axiom ethereum_gray_glacier_vm_exceptions_imports_WriteInStaticContext : + IsImported globals "ethereum.gray_glacier.vm.exceptions" "WriteInStaticContext". + +Axiom ethereum_gray_glacier_vm_gas_imports_GAS_CALL_STIPEND : + IsImported globals "ethereum.gray_glacier.vm.gas" "GAS_CALL_STIPEND". +Axiom ethereum_gray_glacier_vm_gas_imports_GAS_COLD_SLOAD : + IsImported globals "ethereum.gray_glacier.vm.gas" "GAS_COLD_SLOAD". +Axiom ethereum_gray_glacier_vm_gas_imports_GAS_STORAGE_CLEAR_REFUND : + IsImported globals "ethereum.gray_glacier.vm.gas" "GAS_STORAGE_CLEAR_REFUND". +Axiom ethereum_gray_glacier_vm_gas_imports_GAS_STORAGE_SET : + IsImported globals "ethereum.gray_glacier.vm.gas" "GAS_STORAGE_SET". +Axiom ethereum_gray_glacier_vm_gas_imports_GAS_STORAGE_UPDATE : + IsImported globals "ethereum.gray_glacier.vm.gas" "GAS_STORAGE_UPDATE". +Axiom ethereum_gray_glacier_vm_gas_imports_GAS_WARM_ACCESS : + IsImported globals "ethereum.gray_glacier.vm.gas" "GAS_WARM_ACCESS". +Axiom ethereum_gray_glacier_vm_gas_imports_charge_gas : + IsImported globals "ethereum.gray_glacier.vm.gas" "charge_gas". + +Axiom ethereum_gray_glacier_vm_stack_imports_pop : + IsImported globals "ethereum.gray_glacier.vm.stack" "pop". +Axiom ethereum_gray_glacier_vm_stack_imports_push : + IsImported globals "ethereum.gray_glacier.vm.stack" "push". + +Definition sload : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Loads to the stack, the value corresponding to a certain key from the + storage of the current account. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "key" , + M.call (| + M.get_field (| M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |), "to_be_bytes32" |), + make_list [], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.in_ (| + make_tuple [ M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "current_target" |); M.get_name (| globals, "key" |) ], + M.get_field (| M.get_name (| globals, "evm" |), "accessed_storage_keys" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_WARM_ACCESS" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "accessed_storage_keys" |), "add" |), + make_list [ + make_tuple [ M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "current_target" |); M.get_name (| globals, "key" |) ] + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_COLD_SLOAD" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "value" , + M.call (| + M.get_name (| globals, "get_storage" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "env" |), "state" |); + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "current_target" |); + M.get_name (| globals, "key" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.get_name (| globals, "value" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition sstore : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Stores a value at a certain key in the current context's storage. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "key" , + M.call (| + M.get_field (| M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |), "to_be_bytes32" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "new_value" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + Compare.gt (| + M.get_field (| M.get_name (| globals, "evm" |), "gas_left" |), + M.get_name (| globals, "GAS_CALL_STIPEND" |) + |); + M.get_name (| globals, "OutOfGasError" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "original_value" , + M.call (| + M.get_name (| globals, "get_storage_original" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "env" |), "state" |); + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "current_target" |); + M.get_name (| globals, "key" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "current_value" , + M.call (| + M.get_name (| globals, "get_storage" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "env" |), "state" |); + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "current_target" |); + M.get_name (| globals, "key" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "gas_cost" , + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.not_in (| + make_tuple [ M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "current_target" |); M.get_name (| globals, "key" |) ], + M.get_field (| M.get_name (| globals, "evm" |), "accessed_storage_keys" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "accessed_storage_keys" |), "add" |), + make_list [ + make_tuple [ M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "current_target" |); M.get_name (| globals, "key" |) ] + ], + make_dict [] + |) in + let _ := M.assign_op_local (| + BinOp.add, + "gas_cost", + M.get_name (| globals, "GAS_COLD_SLOAD" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + BoolOp.and (| + Compare.eq (| + M.get_name (| globals, "original_value" |), + M.get_name (| globals, "current_value" |) + |), + ltac:(M.monadic ( + Compare.not_eq (| + M.get_name (| globals, "current_value" |), + M.get_name (| globals, "new_value" |) + |) + )) + |), + (* then *) + ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, "original_value" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_op_local (| + BinOp.add, + "gas_cost", + M.get_name (| globals, "GAS_STORAGE_SET" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_op_local (| + BinOp.add, + "gas_cost", + BinOp.sub (| + M.get_name (| globals, "GAS_STORAGE_UPDATE" |), + M.get_name (| globals, "GAS_COLD_SLOAD" |) + |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_op_local (| + BinOp.add, + "gas_cost", + M.get_name (| globals, "GAS_WARM_ACCESS" |) + |) in + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + Compare.not_eq (| + M.get_name (| globals, "current_value" |), + M.get_name (| globals, "new_value" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + BoolOp.and (| + Compare.not_eq (| + M.get_name (| globals, "original_value" |), + Constant.int 0 + |), + ltac:(M.monadic ( + BoolOp.and (| + Compare.not_eq (| + M.get_name (| globals, "current_value" |), + Constant.int 0 + |), + ltac:(M.monadic ( + Compare.eq (| + M.get_name (| globals, "new_value" |), + Constant.int 0 + |) + )) + |) + )) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "refund_counter" |), + M.call (| + M.get_name (| globals, "int" |), + make_list [ + M.get_name (| globals, "GAS_STORAGE_CLEAR_REFUND" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + BoolOp.and (| + Compare.not_eq (| + M.get_name (| globals, "original_value" |), + Constant.int 0 + |), + ltac:(M.monadic ( + Compare.eq (| + M.get_name (| globals, "current_value" |), + Constant.int 0 + |) + )) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_op (| + BinOp.sub, + M.get_field (| M.get_name (| globals, "evm" |), "refund_counter" |), + M.call (| + M.get_name (| globals, "int" |), + make_list [ + M.get_name (| globals, "GAS_STORAGE_CLEAR_REFUND" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, "original_value" |), + M.get_name (| globals, "new_value" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, "original_value" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "refund_counter" |), + M.call (| + M.get_name (| globals, "int" |), + make_list [ + BinOp.sub (| + M.get_name (| globals, "GAS_STORAGE_SET" |), + M.get_name (| globals, "GAS_WARM_ACCESS" |) + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "refund_counter" |), + M.call (| + M.get_name (| globals, "int" |), + make_list [ + BinOp.sub (| + BinOp.sub (| + M.get_name (| globals, "GAS_STORAGE_UPDATE" |), + M.get_name (| globals, "GAS_COLD_SLOAD" |) + |), + M.get_name (| globals, "GAS_WARM_ACCESS" |) + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "gas_cost" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + UnOp.not (| M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "is_static" |) |); + M.get_name (| globals, "WriteInStaticContext" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "set_storage" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "env" |), "state" |); + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "current_target" |); + M.get_name (| globals, "key" |); + M.get_name (| globals, "new_value" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). diff --git a/CoqOfPython/ethereum/gray_glacier/vm/instructions/system.v b/CoqOfPython/ethereum/gray_glacier/vm/instructions/system.v new file mode 100644 index 0000000..0bd77ce --- /dev/null +++ b/CoqOfPython/ethereum/gray_glacier/vm/instructions/system.v @@ -0,0 +1,2215 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.gray_glacier.vm.instructions.system". + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) System Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM system related instructions. +". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_Bytes0 : + IsImported globals "ethereum.base_types" "Bytes0". +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". + +Axiom ethereum_utils_ensure_imports_ensure : + IsImported globals "ethereum.utils.ensure" "ensure". + +Axiom ethereum_utils_numeric_imports_ceil32 : + IsImported globals "ethereum.utils.numeric" "ceil32". + +Axiom ethereum_gray_glacier_fork_types_imports_Address : + IsImported globals "ethereum.gray_glacier.fork_types" "Address". + +Axiom ethereum_gray_glacier_state_imports_account_exists_and_is_empty : + IsImported globals "ethereum.gray_glacier.state" "account_exists_and_is_empty". +Axiom ethereum_gray_glacier_state_imports_account_has_code_or_nonce : + IsImported globals "ethereum.gray_glacier.state" "account_has_code_or_nonce". +Axiom ethereum_gray_glacier_state_imports_get_account : + IsImported globals "ethereum.gray_glacier.state" "get_account". +Axiom ethereum_gray_glacier_state_imports_increment_nonce : + IsImported globals "ethereum.gray_glacier.state" "increment_nonce". +Axiom ethereum_gray_glacier_state_imports_is_account_alive : + IsImported globals "ethereum.gray_glacier.state" "is_account_alive". +Axiom ethereum_gray_glacier_state_imports_set_account_balance : + IsImported globals "ethereum.gray_glacier.state" "set_account_balance". + +Axiom ethereum_gray_glacier_utils_address_imports_compute_contract_address : + IsImported globals "ethereum.gray_glacier.utils.address" "compute_contract_address". +Axiom ethereum_gray_glacier_utils_address_imports_compute_create2_contract_address : + IsImported globals "ethereum.gray_glacier.utils.address" "compute_create2_contract_address". +Axiom ethereum_gray_glacier_utils_address_imports_to_address : + IsImported globals "ethereum.gray_glacier.utils.address" "to_address". + +Axiom ethereum_gray_glacier_vm_imports_Evm : + IsImported globals "ethereum.gray_glacier.vm" "Evm". +Axiom ethereum_gray_glacier_vm_imports_Message : + IsImported globals "ethereum.gray_glacier.vm" "Message". +Axiom ethereum_gray_glacier_vm_imports_incorporate_child_on_error : + IsImported globals "ethereum.gray_glacier.vm" "incorporate_child_on_error". +Axiom ethereum_gray_glacier_vm_imports_incorporate_child_on_success : + IsImported globals "ethereum.gray_glacier.vm" "incorporate_child_on_success". + +Axiom ethereum_gray_glacier_vm_exceptions_imports_Revert : + IsImported globals "ethereum.gray_glacier.vm.exceptions" "Revert". +Axiom ethereum_gray_glacier_vm_exceptions_imports_WriteInStaticContext : + IsImported globals "ethereum.gray_glacier.vm.exceptions" "WriteInStaticContext". + +Axiom ethereum_gray_glacier_vm_gas_imports_GAS_CALL_VALUE : + IsImported globals "ethereum.gray_glacier.vm.gas" "GAS_CALL_VALUE". +Axiom ethereum_gray_glacier_vm_gas_imports_GAS_COLD_ACCOUNT_ACCESS : + IsImported globals "ethereum.gray_glacier.vm.gas" "GAS_COLD_ACCOUNT_ACCESS". +Axiom ethereum_gray_glacier_vm_gas_imports_GAS_CREATE : + IsImported globals "ethereum.gray_glacier.vm.gas" "GAS_CREATE". +Axiom ethereum_gray_glacier_vm_gas_imports_GAS_KECCAK256_WORD : + IsImported globals "ethereum.gray_glacier.vm.gas" "GAS_KECCAK256_WORD". +Axiom ethereum_gray_glacier_vm_gas_imports_GAS_NEW_ACCOUNT : + IsImported globals "ethereum.gray_glacier.vm.gas" "GAS_NEW_ACCOUNT". +Axiom ethereum_gray_glacier_vm_gas_imports_GAS_SELF_DESTRUCT : + IsImported globals "ethereum.gray_glacier.vm.gas" "GAS_SELF_DESTRUCT". +Axiom ethereum_gray_glacier_vm_gas_imports_GAS_SELF_DESTRUCT_NEW_ACCOUNT : + IsImported globals "ethereum.gray_glacier.vm.gas" "GAS_SELF_DESTRUCT_NEW_ACCOUNT". +Axiom ethereum_gray_glacier_vm_gas_imports_GAS_WARM_ACCESS : + IsImported globals "ethereum.gray_glacier.vm.gas" "GAS_WARM_ACCESS". +Axiom ethereum_gray_glacier_vm_gas_imports_GAS_ZERO : + IsImported globals "ethereum.gray_glacier.vm.gas" "GAS_ZERO". +Axiom ethereum_gray_glacier_vm_gas_imports_calculate_gas_extend_memory : + IsImported globals "ethereum.gray_glacier.vm.gas" "calculate_gas_extend_memory". +Axiom ethereum_gray_glacier_vm_gas_imports_calculate_message_call_gas : + IsImported globals "ethereum.gray_glacier.vm.gas" "calculate_message_call_gas". +Axiom ethereum_gray_glacier_vm_gas_imports_charge_gas : + IsImported globals "ethereum.gray_glacier.vm.gas" "charge_gas". +Axiom ethereum_gray_glacier_vm_gas_imports_max_message_call_gas : + IsImported globals "ethereum.gray_glacier.vm.gas" "max_message_call_gas". + +Axiom ethereum_gray_glacier_vm_memory_imports_memory_read_bytes : + IsImported globals "ethereum.gray_glacier.vm.memory" "memory_read_bytes". +Axiom ethereum_gray_glacier_vm_memory_imports_memory_write : + IsImported globals "ethereum.gray_glacier.vm.memory" "memory_write". + +Axiom ethereum_gray_glacier_vm_stack_imports_pop : + IsImported globals "ethereum.gray_glacier.vm.stack" "pop". +Axiom ethereum_gray_glacier_vm_stack_imports_push : + IsImported globals "ethereum.gray_glacier.vm.stack" "push". + +Definition generic_create : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm"; "endowment"; "contract_address"; "memory_start_position"; "memory_size" ] |) in + let _ := Constant.str " + Core logic used by the `CREATE*` family of opcodes. + " in +(* At stmt: unsupported node type: ImportFrom *) + let _ := M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "accessed_addresses" |), "add" |), + make_list [ + M.get_name (| globals, "contract_address" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "create_message_gas" , + M.call (| + M.get_name (| globals, "max_message_call_gas" |), + make_list [ + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "gas_left" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_op (| + BinOp.sub, + M.get_field (| M.get_name (| globals, "evm" |), "gas_left" |), + M.get_name (| globals, "create_message_gas" |) + |) in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + UnOp.not (| M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "is_static" |) |); + M.get_name (| globals, "WriteInStaticContext" |) + ], + make_dict [] + |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, "evm" |), "return_data" |), + Constant.bytes "" + |) in + let _ := M.assign_local (| + "sender_address" , + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "current_target" |) + |) in + let _ := M.assign_local (| + "sender" , + M.call (| + M.get_name (| globals, "get_account" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "env" |), "state" |); + M.get_name (| globals, "sender_address" |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + BoolOp.or (| + Compare.lt (| + M.get_field (| M.get_name (| globals, "sender" |), "balance" |), + M.get_name (| globals, "endowment" |) + |), + ltac:(M.monadic ( + BoolOp.or (| + Compare.eq (| + M.get_field (| M.get_name (| globals, "sender" |), "nonce" |), + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + BinOp.sub (| + BinOp.pow (| + Constant.int 2, + Constant.int 64 + |), + Constant.int 1 + |) + ], + make_dict [] + |) + |), + ltac:(M.monadic ( + Compare.gt (| + BinOp.add (| + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "depth" |), + Constant.int 1 + |), + M.get_name (| globals, "STACK_DEPTH_LIMIT" |) + |) + )) + |) + )) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "gas_left" |), + M.get_name (| globals, "create_message_gas" |) + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.return_ (| + Constant.None_ + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, "account_has_code_or_nonce" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "env" |), "state" |); + M.get_name (| globals, "contract_address" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, "increment_nonce" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "env" |), "state" |); + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "current_target" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.return_ (| + Constant.None_ + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "call_data" , + M.call (| + M.get_name (| globals, "memory_read_bytes" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "memory" |); + M.get_name (| globals, "memory_start_position" |); + M.get_name (| globals, "memory_size" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "increment_nonce" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "env" |), "state" |); + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "current_target" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "child_message" , + M.call (| + M.get_name (| globals, "Message" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "child_evm" , + M.call (| + M.get_name (| globals, "process_create_message" |), + make_list [ + M.get_name (| globals, "child_message" |); + M.get_field (| M.get_name (| globals, "evm" |), "env" |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + M.get_field (| M.get_name (| globals, "child_evm" |), "error" |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, "incorporate_child_on_error" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "child_evm" |) + ], + make_dict [] + |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, "evm" |), "return_data" |), + M.get_field (| M.get_name (| globals, "child_evm" |), "output" |) + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + ], + make_dict [] + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, "incorporate_child_on_success" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "child_evm" |) + ], + make_dict [] + |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, "evm" |), "return_data" |), + Constant.bytes "" + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.call (| + M.get_field (| M.get_name (| globals, "U256" |), "from_be_bytes" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "child_evm" |), "message" |), "current_target" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_)). + +Definition create : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Creates a new account with associated code. + + Parameters + ---------- + evm : + The current EVM frame. + " in + let _ := M.assign_local (| + "endowment" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_start_position" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_size" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "extend_memory" , + M.call (| + M.get_name (| globals, "calculate_gas_extend_memory" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "memory" |); + make_list [ + make_tuple [ M.get_name (| globals, "memory_start_position" |); M.get_name (| globals, "memory_size" |) ] + ] + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + BinOp.add (| + M.get_name (| globals, "GAS_CREATE" |), + M.get_field (| M.get_name (| globals, "extend_memory" |), "cost" |) + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "memory" |), + BinOp.mult (| + Constant.bytes "00", + M.get_field (| M.get_name (| globals, "extend_memory" |), "expand_by" |) + |) + |) in + let _ := M.assign_local (| + "contract_address" , + M.call (| + M.get_name (| globals, "compute_contract_address" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "current_target" |); + M.get_field (| M.call (| + M.get_name (| globals, "get_account" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "env" |), "state" |); + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "current_target" |) + ], + make_dict [] + |), "nonce" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "generic_create" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "endowment" |); + M.get_name (| globals, "contract_address" |); + M.get_name (| globals, "memory_start_position" |); + M.get_name (| globals, "memory_size" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition create2 : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Creates a new account with associated code. + + It's similar to CREATE opcode except that the address of new account + depends on the init_code instead of the nonce of sender. + + Parameters + ---------- + evm : + The current EVM frame. + " in + let _ := M.assign_local (| + "endowment" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_start_position" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_size" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "salt" , + M.call (| + M.get_field (| M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |), "to_be_bytes32" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "extend_memory" , + M.call (| + M.get_name (| globals, "calculate_gas_extend_memory" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "memory" |); + make_list [ + make_tuple [ M.get_name (| globals, "memory_start_position" |); M.get_name (| globals, "memory_size" |) ] + ] + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "call_data_words" , + BinOp.floor_div (| + M.call (| + M.get_name (| globals, "ceil32" |), + make_list [ + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.get_name (| globals, "memory_size" |) + ], + make_dict [] + |) + ], + make_dict [] + |), + Constant.int 32 + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + BinOp.add (| + BinOp.add (| + M.get_name (| globals, "GAS_CREATE" |), + BinOp.mult (| + M.get_name (| globals, "GAS_KECCAK256_WORD" |), + M.get_name (| globals, "call_data_words" |) + |) + |), + M.get_field (| M.get_name (| globals, "extend_memory" |), "cost" |) + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "memory" |), + BinOp.mult (| + Constant.bytes "00", + M.get_field (| M.get_name (| globals, "extend_memory" |), "expand_by" |) + |) + |) in + let _ := M.assign_local (| + "contract_address" , + M.call (| + M.get_name (| globals, "compute_create2_contract_address" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "current_target" |); + M.get_name (| globals, "salt" |); + M.call (| + M.get_name (| globals, "memory_read_bytes" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "memory" |); + M.get_name (| globals, "memory_start_position" |); + M.get_name (| globals, "memory_size" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "generic_create" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "endowment" |); + M.get_name (| globals, "contract_address" |); + M.get_name (| globals, "memory_start_position" |); + M.get_name (| globals, "memory_size" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition return_ : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Halts execution returning output data. + + Parameters + ---------- + evm : + The current EVM frame. + " in + let _ := M.assign_local (| + "memory_start_position" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_size" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "extend_memory" , + M.call (| + M.get_name (| globals, "calculate_gas_extend_memory" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "memory" |); + make_list [ + make_tuple [ M.get_name (| globals, "memory_start_position" |); M.get_name (| globals, "memory_size" |) ] + ] + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + BinOp.add (| + M.get_name (| globals, "GAS_ZERO" |), + M.get_field (| M.get_name (| globals, "extend_memory" |), "cost" |) + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "memory" |), + BinOp.mult (| + Constant.bytes "00", + M.get_field (| M.get_name (| globals, "extend_memory" |), "expand_by" |) + |) + |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, "evm" |), "output" |), + M.call (| + M.get_name (| globals, "memory_read_bytes" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "memory" |); + M.get_name (| globals, "memory_start_position" |); + M.get_name (| globals, "memory_size" |) + ], + make_dict [] + |) + |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, "evm" |), "running" |), + Constant.bool false + |) in + let _ := M.pass (| |) in + M.pure Constant.None_)). + +Definition generic_call : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm"; "gas"; "value"; "caller"; "to"; "code_address"; "should_transfer_value"; "is_staticcall"; "memory_input_start_position"; "memory_input_size"; "memory_output_start_position"; "memory_output_size" ] |) in + let _ := Constant.str " + Perform the core logic of the `CALL*` family of opcodes. + " in +(* At stmt: unsupported node type: ImportFrom *) + let _ := M.assign (| + M.get_field (| M.get_name (| globals, "evm" |), "return_data" |), + Constant.bytes "" + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.gt (| + BinOp.add (| + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "depth" |), + Constant.int 1 + |), + M.get_name (| globals, "STACK_DEPTH_LIMIT" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "gas_left" |), + M.get_name (| globals, "gas" |) + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.return_ (| + Constant.None_ + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "call_data" , + M.call (| + M.get_name (| globals, "memory_read_bytes" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "memory" |); + M.get_name (| globals, "memory_input_start_position" |); + M.get_name (| globals, "memory_input_size" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "code" , + M.get_field (| M.call (| + M.get_name (| globals, "get_account" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "env" |), "state" |); + M.get_name (| globals, "code_address" |) + ], + make_dict [] + |), "code" |) + |) in + let _ := M.assign_local (| + "child_message" , + M.call (| + M.get_name (| globals, "Message" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "child_evm" , + M.call (| + M.get_name (| globals, "process_message" |), + make_list [ + M.get_name (| globals, "child_message" |); + M.get_field (| M.get_name (| globals, "evm" |), "env" |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + M.get_field (| M.get_name (| globals, "child_evm" |), "error" |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, "incorporate_child_on_error" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "child_evm" |) + ], + make_dict [] + |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, "evm" |), "return_data" |), + M.get_field (| M.get_name (| globals, "child_evm" |), "output" |) + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + ], + make_dict [] + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, "incorporate_child_on_success" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "child_evm" |) + ], + make_dict [] + |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, "evm" |), "return_data" |), + M.get_field (| M.get_name (| globals, "child_evm" |), "output" |) + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 1 + ], + make_dict [] + |) + ], + make_dict [] + |) in + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "actual_output_size" , + M.call (| + M.get_name (| globals, "min" |), + make_list [ + M.get_name (| globals, "memory_output_size" |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_field (| M.get_name (| globals, "child_evm" |), "output" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "memory_write" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "memory" |); + M.get_name (| globals, "memory_output_start_position" |); + M.slice (| + M.get_field (| M.get_name (| globals, "child_evm" |), "output" |), + Constant.None_, + M.get_name (| globals, "actual_output_size" |), + Constant.None_ + |) + ], + make_dict [] + |) in + M.pure Constant.None_)). + +Definition call : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Message-call into an account. + + Parameters + ---------- + evm : + The current EVM frame. + " in + let _ := M.assign_local (| + "gas" , + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "to" , + M.call (| + M.get_name (| globals, "to_address" |), + make_list [ + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "value" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_input_start_position" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_input_size" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_output_start_position" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_output_size" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "extend_memory" , + M.call (| + M.get_name (| globals, "calculate_gas_extend_memory" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "memory" |); + make_list [ + make_tuple [ M.get_name (| globals, "memory_input_start_position" |); M.get_name (| globals, "memory_input_size" |) ]; + make_tuple [ M.get_name (| globals, "memory_output_start_position" |); M.get_name (| globals, "memory_output_size" |) ] + ] + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.in_ (| + M.get_name (| globals, "to" |), + M.get_field (| M.get_name (| globals, "evm" |), "accessed_addresses" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "access_gas_cost" , + M.get_name (| globals, "GAS_WARM_ACCESS" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "accessed_addresses" |), "add" |), + make_list [ + M.get_name (| globals, "to" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "access_gas_cost" , + M.get_name (| globals, "GAS_COLD_ACCOUNT_ACCESS" |) + |) in + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "create_gas_cost" , + (* if *) + M.if_then_else (| + BoolOp.or (| + M.call (| + M.get_name (| globals, "is_account_alive" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "env" |), "state" |); + M.get_name (| globals, "to" |) + ], + make_dict [] + |), + ltac:(M.monadic ( + Compare.eq (| + M.get_name (| globals, "value" |), + Constant.int 0 + |) + )) + |), + (* then *) + ltac:(M.monadic ( +M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + (* else *) + )), ltac:(M.monadic ( +M.get_name (| globals, "GAS_NEW_ACCOUNT" |) + )) |) + |) in + let _ := M.assign_local (| + "transfer_gas_cost" , + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, "value" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( +M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + (* else *) + )), ltac:(M.monadic ( +M.get_name (| globals, "GAS_CALL_VALUE" |) + )) |) + |) in + let _ := M.assign_local (| + "message_call_gas" , + M.call (| + M.get_name (| globals, "calculate_message_call_gas" |), + make_list [ + M.get_name (| globals, "value" |); + M.get_name (| globals, "gas" |); + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "gas_left" |) + ], + make_dict [] + |); + M.get_field (| M.get_name (| globals, "extend_memory" |), "cost" |); + BinOp.add (| + BinOp.add (| + M.get_name (| globals, "access_gas_cost" |), + M.get_name (| globals, "create_gas_cost" |) + |), + M.get_name (| globals, "transfer_gas_cost" |) + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + BinOp.add (| + M.get_field (| M.get_name (| globals, "message_call_gas" |), "cost" |), + M.get_field (| M.get_name (| globals, "extend_memory" |), "cost" |) + |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + BoolOp.or (| + UnOp.not (| M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "is_static" |) |), + ltac:(M.monadic ( + Compare.eq (| + M.get_name (| globals, "value" |), + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + |) + )) + |); + M.get_name (| globals, "WriteInStaticContext" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "memory" |), + BinOp.mult (| + Constant.bytes "00", + M.get_field (| M.get_name (| globals, "extend_memory" |), "expand_by" |) + |) + |) in + let _ := M.assign_local (| + "sender_balance" , + M.get_field (| M.call (| + M.get_name (| globals, "get_account" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "env" |), "state" |); + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "current_target" |) + ], + make_dict [] + |), "balance" |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.lt (| + M.get_name (| globals, "sender_balance" |), + M.get_name (| globals, "value" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, "evm" |), "return_data" |), + Constant.bytes "" + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "gas_left" |), + M.get_field (| M.get_name (| globals, "message_call_gas" |), "stipend" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, "generic_call" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_field (| M.get_name (| globals, "message_call_gas" |), "stipend" |); + M.get_name (| globals, "value" |); + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "current_target" |); + M.get_name (| globals, "to" |); + M.get_name (| globals, "to" |); + Constant.bool true; + Constant.bool false; + M.get_name (| globals, "memory_input_start_position" |); + M.get_name (| globals, "memory_input_size" |); + M.get_name (| globals, "memory_output_start_position" |); + M.get_name (| globals, "memory_output_size" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + )) |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition callcode : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Message-call into this account with alternative account’s code. + + Parameters + ---------- + evm : + The current EVM frame. + " in + let _ := M.assign_local (| + "gas" , + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "code_address" , + M.call (| + M.get_name (| globals, "to_address" |), + make_list [ + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "value" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_input_start_position" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_input_size" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_output_start_position" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_output_size" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "to" , + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "current_target" |) + |) in + let _ := M.assign_local (| + "extend_memory" , + M.call (| + M.get_name (| globals, "calculate_gas_extend_memory" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "memory" |); + make_list [ + make_tuple [ M.get_name (| globals, "memory_input_start_position" |); M.get_name (| globals, "memory_input_size" |) ]; + make_tuple [ M.get_name (| globals, "memory_output_start_position" |); M.get_name (| globals, "memory_output_size" |) ] + ] + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.in_ (| + M.get_name (| globals, "code_address" |), + M.get_field (| M.get_name (| globals, "evm" |), "accessed_addresses" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "access_gas_cost" , + M.get_name (| globals, "GAS_WARM_ACCESS" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "accessed_addresses" |), "add" |), + make_list [ + M.get_name (| globals, "code_address" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "access_gas_cost" , + M.get_name (| globals, "GAS_COLD_ACCOUNT_ACCESS" |) + |) in + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "transfer_gas_cost" , + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, "value" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( +M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + (* else *) + )), ltac:(M.monadic ( +M.get_name (| globals, "GAS_CALL_VALUE" |) + )) |) + |) in + let _ := M.assign_local (| + "message_call_gas" , + M.call (| + M.get_name (| globals, "calculate_message_call_gas" |), + make_list [ + M.get_name (| globals, "value" |); + M.get_name (| globals, "gas" |); + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "gas_left" |) + ], + make_dict [] + |); + M.get_field (| M.get_name (| globals, "extend_memory" |), "cost" |); + BinOp.add (| + M.get_name (| globals, "access_gas_cost" |), + M.get_name (| globals, "transfer_gas_cost" |) + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + BinOp.add (| + M.get_field (| M.get_name (| globals, "message_call_gas" |), "cost" |), + M.get_field (| M.get_name (| globals, "extend_memory" |), "cost" |) + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "memory" |), + BinOp.mult (| + Constant.bytes "00", + M.get_field (| M.get_name (| globals, "extend_memory" |), "expand_by" |) + |) + |) in + let _ := M.assign_local (| + "sender_balance" , + M.get_field (| M.call (| + M.get_name (| globals, "get_account" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "env" |), "state" |); + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "current_target" |) + ], + make_dict [] + |), "balance" |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.lt (| + M.get_name (| globals, "sender_balance" |), + M.get_name (| globals, "value" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, "evm" |), "return_data" |), + Constant.bytes "" + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "gas_left" |), + M.get_field (| M.get_name (| globals, "message_call_gas" |), "stipend" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, "generic_call" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_field (| M.get_name (| globals, "message_call_gas" |), "stipend" |); + M.get_name (| globals, "value" |); + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "current_target" |); + M.get_name (| globals, "to" |); + M.get_name (| globals, "code_address" |); + Constant.bool true; + Constant.bool false; + M.get_name (| globals, "memory_input_start_position" |); + M.get_name (| globals, "memory_input_size" |); + M.get_name (| globals, "memory_output_start_position" |); + M.get_name (| globals, "memory_output_size" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + )) |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition selfdestruct : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Halt execution and register account for later deletion. + + Parameters + ---------- + evm : + The current EVM frame. + " in + let _ := M.assign_local (| + "beneficiary" , + M.call (| + M.get_name (| globals, "to_address" |), + make_list [ + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "gas_cost" , + M.get_name (| globals, "GAS_SELF_DESTRUCT" |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.not_in (| + M.get_name (| globals, "beneficiary" |), + M.get_field (| M.get_name (| globals, "evm" |), "accessed_addresses" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "accessed_addresses" |), "add" |), + make_list [ + M.get_name (| globals, "beneficiary" |) + ], + make_dict [] + |) in + let _ := M.assign_op_local (| + BinOp.add, + "gas_cost", + M.get_name (| globals, "GAS_COLD_ACCOUNT_ACCESS" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + BoolOp.and (| + UnOp.not (| M.call (| + M.get_name (| globals, "is_account_alive" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "env" |), "state" |); + M.get_name (| globals, "beneficiary" |) + ], + make_dict [] + |) |), + ltac:(M.monadic ( + Compare.not_eq (| + M.get_field (| M.call (| + M.get_name (| globals, "get_account" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "env" |), "state" |); + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "current_target" |) + ], + make_dict [] + |), "balance" |), + Constant.int 0 + |) + )) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_op_local (| + BinOp.add, + "gas_cost", + M.get_name (| globals, "GAS_SELF_DESTRUCT_NEW_ACCOUNT" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "gas_cost" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + UnOp.not (| M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "is_static" |) |); + M.get_name (| globals, "WriteInStaticContext" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "originator" , + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "current_target" |) + |) in + let _ := M.assign_local (| + "beneficiary_balance" , + M.get_field (| M.call (| + M.get_name (| globals, "get_account" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "env" |), "state" |); + M.get_name (| globals, "beneficiary" |) + ], + make_dict [] + |), "balance" |) + |) in + let _ := M.assign_local (| + "originator_balance" , + M.get_field (| M.call (| + M.get_name (| globals, "get_account" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "env" |), "state" |); + M.get_name (| globals, "originator" |) + ], + make_dict [] + |), "balance" |) + |) in + let _ := M.call (| + M.get_name (| globals, "set_account_balance" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "env" |), "state" |); + M.get_name (| globals, "beneficiary" |); + BinOp.add (| + M.get_name (| globals, "beneficiary_balance" |), + M.get_name (| globals, "originator_balance" |) + |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "set_account_balance" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "env" |), "state" |); + M.get_name (| globals, "originator" |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "accounts_to_delete" |), "add" |), + make_list [ + M.get_name (| globals, "originator" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, "account_exists_and_is_empty" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "env" |), "state" |); + M.get_name (| globals, "beneficiary" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "touched_accounts" |), "add" |), + make_list [ + M.get_name (| globals, "beneficiary" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, "evm" |), "running" |), + Constant.bool false + |) in + let _ := M.pass (| |) in + M.pure Constant.None_)). + +Definition delegatecall : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Message-call into an account. + + Parameters + ---------- + evm : + The current EVM frame. + " in + let _ := M.assign_local (| + "gas" , + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "code_address" , + M.call (| + M.get_name (| globals, "to_address" |), + make_list [ + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_input_start_position" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_input_size" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_output_start_position" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_output_size" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "extend_memory" , + M.call (| + M.get_name (| globals, "calculate_gas_extend_memory" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "memory" |); + make_list [ + make_tuple [ M.get_name (| globals, "memory_input_start_position" |); M.get_name (| globals, "memory_input_size" |) ]; + make_tuple [ M.get_name (| globals, "memory_output_start_position" |); M.get_name (| globals, "memory_output_size" |) ] + ] + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.in_ (| + M.get_name (| globals, "code_address" |), + M.get_field (| M.get_name (| globals, "evm" |), "accessed_addresses" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "access_gas_cost" , + M.get_name (| globals, "GAS_WARM_ACCESS" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "accessed_addresses" |), "add" |), + make_list [ + M.get_name (| globals, "code_address" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "access_gas_cost" , + M.get_name (| globals, "GAS_COLD_ACCOUNT_ACCESS" |) + |) in + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "message_call_gas" , + M.call (| + M.get_name (| globals, "calculate_message_call_gas" |), + make_list [ + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |); + M.get_name (| globals, "gas" |); + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "gas_left" |) + ], + make_dict [] + |); + M.get_field (| M.get_name (| globals, "extend_memory" |), "cost" |); + M.get_name (| globals, "access_gas_cost" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + BinOp.add (| + M.get_field (| M.get_name (| globals, "message_call_gas" |), "cost" |), + M.get_field (| M.get_name (| globals, "extend_memory" |), "cost" |) + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "memory" |), + BinOp.mult (| + Constant.bytes "00", + M.get_field (| M.get_name (| globals, "extend_memory" |), "expand_by" |) + |) + |) in + let _ := M.call (| + M.get_name (| globals, "generic_call" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_field (| M.get_name (| globals, "message_call_gas" |), "stipend" |); + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "value" |); + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "caller" |); + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "current_target" |); + M.get_name (| globals, "code_address" |); + Constant.bool false; + Constant.bool false; + M.get_name (| globals, "memory_input_start_position" |); + M.get_name (| globals, "memory_input_size" |); + M.get_name (| globals, "memory_output_start_position" |); + M.get_name (| globals, "memory_output_size" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition staticcall : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Message-call into an account. + + Parameters + ---------- + evm : + The current EVM frame. + " in + let _ := M.assign_local (| + "gas" , + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "to" , + M.call (| + M.get_name (| globals, "to_address" |), + make_list [ + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_input_start_position" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_input_size" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_output_start_position" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_output_size" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "extend_memory" , + M.call (| + M.get_name (| globals, "calculate_gas_extend_memory" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "memory" |); + make_list [ + make_tuple [ M.get_name (| globals, "memory_input_start_position" |); M.get_name (| globals, "memory_input_size" |) ]; + make_tuple [ M.get_name (| globals, "memory_output_start_position" |); M.get_name (| globals, "memory_output_size" |) ] + ] + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.in_ (| + M.get_name (| globals, "to" |), + M.get_field (| M.get_name (| globals, "evm" |), "accessed_addresses" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "access_gas_cost" , + M.get_name (| globals, "GAS_WARM_ACCESS" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "accessed_addresses" |), "add" |), + make_list [ + M.get_name (| globals, "to" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "access_gas_cost" , + M.get_name (| globals, "GAS_COLD_ACCOUNT_ACCESS" |) + |) in + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "message_call_gas" , + M.call (| + M.get_name (| globals, "calculate_message_call_gas" |), + make_list [ + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |); + M.get_name (| globals, "gas" |); + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "gas_left" |) + ], + make_dict [] + |); + M.get_field (| M.get_name (| globals, "extend_memory" |), "cost" |); + M.get_name (| globals, "access_gas_cost" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + BinOp.add (| + M.get_field (| M.get_name (| globals, "message_call_gas" |), "cost" |), + M.get_field (| M.get_name (| globals, "extend_memory" |), "cost" |) + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "memory" |), + BinOp.mult (| + Constant.bytes "00", + M.get_field (| M.get_name (| globals, "extend_memory" |), "expand_by" |) + |) + |) in + let _ := M.call (| + M.get_name (| globals, "generic_call" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_field (| M.get_name (| globals, "message_call_gas" |), "stipend" |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |); + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "current_target" |); + M.get_name (| globals, "to" |); + M.get_name (| globals, "to" |); + Constant.bool true; + Constant.bool true; + M.get_name (| globals, "memory_input_start_position" |); + M.get_name (| globals, "memory_input_size" |); + M.get_name (| globals, "memory_output_start_position" |); + M.get_name (| globals, "memory_output_size" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition revert : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Stop execution and revert state changes, without consuming all provided gas + and also has the ability to return a reason + Parameters + ---------- + evm : + The current EVM frame. + " in + let _ := M.assign_local (| + "memory_start_index" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "size" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "extend_memory" , + M.call (| + M.get_name (| globals, "calculate_gas_extend_memory" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "memory" |); + make_list [ + make_tuple [ M.get_name (| globals, "memory_start_index" |); M.get_name (| globals, "size" |) ] + ] + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_field (| M.get_name (| globals, "extend_memory" |), "cost" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "memory" |), + BinOp.mult (| + Constant.bytes "00", + M.get_field (| M.get_name (| globals, "extend_memory" |), "expand_by" |) + |) + |) in + let _ := M.assign_local (| + "output" , + M.call (| + M.get_name (| globals, "memory_read_bytes" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "memory" |); + M.get_name (| globals, "memory_start_index" |); + M.get_name (| globals, "size" |) + ], + make_dict [] + |) + |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, "evm" |), "output" |), + M.call (| + M.get_name (| globals, "bytes" |), + make_list [ + M.get_name (| globals, "output" |) + ], + make_dict [] + |) + |) in + let _ := M.raise (| Some (M.get_name (| globals, "Revert" |)) |) in + let _ := M.pass (| |) in + M.pure Constant.None_)). diff --git a/CoqOfPython/ethereum/gray_glacier/vm/interpreter.v b/CoqOfPython/ethereum/gray_glacier/vm/interpreter.v new file mode 100644 index 0000000..af521c5 --- /dev/null +++ b/CoqOfPython/ethereum/gray_glacier/vm/interpreter.v @@ -0,0 +1,675 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.gray_glacier.vm.interpreter". + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) Interpreter +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +A straightforward interpreter that executes EVM code. +". + +Axiom dataclasses_imports_dataclass : + IsImported globals "dataclasses" "dataclass". + +Axiom typing_imports_Iterable : + IsImported globals "typing" "Iterable". +Axiom typing_imports_Optional : + IsImported globals "typing" "Optional". +Axiom typing_imports_Set : + IsImported globals "typing" "Set". +Axiom typing_imports_Tuple : + IsImported globals "typing" "Tuple". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_Bytes0 : + IsImported globals "ethereum.base_types" "Bytes0". +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". + +Axiom ethereum_trace_imports_EvmStop : + IsImported globals "ethereum.trace" "EvmStop". +Axiom ethereum_trace_imports_OpEnd : + IsImported globals "ethereum.trace" "OpEnd". +Axiom ethereum_trace_imports_OpException : + IsImported globals "ethereum.trace" "OpException". +Axiom ethereum_trace_imports_OpStart : + IsImported globals "ethereum.trace" "OpStart". +Axiom ethereum_trace_imports_PrecompileEnd : + IsImported globals "ethereum.trace" "PrecompileEnd". +Axiom ethereum_trace_imports_PrecompileStart : + IsImported globals "ethereum.trace" "PrecompileStart". +Axiom ethereum_trace_imports_TransactionEnd : + IsImported globals "ethereum.trace" "TransactionEnd". +Axiom ethereum_trace_imports_evm_trace : + IsImported globals "ethereum.trace" "evm_trace". + +Axiom ethereum_utils_ensure_imports_ensure : + IsImported globals "ethereum.utils.ensure" "ensure". + +Axiom ethereum_gray_glacier_blocks_imports_Log : + IsImported globals "ethereum.gray_glacier.blocks" "Log". + +Axiom ethereum_gray_glacier_fork_types_imports_Address : + IsImported globals "ethereum.gray_glacier.fork_types" "Address". + +Axiom ethereum_gray_glacier_state_imports_account_exists_and_is_empty : + IsImported globals "ethereum.gray_glacier.state" "account_exists_and_is_empty". +Axiom ethereum_gray_glacier_state_imports_account_has_code_or_nonce : + IsImported globals "ethereum.gray_glacier.state" "account_has_code_or_nonce". +Axiom ethereum_gray_glacier_state_imports_begin_transaction : + IsImported globals "ethereum.gray_glacier.state" "begin_transaction". +Axiom ethereum_gray_glacier_state_imports_commit_transaction : + IsImported globals "ethereum.gray_glacier.state" "commit_transaction". +Axiom ethereum_gray_glacier_state_imports_destroy_storage : + IsImported globals "ethereum.gray_glacier.state" "destroy_storage". +Axiom ethereum_gray_glacier_state_imports_increment_nonce : + IsImported globals "ethereum.gray_glacier.state" "increment_nonce". +Axiom ethereum_gray_glacier_state_imports_mark_account_created : + IsImported globals "ethereum.gray_glacier.state" "mark_account_created". +Axiom ethereum_gray_glacier_state_imports_move_ether : + IsImported globals "ethereum.gray_glacier.state" "move_ether". +Axiom ethereum_gray_glacier_state_imports_rollback_transaction : + IsImported globals "ethereum.gray_glacier.state" "rollback_transaction". +Axiom ethereum_gray_glacier_state_imports_set_code : + IsImported globals "ethereum.gray_glacier.state" "set_code". +Axiom ethereum_gray_glacier_state_imports_touch_account : + IsImported globals "ethereum.gray_glacier.state" "touch_account". + +Axiom ethereum_gray_glacier_vm_imports_Message : + IsImported globals "ethereum.gray_glacier.vm" "Message". + +Axiom ethereum_gray_glacier_vm_gas_imports_GAS_CODE_DEPOSIT : + IsImported globals "ethereum.gray_glacier.vm.gas" "GAS_CODE_DEPOSIT". +Axiom ethereum_gray_glacier_vm_gas_imports_charge_gas : + IsImported globals "ethereum.gray_glacier.vm.gas" "charge_gas". + +Axiom ethereum_gray_glacier_vm_precompiled_contracts_mapping_imports_PRE_COMPILED_CONTRACTS : + IsImported globals "ethereum.gray_glacier.vm.precompiled_contracts.mapping" "PRE_COMPILED_CONTRACTS". + +Axiom ethereum_gray_glacier_vm_imports_Environment : + IsImported globals "ethereum.gray_glacier.vm" "Environment". +Axiom ethereum_gray_glacier_vm_imports_Evm : + IsImported globals "ethereum.gray_glacier.vm" "Evm". + +Axiom ethereum_gray_glacier_vm_exceptions_imports_AddressCollision : + IsImported globals "ethereum.gray_glacier.vm.exceptions" "AddressCollision". +Axiom ethereum_gray_glacier_vm_exceptions_imports_ExceptionalHalt : + IsImported globals "ethereum.gray_glacier.vm.exceptions" "ExceptionalHalt". +Axiom ethereum_gray_glacier_vm_exceptions_imports_InvalidContractPrefix : + IsImported globals "ethereum.gray_glacier.vm.exceptions" "InvalidContractPrefix". +Axiom ethereum_gray_glacier_vm_exceptions_imports_InvalidOpcode : + IsImported globals "ethereum.gray_glacier.vm.exceptions" "InvalidOpcode". +Axiom ethereum_gray_glacier_vm_exceptions_imports_OutOfGasError : + IsImported globals "ethereum.gray_glacier.vm.exceptions" "OutOfGasError". +Axiom ethereum_gray_glacier_vm_exceptions_imports_Revert : + IsImported globals "ethereum.gray_glacier.vm.exceptions" "Revert". +Axiom ethereum_gray_glacier_vm_exceptions_imports_StackDepthLimitError : + IsImported globals "ethereum.gray_glacier.vm.exceptions" "StackDepthLimitError". + +Axiom ethereum_gray_glacier_vm_instructions_imports_Ops : + IsImported globals "ethereum.gray_glacier.vm.instructions" "Ops". +Axiom ethereum_gray_glacier_vm_instructions_imports_op_implementation : + IsImported globals "ethereum.gray_glacier.vm.instructions" "op_implementation". + +Axiom ethereum_gray_glacier_vm_runtime_imports_get_valid_jump_destinations : + IsImported globals "ethereum.gray_glacier.vm.runtime" "get_valid_jump_destinations". + +Definition STACK_DEPTH_LIMIT : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 1024 + ], + make_dict [] + |) +)). + +Definition MAX_CODE_SIZE : Value.t := M.run ltac:(M.monadic ( + Constant.int 24576 +)). + +Definition MessageCallOutput : Value.t := + builtins.make_klass + [] + [ + + ] + [ + + ]. + +Definition process_message_call : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "message"; "env" ] |) in + let _ := Constant.str " + If `message.current` is empty then it creates a smart contract + else it executes a call from the `message.caller` to the `message.target`. + + Parameters + ---------- + message : + Transaction specific items. + + env : + External items required for EVM execution. + + Returns + ------- + output : `MessageCallOutput` + Output of the message call + " in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_field (| M.get_name (| globals, "message" |), "target" |), + M.call (| + M.get_name (| globals, "Bytes0" |), + make_list [ + Constant.bytes "" + ], + make_dict [] + |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "is_collision" , + M.call (| + M.get_name (| globals, "account_has_code_or_nonce" |), + make_list [ + M.get_field (| M.get_name (| globals, "env" |), "state" |); + M.get_field (| M.get_name (| globals, "message" |), "current_target" |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + M.get_name (| globals, "is_collision" |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + M.call (| + M.get_name (| globals, "MessageCallOutput" |), + make_list [ + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |); + M.call (| + M.get_name (| globals, "tuple" |), + make_list [], + make_dict [] + |); + M.call (| + M.get_name (| globals, "set" |), + make_list [], + make_dict [] + |); + M.call (| + M.get_name (| globals, "set" |), + make_list [], + make_dict [] + |); + M.call (| + M.get_name (| globals, "AddressCollision" |), + make_list [], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "evm" , + M.call (| + M.get_name (| globals, "process_create_message" |), + make_list [ + M.get_name (| globals, "message" |); + M.get_name (| globals, "env" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "evm" , + M.call (| + M.get_name (| globals, "process_message" |), + make_list [ + M.get_name (| globals, "message" |); + M.get_name (| globals, "env" |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, "account_exists_and_is_empty" |), + make_list [ + M.get_field (| M.get_name (| globals, "env" |), "state" |); + M.call (| + M.get_name (| globals, "Address" |), + make_list [ + M.get_field (| M.get_name (| globals, "message" |), "target" |) + ], + make_dict [] + |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "touched_accounts" |), "add" |), + make_list [ + M.call (| + M.get_name (| globals, "Address" |), + make_list [ + M.get_field (| M.get_name (| globals, "message" |), "target" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + M.get_field (| M.get_name (| globals, "evm" |), "error" |), + (* then *) + ltac:(M.monadic ( +(* At stmt: unsupported node type: AnnAssign *) + let _ := M.assign_local (| + "accounts_to_delete" , + M.call (| + M.get_name (| globals, "set" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "touched_accounts" , + M.call (| + M.get_name (| globals, "set" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "refund_counter" , + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "logs" , + M.get_field (| M.get_name (| globals, "evm" |), "logs" |) + |) in + let _ := M.assign_local (| + "accounts_to_delete" , + M.get_field (| M.get_name (| globals, "evm" |), "accounts_to_delete" |) + |) in + let _ := M.assign_local (| + "touched_accounts" , + M.get_field (| M.get_name (| globals, "evm" |), "touched_accounts" |) + |) in + let _ := M.assign_local (| + "refund_counter" , + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "refund_counter" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "tx_end" , + M.call (| + M.get_name (| globals, "TransactionEnd" |), + make_list [ + BinOp.sub (| + M.get_field (| M.get_name (| globals, "message" |), "gas" |), + M.get_field (| M.get_name (| globals, "evm" |), "gas_left" |) + |); + M.get_field (| M.get_name (| globals, "evm" |), "output" |); + M.get_field (| M.get_name (| globals, "evm" |), "error" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "evm_trace" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "tx_end" |) + ], + make_dict [] + |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, "MessageCallOutput" |), + make_list [], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Definition process_create_message : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "message"; "env" ] |) in + let _ := Constant.str " + Executes a call to create a smart contract. + + Parameters + ---------- + message : + Transaction specific items. + env : + External items required for EVM execution. + + Returns + ------- + evm: :py:class:`~ethereum.london.vm.Evm` + Items containing execution specific objects. + " in + let _ := M.call (| + M.get_name (| globals, "begin_transaction" |), + make_list [ + M.get_field (| M.get_name (| globals, "env" |), "state" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "destroy_storage" |), + make_list [ + M.get_field (| M.get_name (| globals, "env" |), "state" |); + M.get_field (| M.get_name (| globals, "message" |), "current_target" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "mark_account_created" |), + make_list [ + M.get_field (| M.get_name (| globals, "env" |), "state" |); + M.get_field (| M.get_name (| globals, "message" |), "current_target" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "increment_nonce" |), + make_list [ + M.get_field (| M.get_name (| globals, "env" |), "state" |); + M.get_field (| M.get_name (| globals, "message" |), "current_target" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "evm" , + M.call (| + M.get_name (| globals, "process_message" |), + make_list [ + M.get_name (| globals, "message" |); + M.get_name (| globals, "env" |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + UnOp.not (| M.get_field (| M.get_name (| globals, "evm" |), "error" |) |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "contract_code" , + M.get_field (| M.get_name (| globals, "evm" |), "output" |) + |) in + let _ := M.assign_local (| + "contract_code_gas" , + BinOp.mult (| + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_name (| globals, "contract_code" |) + ], + make_dict [] + |), + M.get_name (| globals, "GAS_CODE_DEPOSIT" |) + |) + |) in +(* At stmt: unsupported node type: Try *) + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, "rollback_transaction" |), + make_list [ + M.get_field (| M.get_name (| globals, "env" |), "state" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + )) |) in + let _ := M.return_ (| + M.get_name (| globals, "evm" |) + |) in + M.pure Constant.None_)). + +Definition process_message : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "message"; "env" ] |) in + let _ := Constant.str " + Executes a call to create a smart contract. + + Parameters + ---------- + message : + Transaction specific items. + env : + External items required for EVM execution. + + Returns + ------- + evm: :py:class:`~ethereum.london.vm.Evm` + Items containing execution specific objects + " in + let _ := + (* if *) + M.if_then_else (| + Compare.gt (| + M.get_field (| M.get_name (| globals, "message" |), "depth" |), + M.get_name (| globals, "STACK_DEPTH_LIMIT" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.call (| + M.get_name (| globals, "StackDepthLimitError" |), + make_list [ + Constant.str "Stack depth limit reached" + ], + make_dict [] + |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.call (| + M.get_name (| globals, "begin_transaction" |), + make_list [ + M.get_field (| M.get_name (| globals, "env" |), "state" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "touch_account" |), + make_list [ + M.get_field (| M.get_name (| globals, "env" |), "state" |); + M.get_field (| M.get_name (| globals, "message" |), "current_target" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + BoolOp.and (| + M.get_field (| M.get_name (| globals, "message" |), "should_transfer_value" |), + ltac:(M.monadic ( + Compare.not_eq (| + M.get_field (| M.get_name (| globals, "message" |), "value" |), + Constant.int 0 + |) + )) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, "move_ether" |), + make_list [ + M.get_field (| M.get_name (| globals, "env" |), "state" |); + M.get_field (| M.get_name (| globals, "message" |), "caller" |); + M.get_field (| M.get_name (| globals, "message" |), "current_target" |); + M.get_field (| M.get_name (| globals, "message" |), "value" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "evm" , + M.call (| + M.get_name (| globals, "execute_code" |), + make_list [ + M.get_name (| globals, "message" |); + M.get_name (| globals, "env" |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + M.get_field (| M.get_name (| globals, "evm" |), "error" |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, "rollback_transaction" |), + make_list [ + M.get_field (| M.get_name (| globals, "env" |), "state" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, "commit_transaction" |), + make_list [ + M.get_field (| M.get_name (| globals, "env" |), "state" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + )) |) in + let _ := M.return_ (| + M.get_name (| globals, "evm" |) + |) in + M.pure Constant.None_)). + +Definition execute_code : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "message"; "env" ] |) in + let _ := Constant.str " + Executes bytecode present in the `message`. + + Parameters + ---------- + message : + Transaction specific items. + env : + External items required for EVM execution. + + Returns + ------- + evm: `ethereum.vm.EVM` + Items containing execution specific objects + " in + let _ := M.assign_local (| + "code" , + M.get_field (| M.get_name (| globals, "message" |), "code" |) + |) in + let _ := M.assign_local (| + "valid_jump_destinations" , + M.call (| + M.get_name (| globals, "get_valid_jump_destinations" |), + make_list [ + M.get_name (| globals, "code" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "evm" , + M.call (| + M.get_name (| globals, "Evm" |), + make_list [], + make_dict [] + |) + |) in +(* At stmt: unsupported node type: Try *) + let _ := M.return_ (| + M.get_name (| globals, "evm" |) + |) in + M.pure Constant.None_)). diff --git a/CoqOfPython/ethereum/gray_glacier/vm/memory.v b/CoqOfPython/ethereum/gray_glacier/vm/memory.v new file mode 100644 index 0000000..3aa8c8a --- /dev/null +++ b/CoqOfPython/ethereum/gray_glacier/vm/memory.v @@ -0,0 +1,166 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.gray_glacier.vm.memory". + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) Memory +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +EVM memory operations. +". + +Axiom ethereum_utils_byte_imports_right_pad_zero_bytes : + IsImported globals "ethereum.utils.byte" "right_pad_zero_bytes". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_Bytes : + IsImported globals "ethereum.base_types" "Bytes". +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". + +Definition memory_write : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "memory"; "start_position"; "value" ] |) in + let _ := Constant.str " + Writes to memory. + + Parameters + ---------- + memory : + Memory contents of the EVM. + start_position : + Starting pointer to the memory. + value : + Data to write to memory. + " in + let _ := M.assign (| + M.slice (| + M.get_name (| globals, "memory" |), + M.get_name (| globals, "start_position" |), + BinOp.add (| + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.get_name (| globals, "start_position" |) + ], + make_dict [] + |), + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_name (| globals, "value" |) + ], + make_dict [] + |) + |), + Constant.None_ + |), + M.get_name (| globals, "value" |) + |) in + M.pure Constant.None_)). + +Definition memory_read_bytes : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "memory"; "start_position"; "size" ] |) in + let _ := Constant.str " + Read bytes from memory. + + Parameters + ---------- + memory : + Memory contents of the EVM. + start_position : + Starting pointer to the memory. + size : + Size of the data that needs to be read from `start_position`. + + Returns + ------- + data_bytes : + Data read from memory. + " in + let _ := M.return_ (| + M.slice (| + M.get_name (| globals, "memory" |), + M.get_name (| globals, "start_position" |), + BinOp.add (| + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.get_name (| globals, "start_position" |) + ], + make_dict [] + |), + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.get_name (| globals, "size" |) + ], + make_dict [] + |) + |), + Constant.None_ + |) + |) in + M.pure Constant.None_)). + +Definition buffer_read : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "buffer"; "start_position"; "size" ] |) in + let _ := Constant.str " + Read bytes from a buffer. Padding with zeros if necessary. + + Parameters + ---------- + buffer : + Memory contents of the EVM. + start_position : + Starting pointer to the memory. + size : + Size of the data that needs to be read from `start_position`. + + Returns + ------- + data_bytes : + Data read from memory. + " in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, "right_pad_zero_bytes" |), + make_list [ + M.slice (| + M.get_name (| globals, "buffer" |), + M.get_name (| globals, "start_position" |), + BinOp.add (| + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.get_name (| globals, "start_position" |) + ], + make_dict [] + |), + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.get_name (| globals, "size" |) + ], + make_dict [] + |) + |), + Constant.None_ + |); + M.get_name (| globals, "size" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). diff --git a/CoqOfPython/ethereum/gray_glacier/vm/precompiled_contracts/__init__.v b/CoqOfPython/ethereum/gray_glacier/vm/precompiled_contracts/__init__.v new file mode 100644 index 0000000..fd5c1ed --- /dev/null +++ b/CoqOfPython/ethereum/gray_glacier/vm/precompiled_contracts/__init__.v @@ -0,0 +1,116 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.gray_glacier.vm.precompiled_contracts.__init__". + +Definition expr_1 : Value.t := + Constant.str " +Precompiled Contract Addresses +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Addresses of precompiled contracts and mappings to their +implementations. +". + +Axiom ethereum_gray_glacier_utils_hexadecimal_imports_hex_to_address : + IsImported globals "ethereum.gray_glacier.utils.hexadecimal" "hex_to_address". + +Definition __all__ : Value.t := M.run ltac:(M.monadic ( + make_tuple [ Constant.str "ECRECOVER_ADDRESS"; Constant.str "SHA256_ADDRESS"; Constant.str "RIPEMD160_ADDRESS"; Constant.str "IDENTITY_ADDRESS"; Constant.str "MODEXP_ADDRESS"; Constant.str "ALT_BN128_ADD_ADDRESS"; Constant.str "ALT_BN128_MUL_ADDRESS"; Constant.str "ALT_BN128_PAIRING_CHECK_ADDRESS"; Constant.str "BLAKE2F_ADDRESS" ] +)). + +Definition ECRECOVER_ADDRESS : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "hex_to_address" |), + make_list [ + Constant.str "0x01" + ], + make_dict [] + |) +)). + +Definition SHA256_ADDRESS : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "hex_to_address" |), + make_list [ + Constant.str "0x02" + ], + make_dict [] + |) +)). + +Definition RIPEMD160_ADDRESS : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "hex_to_address" |), + make_list [ + Constant.str "0x03" + ], + make_dict [] + |) +)). + +Definition IDENTITY_ADDRESS : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "hex_to_address" |), + make_list [ + Constant.str "0x04" + ], + make_dict [] + |) +)). + +Definition MODEXP_ADDRESS : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "hex_to_address" |), + make_list [ + Constant.str "0x05" + ], + make_dict [] + |) +)). + +Definition ALT_BN128_ADD_ADDRESS : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "hex_to_address" |), + make_list [ + Constant.str "0x06" + ], + make_dict [] + |) +)). + +Definition ALT_BN128_MUL_ADDRESS : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "hex_to_address" |), + make_list [ + Constant.str "0x07" + ], + make_dict [] + |) +)). + +Definition ALT_BN128_PAIRING_CHECK_ADDRESS : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "hex_to_address" |), + make_list [ + Constant.str "0x08" + ], + make_dict [] + |) +)). + +Definition BLAKE2F_ADDRESS : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "hex_to_address" |), + make_list [ + Constant.str "0x09" + ], + make_dict [] + |) +)). diff --git a/CoqOfPython/ethereum/gray_glacier/vm/precompiled_contracts/alt_bn128.v b/CoqOfPython/ethereum/gray_glacier/vm/precompiled_contracts/alt_bn128.v new file mode 100644 index 0000000..35d4975 --- /dev/null +++ b/CoqOfPython/ethereum/gray_glacier/vm/precompiled_contracts/alt_bn128.v @@ -0,0 +1,778 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.gray_glacier.vm.precompiled_contracts.alt_bn128". + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) ALT_BN128 CONTRACTS +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementation of the ALT_BN128 precompiled contracts. +". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". + +Axiom ethereum_crypto_alt_bn128_imports_ALT_BN128_CURVE_ORDER : + IsImported globals "ethereum.crypto.alt_bn128" "ALT_BN128_CURVE_ORDER". +Axiom ethereum_crypto_alt_bn128_imports_ALT_BN128_PRIME : + IsImported globals "ethereum.crypto.alt_bn128" "ALT_BN128_PRIME". +Axiom ethereum_crypto_alt_bn128_imports_BNF : + IsImported globals "ethereum.crypto.alt_bn128" "BNF". +Axiom ethereum_crypto_alt_bn128_imports_BNF2 : + IsImported globals "ethereum.crypto.alt_bn128" "BNF2". +Axiom ethereum_crypto_alt_bn128_imports_BNF12 : + IsImported globals "ethereum.crypto.alt_bn128" "BNF12". +Axiom ethereum_crypto_alt_bn128_imports_BNP : + IsImported globals "ethereum.crypto.alt_bn128" "BNP". +Axiom ethereum_crypto_alt_bn128_imports_BNP2 : + IsImported globals "ethereum.crypto.alt_bn128" "BNP2". +Axiom ethereum_crypto_alt_bn128_imports_pairing : + IsImported globals "ethereum.crypto.alt_bn128" "pairing". + +Axiom ethereum_utils_ensure_imports_ensure : + IsImported globals "ethereum.utils.ensure" "ensure". + +Axiom ethereum_gray_glacier_vm_imports_Evm : + IsImported globals "ethereum.gray_glacier.vm" "Evm". + +Axiom ethereum_gray_glacier_vm_gas_imports_charge_gas : + IsImported globals "ethereum.gray_glacier.vm.gas" "charge_gas". + +Axiom ethereum_gray_glacier_vm_memory_imports_buffer_read : + IsImported globals "ethereum.gray_glacier.vm.memory" "buffer_read". + +Axiom ethereum_gray_glacier_vm_exceptions_imports_OutOfGasError : + IsImported globals "ethereum.gray_glacier.vm.exceptions" "OutOfGasError". + +Definition alt_bn128_add : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + The ALT_BN128 addition precompiled contract. + + Parameters + ---------- + evm : + The current EVM frame. + " in + let _ := M.assign_local (| + "data" , + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "data" |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 150 + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "x0_bytes" , + M.call (| + M.get_name (| globals, "buffer_read" |), + make_list [ + M.get_name (| globals, "data" |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 32 + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "x0_value" , + M.call (| + M.get_field (| M.get_name (| globals, "U256" |), "from_be_bytes" |), + make_list [ + M.get_name (| globals, "x0_bytes" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "y0_bytes" , + M.call (| + M.get_name (| globals, "buffer_read" |), + make_list [ + M.get_name (| globals, "data" |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 32 + ], + make_dict [] + |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 32 + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "y0_value" , + M.call (| + M.get_field (| M.get_name (| globals, "U256" |), "from_be_bytes" |), + make_list [ + M.get_name (| globals, "y0_bytes" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "x1_bytes" , + M.call (| + M.get_name (| globals, "buffer_read" |), + make_list [ + M.get_name (| globals, "data" |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 64 + ], + make_dict [] + |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 32 + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "x1_value" , + M.call (| + M.get_field (| M.get_name (| globals, "U256" |), "from_be_bytes" |), + make_list [ + M.get_name (| globals, "x1_bytes" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "y1_bytes" , + M.call (| + M.get_name (| globals, "buffer_read" |), + make_list [ + M.get_name (| globals, "data" |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 96 + ], + make_dict [] + |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 32 + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "y1_value" , + M.call (| + M.get_field (| M.get_name (| globals, "U256" |), "from_be_bytes" |), + make_list [ + M.get_name (| globals, "y1_bytes" |) + ], + make_dict [] + |) + |) in + let _ := + M.for_ (| + M.get_name (| globals, "i" |), + make_tuple [ M.get_name (| globals, "x0_value" |); M.get_name (| globals, "y0_value" |); M.get_name (| globals, "x1_value" |); M.get_name (| globals, "y1_value" |) ], + ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + Compare.gt_e (| + M.get_name (| globals, "i" |), + M.get_name (| globals, "ALT_BN128_PRIME" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, "OutOfGasError" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in +(* At stmt: unsupported node type: Try *) + let _ := M.assign_local (| + "p" , + BinOp.add (| + M.get_name (| globals, "p0" |), + M.get_name (| globals, "p1" |) + |) + |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, "evm" |), "output" |), + BinOp.add (| + M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, "p" |), "x" |), "to_be_bytes32" |), + make_list [], + make_dict [] + |), + M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, "p" |), "y" |), "to_be_bytes32" |), + make_list [], + make_dict [] + |) + |) + |) in + M.pure Constant.None_)). + +Definition alt_bn128_mul : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + The ALT_BN128 multiplication precompiled contract. + + Parameters + ---------- + evm : + The current EVM frame. + " in + let _ := M.assign_local (| + "data" , + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "data" |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 6000 + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "x0_bytes" , + M.call (| + M.get_name (| globals, "buffer_read" |), + make_list [ + M.get_name (| globals, "data" |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 32 + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "x0_value" , + M.call (| + M.get_field (| M.get_name (| globals, "U256" |), "from_be_bytes" |), + make_list [ + M.get_name (| globals, "x0_bytes" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "y0_bytes" , + M.call (| + M.get_name (| globals, "buffer_read" |), + make_list [ + M.get_name (| globals, "data" |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 32 + ], + make_dict [] + |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 32 + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "y0_value" , + M.call (| + M.get_field (| M.get_name (| globals, "U256" |), "from_be_bytes" |), + make_list [ + M.get_name (| globals, "y0_bytes" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "n" , + M.call (| + M.get_field (| M.get_name (| globals, "U256" |), "from_be_bytes" |), + make_list [ + M.call (| + M.get_name (| globals, "buffer_read" |), + make_list [ + M.get_name (| globals, "data" |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 64 + ], + make_dict [] + |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 32 + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := + M.for_ (| + M.get_name (| globals, "i" |), + make_tuple [ M.get_name (| globals, "x0_value" |); M.get_name (| globals, "y0_value" |) ], + ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + Compare.gt_e (| + M.get_name (| globals, "i" |), + M.get_name (| globals, "ALT_BN128_PRIME" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, "OutOfGasError" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in +(* At stmt: unsupported node type: Try *) + let _ := M.assign_local (| + "p" , + M.call (| + M.get_field (| M.get_name (| globals, "p0" |), "mul_by" |), + make_list [ + M.get_name (| globals, "n" |) + ], + make_dict [] + |) + |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, "evm" |), "output" |), + BinOp.add (| + M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, "p" |), "x" |), "to_be_bytes32" |), + make_list [], + make_dict [] + |), + M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, "p" |), "y" |), "to_be_bytes32" |), + make_list [], + make_dict [] + |) + |) + |) in + M.pure Constant.None_)). + +Definition alt_bn128_pairing_check : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + The ALT_BN128 pairing check precompiled contract. + + Parameters + ---------- + evm : + The current EVM frame. + " in + let _ := M.assign_local (| + "data" , + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "data" |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + BinOp.add (| + BinOp.mult (| + Constant.int 34000, + BinOp.floor_div (| + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_name (| globals, "data" |) + ], + make_dict [] + |), + Constant.int 192 + |) + |), + Constant.int 45000 + |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.not_eq (| + BinOp.mod_ (| + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_name (| globals, "data" |) + ], + make_dict [] + |), + Constant.int 192 + |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, "OutOfGasError" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "result" , + M.call (| + M.get_field (| M.get_name (| globals, "BNF12" |), "from_int" |), + make_list [ + Constant.int 1 + ], + make_dict [] + |) + |) in + let _ := + M.for_ (| + M.get_name (| globals, "i" |), + M.call (| + M.get_name (| globals, "range" |), + make_list [ + BinOp.floor_div (| + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_name (| globals, "data" |) + ], + make_dict [] + |), + Constant.int 192 + |) + ], + make_dict [] + |), + ltac:(M.monadic ( + let _ := M.assign_local (| + "values" , + make_list [] + |) in + let _ := + M.for_ (| + M.get_name (| globals, "j" |), + M.call (| + M.get_name (| globals, "range" |), + make_list [ + Constant.int 6 + ], + make_dict [] + |), + ltac:(M.monadic ( + let _ := M.assign_local (| + "value" , + M.call (| + M.get_field (| M.get_name (| globals, "U256" |), "from_be_bytes" |), + make_list [ + M.slice (| + M.get_name (| globals, "data" |), + BinOp.add (| + BinOp.mult (| + M.get_name (| globals, "i" |), + Constant.int 192 + |), + BinOp.mult (| + Constant.int 32, + M.get_name (| globals, "j" |) + |) + |), + BinOp.add (| + BinOp.mult (| + M.get_name (| globals, "i" |), + Constant.int 192 + |), + BinOp.mult (| + Constant.int 32, + BinOp.add (| + M.get_name (| globals, "j" |), + Constant.int 1 + |) + |) + |), + Constant.None_ + |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.gt_e (| + M.get_name (| globals, "value" |), + M.get_name (| globals, "ALT_BN128_PRIME" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, "OutOfGasError" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.call (| + M.get_field (| M.get_name (| globals, "values" |), "append" |), + make_list [ + M.call (| + M.get_name (| globals, "int" |), + make_list [ + M.get_name (| globals, "value" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in +(* At stmt: unsupported node type: Try *) + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + Compare.eq (| + M.call (| + M.get_field (| M.get_name (| globals, "p" |), "mul_by" |), + make_list [ + M.get_name (| globals, "ALT_BN128_CURVE_ORDER" |) + ], + make_dict [] + |), + M.call (| + M.get_field (| M.get_name (| globals, "BNP" |), "point_at_infinity" |), + make_list [], + make_dict [] + |) + |); + M.get_name (| globals, "OutOfGasError" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + Compare.eq (| + M.call (| + M.get_field (| M.get_name (| globals, "q" |), "mul_by" |), + make_list [ + M.get_name (| globals, "ALT_BN128_CURVE_ORDER" |) + ], + make_dict [] + |), + M.call (| + M.get_field (| M.get_name (| globals, "BNP2" |), "point_at_infinity" |), + make_list [], + make_dict [] + |) + |); + M.get_name (| globals, "OutOfGasError" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + BoolOp.and (| + Compare.not_eq (| + M.get_name (| globals, "p" |), + M.call (| + M.get_field (| M.get_name (| globals, "BNP" |), "point_at_infinity" |), + make_list [], + make_dict [] + |) + |), + ltac:(M.monadic ( + Compare.not_eq (| + M.get_name (| globals, "q" |), + M.call (| + M.get_field (| M.get_name (| globals, "BNP2" |), "point_at_infinity" |), + make_list [], + make_dict [] + |) + |) + )) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "result" , + BinOp.mult (| + M.get_name (| globals, "result" |), + M.call (| + M.get_name (| globals, "pairing" |), + make_list [ + M.get_name (| globals, "q" |); + M.get_name (| globals, "p" |) + ], + make_dict [] + |) + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, "result" |), + M.call (| + M.get_field (| M.get_name (| globals, "BNF12" |), "from_int" |), + make_list [ + Constant.int 1 + ], + make_dict [] + |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign (| + M.get_field (| M.get_name (| globals, "evm" |), "output" |), + M.call (| + M.get_field (| M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 1 + ], + make_dict [] + |), "to_be_bytes32" |), + make_list [], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign (| + M.get_field (| M.get_name (| globals, "evm" |), "output" |), + M.call (| + M.get_field (| M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |), "to_be_bytes32" |), + make_list [], + make_dict [] + |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_)). diff --git a/CoqOfPython/ethereum/gray_glacier/vm/precompiled_contracts/blake2f.v b/CoqOfPython/ethereum/gray_glacier/vm/precompiled_contracts/blake2f.v new file mode 100644 index 0000000..febbff6 --- /dev/null +++ b/CoqOfPython/ethereum/gray_glacier/vm/precompiled_contracts/blake2f.v @@ -0,0 +1,127 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.gray_glacier.vm.precompiled_contracts.blake2f". + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) Blake2 PRECOMPILED CONTRACT +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementation of the `Blake2` precompiled contract. +". + +Axiom ethereum_crypto_blake2_imports_Blake2b : + IsImported globals "ethereum.crypto.blake2" "Blake2b". + +Axiom ethereum_utils_ensure_imports_ensure : + IsImported globals "ethereum.utils.ensure" "ensure". + +Axiom ethereum_gray_glacier_vm_imports_Evm : + IsImported globals "ethereum.gray_glacier.vm" "Evm". + +Axiom ethereum_gray_glacier_vm_gas_imports_GAS_BLAKE2_PER_ROUND : + IsImported globals "ethereum.gray_glacier.vm.gas" "GAS_BLAKE2_PER_ROUND". +Axiom ethereum_gray_glacier_vm_gas_imports_charge_gas : + IsImported globals "ethereum.gray_glacier.vm.gas" "charge_gas". + +Axiom ethereum_gray_glacier_vm_exceptions_imports_InvalidParameter : + IsImported globals "ethereum.gray_glacier.vm.exceptions" "InvalidParameter". + +Definition blake2f : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Writes the Blake2 hash to output. + + Parameters + ---------- + evm : + The current EVM frame. + " in + let _ := M.assign_local (| + "data" , + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "data" |) + |) in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + Compare.eq (| + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_name (| globals, "data" |) + ], + make_dict [] + |), + Constant.int 213 + |); + M.get_name (| globals, "InvalidParameter" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "blake2b" , + M.call (| + M.get_name (| globals, "Blake2b" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.assign (| + make_tuple [ M.get_name (| globals, "rounds" |); M.get_name (| globals, "h" |); M.get_name (| globals, "m" |); M.get_name (| globals, "t_0" |); M.get_name (| globals, "t_1" |); M.get_name (| globals, "f" |) ], + M.call (| + M.get_field (| M.get_name (| globals, "blake2b" |), "get_blake2_parameters" |), + make_list [ + M.get_name (| globals, "data" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + BinOp.mult (| + M.get_name (| globals, "GAS_BLAKE2_PER_ROUND" |), + M.get_name (| globals, "rounds" |) + |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + Compare.in_ (| + M.get_name (| globals, "f" |), + make_list [ + Constant.int 0; + Constant.int 1 + ] + |); + M.get_name (| globals, "InvalidParameter" |) + ], + make_dict [] + |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, "evm" |), "output" |), + M.call (| + M.get_field (| M.get_name (| globals, "blake2b" |), "compress" |), + make_list [ + M.get_name (| globals, "rounds" |); + M.get_name (| globals, "h" |); + M.get_name (| globals, "m" |); + M.get_name (| globals, "t_0" |); + M.get_name (| globals, "t_1" |); + M.get_name (| globals, "f" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). diff --git a/CoqOfPython/ethereum/gray_glacier/vm/precompiled_contracts/ecrecover.v b/CoqOfPython/ethereum/gray_glacier/vm/precompiled_contracts/ecrecover.v new file mode 100644 index 0000000..2df1000 --- /dev/null +++ b/CoqOfPython/ethereum/gray_glacier/vm/precompiled_contracts/ecrecover.v @@ -0,0 +1,301 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.gray_glacier.vm.precompiled_contracts.ecrecover". + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) ECRECOVER PRECOMPILED CONTRACT +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementation of the ECRECOVER precompiled contract. +". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". + +Axiom ethereum_crypto_elliptic_curve_imports_SECP256K1N : + IsImported globals "ethereum.crypto.elliptic_curve" "SECP256K1N". +Axiom ethereum_crypto_elliptic_curve_imports_secp256k1_recover : + IsImported globals "ethereum.crypto.elliptic_curve" "secp256k1_recover". + +Axiom ethereum_crypto_hash_imports_Hash32 : + IsImported globals "ethereum.crypto.hash" "Hash32". +Axiom ethereum_crypto_hash_imports_keccak256 : + IsImported globals "ethereum.crypto.hash" "keccak256". + +Axiom ethereum_utils_byte_imports_left_pad_zero_bytes : + IsImported globals "ethereum.utils.byte" "left_pad_zero_bytes". + +Axiom ethereum_gray_glacier_vm_imports_Evm : + IsImported globals "ethereum.gray_glacier.vm" "Evm". + +Axiom ethereum_gray_glacier_vm_gas_imports_GAS_ECRECOVER : + IsImported globals "ethereum.gray_glacier.vm.gas" "GAS_ECRECOVER". +Axiom ethereum_gray_glacier_vm_gas_imports_charge_gas : + IsImported globals "ethereum.gray_glacier.vm.gas" "charge_gas". + +Axiom ethereum_gray_glacier_vm_memory_imports_buffer_read : + IsImported globals "ethereum.gray_glacier.vm.memory" "buffer_read". + +Definition ecrecover : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Decrypts the address using elliptic curve DSA recovery mechanism and writes + the address to output. + + Parameters + ---------- + evm : + The current EVM frame. + " in + let _ := M.assign_local (| + "data" , + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "data" |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_ECRECOVER" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "message_hash_bytes" , + M.call (| + M.get_name (| globals, "buffer_read" |), + make_list [ + M.get_name (| globals, "data" |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 32 + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "message_hash" , + M.call (| + M.get_name (| globals, "Hash32" |), + make_list [ + M.get_name (| globals, "message_hash_bytes" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "v" , + M.call (| + M.get_field (| M.get_name (| globals, "U256" |), "from_be_bytes" |), + make_list [ + M.call (| + M.get_name (| globals, "buffer_read" |), + make_list [ + M.get_name (| globals, "data" |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 32 + ], + make_dict [] + |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 32 + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "r" , + M.call (| + M.get_field (| M.get_name (| globals, "U256" |), "from_be_bytes" |), + make_list [ + M.call (| + M.get_name (| globals, "buffer_read" |), + make_list [ + M.get_name (| globals, "data" |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 64 + ], + make_dict [] + |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 32 + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "s" , + M.call (| + M.get_field (| M.get_name (| globals, "U256" |), "from_be_bytes" |), + make_list [ + M.call (| + M.get_name (| globals, "buffer_read" |), + make_list [ + M.get_name (| globals, "data" |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 96 + ], + make_dict [] + |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 32 + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + BoolOp.and (| + Compare.not_eq (| + M.get_name (| globals, "v" |), + Constant.int 27 + |), + ltac:(M.monadic ( + Compare.not_eq (| + M.get_name (| globals, "v" |), + Constant.int 28 + |) + )) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + Constant.None_ + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + BoolOp.or (| + Compare.gt_e (| + Constant.int 0, + M.get_name (| globals, "r" |) + |), + ltac:(M.monadic ( + Compare.gt_e (| + M.get_name (| globals, "r" |), + M.get_name (| globals, "SECP256K1N" |) + |) + )) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + Constant.None_ + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + BoolOp.or (| + Compare.gt_e (| + Constant.int 0, + M.get_name (| globals, "s" |) + |), + ltac:(M.monadic ( + Compare.gt_e (| + M.get_name (| globals, "s" |), + M.get_name (| globals, "SECP256K1N" |) + |) + )) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + Constant.None_ + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in +(* At stmt: unsupported node type: Try *) + let _ := M.assign_local (| + "address" , + M.slice (| + M.call (| + M.get_name (| globals, "keccak256" |), + make_list [ + M.get_name (| globals, "public_key" |) + ], + make_dict [] + |), + Constant.int 12, + Constant.int 32, + Constant.None_ + |) + |) in + let _ := M.assign_local (| + "padded_address" , + M.call (| + M.get_name (| globals, "left_pad_zero_bytes" |), + make_list [ + M.get_name (| globals, "address" |); + Constant.int 32 + ], + make_dict [] + |) + |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, "evm" |), "output" |), + M.get_name (| globals, "padded_address" |) + |) in + M.pure Constant.None_)). diff --git a/CoqOfPython/ethereum/gray_glacier/vm/precompiled_contracts/identity.v b/CoqOfPython/ethereum/gray_glacier/vm/precompiled_contracts/identity.v new file mode 100644 index 0000000..e41c6b5 --- /dev/null +++ b/CoqOfPython/ethereum/gray_glacier/vm/precompiled_contracts/identity.v @@ -0,0 +1,94 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.gray_glacier.vm.precompiled_contracts.identity". + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) IDENTITY PRECOMPILED CONTRACT +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementation of the `IDENTITY` precompiled contract. +". + +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". + +Axiom ethereum_utils_numeric_imports_ceil32 : + IsImported globals "ethereum.utils.numeric" "ceil32". + +Axiom ethereum_gray_glacier_vm_imports_Evm : + IsImported globals "ethereum.gray_glacier.vm" "Evm". + +Axiom ethereum_gray_glacier_vm_gas_imports_GAS_IDENTITY : + IsImported globals "ethereum.gray_glacier.vm.gas" "GAS_IDENTITY". +Axiom ethereum_gray_glacier_vm_gas_imports_GAS_IDENTITY_WORD : + IsImported globals "ethereum.gray_glacier.vm.gas" "GAS_IDENTITY_WORD". +Axiom ethereum_gray_glacier_vm_gas_imports_charge_gas : + IsImported globals "ethereum.gray_glacier.vm.gas" "charge_gas". + +Definition identity : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Writes the message data to output. + + Parameters + ---------- + evm : + The current EVM frame. + " in + let _ := M.assign_local (| + "data" , + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "data" |) + |) in + let _ := M.assign_local (| + "word_count" , + BinOp.floor_div (| + M.call (| + M.get_name (| globals, "ceil32" |), + make_list [ + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_name (| globals, "data" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |), + Constant.int 32 + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + BinOp.add (| + M.get_name (| globals, "GAS_IDENTITY" |), + BinOp.mult (| + M.get_name (| globals, "GAS_IDENTITY_WORD" |), + M.get_name (| globals, "word_count" |) + |) + |) + ], + make_dict [] + |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, "evm" |), "output" |), + M.get_name (| globals, "data" |) + |) in + M.pure Constant.None_)). diff --git a/CoqOfPython/ethereum/gray_glacier/vm/precompiled_contracts/mapping.v b/CoqOfPython/ethereum/gray_glacier/vm/precompiled_contracts/mapping.v new file mode 100644 index 0000000..61078a7 --- /dev/null +++ b/CoqOfPython/ethereum/gray_glacier/vm/precompiled_contracts/mapping.v @@ -0,0 +1,72 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.gray_glacier.vm.precompiled_contracts.mapping". + +Definition expr_1 : Value.t := + Constant.str " +Precompiled Contract Addresses +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Mapping of precompiled contracts their implementations. +". + +Axiom typing_imports_Callable : + IsImported globals "typing" "Callable". +Axiom typing_imports_Dict : + IsImported globals "typing" "Dict". + +Axiom ethereum_gray_glacier_fork_types_imports_Address : + IsImported globals "ethereum.gray_glacier.fork_types" "Address". + +Axiom ethereum_gray_glacier_vm_precompiled_contracts_imports_ALT_BN128_ADD_ADDRESS : + IsImported globals "ethereum.gray_glacier.vm.precompiled_contracts" "ALT_BN128_ADD_ADDRESS". +Axiom ethereum_gray_glacier_vm_precompiled_contracts_imports_ALT_BN128_MUL_ADDRESS : + IsImported globals "ethereum.gray_glacier.vm.precompiled_contracts" "ALT_BN128_MUL_ADDRESS". +Axiom ethereum_gray_glacier_vm_precompiled_contracts_imports_ALT_BN128_PAIRING_CHECK_ADDRESS : + IsImported globals "ethereum.gray_glacier.vm.precompiled_contracts" "ALT_BN128_PAIRING_CHECK_ADDRESS". +Axiom ethereum_gray_glacier_vm_precompiled_contracts_imports_BLAKE2F_ADDRESS : + IsImported globals "ethereum.gray_glacier.vm.precompiled_contracts" "BLAKE2F_ADDRESS". +Axiom ethereum_gray_glacier_vm_precompiled_contracts_imports_ECRECOVER_ADDRESS : + IsImported globals "ethereum.gray_glacier.vm.precompiled_contracts" "ECRECOVER_ADDRESS". +Axiom ethereum_gray_glacier_vm_precompiled_contracts_imports_IDENTITY_ADDRESS : + IsImported globals "ethereum.gray_glacier.vm.precompiled_contracts" "IDENTITY_ADDRESS". +Axiom ethereum_gray_glacier_vm_precompiled_contracts_imports_MODEXP_ADDRESS : + IsImported globals "ethereum.gray_glacier.vm.precompiled_contracts" "MODEXP_ADDRESS". +Axiom ethereum_gray_glacier_vm_precompiled_contracts_imports_RIPEMD160_ADDRESS : + IsImported globals "ethereum.gray_glacier.vm.precompiled_contracts" "RIPEMD160_ADDRESS". +Axiom ethereum_gray_glacier_vm_precompiled_contracts_imports_SHA256_ADDRESS : + IsImported globals "ethereum.gray_glacier.vm.precompiled_contracts" "SHA256_ADDRESS". + +Axiom ethereum_gray_glacier_vm_precompiled_contracts_alt_bn128_imports_alt_bn128_add : + IsImported globals "ethereum.gray_glacier.vm.precompiled_contracts.alt_bn128" "alt_bn128_add". +Axiom ethereum_gray_glacier_vm_precompiled_contracts_alt_bn128_imports_alt_bn128_mul : + IsImported globals "ethereum.gray_glacier.vm.precompiled_contracts.alt_bn128" "alt_bn128_mul". +Axiom ethereum_gray_glacier_vm_precompiled_contracts_alt_bn128_imports_alt_bn128_pairing_check : + IsImported globals "ethereum.gray_glacier.vm.precompiled_contracts.alt_bn128" "alt_bn128_pairing_check". + +Axiom ethereum_gray_glacier_vm_precompiled_contracts_blake2f_imports_blake2f : + IsImported globals "ethereum.gray_glacier.vm.precompiled_contracts.blake2f" "blake2f". + +Axiom ethereum_gray_glacier_vm_precompiled_contracts_ecrecover_imports_ecrecover : + IsImported globals "ethereum.gray_glacier.vm.precompiled_contracts.ecrecover" "ecrecover". + +Axiom ethereum_gray_glacier_vm_precompiled_contracts_identity_imports_identity : + IsImported globals "ethereum.gray_glacier.vm.precompiled_contracts.identity" "identity". + +Axiom ethereum_gray_glacier_vm_precompiled_contracts_modexp_imports_modexp : + IsImported globals "ethereum.gray_glacier.vm.precompiled_contracts.modexp" "modexp". + +Axiom ethereum_gray_glacier_vm_precompiled_contracts_ripemd160_imports_ripemd160 : + IsImported globals "ethereum.gray_glacier.vm.precompiled_contracts.ripemd160" "ripemd160". + +Axiom ethereum_gray_glacier_vm_precompiled_contracts_sha256_imports_sha256 : + IsImported globals "ethereum.gray_glacier.vm.precompiled_contracts.sha256" "sha256". + +(* At top_level_stmt: unsupported node type: AnnAssign *) diff --git a/CoqOfPython/ethereum/gray_glacier/vm/precompiled_contracts/modexp.v b/CoqOfPython/ethereum/gray_glacier/vm/precompiled_contracts/modexp.v new file mode 100644 index 0000000..a12f219 --- /dev/null +++ b/CoqOfPython/ethereum/gray_glacier/vm/precompiled_contracts/modexp.v @@ -0,0 +1,676 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.gray_glacier.vm.precompiled_contracts.modexp". + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) MODEXP PRECOMPILED CONTRACT +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementation of the `MODEXP` precompiled contract. +". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_Bytes : + IsImported globals "ethereum.base_types" "Bytes". +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". + +Axiom ethereum_gray_glacier_vm_imports_Evm : + IsImported globals "ethereum.gray_glacier.vm" "Evm". + +Axiom ethereum_gray_glacier_vm_gas_imports_charge_gas : + IsImported globals "ethereum.gray_glacier.vm.gas" "charge_gas". + +Axiom ethereum_gray_glacier_vm_memory_imports_buffer_read : + IsImported globals "ethereum.gray_glacier.vm.memory" "buffer_read". + +Definition GQUADDIVISOR : Value.t := M.run ltac:(M.monadic ( + Constant.int 3 +)). + +Definition modexp : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Calculates `(base**exp) % modulus` for arbitrary sized `base`, `exp` and. + `modulus`. The return value is the same length as the modulus. + " in + let _ := M.assign_local (| + "data" , + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "data" |) + |) in + let _ := M.assign_local (| + "base_length" , + M.call (| + M.get_field (| M.get_name (| globals, "U256" |), "from_be_bytes" |), + make_list [ + M.call (| + M.get_name (| globals, "buffer_read" |), + make_list [ + M.get_name (| globals, "data" |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 32 + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "exp_length" , + M.call (| + M.get_field (| M.get_name (| globals, "U256" |), "from_be_bytes" |), + make_list [ + M.call (| + M.get_name (| globals, "buffer_read" |), + make_list [ + M.get_name (| globals, "data" |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 32 + ], + make_dict [] + |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 32 + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "modulus_length" , + M.call (| + M.get_field (| M.get_name (| globals, "U256" |), "from_be_bytes" |), + make_list [ + M.call (| + M.get_name (| globals, "buffer_read" |), + make_list [ + M.get_name (| globals, "data" |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 64 + ], + make_dict [] + |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 32 + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "exp_start" , + BinOp.add (| + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 96 + ], + make_dict [] + |), + M.get_name (| globals, "base_length" |) + |) + |) in + let _ := M.assign_local (| + "exp_head" , + M.call (| + M.get_field (| M.get_name (| globals, "Uint" |), "from_be_bytes" |), + make_list [ + M.call (| + M.get_name (| globals, "buffer_read" |), + make_list [ + M.get_name (| globals, "data" |); + M.get_name (| globals, "exp_start" |); + M.call (| + M.get_name (| globals, "min" |), + make_list [ + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 32 + ], + make_dict [] + |); + M.get_name (| globals, "exp_length" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.call (| + M.get_name (| globals, "gas_cost" |), + make_list [ + M.get_name (| globals, "base_length" |); + M.get_name (| globals, "modulus_length" |); + M.get_name (| globals, "exp_length" |); + M.get_name (| globals, "exp_head" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + BoolOp.and (| + Compare.eq (| + M.get_name (| globals, "base_length" |), + Constant.int 0 + |), + ltac:(M.monadic ( + Compare.eq (| + M.get_name (| globals, "modulus_length" |), + Constant.int 0 + |) + )) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign (| + M.get_field (| M.get_name (| globals, "evm" |), "output" |), + M.call (| + M.get_name (| globals, "Bytes" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.return_ (| + Constant.None_ + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "base" , + M.call (| + M.get_field (| M.get_name (| globals, "Uint" |), "from_be_bytes" |), + make_list [ + M.call (| + M.get_name (| globals, "buffer_read" |), + make_list [ + M.get_name (| globals, "data" |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 96 + ], + make_dict [] + |); + M.get_name (| globals, "base_length" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "exp" , + M.call (| + M.get_field (| M.get_name (| globals, "Uint" |), "from_be_bytes" |), + make_list [ + M.call (| + M.get_name (| globals, "buffer_read" |), + make_list [ + M.get_name (| globals, "data" |); + M.get_name (| globals, "exp_start" |); + M.get_name (| globals, "exp_length" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "modulus_start" , + BinOp.add (| + M.get_name (| globals, "exp_start" |), + M.get_name (| globals, "exp_length" |) + |) + |) in + let _ := M.assign_local (| + "modulus" , + M.call (| + M.get_field (| M.get_name (| globals, "Uint" |), "from_be_bytes" |), + make_list [ + M.call (| + M.get_name (| globals, "buffer_read" |), + make_list [ + M.get_name (| globals, "data" |); + M.get_name (| globals, "modulus_start" |); + M.get_name (| globals, "modulus_length" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, "modulus" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign (| + M.get_field (| M.get_name (| globals, "evm" |), "output" |), + BinOp.mult (| + M.call (| + M.get_name (| globals, "Bytes" |), + make_list [ + Constant.bytes "00" + ], + make_dict [] + |), + M.get_name (| globals, "modulus_length" |) + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign (| + M.get_field (| M.get_name (| globals, "evm" |), "output" |), + M.call (| + M.get_field (| M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, "pow" |), + make_list [ + M.get_name (| globals, "base" |); + M.get_name (| globals, "exp" |); + M.get_name (| globals, "modulus" |) + ], + make_dict [] + |) + ], + make_dict [] + |), "to_bytes" |), + make_list [ + M.get_name (| globals, "modulus_length" |); + Constant.str "big" + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_)). + +Definition complexity : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "base_length"; "modulus_length" ] |) in + let _ := Constant.str " + Estimate the complexity of performing a modular exponentiation. + + Parameters + ---------- + + base_length : + Length of the array representing the base integer. + + modulus_length : + Length of the array representing the modulus integer. + + Returns + ------- + + complexity : `Uint` + Complexity of performing the operation. + " in + let _ := M.assign_local (| + "max_length" , + M.call (| + M.get_name (| globals, "max" |), + make_list [ + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.get_name (| globals, "base_length" |) + ], + make_dict [] + |); + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.get_name (| globals, "modulus_length" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "words" , + BinOp.floor_div (| + BinOp.add (| + M.get_name (| globals, "max_length" |), + Constant.int 7 + |), + Constant.int 8 + |) + |) in + let _ := M.return_ (| + BinOp.pow (| + M.get_name (| globals, "words" |), + Constant.int 2 + |) + |) in + M.pure Constant.None_)). + +Definition iterations : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "exponent_length"; "exponent_head" ] |) in + let _ := Constant.str " + Calculate the number of iterations required to perform a modular + exponentiation. + + Parameters + ---------- + + exponent_length : + Length of the array representing the exponent integer. + + exponent_head : + First 32 bytes of the exponent (with leading zero padding if it is + shorter than 32 bytes), as an unsigned integer. + + Returns + ------- + + iterations : `Uint` + Number of iterations. + " in + let _ := + (* if *) + M.if_then_else (| + BoolOp.and (| + Compare.lt_e (| + M.get_name (| globals, "exponent_length" |), + Constant.int 32 + |), + ltac:(M.monadic ( + Compare.eq (| + M.get_name (| globals, "exponent_head" |), + Constant.int 0 + |) + )) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "count" , + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + Compare.lt_e (| + M.get_name (| globals, "exponent_length" |), + Constant.int 32 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "bit_length" , + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.call (| + M.get_field (| M.get_name (| globals, "exponent_head" |), "bit_length" |), + make_list [], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.gt (| + M.get_name (| globals, "bit_length" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_op_local (| + BinOp.sub, + "bit_length", + Constant.int 1 + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "count" , + M.get_name (| globals, "bit_length" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "length_part" , + BinOp.mult (| + Constant.int 8, + BinOp.sub (| + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.get_name (| globals, "exponent_length" |) + ], + make_dict [] + |), + Constant.int 32 + |) + |) + |) in + let _ := M.assign_local (| + "bits_part" , + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.call (| + M.get_field (| M.get_name (| globals, "exponent_head" |), "bit_length" |), + make_list [], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.gt (| + M.get_name (| globals, "bits_part" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_op_local (| + BinOp.sub, + "bits_part", + Constant.int 1 + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "count" , + BinOp.add (| + M.get_name (| globals, "length_part" |), + M.get_name (| globals, "bits_part" |) + |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )) |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, "max" |), + make_list [ + M.get_name (| globals, "count" |); + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 1 + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Definition gas_cost : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "base_length"; "modulus_length"; "exponent_length"; "exponent_head" ] |) in + let _ := Constant.str " + Calculate the gas cost of performing a modular exponentiation. + + Parameters + ---------- + + base_length : + Length of the array representing the base integer. + + modulus_length : + Length of the array representing the modulus integer. + + exponent_length : + Length of the array representing the exponent integer. + + exponent_head : + First 32 bytes of the exponent (with leading zero padding if it is + shorter than 32 bytes), as an unsigned integer. + + Returns + ------- + + gas_cost : `Uint` + Gas required for performing the operation. + " in + let _ := M.assign_local (| + "multiplication_complexity" , + M.call (| + M.get_name (| globals, "complexity" |), + make_list [ + M.get_name (| globals, "base_length" |); + M.get_name (| globals, "modulus_length" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "iteration_count" , + M.call (| + M.get_name (| globals, "iterations" |), + make_list [ + M.get_name (| globals, "exponent_length" |); + M.get_name (| globals, "exponent_head" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "cost" , + BinOp.mult (| + M.get_name (| globals, "multiplication_complexity" |), + M.get_name (| globals, "iteration_count" |) + |) + |) in + let _ := M.assign_op_local (| + BinOp.floor_div, + "cost", + M.get_name (| globals, "GQUADDIVISOR" |) + |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, "max" |), + make_list [ + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 200 + ], + make_dict [] + |); + M.get_name (| globals, "cost" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). diff --git a/CoqOfPython/ethereum/gray_glacier/vm/precompiled_contracts/ripemd160.v b/CoqOfPython/ethereum/gray_glacier/vm/precompiled_contracts/ripemd160.v new file mode 100644 index 0000000..553c4c2 --- /dev/null +++ b/CoqOfPython/ethereum/gray_glacier/vm/precompiled_contracts/ripemd160.v @@ -0,0 +1,125 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.gray_glacier.vm.precompiled_contracts.ripemd160". + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) RIPEMD160 PRECOMPILED CONTRACT +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementation of the `RIPEMD160` precompiled contract. +". + +(* At top_level_stmt: unsupported node type: Import *) + +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". + +Axiom ethereum_utils_byte_imports_left_pad_zero_bytes : + IsImported globals "ethereum.utils.byte" "left_pad_zero_bytes". + +Axiom ethereum_utils_numeric_imports_ceil32 : + IsImported globals "ethereum.utils.numeric" "ceil32". + +Axiom ethereum_gray_glacier_vm_imports_Evm : + IsImported globals "ethereum.gray_glacier.vm" "Evm". + +Axiom ethereum_gray_glacier_vm_gas_imports_GAS_RIPEMD160 : + IsImported globals "ethereum.gray_glacier.vm.gas" "GAS_RIPEMD160". +Axiom ethereum_gray_glacier_vm_gas_imports_GAS_RIPEMD160_WORD : + IsImported globals "ethereum.gray_glacier.vm.gas" "GAS_RIPEMD160_WORD". +Axiom ethereum_gray_glacier_vm_gas_imports_charge_gas : + IsImported globals "ethereum.gray_glacier.vm.gas" "charge_gas". + +Definition ripemd160 : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Writes the ripemd160 hash to output. + + Parameters + ---------- + evm : + The current EVM frame. + " in + let _ := M.assign_local (| + "data" , + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "data" |) + |) in + let _ := M.assign_local (| + "word_count" , + BinOp.floor_div (| + M.call (| + M.get_name (| globals, "ceil32" |), + make_list [ + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_name (| globals, "data" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |), + Constant.int 32 + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + BinOp.add (| + M.get_name (| globals, "GAS_RIPEMD160" |), + BinOp.mult (| + M.get_name (| globals, "GAS_RIPEMD160_WORD" |), + M.get_name (| globals, "word_count" |) + |) + |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "hash_bytes" , + M.call (| + M.get_field (| M.call (| + M.get_field (| M.get_name (| globals, "hashlib" |), "new" |), + make_list [ + Constant.str "ripemd160"; + M.get_name (| globals, "data" |) + ], + make_dict [] + |), "digest" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "padded_hash" , + M.call (| + M.get_name (| globals, "left_pad_zero_bytes" |), + make_list [ + M.get_name (| globals, "hash_bytes" |); + Constant.int 32 + ], + make_dict [] + |) + |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, "evm" |), "output" |), + M.get_name (| globals, "padded_hash" |) + |) in + M.pure Constant.None_)). diff --git a/CoqOfPython/ethereum/gray_glacier/vm/precompiled_contracts/sha256.v b/CoqOfPython/ethereum/gray_glacier/vm/precompiled_contracts/sha256.v new file mode 100644 index 0000000..ae4e91d --- /dev/null +++ b/CoqOfPython/ethereum/gray_glacier/vm/precompiled_contracts/sha256.v @@ -0,0 +1,106 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.gray_glacier.vm.precompiled_contracts.sha256". + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) SHA256 PRECOMPILED CONTRACT +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementation of the `SHA256` precompiled contract. +". + +(* At top_level_stmt: unsupported node type: Import *) + +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". + +Axiom ethereum_utils_numeric_imports_ceil32 : + IsImported globals "ethereum.utils.numeric" "ceil32". + +Axiom ethereum_gray_glacier_vm_imports_Evm : + IsImported globals "ethereum.gray_glacier.vm" "Evm". + +Axiom ethereum_gray_glacier_vm_gas_imports_GAS_SHA256 : + IsImported globals "ethereum.gray_glacier.vm.gas" "GAS_SHA256". +Axiom ethereum_gray_glacier_vm_gas_imports_GAS_SHA256_WORD : + IsImported globals "ethereum.gray_glacier.vm.gas" "GAS_SHA256_WORD". +Axiom ethereum_gray_glacier_vm_gas_imports_charge_gas : + IsImported globals "ethereum.gray_glacier.vm.gas" "charge_gas". + +Definition sha256 : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Writes the sha256 hash to output. + + Parameters + ---------- + evm : + The current EVM frame. + " in + let _ := M.assign_local (| + "data" , + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "data" |) + |) in + let _ := M.assign_local (| + "word_count" , + BinOp.floor_div (| + M.call (| + M.get_name (| globals, "ceil32" |), + make_list [ + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_name (| globals, "data" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |), + Constant.int 32 + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + BinOp.add (| + M.get_name (| globals, "GAS_SHA256" |), + BinOp.mult (| + M.get_name (| globals, "GAS_SHA256_WORD" |), + M.get_name (| globals, "word_count" |) + |) + |) + ], + make_dict [] + |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, "evm" |), "output" |), + M.call (| + M.get_field (| M.call (| + M.get_field (| M.get_name (| globals, "hashlib" |), "sha256" |), + make_list [ + M.get_name (| globals, "data" |) + ], + make_dict [] + |), "digest" |), + make_list [], + make_dict [] + |) + |) in + M.pure Constant.None_)). diff --git a/CoqOfPython/ethereum/gray_glacier/vm/runtime.v b/CoqOfPython/ethereum/gray_glacier/vm/runtime.v new file mode 100644 index 0000000..4c10884 --- /dev/null +++ b/CoqOfPython/ethereum/gray_glacier/vm/runtime.v @@ -0,0 +1,157 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.gray_glacier.vm.runtime". + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) Runtime Operations +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Runtime related operations used while executing EVM code. +". + +Axiom typing_imports_Set : + IsImported globals "typing" "Set". + +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". + +Axiom ethereum_gray_glacier_vm_instructions_imports_Ops : + IsImported globals "ethereum.gray_glacier.vm.instructions" "Ops". + +Definition get_valid_jump_destinations : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "code" ] |) in + let _ := Constant.str " + Analyze the evm code to obtain the set of valid jump destinations. + + Valid jump destinations are defined as follows: + * The jump destination is less than the length of the code. + * The jump destination should have the `JUMPDEST` opcode (0x5B). + * The jump destination shouldn't be part of the data corresponding to + `PUSH-N` opcodes. + + Note - Jump destinations are 0-indexed. + + Parameters + ---------- + code : + The EVM code which is to be executed. + + Returns + ------- + valid_jump_destinations: `Set[Uint]` + The set of valid jump destinations in the code. + " in + let _ := M.assign_local (| + "valid_jump_destinations" , + M.call (| + M.get_name (| globals, "set" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "pc" , + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + |) in + let _ := + M.while (| + Compare.lt (| + M.get_name (| globals, "pc" |), + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_name (| globals, "code" |) + ], + make_dict [] + |) + |), + ltac:(M.monadic ( +(* At stmt: unsupported node type: Try *) + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, "current_opcode" |), + M.get_field (| M.get_name (| globals, "Ops" |), "JUMPDEST" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_field (| M.get_name (| globals, "valid_jump_destinations" |), "add" |), + make_list [ + M.get_name (| globals, "pc" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + BoolOp.and (| + Compare.lt_e (| + M.get_field (| M.get_field (| M.get_name (| globals, "Ops" |), "PUSH1" |), "value" |), + M.get_field (| M.get_name (| globals, "current_opcode" |), "value" |) + |), + ltac:(M.monadic ( + Compare.lt_e (| + M.get_field (| M.get_name (| globals, "current_opcode" |), "value" |), + M.get_field (| M.get_field (| M.get_name (| globals, "Ops" |), "PUSH32" |), "value" |) + |) + )) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "push_data_size" , + BinOp.add (| + BinOp.sub (| + M.get_field (| M.get_name (| globals, "current_opcode" |), "value" |), + M.get_field (| M.get_field (| M.get_name (| globals, "Ops" |), "PUSH1" |), "value" |) + |), + Constant.int 1 + |) + |) in + let _ := M.assign_op_local (| + BinOp.add, + "pc", + M.get_name (| globals, "push_data_size" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )) |) in + let _ := M.assign_op_local (| + BinOp.add, + "pc", + Constant.int 1 + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := M.return_ (| + M.get_name (| globals, "valid_jump_destinations" |) + |) in + M.pure Constant.None_)). diff --git a/CoqOfPython/ethereum/gray_glacier/vm/stack.v b/CoqOfPython/ethereum/gray_glacier/vm/stack.v new file mode 100644 index 0000000..4742c55 --- /dev/null +++ b/CoqOfPython/ethereum/gray_glacier/vm/stack.v @@ -0,0 +1,123 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.gray_glacier.vm.stack". + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) Stack +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementation of the stack operators for the EVM. +". + +Axiom typing_imports_List : + IsImported globals "typing" "List". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". + +Axiom ethereum_gray_glacier_vm_exceptions_imports_StackOverflowError : + IsImported globals "ethereum.gray_glacier.vm.exceptions" "StackOverflowError". +Axiom ethereum_gray_glacier_vm_exceptions_imports_StackUnderflowError : + IsImported globals "ethereum.gray_glacier.vm.exceptions" "StackUnderflowError". + +Definition pop : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "stack" ] |) in + let _ := Constant.str " + Pops the top item off of `stack`. + + Parameters + ---------- + stack : + EVM stack. + + Returns + ------- + value : `U256` + The top element on the stack. + + " in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_name (| globals, "stack" |) + ], + make_dict [] + |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, "StackUnderflowError" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.return_ (| + M.call (| + M.get_field (| M.get_name (| globals, "stack" |), "pop" |), + make_list [], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Definition push : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "stack"; "value" ] |) in + let _ := Constant.str " + Pushes `value` onto `stack`. + + Parameters + ---------- + stack : + EVM stack. + + value : + Item to be pushed onto `stack`. + + " in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_name (| globals, "stack" |) + ], + make_dict [] + |), + Constant.int 1024 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, "StackOverflowError" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.return_ (| + M.call (| + M.get_field (| M.get_name (| globals, "stack" |), "append" |), + make_list [ + M.get_name (| globals, "value" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). diff --git a/CoqOfPython/ethereum/homestead/__init__.v b/CoqOfPython/ethereum/homestead/__init__.v new file mode 100644 index 0000000..b8b69f5 --- /dev/null +++ b/CoqOfPython/ethereum/homestead/__init__.v @@ -0,0 +1,24 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.homestead.__init__". + +Definition expr_1 : Value.t := + Constant.str " +The Homestead fork increases the gas cost of creating contracts, restricts the +range of valid ECDSA signatures for transactions (but not precompiles), tweaks +the behavior of contract creation with insufficient gas, delays the +difficulty bomb, and adds an improved delegate call EVM instruction. +". + +Axiom ethereum_fork_criteria_imports_ByBlockNumber : + IsImported globals "ethereum.fork_criteria" "ByBlockNumber". + +Definition FORK_CRITERIA : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "ByBlockNumber" |), + make_list [ + Constant.int 1150000 + ], + make_dict [] + |) +)). diff --git a/CoqOfPython/ethereum/homestead/blocks.v b/CoqOfPython/ethereum/homestead/blocks.v new file mode 100644 index 0000000..237a920 --- /dev/null +++ b/CoqOfPython/ethereum/homestead/blocks.v @@ -0,0 +1,87 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.homestead.blocks". + +Definition expr_1 : Value.t := + Constant.str " +A `Block` is a single link in the chain that is Ethereum. Each `Block` contains +a `Header` and zero or more transactions. Each `Header` contains associated +metadata like the block number, parent block hash, and how much gas was +consumed by its transactions. + +Together, these blocks form a cryptographically secure journal recording the +history of all state transitions that have happened since the genesis of the +chain. +". + +Axiom dataclasses_imports_dataclass : + IsImported globals "dataclasses" "dataclass". + +Axiom typing_imports_Tuple : + IsImported globals "typing" "Tuple". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_Bytes : + IsImported globals "ethereum.base_types" "Bytes". +Axiom ethereum_base_types_imports_Bytes8 : + IsImported globals "ethereum.base_types" "Bytes8". +Axiom ethereum_base_types_imports_Bytes32 : + IsImported globals "ethereum.base_types" "Bytes32". +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". +Axiom ethereum_base_types_imports_slotted_freezable : + IsImported globals "ethereum.base_types" "slotted_freezable". + +Axiom ethereum_crypto_hash_imports_Hash32 : + IsImported globals "ethereum.crypto.hash" "Hash32". + +Axiom ethereum_homestead_fork_types_imports_Address : + IsImported globals "ethereum.homestead.fork_types" "Address". +Axiom ethereum_homestead_fork_types_imports_Bloom : + IsImported globals "ethereum.homestead.fork_types" "Bloom". +Axiom ethereum_homestead_fork_types_imports_Root : + IsImported globals "ethereum.homestead.fork_types" "Root". + +Axiom ethereum_homestead_transactions_imports_Transaction : + IsImported globals "ethereum.homestead.transactions" "Transaction". + +Definition Header : Value.t := + builtins.make_klass + [] + [ + + ] + [ + + ]. + +Definition Block : Value.t := + builtins.make_klass + [] + [ + + ] + [ + + ]. + +Definition Log : Value.t := + builtins.make_klass + [] + [ + + ] + [ + + ]. + +Definition Receipt : Value.t := + builtins.make_klass + [] + [ + + ] + [ + + ]. diff --git a/CoqOfPython/ethereum/homestead/bloom.v b/CoqOfPython/ethereum/homestead/bloom.v new file mode 100644 index 0000000..04c7450 --- /dev/null +++ b/CoqOfPython/ethereum/homestead/bloom.v @@ -0,0 +1,207 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.homestead.bloom". + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Logs Bloom +^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +This modules defines functions for calculating bloom filters of logs. For the +general theory of bloom filters see e.g. `Wikipedia +`_. Bloom filters are used to allow +for efficient searching of logs by address and/or topic, by rapidly +eliminating blocks and receipts from their search. +". + +Axiom typing_imports_Tuple : + IsImported globals "typing" "Tuple". + +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". + +Axiom ethereum_crypto_hash_imports_keccak256 : + IsImported globals "ethereum.crypto.hash" "keccak256". + +Axiom ethereum_homestead_blocks_imports_Log : + IsImported globals "ethereum.homestead.blocks" "Log". + +Axiom ethereum_homestead_fork_types_imports_Bloom : + IsImported globals "ethereum.homestead.fork_types" "Bloom". + +Definition add_to_bloom : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "bloom"; "bloom_entry" ] |) in + let _ := Constant.str " + Add a bloom entry to the bloom filter (`bloom`). + + The number of hash functions used is 3. They are calculated by taking the + least significant 11 bits from the first 3 16-bit words of the + `keccak_256()` hash of `bloom_entry`. + + Parameters + ---------- + bloom : + The bloom filter. + bloom_entry : + An entry which is to be added to bloom filter. + " in + let _ := M.assign_local (| + "hash" , + M.call (| + M.get_name (| globals, "keccak256" |), + make_list [ + M.get_name (| globals, "bloom_entry" |) + ], + make_dict [] + |) + |) in + let _ := + M.for_ (| + M.get_name (| globals, "idx" |), + make_tuple [ Constant.int 0; Constant.int 2; Constant.int 4 ], + ltac:(M.monadic ( + let _ := M.assign_local (| + "bit_to_set" , + BinOp.bit_and (| + M.call (| + M.get_field (| M.get_name (| globals, "Uint" |), "from_be_bytes" |), + make_list [ + M.slice (| + M.get_name (| globals, "hash" |), + M.get_name (| globals, "idx" |), + BinOp.add (| + M.get_name (| globals, "idx" |), + Constant.int 2 + |), + Constant.None_ + |) + ], + make_dict [] + |), + Constant.int 2047 + |) + |) in + let _ := M.assign_local (| + "bit_index" , + BinOp.sub (| + Constant.int 2047, + M.get_name (| globals, "bit_to_set" |) + |) + |) in + let _ := M.assign_local (| + "byte_index" , + BinOp.floor_div (| + M.get_name (| globals, "bit_index" |), + Constant.int 8 + |) + |) in + let _ := M.assign_local (| + "bit_value" , + BinOp.l_shift (| + Constant.int 1, + BinOp.sub (| + Constant.int 7, + BinOp.mod_ (| + M.get_name (| globals, "bit_index" |), + Constant.int 8 + |) + |) + |) + |) in + let _ := M.assign (| + M.get_subscript (| + M.get_name (| globals, "bloom" |), + M.get_name (| globals, "byte_index" |) + |), + BinOp.bit_or (| + M.get_subscript (| + M.get_name (| globals, "bloom" |), + M.get_name (| globals, "byte_index" |) + |), + M.get_name (| globals, "bit_value" |) + |) + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + M.pure Constant.None_)). + +Definition logs_bloom : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "logs" ] |) in + let _ := Constant.str " + Obtain the logs bloom from a list of log entries. + + The address and each topic of a log are added to the bloom filter. + + Parameters + ---------- + logs : + List of logs for which the logs bloom is to be obtained. + + Returns + ------- + logs_bloom : `Bloom` + The logs bloom obtained which is 256 bytes with some bits set as per + the caller address and the log topics. + " in +(* At stmt: unsupported node type: AnnAssign *) + let _ := + M.for_ (| + M.get_name (| globals, "log" |), + M.get_name (| globals, "logs" |), + ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, "add_to_bloom" |), + make_list [ + M.get_name (| globals, "bloom" |); + M.get_field (| M.get_name (| globals, "log" |), "address" |) + ], + make_dict [] + |) in + let _ := + M.for_ (| + M.get_name (| globals, "topic" |), + M.get_field (| M.get_name (| globals, "log" |), "topics" |), + ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, "add_to_bloom" |), + make_list [ + M.get_name (| globals, "bloom" |); + M.get_name (| globals, "topic" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, "Bloom" |), + make_list [ + M.get_name (| globals, "bloom" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). diff --git a/CoqOfPython/ethereum/homestead/fork.v b/CoqOfPython/ethereum/homestead/fork.v new file mode 100644 index 0000000..44f0c2f --- /dev/null +++ b/CoqOfPython/ethereum/homestead/fork.v @@ -0,0 +1,2427 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.homestead.fork". + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Specification +^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Entry point for the Ethereum specification. +". + +Axiom dataclasses_imports_dataclass : + IsImported globals "dataclasses" "dataclass". + +Axiom typing_imports_List : + IsImported globals "typing" "List". +Axiom typing_imports_Optional : + IsImported globals "typing" "Optional". +Axiom typing_imports_Set : + IsImported globals "typing" "Set". +Axiom typing_imports_Tuple : + IsImported globals "typing" "Tuple". + +Axiom ethereum_base_types_imports_Bytes0 : + IsImported globals "ethereum.base_types" "Bytes0". + +Axiom ethereum_crypto_elliptic_curve_imports_SECP256K1N : + IsImported globals "ethereum.crypto.elliptic_curve" "SECP256K1N". +Axiom ethereum_crypto_elliptic_curve_imports_secp256k1_recover : + IsImported globals "ethereum.crypto.elliptic_curve" "secp256k1_recover". + +Axiom ethereum_crypto_hash_imports_Hash32 : + IsImported globals "ethereum.crypto.hash" "Hash32". +Axiom ethereum_crypto_hash_imports_keccak256 : + IsImported globals "ethereum.crypto.hash" "keccak256". + +Axiom ethereum_ethash_imports_dataset_size : + IsImported globals "ethereum.ethash" "dataset_size". +Axiom ethereum_ethash_imports_generate_cache : + IsImported globals "ethereum.ethash" "generate_cache". +Axiom ethereum_ethash_imports_hashimoto_light : + IsImported globals "ethereum.ethash" "hashimoto_light". + +Axiom ethereum_exceptions_imports_InvalidBlock : + IsImported globals "ethereum.exceptions" "InvalidBlock". + +Axiom ethereum_utils_ensure_imports_ensure : + IsImported globals "ethereum.utils.ensure" "ensure". + +Axiom ethereum_imports_rlp : + IsImported globals "ethereum" "rlp". + +Axiom ethereum_base_types_imports_U64 : + IsImported globals "ethereum.base_types" "U64". +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_U256_CEIL_VALUE : + IsImported globals "ethereum.base_types" "U256_CEIL_VALUE". +Axiom ethereum_base_types_imports_Bytes : + IsImported globals "ethereum.base_types" "Bytes". +Axiom ethereum_base_types_imports_Bytes32 : + IsImported globals "ethereum.base_types" "Bytes32". +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". + +Axiom ethereum_homestead_imports_vm : + IsImported globals "ethereum.homestead" "vm". + +Axiom ethereum_homestead_blocks_imports_Block : + IsImported globals "ethereum.homestead.blocks" "Block". +Axiom ethereum_homestead_blocks_imports_Header : + IsImported globals "ethereum.homestead.blocks" "Header". +Axiom ethereum_homestead_blocks_imports_Log : + IsImported globals "ethereum.homestead.blocks" "Log". +Axiom ethereum_homestead_blocks_imports_Receipt : + IsImported globals "ethereum.homestead.blocks" "Receipt". + +Axiom ethereum_homestead_bloom_imports_logs_bloom : + IsImported globals "ethereum.homestead.bloom" "logs_bloom". + +Axiom ethereum_homestead_fork_types_imports_Address : + IsImported globals "ethereum.homestead.fork_types" "Address". +Axiom ethereum_homestead_fork_types_imports_Bloom : + IsImported globals "ethereum.homestead.fork_types" "Bloom". +Axiom ethereum_homestead_fork_types_imports_Root : + IsImported globals "ethereum.homestead.fork_types" "Root". + +Axiom ethereum_homestead_state_imports_State : + IsImported globals "ethereum.homestead.state" "State". +Axiom ethereum_homestead_state_imports_create_ether : + IsImported globals "ethereum.homestead.state" "create_ether". +Axiom ethereum_homestead_state_imports_destroy_account : + IsImported globals "ethereum.homestead.state" "destroy_account". +Axiom ethereum_homestead_state_imports_get_account : + IsImported globals "ethereum.homestead.state" "get_account". +Axiom ethereum_homestead_state_imports_increment_nonce : + IsImported globals "ethereum.homestead.state" "increment_nonce". +Axiom ethereum_homestead_state_imports_set_account_balance : + IsImported globals "ethereum.homestead.state" "set_account_balance". +Axiom ethereum_homestead_state_imports_state_root : + IsImported globals "ethereum.homestead.state" "state_root". + +Axiom ethereum_homestead_transactions_imports_TX_BASE_COST : + IsImported globals "ethereum.homestead.transactions" "TX_BASE_COST". +Axiom ethereum_homestead_transactions_imports_TX_CREATE_COST : + IsImported globals "ethereum.homestead.transactions" "TX_CREATE_COST". +Axiom ethereum_homestead_transactions_imports_TX_DATA_COST_PER_NON_ZERO : + IsImported globals "ethereum.homestead.transactions" "TX_DATA_COST_PER_NON_ZERO". +Axiom ethereum_homestead_transactions_imports_TX_DATA_COST_PER_ZERO : + IsImported globals "ethereum.homestead.transactions" "TX_DATA_COST_PER_ZERO". +Axiom ethereum_homestead_transactions_imports_Transaction : + IsImported globals "ethereum.homestead.transactions" "Transaction". + +Axiom ethereum_homestead_trie_imports_Trie : + IsImported globals "ethereum.homestead.trie" "Trie". +Axiom ethereum_homestead_trie_imports_root : + IsImported globals "ethereum.homestead.trie" "root". +Axiom ethereum_homestead_trie_imports_trie_set : + IsImported globals "ethereum.homestead.trie" "trie_set". + +Axiom ethereum_homestead_utils_message_imports_prepare_message : + IsImported globals "ethereum.homestead.utils.message" "prepare_message". + +Axiom ethereum_homestead_vm_interpreter_imports_process_message_call : + IsImported globals "ethereum.homestead.vm.interpreter" "process_message_call". + +Definition BLOCK_REWARD : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + BinOp.mult (| + Constant.int 5, + BinOp.pow (| + Constant.int 10, + Constant.int 18 + |) + |) + ], + make_dict [] + |) +)). + +Definition GAS_LIMIT_ADJUSTMENT_FACTOR : Value.t := M.run ltac:(M.monadic ( + Constant.int 1024 +)). + +Definition GAS_LIMIT_MINIMUM : Value.t := M.run ltac:(M.monadic ( + Constant.int 5000 +)). + +Definition MINIMUM_DIFFICULTY : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 131072 + ], + make_dict [] + |) +)). + +Definition MAX_OMMER_DEPTH : Value.t := M.run ltac:(M.monadic ( + Constant.int 6 +)). + +Definition BlockChain : Value.t := + builtins.make_klass + [] + [ + + ] + [ + + ]. + +Definition apply_fork : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "old" ] |) in + let _ := Constant.str " + Transforms the state from the previous hard fork (`old`) into the block + chain object for this hard fork and returns it. + + When forks need to implement an irregular state transition, this function + is used to handle the irregularity. See the :ref:`DAO Fork ` for + an example. + + Parameters + ---------- + old : + Previous block chain object. + + Returns + ------- + new : `BlockChain` + Upgraded block chain object for this hard fork. + " in + let _ := M.return_ (| + M.get_name (| globals, "old" |) + |) in + M.pure Constant.None_)). + +Definition get_last_256_block_hashes : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "chain" ] |) in + let _ := Constant.str " + Obtain the list of hashes of the previous 256 blocks in order of + increasing block number. + + This function will return less hashes for the first 256 blocks. + + The ``BLOCKHASH`` opcode needs to access the latest hashes on the chain, + therefore this function retrieves them. + + Parameters + ---------- + chain : + History and current state. + + Returns + ------- + recent_block_hashes : `List[Hash32]` + Hashes of the recent 256 blocks in order of increasing block number. + " in + let _ := M.assign_local (| + "recent_blocks" , + M.slice (| + M.get_field (| M.get_name (| globals, "chain" |), "blocks" |), + UnOp.sub (| Constant.int 255 |), + Constant.None_, + Constant.None_ + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_name (| globals, "recent_blocks" |) + ], + make_dict [] + |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + make_list [] + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "recent_block_hashes" , + make_list [] + |) in + let _ := + M.for_ (| + M.get_name (| globals, "block" |), + M.get_name (| globals, "recent_blocks" |), + ltac:(M.monadic ( + let _ := M.assign_local (| + "prev_block_hash" , + M.get_field (| M.get_field (| M.get_name (| globals, "block" |), "header" |), "parent_hash" |) + |) in + let _ := M.call (| + M.get_field (| M.get_name (| globals, "recent_block_hashes" |), "append" |), + make_list [ + M.get_name (| globals, "prev_block_hash" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := M.assign_local (| + "most_recent_block_hash" , + M.call (| + M.get_name (| globals, "keccak256" |), + make_list [ + M.call (| + M.get_field (| M.get_name (| globals, "rlp" |), "encode" |), + make_list [ + M.get_field (| M.get_subscript (| + M.get_name (| globals, "recent_blocks" |), + UnOp.sub (| Constant.int 1 |) + |), "header" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_field (| M.get_name (| globals, "recent_block_hashes" |), "append" |), + make_list [ + M.get_name (| globals, "most_recent_block_hash" |) + ], + make_dict [] + |) in + let _ := M.return_ (| + M.get_name (| globals, "recent_block_hashes" |) + |) in + M.pure Constant.None_)). + +Definition state_transition : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "chain"; "block" ] |) in + let _ := Constant.str " + Attempts to apply a block to an existing block chain. + + All parts of the block's contents need to be verified before being added + to the chain. Blocks are verified by ensuring that the contents of the + block make logical sense with the contents of the parent block. The + information in the block's header must also match the corresponding + information in the block. + + To implement Ethereum, in theory clients are only required to store the + most recent 255 blocks of the chain since as far as execution is + concerned, only those blocks are accessed. Practically, however, clients + should store more blocks to handle reorgs. + + Parameters + ---------- + chain : + History and current state. + block : + Block to apply to `chain`. + " in + let _ := M.assign_local (| + "parent_header" , + M.get_field (| M.get_subscript (| + M.get_field (| M.get_name (| globals, "chain" |), "blocks" |), + UnOp.sub (| Constant.int 1 |) + |), "header" |) + |) in + let _ := M.call (| + M.get_name (| globals, "validate_header" |), + make_list [ + M.get_field (| M.get_name (| globals, "block" |), "header" |); + M.get_name (| globals, "parent_header" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "validate_ommers" |), + make_list [ + M.get_field (| M.get_name (| globals, "block" |), "ommers" |); + M.get_field (| M.get_name (| globals, "block" |), "header" |); + M.get_name (| globals, "chain" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "apply_body_output" , + M.call (| + M.get_name (| globals, "apply_body" |), + make_list [ + M.get_field (| M.get_name (| globals, "chain" |), "state" |); + M.call (| + M.get_name (| globals, "get_last_256_block_hashes" |), + make_list [ + M.get_name (| globals, "chain" |) + ], + make_dict [] + |); + M.get_field (| M.get_field (| M.get_name (| globals, "block" |), "header" |), "coinbase" |); + M.get_field (| M.get_field (| M.get_name (| globals, "block" |), "header" |), "number" |); + M.get_field (| M.get_field (| M.get_name (| globals, "block" |), "header" |), "gas_limit" |); + M.get_field (| M.get_field (| M.get_name (| globals, "block" |), "header" |), "timestamp" |); + M.get_field (| M.get_field (| M.get_name (| globals, "block" |), "header" |), "difficulty" |); + M.get_field (| M.get_name (| globals, "block" |), "transactions" |); + M.get_field (| M.get_name (| globals, "block" |), "ommers" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + Compare.eq (| + M.get_field (| M.get_name (| globals, "apply_body_output" |), "block_gas_used" |), + M.get_field (| M.get_field (| M.get_name (| globals, "block" |), "header" |), "gas_used" |) + |); + M.get_name (| globals, "InvalidBlock" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + Compare.eq (| + M.get_field (| M.get_name (| globals, "apply_body_output" |), "transactions_root" |), + M.get_field (| M.get_field (| M.get_name (| globals, "block" |), "header" |), "transactions_root" |) + |); + M.get_name (| globals, "InvalidBlock" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + Compare.eq (| + M.get_field (| M.get_name (| globals, "apply_body_output" |), "state_root" |), + M.get_field (| M.get_field (| M.get_name (| globals, "block" |), "header" |), "state_root" |) + |); + M.get_name (| globals, "InvalidBlock" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + Compare.eq (| + M.get_field (| M.get_name (| globals, "apply_body_output" |), "receipt_root" |), + M.get_field (| M.get_field (| M.get_name (| globals, "block" |), "header" |), "receipt_root" |) + |); + M.get_name (| globals, "InvalidBlock" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + Compare.eq (| + M.get_field (| M.get_name (| globals, "apply_body_output" |), "block_logs_bloom" |), + M.get_field (| M.get_field (| M.get_name (| globals, "block" |), "header" |), "bloom" |) + |); + M.get_name (| globals, "InvalidBlock" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, "chain" |), "blocks" |), "append" |), + make_list [ + M.get_name (| globals, "block" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.gt (| + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_field (| M.get_name (| globals, "chain" |), "blocks" |) + ], + make_dict [] + |), + Constant.int 255 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign (| + M.get_field (| M.get_name (| globals, "chain" |), "blocks" |), + M.slice (| + M.get_field (| M.get_name (| globals, "chain" |), "blocks" |), + UnOp.sub (| Constant.int 255 |), + Constant.None_, + Constant.None_ + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + M.pure Constant.None_)). + +Definition validate_header : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "header"; "parent_header" ] |) in + let _ := Constant.str " + Verifies a block header. + + In order to consider a block's header valid, the logic for the + quantities in the header should match the logic for the block itself. + For example the header timestamp should be greater than the block's parent + timestamp because the block was created *after* the parent block. + Additionally, the block's number should be directly following the parent + block's number since it is the next block in the sequence. + + Parameters + ---------- + header : + Header to check for correctness. + parent_header : + Parent Header of the header to check for correctness + " in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + Compare.gt (| + M.get_field (| M.get_name (| globals, "header" |), "timestamp" |), + M.get_field (| M.get_name (| globals, "parent_header" |), "timestamp" |) + |); + M.get_name (| globals, "InvalidBlock" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + Compare.eq (| + M.get_field (| M.get_name (| globals, "header" |), "number" |), + BinOp.add (| + M.get_field (| M.get_name (| globals, "parent_header" |), "number" |), + Constant.int 1 + |) + |); + M.get_name (| globals, "InvalidBlock" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + M.call (| + M.get_name (| globals, "check_gas_limit" |), + make_list [ + M.get_field (| M.get_name (| globals, "header" |), "gas_limit" |); + M.get_field (| M.get_name (| globals, "parent_header" |), "gas_limit" |) + ], + make_dict [] + |); + M.get_name (| globals, "InvalidBlock" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + Compare.lt_e (| + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_field (| M.get_name (| globals, "header" |), "extra_data" |) + ], + make_dict [] + |), + Constant.int 32 + |); + M.get_name (| globals, "InvalidBlock" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "block_difficulty" , + M.call (| + M.get_name (| globals, "calculate_block_difficulty" |), + make_list [ + M.get_field (| M.get_name (| globals, "header" |), "number" |); + M.get_field (| M.get_name (| globals, "header" |), "timestamp" |); + M.get_field (| M.get_name (| globals, "parent_header" |), "timestamp" |); + M.get_field (| M.get_name (| globals, "parent_header" |), "difficulty" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + Compare.eq (| + M.get_field (| M.get_name (| globals, "header" |), "difficulty" |), + M.get_name (| globals, "block_difficulty" |) + |); + M.get_name (| globals, "InvalidBlock" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "block_parent_hash" , + M.call (| + M.get_name (| globals, "keccak256" |), + make_list [ + M.call (| + M.get_field (| M.get_name (| globals, "rlp" |), "encode" |), + make_list [ + M.get_name (| globals, "parent_header" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + Compare.eq (| + M.get_field (| M.get_name (| globals, "header" |), "parent_hash" |), + M.get_name (| globals, "block_parent_hash" |) + |); + M.get_name (| globals, "InvalidBlock" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "validate_proof_of_work" |), + make_list [ + M.get_name (| globals, "header" |) + ], + make_dict [] + |) in + M.pure Constant.None_)). + +Definition generate_header_hash_for_pow : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "header" ] |) in + let _ := Constant.str " + Generate rlp hash of the header which is to be used for Proof-of-Work + verification. + + In other words, the PoW artefacts `mix_digest` and `nonce` are ignored + while calculating this hash. + + A particular PoW is valid for a single hash, that hash is computed by + this function. The `nonce` and `mix_digest` are omitted from this hash + because they are being changed by miners in their search for a sufficient + proof-of-work. + + Parameters + ---------- + header : + The header object for which the hash is to be generated. + + Returns + ------- + hash : `Hash32` + The PoW valid rlp hash of the passed in header. + " in + let _ := M.assign_local (| + "header_data_without_pow_artefacts" , + make_list [ + M.get_field (| M.get_name (| globals, "header" |), "parent_hash" |); + M.get_field (| M.get_name (| globals, "header" |), "ommers_hash" |); + M.get_field (| M.get_name (| globals, "header" |), "coinbase" |); + M.get_field (| M.get_name (| globals, "header" |), "state_root" |); + M.get_field (| M.get_name (| globals, "header" |), "transactions_root" |); + M.get_field (| M.get_name (| globals, "header" |), "receipt_root" |); + M.get_field (| M.get_name (| globals, "header" |), "bloom" |); + M.get_field (| M.get_name (| globals, "header" |), "difficulty" |); + M.get_field (| M.get_name (| globals, "header" |), "number" |); + M.get_field (| M.get_name (| globals, "header" |), "gas_limit" |); + M.get_field (| M.get_name (| globals, "header" |), "gas_used" |); + M.get_field (| M.get_name (| globals, "header" |), "timestamp" |); + M.get_field (| M.get_name (| globals, "header" |), "extra_data" |) + ] + |) in + let _ := M.return_ (| + M.call (| + M.get_field (| M.get_name (| globals, "rlp" |), "rlp_hash" |), + make_list [ + M.get_name (| globals, "header_data_without_pow_artefacts" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Definition validate_proof_of_work : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "header" ] |) in + let _ := Constant.str " + Validates the Proof of Work constraints. + + In order to verify that a miner's proof-of-work is valid for a block, a + ``mix-digest`` and ``result`` are calculated using the ``hashimoto_light`` + hash function. The mix digest is a hash of the header and the nonce that + is passed through and it confirms whether or not proof-of-work was done + on the correct block. The result is the actual hash value of the block. + + Parameters + ---------- + header : + Header of interest. + " in + let _ := M.assign_local (| + "header_hash" , + M.call (| + M.get_name (| globals, "generate_header_hash_for_pow" |), + make_list [ + M.get_name (| globals, "header" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "cache" , + M.call (| + M.get_name (| globals, "generate_cache" |), + make_list [ + M.get_field (| M.get_name (| globals, "header" |), "number" |) + ], + make_dict [] + |) + |) in + let _ := M.assign (| + make_tuple [ M.get_name (| globals, "mix_digest" |); M.get_name (| globals, "result" |) ], + M.call (| + M.get_name (| globals, "hashimoto_light" |), + make_list [ + M.get_name (| globals, "header_hash" |); + M.get_field (| M.get_name (| globals, "header" |), "nonce" |); + M.get_name (| globals, "cache" |); + M.call (| + M.get_name (| globals, "dataset_size" |), + make_list [ + M.get_field (| M.get_name (| globals, "header" |), "number" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + Compare.eq (| + M.get_name (| globals, "mix_digest" |), + M.get_field (| M.get_name (| globals, "header" |), "mix_digest" |) + |); + M.get_name (| globals, "InvalidBlock" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + Compare.lt_e (| + M.call (| + M.get_field (| M.get_name (| globals, "Uint" |), "from_be_bytes" |), + make_list [ + M.get_name (| globals, "result" |) + ], + make_dict [] + |), + BinOp.floor_div (| + M.get_name (| globals, "U256_CEIL_VALUE" |), + M.get_field (| M.get_name (| globals, "header" |), "difficulty" |) + |) + |); + M.get_name (| globals, "InvalidBlock" |) + ], + make_dict [] + |) in + M.pure Constant.None_)). + +Definition check_transaction : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "tx"; "gas_available" ] |) in + let _ := Constant.str " + Check if the transaction is includable in the block. + + Parameters + ---------- + tx : + The transaction. + gas_available : + The gas remaining in the block. + + Returns + ------- + sender_address : + The sender of the transaction. + + Raises + ------ + InvalidBlock : + If the transaction is not includable. + " in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + Compare.lt_e (| + M.get_field (| M.get_name (| globals, "tx" |), "gas" |), + M.get_name (| globals, "gas_available" |) + |); + M.get_name (| globals, "InvalidBlock" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "sender_address" , + M.call (| + M.get_name (| globals, "recover_sender" |), + make_list [ + M.get_name (| globals, "tx" |) + ], + make_dict [] + |) + |) in + let _ := M.return_ (| + M.get_name (| globals, "sender_address" |) + |) in + M.pure Constant.None_)). + +Definition make_receipt : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "tx"; "post_state"; "cumulative_gas_used"; "logs" ] |) in + let _ := Constant.str " + Make the receipt for a transaction that was executed. + + Parameters + ---------- + tx : + The executed transaction. + post_state : + The state root immediately after this transaction. + cumulative_gas_used : + The total gas used so far in the block after the transaction was + executed. + logs : + The logs produced by the transaction. + + Returns + ------- + receipt : + The receipt for the transaction. + " in + let _ := M.assign_local (| + "receipt" , + M.call (| + M.get_name (| globals, "Receipt" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.return_ (| + M.get_name (| globals, "receipt" |) + |) in + M.pure Constant.None_)). + +Definition ApplyBodyOutput : Value.t := + builtins.make_klass + [] + [ + + ] + [ + + ]. + +Definition apply_body : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "state"; "block_hashes"; "coinbase"; "block_number"; "block_gas_limit"; "block_time"; "block_difficulty"; "transactions"; "ommers" ] |) in + let _ := Constant.str " + Executes a block. + + Many of the contents of a block are stored in data structures called + tries. There is a transactions trie which is similar to a ledger of the + transactions stored in the current block. There is also a receipts trie + which stores the results of executing a transaction, like the post state + and gas used. This function creates and executes the block that is to be + added to the chain. + + Parameters + ---------- + state : + Current account state. + block_hashes : + List of hashes of the previous 256 blocks in the order of + increasing block number. + coinbase : + Address of account which receives block reward and transaction fees. + block_number : + Position of the block within the chain. + block_gas_limit : + Initial amount of gas available for execution in this block. + block_time : + Time the block was produced, measured in seconds since the epoch. + block_difficulty : + Difficulty of the block. + transactions : + Transactions included in the block. + ommers : + Headers of ancestor blocks which are not direct parents (formerly + uncles.) + + Returns + ------- + apply_body_output : `ApplyBodyOutput` + Output of applying the block body to the state. + " in + let _ := M.assign_local (| + "gas_available" , + M.get_name (| globals, "block_gas_limit" |) + |) in +(* At stmt: unsupported node type: AnnAssign *) +(* At stmt: unsupported node type: AnnAssign *) +(* At stmt: unsupported node type: AnnAssign *) + let _ := + M.for_ (| + make_tuple [ M.get_name (| globals, "i" |); M.get_name (| globals, "tx" |) ], + M.call (| + M.get_name (| globals, "enumerate" |), + make_list [ + M.get_name (| globals, "transactions" |) + ], + make_dict [] + |), + ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, "trie_set" |), + make_list [ + M.get_name (| globals, "transactions_trie" |); + M.call (| + M.get_field (| M.get_name (| globals, "rlp" |), "encode" |), + make_list [ + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.get_name (| globals, "i" |) + ], + make_dict [] + |) + ], + make_dict [] + |); + M.get_name (| globals, "tx" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "sender_address" , + M.call (| + M.get_name (| globals, "check_transaction" |), + make_list [ + M.get_name (| globals, "tx" |); + M.get_name (| globals, "gas_available" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "env" , + M.call (| + M.get_field (| M.get_name (| globals, "vm" |), "Environment" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.assign (| + make_tuple [ M.get_name (| globals, "gas_used" |); M.get_name (| globals, "logs" |) ], + M.call (| + M.get_name (| globals, "process_transaction" |), + make_list [ + M.get_name (| globals, "env" |); + M.get_name (| globals, "tx" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_op_local (| + BinOp.sub, + "gas_available", + M.get_name (| globals, "gas_used" |) + |) in + let _ := M.assign_local (| + "receipt" , + M.call (| + M.get_name (| globals, "make_receipt" |), + make_list [ + M.get_name (| globals, "tx" |); + M.call (| + M.get_name (| globals, "state_root" |), + make_list [ + M.get_name (| globals, "state" |) + ], + make_dict [] + |); + BinOp.sub (| + M.get_name (| globals, "block_gas_limit" |), + M.get_name (| globals, "gas_available" |) + |); + M.get_name (| globals, "logs" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "trie_set" |), + make_list [ + M.get_name (| globals, "receipts_trie" |); + M.call (| + M.get_field (| M.get_name (| globals, "rlp" |), "encode" |), + make_list [ + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.get_name (| globals, "i" |) + ], + make_dict [] + |) + ], + make_dict [] + |); + M.get_name (| globals, "receipt" |) + ], + make_dict [] + |) in + let _ := M.assign_op_local (| + BinOp.add, + "block_logs", + M.get_name (| globals, "logs" |) + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := M.call (| + M.get_name (| globals, "pay_rewards" |), + make_list [ + M.get_name (| globals, "state" |); + M.get_name (| globals, "block_number" |); + M.get_name (| globals, "coinbase" |); + M.get_name (| globals, "ommers" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "block_gas_used" , + BinOp.sub (| + M.get_name (| globals, "block_gas_limit" |), + M.get_name (| globals, "gas_available" |) + |) + |) in + let _ := M.assign_local (| + "block_logs_bloom" , + M.call (| + M.get_name (| globals, "logs_bloom" |), + make_list [ + M.get_name (| globals, "block_logs" |) + ], + make_dict [] + |) + |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, "ApplyBodyOutput" |), + make_list [ + M.get_name (| globals, "block_gas_used" |); + M.call (| + M.get_name (| globals, "root" |), + make_list [ + M.get_name (| globals, "transactions_trie" |) + ], + make_dict [] + |); + M.call (| + M.get_name (| globals, "root" |), + make_list [ + M.get_name (| globals, "receipts_trie" |) + ], + make_dict [] + |); + M.get_name (| globals, "block_logs_bloom" |); + M.call (| + M.get_name (| globals, "state_root" |), + make_list [ + M.get_name (| globals, "state" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Definition validate_ommers : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "ommers"; "block_header"; "chain" ] |) in + let _ := Constant.str " + Validates the ommers mentioned in the block. + + An ommer block is a block that wasn't canonically added to the + blockchain because it wasn't validated as fast as the canonical block + but was mined at the same time. + + To be considered valid, the ommers must adhere to the rules defined in + the Ethereum protocol. The maximum amount of ommers is 2 per block and + there cannot be duplicate ommers in a block. Many of the other ommer + constraints are listed in the in-line comments of this function. + + Parameters + ---------- + ommers : + List of ommers mentioned in the current block. + block_header: + The header of current block. + chain : + History and current state. + " in + let _ := M.assign_local (| + "block_hash" , + M.call (| + M.get_field (| M.get_name (| globals, "rlp" |), "rlp_hash" |), + make_list [ + M.get_name (| globals, "block_header" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + Compare.eq (| + M.call (| + M.get_field (| M.get_name (| globals, "rlp" |), "rlp_hash" |), + make_list [ + M.get_name (| globals, "ommers" |) + ], + make_dict [] + |), + M.get_field (| M.get_name (| globals, "block_header" |), "ommers_hash" |) + |); + M.get_name (| globals, "InvalidBlock" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_name (| globals, "ommers" |) + ], + make_dict [] + |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + Constant.None_ + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + M.for_ (| + M.get_name (| globals, "ommer" |), + M.get_name (| globals, "ommers" |), + ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + BoolOp.and (| + Compare.lt_e (| + Constant.int 1, + M.get_field (| M.get_name (| globals, "ommer" |), "number" |) + |), + ltac:(M.monadic ( + Compare.lt (| + M.get_field (| M.get_name (| globals, "ommer" |), "number" |), + M.get_field (| M.get_name (| globals, "block_header" |), "number" |) + |) + )) + |); + M.get_name (| globals, "InvalidBlock" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "ommer_parent_header" , + M.get_field (| M.get_subscript (| + M.get_field (| M.get_name (| globals, "chain" |), "blocks" |), + BinOp.sub (| + UnOp.sub (| BinOp.sub (| + M.get_field (| M.get_name (| globals, "block_header" |), "number" |), + M.get_field (| M.get_name (| globals, "ommer" |), "number" |) + |) |), + Constant.int 1 + |) + |), "header" |) + |) in + let _ := M.call (| + M.get_name (| globals, "validate_header" |), + make_list [ + M.get_name (| globals, "ommer" |); + M.get_name (| globals, "ommer_parent_header" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + Compare.lt_e (| + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_name (| globals, "ommers" |) + ], + make_dict [] + |), + Constant.int 2 + |); + M.get_name (| globals, "InvalidBlock" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "ommers_hashes" , + Constant.str "(* At expr: unsupported node type: ListComp *)" + |) in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + Compare.eq (| + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_name (| globals, "ommers_hashes" |) + ], + make_dict [] + |), + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.call (| + M.get_name (| globals, "set" |), + make_list [ + M.get_name (| globals, "ommers_hashes" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |); + M.get_name (| globals, "InvalidBlock" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "recent_canonical_blocks" , + M.slice (| + M.get_field (| M.get_name (| globals, "chain" |), "blocks" |), + UnOp.sub (| BinOp.add (| + M.get_name (| globals, "MAX_OMMER_DEPTH" |), + Constant.int 1 + |) |), + Constant.None_, + Constant.None_ + |) + |) in + let _ := M.assign_local (| + "recent_canonical_block_hashes" , + Constant.str "(* At expr: unsupported node type: SetComp *)" + |) in +(* At stmt: unsupported node type: AnnAssign *) + let _ := + M.for_ (| + M.get_name (| globals, "block" |), + M.get_name (| globals, "recent_canonical_blocks" |), + ltac:(M.monadic ( + let _ := M.assign_local (| + "recent_ommers_hashes" , + M.call (| + M.get_field (| M.get_name (| globals, "recent_ommers_hashes" |), "union" |), + make_list [ + Constant.str "(* At expr: unsupported node type: SetComp *)" + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := + M.for_ (| + make_tuple [ M.get_name (| globals, "ommer_index" |); M.get_name (| globals, "ommer" |) ], + M.call (| + M.get_name (| globals, "enumerate" |), + make_list [ + M.get_name (| globals, "ommers" |) + ], + make_dict [] + |), + ltac:(M.monadic ( + let _ := M.assign_local (| + "ommer_hash" , + M.get_subscript (| + M.get_name (| globals, "ommers_hashes" |), + M.get_name (| globals, "ommer_index" |) + |) + |) in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + Compare.not_eq (| + M.get_name (| globals, "ommer_hash" |), + M.get_name (| globals, "block_hash" |) + |); + M.get_name (| globals, "InvalidBlock" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + Compare.not_in (| + M.get_name (| globals, "ommer_hash" |), + M.get_name (| globals, "recent_canonical_block_hashes" |) + |); + M.get_name (| globals, "InvalidBlock" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + Compare.not_in (| + M.get_name (| globals, "ommer_hash" |), + M.get_name (| globals, "recent_ommers_hashes" |) + |); + M.get_name (| globals, "InvalidBlock" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "ommer_age" , + BinOp.sub (| + M.get_field (| M.get_name (| globals, "block_header" |), "number" |), + M.get_field (| M.get_name (| globals, "ommer" |), "number" |) + |) + |) in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + BoolOp.and (| + Compare.lt_e (| + Constant.int 1, + M.get_name (| globals, "ommer_age" |) + |), + ltac:(M.monadic ( + Compare.lt_e (| + M.get_name (| globals, "ommer_age" |), + M.get_name (| globals, "MAX_OMMER_DEPTH" |) + |) + )) + |); + M.get_name (| globals, "InvalidBlock" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + Compare.in_ (| + M.get_field (| M.get_name (| globals, "ommer" |), "parent_hash" |), + M.get_name (| globals, "recent_canonical_block_hashes" |) + |); + M.get_name (| globals, "InvalidBlock" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + Compare.not_eq (| + M.get_field (| M.get_name (| globals, "ommer" |), "parent_hash" |), + M.get_field (| M.get_name (| globals, "block_header" |), "parent_hash" |) + |); + M.get_name (| globals, "InvalidBlock" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + M.pure Constant.None_)). + +Definition pay_rewards : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "state"; "block_number"; "coinbase"; "ommers" ] |) in + let _ := Constant.str " + Pay rewards to the block miner as well as the ommers miners. + + The miner of the canonical block is rewarded with the predetermined + block reward, ``BLOCK_REWARD``, plus a variable award based off of the + number of ommer blocks that were mined around the same time, and included + in the canonical block's header. An ommer block is a block that wasn't + added to the canonical blockchain because it wasn't validated as fast as + the accepted block but was mined at the same time. Although not all blocks + that are mined are added to the canonical chain, miners are still paid a + reward for their efforts. This reward is called an ommer reward and is + calculated based on the number associated with the ommer block that they + mined. + + Parameters + ---------- + state : + Current account state. + block_number : + Position of the block within the chain. + coinbase : + Address of account which receives block reward and transaction fees. + ommers : + List of ommers mentioned in the current block. + " in + let _ := M.assign_local (| + "miner_reward" , + BinOp.add (| + M.get_name (| globals, "BLOCK_REWARD" |), + BinOp.mult (| + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_name (| globals, "ommers" |) + ], + make_dict [] + |), + BinOp.floor_div (| + M.get_name (| globals, "BLOCK_REWARD" |), + Constant.int 32 + |) + |) + |) + |) in + let _ := M.call (| + M.get_name (| globals, "create_ether" |), + make_list [ + M.get_name (| globals, "state" |); + M.get_name (| globals, "coinbase" |); + M.get_name (| globals, "miner_reward" |) + ], + make_dict [] + |) in + let _ := + M.for_ (| + M.get_name (| globals, "ommer" |), + M.get_name (| globals, "ommers" |), + ltac:(M.monadic ( + let _ := M.assign_local (| + "ommer_age" , + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + BinOp.sub (| + M.get_name (| globals, "block_number" |), + M.get_field (| M.get_name (| globals, "ommer" |), "number" |) + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "ommer_miner_reward" , + BinOp.floor_div (| + BinOp.mult (| + BinOp.sub (| + Constant.int 8, + M.get_name (| globals, "ommer_age" |) + |), + M.get_name (| globals, "BLOCK_REWARD" |) + |), + Constant.int 8 + |) + |) in + let _ := M.call (| + M.get_name (| globals, "create_ether" |), + make_list [ + M.get_name (| globals, "state" |); + M.get_field (| M.get_name (| globals, "ommer" |), "coinbase" |); + M.get_name (| globals, "ommer_miner_reward" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + M.pure Constant.None_)). + +Definition process_transaction : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "env"; "tx" ] |) in + let _ := Constant.str " + Execute a transaction against the provided environment. + + This function processes the actions needed to execute a transaction. + It decrements the sender's account after calculating the gas fee and + refunds them the proper amount after execution. Calling contracts, + deploying code, and incrementing nonces are all examples of actions that + happen within this function or from a call made within this function. + + Accounts that are marked for deletion are processed and destroyed after + execution. + + Parameters + ---------- + env : + Environment for the Ethereum Virtual Machine. + tx : + Transaction to execute. + + Returns + ------- + gas_left : `ethereum.base_types.U256` + Remaining gas after execution. + logs : `Tuple[ethereum.blocks.Log, ...]` + Logs generated during execution. + " in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + M.call (| + M.get_name (| globals, "validate_transaction" |), + make_list [ + M.get_name (| globals, "tx" |) + ], + make_dict [] + |); + M.get_name (| globals, "InvalidBlock" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "sender" , + M.get_field (| M.get_name (| globals, "env" |), "origin" |) + |) in + let _ := M.assign_local (| + "sender_account" , + M.call (| + M.get_name (| globals, "get_account" |), + make_list [ + M.get_field (| M.get_name (| globals, "env" |), "state" |); + M.get_name (| globals, "sender" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "gas_fee" , + BinOp.mult (| + M.get_field (| M.get_name (| globals, "tx" |), "gas" |), + M.get_field (| M.get_name (| globals, "tx" |), "gas_price" |) + |) + |) in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + Compare.eq (| + M.get_field (| M.get_name (| globals, "sender_account" |), "nonce" |), + M.get_field (| M.get_name (| globals, "tx" |), "nonce" |) + |); + M.get_name (| globals, "InvalidBlock" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + Compare.gt_e (| + M.get_field (| M.get_name (| globals, "sender_account" |), "balance" |), + BinOp.add (| + M.get_name (| globals, "gas_fee" |), + M.get_field (| M.get_name (| globals, "tx" |), "value" |) + |) + |); + M.get_name (| globals, "InvalidBlock" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + Compare.eq (| + M.get_field (| M.get_name (| globals, "sender_account" |), "code" |), + M.call (| + M.get_name (| globals, "bytearray" |), + make_list [], + make_dict [] + |) + |); + M.get_name (| globals, "InvalidBlock" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "gas" , + BinOp.sub (| + M.get_field (| M.get_name (| globals, "tx" |), "gas" |), + M.call (| + M.get_name (| globals, "calculate_intrinsic_cost" |), + make_list [ + M.get_name (| globals, "tx" |) + ], + make_dict [] + |) + |) + |) in + let _ := M.call (| + M.get_name (| globals, "increment_nonce" |), + make_list [ + M.get_field (| M.get_name (| globals, "env" |), "state" |); + M.get_name (| globals, "sender" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "sender_balance_after_gas_fee" , + BinOp.sub (| + M.get_field (| M.get_name (| globals, "sender_account" |), "balance" |), + M.get_name (| globals, "gas_fee" |) + |) + |) in + let _ := M.call (| + M.get_name (| globals, "set_account_balance" |), + make_list [ + M.get_field (| M.get_name (| globals, "env" |), "state" |); + M.get_name (| globals, "sender" |); + M.get_name (| globals, "sender_balance_after_gas_fee" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "message" , + M.call (| + M.get_name (| globals, "prepare_message" |), + make_list [ + M.get_name (| globals, "sender" |); + M.get_field (| M.get_name (| globals, "tx" |), "to" |); + M.get_field (| M.get_name (| globals, "tx" |), "value" |); + M.get_field (| M.get_name (| globals, "tx" |), "data" |); + M.get_name (| globals, "gas" |); + M.get_name (| globals, "env" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "output" , + M.call (| + M.get_name (| globals, "process_message_call" |), + make_list [ + M.get_name (| globals, "message" |); + M.get_name (| globals, "env" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "gas_used" , + BinOp.sub (| + M.get_field (| M.get_name (| globals, "tx" |), "gas" |), + M.get_field (| M.get_name (| globals, "output" |), "gas_left" |) + |) + |) in + let _ := M.assign_local (| + "gas_refund" , + M.call (| + M.get_name (| globals, "min" |), + make_list [ + BinOp.floor_div (| + M.get_name (| globals, "gas_used" |), + Constant.int 2 + |); + M.get_field (| M.get_name (| globals, "output" |), "refund_counter" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "gas_refund_amount" , + BinOp.mult (| + BinOp.add (| + M.get_field (| M.get_name (| globals, "output" |), "gas_left" |), + M.get_name (| globals, "gas_refund" |) + |), + M.get_field (| M.get_name (| globals, "tx" |), "gas_price" |) + |) + |) in + let _ := M.assign_local (| + "transaction_fee" , + BinOp.mult (| + BinOp.sub (| + BinOp.sub (| + M.get_field (| M.get_name (| globals, "tx" |), "gas" |), + M.get_field (| M.get_name (| globals, "output" |), "gas_left" |) + |), + M.get_name (| globals, "gas_refund" |) + |), + M.get_field (| M.get_name (| globals, "tx" |), "gas_price" |) + |) + |) in + let _ := M.assign_local (| + "total_gas_used" , + BinOp.sub (| + M.get_name (| globals, "gas_used" |), + M.get_name (| globals, "gas_refund" |) + |) + |) in + let _ := M.assign_local (| + "sender_balance_after_refund" , + BinOp.add (| + M.get_field (| M.call (| + M.get_name (| globals, "get_account" |), + make_list [ + M.get_field (| M.get_name (| globals, "env" |), "state" |); + M.get_name (| globals, "sender" |) + ], + make_dict [] + |), "balance" |), + M.get_name (| globals, "gas_refund_amount" |) + |) + |) in + let _ := M.call (| + M.get_name (| globals, "set_account_balance" |), + make_list [ + M.get_field (| M.get_name (| globals, "env" |), "state" |); + M.get_name (| globals, "sender" |); + M.get_name (| globals, "sender_balance_after_refund" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "coinbase_balance_after_mining_fee" , + BinOp.add (| + M.get_field (| M.call (| + M.get_name (| globals, "get_account" |), + make_list [ + M.get_field (| M.get_name (| globals, "env" |), "state" |); + M.get_field (| M.get_name (| globals, "env" |), "coinbase" |) + ], + make_dict [] + |), "balance" |), + M.get_name (| globals, "transaction_fee" |) + |) + |) in + let _ := M.call (| + M.get_name (| globals, "set_account_balance" |), + make_list [ + M.get_field (| M.get_name (| globals, "env" |), "state" |); + M.get_field (| M.get_name (| globals, "env" |), "coinbase" |); + M.get_name (| globals, "coinbase_balance_after_mining_fee" |) + ], + make_dict [] + |) in + let _ := + M.for_ (| + M.get_name (| globals, "address" |), + M.get_field (| M.get_name (| globals, "output" |), "accounts_to_delete" |), + ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, "destroy_account" |), + make_list [ + M.get_field (| M.get_name (| globals, "env" |), "state" |); + M.get_name (| globals, "address" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := M.return_ (| + make_tuple [ M.get_name (| globals, "total_gas_used" |); M.get_field (| M.get_name (| globals, "output" |), "logs" |) ] + |) in + M.pure Constant.None_)). + +Definition validate_transaction : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "tx" ] |) in + let _ := Constant.str " + Verifies a transaction. + + The gas in a transaction gets used to pay for the intrinsic cost of + operations, therefore if there is insufficient gas then it would not + be possible to execute a transaction and it will be declared invalid. + + Additionally, the nonce of a transaction must not equal or exceed the + limit defined in `EIP-2681 `_. + In practice, defining the limit as ``2**64-1`` has no impact because + sending ``2**64-1`` transactions is improbable. It's not strictly + impossible though, ``2**64-1`` transactions is the entire capacity of the + Ethereum blockchain at 2022 gas limits for a little over 22 years. + + Parameters + ---------- + tx : + Transaction to validate. + + Returns + ------- + verified : `bool` + True if the transaction can be executed, or False otherwise. + " in + let _ := M.return_ (| + BoolOp.and (| + Compare.lt_e (| + M.call (| + M.get_name (| globals, "calculate_intrinsic_cost" |), + make_list [ + M.get_name (| globals, "tx" |) + ], + make_dict [] + |), + M.get_field (| M.get_name (| globals, "tx" |), "gas" |) + |), + ltac:(M.monadic ( + Compare.lt (| + M.get_field (| M.get_name (| globals, "tx" |), "nonce" |), + BinOp.sub (| + BinOp.pow (| + Constant.int 2, + Constant.int 64 + |), + Constant.int 1 + |) + |) + )) + |) + |) in + M.pure Constant.None_)). + +Definition calculate_intrinsic_cost : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "tx" ] |) in + let _ := Constant.str " + Calculates the gas that is charged before execution is started. + + The intrinsic cost of the transaction is charged before execution has + begun. Functions/operations in the EVM cost money to execute so this + intrinsic cost is for the operations that need to be paid for as part of + the transaction. Data transfer, for example, is part of this intrinsic + cost. It costs ether to send data over the wire and that ether is + accounted for in the intrinsic cost calculated in this function. This + intrinsic cost must be calculated and paid for before execution in order + for all operations to be implemented. + + Parameters + ---------- + tx : + Transaction to compute the intrinsic cost of. + + Returns + ------- + verified : `ethereum.base_types.Uint` + The intrinsic cost of the transaction. + " in + let _ := M.assign_local (| + "data_cost" , + Constant.int 0 + |) in + let _ := + M.for_ (| + M.get_name (| globals, "byte" |), + M.get_field (| M.get_name (| globals, "tx" |), "data" |), + ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, "byte" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_op_local (| + BinOp.add, + "data_cost", + M.get_name (| globals, "TX_DATA_COST_PER_ZERO" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_op_local (| + BinOp.add, + "data_cost", + M.get_name (| globals, "TX_DATA_COST_PER_NON_ZERO" |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_field (| M.get_name (| globals, "tx" |), "to" |), + M.call (| + M.get_name (| globals, "Bytes0" |), + make_list [ + Constant.bytes "" + ], + make_dict [] + |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "create_cost" , + M.get_name (| globals, "TX_CREATE_COST" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "create_cost" , + Constant.int 0 + |) in + M.pure Constant.None_ + )) |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + BinOp.add (| + BinOp.add (| + M.get_name (| globals, "TX_BASE_COST" |), + M.get_name (| globals, "data_cost" |) + |), + M.get_name (| globals, "create_cost" |) + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Definition recover_sender : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "tx" ] |) in + let _ := Constant.str " + Extracts the sender address from a transaction. + + The v, r, and s values are the three parts that make up the signature + of a transaction. In order to recover the sender of a transaction the two + components needed are the signature (``v``, ``r``, and ``s``) and the + signing hash of the transaction. The sender's public key can be obtained + with these two values and therefore the sender address can be retrieved. + + Parameters + ---------- + tx : + Transaction of interest. + + Returns + ------- + sender : `ethereum.fork_types.Address` + The address of the account that signed the transaction. + " in + let _ := M.assign (| + make_tuple [ M.get_name (| globals, "v" |); M.get_name (| globals, "r" |); M.get_name (| globals, "s" |) ], + make_tuple [ M.get_field (| M.get_name (| globals, "tx" |), "v" |); M.get_field (| M.get_name (| globals, "tx" |), "r" |); M.get_field (| M.get_name (| globals, "tx" |), "s" |) ] + |) in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + BoolOp.or (| + Compare.eq (| + M.get_name (| globals, "v" |), + Constant.int 27 + |), + ltac:(M.monadic ( + Compare.eq (| + M.get_name (| globals, "v" |), + Constant.int 28 + |) + )) + |); + M.get_name (| globals, "InvalidBlock" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + BoolOp.and (| + Compare.lt (| + Constant.int 0, + M.get_name (| globals, "r" |) + |), + ltac:(M.monadic ( + Compare.lt (| + M.get_name (| globals, "r" |), + M.get_name (| globals, "SECP256K1N" |) + |) + )) + |); + M.get_name (| globals, "InvalidBlock" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + BoolOp.and (| + Compare.lt (| + Constant.int 0, + M.get_name (| globals, "s" |) + |), + ltac:(M.monadic ( + Compare.lt_e (| + M.get_name (| globals, "s" |), + BinOp.floor_div (| + M.get_name (| globals, "SECP256K1N" |), + Constant.int 2 + |) + |) + )) + |); + M.get_name (| globals, "InvalidBlock" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "public_key" , + M.call (| + M.get_name (| globals, "secp256k1_recover" |), + make_list [ + M.get_name (| globals, "r" |); + M.get_name (| globals, "s" |); + BinOp.sub (| + M.get_name (| globals, "v" |), + Constant.int 27 + |); + M.call (| + M.get_name (| globals, "signing_hash" |), + make_list [ + M.get_name (| globals, "tx" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, "Address" |), + make_list [ + M.slice (| + M.call (| + M.get_name (| globals, "keccak256" |), + make_list [ + M.get_name (| globals, "public_key" |) + ], + make_dict [] + |), + Constant.int 12, + Constant.int 32, + Constant.None_ + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Definition signing_hash : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "tx" ] |) in + let _ := Constant.str " + Compute the hash of a transaction used in the signature. + + The values that are used to compute the signing hash set the rules for a + transaction. For example, signing over the gas sets a limit for the + amount of money that is allowed to be pulled out of the sender's account. + + Parameters + ---------- + tx : + Transaction of interest. + + Returns + ------- + hash : `ethereum.crypto.hash.Hash32` + Hash of the transaction. + " in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, "keccak256" |), + make_list [ + M.call (| + M.get_field (| M.get_name (| globals, "rlp" |), "encode" |), + make_list [ + make_tuple [ M.get_field (| M.get_name (| globals, "tx" |), "nonce" |); M.get_field (| M.get_name (| globals, "tx" |), "gas_price" |); M.get_field (| M.get_name (| globals, "tx" |), "gas" |); M.get_field (| M.get_name (| globals, "tx" |), "to" |); M.get_field (| M.get_name (| globals, "tx" |), "value" |); M.get_field (| M.get_name (| globals, "tx" |), "data" |) ] + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Definition compute_header_hash : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "header" ] |) in + let _ := Constant.str " + Computes the hash of a block header. + + The header hash of a block is the canonical hash that is used to refer + to a specific block and completely distinguishes a block from another. + + ``keccak256`` is a function that produces a 256 bit hash of any input. + It also takes in any number of bytes as an input and produces a single + hash for them. A hash is a completely unique output for a single input. + So an input corresponds to one unique hash that can be used to identify + the input exactly. + + Prior to using the ``keccak256`` hash function, the header must be + encoded using the Recursive-Length Prefix. See :ref:`rlp`. + RLP encoding the header converts it into a space-efficient format that + allows for easy transfer of data between nodes. The purpose of RLP is to + encode arbitrarily nested arrays of binary data, and RLP is the primary + encoding method used to serialize objects in Ethereum's execution layer. + The only purpose of RLP is to encode structure; encoding specific data + types (e.g. strings, floats) is left up to higher-order protocols. + + Parameters + ---------- + header : + Header of interest. + + Returns + ------- + hash : `ethereum.crypto.hash.Hash32` + Hash of the header. + " in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, "keccak256" |), + make_list [ + M.call (| + M.get_field (| M.get_name (| globals, "rlp" |), "encode" |), + make_list [ + M.get_name (| globals, "header" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Definition check_gas_limit : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "gas_limit"; "parent_gas_limit" ] |) in + let _ := Constant.str " + Validates the gas limit for a block. + + The bounds of the gas limit, ``max_adjustment_delta``, is set as the + quotient of the parent block's gas limit and the + ``GAS_LIMIT_ADJUSTMENT_FACTOR``. Therefore, if the gas limit that is + passed through as a parameter is greater than or equal to the *sum* of + the parent's gas and the adjustment delta then the limit for gas is too + high and fails this function's check. Similarly, if the limit is less + than or equal to the *difference* of the parent's gas and the adjustment + delta *or* the predefined ``GAS_LIMIT_MINIMUM`` then this function's + check fails because the gas limit doesn't allow for a sufficient or + reasonable amount of gas to be used on a block. + + Parameters + ---------- + gas_limit : + Gas limit to validate. + + parent_gas_limit : + Gas limit of the parent block. + + Returns + ------- + check : `bool` + True if gas limit constraints are satisfied, False otherwise. + " in + let _ := M.assign_local (| + "max_adjustment_delta" , + BinOp.floor_div (| + M.get_name (| globals, "parent_gas_limit" |), + M.get_name (| globals, "GAS_LIMIT_ADJUSTMENT_FACTOR" |) + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.gt_e (| + M.get_name (| globals, "gas_limit" |), + BinOp.add (| + M.get_name (| globals, "parent_gas_limit" |), + M.get_name (| globals, "max_adjustment_delta" |) + |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + Constant.bool false + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + Compare.lt_e (| + M.get_name (| globals, "gas_limit" |), + BinOp.sub (| + M.get_name (| globals, "parent_gas_limit" |), + M.get_name (| globals, "max_adjustment_delta" |) + |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + Constant.bool false + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + Compare.lt (| + M.get_name (| globals, "gas_limit" |), + M.get_name (| globals, "GAS_LIMIT_MINIMUM" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + Constant.bool false + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.return_ (| + Constant.bool true + |) in + M.pure Constant.None_)). + +Definition calculate_block_difficulty : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "block_number"; "block_timestamp"; "parent_timestamp"; "parent_difficulty" ] |) in + let _ := Constant.str " + Computes difficulty of a block using its header and parent header. + + The difficulty is determined by the time the block was created after its + parent. The ``offset`` is calculated using the parent block's difficulty, + ``parent_difficulty``, and the timestamp between blocks. This offset is + then added to the parent difficulty and is stored as the ``difficulty`` + variable. If the time between the block and its parent is too short, the + offset will result in a positive number thus making the sum of + ``parent_difficulty`` and ``offset`` to be a greater value in order to + avoid mass forking. But, if the time is long enough, then the offset + results in a negative value making the block less difficult than + its parent. + + The base standard for a block's difficulty is the predefined value + set for the genesis block since it has no parent. So, a block + can't be less difficult than the genesis block, therefore each block's + difficulty is set to the maximum value between the calculated + difficulty and the ``GENESIS_DIFFICULTY``. + + Parameters + ---------- + block_number : + Block number of the block. + block_timestamp : + Timestamp of the block. + parent_timestamp : + Timestamp of the parent block. + parent_difficulty : + difficulty of the parent block. + + Returns + ------- + difficulty : `ethereum.base_types.Uint` + Computed difficulty for a block. + " in + let _ := M.assign_local (| + "offset" , + BinOp.mult (| + BinOp.floor_div (| + M.call (| + M.get_name (| globals, "int" |), + make_list [ + M.get_name (| globals, "parent_difficulty" |) + ], + make_dict [] + |), + Constant.int 2048 + |), + M.call (| + M.get_name (| globals, "max" |), + make_list [ + BinOp.sub (| + Constant.int 1, + BinOp.floor_div (| + M.call (| + M.get_name (| globals, "int" |), + make_list [ + BinOp.sub (| + M.get_name (| globals, "block_timestamp" |), + M.get_name (| globals, "parent_timestamp" |) + |) + ], + make_dict [] + |), + Constant.int 10 + |) + |); + UnOp.sub (| Constant.int 99 |) + ], + make_dict [] + |) + |) + |) in + let _ := M.assign_local (| + "difficulty" , + BinOp.add (| + M.call (| + M.get_name (| globals, "int" |), + make_list [ + M.get_name (| globals, "parent_difficulty" |) + ], + make_dict [] + |), + M.get_name (| globals, "offset" |) + |) + |) in + let _ := M.assign_local (| + "num_bomb_periods" , + BinOp.sub (| + BinOp.floor_div (| + M.call (| + M.get_name (| globals, "int" |), + make_list [ + M.get_name (| globals, "block_number" |) + ], + make_dict [] + |), + Constant.int 100000 + |), + Constant.int 2 + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.gt_e (| + M.get_name (| globals, "num_bomb_periods" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_op_local (| + BinOp.add, + "difficulty", + BinOp.pow (| + Constant.int 2, + M.get_name (| globals, "num_bomb_periods" |) + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, "max" |), + make_list [ + M.get_name (| globals, "difficulty" |); + M.get_name (| globals, "MINIMUM_DIFFICULTY" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). diff --git a/CoqOfPython/ethereum/homestead/fork_types.v b/CoqOfPython/ethereum/homestead/fork_types.v new file mode 100644 index 0000000..b6ac107 --- /dev/null +++ b/CoqOfPython/ethereum/homestead/fork_types.v @@ -0,0 +1,98 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.homestead.fork_types". + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Types +^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Types re-used throughout the specification, which are specific to Ethereum. +". + +Axiom dataclasses_imports_dataclass : + IsImported globals "dataclasses" "dataclass". + +Axiom ethereum_imports_rlp : + IsImported globals "ethereum" "rlp". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_Bytes : + IsImported globals "ethereum.base_types" "Bytes". +Axiom ethereum_base_types_imports_Bytes20 : + IsImported globals "ethereum.base_types" "Bytes20". +Axiom ethereum_base_types_imports_Bytes256 : + IsImported globals "ethereum.base_types" "Bytes256". +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". +Axiom ethereum_base_types_imports_slotted_freezable : + IsImported globals "ethereum.base_types" "slotted_freezable". + +Axiom ethereum_crypto_hash_imports_Hash32 : + IsImported globals "ethereum.crypto.hash" "Hash32". +Axiom ethereum_crypto_hash_imports_keccak256 : + IsImported globals "ethereum.crypto.hash" "keccak256". + +Definition Address : Value.t := M.run ltac:(M.monadic ( + M.get_name (| globals, "Bytes20" |) +)). + +Definition Root : Value.t := M.run ltac:(M.monadic ( + M.get_name (| globals, "Hash32" |) +)). + +Definition Bloom : Value.t := M.run ltac:(M.monadic ( + M.get_name (| globals, "Bytes256" |) +)). + +Definition Account : Value.t := + builtins.make_klass + [] + [ + + ] + [ + + ]. + +Definition EMPTY_ACCOUNT : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Account" |), + make_list [], + make_dict [] + |) +)). + +Definition encode_account : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "raw_account_data"; "storage_root" ] |) in + let _ := Constant.str " + Encode `Account` dataclass. + + Storage is not stored in the `Account` dataclass, so `Accounts` cannot be + encoded with providing a storage root. + " in + let _ := M.return_ (| + M.call (| + M.get_field (| M.get_name (| globals, "rlp" |), "encode" |), + make_list [ + make_tuple [ M.get_field (| M.get_name (| globals, "raw_account_data" |), "nonce" |); M.get_field (| M.get_name (| globals, "raw_account_data" |), "balance" |); M.get_name (| globals, "storage_root" |); M.call (| + M.get_name (| globals, "keccak256" |), + make_list [ + M.get_field (| M.get_name (| globals, "raw_account_data" |), "code" |) + ], + make_dict [] + |) ] + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). diff --git a/CoqOfPython/ethereum/homestead/state.v b/CoqOfPython/ethereum/homestead/state.v new file mode 100644 index 0000000..139e07b --- /dev/null +++ b/CoqOfPython/ethereum/homestead/state.v @@ -0,0 +1,906 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.homestead.state". + +Definition expr_1 : Value.t := + Constant.str " +State +^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +The state contains all information that is preserved between transactions. + +It consists of a main account trie and storage tries for each contract. + +There is a distinction between an account that does not exist and +`EMPTY_ACCOUNT`. +". + +Axiom dataclasses_imports_dataclass : + IsImported globals "dataclasses" "dataclass". +Axiom dataclasses_imports_field : + IsImported globals "dataclasses" "field". + +Axiom typing_imports_Callable : + IsImported globals "typing" "Callable". +Axiom typing_imports_Dict : + IsImported globals "typing" "Dict". +Axiom typing_imports_List : + IsImported globals "typing" "List". +Axiom typing_imports_Optional : + IsImported globals "typing" "Optional". +Axiom typing_imports_Tuple : + IsImported globals "typing" "Tuple". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_Bytes : + IsImported globals "ethereum.base_types" "Bytes". +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". +Axiom ethereum_base_types_imports_modify : + IsImported globals "ethereum.base_types" "modify". + +Axiom ethereum_utils_ensure_imports_ensure : + IsImported globals "ethereum.utils.ensure" "ensure". + +Axiom ethereum_homestead_fork_types_imports_EMPTY_ACCOUNT : + IsImported globals "ethereum.homestead.fork_types" "EMPTY_ACCOUNT". +Axiom ethereum_homestead_fork_types_imports_Account : + IsImported globals "ethereum.homestead.fork_types" "Account". +Axiom ethereum_homestead_fork_types_imports_Address : + IsImported globals "ethereum.homestead.fork_types" "Address". +Axiom ethereum_homestead_fork_types_imports_Root : + IsImported globals "ethereum.homestead.fork_types" "Root". + +Axiom ethereum_homestead_trie_imports_EMPTY_TRIE_ROOT : + IsImported globals "ethereum.homestead.trie" "EMPTY_TRIE_ROOT". +Axiom ethereum_homestead_trie_imports_Trie : + IsImported globals "ethereum.homestead.trie" "Trie". +Axiom ethereum_homestead_trie_imports_copy_trie : + IsImported globals "ethereum.homestead.trie" "copy_trie". +Axiom ethereum_homestead_trie_imports_root : + IsImported globals "ethereum.homestead.trie" "root". +Axiom ethereum_homestead_trie_imports_trie_get : + IsImported globals "ethereum.homestead.trie" "trie_get". +Axiom ethereum_homestead_trie_imports_trie_set : + IsImported globals "ethereum.homestead.trie" "trie_set". + +Definition State : Value.t := + builtins.make_klass + [] + [ + + ] + [ + + ]. + +Definition close_state : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "state" ] |) in + let _ := Constant.str " + Free resources held by the state. Used by optimized implementations to + release file descriptors. + " in + let _ := M.delete (| M.get_field (| M.get_name (| globals, "state" |), "_main_trie" |) |) in + let _ := M.delete (| M.get_field (| M.get_name (| globals, "state" |), "_storage_tries" |) |) in + let _ := M.delete (| M.get_field (| M.get_name (| globals, "state" |), "_snapshots" |) |) in + M.pure Constant.None_)). + +Definition begin_transaction : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "state" ] |) in + let _ := Constant.str " + Start a state transaction. + + Transactions are entirely implicit and can be nested. It is not possible to + calculate the state root during a transaction. + + Parameters + ---------- + state : State + The state. + " in + let _ := M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, "state" |), "_snapshots" |), "append" |), + make_list [ + make_tuple [ M.call (| + M.get_name (| globals, "copy_trie" |), + make_list [ + M.get_field (| M.get_name (| globals, "state" |), "_main_trie" |) + ], + make_dict [] + |); Constant.str "(* At expr: unsupported node type: DictComp *)" ] + ], + make_dict [] + |) in + M.pure Constant.None_)). + +Definition commit_transaction : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "state" ] |) in + let _ := Constant.str " + Commit a state transaction. + + Parameters + ---------- + state : State + The state. + " in + let _ := M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, "state" |), "_snapshots" |), "pop" |), + make_list [], + make_dict [] + |) in + M.pure Constant.None_)). + +Definition rollback_transaction : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "state" ] |) in + let _ := Constant.str " + Rollback a state transaction, resetting the state to the point when the + corresponding `start_transaction()` call was made. + + Parameters + ---------- + state : State + The state. + " in + let _ := M.assign (| + make_tuple [ M.get_field (| M.get_name (| globals, "state" |), "_main_trie" |); M.get_field (| M.get_name (| globals, "state" |), "_storage_tries" |) ], + M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, "state" |), "_snapshots" |), "pop" |), + make_list [], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Definition get_account : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "state"; "address" ] |) in + let _ := Constant.str " + Get the `Account` object at an address. Returns `EMPTY_ACCOUNT` if there + is no account at the address. + + Use `get_account_optional()` if you care about the difference between a + non-existent account and `EMPTY_ACCOUNT`. + + Parameters + ---------- + state: `State` + The state + address : `Address` + Address to lookup. + + Returns + ------- + account : `Account` + Account at address. + " in + let _ := M.assign_local (| + "account" , + M.call (| + M.get_name (| globals, "get_account_optional" |), + make_list [ + M.get_name (| globals, "state" |); + M.get_name (| globals, "address" |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, "isinstance" |), + make_list [ + M.get_name (| globals, "account" |); + M.get_name (| globals, "Account" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + M.get_name (| globals, "account" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.return_ (| + M.get_name (| globals, "EMPTY_ACCOUNT" |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_)). + +Definition get_account_optional : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "state"; "address" ] |) in + let _ := Constant.str " + Get the `Account` object at an address. Returns `None` (rather than + `EMPTY_ACCOUNT`) if there is no account at the address. + + Parameters + ---------- + state: `State` + The state + address : `Address` + Address to lookup. + + Returns + ------- + account : `Account` + Account at address. + " in + let _ := M.assign_local (| + "account" , + M.call (| + M.get_name (| globals, "trie_get" |), + make_list [ + M.get_field (| M.get_name (| globals, "state" |), "_main_trie" |); + M.get_name (| globals, "address" |) + ], + make_dict [] + |) + |) in + let _ := M.return_ (| + M.get_name (| globals, "account" |) + |) in + M.pure Constant.None_)). + +Definition set_account : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "state"; "address"; "account" ] |) in + let _ := Constant.str " + Set the `Account` object at an address. Setting to `None` deletes + the account (but not its storage, see `destroy_account()`). + + Parameters + ---------- + state: `State` + The state + address : `Address` + Address to set. + account : `Account` + Account to set at address. + " in + let _ := M.call (| + M.get_name (| globals, "trie_set" |), + make_list [ + M.get_field (| M.get_name (| globals, "state" |), "_main_trie" |); + M.get_name (| globals, "address" |); + M.get_name (| globals, "account" |) + ], + make_dict [] + |) in + M.pure Constant.None_)). + +Definition destroy_account : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "state"; "address" ] |) in + let _ := Constant.str " + Completely remove the account at `address` and all of its storage. + + This function is made available exclusively for the `SELFDESTRUCT` + opcode. It is expected that `SELFDESTRUCT` will be disabled in a future + hardfork and this function will be removed. + + Parameters + ---------- + state: `State` + The state + address : `Address` + Address of account to destroy. + " in + let _ := M.call (| + M.get_name (| globals, "destroy_storage" |), + make_list [ + M.get_name (| globals, "state" |); + M.get_name (| globals, "address" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "set_account" |), + make_list [ + M.get_name (| globals, "state" |); + M.get_name (| globals, "address" |); + Constant.None_ + ], + make_dict [] + |) in + M.pure Constant.None_)). + +Definition destroy_storage : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "state"; "address" ] |) in + let _ := Constant.str " + Completely remove the storage at `address`. + + Parameters + ---------- + state: `State` + The state + address : `Address` + Address of account whose storage is to be deleted. + " in + let _ := + (* if *) + M.if_then_else (| + Compare.in_ (| + M.get_name (| globals, "address" |), + M.get_field (| M.get_name (| globals, "state" |), "_storage_tries" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.delete (| M.get_subscript (| + M.get_field (| M.get_name (| globals, "state" |), "_storage_tries" |), + M.get_name (| globals, "address" |) + |) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + M.pure Constant.None_)). + +Definition get_storage : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "state"; "address"; "key" ] |) in + let _ := Constant.str " + Get a value at a storage key on an account. Returns `U256(0)` if the + storage key has not been set previously. + + Parameters + ---------- + state: `State` + The state + address : `Address` + Address of the account. + key : `Bytes` + Key to lookup. + + Returns + ------- + value : `U256` + Value at the key. + " in + let _ := M.assign_local (| + "trie" , + M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, "state" |), "_storage_tries" |), "get" |), + make_list [ + M.get_name (| globals, "address" |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.is (| + M.get_name (| globals, "trie" |), + Constant.None_ + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "value" , + M.call (| + M.get_name (| globals, "trie_get" |), + make_list [ + M.get_name (| globals, "trie" |); + M.get_name (| globals, "key" |) + ], + make_dict [] + |) + |) in + let _ := M.assert (| M.call (| + M.get_name (| globals, "isinstance" |), + make_list [ + M.get_name (| globals, "value" |); + M.get_name (| globals, "U256" |) + ], + make_dict [] + |) |) in + let _ := M.return_ (| + M.get_name (| globals, "value" |) + |) in + M.pure Constant.None_)). + +Definition set_storage : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "state"; "address"; "key"; "value" ] |) in + let _ := Constant.str " + Set a value at a storage key on an account. Setting to `U256(0)` deletes + the key. + + Parameters + ---------- + state: `State` + The state + address : `Address` + Address of the account. + key : `Bytes` + Key to set. + value : `U256` + Value to set at the key. + " in + let _ := M.assert (| Compare.is_not (| + M.call (| + M.get_name (| globals, "trie_get" |), + make_list [ + M.get_field (| M.get_name (| globals, "state" |), "_main_trie" |); + M.get_name (| globals, "address" |) + ], + make_dict [] + |), + Constant.None_ + |) |) in + let _ := M.assign_local (| + "trie" , + M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, "state" |), "_storage_tries" |), "get" |), + make_list [ + M.get_name (| globals, "address" |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.is (| + M.get_name (| globals, "trie" |), + Constant.None_ + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "trie" , + M.call (| + M.get_name (| globals, "Trie" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.assign (| + M.get_subscript (| + M.get_field (| M.get_name (| globals, "state" |), "_storage_tries" |), + M.get_name (| globals, "address" |) + |), + M.get_name (| globals, "trie" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.call (| + M.get_name (| globals, "trie_set" |), + make_list [ + M.get_name (| globals, "trie" |); + M.get_name (| globals, "key" |); + M.get_name (| globals, "value" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_field (| M.get_name (| globals, "trie" |), "_data" |), + Constant.str "(* At expr: unsupported node type: Dict *)" + |), + (* then *) + ltac:(M.monadic ( + let _ := M.delete (| M.get_subscript (| + M.get_field (| M.get_name (| globals, "state" |), "_storage_tries" |), + M.get_name (| globals, "address" |) + |) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + M.pure Constant.None_)). + +Definition storage_root : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "state"; "address" ] |) in + let _ := Constant.str " + Calculate the storage root of an account. + + Parameters + ---------- + state: + The state + address : + Address of the account. + + Returns + ------- + root : `Root` + Storage root of the account. + " in + let _ := M.assert (| UnOp.not (| M.get_field (| M.get_name (| globals, "state" |), "_snapshots" |) |) |) in + let _ := + (* if *) + M.if_then_else (| + Compare.in_ (| + M.get_name (| globals, "address" |), + M.get_field (| M.get_name (| globals, "state" |), "_storage_tries" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + M.call (| + M.get_name (| globals, "root" |), + make_list [ + M.get_subscript (| + M.get_field (| M.get_name (| globals, "state" |), "_storage_tries" |), + M.get_name (| globals, "address" |) + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.return_ (| + M.get_name (| globals, "EMPTY_TRIE_ROOT" |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_)). + +Definition state_root : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "state" ] |) in + let _ := Constant.str " + Calculate the state root. + + Parameters + ---------- + state: + The current state. + + Returns + ------- + root : `Root` + The state root. + " in + let _ := M.assert (| UnOp.not (| M.get_field (| M.get_name (| globals, "state" |), "_snapshots" |) |) |) in +(* At stmt: unsupported node type: FunctionDef *) + let _ := M.return_ (| + M.call (| + M.get_name (| globals, "root" |), + make_list [ + M.get_field (| M.get_name (| globals, "state" |), "_main_trie" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Definition account_exists : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "state"; "address" ] |) in + let _ := Constant.str " + Checks if an account exists in the state trie + + Parameters + ---------- + state: + The state + address: + Address of the account that needs to be checked. + + Returns + ------- + account_exists : `bool` + True if account exists in the state trie, False otherwise + " in + let _ := M.return_ (| + Compare.is_not (| + M.call (| + M.get_name (| globals, "get_account_optional" |), + make_list [ + M.get_name (| globals, "state" |); + M.get_name (| globals, "address" |) + ], + make_dict [] + |), + Constant.None_ + |) + |) in + M.pure Constant.None_)). + +Definition account_has_code_or_nonce : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "state"; "address" ] |) in + let _ := Constant.str " + Checks if an account has non zero nonce or non empty code + + Parameters + ---------- + state: + The state + address: + Address of the account that needs to be checked. + + Returns + ------- + has_code_or_nonce : `bool` + True if if an account has non zero nonce or non empty code, + False otherwise. + " in + let _ := M.assign_local (| + "account" , + M.call (| + M.get_name (| globals, "get_account" |), + make_list [ + M.get_name (| globals, "state" |); + M.get_name (| globals, "address" |) + ], + make_dict [] + |) + |) in + let _ := M.return_ (| + BoolOp.or (| + Compare.not_eq (| + M.get_field (| M.get_name (| globals, "account" |), "nonce" |), + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + |), + ltac:(M.monadic ( + Compare.not_eq (| + M.get_field (| M.get_name (| globals, "account" |), "code" |), + Constant.bytes "" + |) + )) + |) + |) in + M.pure Constant.None_)). + +Definition modify_state : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "state"; "address"; "f" ] |) in + let _ := Constant.str " + Modify an `Account` in the `State`. + " in + let _ := M.call (| + M.get_name (| globals, "set_account" |), + make_list [ + M.get_name (| globals, "state" |); + M.get_name (| globals, "address" |); + M.call (| + M.get_name (| globals, "modify" |), + make_list [ + M.call (| + M.get_name (| globals, "get_account" |), + make_list [ + M.get_name (| globals, "state" |); + M.get_name (| globals, "address" |) + ], + make_dict [] + |); + M.get_name (| globals, "f" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + M.pure Constant.None_)). + +Definition move_ether : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "state"; "sender_address"; "recipient_address"; "amount" ] |) in + let _ := Constant.str " + Move funds between accounts. + " in +(* At stmt: unsupported node type: FunctionDef *) +(* At stmt: unsupported node type: FunctionDef *) + let _ := M.call (| + M.get_name (| globals, "modify_state" |), + make_list [ + M.get_name (| globals, "state" |); + M.get_name (| globals, "sender_address" |); + M.get_name (| globals, "reduce_sender_balance" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "modify_state" |), + make_list [ + M.get_name (| globals, "state" |); + M.get_name (| globals, "recipient_address" |); + M.get_name (| globals, "increase_recipient_balance" |) + ], + make_dict [] + |) in + M.pure Constant.None_)). + +Definition set_account_balance : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "state"; "address"; "amount" ] |) in + let _ := Constant.str " + Sets the balance of an account. + + Parameters + ---------- + state: + The current state. + + address: + Address of the account whose nonce needs to be incremented. + + amount: + The amount that needs to set in balance. + " in +(* At stmt: unsupported node type: FunctionDef *) + let _ := M.call (| + M.get_name (| globals, "modify_state" |), + make_list [ + M.get_name (| globals, "state" |); + M.get_name (| globals, "address" |); + M.get_name (| globals, "set_balance" |) + ], + make_dict [] + |) in + M.pure Constant.None_)). + +Definition touch_account : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "state"; "address" ] |) in + let _ := Constant.str " + Initializes an account to state. + + Parameters + ---------- + state: + The current state. + + address: + The address of the account that need to initialised. + " in + let _ := + (* if *) + M.if_then_else (| + UnOp.not (| M.call (| + M.get_name (| globals, "account_exists" |), + make_list [ + M.get_name (| globals, "state" |); + M.get_name (| globals, "address" |) + ], + make_dict [] + |) |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, "set_account" |), + make_list [ + M.get_name (| globals, "state" |); + M.get_name (| globals, "address" |); + M.get_name (| globals, "EMPTY_ACCOUNT" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + M.pure Constant.None_)). + +Definition increment_nonce : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "state"; "address" ] |) in + let _ := Constant.str " + Increments the nonce of an account. + + Parameters + ---------- + state: + The current state. + + address: + Address of the account whose nonce needs to be incremented. + " in +(* At stmt: unsupported node type: FunctionDef *) + let _ := M.call (| + M.get_name (| globals, "modify_state" |), + make_list [ + M.get_name (| globals, "state" |); + M.get_name (| globals, "address" |); + M.get_name (| globals, "increase_nonce" |) + ], + make_dict [] + |) in + M.pure Constant.None_)). + +Definition set_code : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "state"; "address"; "code" ] |) in + let _ := Constant.str " + Sets Account code. + + Parameters + ---------- + state: + The current state. + + address: + Address of the account whose code needs to be update. + + code: + The bytecode that needs to be set. + " in +(* At stmt: unsupported node type: FunctionDef *) + let _ := M.call (| + M.get_name (| globals, "modify_state" |), + make_list [ + M.get_name (| globals, "state" |); + M.get_name (| globals, "address" |); + M.get_name (| globals, "write_code" |) + ], + make_dict [] + |) in + M.pure Constant.None_)). + +Definition create_ether : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "state"; "address"; "amount" ] |) in + let _ := Constant.str " + Add newly created ether to an account. + + Parameters + ---------- + state: + The current state. + address: + Address of the account to which ether is added. + amount: + The amount of ether to be added to the account of interest. + " in +(* At stmt: unsupported node type: FunctionDef *) + let _ := M.call (| + M.get_name (| globals, "modify_state" |), + make_list [ + M.get_name (| globals, "state" |); + M.get_name (| globals, "address" |); + M.get_name (| globals, "increase_balance" |) + ], + make_dict [] + |) in + M.pure Constant.None_)). diff --git a/CoqOfPython/ethereum/homestead/transactions.v b/CoqOfPython/ethereum/homestead/transactions.v new file mode 100644 index 0000000..18720ce --- /dev/null +++ b/CoqOfPython/ethereum/homestead/transactions.v @@ -0,0 +1,56 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.homestead.transactions". + +Definition expr_1 : Value.t := + Constant.str " +Transactions are atomic units of work created externally to Ethereum and +submitted to be executed. If Ethereum is viewed as a state machine, +transactions are the events that move between states. +". + +Axiom dataclasses_imports_dataclass : + IsImported globals "dataclasses" "dataclass". + +Axiom typing_imports_Union : + IsImported globals "typing" "Union". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_Bytes : + IsImported globals "ethereum.base_types" "Bytes". +Axiom ethereum_base_types_imports_Bytes0 : + IsImported globals "ethereum.base_types" "Bytes0". +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". +Axiom ethereum_base_types_imports_slotted_freezable : + IsImported globals "ethereum.base_types" "slotted_freezable". + +Axiom ethereum_homestead_fork_types_imports_Address : + IsImported globals "ethereum.homestead.fork_types" "Address". + +Definition TX_BASE_COST : Value.t := M.run ltac:(M.monadic ( + Constant.int 21000 +)). + +Definition TX_DATA_COST_PER_NON_ZERO : Value.t := M.run ltac:(M.monadic ( + Constant.int 68 +)). + +Definition TX_DATA_COST_PER_ZERO : Value.t := M.run ltac:(M.monadic ( + Constant.int 4 +)). + +Definition TX_CREATE_COST : Value.t := M.run ltac:(M.monadic ( + Constant.int 32000 +)). + +Definition Transaction : Value.t := + builtins.make_klass + [] + [ + + ] + [ + + ]. diff --git a/CoqOfPython/ethereum/homestead/trie.v b/CoqOfPython/ethereum/homestead/trie.v new file mode 100644 index 0000000..62f57c9 --- /dev/null +++ b/CoqOfPython/ethereum/homestead/trie.v @@ -0,0 +1,1589 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.homestead.trie". + +Definition expr_1 : Value.t := + Constant.str " +State Trie +^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +The state trie is the structure responsible for storing +`.fork_types.Account` objects. +". + +(* At top_level_stmt: unsupported node type: Import *) + +Axiom dataclasses_imports_dataclass : + IsImported globals "dataclasses" "dataclass". +Axiom dataclasses_imports_field : + IsImported globals "dataclasses" "field". + +Axiom typing_imports_Callable : + IsImported globals "typing" "Callable". +Axiom typing_imports_Dict : + IsImported globals "typing" "Dict". +Axiom typing_imports_Generic : + IsImported globals "typing" "Generic". +Axiom typing_imports_List : + IsImported globals "typing" "List". +Axiom typing_imports_Mapping : + IsImported globals "typing" "Mapping". +Axiom typing_imports_MutableMapping : + IsImported globals "typing" "MutableMapping". +Axiom typing_imports_Optional : + IsImported globals "typing" "Optional". +Axiom typing_imports_Sequence : + IsImported globals "typing" "Sequence". +Axiom typing_imports_TypeVar : + IsImported globals "typing" "TypeVar". +Axiom typing_imports_Union : + IsImported globals "typing" "Union". +Axiom typing_imports_cast : + IsImported globals "typing" "cast". + +Axiom ethereum_crypto_hash_imports_keccak256 : + IsImported globals "ethereum.crypto.hash" "keccak256". + +Axiom ethereum_frontier_imports_trie : + IsImported globals "ethereum.frontier" "trie". + +Axiom ethereum_utils_ensure_imports_ensure : + IsImported globals "ethereum.utils.ensure" "ensure". + +Axiom ethereum_utils_hexadecimal_imports_hex_to_bytes : + IsImported globals "ethereum.utils.hexadecimal" "hex_to_bytes". + +Axiom ethereum_imports_rlp : + IsImported globals "ethereum" "rlp". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_Bytes : + IsImported globals "ethereum.base_types" "Bytes". +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". +Axiom ethereum_base_types_imports_slotted_freezable : + IsImported globals "ethereum.base_types" "slotted_freezable". + +Axiom ethereum_homestead_blocks_imports_Receipt : + IsImported globals "ethereum.homestead.blocks" "Receipt". + +Axiom ethereum_homestead_fork_types_imports_Account : + IsImported globals "ethereum.homestead.fork_types" "Account". +Axiom ethereum_homestead_fork_types_imports_Address : + IsImported globals "ethereum.homestead.fork_types" "Address". +Axiom ethereum_homestead_fork_types_imports_Root : + IsImported globals "ethereum.homestead.fork_types" "Root". +Axiom ethereum_homestead_fork_types_imports_encode_account : + IsImported globals "ethereum.homestead.fork_types" "encode_account". + +Axiom ethereum_homestead_transactions_imports_Transaction : + IsImported globals "ethereum.homestead.transactions" "Transaction". + +Definition EMPTY_TRIE_ROOT : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Root" |), + make_list [ + M.call (| + M.get_name (| globals, "hex_to_bytes" |), + make_list [ + Constant.str "56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421" + ], + make_dict [] + |) + ], + make_dict [] + |) +)). + +Definition Node : Value.t := M.run ltac:(M.monadic ( + M.get_subscript (| + M.get_name (| globals, "Union" |), + make_tuple [ M.get_name (| globals, "Account" |); M.get_name (| globals, "Bytes" |); M.get_name (| globals, "Transaction" |); M.get_name (| globals, "Receipt" |); M.get_name (| globals, "Uint" |); M.get_name (| globals, "U256" |); Constant.None_ ] + |) +)). + +Definition K : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "TypeVar" |), + make_list [ + Constant.str "K" + ], + make_dict [] + |) +)). + +Definition V : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "TypeVar" |), + make_list [ + Constant.str "V"; + M.get_subscript (| + M.get_name (| globals, "Optional" |), + M.get_name (| globals, "Account" |) + |); + M.get_subscript (| + M.get_name (| globals, "Optional" |), + M.get_name (| globals, "Bytes" |) + |); + M.get_name (| globals, "Bytes" |); + M.get_subscript (| + M.get_name (| globals, "Optional" |), + M.get_name (| globals, "Transaction" |) + |); + M.get_subscript (| + M.get_name (| globals, "Optional" |), + M.get_name (| globals, "Receipt" |) + |); + M.get_name (| globals, "Uint" |); + M.get_name (| globals, "U256" |) + ], + make_dict [] + |) +)). + +Definition LeafNode : Value.t := + builtins.make_klass + [] + [ + + ] + [ + + ]. + +Definition ExtensionNode : Value.t := + builtins.make_klass + [] + [ + + ] + [ + + ]. + +Definition BranchNode : Value.t := + builtins.make_klass + [] + [ + + ] + [ + + ]. + +Definition InternalNode : Value.t := M.run ltac:(M.monadic ( + M.get_subscript (| + M.get_name (| globals, "Union" |), + make_tuple [ M.get_name (| globals, "LeafNode" |); M.get_name (| globals, "ExtensionNode" |); M.get_name (| globals, "BranchNode" |) ] + |) +)). + +Definition encode_internal_node : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "node" ] |) in + let _ := Constant.str " + Encodes a Merkle Trie node into its RLP form. The RLP will then be + serialized into a `Bytes` and hashed unless it is less that 32 bytes + when serialized. + + This function also accepts `None`, representing the absence of a node, + which is encoded to `b""""`. + + Parameters + ---------- + node : Optional[InternalNode] + The node to encode. + + Returns + ------- + encoded : `rlp.RLP` + The node encoded as RLP. + " in +(* At stmt: unsupported node type: AnnAssign *) + let _ := + (* if *) + M.if_then_else (| + Compare.is (| + M.get_name (| globals, "node" |), + Constant.None_ + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "unencoded" , + Constant.bytes "" + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, "isinstance" |), + make_list [ + M.get_name (| globals, "node" |); + M.get_name (| globals, "LeafNode" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "unencoded" , + make_tuple [ M.call (| + M.get_name (| globals, "nibble_list_to_compact" |), + make_list [ + M.get_field (| M.get_name (| globals, "node" |), "rest_of_key" |); + Constant.bool true + ], + make_dict [] + |); M.get_field (| M.get_name (| globals, "node" |), "value" |) ] + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, "isinstance" |), + make_list [ + M.get_name (| globals, "node" |); + M.get_name (| globals, "ExtensionNode" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "unencoded" , + make_tuple [ M.call (| + M.get_name (| globals, "nibble_list_to_compact" |), + make_list [ + M.get_field (| M.get_name (| globals, "node" |), "key_segment" |); + Constant.bool false + ], + make_dict [] + |); M.get_field (| M.get_name (| globals, "node" |), "subnode" |) ] + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, "isinstance" |), + make_list [ + M.get_name (| globals, "node" |); + M.get_name (| globals, "BranchNode" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "unencoded" , + BinOp.add (| + M.get_field (| M.get_name (| globals, "node" |), "subnodes" |), + make_list [ + M.get_field (| M.get_name (| globals, "node" |), "value" |) + ] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.raise (| Some (M.call (| + M.get_name (| globals, "AssertionError" |), + make_list [ + Constant.str "(* At expr: unsupported node type: JoinedStr *)" + ], + make_dict [] + |)) |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "encoded" , + M.call (| + M.get_field (| M.get_name (| globals, "rlp" |), "encode" |), + make_list [ + M.get_name (| globals, "unencoded" |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.lt (| + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_name (| globals, "encoded" |) + ], + make_dict [] + |), + Constant.int 32 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + M.get_name (| globals, "unencoded" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.return_ (| + M.call (| + M.get_name (| globals, "keccak256" |), + make_list [ + M.get_name (| globals, "encoded" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_)). + +Definition encode_node : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "node"; "storage_root" ] |) in + let _ := Constant.str " + Encode a Node for storage in the Merkle Trie. + + Currently mostly an unimplemented stub. + " in + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, "isinstance" |), + make_list [ + M.get_name (| globals, "node" |); + M.get_name (| globals, "Account" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assert (| Compare.is_not (| + M.get_name (| globals, "storage_root" |), + Constant.None_ + |) |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, "encode_account" |), + make_list [ + M.get_name (| globals, "node" |); + M.get_name (| globals, "storage_root" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, "isinstance" |), + make_list [ + M.get_name (| globals, "node" |); + make_tuple [ M.get_name (| globals, "Transaction" |); M.get_name (| globals, "Receipt" |); M.get_name (| globals, "U256" |) ] + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + M.call (| + M.get_field (| M.get_name (| globals, "rlp" |), "encode" |), + make_list [ + M.call (| + M.get_name (| globals, "cast" |), + make_list [ + M.get_field (| M.get_name (| globals, "rlp" |), "RLP" |); + M.get_name (| globals, "node" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, "isinstance" |), + make_list [ + M.get_name (| globals, "node" |); + M.get_name (| globals, "Bytes" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + M.get_name (| globals, "node" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.return_ (| + M.call (| + M.get_field (| M.get_name (| globals, "previous_trie" |), "encode_node" |), + make_list [ + M.get_name (| globals, "node" |); + M.get_name (| globals, "storage_root" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_)). + +Definition Trie : Value.t := + builtins.make_klass + [(* At base: unsupported node type: Subscript *)] + [ + + ] + [ + + ]. + +Definition copy_trie : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "trie" ] |) in + let _ := Constant.str " + Create a copy of `trie`. Since only frozen objects may be stored in tries, + the contents are reused. + + Parameters + ---------- + trie: `Trie` + Trie to copy. + + Returns + ------- + new_trie : `Trie[K, V]` + A copy of the trie. + " in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, "Trie" |), + make_list [ + M.get_field (| M.get_name (| globals, "trie" |), "secured" |); + M.get_field (| M.get_name (| globals, "trie" |), "default" |); + M.call (| + M.get_field (| M.get_name (| globals, "copy" |), "copy" |), + make_list [ + M.get_field (| M.get_name (| globals, "trie" |), "_data" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Definition trie_set : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "trie"; "key"; "value" ] |) in + let _ := Constant.str " + Stores an item in a Merkle Trie. + + This method deletes the key if `value == trie.default`, because the Merkle + Trie represents the default value by omitting it from the trie. + + Parameters + ---------- + trie: `Trie` + Trie to store in. + key : `Bytes` + Key to lookup. + value : `V` + Node to insert at `key`. + " in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, "value" |), + M.get_field (| M.get_name (| globals, "trie" |), "default" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + Compare.in_ (| + M.get_name (| globals, "key" |), + M.get_field (| M.get_name (| globals, "trie" |), "_data" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.delete (| M.get_subscript (| + M.get_field (| M.get_name (| globals, "trie" |), "_data" |), + M.get_name (| globals, "key" |) + |) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign (| + M.get_subscript (| + M.get_field (| M.get_name (| globals, "trie" |), "_data" |), + M.get_name (| globals, "key" |) + |), + M.get_name (| globals, "value" |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_)). + +Definition trie_get : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "trie"; "key" ] |) in + let _ := Constant.str " + Gets an item from the Merkle Trie. + + This method returns `trie.default` if the key is missing. + + Parameters + ---------- + trie: + Trie to lookup in. + key : + Key to lookup. + + Returns + ------- + node : `V` + Node at `key` in the trie. + " in + let _ := M.return_ (| + M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, "trie" |), "_data" |), "get" |), + make_list [ + M.get_name (| globals, "key" |); + M.get_field (| M.get_name (| globals, "trie" |), "default" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Definition common_prefix_length : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "a"; "b" ] |) in + let _ := Constant.str " + Find the longest common prefix of two sequences. + " in + let _ := + M.for_ (| + M.get_name (| globals, "i" |), + M.call (| + M.get_name (| globals, "range" |), + make_list [ + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_name (| globals, "a" |) + ], + make_dict [] + |) + ], + make_dict [] + |), + ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + BoolOp.or (| + Compare.gt_e (| + M.get_name (| globals, "i" |), + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_name (| globals, "b" |) + ], + make_dict [] + |) + |), + ltac:(M.monadic ( + Compare.not_eq (| + M.get_subscript (| + M.get_name (| globals, "a" |), + M.get_name (| globals, "i" |) + |), + M.get_subscript (| + M.get_name (| globals, "b" |), + M.get_name (| globals, "i" |) + |) + |) + )) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + M.get_name (| globals, "i" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_name (| globals, "a" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Definition nibble_list_to_compact : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "x"; "is_leaf" ] |) in + let _ := Constant.str " + Compresses nibble-list into a standard byte array with a flag. + + A nibble-list is a list of byte values no greater than `15`. The flag is + encoded in high nibble of the highest byte. The flag nibble can be broken + down into two two-bit flags. + + Highest nibble:: + + +---+---+----------+--------+ + | _ | _ | is_leaf | parity | + +---+---+----------+--------+ + 3 2 1 0 + + + The lowest bit of the nibble encodes the parity of the length of the + remaining nibbles -- `0` when even and `1` when odd. The second lowest bit + is used to distinguish leaf and extension nodes. The other two bits are not + used. + + Parameters + ---------- + x : + Array of nibbles. + is_leaf : + True if this is part of a leaf node, or false if it is an extension + node. + + Returns + ------- + compressed : `bytearray` + Compact byte array. + " in + let _ := M.assign_local (| + "compact" , + M.call (| + M.get_name (| globals, "bytearray" |), + make_list [], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + BinOp.mod_ (| + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_name (| globals, "x" |) + ], + make_dict [] + |), + Constant.int 2 + |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_field (| M.get_name (| globals, "compact" |), "append" |), + make_list [ + BinOp.mult (| + Constant.int 16, + BinOp.mult (| + Constant.int 2, + M.get_name (| globals, "is_leaf" |) + |) + |) + ], + make_dict [] + |) in + let _ := + M.for_ (| + M.get_name (| globals, "i" |), + M.call (| + M.get_name (| globals, "range" |), + make_list [ + Constant.int 0; + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_name (| globals, "x" |) + ], + make_dict [] + |); + Constant.int 2 + ], + make_dict [] + |), + ltac:(M.monadic ( + let _ := M.call (| + M.get_field (| M.get_name (| globals, "compact" |), "append" |), + make_list [ + BinOp.add (| + BinOp.mult (| + Constant.int 16, + M.get_subscript (| + M.get_name (| globals, "x" |), + M.get_name (| globals, "i" |) + |) + |), + M.get_subscript (| + M.get_name (| globals, "x" |), + BinOp.add (| + M.get_name (| globals, "i" |), + Constant.int 1 + |) + |) + |) + ], + make_dict [] + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.call (| + M.get_field (| M.get_name (| globals, "compact" |), "append" |), + make_list [ + BinOp.add (| + BinOp.mult (| + Constant.int 16, + BinOp.add (| + BinOp.mult (| + Constant.int 2, + M.get_name (| globals, "is_leaf" |) + |), + Constant.int 1 + |) + |), + M.get_subscript (| + M.get_name (| globals, "x" |), + Constant.int 0 + |) + |) + ], + make_dict [] + |) in + let _ := + M.for_ (| + M.get_name (| globals, "i" |), + M.call (| + M.get_name (| globals, "range" |), + make_list [ + Constant.int 1; + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_name (| globals, "x" |) + ], + make_dict [] + |); + Constant.int 2 + ], + make_dict [] + |), + ltac:(M.monadic ( + let _ := M.call (| + M.get_field (| M.get_name (| globals, "compact" |), "append" |), + make_list [ + BinOp.add (| + BinOp.mult (| + Constant.int 16, + M.get_subscript (| + M.get_name (| globals, "x" |), + M.get_name (| globals, "i" |) + |) + |), + M.get_subscript (| + M.get_name (| globals, "x" |), + BinOp.add (| + M.get_name (| globals, "i" |), + Constant.int 1 + |) + |) + |) + ], + make_dict [] + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + M.pure Constant.None_ + )) |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, "Bytes" |), + make_list [ + M.get_name (| globals, "compact" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Definition bytes_to_nibble_list : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "bytes_" ] |) in + let _ := Constant.str " + Converts a `Bytes` into to a sequence of nibbles (bytes with value < 16). + + Parameters + ---------- + bytes_: + The `Bytes` to convert. + + Returns + ------- + nibble_list : `Bytes` + The `Bytes` in nibble-list format. + " in + let _ := M.assign_local (| + "nibble_list" , + M.call (| + M.get_name (| globals, "bytearray" |), + make_list [ + BinOp.mult (| + Constant.int 2, + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_name (| globals, "bytes_" |) + ], + make_dict [] + |) + |) + ], + make_dict [] + |) + |) in + let _ := + M.for_ (| + make_tuple [ M.get_name (| globals, "byte_index" |); M.get_name (| globals, "byte" |) ], + M.call (| + M.get_name (| globals, "enumerate" |), + make_list [ + M.get_name (| globals, "bytes_" |) + ], + make_dict [] + |), + ltac:(M.monadic ( + let _ := M.assign (| + M.get_subscript (| + M.get_name (| globals, "nibble_list" |), + BinOp.mult (| + M.get_name (| globals, "byte_index" |), + Constant.int 2 + |) + |), + BinOp.r_shift (| + BinOp.bit_and (| + M.get_name (| globals, "byte" |), + Constant.int 240 + |), + Constant.int 4 + |) + |) in + let _ := M.assign (| + M.get_subscript (| + M.get_name (| globals, "nibble_list" |), + BinOp.add (| + BinOp.mult (| + M.get_name (| globals, "byte_index" |), + Constant.int 2 + |), + Constant.int 1 + |) + |), + BinOp.bit_and (| + M.get_name (| globals, "byte" |), + Constant.int 15 + |) + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, "Bytes" |), + make_list [ + M.get_name (| globals, "nibble_list" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Definition _prepare_trie : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "trie"; "get_storage_root" ] |) in + let _ := Constant.str " + Prepares the trie for root calculation. Removes values that are empty, + hashes the keys (if `secured == True`) and encodes all the nodes. + + Parameters + ---------- + trie : + The `Trie` to prepare. + get_storage_root : + Function to get the storage root of an account. Needed to encode + `Account` objects. + + Returns + ------- + out : `Mapping[ethereum.base_types.Bytes, Node]` + Object with keys mapped to nibble-byte form. + " in +(* At stmt: unsupported node type: AnnAssign *) + let _ := + M.for_ (| + make_tuple [ M.get_name (| globals, "preimage" |); M.get_name (| globals, "value" |) ], + M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, "trie" |), "_data" |), "items" |), + make_list [], + make_dict [] + |), + ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, "isinstance" |), + make_list [ + M.get_name (| globals, "value" |); + M.get_name (| globals, "Account" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assert (| Compare.is_not (| + M.get_name (| globals, "get_storage_root" |), + Constant.None_ + |) |) in + let _ := M.assign_local (| + "address" , + M.call (| + M.get_name (| globals, "Address" |), + make_list [ + M.get_name (| globals, "preimage" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "encoded_value" , + M.call (| + M.get_name (| globals, "encode_node" |), + make_list [ + M.get_name (| globals, "value" |); + M.call (| + M.get_name (| globals, "get_storage_root" |), + make_list [ + M.get_name (| globals, "address" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "encoded_value" , + M.call (| + M.get_name (| globals, "encode_node" |), + make_list [ + M.get_name (| globals, "value" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + )) |) in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + Compare.not_eq (| + M.get_name (| globals, "encoded_value" |), + Constant.bytes "" + |); + M.get_name (| globals, "AssertionError" |) + ], + make_dict [] + |) in +(* At stmt: unsupported node type: AnnAssign *) + let _ := + (* if *) + M.if_then_else (| + M.get_field (| M.get_name (| globals, "trie" |), "secured" |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "key" , + M.call (| + M.get_name (| globals, "keccak256" |), + make_list [ + M.get_name (| globals, "preimage" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "key" , + M.get_name (| globals, "preimage" |) + |) in + M.pure Constant.None_ + )) |) in + let _ := M.assign (| + M.get_subscript (| + M.get_name (| globals, "mapped" |), + M.call (| + M.get_name (| globals, "bytes_to_nibble_list" |), + make_list [ + M.get_name (| globals, "key" |) + ], + make_dict [] + |) + |), + M.get_name (| globals, "encoded_value" |) + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := M.return_ (| + M.get_name (| globals, "mapped" |) + |) in + M.pure Constant.None_)). + +Definition root : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "trie"; "get_storage_root" ] |) in + let _ := Constant.str " + Computes the root of a modified merkle patricia trie (MPT). + + Parameters + ---------- + trie : + `Trie` to get the root of. + get_storage_root : + Function to get the storage root of an account. Needed to encode + `Account` objects. + + + Returns + ------- + root : `.fork_types.Root` + MPT root of the underlying key-value pairs. + " in + let _ := M.assign_local (| + "obj" , + M.call (| + M.get_name (| globals, "_prepare_trie" |), + make_list [ + M.get_name (| globals, "trie" |); + M.get_name (| globals, "get_storage_root" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "root_node" , + M.call (| + M.get_name (| globals, "encode_internal_node" |), + make_list [ + M.call (| + M.get_name (| globals, "patricialize" |), + make_list [ + M.get_name (| globals, "obj" |); + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.lt (| + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.call (| + M.get_field (| M.get_name (| globals, "rlp" |), "encode" |), + make_list [ + M.get_name (| globals, "root_node" |) + ], + make_dict [] + |) + ], + make_dict [] + |), + Constant.int 32 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + M.call (| + M.get_name (| globals, "keccak256" |), + make_list [ + M.call (| + M.get_field (| M.get_name (| globals, "rlp" |), "encode" |), + make_list [ + M.get_name (| globals, "root_node" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assert (| M.call (| + M.get_name (| globals, "isinstance" |), + make_list [ + M.get_name (| globals, "root_node" |); + M.get_name (| globals, "Bytes" |) + ], + make_dict [] + |) |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, "Root" |), + make_list [ + M.get_name (| globals, "root_node" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_)). + +Definition patricialize : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "obj"; "level" ] |) in + let _ := Constant.str " + Structural composition function. + + Used to recursively patricialize and merkleize a dictionary. Includes + memoization of the tree structure and hashes. + + Parameters + ---------- + obj : + Underlying trie key-value pairs, with keys in nibble-list format. + level : + Current trie level. + + Returns + ------- + node : `ethereum.base_types.Bytes` + Root node of `obj`. + " in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_name (| globals, "obj" |) + ], + make_dict [] + |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + Constant.None_ + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "arbitrary_key" , + M.call (| + M.get_name (| globals, "next" |), + make_list [ + M.call (| + M.get_name (| globals, "iter" |), + make_list [ + M.get_name (| globals, "obj" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_name (| globals, "obj" |) + ], + make_dict [] + |), + Constant.int 1 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "leaf" , + M.call (| + M.get_name (| globals, "LeafNode" |), + make_list [ + M.slice (| + M.get_name (| globals, "arbitrary_key" |), + M.get_name (| globals, "level" |), + Constant.None_, + Constant.None_ + |); + M.get_subscript (| + M.get_name (| globals, "obj" |), + M.get_name (| globals, "arbitrary_key" |) + |) + ], + make_dict [] + |) + |) in + let _ := M.return_ (| + M.get_name (| globals, "leaf" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "substring" , + M.slice (| + M.get_name (| globals, "arbitrary_key" |), + M.get_name (| globals, "level" |), + Constant.None_, + Constant.None_ + |) + |) in + let _ := M.assign_local (| + "prefix_length" , + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_name (| globals, "substring" |) + ], + make_dict [] + |) + |) in + let _ := + M.for_ (| + M.get_name (| globals, "key" |), + M.get_name (| globals, "obj" |), + ltac:(M.monadic ( + let _ := M.assign_local (| + "prefix_length" , + M.call (| + M.get_name (| globals, "min" |), + make_list [ + M.get_name (| globals, "prefix_length" |); + M.call (| + M.get_name (| globals, "common_prefix_length" |), + make_list [ + M.get_name (| globals, "substring" |); + M.slice (| + M.get_name (| globals, "key" |), + M.get_name (| globals, "level" |), + Constant.None_, + Constant.None_ + |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, "prefix_length" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.break (| |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.gt (| + M.get_name (| globals, "prefix_length" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "prefix" , + M.slice (| + M.get_name (| globals, "arbitrary_key" |), + M.get_name (| globals, "level" |), + BinOp.add (| + M.get_name (| globals, "level" |), + M.get_name (| globals, "prefix_length" |) + |), + Constant.None_ + |) + |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, "ExtensionNode" |), + make_list [ + M.get_name (| globals, "prefix" |); + M.call (| + M.get_name (| globals, "encode_internal_node" |), + make_list [ + M.call (| + M.get_name (| globals, "patricialize" |), + make_list [ + M.get_name (| globals, "obj" |); + BinOp.add (| + M.get_name (| globals, "level" |), + M.get_name (| globals, "prefix_length" |) + |) + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in +(* At stmt: unsupported node type: AnnAssign *) + let _ := + M.for_ (| + M.get_name (| globals, "_" |), + M.call (| + M.get_name (| globals, "range" |), + make_list [ + Constant.int 16 + ], + make_dict [] + |), + ltac:(M.monadic ( + let _ := M.call (| + M.get_field (| M.get_name (| globals, "branches" |), "append" |), + make_list [ + Constant.str "(* At expr: unsupported node type: Dict *)" + ], + make_dict [] + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := M.assign_local (| + "value" , + Constant.bytes "" + |) in + let _ := + M.for_ (| + M.get_name (| globals, "key" |), + M.get_name (| globals, "obj" |), + ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_name (| globals, "key" |) + ], + make_dict [] + |), + M.get_name (| globals, "level" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, "isinstance" |), + make_list [ + M.get_subscript (| + M.get_name (| globals, "obj" |), + M.get_name (| globals, "key" |) + |); + make_tuple [ M.get_name (| globals, "Account" |); M.get_name (| globals, "Receipt" |); M.get_name (| globals, "Uint" |) ] + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, "AssertionError" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "value" , + M.get_subscript (| + M.get_name (| globals, "obj" |), + M.get_name (| globals, "key" |) + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign (| + M.get_subscript (| + M.get_subscript (| + M.get_name (| globals, "branches" |), + M.get_subscript (| + M.get_name (| globals, "key" |), + M.get_name (| globals, "level" |) + |) + |), + M.get_name (| globals, "key" |) + |), + M.get_subscript (| + M.get_name (| globals, "obj" |), + M.get_name (| globals, "key" |) + |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, "BranchNode" |), + make_list [ + Constant.str "(* At expr: unsupported node type: ListComp *)"; + M.get_name (| globals, "value" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). diff --git a/CoqOfPython/ethereum/homestead/utils/__init__.v b/CoqOfPython/ethereum/homestead/utils/__init__.v new file mode 100644 index 0000000..c70cb4e --- /dev/null +++ b/CoqOfPython/ethereum/homestead/utils/__init__.v @@ -0,0 +1,8 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.homestead.utils.__init__". + +Definition expr_1 : Value.t := + Constant.str " +Utility functions unique to this particular fork. +". diff --git a/CoqOfPython/ethereum/homestead/utils/address.v b/CoqOfPython/ethereum/homestead/utils/address.v new file mode 100644 index 0000000..82ad5d5 --- /dev/null +++ b/CoqOfPython/ethereum/homestead/utils/address.v @@ -0,0 +1,143 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.homestead.utils.address". + +Definition expr_1 : Value.t := + Constant.str " +Hardfork Utility Functions For Addresses +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Address specific functions used in this homestead version of specification. +". + +Axiom typing_imports_Union : + IsImported globals "typing" "Union". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". + +Axiom ethereum_crypto_hash_imports_keccak256 : + IsImported globals "ethereum.crypto.hash" "keccak256". + +Axiom ethereum_utils_byte_imports_left_pad_zero_bytes : + IsImported globals "ethereum.utils.byte" "left_pad_zero_bytes". + +Axiom ethereum_imports_rlp : + IsImported globals "ethereum" "rlp". + +Axiom ethereum_homestead_fork_types_imports_Address : + IsImported globals "ethereum.homestead.fork_types" "Address". + +Definition to_address : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "data" ] |) in + let _ := Constant.str " + Convert a Uint or U256 value to a valid address (20 bytes). + + Parameters + ---------- + data : + The string to be converted to bytes. + + Returns + ------- + address : `Address` + The obtained address. + " in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, "Address" |), + make_list [ + M.slice (| + M.call (| + M.get_field (| M.get_name (| globals, "data" |), "to_be_bytes32" |), + make_list [], + make_dict [] + |), + UnOp.sub (| Constant.int 20 |), + Constant.None_, + Constant.None_ + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Definition compute_contract_address : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "address"; "nonce" ] |) in + let _ := Constant.str " + Computes address of the new account that needs to be created. + + Parameters + ---------- + address : + The address of the account that wants to create the new account. + nonce : + The transaction count of the account that wants to create the new + account. + + Returns + ------- + address: `ethereum.homestead.fork_types.Address` + The computed address of the new account. + " in + let _ := M.assign_local (| + "computed_address" , + M.call (| + M.get_name (| globals, "keccak256" |), + make_list [ + M.call (| + M.get_field (| M.get_name (| globals, "rlp" |), "encode" |), + make_list [ + make_list [ + M.get_name (| globals, "address" |); + M.get_name (| globals, "nonce" |) + ] + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "canonical_address" , + M.slice (| + M.get_name (| globals, "computed_address" |), + UnOp.sub (| Constant.int 20 |), + Constant.None_, + Constant.None_ + |) + |) in + let _ := M.assign_local (| + "padded_address" , + M.call (| + M.get_name (| globals, "left_pad_zero_bytes" |), + make_list [ + M.get_name (| globals, "canonical_address" |); + Constant.int 20 + ], + make_dict [] + |) + |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, "Address" |), + make_list [ + M.get_name (| globals, "padded_address" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). diff --git a/CoqOfPython/ethereum/homestead/utils/hexadecimal.v b/CoqOfPython/ethereum/homestead/utils/hexadecimal.v new file mode 100644 index 0000000..83917ff --- /dev/null +++ b/CoqOfPython/ethereum/homestead/utils/hexadecimal.v @@ -0,0 +1,153 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.homestead.utils.hexadecimal". + +Definition expr_1 : Value.t := + Constant.str " +Utility Functions For Hexadecimal Strings +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Hexadecimal utility functions used in this specification, specific to Homestead +types. +". + +Axiom ethereum_utils_hexadecimal_imports_remove_hex_prefix : + IsImported globals "ethereum.utils.hexadecimal" "remove_hex_prefix". + +Axiom ethereum_homestead_fork_types_imports_Address : + IsImported globals "ethereum.homestead.fork_types" "Address". +Axiom ethereum_homestead_fork_types_imports_Bloom : + IsImported globals "ethereum.homestead.fork_types" "Bloom". +Axiom ethereum_homestead_fork_types_imports_Root : + IsImported globals "ethereum.homestead.fork_types" "Root". + +Definition hex_to_root : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "hex_string" ] |) in + let _ := Constant.str " + Convert hex string to trie root. + + Parameters + ---------- + hex_string : + The hexadecimal string to be converted to trie root. + + Returns + ------- + root : `Root` + Trie root obtained from the given hexadecimal string. + " in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, "Root" |), + make_list [ + M.call (| + M.get_field (| M.get_name (| globals, "bytes" |), "fromhex" |), + make_list [ + M.call (| + M.get_name (| globals, "remove_hex_prefix" |), + make_list [ + M.get_name (| globals, "hex_string" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Definition hex_to_bloom : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "hex_string" ] |) in + let _ := Constant.str " + Convert hex string to bloom. + + Parameters + ---------- + hex_string : + The hexadecimal string to be converted to bloom. + + Returns + ------- + bloom : `Bloom` + Bloom obtained from the given hexadecimal string. + " in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, "Bloom" |), + make_list [ + M.call (| + M.get_field (| M.get_name (| globals, "bytes" |), "fromhex" |), + make_list [ + M.call (| + M.get_name (| globals, "remove_hex_prefix" |), + make_list [ + M.get_name (| globals, "hex_string" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Definition hex_to_address : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "hex_string" ] |) in + let _ := Constant.str " + Convert hex string to Address (20 bytes). + + Parameters + ---------- + hex_string : + The hexadecimal string to be converted to Address. + + Returns + ------- + address : `Address` + The address obtained from the given hexadecimal string. + " in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, "Address" |), + make_list [ + M.call (| + M.get_field (| M.get_name (| globals, "bytes" |), "fromhex" |), + make_list [ + M.call (| + M.get_field (| M.call (| + M.get_name (| globals, "remove_hex_prefix" |), + make_list [ + M.get_name (| globals, "hex_string" |) + ], + make_dict [] + |), "rjust" |), + make_list [ + Constant.int 40; + Constant.str "0" + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). diff --git a/CoqOfPython/ethereum/homestead/utils/message.v b/CoqOfPython/ethereum/homestead/utils/message.v new file mode 100644 index 0000000..9f53490 --- /dev/null +++ b/CoqOfPython/ethereum/homestead/utils/message.v @@ -0,0 +1,208 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.homestead.utils.message". + +Definition expr_1 : Value.t := + Constant.str " +Hardfork Utility Functions For The Message Data-structure +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Message specific functions used in this homestead version of specification. +". + +Axiom typing_imports_Optional : + IsImported globals "typing" "Optional". +Axiom typing_imports_Union : + IsImported globals "typing" "Union". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_Bytes : + IsImported globals "ethereum.base_types" "Bytes". +Axiom ethereum_base_types_imports_Bytes0 : + IsImported globals "ethereum.base_types" "Bytes0". +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". + +Axiom ethereum_homestead_fork_types_imports_Address : + IsImported globals "ethereum.homestead.fork_types" "Address". + +Axiom ethereum_homestead_state_imports_get_account : + IsImported globals "ethereum.homestead.state" "get_account". + +Axiom ethereum_homestead_vm_imports_Environment : + IsImported globals "ethereum.homestead.vm" "Environment". +Axiom ethereum_homestead_vm_imports_Message : + IsImported globals "ethereum.homestead.vm" "Message". + +Axiom ethereum_homestead_utils_address_imports_compute_contract_address : + IsImported globals "ethereum.homestead.utils.address" "compute_contract_address". + +Definition prepare_message : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "caller"; "target"; "value"; "data"; "gas"; "env"; "code_address"; "should_transfer_value" ] |) in + let _ := Constant.str " + Execute a transaction against the provided environment. + + Parameters + ---------- + caller : + Address which initiated the transaction + target : + Address whose code will be executed + value : + Value to be transferred. + data : + Array of bytes provided to the code in `target`. + gas : + Gas provided for the code in `target`. + env : + Environment for the Ethereum Virtual Machine. + code_address : + This is usually same as the `target` address except when an alternative + accounts code needs to be executed. + eg. `CALLCODE` calling a precompile. + should_transfer_value : + if True ETH should be transferred while executing a message call. + + Returns + ------- + message: `ethereum.homestead.vm.Message` + Items containing contract creation or message call specific data. + " in + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, "isinstance" |), + make_list [ + M.get_name (| globals, "target" |); + M.get_name (| globals, "Bytes0" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "current_target" , + M.call (| + M.get_name (| globals, "compute_contract_address" |), + make_list [ + M.get_name (| globals, "caller" |); + BinOp.sub (| + M.get_field (| M.call (| + M.get_name (| globals, "get_account" |), + make_list [ + M.get_field (| M.get_name (| globals, "env" |), "state" |); + M.get_name (| globals, "caller" |) + ], + make_dict [] + |), "nonce" |), + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 1 + ], + make_dict [] + |) + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "msg_data" , + M.call (| + M.get_name (| globals, "Bytes" |), + make_list [ + Constant.bytes "" + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "code" , + M.get_name (| globals, "data" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, "isinstance" |), + make_list [ + M.get_name (| globals, "target" |); + M.get_name (| globals, "Address" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "current_target" , + M.get_name (| globals, "target" |) + |) in + let _ := M.assign_local (| + "msg_data" , + M.get_name (| globals, "data" |) + |) in + let _ := M.assign_local (| + "code" , + M.get_field (| M.call (| + M.get_name (| globals, "get_account" |), + make_list [ + M.get_field (| M.get_name (| globals, "env" |), "state" |); + M.get_name (| globals, "target" |) + ], + make_dict [] + |), "code" |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.is (| + M.get_name (| globals, "code_address" |), + Constant.None_ + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "code_address" , + M.get_name (| globals, "target" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.raise (| Some (M.call (| + M.get_name (| globals, "AssertionError" |), + make_list [ + Constant.str "Target must be address or empty bytes" + ], + make_dict [] + |)) |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )) |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, "Message" |), + make_list [], + make_dict [] + |) + |) in + M.pure Constant.None_)). diff --git a/CoqOfPython/ethereum/homestead/vm/__init__.v b/CoqOfPython/ethereum/homestead/vm/__init__.v new file mode 100644 index 0000000..3653dc8 --- /dev/null +++ b/CoqOfPython/ethereum/homestead/vm/__init__.v @@ -0,0 +1,145 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.homestead.vm.__init__". + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +The abstract computer which runs the code stored in an +`.fork_types.Account`. +". + +Axiom dataclasses_imports_dataclass : + IsImported globals "dataclasses" "dataclass". + +Axiom typing_imports_List : + IsImported globals "typing" "List". +Axiom typing_imports_Optional : + IsImported globals "typing" "Optional". +Axiom typing_imports_Set : + IsImported globals "typing" "Set". +Axiom typing_imports_Tuple : + IsImported globals "typing" "Tuple". +Axiom typing_imports_Union : + IsImported globals "typing" "Union". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_Bytes : + IsImported globals "ethereum.base_types" "Bytes". +Axiom ethereum_base_types_imports_Bytes0 : + IsImported globals "ethereum.base_types" "Bytes0". +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". + +Axiom ethereum_crypto_hash_imports_Hash32 : + IsImported globals "ethereum.crypto.hash" "Hash32". + +Axiom ethereum_homestead_blocks_imports_Log : + IsImported globals "ethereum.homestead.blocks" "Log". + +Axiom ethereum_homestead_fork_types_imports_Address : + IsImported globals "ethereum.homestead.fork_types" "Address". + +Axiom ethereum_homestead_state_imports_State : + IsImported globals "ethereum.homestead.state" "State". + +Definition __all__ : Value.t := M.run ltac:(M.monadic ( + make_tuple [ Constant.str "Environment"; Constant.str "Evm"; Constant.str "Message" ] +)). + +Definition Environment : Value.t := + builtins.make_klass + [] + [ + + ] + [ + + ]. + +Definition Message : Value.t := + builtins.make_klass + [] + [ + + ] + [ + + ]. + +Definition Evm : Value.t := + builtins.make_klass + [] + [ + + ] + [ + + ]. + +Definition incorporate_child_on_success : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm"; "child_evm" ] |) in + let _ := Constant.str " + Incorporate the state of a successful `child_evm` into the parent `evm`. + + Parameters + ---------- + evm : + The parent `EVM`. + child_evm : + The child evm to incorporate. + " in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "gas_left" |), + M.get_field (| M.get_name (| globals, "child_evm" |), "gas_left" |) + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "logs" |), + M.get_field (| M.get_name (| globals, "child_evm" |), "logs" |) + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "refund_counter" |), + M.get_field (| M.get_name (| globals, "child_evm" |), "refund_counter" |) + |) in + let _ := M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "accounts_to_delete" |), "update" |), + make_list [ + M.get_field (| M.get_name (| globals, "child_evm" |), "accounts_to_delete" |) + ], + make_dict [] + |) in + M.pure Constant.None_)). + +Definition incorporate_child_on_error : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm"; "child_evm" ] |) in + let _ := Constant.str " + Incorporate the state of an unsuccessful `child_evm` into the parent `evm`. + + Parameters + ---------- + evm : + The parent `EVM`. + child_evm : + The child evm to incorporate. + " in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "gas_left" |), + M.get_field (| M.get_name (| globals, "child_evm" |), "gas_left" |) + |) in + M.pure Constant.None_)). diff --git a/CoqOfPython/ethereum/homestead/vm/exceptions.v b/CoqOfPython/ethereum/homestead/vm/exceptions.v new file mode 100644 index 0000000..3c7fd2e --- /dev/null +++ b/CoqOfPython/ethereum/homestead/vm/exceptions.v @@ -0,0 +1,121 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.homestead.vm.exceptions". + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) Exceptions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Exceptions which cause the EVM to halt exceptionally. +". + +Axiom ethereum_exceptions_imports_EthereumException : + IsImported globals "ethereum.exceptions" "EthereumException". + +Definition ExceptionalHalt : Value.t := + builtins.make_klass + [(globals, "EthereumException")] + [ + + ] + [ + + ]. + +Definition StackUnderflowError : Value.t := + builtins.make_klass + [(globals, "ExceptionalHalt")] + [ + + ] + [ + + ]. + +Definition StackOverflowError : Value.t := + builtins.make_klass + [(globals, "ExceptionalHalt")] + [ + + ] + [ + + ]. + +Definition OutOfGasError : Value.t := + builtins.make_klass + [(globals, "ExceptionalHalt")] + [ + + ] + [ + + ]. + +Definition InvalidOpcode : Value.t := + builtins.make_klass + [(globals, "ExceptionalHalt")] + [ + + ] + [ + ( + "__init__", + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "self"; "code" ] |) in + let _ := M.call (| + M.get_field (| M.call (| + M.get_name (| globals, "super" |), + make_list [], + make_dict [] + |), "__init__" |), + make_list [ + M.get_name (| globals, "code" |) + ], + make_dict [] + |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, "self" |), "code" |), + M.get_name (| globals, "code" |) + |) in + M.pure Constant.None_)) + ) + ]. + +Definition InvalidJumpDestError : Value.t := + builtins.make_klass + [(globals, "ExceptionalHalt")] + [ + + ] + [ + + ]. + +Definition StackDepthLimitError : Value.t := + builtins.make_klass + [(globals, "ExceptionalHalt")] + [ + + ] + [ + + ]. + +Definition AddressCollision : Value.t := + builtins.make_klass + [(globals, "ExceptionalHalt")] + [ + + ] + [ + + ]. diff --git a/CoqOfPython/ethereum/homestead/vm/gas.v b/CoqOfPython/ethereum/homestead/vm/gas.v new file mode 100644 index 0000000..db0a564 --- /dev/null +++ b/CoqOfPython/ethereum/homestead/vm/gas.v @@ -0,0 +1,852 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.homestead.vm.gas". + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) Gas +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +EVM gas constants and calculators. +". + +Axiom dataclasses_imports_dataclass : + IsImported globals "dataclasses" "dataclass". + +Axiom typing_imports_List : + IsImported globals "typing" "List". +Axiom typing_imports_Tuple : + IsImported globals "typing" "Tuple". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". + +Axiom ethereum_trace_imports_GasAndRefund : + IsImported globals "ethereum.trace" "GasAndRefund". +Axiom ethereum_trace_imports_evm_trace : + IsImported globals "ethereum.trace" "evm_trace". + +Axiom ethereum_utils_numeric_imports_ceil32 : + IsImported globals "ethereum.utils.numeric" "ceil32". + +Axiom ethereum_homestead_fork_types_imports_Address : + IsImported globals "ethereum.homestead.fork_types" "Address". + +Axiom ethereum_homestead_state_imports_State : + IsImported globals "ethereum.homestead.state" "State". +Axiom ethereum_homestead_state_imports_account_exists : + IsImported globals "ethereum.homestead.state" "account_exists". + +Axiom ethereum_homestead_vm_imports_Evm : + IsImported globals "ethereum.homestead.vm" "Evm". + +Axiom ethereum_homestead_vm_exceptions_imports_OutOfGasError : + IsImported globals "ethereum.homestead.vm.exceptions" "OutOfGasError". + +Definition GAS_JUMPDEST : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 1 + ], + make_dict [] + |) +)). + +Definition GAS_BASE : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 2 + ], + make_dict [] + |) +)). + +Definition GAS_VERY_LOW : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 3 + ], + make_dict [] + |) +)). + +Definition GAS_SLOAD : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 50 + ], + make_dict [] + |) +)). + +Definition GAS_STORAGE_SET : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 20000 + ], + make_dict [] + |) +)). + +Definition GAS_STORAGE_UPDATE : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 5000 + ], + make_dict [] + |) +)). + +Definition GAS_STORAGE_CLEAR_REFUND : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 15000 + ], + make_dict [] + |) +)). + +Definition GAS_LOW : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 5 + ], + make_dict [] + |) +)). + +Definition GAS_MID : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 8 + ], + make_dict [] + |) +)). + +Definition GAS_HIGH : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 10 + ], + make_dict [] + |) +)). + +Definition GAS_EXPONENTIATION : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 10 + ], + make_dict [] + |) +)). + +Definition GAS_EXPONENTIATION_PER_BYTE : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 10 + ], + make_dict [] + |) +)). + +Definition GAS_MEMORY : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 3 + ], + make_dict [] + |) +)). + +Definition GAS_KECCAK256 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 30 + ], + make_dict [] + |) +)). + +Definition GAS_KECCAK256_WORD : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 6 + ], + make_dict [] + |) +)). + +Definition GAS_COPY : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 3 + ], + make_dict [] + |) +)). + +Definition GAS_BLOCK_HASH : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 20 + ], + make_dict [] + |) +)). + +Definition GAS_EXTERNAL : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 20 + ], + make_dict [] + |) +)). + +Definition GAS_BALANCE : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 20 + ], + make_dict [] + |) +)). + +Definition GAS_LOG : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 375 + ], + make_dict [] + |) +)). + +Definition GAS_LOG_DATA : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 8 + ], + make_dict [] + |) +)). + +Definition GAS_LOG_TOPIC : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 375 + ], + make_dict [] + |) +)). + +Definition GAS_CREATE : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 32000 + ], + make_dict [] + |) +)). + +Definition GAS_CODE_DEPOSIT : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 200 + ], + make_dict [] + |) +)). + +Definition GAS_ZERO : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) +)). + +Definition GAS_CALL : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 40 + ], + make_dict [] + |) +)). + +Definition GAS_NEW_ACCOUNT : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 25000 + ], + make_dict [] + |) +)). + +Definition GAS_CALL_VALUE : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 9000 + ], + make_dict [] + |) +)). + +Definition GAS_CALL_STIPEND : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 2300 + ], + make_dict [] + |) +)). + +Definition REFUND_SELF_DESTRUCT : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 24000 + ], + make_dict [] + |) +)). + +Definition GAS_ECRECOVER : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 3000 + ], + make_dict [] + |) +)). + +Definition GAS_SHA256 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 60 + ], + make_dict [] + |) +)). + +Definition GAS_SHA256_WORD : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 12 + ], + make_dict [] + |) +)). + +Definition GAS_RIPEMD160 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 600 + ], + make_dict [] + |) +)). + +Definition GAS_RIPEMD160_WORD : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 120 + ], + make_dict [] + |) +)). + +Definition GAS_IDENTITY : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 15 + ], + make_dict [] + |) +)). + +Definition GAS_IDENTITY_WORD : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 3 + ], + make_dict [] + |) +)). + +Definition ExtendMemory : Value.t := + builtins.make_klass + [] + [ + + ] + [ + + ]. + +Definition MessageCallGas : Value.t := + builtins.make_klass + [] + [ + + ] + [ + + ]. + +Definition charge_gas : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm"; "amount" ] |) in + let _ := Constant.str " + Subtracts `amount` from `evm.gas_left`. + + Parameters + ---------- + evm : + The current EVM. + amount : + The amount of gas the current operation requires. + + " in + let _ := M.call (| + M.get_name (| globals, "evm_trace" |), + make_list [ + M.get_name (| globals, "evm" |); + M.call (| + M.get_name (| globals, "GasAndRefund" |), + make_list [ + M.get_name (| globals, "amount" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.lt (| + M.get_field (| M.get_name (| globals, "evm" |), "gas_left" |), + M.get_name (| globals, "amount" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, "OutOfGasError" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_op (| + BinOp.sub, + M.get_field (| M.get_name (| globals, "evm" |), "gas_left" |), + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + M.get_name (| globals, "amount" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_)). + +Definition calculate_memory_gas_cost : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "size_in_bytes" ] |) in + let _ := Constant.str " + Calculates the gas cost for allocating memory + to the smallest multiple of 32 bytes, + such that the allocated size is at least as big as the given size. + + Parameters + ---------- + size_in_bytes : + The size of the data in bytes. + + Returns + ------- + total_gas_cost : `ethereum.base_types.Uint` + The gas cost for storing data in memory. + " in + let _ := M.assign_local (| + "size_in_words" , + BinOp.floor_div (| + M.call (| + M.get_name (| globals, "ceil32" |), + make_list [ + M.get_name (| globals, "size_in_bytes" |) + ], + make_dict [] + |), + Constant.int 32 + |) + |) in + let _ := M.assign_local (| + "linear_cost" , + BinOp.mult (| + M.get_name (| globals, "size_in_words" |), + M.get_name (| globals, "GAS_MEMORY" |) + |) + |) in + let _ := M.assign_local (| + "quadratic_cost" , + BinOp.floor_div (| + BinOp.pow (| + M.get_name (| globals, "size_in_words" |), + Constant.int 2 + |), + Constant.int 512 + |) + |) in + let _ := M.assign_local (| + "total_gas_cost" , + BinOp.add (| + M.get_name (| globals, "linear_cost" |), + M.get_name (| globals, "quadratic_cost" |) + |) + |) in +(* At stmt: unsupported node type: Try *) + M.pure Constant.None_)). + +Definition calculate_gas_extend_memory : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "memory"; "extensions" ] |) in + let _ := Constant.str " + Calculates the gas amount to extend memory + + Parameters + ---------- + memory : + Memory contents of the EVM. + extensions: + List of extensions to be made to the memory. + Consists of a tuple of start position and size. + + Returns + ------- + extend_memory: `ExtendMemory` + " in + let _ := M.assign_local (| + "size_to_extend" , + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "to_be_paid" , + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "current_size" , + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_name (| globals, "memory" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := + M.for_ (| + make_tuple [ M.get_name (| globals, "start_position" |); M.get_name (| globals, "size" |) ], + M.get_name (| globals, "extensions" |), + ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, "size" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.continue (| |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "before_size" , + M.call (| + M.get_name (| globals, "ceil32" |), + make_list [ + M.get_name (| globals, "current_size" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "after_size" , + M.call (| + M.get_name (| globals, "ceil32" |), + make_list [ + BinOp.add (| + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.get_name (| globals, "start_position" |) + ], + make_dict [] + |), + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.get_name (| globals, "size" |) + ], + make_dict [] + |) + |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.lt_e (| + M.get_name (| globals, "after_size" |), + M.get_name (| globals, "before_size" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.continue (| |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_op_local (| + BinOp.add, + "size_to_extend", + BinOp.sub (| + M.get_name (| globals, "after_size" |), + M.get_name (| globals, "before_size" |) + |) + |) in + let _ := M.assign_local (| + "already_paid" , + M.call (| + M.get_name (| globals, "calculate_memory_gas_cost" |), + make_list [ + M.get_name (| globals, "before_size" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "total_cost" , + M.call (| + M.get_name (| globals, "calculate_memory_gas_cost" |), + make_list [ + M.get_name (| globals, "after_size" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_op_local (| + BinOp.add, + "to_be_paid", + BinOp.sub (| + M.get_name (| globals, "total_cost" |), + M.get_name (| globals, "already_paid" |) + |) + |) in + let _ := M.assign_local (| + "current_size" , + M.get_name (| globals, "after_size" |) + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, "ExtendMemory" |), + make_list [ + M.get_name (| globals, "to_be_paid" |); + M.get_name (| globals, "size_to_extend" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Definition calculate_message_call_gas : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "state"; "gas"; "to"; "value" ] |) in + let _ := Constant.str " + Calculates the gas amount for executing Opcodes `CALL` and `CALLCODE`. + + Parameters + ---------- + state : + The current state. + gas : + The amount of gas provided to the message-call. + to: + The address of the recipient account. + value: + The amount of `ETH` that needs to be transferred. + + Returns + ------- + message_call_gas: `MessageCallGas` + " in + let _ := M.assign_local (| + "create_gas_cost" , + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, "account_exists" |), + make_list [ + M.get_name (| globals, "state" |); + M.get_name (| globals, "to" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( +M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + (* else *) + )), ltac:(M.monadic ( +M.get_name (| globals, "GAS_NEW_ACCOUNT" |) + )) |) + |) in + let _ := M.assign_local (| + "transfer_gas_cost" , + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, "value" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( +M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + (* else *) + )), ltac:(M.monadic ( +M.get_name (| globals, "GAS_CALL_VALUE" |) + )) |) + |) in + let _ := M.assign_local (| + "cost" , + BinOp.add (| + BinOp.add (| + BinOp.add (| + M.get_name (| globals, "GAS_CALL" |), + M.get_name (| globals, "gas" |) + |), + M.get_name (| globals, "create_gas_cost" |) + |), + M.get_name (| globals, "transfer_gas_cost" |) + |) + |) in + let _ := M.assign_local (| + "stipend" , + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, "value" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( +M.get_name (| globals, "gas" |) + (* else *) + )), ltac:(M.monadic ( +BinOp.add (| + M.get_name (| globals, "GAS_CALL_STIPEND" |), + M.get_name (| globals, "gas" |) + |) + )) |) + |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, "MessageCallGas" |), + make_list [ + M.get_name (| globals, "cost" |); + M.get_name (| globals, "stipend" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). diff --git a/CoqOfPython/ethereum/homestead/vm/instructions/__init__.v b/CoqOfPython/ethereum/homestead/vm/instructions/__init__.v new file mode 100644 index 0000000..7a70aef --- /dev/null +++ b/CoqOfPython/ethereum/homestead/vm/instructions/__init__.v @@ -0,0 +1,74 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.homestead.vm.instructions.__init__". + +Definition expr_1 : Value.t := + Constant.str " +EVM Instruction Encoding (Opcodes) +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Machine readable representations of EVM instructions, and a mapping to their +implementations. +". + +(* At top_level_stmt: unsupported node type: Import *) + +Axiom typing_imports_Callable : + IsImported globals "typing" "Callable". +Axiom typing_imports_Dict : + IsImported globals "typing" "Dict". + +Axiom ethereum_homestead_vm_instructions_imports_arithmetic : + IsImported globals "ethereum.homestead.vm.instructions" "arithmetic". + +Axiom ethereum_homestead_vm_instructions_imports_bitwise : + IsImported globals "ethereum.homestead.vm.instructions" "bitwise". + +Axiom ethereum_homestead_vm_instructions_imports_block : + IsImported globals "ethereum.homestead.vm.instructions" "block". + +Axiom ethereum_homestead_vm_instructions_imports_comparison : + IsImported globals "ethereum.homestead.vm.instructions" "comparison". + +Axiom ethereum_homestead_vm_instructions_imports_control_flow : + IsImported globals "ethereum.homestead.vm.instructions" "control_flow". + +Axiom ethereum_homestead_vm_instructions_imports_environment : + IsImported globals "ethereum.homestead.vm.instructions" "environment". + +Axiom ethereum_homestead_vm_instructions_imports_keccak : + IsImported globals "ethereum.homestead.vm.instructions" "keccak". + +Axiom ethereum_homestead_vm_instructions_imports_log : + IsImported globals "ethereum.homestead.vm.instructions" "log". + +Axiom ethereum_homestead_vm_instructions_imports_memory : + IsImported globals "ethereum.homestead.vm.instructions" "memory". + +Axiom ethereum_homestead_vm_instructions_imports_stack : + IsImported globals "ethereum.homestead.vm.instructions" "stack". + +Axiom ethereum_homestead_vm_instructions_imports_storage : + IsImported globals "ethereum.homestead.vm.instructions" "storage". + +Axiom ethereum_homestead_vm_instructions_imports_system : + IsImported globals "ethereum.homestead.vm.instructions" "system". + +Definition Ops : Value.t := + builtins.make_klass + [(* At base: unsupported node type: Attribute *)] + [ + + ] + [ + + ]. + +(* At top_level_stmt: unsupported node type: AnnAssign *) diff --git a/CoqOfPython/ethereum/homestead/vm/instructions/arithmetic.v b/CoqOfPython/ethereum/homestead/vm/instructions/arithmetic.v new file mode 100644 index 0000000..1c889a2 --- /dev/null +++ b/CoqOfPython/ethereum/homestead/vm/instructions/arithmetic.v @@ -0,0 +1,1220 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.homestead.vm.instructions.arithmetic". + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) Arithmetic Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM Arithmetic instructions. +". + +Axiom ethereum_base_types_imports_U255_CEIL_VALUE : + IsImported globals "ethereum.base_types" "U255_CEIL_VALUE". +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_U256_CEIL_VALUE : + IsImported globals "ethereum.base_types" "U256_CEIL_VALUE". +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". + +Axiom ethereum_utils_numeric_imports_get_sign : + IsImported globals "ethereum.utils.numeric" "get_sign". + +Axiom ethereum_homestead_vm_imports_Evm : + IsImported globals "ethereum.homestead.vm" "Evm". + +Axiom ethereum_homestead_vm_gas_imports_GAS_EXPONENTIATION : + IsImported globals "ethereum.homestead.vm.gas" "GAS_EXPONENTIATION". +Axiom ethereum_homestead_vm_gas_imports_GAS_EXPONENTIATION_PER_BYTE : + IsImported globals "ethereum.homestead.vm.gas" "GAS_EXPONENTIATION_PER_BYTE". +Axiom ethereum_homestead_vm_gas_imports_GAS_LOW : + IsImported globals "ethereum.homestead.vm.gas" "GAS_LOW". +Axiom ethereum_homestead_vm_gas_imports_GAS_MID : + IsImported globals "ethereum.homestead.vm.gas" "GAS_MID". +Axiom ethereum_homestead_vm_gas_imports_GAS_VERY_LOW : + IsImported globals "ethereum.homestead.vm.gas" "GAS_VERY_LOW". +Axiom ethereum_homestead_vm_gas_imports_charge_gas : + IsImported globals "ethereum.homestead.vm.gas" "charge_gas". + +Axiom ethereum_homestead_vm_stack_imports_pop : + IsImported globals "ethereum.homestead.vm.stack" "pop". +Axiom ethereum_homestead_vm_stack_imports_push : + IsImported globals "ethereum.homestead.vm.stack" "push". + +Definition add : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Adds the top two elements of the stack together, and pushes the result back + on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "x" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "y" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_VERY_LOW" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "result" , + M.call (| + M.get_field (| M.get_name (| globals, "x" |), "wrapping_add" |), + make_list [ + M.get_name (| globals, "y" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.get_name (| globals, "result" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition sub : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Subtracts the top two elements of the stack, and pushes the result back + on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "x" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "y" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_VERY_LOW" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "result" , + M.call (| + M.get_field (| M.get_name (| globals, "x" |), "wrapping_sub" |), + make_list [ + M.get_name (| globals, "y" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.get_name (| globals, "result" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition mul : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Multiply the top two elements of the stack, and pushes the result back + on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "x" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "y" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_LOW" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "result" , + M.call (| + M.get_field (| M.get_name (| globals, "x" |), "wrapping_mul" |), + make_list [ + M.get_name (| globals, "y" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.get_name (| globals, "result" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition div : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Integer division of the top two elements of the stack. Pushes the result + back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "dividend" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "divisor" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_LOW" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, "divisor" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "quotient" , + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "quotient" , + BinOp.floor_div (| + M.get_name (| globals, "dividend" |), + M.get_name (| globals, "divisor" |) + |) + |) in + M.pure Constant.None_ + )) |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.get_name (| globals, "quotient" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition sdiv : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Signed integer division of the top two elements of the stack. Pushes the + result back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "dividend" , + M.call (| + M.get_field (| M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |), "to_signed" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "divisor" , + M.call (| + M.get_field (| M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |), "to_signed" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_LOW" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, "divisor" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "quotient" , + Constant.int 0 + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + BoolOp.and (| + Compare.eq (| + M.get_name (| globals, "dividend" |), + UnOp.sub (| M.get_name (| globals, "U255_CEIL_VALUE" |) |) + |), + ltac:(M.monadic ( + Compare.eq (| + M.get_name (| globals, "divisor" |), + UnOp.sub (| Constant.int 1 |) + |) + )) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "quotient" , + UnOp.sub (| M.get_name (| globals, "U255_CEIL_VALUE" |) |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "sign" , + M.call (| + M.get_name (| globals, "get_sign" |), + make_list [ + BinOp.mult (| + M.get_name (| globals, "dividend" |), + M.get_name (| globals, "divisor" |) + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "quotient" , + BinOp.mult (| + M.get_name (| globals, "sign" |), + BinOp.floor_div (| + M.call (| + M.get_name (| globals, "abs" |), + make_list [ + M.get_name (| globals, "dividend" |) + ], + make_dict [] + |), + M.call (| + M.get_name (| globals, "abs" |), + make_list [ + M.get_name (| globals, "divisor" |) + ], + make_dict [] + |) + |) + |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )) |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.call (| + M.get_field (| M.get_name (| globals, "U256" |), "from_signed" |), + make_list [ + M.get_name (| globals, "quotient" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition mod_ : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Modulo remainder of the top two elements of the stack. Pushes the result + back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "x" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "y" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_LOW" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, "y" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "remainder" , + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "remainder" , + BinOp.mod_ (| + M.get_name (| globals, "x" |), + M.get_name (| globals, "y" |) + |) + |) in + M.pure Constant.None_ + )) |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.get_name (| globals, "remainder" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition smod : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Signed modulo remainder of the top two elements of the stack. Pushes the + result back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "x" , + M.call (| + M.get_field (| M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |), "to_signed" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "y" , + M.call (| + M.get_field (| M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |), "to_signed" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_LOW" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, "y" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "remainder" , + Constant.int 0 + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "remainder" , + BinOp.mult (| + M.call (| + M.get_name (| globals, "get_sign" |), + make_list [ + M.get_name (| globals, "x" |) + ], + make_dict [] + |), + BinOp.mod_ (| + M.call (| + M.get_name (| globals, "abs" |), + make_list [ + M.get_name (| globals, "x" |) + ], + make_dict [] + |), + M.call (| + M.get_name (| globals, "abs" |), + make_list [ + M.get_name (| globals, "y" |) + ], + make_dict [] + |) + |) + |) + |) in + M.pure Constant.None_ + )) |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.call (| + M.get_field (| M.get_name (| globals, "U256" |), "from_signed" |), + make_list [ + M.get_name (| globals, "remainder" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition addmod : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Modulo addition of the top 2 elements with the 3rd element. Pushes the + result back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "x" , + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "y" , + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "z" , + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_MID" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, "z" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "result" , + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "result" , + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + BinOp.mod_ (| + BinOp.add (| + M.get_name (| globals, "x" |), + M.get_name (| globals, "y" |) + |), + M.get_name (| globals, "z" |) + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + )) |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.get_name (| globals, "result" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition mulmod : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Modulo multiplication of the top 2 elements with the 3rd element. Pushes + the result back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "x" , + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "y" , + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "z" , + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_MID" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, "z" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "result" , + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "result" , + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + BinOp.mod_ (| + BinOp.mult (| + M.get_name (| globals, "x" |), + M.get_name (| globals, "y" |) + |), + M.get_name (| globals, "z" |) + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + )) |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.get_name (| globals, "result" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition exp : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Exponential operation of the top 2 elements. Pushes the result back on + the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "base" , + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "exponent" , + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "exponent_bits" , + M.call (| + M.get_field (| M.get_name (| globals, "exponent" |), "bit_length" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "exponent_bytes" , + BinOp.floor_div (| + BinOp.add (| + M.get_name (| globals, "exponent_bits" |), + Constant.int 7 + |), + Constant.int 8 + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + BinOp.add (| + M.get_name (| globals, "GAS_EXPONENTIATION" |), + BinOp.mult (| + M.get_name (| globals, "GAS_EXPONENTIATION_PER_BYTE" |), + M.get_name (| globals, "exponent_bytes" |) + |) + |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "result" , + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + M.call (| + M.get_name (| globals, "pow" |), + make_list [ + M.get_name (| globals, "base" |); + M.get_name (| globals, "exponent" |); + M.get_name (| globals, "U256_CEIL_VALUE" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.get_name (| globals, "result" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition signextend : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Sign extend operation. In other words, extend a signed number which + fits in N bytes to 32 bytes. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "byte_num" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "value" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_LOW" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.gt (| + M.get_name (| globals, "byte_num" |), + Constant.int 31 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "result" , + M.get_name (| globals, "value" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "value_bytes" , + M.call (| + M.get_name (| globals, "bytes" |), + make_list [ + M.call (| + M.get_field (| M.get_name (| globals, "value" |), "to_be_bytes32" |), + make_list [], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "value_bytes" , + M.slice (| + M.get_name (| globals, "value_bytes" |), + BinOp.sub (| + Constant.int 31, + M.call (| + M.get_name (| globals, "int" |), + make_list [ + M.get_name (| globals, "byte_num" |) + ], + make_dict [] + |) + |), + Constant.None_, + Constant.None_ + |) + |) in + let _ := M.assign_local (| + "sign_bit" , + BinOp.r_shift (| + M.get_subscript (| + M.get_name (| globals, "value_bytes" |), + Constant.int 0 + |), + Constant.int 7 + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, "sign_bit" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "result" , + M.call (| + M.get_field (| M.get_name (| globals, "U256" |), "from_be_bytes" |), + make_list [ + M.get_name (| globals, "value_bytes" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "num_bytes_prepend" , + BinOp.sub (| + Constant.int 32, + BinOp.add (| + M.get_name (| globals, "byte_num" |), + Constant.int 1 + |) + |) + |) in + let _ := M.assign_local (| + "result" , + M.call (| + M.get_field (| M.get_name (| globals, "U256" |), "from_be_bytes" |), + make_list [ + BinOp.add (| + M.call (| + M.get_name (| globals, "bytearray" |), + make_list [ + BinOp.mult (| + make_list [ + Constant.int 255 + ], + M.get_name (| globals, "num_bytes_prepend" |) + |) + ], + make_dict [] + |), + M.get_name (| globals, "value_bytes" |) + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )) |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.get_name (| globals, "result" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). diff --git a/CoqOfPython/ethereum/homestead/vm/instructions/bitwise.v b/CoqOfPython/ethereum/homestead/vm/instructions/bitwise.v new file mode 100644 index 0000000..9a886dd --- /dev/null +++ b/CoqOfPython/ethereum/homestead/vm/instructions/bitwise.v @@ -0,0 +1,372 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.homestead.vm.instructions.bitwise". + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) Bitwise Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM bitwise instructions. +". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". + +Axiom ethereum_homestead_vm_imports_Evm : + IsImported globals "ethereum.homestead.vm" "Evm". + +Axiom ethereum_homestead_vm_gas_imports_GAS_VERY_LOW : + IsImported globals "ethereum.homestead.vm.gas" "GAS_VERY_LOW". +Axiom ethereum_homestead_vm_gas_imports_charge_gas : + IsImported globals "ethereum.homestead.vm.gas" "charge_gas". + +Axiom ethereum_homestead_vm_stack_imports_pop : + IsImported globals "ethereum.homestead.vm.stack" "pop". +Axiom ethereum_homestead_vm_stack_imports_push : + IsImported globals "ethereum.homestead.vm.stack" "push". + +Definition bitwise_and : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Bitwise AND operation of the top 2 elements of the stack. Pushes the + result back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "x" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "y" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_VERY_LOW" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + BinOp.bit_and (| + M.get_name (| globals, "x" |), + M.get_name (| globals, "y" |) + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition bitwise_or : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Bitwise OR operation of the top 2 elements of the stack. Pushes the + result back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "x" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "y" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_VERY_LOW" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + BinOp.bit_or (| + M.get_name (| globals, "x" |), + M.get_name (| globals, "y" |) + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition bitwise_xor : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Bitwise XOR operation of the top 2 elements of the stack. Pushes the + result back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "x" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "y" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_VERY_LOW" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + BinOp.bit_xor (| + M.get_name (| globals, "x" |), + M.get_name (| globals, "y" |) + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition bitwise_not : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Bitwise NOT operation of the top element of the stack. Pushes the + result back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "x" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_VERY_LOW" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + UnOp.invert (| M.get_name (| globals, "x" |) |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition get_byte : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + For a word (defined by next top element of the stack), retrieve the + Nth byte (0-indexed and defined by top element of stack) from the + left (most significant) to right (least significant). + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "byte_index" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "word" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_VERY_LOW" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.gt_e (| + M.get_name (| globals, "byte_index" |), + Constant.int 32 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "result" , + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "extra_bytes_to_right" , + BinOp.sub (| + Constant.int 31, + M.get_name (| globals, "byte_index" |) + |) + |) in + let _ := M.assign_local (| + "word" , + BinOp.r_shift (| + M.get_name (| globals, "word" |), + BinOp.mult (| + M.get_name (| globals, "extra_bytes_to_right" |), + Constant.int 8 + |) + |) + |) in + let _ := M.assign_local (| + "word" , + BinOp.bit_and (| + M.get_name (| globals, "word" |), + Constant.int 255 + |) + |) in + let _ := M.assign_local (| + "result" , + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + M.get_name (| globals, "word" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + )) |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.get_name (| globals, "result" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). diff --git a/CoqOfPython/ethereum/homestead/vm/instructions/block.v b/CoqOfPython/ethereum/homestead/vm/instructions/block.v new file mode 100644 index 0000000..b5d16dd --- /dev/null +++ b/CoqOfPython/ethereum/homestead/vm/instructions/block.v @@ -0,0 +1,348 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.homestead.vm.instructions.block". + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) Block Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM block instructions. +". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". + +Axiom ethereum_homestead_vm_imports_Evm : + IsImported globals "ethereum.homestead.vm" "Evm". + +Axiom ethereum_homestead_vm_gas_imports_GAS_BASE : + IsImported globals "ethereum.homestead.vm.gas" "GAS_BASE". +Axiom ethereum_homestead_vm_gas_imports_GAS_BLOCK_HASH : + IsImported globals "ethereum.homestead.vm.gas" "GAS_BLOCK_HASH". +Axiom ethereum_homestead_vm_gas_imports_charge_gas : + IsImported globals "ethereum.homestead.vm.gas" "charge_gas". + +Axiom ethereum_homestead_vm_stack_imports_pop : + IsImported globals "ethereum.homestead.vm.stack" "pop". +Axiom ethereum_homestead_vm_stack_imports_push : + IsImported globals "ethereum.homestead.vm.stack" "push". + +Definition block_hash : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Push the hash of one of the 256 most recent complete blocks onto the + stack. The block number to hash is present at the top of the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "block_number" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_BLOCK_HASH" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + BoolOp.or (| + Compare.lt_e (| + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "env" |), "number" |), + M.get_name (| globals, "block_number" |) + |), + ltac:(M.monadic ( + Compare.gt (| + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "env" |), "number" |), + BinOp.add (| + M.get_name (| globals, "block_number" |), + Constant.int 256 + |) + |) + )) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "hash" , + Constant.bytes "00" + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "hash" , + M.get_subscript (| + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "env" |), "block_hashes" |), + UnOp.sub (| BinOp.sub (| + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "env" |), "number" |), + M.get_name (| globals, "block_number" |) + |) |) + |) + |) in + M.pure Constant.None_ + )) |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.call (| + M.get_field (| M.get_name (| globals, "U256" |), "from_be_bytes" |), + make_list [ + M.get_name (| globals, "hash" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition coinbase : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Push the current block's beneficiary address (address of the block miner) + onto the stack. + + Here the current block refers to the block in which the currently + executing transaction/call resides. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_BASE" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.call (| + M.get_field (| M.get_name (| globals, "U256" |), "from_be_bytes" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "env" |), "coinbase" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition timestamp : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Push the current block's timestamp onto the stack. Here the timestamp + being referred is actually the unix timestamp in seconds. + + Here the current block refers to the block in which the currently + executing transaction/call resides. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_BASE" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "env" |), "time" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition number : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Push the current block's number onto the stack. + + Here the current block refers to the block in which the currently + executing transaction/call resides. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_BASE" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "env" |), "number" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition difficulty : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Push the current block's difficulty onto the stack. + + Here the current block refers to the block in which the currently + executing transaction/call resides. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_BASE" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "env" |), "difficulty" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition gas_limit : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Push the current block's gas limit onto the stack. + + Here the current block refers to the block in which the currently + executing transaction/call resides. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_BASE" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "env" |), "gas_limit" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). diff --git a/CoqOfPython/ethereum/homestead/vm/instructions/comparison.v b/CoqOfPython/ethereum/homestead/vm/instructions/comparison.v new file mode 100644 index 0000000..dae8d81 --- /dev/null +++ b/CoqOfPython/ethereum/homestead/vm/instructions/comparison.v @@ -0,0 +1,452 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.homestead.vm.instructions.comparison". + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) Comparison Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM Comparison instructions. +". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". + +Axiom ethereum_homestead_vm_imports_Evm : + IsImported globals "ethereum.homestead.vm" "Evm". + +Axiom ethereum_homestead_vm_gas_imports_GAS_VERY_LOW : + IsImported globals "ethereum.homestead.vm.gas" "GAS_VERY_LOW". +Axiom ethereum_homestead_vm_gas_imports_charge_gas : + IsImported globals "ethereum.homestead.vm.gas" "charge_gas". + +Axiom ethereum_homestead_vm_stack_imports_pop : + IsImported globals "ethereum.homestead.vm.stack" "pop". +Axiom ethereum_homestead_vm_stack_imports_push : + IsImported globals "ethereum.homestead.vm.stack" "push". + +Definition less_than : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Checks if the top element is less than the next top element. Pushes the + result back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "left" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "right" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_VERY_LOW" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "result" , + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Compare.lt (| + M.get_name (| globals, "left" |), + M.get_name (| globals, "right" |) + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.get_name (| globals, "result" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition signed_less_than : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Signed less-than comparison. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "left" , + M.call (| + M.get_field (| M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |), "to_signed" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "right" , + M.call (| + M.get_field (| M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |), "to_signed" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_VERY_LOW" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "result" , + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Compare.lt (| + M.get_name (| globals, "left" |), + M.get_name (| globals, "right" |) + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.get_name (| globals, "result" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition greater_than : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Checks if the top element is greater than the next top element. Pushes + the result back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "left" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "right" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_VERY_LOW" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "result" , + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Compare.gt (| + M.get_name (| globals, "left" |), + M.get_name (| globals, "right" |) + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.get_name (| globals, "result" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition signed_greater_than : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Signed greater-than comparison. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "left" , + M.call (| + M.get_field (| M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |), "to_signed" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "right" , + M.call (| + M.get_field (| M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |), "to_signed" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_VERY_LOW" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "result" , + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Compare.gt (| + M.get_name (| globals, "left" |), + M.get_name (| globals, "right" |) + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.get_name (| globals, "result" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition equal : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Checks if the top element is equal to the next top element. Pushes + the result back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "left" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "right" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_VERY_LOW" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "result" , + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Compare.eq (| + M.get_name (| globals, "left" |), + M.get_name (| globals, "right" |) + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.get_name (| globals, "result" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition is_zero : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Checks if the top element is equal to 0. Pushes the result back on the + stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "x" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_VERY_LOW" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "result" , + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Compare.eq (| + M.get_name (| globals, "x" |), + Constant.int 0 + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.get_name (| globals, "result" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). diff --git a/CoqOfPython/ethereum/homestead/vm/instructions/control_flow.v b/CoqOfPython/ethereum/homestead/vm/instructions/control_flow.v new file mode 100644 index 0000000..80e73c8 --- /dev/null +++ b/CoqOfPython/ethereum/homestead/vm/instructions/control_flow.v @@ -0,0 +1,350 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.homestead.vm.instructions.control_flow". + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) Control Flow Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM control flow instructions. +". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". + +Axiom ethereum_homestead_vm_gas_imports_GAS_BASE : + IsImported globals "ethereum.homestead.vm.gas" "GAS_BASE". +Axiom ethereum_homestead_vm_gas_imports_GAS_HIGH : + IsImported globals "ethereum.homestead.vm.gas" "GAS_HIGH". +Axiom ethereum_homestead_vm_gas_imports_GAS_JUMPDEST : + IsImported globals "ethereum.homestead.vm.gas" "GAS_JUMPDEST". +Axiom ethereum_homestead_vm_gas_imports_GAS_MID : + IsImported globals "ethereum.homestead.vm.gas" "GAS_MID". +Axiom ethereum_homestead_vm_gas_imports_charge_gas : + IsImported globals "ethereum.homestead.vm.gas" "charge_gas". + +Axiom ethereum_homestead_vm_imports_Evm : + IsImported globals "ethereum.homestead.vm" "Evm". + +Axiom ethereum_homestead_vm_exceptions_imports_InvalidJumpDestError : + IsImported globals "ethereum.homestead.vm.exceptions" "InvalidJumpDestError". + +Axiom ethereum_homestead_vm_stack_imports_pop : + IsImported globals "ethereum.homestead.vm.stack" "pop". +Axiom ethereum_homestead_vm_stack_imports_push : + IsImported globals "ethereum.homestead.vm.stack" "push". + +Definition stop : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Stop further execution of EVM code. + + Parameters + ---------- + evm : + The current EVM frame. + " in + let _ := M.pass (| |) in + let _ := M.pass (| |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, "evm" |), "running" |), + Constant.bool false + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition jump : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Alter the program counter to the location specified by the top of the + stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "jump_dest" , + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_MID" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.not_in (| + M.get_name (| globals, "jump_dest" |), + M.get_field (| M.get_name (| globals, "evm" |), "valid_jump_destinations" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, "InvalidJumpDestError" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.get_name (| globals, "jump_dest" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Definition jumpi : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Alter the program counter to the specified location if and only if a + condition is true. If the condition is not true, then the program counter + would increase only by 1. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "jump_dest" , + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "conditional_value" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_HIGH" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, "conditional_value" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "destination" , + BinOp.add (| + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + Compare.not_in (| + M.get_name (| globals, "jump_dest" |), + M.get_field (| M.get_name (| globals, "evm" |), "valid_jump_destinations" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, "InvalidJumpDestError" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "destination" , + M.get_name (| globals, "jump_dest" |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )) |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.get_name (| globals, "destination" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Definition pc : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Push onto the stack the value of the program counter after reaching the + current instruction and without increasing it for the next instruction. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_BASE" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "pc" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition gas_left : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Push the amount of available gas (including the corresponding reduction + for the cost of this instruction) onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_BASE" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "gas_left" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition jumpdest : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Mark a valid destination for jumps. This is a noop, present only + to be used by `JUMP` and `JUMPI` opcodes to verify that their jump is + valid. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_JUMPDEST" |) + ], + make_dict [] + |) in + let _ := M.pass (| |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). diff --git a/CoqOfPython/ethereum/homestead/vm/instructions/environment.v b/CoqOfPython/ethereum/homestead/vm/instructions/environment.v new file mode 100644 index 0000000..d7f3281 --- /dev/null +++ b/CoqOfPython/ethereum/homestead/vm/instructions/environment.v @@ -0,0 +1,993 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.homestead.vm.instructions.environment". + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) Environmental Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM environment related instructions. +". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". + +Axiom ethereum_utils_numeric_imports_ceil32 : + IsImported globals "ethereum.utils.numeric" "ceil32". + +Axiom ethereum_homestead_state_imports_get_account : + IsImported globals "ethereum.homestead.state" "get_account". + +Axiom ethereum_homestead_utils_address_imports_to_address : + IsImported globals "ethereum.homestead.utils.address" "to_address". + +Axiom ethereum_homestead_vm_memory_imports_buffer_read : + IsImported globals "ethereum.homestead.vm.memory" "buffer_read". +Axiom ethereum_homestead_vm_memory_imports_memory_write : + IsImported globals "ethereum.homestead.vm.memory" "memory_write". + +Axiom ethereum_homestead_vm_imports_Evm : + IsImported globals "ethereum.homestead.vm" "Evm". + +Axiom ethereum_homestead_vm_gas_imports_GAS_BALANCE : + IsImported globals "ethereum.homestead.vm.gas" "GAS_BALANCE". +Axiom ethereum_homestead_vm_gas_imports_GAS_BASE : + IsImported globals "ethereum.homestead.vm.gas" "GAS_BASE". +Axiom ethereum_homestead_vm_gas_imports_GAS_COPY : + IsImported globals "ethereum.homestead.vm.gas" "GAS_COPY". +Axiom ethereum_homestead_vm_gas_imports_GAS_EXTERNAL : + IsImported globals "ethereum.homestead.vm.gas" "GAS_EXTERNAL". +Axiom ethereum_homestead_vm_gas_imports_GAS_VERY_LOW : + IsImported globals "ethereum.homestead.vm.gas" "GAS_VERY_LOW". +Axiom ethereum_homestead_vm_gas_imports_calculate_gas_extend_memory : + IsImported globals "ethereum.homestead.vm.gas" "calculate_gas_extend_memory". +Axiom ethereum_homestead_vm_gas_imports_charge_gas : + IsImported globals "ethereum.homestead.vm.gas" "charge_gas". + +Axiom ethereum_homestead_vm_stack_imports_pop : + IsImported globals "ethereum.homestead.vm.stack" "pop". +Axiom ethereum_homestead_vm_stack_imports_push : + IsImported globals "ethereum.homestead.vm.stack" "push". + +Definition address : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Pushes the address of the current executing account to the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_BASE" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.call (| + M.get_field (| M.get_name (| globals, "U256" |), "from_be_bytes" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "current_target" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition balance : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Pushes the balance of the given account onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "address" , + M.call (| + M.get_name (| globals, "to_address" |), + make_list [ + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_BALANCE" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "balance" , + M.get_field (| M.call (| + M.get_name (| globals, "get_account" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "env" |), "state" |); + M.get_name (| globals, "address" |) + ], + make_dict [] + |), "balance" |) + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.get_name (| globals, "balance" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition origin : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Pushes the address of the original transaction sender to the stack. + The origin address can only be an EOA. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_BASE" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.call (| + M.get_field (| M.get_name (| globals, "U256" |), "from_be_bytes" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "env" |), "origin" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition caller : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Pushes the address of the caller onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_BASE" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.call (| + M.get_field (| M.get_name (| globals, "U256" |), "from_be_bytes" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "caller" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition callvalue : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Push the value (in wei) sent with the call onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_BASE" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "value" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition calldataload : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Push a word (32 bytes) of the input data belonging to the current + environment onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "start_index" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_VERY_LOW" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "value" , + M.call (| + M.get_name (| globals, "buffer_read" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "data" |); + M.get_name (| globals, "start_index" |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 32 + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.call (| + M.get_field (| M.get_name (| globals, "U256" |), "from_be_bytes" |), + make_list [ + M.get_name (| globals, "value" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition calldatasize : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Push the size of input data in current environment onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_BASE" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "data" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition calldatacopy : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Copy a portion of the input data in current environment to memory. + + This will also expand the memory, in case that the memory is insufficient + to store the data. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "memory_start_index" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "data_start_index" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "size" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "words" , + BinOp.floor_div (| + M.call (| + M.get_name (| globals, "ceil32" |), + make_list [ + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.get_name (| globals, "size" |) + ], + make_dict [] + |) + ], + make_dict [] + |), + Constant.int 32 + |) + |) in + let _ := M.assign_local (| + "copy_gas_cost" , + BinOp.mult (| + M.get_name (| globals, "GAS_COPY" |), + M.get_name (| globals, "words" |) + |) + |) in + let _ := M.assign_local (| + "extend_memory" , + M.call (| + M.get_name (| globals, "calculate_gas_extend_memory" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "memory" |); + make_list [ + make_tuple [ M.get_name (| globals, "memory_start_index" |); M.get_name (| globals, "size" |) ] + ] + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + BinOp.add (| + BinOp.add (| + M.get_name (| globals, "GAS_VERY_LOW" |), + M.get_name (| globals, "copy_gas_cost" |) + |), + M.get_field (| M.get_name (| globals, "extend_memory" |), "cost" |) + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "memory" |), + BinOp.mult (| + Constant.bytes "00", + M.get_field (| M.get_name (| globals, "extend_memory" |), "expand_by" |) + |) + |) in + let _ := M.assign_local (| + "value" , + M.call (| + M.get_name (| globals, "buffer_read" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "data" |); + M.get_name (| globals, "data_start_index" |); + M.get_name (| globals, "size" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "memory_write" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "memory" |); + M.get_name (| globals, "memory_start_index" |); + M.get_name (| globals, "value" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition codesize : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Push the size of code running in current environment onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_BASE" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "code" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition codecopy : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Copy a portion of the code in current environment to memory. + + This will also expand the memory, in case that the memory is insufficient + to store the data. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "memory_start_index" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "code_start_index" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "size" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "words" , + BinOp.floor_div (| + M.call (| + M.get_name (| globals, "ceil32" |), + make_list [ + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.get_name (| globals, "size" |) + ], + make_dict [] + |) + ], + make_dict [] + |), + Constant.int 32 + |) + |) in + let _ := M.assign_local (| + "copy_gas_cost" , + BinOp.mult (| + M.get_name (| globals, "GAS_COPY" |), + M.get_name (| globals, "words" |) + |) + |) in + let _ := M.assign_local (| + "extend_memory" , + M.call (| + M.get_name (| globals, "calculate_gas_extend_memory" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "memory" |); + make_list [ + make_tuple [ M.get_name (| globals, "memory_start_index" |); M.get_name (| globals, "size" |) ] + ] + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + BinOp.add (| + BinOp.add (| + M.get_name (| globals, "GAS_VERY_LOW" |), + M.get_name (| globals, "copy_gas_cost" |) + |), + M.get_field (| M.get_name (| globals, "extend_memory" |), "cost" |) + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "memory" |), + BinOp.mult (| + Constant.bytes "00", + M.get_field (| M.get_name (| globals, "extend_memory" |), "expand_by" |) + |) + |) in + let _ := M.assign_local (| + "value" , + M.call (| + M.get_name (| globals, "buffer_read" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "code" |); + M.get_name (| globals, "code_start_index" |); + M.get_name (| globals, "size" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "memory_write" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "memory" |); + M.get_name (| globals, "memory_start_index" |); + M.get_name (| globals, "value" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition gasprice : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Push the gas price used in current environment onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_BASE" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "env" |), "gas_price" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition extcodesize : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Push the code size of a given account onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "address" , + M.call (| + M.get_name (| globals, "to_address" |), + make_list [ + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_EXTERNAL" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "codesize" , + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_field (| M.call (| + M.get_name (| globals, "get_account" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "env" |), "state" |); + M.get_name (| globals, "address" |) + ], + make_dict [] + |), "code" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.get_name (| globals, "codesize" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition extcodecopy : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Copy a portion of an account's code to memory. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "address" , + M.call (| + M.get_name (| globals, "to_address" |), + make_list [ + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_start_index" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "code_start_index" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "size" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "words" , + BinOp.floor_div (| + M.call (| + M.get_name (| globals, "ceil32" |), + make_list [ + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.get_name (| globals, "size" |) + ], + make_dict [] + |) + ], + make_dict [] + |), + Constant.int 32 + |) + |) in + let _ := M.assign_local (| + "copy_gas_cost" , + BinOp.mult (| + M.get_name (| globals, "GAS_COPY" |), + M.get_name (| globals, "words" |) + |) + |) in + let _ := M.assign_local (| + "extend_memory" , + M.call (| + M.get_name (| globals, "calculate_gas_extend_memory" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "memory" |); + make_list [ + make_tuple [ M.get_name (| globals, "memory_start_index" |); M.get_name (| globals, "size" |) ] + ] + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + BinOp.add (| + BinOp.add (| + M.get_name (| globals, "GAS_EXTERNAL" |), + M.get_name (| globals, "copy_gas_cost" |) + |), + M.get_field (| M.get_name (| globals, "extend_memory" |), "cost" |) + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "memory" |), + BinOp.mult (| + Constant.bytes "00", + M.get_field (| M.get_name (| globals, "extend_memory" |), "expand_by" |) + |) + |) in + let _ := M.assign_local (| + "code" , + M.get_field (| M.call (| + M.get_name (| globals, "get_account" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "env" |), "state" |); + M.get_name (| globals, "address" |) + ], + make_dict [] + |), "code" |) + |) in + let _ := M.assign_local (| + "value" , + M.call (| + M.get_name (| globals, "buffer_read" |), + make_list [ + M.get_name (| globals, "code" |); + M.get_name (| globals, "code_start_index" |); + M.get_name (| globals, "size" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "memory_write" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "memory" |); + M.get_name (| globals, "memory_start_index" |); + M.get_name (| globals, "value" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). diff --git a/CoqOfPython/ethereum/homestead/vm/instructions/keccak.v b/CoqOfPython/ethereum/homestead/vm/instructions/keccak.v new file mode 100644 index 0000000..6e22190 --- /dev/null +++ b/CoqOfPython/ethereum/homestead/vm/instructions/keccak.v @@ -0,0 +1,188 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.homestead.vm.instructions.keccak". + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) Keccak Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM keccak instructions. +". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". + +Axiom ethereum_crypto_hash_imports_keccak256 : + IsImported globals "ethereum.crypto.hash" "keccak256". + +Axiom ethereum_utils_numeric_imports_ceil32 : + IsImported globals "ethereum.utils.numeric" "ceil32". + +Axiom ethereum_homestead_vm_imports_Evm : + IsImported globals "ethereum.homestead.vm" "Evm". + +Axiom ethereum_homestead_vm_gas_imports_GAS_KECCAK256 : + IsImported globals "ethereum.homestead.vm.gas" "GAS_KECCAK256". +Axiom ethereum_homestead_vm_gas_imports_GAS_KECCAK256_WORD : + IsImported globals "ethereum.homestead.vm.gas" "GAS_KECCAK256_WORD". +Axiom ethereum_homestead_vm_gas_imports_calculate_gas_extend_memory : + IsImported globals "ethereum.homestead.vm.gas" "calculate_gas_extend_memory". +Axiom ethereum_homestead_vm_gas_imports_charge_gas : + IsImported globals "ethereum.homestead.vm.gas" "charge_gas". + +Axiom ethereum_homestead_vm_memory_imports_memory_read_bytes : + IsImported globals "ethereum.homestead.vm.memory" "memory_read_bytes". + +Axiom ethereum_homestead_vm_stack_imports_pop : + IsImported globals "ethereum.homestead.vm.stack" "pop". +Axiom ethereum_homestead_vm_stack_imports_push : + IsImported globals "ethereum.homestead.vm.stack" "push". + +Definition keccak : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Pushes to the stack the Keccak-256 hash of a region of memory. + + This also expands the memory, in case the memory is insufficient to + access the data's memory location. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "memory_start_index" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "size" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "words" , + BinOp.floor_div (| + M.call (| + M.get_name (| globals, "ceil32" |), + make_list [ + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.get_name (| globals, "size" |) + ], + make_dict [] + |) + ], + make_dict [] + |), + Constant.int 32 + |) + |) in + let _ := M.assign_local (| + "word_gas_cost" , + BinOp.mult (| + M.get_name (| globals, "GAS_KECCAK256_WORD" |), + M.get_name (| globals, "words" |) + |) + |) in + let _ := M.assign_local (| + "extend_memory" , + M.call (| + M.get_name (| globals, "calculate_gas_extend_memory" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "memory" |); + make_list [ + make_tuple [ M.get_name (| globals, "memory_start_index" |); M.get_name (| globals, "size" |) ] + ] + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + BinOp.add (| + BinOp.add (| + M.get_name (| globals, "GAS_KECCAK256" |), + M.get_name (| globals, "word_gas_cost" |) + |), + M.get_field (| M.get_name (| globals, "extend_memory" |), "cost" |) + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "memory" |), + BinOp.mult (| + Constant.bytes "00", + M.get_field (| M.get_name (| globals, "extend_memory" |), "expand_by" |) + |) + |) in + let _ := M.assign_local (| + "data" , + M.call (| + M.get_name (| globals, "memory_read_bytes" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "memory" |); + M.get_name (| globals, "memory_start_index" |); + M.get_name (| globals, "size" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "hash" , + M.call (| + M.get_name (| globals, "keccak256" |), + make_list [ + M.get_name (| globals, "data" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.call (| + M.get_field (| M.get_name (| globals, "U256" |), "from_be_bytes" |), + make_list [ + M.get_name (| globals, "hash" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). diff --git a/CoqOfPython/ethereum/homestead/vm/instructions/log.v b/CoqOfPython/ethereum/homestead/vm/instructions/log.v new file mode 100644 index 0000000..7780f07 --- /dev/null +++ b/CoqOfPython/ethereum/homestead/vm/instructions/log.v @@ -0,0 +1,242 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.homestead.vm.instructions.log". + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) Logging Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM logging instructions. +". + +Axiom functools_imports_partial : + IsImported globals "functools" "partial". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". + +Axiom ethereum_homestead_blocks_imports_Log : + IsImported globals "ethereum.homestead.blocks" "Log". + +Axiom ethereum_homestead_vm_imports_Evm : + IsImported globals "ethereum.homestead.vm" "Evm". + +Axiom ethereum_homestead_vm_gas_imports_GAS_LOG : + IsImported globals "ethereum.homestead.vm.gas" "GAS_LOG". +Axiom ethereum_homestead_vm_gas_imports_GAS_LOG_DATA : + IsImported globals "ethereum.homestead.vm.gas" "GAS_LOG_DATA". +Axiom ethereum_homestead_vm_gas_imports_GAS_LOG_TOPIC : + IsImported globals "ethereum.homestead.vm.gas" "GAS_LOG_TOPIC". +Axiom ethereum_homestead_vm_gas_imports_calculate_gas_extend_memory : + IsImported globals "ethereum.homestead.vm.gas" "calculate_gas_extend_memory". +Axiom ethereum_homestead_vm_gas_imports_charge_gas : + IsImported globals "ethereum.homestead.vm.gas" "charge_gas". + +Axiom ethereum_homestead_vm_memory_imports_memory_read_bytes : + IsImported globals "ethereum.homestead.vm.memory" "memory_read_bytes". + +Axiom ethereum_homestead_vm_stack_imports_pop : + IsImported globals "ethereum.homestead.vm.stack" "pop". + +Definition log_n : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm"; "num_topics" ] |) in + let _ := Constant.str " + Appends a log entry, having `num_topics` topics, to the evm logs. + + This will also expand the memory if the data (required by the log entry) + corresponding to the memory is not accessible. + + Parameters + ---------- + evm : + The current EVM frame. + num_topics : + The number of topics to be included in the log entry. + + " in + let _ := M.assign_local (| + "memory_start_index" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "size" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "topics" , + make_list [] + |) in + let _ := + M.for_ (| + M.get_name (| globals, "_" |), + M.call (| + M.get_name (| globals, "range" |), + make_list [ + M.get_name (| globals, "num_topics" |) + ], + make_dict [] + |), + ltac:(M.monadic ( + let _ := M.assign_local (| + "topic" , + M.call (| + M.get_field (| M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |), "to_be_bytes32" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_field (| M.get_name (| globals, "topics" |), "append" |), + make_list [ + M.get_name (| globals, "topic" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := M.assign_local (| + "extend_memory" , + M.call (| + M.get_name (| globals, "calculate_gas_extend_memory" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "memory" |); + make_list [ + make_tuple [ M.get_name (| globals, "memory_start_index" |); M.get_name (| globals, "size" |) ] + ] + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + BinOp.add (| + BinOp.add (| + BinOp.add (| + M.get_name (| globals, "GAS_LOG" |), + BinOp.mult (| + M.get_name (| globals, "GAS_LOG_DATA" |), + M.get_name (| globals, "size" |) + |) + |), + BinOp.mult (| + M.get_name (| globals, "GAS_LOG_TOPIC" |), + M.get_name (| globals, "num_topics" |) + |) + |), + M.get_field (| M.get_name (| globals, "extend_memory" |), "cost" |) + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "memory" |), + BinOp.mult (| + Constant.bytes "00", + M.get_field (| M.get_name (| globals, "extend_memory" |), "expand_by" |) + |) + |) in + let _ := M.assign_local (| + "log_entry" , + M.call (| + M.get_name (| globals, "Log" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, "evm" |), "logs" |), + BinOp.add (| + M.get_field (| M.get_name (| globals, "evm" |), "logs" |), + make_tuple [ M.get_name (| globals, "log_entry" |) ] + |) + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition log0 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "log_n" |) + ], + make_dict [] + |) +)). + +Definition log1 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "log_n" |) + ], + make_dict [] + |) +)). + +Definition log2 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "log_n" |) + ], + make_dict [] + |) +)). + +Definition log3 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "log_n" |) + ], + make_dict [] + |) +)). + +Definition log4 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "log_n" |) + ], + make_dict [] + |) +)). diff --git a/CoqOfPython/ethereum/homestead/vm/instructions/memory.v b/CoqOfPython/ethereum/homestead/vm/instructions/memory.v new file mode 100644 index 0000000..e8029f0 --- /dev/null +++ b/CoqOfPython/ethereum/homestead/vm/instructions/memory.v @@ -0,0 +1,393 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.homestead.vm.instructions.memory". + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) Memory Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM Memory instructions. +". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_Bytes : + IsImported globals "ethereum.base_types" "Bytes". + +Axiom ethereum_homestead_vm_imports_Evm : + IsImported globals "ethereum.homestead.vm" "Evm". + +Axiom ethereum_homestead_vm_gas_imports_GAS_BASE : + IsImported globals "ethereum.homestead.vm.gas" "GAS_BASE". +Axiom ethereum_homestead_vm_gas_imports_GAS_VERY_LOW : + IsImported globals "ethereum.homestead.vm.gas" "GAS_VERY_LOW". +Axiom ethereum_homestead_vm_gas_imports_calculate_gas_extend_memory : + IsImported globals "ethereum.homestead.vm.gas" "calculate_gas_extend_memory". +Axiom ethereum_homestead_vm_gas_imports_charge_gas : + IsImported globals "ethereum.homestead.vm.gas" "charge_gas". + +Axiom ethereum_homestead_vm_memory_imports_memory_read_bytes : + IsImported globals "ethereum.homestead.vm.memory" "memory_read_bytes". +Axiom ethereum_homestead_vm_memory_imports_memory_write : + IsImported globals "ethereum.homestead.vm.memory" "memory_write". + +Axiom ethereum_homestead_vm_stack_imports_pop : + IsImported globals "ethereum.homestead.vm.stack" "pop". +Axiom ethereum_homestead_vm_stack_imports_push : + IsImported globals "ethereum.homestead.vm.stack" "push". + +Definition mstore : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Stores a word to memory. + This also expands the memory, if the memory is + insufficient to store the word. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "start_position" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "value" , + M.call (| + M.get_field (| M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |), "to_be_bytes32" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "extend_memory" , + M.call (| + M.get_name (| globals, "calculate_gas_extend_memory" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "memory" |); + make_list [ + make_tuple [ M.get_name (| globals, "start_position" |); M.call (| + M.get_name (| globals, "U256" |), + make_list [ + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_name (| globals, "value" |) + ], + make_dict [] + |) + ], + make_dict [] + |) ] + ] + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + BinOp.add (| + M.get_name (| globals, "GAS_VERY_LOW" |), + M.get_field (| M.get_name (| globals, "extend_memory" |), "cost" |) + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "memory" |), + BinOp.mult (| + Constant.bytes "00", + M.get_field (| M.get_name (| globals, "extend_memory" |), "expand_by" |) + |) + |) in + let _ := M.call (| + M.get_name (| globals, "memory_write" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "memory" |); + M.get_name (| globals, "start_position" |); + M.get_name (| globals, "value" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition mstore8 : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Stores a byte to memory. + This also expands the memory, if the memory is + insufficient to store the word. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "start_position" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "value" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "extend_memory" , + M.call (| + M.get_name (| globals, "calculate_gas_extend_memory" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "memory" |); + make_list [ + make_tuple [ M.get_name (| globals, "start_position" |); M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 1 + ], + make_dict [] + |) ] + ] + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + BinOp.add (| + M.get_name (| globals, "GAS_VERY_LOW" |), + M.get_field (| M.get_name (| globals, "extend_memory" |), "cost" |) + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "memory" |), + BinOp.mult (| + Constant.bytes "00", + M.get_field (| M.get_name (| globals, "extend_memory" |), "expand_by" |) + |) + |) in + let _ := M.assign_local (| + "normalized_bytes_value" , + M.call (| + M.get_name (| globals, "Bytes" |), + make_list [ + make_list [ + BinOp.bit_and (| + M.get_name (| globals, "value" |), + Constant.int 255 + |) + ] + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "memory_write" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "memory" |); + M.get_name (| globals, "start_position" |); + M.get_name (| globals, "normalized_bytes_value" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition mload : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Load word from memory. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "start_position" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "extend_memory" , + M.call (| + M.get_name (| globals, "calculate_gas_extend_memory" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "memory" |); + make_list [ + make_tuple [ M.get_name (| globals, "start_position" |); M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 32 + ], + make_dict [] + |) ] + ] + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + BinOp.add (| + M.get_name (| globals, "GAS_VERY_LOW" |), + M.get_field (| M.get_name (| globals, "extend_memory" |), "cost" |) + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "memory" |), + BinOp.mult (| + Constant.bytes "00", + M.get_field (| M.get_name (| globals, "extend_memory" |), "expand_by" |) + |) + |) in + let _ := M.assign_local (| + "value" , + M.call (| + M.get_field (| M.get_name (| globals, "U256" |), "from_be_bytes" |), + make_list [ + M.call (| + M.get_name (| globals, "memory_read_bytes" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "memory" |); + M.get_name (| globals, "start_position" |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 32 + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.get_name (| globals, "value" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition msize : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Push the size of active memory in bytes onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_BASE" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "memory" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). diff --git a/CoqOfPython/ethereum/homestead/vm/instructions/stack.v b/CoqOfPython/ethereum/homestead/vm/instructions/stack.v new file mode 100644 index 0000000..dbfa9fb --- /dev/null +++ b/CoqOfPython/ethereum/homestead/vm/instructions/stack.v @@ -0,0 +1,947 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.homestead.vm.instructions.stack". + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) Stack Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM stack related instructions. +". + +Axiom functools_imports_partial : + IsImported globals "functools" "partial". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". + +Axiom ethereum_utils_ensure_imports_ensure : + IsImported globals "ethereum.utils.ensure" "ensure". + +Axiom ethereum_homestead_vm_imports_Evm : + IsImported globals "ethereum.homestead.vm" "Evm". +Axiom ethereum_homestead_vm_imports_stack : + IsImported globals "ethereum.homestead.vm" "stack". + +Axiom ethereum_homestead_vm_exceptions_imports_StackUnderflowError : + IsImported globals "ethereum.homestead.vm.exceptions" "StackUnderflowError". + +Axiom ethereum_homestead_vm_gas_imports_GAS_BASE : + IsImported globals "ethereum.homestead.vm.gas" "GAS_BASE". +Axiom ethereum_homestead_vm_gas_imports_GAS_VERY_LOW : + IsImported globals "ethereum.homestead.vm.gas" "GAS_VERY_LOW". +Axiom ethereum_homestead_vm_gas_imports_charge_gas : + IsImported globals "ethereum.homestead.vm.gas" "charge_gas". + +Axiom ethereum_homestead_vm_memory_imports_buffer_read : + IsImported globals "ethereum.homestead.vm.memory" "buffer_read". + +Definition pop : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Remove item from stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.call (| + M.get_field (| M.get_name (| globals, "stack" |), "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_BASE" |) + ], + make_dict [] + |) in + let _ := M.pass (| |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition push_n : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm"; "num_bytes" ] |) in + let _ := Constant.str " + Pushes a N-byte immediate onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + num_bytes : + The number of immediate bytes to be read from the code and pushed to + the stack. + + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_VERY_LOW" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "data_to_push" , + M.call (| + M.get_field (| M.get_name (| globals, "U256" |), "from_be_bytes" |), + make_list [ + M.call (| + M.get_name (| globals, "buffer_read" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "code" |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + BinOp.add (| + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) + ], + make_dict [] + |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + M.get_name (| globals, "num_bytes" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_field (| M.get_name (| globals, "stack" |), "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.get_name (| globals, "data_to_push" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + BinOp.add (| + Constant.int 1, + M.get_name (| globals, "num_bytes" |) + |) + |) in + M.pure Constant.None_)). + +Definition dup_n : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm"; "item_number" ] |) in + let _ := Constant.str " + Duplicate the Nth stack item (from top of the stack) to the top of stack. + + Parameters + ---------- + evm : + The current EVM frame. + + item_number : + The stack item number (0-indexed from top of stack) to be duplicated + to the top of stack. + + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_VERY_LOW" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + Compare.lt (| + M.get_name (| globals, "item_number" |), + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |); + M.get_name (| globals, "StackUnderflowError" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "data_to_duplicate" , + M.get_subscript (| + M.get_field (| M.get_name (| globals, "evm" |), "stack" |), + BinOp.sub (| + BinOp.sub (| + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |), + Constant.int 1 + |), + M.get_name (| globals, "item_number" |) + |) + |) + |) in + let _ := M.call (| + M.get_field (| M.get_name (| globals, "stack" |), "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.get_name (| globals, "data_to_duplicate" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition swap_n : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm"; "item_number" ] |) in + let _ := Constant.str " + Swap the top and the `item_number` element of the stack, where + the top of the stack is position zero. + + If `item_number` is zero, this function does nothing (which should not be + possible, since there is no `SWAP0` instruction). + + Parameters + ---------- + evm : + The current EVM frame. + + item_number : + The stack item number (0-indexed from top of stack) to be swapped + with the top of stack element. + + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_VERY_LOW" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + Compare.lt (| + M.get_name (| globals, "item_number" |), + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |); + M.get_name (| globals, "StackUnderflowError" |) + ], + make_dict [] + |) in + let _ := M.assign (| + make_tuple [ M.get_subscript (| + M.get_field (| M.get_name (| globals, "evm" |), "stack" |), + UnOp.sub (| Constant.int 1 |) + |); M.get_subscript (| + M.get_field (| M.get_name (| globals, "evm" |), "stack" |), + BinOp.sub (| + UnOp.sub (| Constant.int 1 |), + M.get_name (| globals, "item_number" |) + |) + |) ], + make_tuple [ M.get_subscript (| + M.get_field (| M.get_name (| globals, "evm" |), "stack" |), + BinOp.sub (| + UnOp.sub (| Constant.int 1 |), + M.get_name (| globals, "item_number" |) + |) + |); M.get_subscript (| + M.get_field (| M.get_name (| globals, "evm" |), "stack" |), + UnOp.sub (| Constant.int 1 |) + |) ] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition push1 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push2 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push3 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push4 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push5 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push6 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push7 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push8 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push9 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push10 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push11 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push12 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push13 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push14 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push15 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push16 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push17 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push18 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push19 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push20 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push21 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push22 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push23 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push24 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push25 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push26 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push27 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push28 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push29 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push30 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push31 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push32 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "push_n" |) + ], + make_dict [] + |) +)). + +Definition dup1 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "dup_n" |) + ], + make_dict [] + |) +)). + +Definition dup2 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "dup_n" |) + ], + make_dict [] + |) +)). + +Definition dup3 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "dup_n" |) + ], + make_dict [] + |) +)). + +Definition dup4 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "dup_n" |) + ], + make_dict [] + |) +)). + +Definition dup5 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "dup_n" |) + ], + make_dict [] + |) +)). + +Definition dup6 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "dup_n" |) + ], + make_dict [] + |) +)). + +Definition dup7 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "dup_n" |) + ], + make_dict [] + |) +)). + +Definition dup8 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "dup_n" |) + ], + make_dict [] + |) +)). + +Definition dup9 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "dup_n" |) + ], + make_dict [] + |) +)). + +Definition dup10 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "dup_n" |) + ], + make_dict [] + |) +)). + +Definition dup11 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "dup_n" |) + ], + make_dict [] + |) +)). + +Definition dup12 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "dup_n" |) + ], + make_dict [] + |) +)). + +Definition dup13 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "dup_n" |) + ], + make_dict [] + |) +)). + +Definition dup14 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "dup_n" |) + ], + make_dict [] + |) +)). + +Definition dup15 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "dup_n" |) + ], + make_dict [] + |) +)). + +Definition dup16 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "dup_n" |) + ], + make_dict [] + |) +)). + +Definition swap1 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "swap_n" |) + ], + make_dict [] + |) +)). + +Definition swap2 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "swap_n" |) + ], + make_dict [] + |) +)). + +Definition swap3 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "swap_n" |) + ], + make_dict [] + |) +)). + +Definition swap4 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "swap_n" |) + ], + make_dict [] + |) +)). + +Definition swap5 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "swap_n" |) + ], + make_dict [] + |) +)). + +Definition swap6 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "swap_n" |) + ], + make_dict [] + |) +)). + +Definition swap7 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "swap_n" |) + ], + make_dict [] + |) +)). + +Definition swap8 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "swap_n" |) + ], + make_dict [] + |) +)). + +Definition swap9 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "swap_n" |) + ], + make_dict [] + |) +)). + +Definition swap10 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "swap_n" |) + ], + make_dict [] + |) +)). + +Definition swap11 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "swap_n" |) + ], + make_dict [] + |) +)). + +Definition swap12 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "swap_n" |) + ], + make_dict [] + |) +)). + +Definition swap13 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "swap_n" |) + ], + make_dict [] + |) +)). + +Definition swap14 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "swap_n" |) + ], + make_dict [] + |) +)). + +Definition swap15 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "swap_n" |) + ], + make_dict [] + |) +)). + +Definition swap16 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "swap_n" |) + ], + make_dict [] + |) +)). diff --git a/CoqOfPython/ethereum/homestead/vm/instructions/storage.v b/CoqOfPython/ethereum/homestead/vm/instructions/storage.v new file mode 100644 index 0000000..aa3f335 --- /dev/null +++ b/CoqOfPython/ethereum/homestead/vm/instructions/storage.v @@ -0,0 +1,234 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.homestead.vm.instructions.storage". + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) Storage Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM storage related instructions. +". + +Axiom ethereum_homestead_state_imports_get_storage : + IsImported globals "ethereum.homestead.state" "get_storage". +Axiom ethereum_homestead_state_imports_set_storage : + IsImported globals "ethereum.homestead.state" "set_storage". + +Axiom ethereum_homestead_vm_imports_Evm : + IsImported globals "ethereum.homestead.vm" "Evm". + +Axiom ethereum_homestead_vm_gas_imports_GAS_SLOAD : + IsImported globals "ethereum.homestead.vm.gas" "GAS_SLOAD". +Axiom ethereum_homestead_vm_gas_imports_GAS_STORAGE_CLEAR_REFUND : + IsImported globals "ethereum.homestead.vm.gas" "GAS_STORAGE_CLEAR_REFUND". +Axiom ethereum_homestead_vm_gas_imports_GAS_STORAGE_SET : + IsImported globals "ethereum.homestead.vm.gas" "GAS_STORAGE_SET". +Axiom ethereum_homestead_vm_gas_imports_GAS_STORAGE_UPDATE : + IsImported globals "ethereum.homestead.vm.gas" "GAS_STORAGE_UPDATE". +Axiom ethereum_homestead_vm_gas_imports_charge_gas : + IsImported globals "ethereum.homestead.vm.gas" "charge_gas". + +Axiom ethereum_homestead_vm_stack_imports_pop : + IsImported globals "ethereum.homestead.vm.stack" "pop". +Axiom ethereum_homestead_vm_stack_imports_push : + IsImported globals "ethereum.homestead.vm.stack" "push". + +Definition sload : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Loads to the stack, the value corresponding to a certain key from the + storage of the current account. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "key" , + M.call (| + M.get_field (| M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |), "to_be_bytes32" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_SLOAD" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "value" , + M.call (| + M.get_name (| globals, "get_storage" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "env" |), "state" |); + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "current_target" |); + M.get_name (| globals, "key" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.get_name (| globals, "value" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition sstore : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Stores a value at a certain key in the current context's storage. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "key" , + M.call (| + M.get_field (| M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |), "to_be_bytes32" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "new_value" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "current_value" , + M.call (| + M.get_name (| globals, "get_storage" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "env" |), "state" |); + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "current_target" |); + M.get_name (| globals, "key" |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + BoolOp.and (| + Compare.not_eq (| + M.get_name (| globals, "new_value" |), + Constant.int 0 + |), + ltac:(M.monadic ( + Compare.eq (| + M.get_name (| globals, "current_value" |), + Constant.int 0 + |) + )) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "gas_cost" , + M.get_name (| globals, "GAS_STORAGE_SET" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "gas_cost" , + M.get_name (| globals, "GAS_STORAGE_UPDATE" |) + |) in + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + BoolOp.and (| + Compare.eq (| + M.get_name (| globals, "new_value" |), + Constant.int 0 + |), + ltac:(M.monadic ( + Compare.not_eq (| + M.get_name (| globals, "current_value" |), + Constant.int 0 + |) + )) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "refund_counter" |), + M.get_name (| globals, "GAS_STORAGE_CLEAR_REFUND" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "gas_cost" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "set_storage" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "env" |), "state" |); + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "current_target" |); + M.get_name (| globals, "key" |); + M.get_name (| globals, "new_value" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). diff --git a/CoqOfPython/ethereum/homestead/vm/instructions/system.v b/CoqOfPython/ethereum/homestead/vm/instructions/system.v new file mode 100644 index 0000000..924bdf2 --- /dev/null +++ b/CoqOfPython/ethereum/homestead/vm/instructions/system.v @@ -0,0 +1,1384 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.homestead.vm.instructions.system". + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) System Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM system related instructions. +". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_Bytes0 : + IsImported globals "ethereum.base_types" "Bytes0". +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". + +Axiom ethereum_homestead_fork_types_imports_Address : + IsImported globals "ethereum.homestead.fork_types" "Address". + +Axiom ethereum_homestead_state_imports_account_has_code_or_nonce : + IsImported globals "ethereum.homestead.state" "account_has_code_or_nonce". +Axiom ethereum_homestead_state_imports_get_account : + IsImported globals "ethereum.homestead.state" "get_account". +Axiom ethereum_homestead_state_imports_increment_nonce : + IsImported globals "ethereum.homestead.state" "increment_nonce". +Axiom ethereum_homestead_state_imports_set_account_balance : + IsImported globals "ethereum.homestead.state" "set_account_balance". + +Axiom ethereum_homestead_utils_address_imports_compute_contract_address : + IsImported globals "ethereum.homestead.utils.address" "compute_contract_address". +Axiom ethereum_homestead_utils_address_imports_to_address : + IsImported globals "ethereum.homestead.utils.address" "to_address". + +Axiom ethereum_homestead_vm_imports_Evm : + IsImported globals "ethereum.homestead.vm" "Evm". +Axiom ethereum_homestead_vm_imports_Message : + IsImported globals "ethereum.homestead.vm" "Message". +Axiom ethereum_homestead_vm_imports_incorporate_child_on_error : + IsImported globals "ethereum.homestead.vm" "incorporate_child_on_error". +Axiom ethereum_homestead_vm_imports_incorporate_child_on_success : + IsImported globals "ethereum.homestead.vm" "incorporate_child_on_success". + +Axiom ethereum_homestead_vm_gas_imports_GAS_CALL : + IsImported globals "ethereum.homestead.vm.gas" "GAS_CALL". +Axiom ethereum_homestead_vm_gas_imports_GAS_CREATE : + IsImported globals "ethereum.homestead.vm.gas" "GAS_CREATE". +Axiom ethereum_homestead_vm_gas_imports_GAS_ZERO : + IsImported globals "ethereum.homestead.vm.gas" "GAS_ZERO". +Axiom ethereum_homestead_vm_gas_imports_REFUND_SELF_DESTRUCT : + IsImported globals "ethereum.homestead.vm.gas" "REFUND_SELF_DESTRUCT". +Axiom ethereum_homestead_vm_gas_imports_calculate_gas_extend_memory : + IsImported globals "ethereum.homestead.vm.gas" "calculate_gas_extend_memory". +Axiom ethereum_homestead_vm_gas_imports_calculate_message_call_gas : + IsImported globals "ethereum.homestead.vm.gas" "calculate_message_call_gas". +Axiom ethereum_homestead_vm_gas_imports_charge_gas : + IsImported globals "ethereum.homestead.vm.gas" "charge_gas". + +Axiom ethereum_homestead_vm_memory_imports_memory_read_bytes : + IsImported globals "ethereum.homestead.vm.memory" "memory_read_bytes". +Axiom ethereum_homestead_vm_memory_imports_memory_write : + IsImported globals "ethereum.homestead.vm.memory" "memory_write". + +Axiom ethereum_homestead_vm_stack_imports_pop : + IsImported globals "ethereum.homestead.vm.stack" "pop". +Axiom ethereum_homestead_vm_stack_imports_push : + IsImported globals "ethereum.homestead.vm.stack" "push". + +Definition create : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Creates a new account with associated code. + + Parameters + ---------- + evm : + The current EVM frame. + " in +(* At stmt: unsupported node type: ImportFrom *) + let _ := M.assign_local (| + "endowment" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_start_position" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_size" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "extend_memory" , + M.call (| + M.get_name (| globals, "calculate_gas_extend_memory" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "memory" |); + make_list [ + make_tuple [ M.get_name (| globals, "memory_start_position" |); M.get_name (| globals, "memory_size" |) ] + ] + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + BinOp.add (| + M.get_name (| globals, "GAS_CREATE" |), + M.get_field (| M.get_name (| globals, "extend_memory" |), "cost" |) + |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "create_message_gas" , + M.get_field (| M.get_name (| globals, "evm" |), "gas_left" |) + |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, "evm" |), "gas_left" |), + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "memory" |), + BinOp.mult (| + Constant.bytes "00", + M.get_field (| M.get_name (| globals, "extend_memory" |), "expand_by" |) + |) + |) in + let _ := M.assign_local (| + "sender_address" , + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "current_target" |) + |) in + let _ := M.assign_local (| + "sender" , + M.call (| + M.get_name (| globals, "get_account" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "env" |), "state" |); + M.get_name (| globals, "sender_address" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "contract_address" , + M.call (| + M.get_name (| globals, "compute_contract_address" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "current_target" |); + M.get_field (| M.call (| + M.get_name (| globals, "get_account" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "env" |), "state" |); + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "current_target" |) + ], + make_dict [] + |), "nonce" |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + BoolOp.or (| + Compare.lt (| + M.get_field (| M.get_name (| globals, "sender" |), "balance" |), + M.get_name (| globals, "endowment" |) + |), + ltac:(M.monadic ( + BoolOp.or (| + Compare.eq (| + M.get_field (| M.get_name (| globals, "sender" |), "nonce" |), + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + BinOp.sub (| + BinOp.pow (| + Constant.int 2, + Constant.int 64 + |), + Constant.int 1 + |) + ], + make_dict [] + |) + |), + ltac:(M.monadic ( + Compare.gt (| + BinOp.add (| + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "depth" |), + Constant.int 1 + |), + M.get_name (| globals, "STACK_DEPTH_LIMIT" |) + |) + )) + |) + )) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "gas_left" |), + M.get_name (| globals, "create_message_gas" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, "account_has_code_or_nonce" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "env" |), "state" |); + M.get_name (| globals, "contract_address" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, "increment_nonce" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "env" |), "state" |); + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "current_target" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + ], + make_dict [] + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "call_data" , + M.call (| + M.get_name (| globals, "memory_read_bytes" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "memory" |); + M.get_name (| globals, "memory_start_position" |); + M.get_name (| globals, "memory_size" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "increment_nonce" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "env" |), "state" |); + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "current_target" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "child_message" , + M.call (| + M.get_name (| globals, "Message" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "child_evm" , + M.call (| + M.get_name (| globals, "process_create_message" |), + make_list [ + M.get_name (| globals, "child_message" |); + M.get_field (| M.get_name (| globals, "evm" |), "env" |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + M.get_field (| M.get_name (| globals, "child_evm" |), "error" |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, "incorporate_child_on_error" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "child_evm" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + ], + make_dict [] + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, "incorporate_child_on_success" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "child_evm" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.call (| + M.get_field (| M.get_name (| globals, "U256" |), "from_be_bytes" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "child_evm" |), "message" |), "current_target" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )) |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition return_ : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Halts execution returning output data. + + Parameters + ---------- + evm : + The current EVM frame. + " in + let _ := M.assign_local (| + "memory_start_position" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_size" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "extend_memory" , + M.call (| + M.get_name (| globals, "calculate_gas_extend_memory" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "memory" |); + make_list [ + make_tuple [ M.get_name (| globals, "memory_start_position" |); M.get_name (| globals, "memory_size" |) ] + ] + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + BinOp.add (| + M.get_name (| globals, "GAS_ZERO" |), + M.get_field (| M.get_name (| globals, "extend_memory" |), "cost" |) + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "memory" |), + BinOp.mult (| + Constant.bytes "00", + M.get_field (| M.get_name (| globals, "extend_memory" |), "expand_by" |) + |) + |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, "evm" |), "output" |), + M.call (| + M.get_name (| globals, "memory_read_bytes" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "memory" |); + M.get_name (| globals, "memory_start_position" |); + M.get_name (| globals, "memory_size" |) + ], + make_dict [] + |) + |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, "evm" |), "running" |), + Constant.bool false + |) in + let _ := M.pass (| |) in + M.pure Constant.None_)). + +Definition generic_call : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm"; "gas"; "value"; "caller"; "to"; "code_address"; "should_transfer_value"; "memory_input_start_position"; "memory_input_size"; "memory_output_start_position"; "memory_output_size" ] |) in + let _ := Constant.str " + Perform the core logic of the `CALL*` family of opcodes. + " in +(* At stmt: unsupported node type: ImportFrom *) + let _ := + (* if *) + M.if_then_else (| + Compare.gt (| + BinOp.add (| + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "depth" |), + Constant.int 1 + |), + M.get_name (| globals, "STACK_DEPTH_LIMIT" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "gas_left" |), + M.get_name (| globals, "gas" |) + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.return_ (| + Constant.None_ + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "call_data" , + M.call (| + M.get_name (| globals, "memory_read_bytes" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "memory" |); + M.get_name (| globals, "memory_input_start_position" |); + M.get_name (| globals, "memory_input_size" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "code" , + M.get_field (| M.call (| + M.get_name (| globals, "get_account" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "env" |), "state" |); + M.get_name (| globals, "code_address" |) + ], + make_dict [] + |), "code" |) + |) in + let _ := M.assign_local (| + "child_message" , + M.call (| + M.get_name (| globals, "Message" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "child_evm" , + M.call (| + M.get_name (| globals, "process_message" |), + make_list [ + M.get_name (| globals, "child_message" |); + M.get_field (| M.get_name (| globals, "evm" |), "env" |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + M.get_field (| M.get_name (| globals, "child_evm" |), "error" |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, "incorporate_child_on_error" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "child_evm" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + ], + make_dict [] + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, "incorporate_child_on_success" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "child_evm" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 1 + ], + make_dict [] + |) + ], + make_dict [] + |) in + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "actual_output_size" , + M.call (| + M.get_name (| globals, "min" |), + make_list [ + M.get_name (| globals, "memory_output_size" |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_field (| M.get_name (| globals, "child_evm" |), "output" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "memory_write" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "memory" |); + M.get_name (| globals, "memory_output_start_position" |); + M.slice (| + M.get_field (| M.get_name (| globals, "child_evm" |), "output" |), + Constant.None_, + M.get_name (| globals, "actual_output_size" |), + Constant.None_ + |) + ], + make_dict [] + |) in + M.pure Constant.None_)). + +Definition call : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Message-call into an account. + + Parameters + ---------- + evm : + The current EVM frame. + " in + let _ := M.assign_local (| + "gas" , + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "to" , + M.call (| + M.get_name (| globals, "to_address" |), + make_list [ + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "value" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_input_start_position" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_input_size" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_output_start_position" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_output_size" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "extend_memory" , + M.call (| + M.get_name (| globals, "calculate_gas_extend_memory" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "memory" |); + make_list [ + make_tuple [ M.get_name (| globals, "memory_input_start_position" |); M.get_name (| globals, "memory_input_size" |) ]; + make_tuple [ M.get_name (| globals, "memory_output_start_position" |); M.get_name (| globals, "memory_output_size" |) ] + ] + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "message_call_gas" , + M.call (| + M.get_name (| globals, "calculate_message_call_gas" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "env" |), "state" |); + M.get_name (| globals, "gas" |); + M.get_name (| globals, "to" |); + M.get_name (| globals, "value" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + BinOp.add (| + M.get_field (| M.get_name (| globals, "message_call_gas" |), "cost" |), + M.get_field (| M.get_name (| globals, "extend_memory" |), "cost" |) + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "memory" |), + BinOp.mult (| + Constant.bytes "00", + M.get_field (| M.get_name (| globals, "extend_memory" |), "expand_by" |) + |) + |) in + let _ := M.assign_local (| + "sender_balance" , + M.get_field (| M.call (| + M.get_name (| globals, "get_account" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "env" |), "state" |); + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "current_target" |) + ], + make_dict [] + |), "balance" |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.lt (| + M.get_name (| globals, "sender_balance" |), + M.get_name (| globals, "value" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "gas_left" |), + M.get_field (| M.get_name (| globals, "message_call_gas" |), "stipend" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, "generic_call" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_field (| M.get_name (| globals, "message_call_gas" |), "stipend" |); + M.get_name (| globals, "value" |); + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "current_target" |); + M.get_name (| globals, "to" |); + M.get_name (| globals, "to" |); + Constant.bool true; + M.get_name (| globals, "memory_input_start_position" |); + M.get_name (| globals, "memory_input_size" |); + M.get_name (| globals, "memory_output_start_position" |); + M.get_name (| globals, "memory_output_size" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + )) |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition callcode : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Message-call into this account with alternative account’s code. + + Parameters + ---------- + evm : + The current EVM frame. + " in + let _ := M.assign_local (| + "gas" , + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "code_address" , + M.call (| + M.get_name (| globals, "to_address" |), + make_list [ + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "value" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_input_start_position" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_input_size" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_output_start_position" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_output_size" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "to" , + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "current_target" |) + |) in + let _ := M.assign_local (| + "extend_memory" , + M.call (| + M.get_name (| globals, "calculate_gas_extend_memory" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "memory" |); + make_list [ + make_tuple [ M.get_name (| globals, "memory_input_start_position" |); M.get_name (| globals, "memory_input_size" |) ]; + make_tuple [ M.get_name (| globals, "memory_output_start_position" |); M.get_name (| globals, "memory_output_size" |) ] + ] + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "message_call_gas" , + M.call (| + M.get_name (| globals, "calculate_message_call_gas" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "env" |), "state" |); + M.get_name (| globals, "gas" |); + M.get_name (| globals, "to" |); + M.get_name (| globals, "value" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + BinOp.add (| + M.get_field (| M.get_name (| globals, "message_call_gas" |), "cost" |), + M.get_field (| M.get_name (| globals, "extend_memory" |), "cost" |) + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "memory" |), + BinOp.mult (| + Constant.bytes "00", + M.get_field (| M.get_name (| globals, "extend_memory" |), "expand_by" |) + |) + |) in + let _ := M.assign_local (| + "sender_balance" , + M.get_field (| M.call (| + M.get_name (| globals, "get_account" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "env" |), "state" |); + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "current_target" |) + ], + make_dict [] + |), "balance" |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.lt (| + M.get_name (| globals, "sender_balance" |), + M.get_name (| globals, "value" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "gas_left" |), + M.get_field (| M.get_name (| globals, "message_call_gas" |), "stipend" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, "generic_call" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_field (| M.get_name (| globals, "message_call_gas" |), "stipend" |); + M.get_name (| globals, "value" |); + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "current_target" |); + M.get_name (| globals, "to" |); + M.get_name (| globals, "code_address" |); + Constant.bool true; + M.get_name (| globals, "memory_input_start_position" |); + M.get_name (| globals, "memory_input_size" |); + M.get_name (| globals, "memory_output_start_position" |); + M.get_name (| globals, "memory_output_size" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + )) |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition selfdestruct : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Halt execution and register account for later deletion. + + Parameters + ---------- + evm : + The current EVM frame. + " in + let _ := M.assign_local (| + "beneficiary" , + M.call (| + M.get_name (| globals, "to_address" |), + make_list [ + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "gas_cost" , + M.get_name (| globals, "GAS_ZERO" |) + |) in + let _ := M.assign_local (| + "originator" , + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "current_target" |) + |) in + let _ := M.assign_local (| + "refunded_accounts" , + M.get_field (| M.get_name (| globals, "evm" |), "accounts_to_delete" |) + |) in + let _ := M.assign_local (| + "parent_evm" , + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "parent_evm" |) + |) in + let _ := + M.while (| + Compare.is_not (| + M.get_name (| globals, "parent_evm" |), + Constant.None_ + |), + ltac:(M.monadic ( + let _ := M.call (| + M.get_field (| M.get_name (| globals, "refunded_accounts" |), "update" |), + make_list [ + M.get_field (| M.get_name (| globals, "parent_evm" |), "accounts_to_delete" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "parent_evm" , + M.get_field (| M.get_field (| M.get_name (| globals, "parent_evm" |), "message" |), "parent_evm" |) + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.not_in (| + M.get_name (| globals, "originator" |), + M.get_name (| globals, "refunded_accounts" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "refund_counter" |), + M.get_name (| globals, "REFUND_SELF_DESTRUCT" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "gas_cost" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "beneficiary_balance" , + M.get_field (| M.call (| + M.get_name (| globals, "get_account" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "env" |), "state" |); + M.get_name (| globals, "beneficiary" |) + ], + make_dict [] + |), "balance" |) + |) in + let _ := M.assign_local (| + "originator_balance" , + M.get_field (| M.call (| + M.get_name (| globals, "get_account" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "env" |), "state" |); + M.get_name (| globals, "originator" |) + ], + make_dict [] + |), "balance" |) + |) in + let _ := M.call (| + M.get_name (| globals, "set_account_balance" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "env" |), "state" |); + M.get_name (| globals, "beneficiary" |); + BinOp.add (| + M.get_name (| globals, "beneficiary_balance" |), + M.get_name (| globals, "originator_balance" |) + |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "set_account_balance" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "env" |), "state" |); + M.get_name (| globals, "originator" |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "accounts_to_delete" |), "add" |), + make_list [ + M.get_name (| globals, "originator" |) + ], + make_dict [] + |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, "evm" |), "running" |), + Constant.bool false + |) in + let _ := M.pass (| |) in + M.pure Constant.None_)). + +Definition delegatecall : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Message-call into an account. + + Parameters + ---------- + evm : + The current EVM frame. + " in + let _ := M.assign_local (| + "gas" , + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "code_address" , + M.call (| + M.get_name (| globals, "to_address" |), + make_list [ + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_input_start_position" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_input_size" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_output_start_position" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_output_size" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "extend_memory" , + M.call (| + M.get_name (| globals, "calculate_gas_extend_memory" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "memory" |); + make_list [ + make_tuple [ M.get_name (| globals, "memory_input_start_position" |); M.get_name (| globals, "memory_input_size" |) ]; + make_tuple [ M.get_name (| globals, "memory_output_start_position" |); M.get_name (| globals, "memory_output_size" |) ] + ] + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + BinOp.add (| + BinOp.add (| + M.get_name (| globals, "GAS_CALL" |), + M.get_name (| globals, "gas" |) + |), + M.get_field (| M.get_name (| globals, "extend_memory" |), "cost" |) + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "memory" |), + BinOp.mult (| + Constant.bytes "00", + M.get_field (| M.get_name (| globals, "extend_memory" |), "expand_by" |) + |) + |) in + let _ := M.call (| + M.get_name (| globals, "generic_call" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "gas" |); + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "value" |); + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "caller" |); + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "current_target" |); + M.get_name (| globals, "code_address" |); + Constant.bool false; + M.get_name (| globals, "memory_input_start_position" |); + M.get_name (| globals, "memory_input_size" |); + M.get_name (| globals, "memory_output_start_position" |); + M.get_name (| globals, "memory_output_size" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). diff --git a/CoqOfPython/ethereum/homestead/vm/interpreter.v b/CoqOfPython/ethereum/homestead/vm/interpreter.v new file mode 100644 index 0000000..e60282d --- /dev/null +++ b/CoqOfPython/ethereum/homestead/vm/interpreter.v @@ -0,0 +1,578 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.homestead.vm.interpreter". + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) Interpreter +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +A straightforward interpreter that executes EVM code. +". + +Axiom dataclasses_imports_dataclass : + IsImported globals "dataclasses" "dataclass". + +Axiom typing_imports_Optional : + IsImported globals "typing" "Optional". +Axiom typing_imports_Set : + IsImported globals "typing" "Set". +Axiom typing_imports_Tuple : + IsImported globals "typing" "Tuple". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_Bytes0 : + IsImported globals "ethereum.base_types" "Bytes0". +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". + +Axiom ethereum_trace_imports_EvmStop : + IsImported globals "ethereum.trace" "EvmStop". +Axiom ethereum_trace_imports_OpEnd : + IsImported globals "ethereum.trace" "OpEnd". +Axiom ethereum_trace_imports_OpException : + IsImported globals "ethereum.trace" "OpException". +Axiom ethereum_trace_imports_OpStart : + IsImported globals "ethereum.trace" "OpStart". +Axiom ethereum_trace_imports_PrecompileEnd : + IsImported globals "ethereum.trace" "PrecompileEnd". +Axiom ethereum_trace_imports_PrecompileStart : + IsImported globals "ethereum.trace" "PrecompileStart". +Axiom ethereum_trace_imports_TransactionEnd : + IsImported globals "ethereum.trace" "TransactionEnd". +Axiom ethereum_trace_imports_evm_trace : + IsImported globals "ethereum.trace" "evm_trace". + +Axiom ethereum_homestead_blocks_imports_Log : + IsImported globals "ethereum.homestead.blocks" "Log". + +Axiom ethereum_homestead_fork_types_imports_Address : + IsImported globals "ethereum.homestead.fork_types" "Address". + +Axiom ethereum_homestead_state_imports_account_has_code_or_nonce : + IsImported globals "ethereum.homestead.state" "account_has_code_or_nonce". +Axiom ethereum_homestead_state_imports_begin_transaction : + IsImported globals "ethereum.homestead.state" "begin_transaction". +Axiom ethereum_homestead_state_imports_commit_transaction : + IsImported globals "ethereum.homestead.state" "commit_transaction". +Axiom ethereum_homestead_state_imports_destroy_storage : + IsImported globals "ethereum.homestead.state" "destroy_storage". +Axiom ethereum_homestead_state_imports_move_ether : + IsImported globals "ethereum.homestead.state" "move_ether". +Axiom ethereum_homestead_state_imports_rollback_transaction : + IsImported globals "ethereum.homestead.state" "rollback_transaction". +Axiom ethereum_homestead_state_imports_set_code : + IsImported globals "ethereum.homestead.state" "set_code". +Axiom ethereum_homestead_state_imports_touch_account : + IsImported globals "ethereum.homestead.state" "touch_account". + +Axiom ethereum_homestead_vm_imports_Message : + IsImported globals "ethereum.homestead.vm" "Message". + +Axiom ethereum_homestead_vm_gas_imports_GAS_CODE_DEPOSIT : + IsImported globals "ethereum.homestead.vm.gas" "GAS_CODE_DEPOSIT". +Axiom ethereum_homestead_vm_gas_imports_charge_gas : + IsImported globals "ethereum.homestead.vm.gas" "charge_gas". + +Axiom ethereum_homestead_vm_precompiled_contracts_mapping_imports_PRE_COMPILED_CONTRACTS : + IsImported globals "ethereum.homestead.vm.precompiled_contracts.mapping" "PRE_COMPILED_CONTRACTS". + +Axiom ethereum_homestead_vm_imports_Environment : + IsImported globals "ethereum.homestead.vm" "Environment". +Axiom ethereum_homestead_vm_imports_Evm : + IsImported globals "ethereum.homestead.vm" "Evm". + +Axiom ethereum_homestead_vm_exceptions_imports_AddressCollision : + IsImported globals "ethereum.homestead.vm.exceptions" "AddressCollision". +Axiom ethereum_homestead_vm_exceptions_imports_ExceptionalHalt : + IsImported globals "ethereum.homestead.vm.exceptions" "ExceptionalHalt". +Axiom ethereum_homestead_vm_exceptions_imports_InvalidOpcode : + IsImported globals "ethereum.homestead.vm.exceptions" "InvalidOpcode". +Axiom ethereum_homestead_vm_exceptions_imports_StackDepthLimitError : + IsImported globals "ethereum.homestead.vm.exceptions" "StackDepthLimitError". + +Axiom ethereum_homestead_vm_instructions_imports_Ops : + IsImported globals "ethereum.homestead.vm.instructions" "Ops". +Axiom ethereum_homestead_vm_instructions_imports_op_implementation : + IsImported globals "ethereum.homestead.vm.instructions" "op_implementation". + +Axiom ethereum_homestead_vm_runtime_imports_get_valid_jump_destinations : + IsImported globals "ethereum.homestead.vm.runtime" "get_valid_jump_destinations". + +Definition STACK_DEPTH_LIMIT : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 1024 + ], + make_dict [] + |) +)). + +Definition MessageCallOutput : Value.t := + builtins.make_klass + [] + [ + + ] + [ + + ]. + +Definition process_message_call : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "message"; "env" ] |) in + let _ := Constant.str " + If `message.current` is empty then it creates a smart contract + else it executes a call from the `message.caller` to the `message.target`. + + Parameters + ---------- + message : + Transaction specific items. + + env : + External items required for EVM execution. + + Returns + ------- + output : `MessageCallOutput` + Output of the message call + " in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_field (| M.get_name (| globals, "message" |), "target" |), + M.call (| + M.get_name (| globals, "Bytes0" |), + make_list [ + Constant.bytes "" + ], + make_dict [] + |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "is_collision" , + M.call (| + M.get_name (| globals, "account_has_code_or_nonce" |), + make_list [ + M.get_field (| M.get_name (| globals, "env" |), "state" |); + M.get_field (| M.get_name (| globals, "message" |), "current_target" |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + M.get_name (| globals, "is_collision" |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + M.call (| + M.get_name (| globals, "MessageCallOutput" |), + make_list [ + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |); + M.call (| + M.get_name (| globals, "tuple" |), + make_list [], + make_dict [] + |); + M.call (| + M.get_name (| globals, "set" |), + make_list [], + make_dict [] + |); + M.call (| + M.get_name (| globals, "AddressCollision" |), + make_list [], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "evm" , + M.call (| + M.get_name (| globals, "process_create_message" |), + make_list [ + M.get_name (| globals, "message" |); + M.get_name (| globals, "env" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "evm" , + M.call (| + M.get_name (| globals, "process_message" |), + make_list [ + M.get_name (| globals, "message" |); + M.get_name (| globals, "env" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + M.get_field (| M.get_name (| globals, "evm" |), "error" |), + (* then *) + ltac:(M.monadic ( +(* At stmt: unsupported node type: AnnAssign *) + let _ := M.assign_local (| + "accounts_to_delete" , + M.call (| + M.get_name (| globals, "set" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "refund_counter" , + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "logs" , + M.get_field (| M.get_name (| globals, "evm" |), "logs" |) + |) in + let _ := M.assign_local (| + "accounts_to_delete" , + M.get_field (| M.get_name (| globals, "evm" |), "accounts_to_delete" |) + |) in + let _ := M.assign_local (| + "refund_counter" , + M.get_field (| M.get_name (| globals, "evm" |), "refund_counter" |) + |) in + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "tx_end" , + M.call (| + M.get_name (| globals, "TransactionEnd" |), + make_list [ + BinOp.sub (| + M.get_field (| M.get_name (| globals, "message" |), "gas" |), + M.get_field (| M.get_name (| globals, "evm" |), "gas_left" |) + |); + M.get_field (| M.get_name (| globals, "evm" |), "output" |); + M.get_field (| M.get_name (| globals, "evm" |), "error" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "evm_trace" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "tx_end" |) + ], + make_dict [] + |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, "MessageCallOutput" |), + make_list [], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Definition process_create_message : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "message"; "env" ] |) in + let _ := Constant.str " + Executes a call to create a smart contract. + + Parameters + ---------- + message : + Transaction specific items. + env : + External items required for EVM execution. + + Returns + ------- + evm: :py:class:`~ethereum.homestead.vm.Evm` + Items containing execution specific objects. + " in + let _ := M.call (| + M.get_name (| globals, "begin_transaction" |), + make_list [ + M.get_field (| M.get_name (| globals, "env" |), "state" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "destroy_storage" |), + make_list [ + M.get_field (| M.get_name (| globals, "env" |), "state" |); + M.get_field (| M.get_name (| globals, "message" |), "current_target" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "evm" , + M.call (| + M.get_name (| globals, "process_message" |), + make_list [ + M.get_name (| globals, "message" |); + M.get_name (| globals, "env" |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + UnOp.not (| M.get_field (| M.get_name (| globals, "evm" |), "error" |) |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "contract_code" , + M.get_field (| M.get_name (| globals, "evm" |), "output" |) + |) in + let _ := M.assign_local (| + "contract_code_gas" , + BinOp.mult (| + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_name (| globals, "contract_code" |) + ], + make_dict [] + |), + M.get_name (| globals, "GAS_CODE_DEPOSIT" |) + |) + |) in +(* At stmt: unsupported node type: Try *) + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, "rollback_transaction" |), + make_list [ + M.get_field (| M.get_name (| globals, "env" |), "state" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + )) |) in + let _ := M.return_ (| + M.get_name (| globals, "evm" |) + |) in + M.pure Constant.None_)). + +Definition process_message : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "message"; "env" ] |) in + let _ := Constant.str " + Executes a call to create a smart contract. + + Parameters + ---------- + message : + Transaction specific items. + env : + External items required for EVM execution. + + Returns + ------- + evm: :py:class:`~ethereum.homestead.vm.Evm` + Items containing execution specific objects + " in + let _ := + (* if *) + M.if_then_else (| + Compare.gt (| + M.get_field (| M.get_name (| globals, "message" |), "depth" |), + M.get_name (| globals, "STACK_DEPTH_LIMIT" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.call (| + M.get_name (| globals, "StackDepthLimitError" |), + make_list [ + Constant.str "Stack depth limit reached" + ], + make_dict [] + |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.call (| + M.get_name (| globals, "begin_transaction" |), + make_list [ + M.get_field (| M.get_name (| globals, "env" |), "state" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "touch_account" |), + make_list [ + M.get_field (| M.get_name (| globals, "env" |), "state" |); + M.get_field (| M.get_name (| globals, "message" |), "current_target" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + BoolOp.and (| + M.get_field (| M.get_name (| globals, "message" |), "should_transfer_value" |), + ltac:(M.monadic ( + Compare.not_eq (| + M.get_field (| M.get_name (| globals, "message" |), "value" |), + Constant.int 0 + |) + )) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, "move_ether" |), + make_list [ + M.get_field (| M.get_name (| globals, "env" |), "state" |); + M.get_field (| M.get_name (| globals, "message" |), "caller" |); + M.get_field (| M.get_name (| globals, "message" |), "current_target" |); + M.get_field (| M.get_name (| globals, "message" |), "value" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "evm" , + M.call (| + M.get_name (| globals, "execute_code" |), + make_list [ + M.get_name (| globals, "message" |); + M.get_name (| globals, "env" |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + M.get_field (| M.get_name (| globals, "evm" |), "error" |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, "rollback_transaction" |), + make_list [ + M.get_field (| M.get_name (| globals, "env" |), "state" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, "commit_transaction" |), + make_list [ + M.get_field (| M.get_name (| globals, "env" |), "state" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + )) |) in + let _ := M.return_ (| + M.get_name (| globals, "evm" |) + |) in + M.pure Constant.None_)). + +Definition execute_code : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "message"; "env" ] |) in + let _ := Constant.str " + Executes bytecode present in the `message`. + + Parameters + ---------- + message : + Transaction specific items. + env : + External items required for EVM execution. + + Returns + ------- + evm: `ethereum.vm.EVM` + Items containing execution specific objects + " in + let _ := M.assign_local (| + "code" , + M.get_field (| M.get_name (| globals, "message" |), "code" |) + |) in + let _ := M.assign_local (| + "valid_jump_destinations" , + M.call (| + M.get_name (| globals, "get_valid_jump_destinations" |), + make_list [ + M.get_name (| globals, "code" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "evm" , + M.call (| + M.get_name (| globals, "Evm" |), + make_list [], + make_dict [] + |) + |) in +(* At stmt: unsupported node type: Try *) + let _ := M.return_ (| + M.get_name (| globals, "evm" |) + |) in + M.pure Constant.None_)). diff --git a/CoqOfPython/ethereum/homestead/vm/memory.v b/CoqOfPython/ethereum/homestead/vm/memory.v new file mode 100644 index 0000000..e10df21 --- /dev/null +++ b/CoqOfPython/ethereum/homestead/vm/memory.v @@ -0,0 +1,166 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.homestead.vm.memory". + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) Memory +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +EVM memory operations. +". + +Axiom ethereum_utils_byte_imports_right_pad_zero_bytes : + IsImported globals "ethereum.utils.byte" "right_pad_zero_bytes". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_Bytes : + IsImported globals "ethereum.base_types" "Bytes". +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". + +Definition memory_write : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "memory"; "start_position"; "value" ] |) in + let _ := Constant.str " + Writes to memory. + + Parameters + ---------- + memory : + Memory contents of the EVM. + start_position : + Starting pointer to the memory. + value : + Data to write to memory. + " in + let _ := M.assign (| + M.slice (| + M.get_name (| globals, "memory" |), + M.get_name (| globals, "start_position" |), + BinOp.add (| + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.get_name (| globals, "start_position" |) + ], + make_dict [] + |), + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_name (| globals, "value" |) + ], + make_dict [] + |) + |), + Constant.None_ + |), + M.get_name (| globals, "value" |) + |) in + M.pure Constant.None_)). + +Definition memory_read_bytes : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "memory"; "start_position"; "size" ] |) in + let _ := Constant.str " + Read bytes from memory. + + Parameters + ---------- + memory : + Memory contents of the EVM. + start_position : + Starting pointer to the memory. + size : + Size of the data that needs to be read from `start_position`. + + Returns + ------- + data_bytes : + Data read from memory. + " in + let _ := M.return_ (| + M.slice (| + M.get_name (| globals, "memory" |), + M.get_name (| globals, "start_position" |), + BinOp.add (| + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.get_name (| globals, "start_position" |) + ], + make_dict [] + |), + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.get_name (| globals, "size" |) + ], + make_dict [] + |) + |), + Constant.None_ + |) + |) in + M.pure Constant.None_)). + +Definition buffer_read : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "buffer"; "start_position"; "size" ] |) in + let _ := Constant.str " + Read bytes from a buffer. Padding with zeros if necessary. + + Parameters + ---------- + buffer : + Memory contents of the EVM. + start_position : + Starting pointer to the memory. + size : + Size of the data that needs to be read from `start_position`. + + Returns + ------- + data_bytes : + Data read from memory. + " in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, "right_pad_zero_bytes" |), + make_list [ + M.slice (| + M.get_name (| globals, "buffer" |), + M.get_name (| globals, "start_position" |), + BinOp.add (| + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.get_name (| globals, "start_position" |) + ], + make_dict [] + |), + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.get_name (| globals, "size" |) + ], + make_dict [] + |) + |), + Constant.None_ + |); + M.get_name (| globals, "size" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). diff --git a/CoqOfPython/ethereum/homestead/vm/precompiled_contracts/__init__.v b/CoqOfPython/ethereum/homestead/vm/precompiled_contracts/__init__.v new file mode 100644 index 0000000..f7f7382 --- /dev/null +++ b/CoqOfPython/ethereum/homestead/vm/precompiled_contracts/__init__.v @@ -0,0 +1,66 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.homestead.vm.precompiled_contracts.__init__". + +Definition expr_1 : Value.t := + Constant.str " +Precompiled Contract Addresses +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Addresses of precompiled contracts and mappings to their +implementations. +". + +Axiom ethereum_homestead_utils_hexadecimal_imports_hex_to_address : + IsImported globals "ethereum.homestead.utils.hexadecimal" "hex_to_address". + +Definition __all__ : Value.t := M.run ltac:(M.monadic ( + make_tuple [ Constant.str "ECRECOVER_ADDRESS"; Constant.str "SHA256_ADDRESS"; Constant.str "RIPEMD160_ADDRESS"; Constant.str "IDENTITY_ADDRESS" ] +)). + +Definition ECRECOVER_ADDRESS : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "hex_to_address" |), + make_list [ + Constant.str "0x01" + ], + make_dict [] + |) +)). + +Definition SHA256_ADDRESS : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "hex_to_address" |), + make_list [ + Constant.str "0x02" + ], + make_dict [] + |) +)). + +Definition RIPEMD160_ADDRESS : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "hex_to_address" |), + make_list [ + Constant.str "0x03" + ], + make_dict [] + |) +)). + +Definition IDENTITY_ADDRESS : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "hex_to_address" |), + make_list [ + Constant.str "0x04" + ], + make_dict [] + |) +)). diff --git a/CoqOfPython/ethereum/homestead/vm/precompiled_contracts/ecrecover.v b/CoqOfPython/ethereum/homestead/vm/precompiled_contracts/ecrecover.v new file mode 100644 index 0000000..e4781ca --- /dev/null +++ b/CoqOfPython/ethereum/homestead/vm/precompiled_contracts/ecrecover.v @@ -0,0 +1,301 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.homestead.vm.precompiled_contracts.ecrecover". + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) ECRECOVER PRECOMPILED CONTRACT +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementation of the ECRECOVER precompiled contract. +". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". + +Axiom ethereum_crypto_elliptic_curve_imports_SECP256K1N : + IsImported globals "ethereum.crypto.elliptic_curve" "SECP256K1N". +Axiom ethereum_crypto_elliptic_curve_imports_secp256k1_recover : + IsImported globals "ethereum.crypto.elliptic_curve" "secp256k1_recover". + +Axiom ethereum_crypto_hash_imports_Hash32 : + IsImported globals "ethereum.crypto.hash" "Hash32". +Axiom ethereum_crypto_hash_imports_keccak256 : + IsImported globals "ethereum.crypto.hash" "keccak256". + +Axiom ethereum_utils_byte_imports_left_pad_zero_bytes : + IsImported globals "ethereum.utils.byte" "left_pad_zero_bytes". + +Axiom ethereum_homestead_vm_imports_Evm : + IsImported globals "ethereum.homestead.vm" "Evm". + +Axiom ethereum_homestead_vm_gas_imports_GAS_ECRECOVER : + IsImported globals "ethereum.homestead.vm.gas" "GAS_ECRECOVER". +Axiom ethereum_homestead_vm_gas_imports_charge_gas : + IsImported globals "ethereum.homestead.vm.gas" "charge_gas". + +Axiom ethereum_homestead_vm_memory_imports_buffer_read : + IsImported globals "ethereum.homestead.vm.memory" "buffer_read". + +Definition ecrecover : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Decrypts the address using elliptic curve DSA recovery mechanism and writes + the address to output. + + Parameters + ---------- + evm : + The current EVM frame. + " in + let _ := M.assign_local (| + "data" , + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "data" |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_ECRECOVER" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "message_hash_bytes" , + M.call (| + M.get_name (| globals, "buffer_read" |), + make_list [ + M.get_name (| globals, "data" |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 32 + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "message_hash" , + M.call (| + M.get_name (| globals, "Hash32" |), + make_list [ + M.get_name (| globals, "message_hash_bytes" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "v" , + M.call (| + M.get_field (| M.get_name (| globals, "U256" |), "from_be_bytes" |), + make_list [ + M.call (| + M.get_name (| globals, "buffer_read" |), + make_list [ + M.get_name (| globals, "data" |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 32 + ], + make_dict [] + |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 32 + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "r" , + M.call (| + M.get_field (| M.get_name (| globals, "U256" |), "from_be_bytes" |), + make_list [ + M.call (| + M.get_name (| globals, "buffer_read" |), + make_list [ + M.get_name (| globals, "data" |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 64 + ], + make_dict [] + |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 32 + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "s" , + M.call (| + M.get_field (| M.get_name (| globals, "U256" |), "from_be_bytes" |), + make_list [ + M.call (| + M.get_name (| globals, "buffer_read" |), + make_list [ + M.get_name (| globals, "data" |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 96 + ], + make_dict [] + |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 32 + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + BoolOp.and (| + Compare.not_eq (| + M.get_name (| globals, "v" |), + Constant.int 27 + |), + ltac:(M.monadic ( + Compare.not_eq (| + M.get_name (| globals, "v" |), + Constant.int 28 + |) + )) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + Constant.None_ + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + BoolOp.or (| + Compare.gt_e (| + Constant.int 0, + M.get_name (| globals, "r" |) + |), + ltac:(M.monadic ( + Compare.gt_e (| + M.get_name (| globals, "r" |), + M.get_name (| globals, "SECP256K1N" |) + |) + )) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + Constant.None_ + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + BoolOp.or (| + Compare.gt_e (| + Constant.int 0, + M.get_name (| globals, "s" |) + |), + ltac:(M.monadic ( + Compare.gt_e (| + M.get_name (| globals, "s" |), + M.get_name (| globals, "SECP256K1N" |) + |) + )) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + Constant.None_ + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in +(* At stmt: unsupported node type: Try *) + let _ := M.assign_local (| + "address" , + M.slice (| + M.call (| + M.get_name (| globals, "keccak256" |), + make_list [ + M.get_name (| globals, "public_key" |) + ], + make_dict [] + |), + Constant.int 12, + Constant.int 32, + Constant.None_ + |) + |) in + let _ := M.assign_local (| + "padded_address" , + M.call (| + M.get_name (| globals, "left_pad_zero_bytes" |), + make_list [ + M.get_name (| globals, "address" |); + Constant.int 32 + ], + make_dict [] + |) + |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, "evm" |), "output" |), + M.get_name (| globals, "padded_address" |) + |) in + M.pure Constant.None_)). diff --git a/CoqOfPython/ethereum/homestead/vm/precompiled_contracts/identity.v b/CoqOfPython/ethereum/homestead/vm/precompiled_contracts/identity.v new file mode 100644 index 0000000..1f02089 --- /dev/null +++ b/CoqOfPython/ethereum/homestead/vm/precompiled_contracts/identity.v @@ -0,0 +1,94 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.homestead.vm.precompiled_contracts.identity". + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) IDENTITY PRECOMPILED CONTRACT +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementation of the `IDENTITY` precompiled contract. +". + +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". + +Axiom ethereum_utils_numeric_imports_ceil32 : + IsImported globals "ethereum.utils.numeric" "ceil32". + +Axiom ethereum_homestead_vm_imports_Evm : + IsImported globals "ethereum.homestead.vm" "Evm". + +Axiom ethereum_homestead_vm_gas_imports_GAS_IDENTITY : + IsImported globals "ethereum.homestead.vm.gas" "GAS_IDENTITY". +Axiom ethereum_homestead_vm_gas_imports_GAS_IDENTITY_WORD : + IsImported globals "ethereum.homestead.vm.gas" "GAS_IDENTITY_WORD". +Axiom ethereum_homestead_vm_gas_imports_charge_gas : + IsImported globals "ethereum.homestead.vm.gas" "charge_gas". + +Definition identity : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Writes the message data to output. + + Parameters + ---------- + evm : + The current EVM frame. + " in + let _ := M.assign_local (| + "data" , + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "data" |) + |) in + let _ := M.assign_local (| + "word_count" , + BinOp.floor_div (| + M.call (| + M.get_name (| globals, "ceil32" |), + make_list [ + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_name (| globals, "data" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |), + Constant.int 32 + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + BinOp.add (| + M.get_name (| globals, "GAS_IDENTITY" |), + BinOp.mult (| + M.get_name (| globals, "GAS_IDENTITY_WORD" |), + M.get_name (| globals, "word_count" |) + |) + |) + ], + make_dict [] + |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, "evm" |), "output" |), + M.get_name (| globals, "data" |) + |) in + M.pure Constant.None_)). diff --git a/CoqOfPython/ethereum/homestead/vm/precompiled_contracts/mapping.v b/CoqOfPython/ethereum/homestead/vm/precompiled_contracts/mapping.v new file mode 100644 index 0000000..317a774 --- /dev/null +++ b/CoqOfPython/ethereum/homestead/vm/precompiled_contracts/mapping.v @@ -0,0 +1,49 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.homestead.vm.precompiled_contracts.mapping". + +Definition expr_1 : Value.t := + Constant.str " +Precompiled Contract Addresses +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Mapping of precompiled contracts their implementations. +". + +Axiom typing_imports_Callable : + IsImported globals "typing" "Callable". +Axiom typing_imports_Dict : + IsImported globals "typing" "Dict". + +Axiom ethereum_homestead_fork_types_imports_Address : + IsImported globals "ethereum.homestead.fork_types" "Address". + +Axiom ethereum_homestead_vm_precompiled_contracts_imports_ECRECOVER_ADDRESS : + IsImported globals "ethereum.homestead.vm.precompiled_contracts" "ECRECOVER_ADDRESS". +Axiom ethereum_homestead_vm_precompiled_contracts_imports_IDENTITY_ADDRESS : + IsImported globals "ethereum.homestead.vm.precompiled_contracts" "IDENTITY_ADDRESS". +Axiom ethereum_homestead_vm_precompiled_contracts_imports_RIPEMD160_ADDRESS : + IsImported globals "ethereum.homestead.vm.precompiled_contracts" "RIPEMD160_ADDRESS". +Axiom ethereum_homestead_vm_precompiled_contracts_imports_SHA256_ADDRESS : + IsImported globals "ethereum.homestead.vm.precompiled_contracts" "SHA256_ADDRESS". + +Axiom ethereum_homestead_vm_precompiled_contracts_ecrecover_imports_ecrecover : + IsImported globals "ethereum.homestead.vm.precompiled_contracts.ecrecover" "ecrecover". + +Axiom ethereum_homestead_vm_precompiled_contracts_identity_imports_identity : + IsImported globals "ethereum.homestead.vm.precompiled_contracts.identity" "identity". + +Axiom ethereum_homestead_vm_precompiled_contracts_ripemd160_imports_ripemd160 : + IsImported globals "ethereum.homestead.vm.precompiled_contracts.ripemd160" "ripemd160". + +Axiom ethereum_homestead_vm_precompiled_contracts_sha256_imports_sha256 : + IsImported globals "ethereum.homestead.vm.precompiled_contracts.sha256" "sha256". + +(* At top_level_stmt: unsupported node type: AnnAssign *) diff --git a/CoqOfPython/ethereum/homestead/vm/precompiled_contracts/ripemd160.v b/CoqOfPython/ethereum/homestead/vm/precompiled_contracts/ripemd160.v new file mode 100644 index 0000000..659b238 --- /dev/null +++ b/CoqOfPython/ethereum/homestead/vm/precompiled_contracts/ripemd160.v @@ -0,0 +1,125 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.homestead.vm.precompiled_contracts.ripemd160". + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) RIPEMD160 PRECOMPILED CONTRACT +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementation of the `RIPEMD160` precompiled contract. +". + +(* At top_level_stmt: unsupported node type: Import *) + +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". + +Axiom ethereum_utils_byte_imports_left_pad_zero_bytes : + IsImported globals "ethereum.utils.byte" "left_pad_zero_bytes". + +Axiom ethereum_utils_numeric_imports_ceil32 : + IsImported globals "ethereum.utils.numeric" "ceil32". + +Axiom ethereum_homestead_vm_imports_Evm : + IsImported globals "ethereum.homestead.vm" "Evm". + +Axiom ethereum_homestead_vm_gas_imports_GAS_RIPEMD160 : + IsImported globals "ethereum.homestead.vm.gas" "GAS_RIPEMD160". +Axiom ethereum_homestead_vm_gas_imports_GAS_RIPEMD160_WORD : + IsImported globals "ethereum.homestead.vm.gas" "GAS_RIPEMD160_WORD". +Axiom ethereum_homestead_vm_gas_imports_charge_gas : + IsImported globals "ethereum.homestead.vm.gas" "charge_gas". + +Definition ripemd160 : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Writes the ripemd160 hash to output. + + Parameters + ---------- + evm : + The current EVM frame. + " in + let _ := M.assign_local (| + "data" , + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "data" |) + |) in + let _ := M.assign_local (| + "word_count" , + BinOp.floor_div (| + M.call (| + M.get_name (| globals, "ceil32" |), + make_list [ + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_name (| globals, "data" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |), + Constant.int 32 + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + BinOp.add (| + M.get_name (| globals, "GAS_RIPEMD160" |), + BinOp.mult (| + M.get_name (| globals, "GAS_RIPEMD160_WORD" |), + M.get_name (| globals, "word_count" |) + |) + |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "hash_bytes" , + M.call (| + M.get_field (| M.call (| + M.get_field (| M.get_name (| globals, "hashlib" |), "new" |), + make_list [ + Constant.str "ripemd160"; + M.get_name (| globals, "data" |) + ], + make_dict [] + |), "digest" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "padded_hash" , + M.call (| + M.get_name (| globals, "left_pad_zero_bytes" |), + make_list [ + M.get_name (| globals, "hash_bytes" |); + Constant.int 32 + ], + make_dict [] + |) + |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, "evm" |), "output" |), + M.get_name (| globals, "padded_hash" |) + |) in + M.pure Constant.None_)). diff --git a/CoqOfPython/ethereum/homestead/vm/precompiled_contracts/sha256.v b/CoqOfPython/ethereum/homestead/vm/precompiled_contracts/sha256.v new file mode 100644 index 0000000..e8dbb14 --- /dev/null +++ b/CoqOfPython/ethereum/homestead/vm/precompiled_contracts/sha256.v @@ -0,0 +1,106 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.homestead.vm.precompiled_contracts.sha256". + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) SHA256 PRECOMPILED CONTRACT +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementation of the `SHA256` precompiled contract. +". + +(* At top_level_stmt: unsupported node type: Import *) + +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". + +Axiom ethereum_utils_numeric_imports_ceil32 : + IsImported globals "ethereum.utils.numeric" "ceil32". + +Axiom ethereum_homestead_vm_imports_Evm : + IsImported globals "ethereum.homestead.vm" "Evm". + +Axiom ethereum_homestead_vm_gas_imports_GAS_SHA256 : + IsImported globals "ethereum.homestead.vm.gas" "GAS_SHA256". +Axiom ethereum_homestead_vm_gas_imports_GAS_SHA256_WORD : + IsImported globals "ethereum.homestead.vm.gas" "GAS_SHA256_WORD". +Axiom ethereum_homestead_vm_gas_imports_charge_gas : + IsImported globals "ethereum.homestead.vm.gas" "charge_gas". + +Definition sha256 : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Writes the sha256 hash to output. + + Parameters + ---------- + evm : + The current EVM frame. + " in + let _ := M.assign_local (| + "data" , + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "data" |) + |) in + let _ := M.assign_local (| + "word_count" , + BinOp.floor_div (| + M.call (| + M.get_name (| globals, "ceil32" |), + make_list [ + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_name (| globals, "data" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |), + Constant.int 32 + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + BinOp.add (| + M.get_name (| globals, "GAS_SHA256" |), + BinOp.mult (| + M.get_name (| globals, "GAS_SHA256_WORD" |), + M.get_name (| globals, "word_count" |) + |) + |) + ], + make_dict [] + |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, "evm" |), "output" |), + M.call (| + M.get_field (| M.call (| + M.get_field (| M.get_name (| globals, "hashlib" |), "sha256" |), + make_list [ + M.get_name (| globals, "data" |) + ], + make_dict [] + |), "digest" |), + make_list [], + make_dict [] + |) + |) in + M.pure Constant.None_)). diff --git a/CoqOfPython/ethereum/homestead/vm/runtime.v b/CoqOfPython/ethereum/homestead/vm/runtime.v new file mode 100644 index 0000000..d8d8829 --- /dev/null +++ b/CoqOfPython/ethereum/homestead/vm/runtime.v @@ -0,0 +1,157 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.homestead.vm.runtime". + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) Runtime Operations +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Runtime related operations used while executing EVM code. +". + +Axiom typing_imports_Set : + IsImported globals "typing" "Set". + +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". + +Axiom ethereum_homestead_vm_instructions_imports_Ops : + IsImported globals "ethereum.homestead.vm.instructions" "Ops". + +Definition get_valid_jump_destinations : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "code" ] |) in + let _ := Constant.str " + Analyze the evm code to obtain the set of valid jump destinations. + + Valid jump destinations are defined as follows: + * The jump destination is less than the length of the code. + * The jump destination should have the `JUMPDEST` opcode (0x5B). + * The jump destination shouldn't be part of the data corresponding to + `PUSH-N` opcodes. + + Note - Jump destinations are 0-indexed. + + Parameters + ---------- + code : + The EVM code which is to be executed. + + Returns + ------- + valid_jump_destinations: `Set[Uint]` + The set of valid jump destinations in the code. + " in + let _ := M.assign_local (| + "valid_jump_destinations" , + M.call (| + M.get_name (| globals, "set" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "pc" , + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + |) in + let _ := + M.while (| + Compare.lt (| + M.get_name (| globals, "pc" |), + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_name (| globals, "code" |) + ], + make_dict [] + |) + |), + ltac:(M.monadic ( +(* At stmt: unsupported node type: Try *) + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, "current_opcode" |), + M.get_field (| M.get_name (| globals, "Ops" |), "JUMPDEST" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_field (| M.get_name (| globals, "valid_jump_destinations" |), "add" |), + make_list [ + M.get_name (| globals, "pc" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + BoolOp.and (| + Compare.lt_e (| + M.get_field (| M.get_field (| M.get_name (| globals, "Ops" |), "PUSH1" |), "value" |), + M.get_field (| M.get_name (| globals, "current_opcode" |), "value" |) + |), + ltac:(M.monadic ( + Compare.lt_e (| + M.get_field (| M.get_name (| globals, "current_opcode" |), "value" |), + M.get_field (| M.get_field (| M.get_name (| globals, "Ops" |), "PUSH32" |), "value" |) + |) + )) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "push_data_size" , + BinOp.add (| + BinOp.sub (| + M.get_field (| M.get_name (| globals, "current_opcode" |), "value" |), + M.get_field (| M.get_field (| M.get_name (| globals, "Ops" |), "PUSH1" |), "value" |) + |), + Constant.int 1 + |) + |) in + let _ := M.assign_op_local (| + BinOp.add, + "pc", + M.get_name (| globals, "push_data_size" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )) |) in + let _ := M.assign_op_local (| + BinOp.add, + "pc", + Constant.int 1 + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := M.return_ (| + M.get_name (| globals, "valid_jump_destinations" |) + |) in + M.pure Constant.None_)). diff --git a/CoqOfPython/ethereum/homestead/vm/stack.v b/CoqOfPython/ethereum/homestead/vm/stack.v new file mode 100644 index 0000000..e8c3493 --- /dev/null +++ b/CoqOfPython/ethereum/homestead/vm/stack.v @@ -0,0 +1,123 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.homestead.vm.stack". + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) Stack +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementation of the stack operators for the EVM. +". + +Axiom typing_imports_List : + IsImported globals "typing" "List". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". + +Axiom ethereum_homestead_vm_exceptions_imports_StackOverflowError : + IsImported globals "ethereum.homestead.vm.exceptions" "StackOverflowError". +Axiom ethereum_homestead_vm_exceptions_imports_StackUnderflowError : + IsImported globals "ethereum.homestead.vm.exceptions" "StackUnderflowError". + +Definition pop : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "stack" ] |) in + let _ := Constant.str " + Pops the top item off of `stack`. + + Parameters + ---------- + stack : + EVM stack. + + Returns + ------- + value : `U256` + The top element on the stack. + + " in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_name (| globals, "stack" |) + ], + make_dict [] + |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, "StackUnderflowError" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.return_ (| + M.call (| + M.get_field (| M.get_name (| globals, "stack" |), "pop" |), + make_list [], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Definition push : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "stack"; "value" ] |) in + let _ := Constant.str " + Pushes `value` onto `stack`. + + Parameters + ---------- + stack : + EVM stack. + + value : + Item to be pushed onto `stack`. + + " in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_name (| globals, "stack" |) + ], + make_dict [] + |), + Constant.int 1024 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, "StackOverflowError" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.return_ (| + M.call (| + M.get_field (| M.get_name (| globals, "stack" |), "append" |), + make_list [ + M.get_name (| globals, "value" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). diff --git a/CoqOfPython/ethereum/istanbul/__init__.v b/CoqOfPython/ethereum/istanbul/__init__.v new file mode 100644 index 0000000..41dba6f --- /dev/null +++ b/CoqOfPython/ethereum/istanbul/__init__.v @@ -0,0 +1,23 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.istanbul.__init__". + +Definition expr_1 : Value.t := + Constant.str " +The Istanbul fork makes changes to the gas costs of EVM instructions and data, +adds a cryptographic primitive, and introduces an instruction to fetch the +current chain identifier. +". + +Axiom ethereum_fork_criteria_imports_ByBlockNumber : + IsImported globals "ethereum.fork_criteria" "ByBlockNumber". + +Definition FORK_CRITERIA : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "ByBlockNumber" |), + make_list [ + Constant.int 9069000 + ], + make_dict [] + |) +)). diff --git a/CoqOfPython/ethereum/istanbul/blocks.v b/CoqOfPython/ethereum/istanbul/blocks.v new file mode 100644 index 0000000..09c7599 --- /dev/null +++ b/CoqOfPython/ethereum/istanbul/blocks.v @@ -0,0 +1,87 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.istanbul.blocks". + +Definition expr_1 : Value.t := + Constant.str " +A `Block` is a single link in the chain that is Ethereum. Each `Block` contains +a `Header` and zero or more transactions. Each `Header` contains associated +metadata like the block number, parent block hash, and how much gas was +consumed by its transactions. + +Together, these blocks form a cryptographically secure journal recording the +history of all state transitions that have happened since the genesis of the +chain. +". + +Axiom dataclasses_imports_dataclass : + IsImported globals "dataclasses" "dataclass". + +Axiom typing_imports_Tuple : + IsImported globals "typing" "Tuple". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_Bytes : + IsImported globals "ethereum.base_types" "Bytes". +Axiom ethereum_base_types_imports_Bytes8 : + IsImported globals "ethereum.base_types" "Bytes8". +Axiom ethereum_base_types_imports_Bytes32 : + IsImported globals "ethereum.base_types" "Bytes32". +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". +Axiom ethereum_base_types_imports_slotted_freezable : + IsImported globals "ethereum.base_types" "slotted_freezable". + +Axiom ethereum_crypto_hash_imports_Hash32 : + IsImported globals "ethereum.crypto.hash" "Hash32". + +Axiom ethereum_istanbul_fork_types_imports_Address : + IsImported globals "ethereum.istanbul.fork_types" "Address". +Axiom ethereum_istanbul_fork_types_imports_Bloom : + IsImported globals "ethereum.istanbul.fork_types" "Bloom". +Axiom ethereum_istanbul_fork_types_imports_Root : + IsImported globals "ethereum.istanbul.fork_types" "Root". + +Axiom ethereum_istanbul_transactions_imports_Transaction : + IsImported globals "ethereum.istanbul.transactions" "Transaction". + +Definition Header : Value.t := + builtins.make_klass + [] + [ + + ] + [ + + ]. + +Definition Block : Value.t := + builtins.make_klass + [] + [ + + ] + [ + + ]. + +Definition Log : Value.t := + builtins.make_klass + [] + [ + + ] + [ + + ]. + +Definition Receipt : Value.t := + builtins.make_klass + [] + [ + + ] + [ + + ]. diff --git a/CoqOfPython/ethereum/istanbul/bloom.v b/CoqOfPython/ethereum/istanbul/bloom.v new file mode 100644 index 0000000..9f67f06 --- /dev/null +++ b/CoqOfPython/ethereum/istanbul/bloom.v @@ -0,0 +1,207 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.istanbul.bloom". + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Logs Bloom +^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +This modules defines functions for calculating bloom filters of logs. For the +general theory of bloom filters see e.g. `Wikipedia +`_. Bloom filters are used to allow +for efficient searching of logs by address and/or topic, by rapidly +eliminating blocks and receipts from their search. +". + +Axiom typing_imports_Tuple : + IsImported globals "typing" "Tuple". + +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". + +Axiom ethereum_crypto_hash_imports_keccak256 : + IsImported globals "ethereum.crypto.hash" "keccak256". + +Axiom ethereum_istanbul_blocks_imports_Log : + IsImported globals "ethereum.istanbul.blocks" "Log". + +Axiom ethereum_istanbul_fork_types_imports_Bloom : + IsImported globals "ethereum.istanbul.fork_types" "Bloom". + +Definition add_to_bloom : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "bloom"; "bloom_entry" ] |) in + let _ := Constant.str " + Add a bloom entry to the bloom filter (`bloom`). + + The number of hash functions used is 3. They are calculated by taking the + least significant 11 bits from the first 3 16-bit words of the + `keccak_256()` hash of `bloom_entry`. + + Parameters + ---------- + bloom : + The bloom filter. + bloom_entry : + An entry which is to be added to bloom filter. + " in + let _ := M.assign_local (| + "hash" , + M.call (| + M.get_name (| globals, "keccak256" |), + make_list [ + M.get_name (| globals, "bloom_entry" |) + ], + make_dict [] + |) + |) in + let _ := + M.for_ (| + M.get_name (| globals, "idx" |), + make_tuple [ Constant.int 0; Constant.int 2; Constant.int 4 ], + ltac:(M.monadic ( + let _ := M.assign_local (| + "bit_to_set" , + BinOp.bit_and (| + M.call (| + M.get_field (| M.get_name (| globals, "Uint" |), "from_be_bytes" |), + make_list [ + M.slice (| + M.get_name (| globals, "hash" |), + M.get_name (| globals, "idx" |), + BinOp.add (| + M.get_name (| globals, "idx" |), + Constant.int 2 + |), + Constant.None_ + |) + ], + make_dict [] + |), + Constant.int 2047 + |) + |) in + let _ := M.assign_local (| + "bit_index" , + BinOp.sub (| + Constant.int 2047, + M.get_name (| globals, "bit_to_set" |) + |) + |) in + let _ := M.assign_local (| + "byte_index" , + BinOp.floor_div (| + M.get_name (| globals, "bit_index" |), + Constant.int 8 + |) + |) in + let _ := M.assign_local (| + "bit_value" , + BinOp.l_shift (| + Constant.int 1, + BinOp.sub (| + Constant.int 7, + BinOp.mod_ (| + M.get_name (| globals, "bit_index" |), + Constant.int 8 + |) + |) + |) + |) in + let _ := M.assign (| + M.get_subscript (| + M.get_name (| globals, "bloom" |), + M.get_name (| globals, "byte_index" |) + |), + BinOp.bit_or (| + M.get_subscript (| + M.get_name (| globals, "bloom" |), + M.get_name (| globals, "byte_index" |) + |), + M.get_name (| globals, "bit_value" |) + |) + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + M.pure Constant.None_)). + +Definition logs_bloom : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "logs" ] |) in + let _ := Constant.str " + Obtain the logs bloom from a list of log entries. + + The address and each topic of a log are added to the bloom filter. + + Parameters + ---------- + logs : + List of logs for which the logs bloom is to be obtained. + + Returns + ------- + logs_bloom : `Bloom` + The logs bloom obtained which is 256 bytes with some bits set as per + the caller address and the log topics. + " in +(* At stmt: unsupported node type: AnnAssign *) + let _ := + M.for_ (| + M.get_name (| globals, "log" |), + M.get_name (| globals, "logs" |), + ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, "add_to_bloom" |), + make_list [ + M.get_name (| globals, "bloom" |); + M.get_field (| M.get_name (| globals, "log" |), "address" |) + ], + make_dict [] + |) in + let _ := + M.for_ (| + M.get_name (| globals, "topic" |), + M.get_field (| M.get_name (| globals, "log" |), "topics" |), + ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, "add_to_bloom" |), + make_list [ + M.get_name (| globals, "bloom" |); + M.get_name (| globals, "topic" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, "Bloom" |), + make_list [ + M.get_name (| globals, "bloom" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). diff --git a/CoqOfPython/ethereum/istanbul/fork.v b/CoqOfPython/ethereum/istanbul/fork.v new file mode 100644 index 0000000..ce58ae7 --- /dev/null +++ b/CoqOfPython/ethereum/istanbul/fork.v @@ -0,0 +1,2655 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.istanbul.fork". + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Specification +^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Entry point for the Ethereum specification. +". + +Axiom dataclasses_imports_dataclass : + IsImported globals "dataclasses" "dataclass". + +Axiom typing_imports_List : + IsImported globals "typing" "List". +Axiom typing_imports_Optional : + IsImported globals "typing" "Optional". +Axiom typing_imports_Set : + IsImported globals "typing" "Set". +Axiom typing_imports_Tuple : + IsImported globals "typing" "Tuple". + +Axiom ethereum_base_types_imports_Bytes0 : + IsImported globals "ethereum.base_types" "Bytes0". + +Axiom ethereum_crypto_elliptic_curve_imports_SECP256K1N : + IsImported globals "ethereum.crypto.elliptic_curve" "SECP256K1N". +Axiom ethereum_crypto_elliptic_curve_imports_secp256k1_recover : + IsImported globals "ethereum.crypto.elliptic_curve" "secp256k1_recover". + +Axiom ethereum_crypto_hash_imports_Hash32 : + IsImported globals "ethereum.crypto.hash" "Hash32". +Axiom ethereum_crypto_hash_imports_keccak256 : + IsImported globals "ethereum.crypto.hash" "keccak256". + +Axiom ethereum_ethash_imports_dataset_size : + IsImported globals "ethereum.ethash" "dataset_size". +Axiom ethereum_ethash_imports_generate_cache : + IsImported globals "ethereum.ethash" "generate_cache". +Axiom ethereum_ethash_imports_hashimoto_light : + IsImported globals "ethereum.ethash" "hashimoto_light". + +Axiom ethereum_exceptions_imports_InvalidBlock : + IsImported globals "ethereum.exceptions" "InvalidBlock". + +Axiom ethereum_utils_ensure_imports_ensure : + IsImported globals "ethereum.utils.ensure" "ensure". + +Axiom ethereum_imports_rlp : + IsImported globals "ethereum" "rlp". + +Axiom ethereum_base_types_imports_U64 : + IsImported globals "ethereum.base_types" "U64". +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_U256_CEIL_VALUE : + IsImported globals "ethereum.base_types" "U256_CEIL_VALUE". +Axiom ethereum_base_types_imports_Bytes : + IsImported globals "ethereum.base_types" "Bytes". +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". + +Axiom ethereum_istanbul_imports_vm : + IsImported globals "ethereum.istanbul" "vm". + +Axiom ethereum_istanbul_blocks_imports_Block : + IsImported globals "ethereum.istanbul.blocks" "Block". +Axiom ethereum_istanbul_blocks_imports_Header : + IsImported globals "ethereum.istanbul.blocks" "Header". +Axiom ethereum_istanbul_blocks_imports_Log : + IsImported globals "ethereum.istanbul.blocks" "Log". +Axiom ethereum_istanbul_blocks_imports_Receipt : + IsImported globals "ethereum.istanbul.blocks" "Receipt". + +Axiom ethereum_istanbul_bloom_imports_logs_bloom : + IsImported globals "ethereum.istanbul.bloom" "logs_bloom". + +Axiom ethereum_istanbul_fork_types_imports_Address : + IsImported globals "ethereum.istanbul.fork_types" "Address". +Axiom ethereum_istanbul_fork_types_imports_Bloom : + IsImported globals "ethereum.istanbul.fork_types" "Bloom". +Axiom ethereum_istanbul_fork_types_imports_Root : + IsImported globals "ethereum.istanbul.fork_types" "Root". + +Axiom ethereum_istanbul_state_imports_State : + IsImported globals "ethereum.istanbul.state" "State". +Axiom ethereum_istanbul_state_imports_account_exists_and_is_empty : + IsImported globals "ethereum.istanbul.state" "account_exists_and_is_empty". +Axiom ethereum_istanbul_state_imports_create_ether : + IsImported globals "ethereum.istanbul.state" "create_ether". +Axiom ethereum_istanbul_state_imports_destroy_account : + IsImported globals "ethereum.istanbul.state" "destroy_account". +Axiom ethereum_istanbul_state_imports_get_account : + IsImported globals "ethereum.istanbul.state" "get_account". +Axiom ethereum_istanbul_state_imports_increment_nonce : + IsImported globals "ethereum.istanbul.state" "increment_nonce". +Axiom ethereum_istanbul_state_imports_set_account_balance : + IsImported globals "ethereum.istanbul.state" "set_account_balance". +Axiom ethereum_istanbul_state_imports_state_root : + IsImported globals "ethereum.istanbul.state" "state_root". + +Axiom ethereum_istanbul_transactions_imports_TX_BASE_COST : + IsImported globals "ethereum.istanbul.transactions" "TX_BASE_COST". +Axiom ethereum_istanbul_transactions_imports_TX_CREATE_COST : + IsImported globals "ethereum.istanbul.transactions" "TX_CREATE_COST". +Axiom ethereum_istanbul_transactions_imports_TX_DATA_COST_PER_NON_ZERO : + IsImported globals "ethereum.istanbul.transactions" "TX_DATA_COST_PER_NON_ZERO". +Axiom ethereum_istanbul_transactions_imports_TX_DATA_COST_PER_ZERO : + IsImported globals "ethereum.istanbul.transactions" "TX_DATA_COST_PER_ZERO". +Axiom ethereum_istanbul_transactions_imports_Transaction : + IsImported globals "ethereum.istanbul.transactions" "Transaction". + +Axiom ethereum_istanbul_trie_imports_Trie : + IsImported globals "ethereum.istanbul.trie" "Trie". +Axiom ethereum_istanbul_trie_imports_root : + IsImported globals "ethereum.istanbul.trie" "root". +Axiom ethereum_istanbul_trie_imports_trie_set : + IsImported globals "ethereum.istanbul.trie" "trie_set". + +Axiom ethereum_istanbul_utils_message_imports_prepare_message : + IsImported globals "ethereum.istanbul.utils.message" "prepare_message". + +Axiom ethereum_istanbul_vm_interpreter_imports_process_message_call : + IsImported globals "ethereum.istanbul.vm.interpreter" "process_message_call". + +Definition BLOCK_REWARD : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + BinOp.mult (| + Constant.int 2, + BinOp.pow (| + Constant.int 10, + Constant.int 18 + |) + |) + ], + make_dict [] + |) +)). + +Definition GAS_LIMIT_ADJUSTMENT_FACTOR : Value.t := M.run ltac:(M.monadic ( + Constant.int 1024 +)). + +Definition GAS_LIMIT_MINIMUM : Value.t := M.run ltac:(M.monadic ( + Constant.int 5000 +)). + +Definition MINIMUM_DIFFICULTY : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 131072 + ], + make_dict [] + |) +)). + +Definition MAX_OMMER_DEPTH : Value.t := M.run ltac:(M.monadic ( + Constant.int 6 +)). + +Definition BOMB_DELAY_BLOCKS : Value.t := M.run ltac:(M.monadic ( + Constant.int 5000000 +)). + +Definition EMPTY_OMMER_HASH : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "keccak256" |), + make_list [ + M.call (| + M.get_field (| M.get_name (| globals, "rlp" |), "encode" |), + make_list [ + make_list [] + ], + make_dict [] + |) + ], + make_dict [] + |) +)). + +Definition BlockChain : Value.t := + builtins.make_klass + [] + [ + + ] + [ + + ]. + +Definition apply_fork : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "old" ] |) in + let _ := Constant.str " + Transforms the state from the previous hard fork (`old`) into the block + chain object for this hard fork and returns it. + + When forks need to implement an irregular state transition, this function + is used to handle the irregularity. See the :ref:`DAO Fork ` for + an example. + + Parameters + ---------- + old : + Previous block chain object. + + Returns + ------- + new : `BlockChain` + Upgraded block chain object for this hard fork. + " in + let _ := M.return_ (| + M.get_name (| globals, "old" |) + |) in + M.pure Constant.None_)). + +Definition get_last_256_block_hashes : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "chain" ] |) in + let _ := Constant.str " + Obtain the list of hashes of the previous 256 blocks in order of + increasing block number. + + This function will return less hashes for the first 256 blocks. + + The ``BLOCKHASH`` opcode needs to access the latest hashes on the chain, + therefore this function retrieves them. + + Parameters + ---------- + chain : + History and current state. + + Returns + ------- + recent_block_hashes : `List[Hash32]` + Hashes of the recent 256 blocks in order of increasing block number. + " in + let _ := M.assign_local (| + "recent_blocks" , + M.slice (| + M.get_field (| M.get_name (| globals, "chain" |), "blocks" |), + UnOp.sub (| Constant.int 255 |), + Constant.None_, + Constant.None_ + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_name (| globals, "recent_blocks" |) + ], + make_dict [] + |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + make_list [] + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "recent_block_hashes" , + make_list [] + |) in + let _ := + M.for_ (| + M.get_name (| globals, "block" |), + M.get_name (| globals, "recent_blocks" |), + ltac:(M.monadic ( + let _ := M.assign_local (| + "prev_block_hash" , + M.get_field (| M.get_field (| M.get_name (| globals, "block" |), "header" |), "parent_hash" |) + |) in + let _ := M.call (| + M.get_field (| M.get_name (| globals, "recent_block_hashes" |), "append" |), + make_list [ + M.get_name (| globals, "prev_block_hash" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := M.assign_local (| + "most_recent_block_hash" , + M.call (| + M.get_name (| globals, "keccak256" |), + make_list [ + M.call (| + M.get_field (| M.get_name (| globals, "rlp" |), "encode" |), + make_list [ + M.get_field (| M.get_subscript (| + M.get_name (| globals, "recent_blocks" |), + UnOp.sub (| Constant.int 1 |) + |), "header" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_field (| M.get_name (| globals, "recent_block_hashes" |), "append" |), + make_list [ + M.get_name (| globals, "most_recent_block_hash" |) + ], + make_dict [] + |) in + let _ := M.return_ (| + M.get_name (| globals, "recent_block_hashes" |) + |) in + M.pure Constant.None_)). + +Definition state_transition : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "chain"; "block" ] |) in + let _ := Constant.str " + Attempts to apply a block to an existing block chain. + + All parts of the block's contents need to be verified before being added + to the chain. Blocks are verified by ensuring that the contents of the + block make logical sense with the contents of the parent block. The + information in the block's header must also match the corresponding + information in the block. + + To implement Ethereum, in theory clients are only required to store the + most recent 255 blocks of the chain since as far as execution is + concerned, only those blocks are accessed. Practically, however, clients + should store more blocks to handle reorgs. + + Parameters + ---------- + chain : + History and current state. + block : + Block to apply to `chain`. + " in + let _ := M.assign_local (| + "parent_header" , + M.get_field (| M.get_subscript (| + M.get_field (| M.get_name (| globals, "chain" |), "blocks" |), + UnOp.sub (| Constant.int 1 |) + |), "header" |) + |) in + let _ := M.call (| + M.get_name (| globals, "validate_header" |), + make_list [ + M.get_field (| M.get_name (| globals, "block" |), "header" |); + M.get_name (| globals, "parent_header" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "validate_ommers" |), + make_list [ + M.get_field (| M.get_name (| globals, "block" |), "ommers" |); + M.get_field (| M.get_name (| globals, "block" |), "header" |); + M.get_name (| globals, "chain" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "apply_body_output" , + M.call (| + M.get_name (| globals, "apply_body" |), + make_list [ + M.get_field (| M.get_name (| globals, "chain" |), "state" |); + M.call (| + M.get_name (| globals, "get_last_256_block_hashes" |), + make_list [ + M.get_name (| globals, "chain" |) + ], + make_dict [] + |); + M.get_field (| M.get_field (| M.get_name (| globals, "block" |), "header" |), "coinbase" |); + M.get_field (| M.get_field (| M.get_name (| globals, "block" |), "header" |), "number" |); + M.get_field (| M.get_field (| M.get_name (| globals, "block" |), "header" |), "gas_limit" |); + M.get_field (| M.get_field (| M.get_name (| globals, "block" |), "header" |), "timestamp" |); + M.get_field (| M.get_field (| M.get_name (| globals, "block" |), "header" |), "difficulty" |); + M.get_field (| M.get_name (| globals, "block" |), "transactions" |); + M.get_field (| M.get_name (| globals, "block" |), "ommers" |); + M.get_field (| M.get_name (| globals, "chain" |), "chain_id" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + Compare.eq (| + M.get_field (| M.get_name (| globals, "apply_body_output" |), "block_gas_used" |), + M.get_field (| M.get_field (| M.get_name (| globals, "block" |), "header" |), "gas_used" |) + |); + M.get_name (| globals, "InvalidBlock" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + Compare.eq (| + M.get_field (| M.get_name (| globals, "apply_body_output" |), "transactions_root" |), + M.get_field (| M.get_field (| M.get_name (| globals, "block" |), "header" |), "transactions_root" |) + |); + M.get_name (| globals, "InvalidBlock" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + Compare.eq (| + M.get_field (| M.get_name (| globals, "apply_body_output" |), "state_root" |), + M.get_field (| M.get_field (| M.get_name (| globals, "block" |), "header" |), "state_root" |) + |); + M.get_name (| globals, "InvalidBlock" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + Compare.eq (| + M.get_field (| M.get_name (| globals, "apply_body_output" |), "receipt_root" |), + M.get_field (| M.get_field (| M.get_name (| globals, "block" |), "header" |), "receipt_root" |) + |); + M.get_name (| globals, "InvalidBlock" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + Compare.eq (| + M.get_field (| M.get_name (| globals, "apply_body_output" |), "block_logs_bloom" |), + M.get_field (| M.get_field (| M.get_name (| globals, "block" |), "header" |), "bloom" |) + |); + M.get_name (| globals, "InvalidBlock" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, "chain" |), "blocks" |), "append" |), + make_list [ + M.get_name (| globals, "block" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.gt (| + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_field (| M.get_name (| globals, "chain" |), "blocks" |) + ], + make_dict [] + |), + Constant.int 255 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign (| + M.get_field (| M.get_name (| globals, "chain" |), "blocks" |), + M.slice (| + M.get_field (| M.get_name (| globals, "chain" |), "blocks" |), + UnOp.sub (| Constant.int 255 |), + Constant.None_, + Constant.None_ + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + M.pure Constant.None_)). + +Definition validate_header : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "header"; "parent_header" ] |) in + let _ := Constant.str " + Verifies a block header. + + In order to consider a block's header valid, the logic for the + quantities in the header should match the logic for the block itself. + For example the header timestamp should be greater than the block's parent + timestamp because the block was created *after* the parent block. + Additionally, the block's number should be directly following the parent + block's number since it is the next block in the sequence. + + Parameters + ---------- + header : + Header to check for correctness. + parent_header : + Parent Header of the header to check for correctness + " in + let _ := M.assign_local (| + "parent_has_ommers" , + Compare.not_eq (| + M.get_field (| M.get_name (| globals, "parent_header" |), "ommers_hash" |), + M.get_name (| globals, "EMPTY_OMMER_HASH" |) + |) + |) in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + Compare.gt (| + M.get_field (| M.get_name (| globals, "header" |), "timestamp" |), + M.get_field (| M.get_name (| globals, "parent_header" |), "timestamp" |) + |); + M.get_name (| globals, "InvalidBlock" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + Compare.eq (| + M.get_field (| M.get_name (| globals, "header" |), "number" |), + BinOp.add (| + M.get_field (| M.get_name (| globals, "parent_header" |), "number" |), + Constant.int 1 + |) + |); + M.get_name (| globals, "InvalidBlock" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + M.call (| + M.get_name (| globals, "check_gas_limit" |), + make_list [ + M.get_field (| M.get_name (| globals, "header" |), "gas_limit" |); + M.get_field (| M.get_name (| globals, "parent_header" |), "gas_limit" |) + ], + make_dict [] + |); + M.get_name (| globals, "InvalidBlock" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + Compare.lt_e (| + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_field (| M.get_name (| globals, "header" |), "extra_data" |) + ], + make_dict [] + |), + Constant.int 32 + |); + M.get_name (| globals, "InvalidBlock" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "block_difficulty" , + M.call (| + M.get_name (| globals, "calculate_block_difficulty" |), + make_list [ + M.get_field (| M.get_name (| globals, "header" |), "number" |); + M.get_field (| M.get_name (| globals, "header" |), "timestamp" |); + M.get_field (| M.get_name (| globals, "parent_header" |), "timestamp" |); + M.get_field (| M.get_name (| globals, "parent_header" |), "difficulty" |); + M.get_name (| globals, "parent_has_ommers" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + Compare.eq (| + M.get_field (| M.get_name (| globals, "header" |), "difficulty" |), + M.get_name (| globals, "block_difficulty" |) + |); + M.get_name (| globals, "InvalidBlock" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "block_parent_hash" , + M.call (| + M.get_name (| globals, "keccak256" |), + make_list [ + M.call (| + M.get_field (| M.get_name (| globals, "rlp" |), "encode" |), + make_list [ + M.get_name (| globals, "parent_header" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + Compare.eq (| + M.get_field (| M.get_name (| globals, "header" |), "parent_hash" |), + M.get_name (| globals, "block_parent_hash" |) + |); + M.get_name (| globals, "InvalidBlock" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "validate_proof_of_work" |), + make_list [ + M.get_name (| globals, "header" |) + ], + make_dict [] + |) in + M.pure Constant.None_)). + +Definition generate_header_hash_for_pow : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "header" ] |) in + let _ := Constant.str " + Generate rlp hash of the header which is to be used for Proof-of-Work + verification. + + In other words, the PoW artefacts `mix_digest` and `nonce` are ignored + while calculating this hash. + + A particular PoW is valid for a single hash, that hash is computed by + this function. The `nonce` and `mix_digest` are omitted from this hash + because they are being changed by miners in their search for a sufficient + proof-of-work. + + Parameters + ---------- + header : + The header object for which the hash is to be generated. + + Returns + ------- + hash : `Hash32` + The PoW valid rlp hash of the passed in header. + " in + let _ := M.assign_local (| + "header_data_without_pow_artefacts" , + make_list [ + M.get_field (| M.get_name (| globals, "header" |), "parent_hash" |); + M.get_field (| M.get_name (| globals, "header" |), "ommers_hash" |); + M.get_field (| M.get_name (| globals, "header" |), "coinbase" |); + M.get_field (| M.get_name (| globals, "header" |), "state_root" |); + M.get_field (| M.get_name (| globals, "header" |), "transactions_root" |); + M.get_field (| M.get_name (| globals, "header" |), "receipt_root" |); + M.get_field (| M.get_name (| globals, "header" |), "bloom" |); + M.get_field (| M.get_name (| globals, "header" |), "difficulty" |); + M.get_field (| M.get_name (| globals, "header" |), "number" |); + M.get_field (| M.get_name (| globals, "header" |), "gas_limit" |); + M.get_field (| M.get_name (| globals, "header" |), "gas_used" |); + M.get_field (| M.get_name (| globals, "header" |), "timestamp" |); + M.get_field (| M.get_name (| globals, "header" |), "extra_data" |) + ] + |) in + let _ := M.return_ (| + M.call (| + M.get_field (| M.get_name (| globals, "rlp" |), "rlp_hash" |), + make_list [ + M.get_name (| globals, "header_data_without_pow_artefacts" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Definition validate_proof_of_work : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "header" ] |) in + let _ := Constant.str " + Validates the Proof of Work constraints. + + In order to verify that a miner's proof-of-work is valid for a block, a + ``mix-digest`` and ``result`` are calculated using the ``hashimoto_light`` + hash function. The mix digest is a hash of the header and the nonce that + is passed through and it confirms whether or not proof-of-work was done + on the correct block. The result is the actual hash value of the block. + + Parameters + ---------- + header : + Header of interest. + " in + let _ := M.assign_local (| + "header_hash" , + M.call (| + M.get_name (| globals, "generate_header_hash_for_pow" |), + make_list [ + M.get_name (| globals, "header" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "cache" , + M.call (| + M.get_name (| globals, "generate_cache" |), + make_list [ + M.get_field (| M.get_name (| globals, "header" |), "number" |) + ], + make_dict [] + |) + |) in + let _ := M.assign (| + make_tuple [ M.get_name (| globals, "mix_digest" |); M.get_name (| globals, "result" |) ], + M.call (| + M.get_name (| globals, "hashimoto_light" |), + make_list [ + M.get_name (| globals, "header_hash" |); + M.get_field (| M.get_name (| globals, "header" |), "nonce" |); + M.get_name (| globals, "cache" |); + M.call (| + M.get_name (| globals, "dataset_size" |), + make_list [ + M.get_field (| M.get_name (| globals, "header" |), "number" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + Compare.eq (| + M.get_name (| globals, "mix_digest" |), + M.get_field (| M.get_name (| globals, "header" |), "mix_digest" |) + |); + M.get_name (| globals, "InvalidBlock" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + Compare.lt_e (| + M.call (| + M.get_field (| M.get_name (| globals, "Uint" |), "from_be_bytes" |), + make_list [ + M.get_name (| globals, "result" |) + ], + make_dict [] + |), + BinOp.floor_div (| + M.get_name (| globals, "U256_CEIL_VALUE" |), + M.get_field (| M.get_name (| globals, "header" |), "difficulty" |) + |) + |); + M.get_name (| globals, "InvalidBlock" |) + ], + make_dict [] + |) in + M.pure Constant.None_)). + +Definition check_transaction : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "tx"; "gas_available"; "chain_id" ] |) in + let _ := Constant.str " + Check if the transaction is includable in the block. + + Parameters + ---------- + tx : + The transaction. + gas_available : + The gas remaining in the block. + chain_id : + The ID of the current chain. + + Returns + ------- + sender_address : + The sender of the transaction. + + Raises + ------ + InvalidBlock : + If the transaction is not includable. + " in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + Compare.lt_e (| + M.get_field (| M.get_name (| globals, "tx" |), "gas" |), + M.get_name (| globals, "gas_available" |) + |); + M.get_name (| globals, "InvalidBlock" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "sender_address" , + M.call (| + M.get_name (| globals, "recover_sender" |), + make_list [ + M.get_name (| globals, "chain_id" |); + M.get_name (| globals, "tx" |) + ], + make_dict [] + |) + |) in + let _ := M.return_ (| + M.get_name (| globals, "sender_address" |) + |) in + M.pure Constant.None_)). + +Definition make_receipt : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "tx"; "error"; "cumulative_gas_used"; "logs" ] |) in + let _ := Constant.str " + Make the receipt for a transaction that was executed. + + Parameters + ---------- + tx : + The executed transaction. + error : + Error in the top level frame of the transaction, if any. + cumulative_gas_used : + The total gas used so far in the block after the transaction was + executed. + logs : + The logs produced by the transaction. + + Returns + ------- + receipt : + The receipt for the transaction. + " in + let _ := M.assign_local (| + "receipt" , + M.call (| + M.get_name (| globals, "Receipt" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.return_ (| + M.get_name (| globals, "receipt" |) + |) in + M.pure Constant.None_)). + +Definition ApplyBodyOutput : Value.t := + builtins.make_klass + [] + [ + + ] + [ + + ]. + +Definition apply_body : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "state"; "block_hashes"; "coinbase"; "block_number"; "block_gas_limit"; "block_time"; "block_difficulty"; "transactions"; "ommers"; "chain_id" ] |) in + let _ := Constant.str " + Executes a block. + + Many of the contents of a block are stored in data structures called + tries. There is a transactions trie which is similar to a ledger of the + transactions stored in the current block. There is also a receipts trie + which stores the results of executing a transaction, like the post state + and gas used. This function creates and executes the block that is to be + added to the chain. + + Parameters + ---------- + state : + Current account state. + block_hashes : + List of hashes of the previous 256 blocks in the order of + increasing block number. + coinbase : + Address of account which receives block reward and transaction fees. + block_number : + Position of the block within the chain. + block_gas_limit : + Initial amount of gas available for execution in this block. + block_time : + Time the block was produced, measured in seconds since the epoch. + block_difficulty : + Difficulty of the block. + transactions : + Transactions included in the block. + ommers : + Headers of ancestor blocks which are not direct parents (formerly + uncles.) + chain_id : + ID of the executing chain. + + Returns + ------- + apply_body_output : `ApplyBodyOutput` + Output of applying the block body to the state. + " in + let _ := M.assign_local (| + "gas_available" , + M.get_name (| globals, "block_gas_limit" |) + |) in +(* At stmt: unsupported node type: AnnAssign *) +(* At stmt: unsupported node type: AnnAssign *) +(* At stmt: unsupported node type: AnnAssign *) + let _ := + M.for_ (| + make_tuple [ M.get_name (| globals, "i" |); M.get_name (| globals, "tx" |) ], + M.call (| + M.get_name (| globals, "enumerate" |), + make_list [ + M.get_name (| globals, "transactions" |) + ], + make_dict [] + |), + ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, "trie_set" |), + make_list [ + M.get_name (| globals, "transactions_trie" |); + M.call (| + M.get_field (| M.get_name (| globals, "rlp" |), "encode" |), + make_list [ + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.get_name (| globals, "i" |) + ], + make_dict [] + |) + ], + make_dict [] + |); + M.get_name (| globals, "tx" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "sender_address" , + M.call (| + M.get_name (| globals, "check_transaction" |), + make_list [ + M.get_name (| globals, "tx" |); + M.get_name (| globals, "gas_available" |); + M.get_name (| globals, "chain_id" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "env" , + M.call (| + M.get_field (| M.get_name (| globals, "vm" |), "Environment" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.assign (| + make_tuple [ M.get_name (| globals, "gas_used" |); M.get_name (| globals, "logs" |); M.get_name (| globals, "error" |) ], + M.call (| + M.get_name (| globals, "process_transaction" |), + make_list [ + M.get_name (| globals, "env" |); + M.get_name (| globals, "tx" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_op_local (| + BinOp.sub, + "gas_available", + M.get_name (| globals, "gas_used" |) + |) in + let _ := M.assign_local (| + "receipt" , + M.call (| + M.get_name (| globals, "make_receipt" |), + make_list [ + M.get_name (| globals, "tx" |); + M.get_name (| globals, "error" |); + BinOp.sub (| + M.get_name (| globals, "block_gas_limit" |), + M.get_name (| globals, "gas_available" |) + |); + M.get_name (| globals, "logs" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "trie_set" |), + make_list [ + M.get_name (| globals, "receipts_trie" |); + M.call (| + M.get_field (| M.get_name (| globals, "rlp" |), "encode" |), + make_list [ + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.get_name (| globals, "i" |) + ], + make_dict [] + |) + ], + make_dict [] + |); + M.get_name (| globals, "receipt" |) + ], + make_dict [] + |) in + let _ := M.assign_op_local (| + BinOp.add, + "block_logs", + M.get_name (| globals, "logs" |) + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := M.call (| + M.get_name (| globals, "pay_rewards" |), + make_list [ + M.get_name (| globals, "state" |); + M.get_name (| globals, "block_number" |); + M.get_name (| globals, "coinbase" |); + M.get_name (| globals, "ommers" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "block_gas_used" , + BinOp.sub (| + M.get_name (| globals, "block_gas_limit" |), + M.get_name (| globals, "gas_available" |) + |) + |) in + let _ := M.assign_local (| + "block_logs_bloom" , + M.call (| + M.get_name (| globals, "logs_bloom" |), + make_list [ + M.get_name (| globals, "block_logs" |) + ], + make_dict [] + |) + |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, "ApplyBodyOutput" |), + make_list [ + M.get_name (| globals, "block_gas_used" |); + M.call (| + M.get_name (| globals, "root" |), + make_list [ + M.get_name (| globals, "transactions_trie" |) + ], + make_dict [] + |); + M.call (| + M.get_name (| globals, "root" |), + make_list [ + M.get_name (| globals, "receipts_trie" |) + ], + make_dict [] + |); + M.get_name (| globals, "block_logs_bloom" |); + M.call (| + M.get_name (| globals, "state_root" |), + make_list [ + M.get_name (| globals, "state" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Definition validate_ommers : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "ommers"; "block_header"; "chain" ] |) in + let _ := Constant.str " + Validates the ommers mentioned in the block. + + An ommer block is a block that wasn't canonically added to the + blockchain because it wasn't validated as fast as the canonical block + but was mined at the same time. + + To be considered valid, the ommers must adhere to the rules defined in + the Ethereum protocol. The maximum amount of ommers is 2 per block and + there cannot be duplicate ommers in a block. Many of the other ommer + constraints are listed in the in-line comments of this function. + + Parameters + ---------- + ommers : + List of ommers mentioned in the current block. + block_header: + The header of current block. + chain : + History and current state. + " in + let _ := M.assign_local (| + "block_hash" , + M.call (| + M.get_field (| M.get_name (| globals, "rlp" |), "rlp_hash" |), + make_list [ + M.get_name (| globals, "block_header" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + Compare.eq (| + M.call (| + M.get_field (| M.get_name (| globals, "rlp" |), "rlp_hash" |), + make_list [ + M.get_name (| globals, "ommers" |) + ], + make_dict [] + |), + M.get_field (| M.get_name (| globals, "block_header" |), "ommers_hash" |) + |); + M.get_name (| globals, "InvalidBlock" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_name (| globals, "ommers" |) + ], + make_dict [] + |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + Constant.None_ + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + M.for_ (| + M.get_name (| globals, "ommer" |), + M.get_name (| globals, "ommers" |), + ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + BoolOp.and (| + Compare.lt_e (| + Constant.int 1, + M.get_field (| M.get_name (| globals, "ommer" |), "number" |) + |), + ltac:(M.monadic ( + Compare.lt (| + M.get_field (| M.get_name (| globals, "ommer" |), "number" |), + M.get_field (| M.get_name (| globals, "block_header" |), "number" |) + |) + )) + |); + M.get_name (| globals, "InvalidBlock" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "ommer_parent_header" , + M.get_field (| M.get_subscript (| + M.get_field (| M.get_name (| globals, "chain" |), "blocks" |), + BinOp.sub (| + UnOp.sub (| BinOp.sub (| + M.get_field (| M.get_name (| globals, "block_header" |), "number" |), + M.get_field (| M.get_name (| globals, "ommer" |), "number" |) + |) |), + Constant.int 1 + |) + |), "header" |) + |) in + let _ := M.call (| + M.get_name (| globals, "validate_header" |), + make_list [ + M.get_name (| globals, "ommer" |); + M.get_name (| globals, "ommer_parent_header" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + Compare.lt_e (| + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_name (| globals, "ommers" |) + ], + make_dict [] + |), + Constant.int 2 + |); + M.get_name (| globals, "InvalidBlock" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "ommers_hashes" , + Constant.str "(* At expr: unsupported node type: ListComp *)" + |) in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + Compare.eq (| + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_name (| globals, "ommers_hashes" |) + ], + make_dict [] + |), + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.call (| + M.get_name (| globals, "set" |), + make_list [ + M.get_name (| globals, "ommers_hashes" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |); + M.get_name (| globals, "InvalidBlock" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "recent_canonical_blocks" , + M.slice (| + M.get_field (| M.get_name (| globals, "chain" |), "blocks" |), + UnOp.sub (| BinOp.add (| + M.get_name (| globals, "MAX_OMMER_DEPTH" |), + Constant.int 1 + |) |), + Constant.None_, + Constant.None_ + |) + |) in + let _ := M.assign_local (| + "recent_canonical_block_hashes" , + Constant.str "(* At expr: unsupported node type: SetComp *)" + |) in +(* At stmt: unsupported node type: AnnAssign *) + let _ := + M.for_ (| + M.get_name (| globals, "block" |), + M.get_name (| globals, "recent_canonical_blocks" |), + ltac:(M.monadic ( + let _ := M.assign_local (| + "recent_ommers_hashes" , + M.call (| + M.get_field (| M.get_name (| globals, "recent_ommers_hashes" |), "union" |), + make_list [ + Constant.str "(* At expr: unsupported node type: SetComp *)" + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := + M.for_ (| + make_tuple [ M.get_name (| globals, "ommer_index" |); M.get_name (| globals, "ommer" |) ], + M.call (| + M.get_name (| globals, "enumerate" |), + make_list [ + M.get_name (| globals, "ommers" |) + ], + make_dict [] + |), + ltac:(M.monadic ( + let _ := M.assign_local (| + "ommer_hash" , + M.get_subscript (| + M.get_name (| globals, "ommers_hashes" |), + M.get_name (| globals, "ommer_index" |) + |) + |) in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + Compare.not_eq (| + M.get_name (| globals, "ommer_hash" |), + M.get_name (| globals, "block_hash" |) + |); + M.get_name (| globals, "InvalidBlock" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + Compare.not_in (| + M.get_name (| globals, "ommer_hash" |), + M.get_name (| globals, "recent_canonical_block_hashes" |) + |); + M.get_name (| globals, "InvalidBlock" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + Compare.not_in (| + M.get_name (| globals, "ommer_hash" |), + M.get_name (| globals, "recent_ommers_hashes" |) + |); + M.get_name (| globals, "InvalidBlock" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "ommer_age" , + BinOp.sub (| + M.get_field (| M.get_name (| globals, "block_header" |), "number" |), + M.get_field (| M.get_name (| globals, "ommer" |), "number" |) + |) + |) in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + BoolOp.and (| + Compare.lt_e (| + Constant.int 1, + M.get_name (| globals, "ommer_age" |) + |), + ltac:(M.monadic ( + Compare.lt_e (| + M.get_name (| globals, "ommer_age" |), + M.get_name (| globals, "MAX_OMMER_DEPTH" |) + |) + )) + |); + M.get_name (| globals, "InvalidBlock" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + Compare.in_ (| + M.get_field (| M.get_name (| globals, "ommer" |), "parent_hash" |), + M.get_name (| globals, "recent_canonical_block_hashes" |) + |); + M.get_name (| globals, "InvalidBlock" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + Compare.not_eq (| + M.get_field (| M.get_name (| globals, "ommer" |), "parent_hash" |), + M.get_field (| M.get_name (| globals, "block_header" |), "parent_hash" |) + |); + M.get_name (| globals, "InvalidBlock" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + M.pure Constant.None_)). + +Definition pay_rewards : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "state"; "block_number"; "coinbase"; "ommers" ] |) in + let _ := Constant.str " + Pay rewards to the block miner as well as the ommers miners. + + The miner of the canonical block is rewarded with the predetermined + block reward, ``BLOCK_REWARD``, plus a variable award based off of the + number of ommer blocks that were mined around the same time, and included + in the canonical block's header. An ommer block is a block that wasn't + added to the canonical blockchain because it wasn't validated as fast as + the accepted block but was mined at the same time. Although not all blocks + that are mined are added to the canonical chain, miners are still paid a + reward for their efforts. This reward is called an ommer reward and is + calculated based on the number associated with the ommer block that they + mined. + + Parameters + ---------- + state : + Current account state. + block_number : + Position of the block within the chain. + coinbase : + Address of account which receives block reward and transaction fees. + ommers : + List of ommers mentioned in the current block. + " in + let _ := M.assign_local (| + "miner_reward" , + BinOp.add (| + M.get_name (| globals, "BLOCK_REWARD" |), + BinOp.mult (| + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_name (| globals, "ommers" |) + ], + make_dict [] + |), + BinOp.floor_div (| + M.get_name (| globals, "BLOCK_REWARD" |), + Constant.int 32 + |) + |) + |) + |) in + let _ := M.call (| + M.get_name (| globals, "create_ether" |), + make_list [ + M.get_name (| globals, "state" |); + M.get_name (| globals, "coinbase" |); + M.get_name (| globals, "miner_reward" |) + ], + make_dict [] + |) in + let _ := + M.for_ (| + M.get_name (| globals, "ommer" |), + M.get_name (| globals, "ommers" |), + ltac:(M.monadic ( + let _ := M.assign_local (| + "ommer_age" , + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + BinOp.sub (| + M.get_name (| globals, "block_number" |), + M.get_field (| M.get_name (| globals, "ommer" |), "number" |) + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "ommer_miner_reward" , + BinOp.floor_div (| + BinOp.mult (| + BinOp.sub (| + Constant.int 8, + M.get_name (| globals, "ommer_age" |) + |), + M.get_name (| globals, "BLOCK_REWARD" |) + |), + Constant.int 8 + |) + |) in + let _ := M.call (| + M.get_name (| globals, "create_ether" |), + make_list [ + M.get_name (| globals, "state" |); + M.get_field (| M.get_name (| globals, "ommer" |), "coinbase" |); + M.get_name (| globals, "ommer_miner_reward" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + M.pure Constant.None_)). + +Definition process_transaction : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "env"; "tx" ] |) in + let _ := Constant.str " + Execute a transaction against the provided environment. + + This function processes the actions needed to execute a transaction. + It decrements the sender's account after calculating the gas fee and + refunds them the proper amount after execution. Calling contracts, + deploying code, and incrementing nonces are all examples of actions that + happen within this function or from a call made within this function. + + Accounts that are marked for deletion are processed and destroyed after + execution. + + Parameters + ---------- + env : + Environment for the Ethereum Virtual Machine. + tx : + Transaction to execute. + + Returns + ------- + gas_left : `ethereum.base_types.U256` + Remaining gas after execution. + logs : `Tuple[ethereum.blocks.Log, ...]` + Logs generated during execution. + " in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + M.call (| + M.get_name (| globals, "validate_transaction" |), + make_list [ + M.get_name (| globals, "tx" |) + ], + make_dict [] + |); + M.get_name (| globals, "InvalidBlock" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "sender" , + M.get_field (| M.get_name (| globals, "env" |), "origin" |) + |) in + let _ := M.assign_local (| + "sender_account" , + M.call (| + M.get_name (| globals, "get_account" |), + make_list [ + M.get_field (| M.get_name (| globals, "env" |), "state" |); + M.get_name (| globals, "sender" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "gas_fee" , + BinOp.mult (| + M.get_field (| M.get_name (| globals, "tx" |), "gas" |), + M.get_field (| M.get_name (| globals, "tx" |), "gas_price" |) + |) + |) in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + Compare.eq (| + M.get_field (| M.get_name (| globals, "sender_account" |), "nonce" |), + M.get_field (| M.get_name (| globals, "tx" |), "nonce" |) + |); + M.get_name (| globals, "InvalidBlock" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + Compare.gt_e (| + M.get_field (| M.get_name (| globals, "sender_account" |), "balance" |), + BinOp.add (| + M.get_name (| globals, "gas_fee" |), + M.get_field (| M.get_name (| globals, "tx" |), "value" |) + |) + |); + M.get_name (| globals, "InvalidBlock" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + Compare.eq (| + M.get_field (| M.get_name (| globals, "sender_account" |), "code" |), + M.call (| + M.get_name (| globals, "bytearray" |), + make_list [], + make_dict [] + |) + |); + M.get_name (| globals, "InvalidBlock" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "gas" , + BinOp.sub (| + M.get_field (| M.get_name (| globals, "tx" |), "gas" |), + M.call (| + M.get_name (| globals, "calculate_intrinsic_cost" |), + make_list [ + M.get_name (| globals, "tx" |) + ], + make_dict [] + |) + |) + |) in + let _ := M.call (| + M.get_name (| globals, "increment_nonce" |), + make_list [ + M.get_field (| M.get_name (| globals, "env" |), "state" |); + M.get_name (| globals, "sender" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "sender_balance_after_gas_fee" , + BinOp.sub (| + M.get_field (| M.get_name (| globals, "sender_account" |), "balance" |), + M.get_name (| globals, "gas_fee" |) + |) + |) in + let _ := M.call (| + M.get_name (| globals, "set_account_balance" |), + make_list [ + M.get_field (| M.get_name (| globals, "env" |), "state" |); + M.get_name (| globals, "sender" |); + M.get_name (| globals, "sender_balance_after_gas_fee" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "message" , + M.call (| + M.get_name (| globals, "prepare_message" |), + make_list [ + M.get_name (| globals, "sender" |); + M.get_field (| M.get_name (| globals, "tx" |), "to" |); + M.get_field (| M.get_name (| globals, "tx" |), "value" |); + M.get_field (| M.get_name (| globals, "tx" |), "data" |); + M.get_name (| globals, "gas" |); + M.get_name (| globals, "env" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "output" , + M.call (| + M.get_name (| globals, "process_message_call" |), + make_list [ + M.get_name (| globals, "message" |); + M.get_name (| globals, "env" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "gas_used" , + BinOp.sub (| + M.get_field (| M.get_name (| globals, "tx" |), "gas" |), + M.get_field (| M.get_name (| globals, "output" |), "gas_left" |) + |) + |) in + let _ := M.assign_local (| + "gas_refund" , + M.call (| + M.get_name (| globals, "min" |), + make_list [ + BinOp.floor_div (| + M.get_name (| globals, "gas_used" |), + Constant.int 2 + |); + M.get_field (| M.get_name (| globals, "output" |), "refund_counter" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "gas_refund_amount" , + BinOp.mult (| + BinOp.add (| + M.get_field (| M.get_name (| globals, "output" |), "gas_left" |), + M.get_name (| globals, "gas_refund" |) + |), + M.get_field (| M.get_name (| globals, "tx" |), "gas_price" |) + |) + |) in + let _ := M.assign_local (| + "transaction_fee" , + BinOp.mult (| + BinOp.sub (| + BinOp.sub (| + M.get_field (| M.get_name (| globals, "tx" |), "gas" |), + M.get_field (| M.get_name (| globals, "output" |), "gas_left" |) + |), + M.get_name (| globals, "gas_refund" |) + |), + M.get_field (| M.get_name (| globals, "tx" |), "gas_price" |) + |) + |) in + let _ := M.assign_local (| + "total_gas_used" , + BinOp.sub (| + M.get_name (| globals, "gas_used" |), + M.get_name (| globals, "gas_refund" |) + |) + |) in + let _ := M.assign_local (| + "sender_balance_after_refund" , + BinOp.add (| + M.get_field (| M.call (| + M.get_name (| globals, "get_account" |), + make_list [ + M.get_field (| M.get_name (| globals, "env" |), "state" |); + M.get_name (| globals, "sender" |) + ], + make_dict [] + |), "balance" |), + M.get_name (| globals, "gas_refund_amount" |) + |) + |) in + let _ := M.call (| + M.get_name (| globals, "set_account_balance" |), + make_list [ + M.get_field (| M.get_name (| globals, "env" |), "state" |); + M.get_name (| globals, "sender" |); + M.get_name (| globals, "sender_balance_after_refund" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "coinbase_balance_after_mining_fee" , + BinOp.add (| + M.get_field (| M.call (| + M.get_name (| globals, "get_account" |), + make_list [ + M.get_field (| M.get_name (| globals, "env" |), "state" |); + M.get_field (| M.get_name (| globals, "env" |), "coinbase" |) + ], + make_dict [] + |), "balance" |), + M.get_name (| globals, "transaction_fee" |) + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.not_eq (| + M.get_name (| globals, "coinbase_balance_after_mining_fee" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, "set_account_balance" |), + make_list [ + M.get_field (| M.get_name (| globals, "env" |), "state" |); + M.get_field (| M.get_name (| globals, "env" |), "coinbase" |); + M.get_name (| globals, "coinbase_balance_after_mining_fee" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, "account_exists_and_is_empty" |), + make_list [ + M.get_field (| M.get_name (| globals, "env" |), "state" |); + M.get_field (| M.get_name (| globals, "env" |), "coinbase" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, "destroy_account" |), + make_list [ + M.get_field (| M.get_name (| globals, "env" |), "state" |); + M.get_field (| M.get_name (| globals, "env" |), "coinbase" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )) |) in + let _ := + M.for_ (| + M.get_name (| globals, "address" |), + M.get_field (| M.get_name (| globals, "output" |), "accounts_to_delete" |), + ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, "destroy_account" |), + make_list [ + M.get_field (| M.get_name (| globals, "env" |), "state" |); + M.get_name (| globals, "address" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := + M.for_ (| + M.get_name (| globals, "address" |), + M.get_field (| M.get_name (| globals, "output" |), "touched_accounts" |), + ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, "account_exists_and_is_empty" |), + make_list [ + M.get_field (| M.get_name (| globals, "env" |), "state" |); + M.get_name (| globals, "address" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, "destroy_account" |), + make_list [ + M.get_field (| M.get_name (| globals, "env" |), "state" |); + M.get_name (| globals, "address" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := M.return_ (| + make_tuple [ M.get_name (| globals, "total_gas_used" |); M.get_field (| M.get_name (| globals, "output" |), "logs" |); M.get_field (| M.get_name (| globals, "output" |), "error" |) ] + |) in + M.pure Constant.None_)). + +Definition validate_transaction : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "tx" ] |) in + let _ := Constant.str " + Verifies a transaction. + + The gas in a transaction gets used to pay for the intrinsic cost of + operations, therefore if there is insufficient gas then it would not + be possible to execute a transaction and it will be declared invalid. + + Additionally, the nonce of a transaction must not equal or exceed the + limit defined in `EIP-2681 `_. + In practice, defining the limit as ``2**64-1`` has no impact because + sending ``2**64-1`` transactions is improbable. It's not strictly + impossible though, ``2**64-1`` transactions is the entire capacity of the + Ethereum blockchain at 2022 gas limits for a little over 22 years. + + Parameters + ---------- + tx : + Transaction to validate. + + Returns + ------- + verified : `bool` + True if the transaction can be executed, or False otherwise. + " in + let _ := M.return_ (| + BoolOp.and (| + Compare.lt_e (| + M.call (| + M.get_name (| globals, "calculate_intrinsic_cost" |), + make_list [ + M.get_name (| globals, "tx" |) + ], + make_dict [] + |), + M.get_field (| M.get_name (| globals, "tx" |), "gas" |) + |), + ltac:(M.monadic ( + Compare.lt (| + M.get_field (| M.get_name (| globals, "tx" |), "nonce" |), + BinOp.sub (| + BinOp.pow (| + Constant.int 2, + Constant.int 64 + |), + Constant.int 1 + |) + |) + )) + |) + |) in + M.pure Constant.None_)). + +Definition calculate_intrinsic_cost : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "tx" ] |) in + let _ := Constant.str " + Calculates the gas that is charged before execution is started. + + The intrinsic cost of the transaction is charged before execution has + begun. Functions/operations in the EVM cost money to execute so this + intrinsic cost is for the operations that need to be paid for as part of + the transaction. Data transfer, for example, is part of this intrinsic + cost. It costs ether to send data over the wire and that ether is + accounted for in the intrinsic cost calculated in this function. This + intrinsic cost must be calculated and paid for before execution in order + for all operations to be implemented. + + Parameters + ---------- + tx : + Transaction to compute the intrinsic cost of. + + Returns + ------- + verified : `ethereum.base_types.Uint` + The intrinsic cost of the transaction. + " in + let _ := M.assign_local (| + "data_cost" , + Constant.int 0 + |) in + let _ := + M.for_ (| + M.get_name (| globals, "byte" |), + M.get_field (| M.get_name (| globals, "tx" |), "data" |), + ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, "byte" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_op_local (| + BinOp.add, + "data_cost", + M.get_name (| globals, "TX_DATA_COST_PER_ZERO" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_op_local (| + BinOp.add, + "data_cost", + M.get_name (| globals, "TX_DATA_COST_PER_NON_ZERO" |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_field (| M.get_name (| globals, "tx" |), "to" |), + M.call (| + M.get_name (| globals, "Bytes0" |), + make_list [ + Constant.bytes "" + ], + make_dict [] + |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "create_cost" , + M.get_name (| globals, "TX_CREATE_COST" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "create_cost" , + Constant.int 0 + |) in + M.pure Constant.None_ + )) |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + BinOp.add (| + BinOp.add (| + M.get_name (| globals, "TX_BASE_COST" |), + M.get_name (| globals, "data_cost" |) + |), + M.get_name (| globals, "create_cost" |) + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Definition recover_sender : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "chain_id"; "tx" ] |) in + let _ := Constant.str " + Extracts the sender address from a transaction. + + The v, r, and s values are the three parts that make up the signature + of a transaction. In order to recover the sender of a transaction the two + components needed are the signature (``v``, ``r``, and ``s``) and the + signing hash of the transaction. The sender's public key can be obtained + with these two values and therefore the sender address can be retrieved. + + Parameters + ---------- + tx : + Transaction of interest. + chain_id : + ID of the executing chain. + + Returns + ------- + sender : `ethereum.fork_types.Address` + The address of the account that signed the transaction. + " in + let _ := M.assign (| + make_tuple [ M.get_name (| globals, "v" |); M.get_name (| globals, "r" |); M.get_name (| globals, "s" |) ], + make_tuple [ M.get_field (| M.get_name (| globals, "tx" |), "v" |); M.get_field (| M.get_name (| globals, "tx" |), "r" |); M.get_field (| M.get_name (| globals, "tx" |), "s" |) ] + |) in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + BoolOp.and (| + Compare.lt (| + Constant.int 0, + M.get_name (| globals, "r" |) + |), + ltac:(M.monadic ( + Compare.lt (| + M.get_name (| globals, "r" |), + M.get_name (| globals, "SECP256K1N" |) + |) + )) + |); + M.get_name (| globals, "InvalidBlock" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + BoolOp.and (| + Compare.lt (| + Constant.int 0, + M.get_name (| globals, "s" |) + |), + ltac:(M.monadic ( + Compare.lt_e (| + M.get_name (| globals, "s" |), + BinOp.floor_div (| + M.get_name (| globals, "SECP256K1N" |), + Constant.int 2 + |) + |) + )) + |); + M.get_name (| globals, "InvalidBlock" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + BoolOp.or (| + Compare.eq (| + M.get_name (| globals, "v" |), + Constant.int 27 + |), + ltac:(M.monadic ( + Compare.eq (| + M.get_name (| globals, "v" |), + Constant.int 28 + |) + )) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "public_key" , + M.call (| + M.get_name (| globals, "secp256k1_recover" |), + make_list [ + M.get_name (| globals, "r" |); + M.get_name (| globals, "s" |); + BinOp.sub (| + M.get_name (| globals, "v" |), + Constant.int 27 + |); + M.call (| + M.get_name (| globals, "signing_hash_pre155" |), + make_list [ + M.get_name (| globals, "tx" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + BoolOp.or (| + Compare.eq (| + M.get_name (| globals, "v" |), + BinOp.add (| + Constant.int 35, + BinOp.mult (| + M.get_name (| globals, "chain_id" |), + Constant.int 2 + |) + |) + |), + ltac:(M.monadic ( + Compare.eq (| + M.get_name (| globals, "v" |), + BinOp.add (| + Constant.int 36, + BinOp.mult (| + M.get_name (| globals, "chain_id" |), + Constant.int 2 + |) + |) + |) + )) + |); + M.get_name (| globals, "InvalidBlock" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "public_key" , + M.call (| + M.get_name (| globals, "secp256k1_recover" |), + make_list [ + M.get_name (| globals, "r" |); + M.get_name (| globals, "s" |); + BinOp.sub (| + BinOp.sub (| + M.get_name (| globals, "v" |), + Constant.int 35 + |), + BinOp.mult (| + M.get_name (| globals, "chain_id" |), + Constant.int 2 + |) + |); + M.call (| + M.get_name (| globals, "signing_hash_155" |), + make_list [ + M.get_name (| globals, "tx" |); + M.get_name (| globals, "chain_id" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + )) |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, "Address" |), + make_list [ + M.slice (| + M.call (| + M.get_name (| globals, "keccak256" |), + make_list [ + M.get_name (| globals, "public_key" |) + ], + make_dict [] + |), + Constant.int 12, + Constant.int 32, + Constant.None_ + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Definition signing_hash_pre155 : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "tx" ] |) in + let _ := Constant.str " + Compute the hash of a transaction used in a legacy (pre EIP 155) signature. + + Parameters + ---------- + tx : + Transaction of interest. + + Returns + ------- + hash : `ethereum.crypto.hash.Hash32` + Hash of the transaction. + " in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, "keccak256" |), + make_list [ + M.call (| + M.get_field (| M.get_name (| globals, "rlp" |), "encode" |), + make_list [ + make_tuple [ M.get_field (| M.get_name (| globals, "tx" |), "nonce" |); M.get_field (| M.get_name (| globals, "tx" |), "gas_price" |); M.get_field (| M.get_name (| globals, "tx" |), "gas" |); M.get_field (| M.get_name (| globals, "tx" |), "to" |); M.get_field (| M.get_name (| globals, "tx" |), "value" |); M.get_field (| M.get_name (| globals, "tx" |), "data" |) ] + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Definition signing_hash_155 : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "tx"; "chain_id" ] |) in + let _ := Constant.str " + Compute the hash of a transaction used in a EIP 155 signature. + + Parameters + ---------- + tx : + Transaction of interest. + chain_id : + The id of the current chain. + + Returns + ------- + hash : `ethereum.crypto.hash.Hash32` + Hash of the transaction. + " in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, "keccak256" |), + make_list [ + M.call (| + M.get_field (| M.get_name (| globals, "rlp" |), "encode" |), + make_list [ + make_tuple [ M.get_field (| M.get_name (| globals, "tx" |), "nonce" |); M.get_field (| M.get_name (| globals, "tx" |), "gas_price" |); M.get_field (| M.get_name (| globals, "tx" |), "gas" |); M.get_field (| M.get_name (| globals, "tx" |), "to" |); M.get_field (| M.get_name (| globals, "tx" |), "value" |); M.get_field (| M.get_name (| globals, "tx" |), "data" |); M.get_name (| globals, "chain_id" |); M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |); M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) ] + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Definition compute_header_hash : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "header" ] |) in + let _ := Constant.str " + Computes the hash of a block header. + + The header hash of a block is the canonical hash that is used to refer + to a specific block and completely distinguishes a block from another. + + ``keccak256`` is a function that produces a 256 bit hash of any input. + It also takes in any number of bytes as an input and produces a single + hash for them. A hash is a completely unique output for a single input. + So an input corresponds to one unique hash that can be used to identify + the input exactly. + + Prior to using the ``keccak256`` hash function, the header must be + encoded using the Recursive-Length Prefix. See :ref:`rlp`. + RLP encoding the header converts it into a space-efficient format that + allows for easy transfer of data between nodes. The purpose of RLP is to + encode arbitrarily nested arrays of binary data, and RLP is the primary + encoding method used to serialize objects in Ethereum's execution layer. + The only purpose of RLP is to encode structure; encoding specific data + types (e.g. strings, floats) is left up to higher-order protocols. + + Parameters + ---------- + header : + Header of interest. + + Returns + ------- + hash : `ethereum.crypto.hash.Hash32` + Hash of the header. + " in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, "keccak256" |), + make_list [ + M.call (| + M.get_field (| M.get_name (| globals, "rlp" |), "encode" |), + make_list [ + M.get_name (| globals, "header" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Definition check_gas_limit : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "gas_limit"; "parent_gas_limit" ] |) in + let _ := Constant.str " + Validates the gas limit for a block. + + The bounds of the gas limit, ``max_adjustment_delta``, is set as the + quotient of the parent block's gas limit and the + ``GAS_LIMIT_ADJUSTMENT_FACTOR``. Therefore, if the gas limit that is + passed through as a parameter is greater than or equal to the *sum* of + the parent's gas and the adjustment delta then the limit for gas is too + high and fails this function's check. Similarly, if the limit is less + than or equal to the *difference* of the parent's gas and the adjustment + delta *or* the predefined ``GAS_LIMIT_MINIMUM`` then this function's + check fails because the gas limit doesn't allow for a sufficient or + reasonable amount of gas to be used on a block. + + Parameters + ---------- + gas_limit : + Gas limit to validate. + + parent_gas_limit : + Gas limit of the parent block. + + Returns + ------- + check : `bool` + True if gas limit constraints are satisfied, False otherwise. + " in + let _ := M.assign_local (| + "max_adjustment_delta" , + BinOp.floor_div (| + M.get_name (| globals, "parent_gas_limit" |), + M.get_name (| globals, "GAS_LIMIT_ADJUSTMENT_FACTOR" |) + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.gt_e (| + M.get_name (| globals, "gas_limit" |), + BinOp.add (| + M.get_name (| globals, "parent_gas_limit" |), + M.get_name (| globals, "max_adjustment_delta" |) + |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + Constant.bool false + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + Compare.lt_e (| + M.get_name (| globals, "gas_limit" |), + BinOp.sub (| + M.get_name (| globals, "parent_gas_limit" |), + M.get_name (| globals, "max_adjustment_delta" |) + |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + Constant.bool false + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + Compare.lt (| + M.get_name (| globals, "gas_limit" |), + M.get_name (| globals, "GAS_LIMIT_MINIMUM" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + Constant.bool false + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.return_ (| + Constant.bool true + |) in + M.pure Constant.None_)). + +Definition calculate_block_difficulty : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "block_number"; "block_timestamp"; "parent_timestamp"; "parent_difficulty"; "parent_has_ommers" ] |) in + let _ := Constant.str " + Computes difficulty of a block using its header and parent header. + + The difficulty is determined by the time the block was created after its + parent. The ``offset`` is calculated using the parent block's difficulty, + ``parent_difficulty``, and the timestamp between blocks. This offset is + then added to the parent difficulty and is stored as the ``difficulty`` + variable. If the time between the block and its parent is too short, the + offset will result in a positive number thus making the sum of + ``parent_difficulty`` and ``offset`` to be a greater value in order to + avoid mass forking. But, if the time is long enough, then the offset + results in a negative value making the block less difficult than + its parent. + + The base standard for a block's difficulty is the predefined value + set for the genesis block since it has no parent. So, a block + can't be less difficult than the genesis block, therefore each block's + difficulty is set to the maximum value between the calculated + difficulty and the ``GENESIS_DIFFICULTY``. + + Parameters + ---------- + block_number : + Block number of the block. + block_timestamp : + Timestamp of the block. + parent_timestamp : + Timestamp of the parent block. + parent_difficulty : + difficulty of the parent block. + parent_has_ommers: + does the parent have ommers. + + Returns + ------- + difficulty : `ethereum.base_types.Uint` + Computed difficulty for a block. + " in + let _ := M.assign_local (| + "offset" , + BinOp.mult (| + BinOp.floor_div (| + M.call (| + M.get_name (| globals, "int" |), + make_list [ + M.get_name (| globals, "parent_difficulty" |) + ], + make_dict [] + |), + Constant.int 2048 + |), + M.call (| + M.get_name (| globals, "max" |), + make_list [ + BinOp.sub (| + (* if *) + M.if_then_else (| + M.get_name (| globals, "parent_has_ommers" |), + (* then *) + ltac:(M.monadic ( +Constant.int 2 + (* else *) + )), ltac:(M.monadic ( +Constant.int 1 + )) |), + BinOp.floor_div (| + M.call (| + M.get_name (| globals, "int" |), + make_list [ + BinOp.sub (| + M.get_name (| globals, "block_timestamp" |), + M.get_name (| globals, "parent_timestamp" |) + |) + ], + make_dict [] + |), + Constant.int 9 + |) + |); + UnOp.sub (| Constant.int 99 |) + ], + make_dict [] + |) + |) + |) in + let _ := M.assign_local (| + "difficulty" , + BinOp.add (| + M.call (| + M.get_name (| globals, "int" |), + make_list [ + M.get_name (| globals, "parent_difficulty" |) + ], + make_dict [] + |), + M.get_name (| globals, "offset" |) + |) + |) in + let _ := M.assign_local (| + "num_bomb_periods" , + BinOp.sub (| + BinOp.floor_div (| + BinOp.sub (| + M.call (| + M.get_name (| globals, "int" |), + make_list [ + M.get_name (| globals, "block_number" |) + ], + make_dict [] + |), + M.get_name (| globals, "BOMB_DELAY_BLOCKS" |) + |), + Constant.int 100000 + |), + Constant.int 2 + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.gt_e (| + M.get_name (| globals, "num_bomb_periods" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_op_local (| + BinOp.add, + "difficulty", + BinOp.pow (| + Constant.int 2, + M.get_name (| globals, "num_bomb_periods" |) + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, "max" |), + make_list [ + M.get_name (| globals, "difficulty" |); + M.get_name (| globals, "MINIMUM_DIFFICULTY" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). diff --git a/CoqOfPython/ethereum/istanbul/fork_types.v b/CoqOfPython/ethereum/istanbul/fork_types.v new file mode 100644 index 0000000..f19cd79 --- /dev/null +++ b/CoqOfPython/ethereum/istanbul/fork_types.v @@ -0,0 +1,98 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.istanbul.fork_types". + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Types +^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Types re-used throughout the specification, which are specific to Ethereum. +". + +Axiom dataclasses_imports_dataclass : + IsImported globals "dataclasses" "dataclass". + +Axiom ethereum_imports_rlp : + IsImported globals "ethereum" "rlp". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_Bytes : + IsImported globals "ethereum.base_types" "Bytes". +Axiom ethereum_base_types_imports_Bytes20 : + IsImported globals "ethereum.base_types" "Bytes20". +Axiom ethereum_base_types_imports_Bytes256 : + IsImported globals "ethereum.base_types" "Bytes256". +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". +Axiom ethereum_base_types_imports_slotted_freezable : + IsImported globals "ethereum.base_types" "slotted_freezable". + +Axiom ethereum_crypto_hash_imports_Hash32 : + IsImported globals "ethereum.crypto.hash" "Hash32". +Axiom ethereum_crypto_hash_imports_keccak256 : + IsImported globals "ethereum.crypto.hash" "keccak256". + +Definition Address : Value.t := M.run ltac:(M.monadic ( + M.get_name (| globals, "Bytes20" |) +)). + +Definition Root : Value.t := M.run ltac:(M.monadic ( + M.get_name (| globals, "Hash32" |) +)). + +Definition Bloom : Value.t := M.run ltac:(M.monadic ( + M.get_name (| globals, "Bytes256" |) +)). + +Definition Account : Value.t := + builtins.make_klass + [] + [ + + ] + [ + + ]. + +Definition EMPTY_ACCOUNT : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Account" |), + make_list [], + make_dict [] + |) +)). + +Definition encode_account : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "raw_account_data"; "storage_root" ] |) in + let _ := Constant.str " + Encode `Account` dataclass. + + Storage is not stored in the `Account` dataclass, so `Accounts` cannot be + encoded with providing a storage root. + " in + let _ := M.return_ (| + M.call (| + M.get_field (| M.get_name (| globals, "rlp" |), "encode" |), + make_list [ + make_tuple [ M.get_field (| M.get_name (| globals, "raw_account_data" |), "nonce" |); M.get_field (| M.get_name (| globals, "raw_account_data" |), "balance" |); M.get_name (| globals, "storage_root" |); M.call (| + M.get_name (| globals, "keccak256" |), + make_list [ + M.get_field (| M.get_name (| globals, "raw_account_data" |), "code" |) + ], + make_dict [] + |) ] + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). diff --git a/CoqOfPython/ethereum/istanbul/state.v b/CoqOfPython/ethereum/istanbul/state.v new file mode 100644 index 0000000..d2aaed7 --- /dev/null +++ b/CoqOfPython/ethereum/istanbul/state.v @@ -0,0 +1,1279 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.istanbul.state". + +Definition expr_1 : Value.t := + Constant.str " +State +^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +The state contains all information that is preserved between transactions. + +It consists of a main account trie and storage tries for each contract. + +There is a distinction between an account that does not exist and +`EMPTY_ACCOUNT`. +". + +Axiom dataclasses_imports_dataclass : + IsImported globals "dataclasses" "dataclass". +Axiom dataclasses_imports_field : + IsImported globals "dataclasses" "field". + +Axiom typing_imports_Callable : + IsImported globals "typing" "Callable". +Axiom typing_imports_Dict : + IsImported globals "typing" "Dict". +Axiom typing_imports_List : + IsImported globals "typing" "List". +Axiom typing_imports_Optional : + IsImported globals "typing" "Optional". +Axiom typing_imports_Set : + IsImported globals "typing" "Set". +Axiom typing_imports_Tuple : + IsImported globals "typing" "Tuple". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_Bytes : + IsImported globals "ethereum.base_types" "Bytes". +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". +Axiom ethereum_base_types_imports_modify : + IsImported globals "ethereum.base_types" "modify". + +Axiom ethereum_utils_ensure_imports_ensure : + IsImported globals "ethereum.utils.ensure" "ensure". + +Axiom ethereum_istanbul_fork_types_imports_EMPTY_ACCOUNT : + IsImported globals "ethereum.istanbul.fork_types" "EMPTY_ACCOUNT". +Axiom ethereum_istanbul_fork_types_imports_Account : + IsImported globals "ethereum.istanbul.fork_types" "Account". +Axiom ethereum_istanbul_fork_types_imports_Address : + IsImported globals "ethereum.istanbul.fork_types" "Address". +Axiom ethereum_istanbul_fork_types_imports_Root : + IsImported globals "ethereum.istanbul.fork_types" "Root". + +Axiom ethereum_istanbul_trie_imports_EMPTY_TRIE_ROOT : + IsImported globals "ethereum.istanbul.trie" "EMPTY_TRIE_ROOT". +Axiom ethereum_istanbul_trie_imports_Trie : + IsImported globals "ethereum.istanbul.trie" "Trie". +Axiom ethereum_istanbul_trie_imports_copy_trie : + IsImported globals "ethereum.istanbul.trie" "copy_trie". +Axiom ethereum_istanbul_trie_imports_root : + IsImported globals "ethereum.istanbul.trie" "root". +Axiom ethereum_istanbul_trie_imports_trie_get : + IsImported globals "ethereum.istanbul.trie" "trie_get". +Axiom ethereum_istanbul_trie_imports_trie_set : + IsImported globals "ethereum.istanbul.trie" "trie_set". + +Definition State : Value.t := + builtins.make_klass + [] + [ + + ] + [ + + ]. + +Definition close_state : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "state" ] |) in + let _ := Constant.str " + Free resources held by the state. Used by optimized implementations to + release file descriptors. + " in + let _ := M.delete (| M.get_field (| M.get_name (| globals, "state" |), "_main_trie" |) |) in + let _ := M.delete (| M.get_field (| M.get_name (| globals, "state" |), "_storage_tries" |) |) in + let _ := M.delete (| M.get_field (| M.get_name (| globals, "state" |), "_snapshots" |) |) in + let _ := M.delete (| M.get_field (| M.get_name (| globals, "state" |), "_created_accounts" |) |) in + M.pure Constant.None_)). + +Definition begin_transaction : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "state" ] |) in + let _ := Constant.str " + Start a state transaction. + + Transactions are entirely implicit and can be nested. It is not possible to + calculate the state root during a transaction. + + Parameters + ---------- + state : State + The state. + " in + let _ := M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, "state" |), "_snapshots" |), "append" |), + make_list [ + make_tuple [ M.call (| + M.get_name (| globals, "copy_trie" |), + make_list [ + M.get_field (| M.get_name (| globals, "state" |), "_main_trie" |) + ], + make_dict [] + |); Constant.str "(* At expr: unsupported node type: DictComp *)" ] + ], + make_dict [] + |) in + M.pure Constant.None_)). + +Definition commit_transaction : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "state" ] |) in + let _ := Constant.str " + Commit a state transaction. + + Parameters + ---------- + state : State + The state. + " in + let _ := M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, "state" |), "_snapshots" |), "pop" |), + make_list [], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + UnOp.not (| M.get_field (| M.get_name (| globals, "state" |), "_snapshots" |) |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, "state" |), "_created_accounts" |), "clear" |), + make_list [], + make_dict [] + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + M.pure Constant.None_)). + +Definition rollback_transaction : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "state" ] |) in + let _ := Constant.str " + Rollback a state transaction, resetting the state to the point when the + corresponding `start_transaction()` call was made. + + Parameters + ---------- + state : State + The state. + " in + let _ := M.assign (| + make_tuple [ M.get_field (| M.get_name (| globals, "state" |), "_main_trie" |); M.get_field (| M.get_name (| globals, "state" |), "_storage_tries" |) ], + M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, "state" |), "_snapshots" |), "pop" |), + make_list [], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + UnOp.not (| M.get_field (| M.get_name (| globals, "state" |), "_snapshots" |) |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, "state" |), "_created_accounts" |), "clear" |), + make_list [], + make_dict [] + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + M.pure Constant.None_)). + +Definition get_account : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "state"; "address" ] |) in + let _ := Constant.str " + Get the `Account` object at an address. Returns `EMPTY_ACCOUNT` if there + is no account at the address. + + Use `get_account_optional()` if you care about the difference between a + non-existent account and `EMPTY_ACCOUNT`. + + Parameters + ---------- + state: `State` + The state + address : `Address` + Address to lookup. + + Returns + ------- + account : `Account` + Account at address. + " in + let _ := M.assign_local (| + "account" , + M.call (| + M.get_name (| globals, "get_account_optional" |), + make_list [ + M.get_name (| globals, "state" |); + M.get_name (| globals, "address" |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, "isinstance" |), + make_list [ + M.get_name (| globals, "account" |); + M.get_name (| globals, "Account" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + M.get_name (| globals, "account" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.return_ (| + M.get_name (| globals, "EMPTY_ACCOUNT" |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_)). + +Definition get_account_optional : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "state"; "address" ] |) in + let _ := Constant.str " + Get the `Account` object at an address. Returns `None` (rather than + `EMPTY_ACCOUNT`) if there is no account at the address. + + Parameters + ---------- + state: `State` + The state + address : `Address` + Address to lookup. + + Returns + ------- + account : `Account` + Account at address. + " in + let _ := M.assign_local (| + "account" , + M.call (| + M.get_name (| globals, "trie_get" |), + make_list [ + M.get_field (| M.get_name (| globals, "state" |), "_main_trie" |); + M.get_name (| globals, "address" |) + ], + make_dict [] + |) + |) in + let _ := M.return_ (| + M.get_name (| globals, "account" |) + |) in + M.pure Constant.None_)). + +Definition set_account : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "state"; "address"; "account" ] |) in + let _ := Constant.str " + Set the `Account` object at an address. Setting to `None` deletes + the account (but not its storage, see `destroy_account()`). + + Parameters + ---------- + state: `State` + The state + address : `Address` + Address to set. + account : `Account` + Account to set at address. + " in + let _ := M.call (| + M.get_name (| globals, "trie_set" |), + make_list [ + M.get_field (| M.get_name (| globals, "state" |), "_main_trie" |); + M.get_name (| globals, "address" |); + M.get_name (| globals, "account" |) + ], + make_dict [] + |) in + M.pure Constant.None_)). + +Definition destroy_account : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "state"; "address" ] |) in + let _ := Constant.str " + Completely remove the account at `address` and all of its storage. + + This function is made available exclusively for the `SELFDESTRUCT` + opcode. It is expected that `SELFDESTRUCT` will be disabled in a future + hardfork and this function will be removed. + + Parameters + ---------- + state: `State` + The state + address : `Address` + Address of account to destroy. + " in + let _ := M.call (| + M.get_name (| globals, "destroy_storage" |), + make_list [ + M.get_name (| globals, "state" |); + M.get_name (| globals, "address" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "set_account" |), + make_list [ + M.get_name (| globals, "state" |); + M.get_name (| globals, "address" |); + Constant.None_ + ], + make_dict [] + |) in + M.pure Constant.None_)). + +Definition destroy_storage : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "state"; "address" ] |) in + let _ := Constant.str " + Completely remove the storage at `address`. + + Parameters + ---------- + state: `State` + The state + address : `Address` + Address of account whose storage is to be deleted. + " in + let _ := + (* if *) + M.if_then_else (| + Compare.in_ (| + M.get_name (| globals, "address" |), + M.get_field (| M.get_name (| globals, "state" |), "_storage_tries" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.delete (| M.get_subscript (| + M.get_field (| M.get_name (| globals, "state" |), "_storage_tries" |), + M.get_name (| globals, "address" |) + |) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + M.pure Constant.None_)). + +Definition mark_account_created : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "state"; "address" ] |) in + let _ := Constant.str " + Mark an account as having been created in the current transaction. + This information is used by `get_storage_original()` to handle an obscure + edgecase. + + The marker is not removed even if the account creation reverts. Since the + account cannot have had code prior to its creation and can't call + `get_storage_original()`, this is harmless. + + Parameters + ---------- + state: `State` + The state + address : `Address` + Address of the account that has been created. + " in + let _ := M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, "state" |), "_created_accounts" |), "add" |), + make_list [ + M.get_name (| globals, "address" |) + ], + make_dict [] + |) in + M.pure Constant.None_)). + +Definition get_storage : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "state"; "address"; "key" ] |) in + let _ := Constant.str " + Get a value at a storage key on an account. Returns `U256(0)` if the + storage key has not been set previously. + + Parameters + ---------- + state: `State` + The state + address : `Address` + Address of the account. + key : `Bytes` + Key to lookup. + + Returns + ------- + value : `U256` + Value at the key. + " in + let _ := M.assign_local (| + "trie" , + M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, "state" |), "_storage_tries" |), "get" |), + make_list [ + M.get_name (| globals, "address" |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.is (| + M.get_name (| globals, "trie" |), + Constant.None_ + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "value" , + M.call (| + M.get_name (| globals, "trie_get" |), + make_list [ + M.get_name (| globals, "trie" |); + M.get_name (| globals, "key" |) + ], + make_dict [] + |) + |) in + let _ := M.assert (| M.call (| + M.get_name (| globals, "isinstance" |), + make_list [ + M.get_name (| globals, "value" |); + M.get_name (| globals, "U256" |) + ], + make_dict [] + |) |) in + let _ := M.return_ (| + M.get_name (| globals, "value" |) + |) in + M.pure Constant.None_)). + +Definition set_storage : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "state"; "address"; "key"; "value" ] |) in + let _ := Constant.str " + Set a value at a storage key on an account. Setting to `U256(0)` deletes + the key. + + Parameters + ---------- + state: `State` + The state + address : `Address` + Address of the account. + key : `Bytes` + Key to set. + value : `U256` + Value to set at the key. + " in + let _ := M.assert (| Compare.is_not (| + M.call (| + M.get_name (| globals, "trie_get" |), + make_list [ + M.get_field (| M.get_name (| globals, "state" |), "_main_trie" |); + M.get_name (| globals, "address" |) + ], + make_dict [] + |), + Constant.None_ + |) |) in + let _ := M.assign_local (| + "trie" , + M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, "state" |), "_storage_tries" |), "get" |), + make_list [ + M.get_name (| globals, "address" |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.is (| + M.get_name (| globals, "trie" |), + Constant.None_ + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "trie" , + M.call (| + M.get_name (| globals, "Trie" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.assign (| + M.get_subscript (| + M.get_field (| M.get_name (| globals, "state" |), "_storage_tries" |), + M.get_name (| globals, "address" |) + |), + M.get_name (| globals, "trie" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.call (| + M.get_name (| globals, "trie_set" |), + make_list [ + M.get_name (| globals, "trie" |); + M.get_name (| globals, "key" |); + M.get_name (| globals, "value" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_field (| M.get_name (| globals, "trie" |), "_data" |), + Constant.str "(* At expr: unsupported node type: Dict *)" + |), + (* then *) + ltac:(M.monadic ( + let _ := M.delete (| M.get_subscript (| + M.get_field (| M.get_name (| globals, "state" |), "_storage_tries" |), + M.get_name (| globals, "address" |) + |) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + M.pure Constant.None_)). + +Definition storage_root : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "state"; "address" ] |) in + let _ := Constant.str " + Calculate the storage root of an account. + + Parameters + ---------- + state: + The state + address : + Address of the account. + + Returns + ------- + root : `Root` + Storage root of the account. + " in + let _ := M.assert (| UnOp.not (| M.get_field (| M.get_name (| globals, "state" |), "_snapshots" |) |) |) in + let _ := + (* if *) + M.if_then_else (| + Compare.in_ (| + M.get_name (| globals, "address" |), + M.get_field (| M.get_name (| globals, "state" |), "_storage_tries" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + M.call (| + M.get_name (| globals, "root" |), + make_list [ + M.get_subscript (| + M.get_field (| M.get_name (| globals, "state" |), "_storage_tries" |), + M.get_name (| globals, "address" |) + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.return_ (| + M.get_name (| globals, "EMPTY_TRIE_ROOT" |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_)). + +Definition state_root : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "state" ] |) in + let _ := Constant.str " + Calculate the state root. + + Parameters + ---------- + state: + The current state. + + Returns + ------- + root : `Root` + The state root. + " in + let _ := M.assert (| UnOp.not (| M.get_field (| M.get_name (| globals, "state" |), "_snapshots" |) |) |) in +(* At stmt: unsupported node type: FunctionDef *) + let _ := M.return_ (| + M.call (| + M.get_name (| globals, "root" |), + make_list [ + M.get_field (| M.get_name (| globals, "state" |), "_main_trie" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Definition account_exists : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "state"; "address" ] |) in + let _ := Constant.str " + Checks if an account exists in the state trie + + Parameters + ---------- + state: + The state + address: + Address of the account that needs to be checked. + + Returns + ------- + account_exists : `bool` + True if account exists in the state trie, False otherwise + " in + let _ := M.return_ (| + Compare.is_not (| + M.call (| + M.get_name (| globals, "get_account_optional" |), + make_list [ + M.get_name (| globals, "state" |); + M.get_name (| globals, "address" |) + ], + make_dict [] + |), + Constant.None_ + |) + |) in + M.pure Constant.None_)). + +Definition account_has_code_or_nonce : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "state"; "address" ] |) in + let _ := Constant.str " + Checks if an account has non zero nonce or non empty code + + Parameters + ---------- + state: + The state + address: + Address of the account that needs to be checked. + + Returns + ------- + has_code_or_nonce : `bool` + True if if an account has non zero nonce or non empty code, + False otherwise. + " in + let _ := M.assign_local (| + "account" , + M.call (| + M.get_name (| globals, "get_account" |), + make_list [ + M.get_name (| globals, "state" |); + M.get_name (| globals, "address" |) + ], + make_dict [] + |) + |) in + let _ := M.return_ (| + BoolOp.or (| + Compare.not_eq (| + M.get_field (| M.get_name (| globals, "account" |), "nonce" |), + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + |), + ltac:(M.monadic ( + Compare.not_eq (| + M.get_field (| M.get_name (| globals, "account" |), "code" |), + Constant.bytes "" + |) + )) + |) + |) in + M.pure Constant.None_)). + +Definition is_account_empty : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "state"; "address" ] |) in + let _ := Constant.str " + Checks if an account has zero nonce, empty code and zero balance. + + Parameters + ---------- + state: + The state + address: + Address of the account that needs to be checked. + + Returns + ------- + is_empty : `bool` + True if if an account has zero nonce, empty code and zero balance, + False otherwise. + " in + let _ := M.assign_local (| + "account" , + M.call (| + M.get_name (| globals, "get_account" |), + make_list [ + M.get_name (| globals, "state" |); + M.get_name (| globals, "address" |) + ], + make_dict [] + |) + |) in + let _ := M.return_ (| + BoolOp.and (| + Compare.eq (| + M.get_field (| M.get_name (| globals, "account" |), "nonce" |), + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + |), + ltac:(M.monadic ( + BoolOp.and (| + Compare.eq (| + M.get_field (| M.get_name (| globals, "account" |), "code" |), + Constant.bytes "" + |), + ltac:(M.monadic ( + Compare.eq (| + M.get_field (| M.get_name (| globals, "account" |), "balance" |), + Constant.int 0 + |) + )) + |) + )) + |) + |) in + M.pure Constant.None_)). + +Definition account_exists_and_is_empty : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "state"; "address" ] |) in + let _ := Constant.str " + Checks if an account exists and has zero nonce, empty code and zero + balance. + + Parameters + ---------- + state: + The state + address: + Address of the account that needs to be checked. + + Returns + ------- + exists_and_is_empty : `bool` + True if an account exists and has zero nonce, empty code and zero + balance, False otherwise. + " in + let _ := M.assign_local (| + "account" , + M.call (| + M.get_name (| globals, "get_account_optional" |), + make_list [ + M.get_name (| globals, "state" |); + M.get_name (| globals, "address" |) + ], + make_dict [] + |) + |) in + let _ := M.return_ (| + BoolOp.and (| + Compare.is_not (| + M.get_name (| globals, "account" |), + Constant.None_ + |), + ltac:(M.monadic ( + BoolOp.and (| + Compare.eq (| + M.get_field (| M.get_name (| globals, "account" |), "nonce" |), + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + |), + ltac:(M.monadic ( + BoolOp.and (| + Compare.eq (| + M.get_field (| M.get_name (| globals, "account" |), "code" |), + Constant.bytes "" + |), + ltac:(M.monadic ( + Compare.eq (| + M.get_field (| M.get_name (| globals, "account" |), "balance" |), + Constant.int 0 + |) + )) + |) + )) + |) + )) + |) + |) in + M.pure Constant.None_)). + +Definition is_account_alive : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "state"; "address" ] |) in + let _ := Constant.str " + Check whether is an account is both in the state and non empty. + + Parameters + ---------- + state: + The state + address: + Address of the account that needs to be checked. + + Returns + ------- + is_alive : `bool` + True if the account is alive. + " in + let _ := M.assign_local (| + "account" , + M.call (| + M.get_name (| globals, "get_account_optional" |), + make_list [ + M.get_name (| globals, "state" |); + M.get_name (| globals, "address" |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.is (| + M.get_name (| globals, "account" |), + Constant.None_ + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + Constant.bool false + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.return_ (| + UnOp.not (| BoolOp.and (| + Compare.eq (| + M.get_field (| M.get_name (| globals, "account" |), "nonce" |), + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + |), + ltac:(M.monadic ( + BoolOp.and (| + Compare.eq (| + M.get_field (| M.get_name (| globals, "account" |), "code" |), + Constant.bytes "" + |), + ltac:(M.monadic ( + Compare.eq (| + M.get_field (| M.get_name (| globals, "account" |), "balance" |), + Constant.int 0 + |) + )) + |) + )) + |) |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_)). + +Definition modify_state : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "state"; "address"; "f" ] |) in + let _ := Constant.str " + Modify an `Account` in the `State`. + " in + let _ := M.call (| + M.get_name (| globals, "set_account" |), + make_list [ + M.get_name (| globals, "state" |); + M.get_name (| globals, "address" |); + M.call (| + M.get_name (| globals, "modify" |), + make_list [ + M.call (| + M.get_name (| globals, "get_account" |), + make_list [ + M.get_name (| globals, "state" |); + M.get_name (| globals, "address" |) + ], + make_dict [] + |); + M.get_name (| globals, "f" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + M.pure Constant.None_)). + +Definition move_ether : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "state"; "sender_address"; "recipient_address"; "amount" ] |) in + let _ := Constant.str " + Move funds between accounts. + " in +(* At stmt: unsupported node type: FunctionDef *) +(* At stmt: unsupported node type: FunctionDef *) + let _ := M.call (| + M.get_name (| globals, "modify_state" |), + make_list [ + M.get_name (| globals, "state" |); + M.get_name (| globals, "sender_address" |); + M.get_name (| globals, "reduce_sender_balance" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "modify_state" |), + make_list [ + M.get_name (| globals, "state" |); + M.get_name (| globals, "recipient_address" |); + M.get_name (| globals, "increase_recipient_balance" |) + ], + make_dict [] + |) in + M.pure Constant.None_)). + +Definition set_account_balance : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "state"; "address"; "amount" ] |) in + let _ := Constant.str " + Sets the balance of an account. + + Parameters + ---------- + state: + The current state. + + address: + Address of the account whose nonce needs to be incremented. + + amount: + The amount that needs to set in balance. + " in +(* At stmt: unsupported node type: FunctionDef *) + let _ := M.call (| + M.get_name (| globals, "modify_state" |), + make_list [ + M.get_name (| globals, "state" |); + M.get_name (| globals, "address" |); + M.get_name (| globals, "set_balance" |) + ], + make_dict [] + |) in + M.pure Constant.None_)). + +Definition touch_account : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "state"; "address" ] |) in + let _ := Constant.str " + Initializes an account to state. + + Parameters + ---------- + state: + The current state. + + address: + The address of the account that need to initialised. + " in + let _ := + (* if *) + M.if_then_else (| + UnOp.not (| M.call (| + M.get_name (| globals, "account_exists" |), + make_list [ + M.get_name (| globals, "state" |); + M.get_name (| globals, "address" |) + ], + make_dict [] + |) |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, "set_account" |), + make_list [ + M.get_name (| globals, "state" |); + M.get_name (| globals, "address" |); + M.get_name (| globals, "EMPTY_ACCOUNT" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + M.pure Constant.None_)). + +Definition increment_nonce : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "state"; "address" ] |) in + let _ := Constant.str " + Increments the nonce of an account. + + Parameters + ---------- + state: + The current state. + + address: + Address of the account whose nonce needs to be incremented. + " in +(* At stmt: unsupported node type: FunctionDef *) + let _ := M.call (| + M.get_name (| globals, "modify_state" |), + make_list [ + M.get_name (| globals, "state" |); + M.get_name (| globals, "address" |); + M.get_name (| globals, "increase_nonce" |) + ], + make_dict [] + |) in + M.pure Constant.None_)). + +Definition set_code : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "state"; "address"; "code" ] |) in + let _ := Constant.str " + Sets Account code. + + Parameters + ---------- + state: + The current state. + + address: + Address of the account whose code needs to be update. + + code: + The bytecode that needs to be set. + " in +(* At stmt: unsupported node type: FunctionDef *) + let _ := M.call (| + M.get_name (| globals, "modify_state" |), + make_list [ + M.get_name (| globals, "state" |); + M.get_name (| globals, "address" |); + M.get_name (| globals, "write_code" |) + ], + make_dict [] + |) in + M.pure Constant.None_)). + +Definition create_ether : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "state"; "address"; "amount" ] |) in + let _ := Constant.str " + Add newly created ether to an account. + + Parameters + ---------- + state: + The current state. + address: + Address of the account to which ether is added. + amount: + The amount of ether to be added to the account of interest. + " in +(* At stmt: unsupported node type: FunctionDef *) + let _ := M.call (| + M.get_name (| globals, "modify_state" |), + make_list [ + M.get_name (| globals, "state" |); + M.get_name (| globals, "address" |); + M.get_name (| globals, "increase_balance" |) + ], + make_dict [] + |) in + M.pure Constant.None_)). + +Definition get_storage_original : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "state"; "address"; "key" ] |) in + let _ := Constant.str " + Get the original value in a storage slot i.e. the value before the current + transaction began. This function reads the value from the snapshots taken + before executing the transaction. + + Parameters + ---------- + state: + The current state. + address: + Address of the account to read the value from. + key: + Key of the storage slot. + " in + let _ := + (* if *) + M.if_then_else (| + Compare.in_ (| + M.get_name (| globals, "address" |), + M.get_field (| M.get_name (| globals, "state" |), "_created_accounts" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign (| + make_tuple [ M.get_name (| globals, "_" |); M.get_name (| globals, "original_trie" |) ], + M.get_subscript (| + M.get_field (| M.get_name (| globals, "state" |), "_snapshots" |), + Constant.int 0 + |) + |) in + let _ := M.assign_local (| + "original_account_trie" , + M.call (| + M.get_field (| M.get_name (| globals, "original_trie" |), "get" |), + make_list [ + M.get_name (| globals, "address" |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.is (| + M.get_name (| globals, "original_account_trie" |), + Constant.None_ + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "original_value" , + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "original_value" , + M.call (| + M.get_name (| globals, "trie_get" |), + make_list [ + M.get_name (| globals, "original_account_trie" |); + M.get_name (| globals, "key" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + )) |) in + let _ := M.assert (| M.call (| + M.get_name (| globals, "isinstance" |), + make_list [ + M.get_name (| globals, "original_value" |); + M.get_name (| globals, "U256" |) + ], + make_dict [] + |) |) in + let _ := M.return_ (| + M.get_name (| globals, "original_value" |) + |) in + M.pure Constant.None_)). diff --git a/CoqOfPython/ethereum/istanbul/transactions.v b/CoqOfPython/ethereum/istanbul/transactions.v new file mode 100644 index 0000000..0658f47 --- /dev/null +++ b/CoqOfPython/ethereum/istanbul/transactions.v @@ -0,0 +1,56 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.istanbul.transactions". + +Definition expr_1 : Value.t := + Constant.str " +Transactions are atomic units of work created externally to Ethereum and +submitted to be executed. If Ethereum is viewed as a state machine, +transactions are the events that move between states. +". + +Axiom dataclasses_imports_dataclass : + IsImported globals "dataclasses" "dataclass". + +Axiom typing_imports_Union : + IsImported globals "typing" "Union". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_Bytes : + IsImported globals "ethereum.base_types" "Bytes". +Axiom ethereum_base_types_imports_Bytes0 : + IsImported globals "ethereum.base_types" "Bytes0". +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". +Axiom ethereum_base_types_imports_slotted_freezable : + IsImported globals "ethereum.base_types" "slotted_freezable". + +Axiom ethereum_istanbul_fork_types_imports_Address : + IsImported globals "ethereum.istanbul.fork_types" "Address". + +Definition TX_BASE_COST : Value.t := M.run ltac:(M.monadic ( + Constant.int 21000 +)). + +Definition TX_DATA_COST_PER_NON_ZERO : Value.t := M.run ltac:(M.monadic ( + Constant.int 16 +)). + +Definition TX_DATA_COST_PER_ZERO : Value.t := M.run ltac:(M.monadic ( + Constant.int 4 +)). + +Definition TX_CREATE_COST : Value.t := M.run ltac:(M.monadic ( + Constant.int 32000 +)). + +Definition Transaction : Value.t := + builtins.make_klass + [] + [ + + ] + [ + + ]. diff --git a/CoqOfPython/ethereum/istanbul/trie.v b/CoqOfPython/ethereum/istanbul/trie.v new file mode 100644 index 0000000..0265390 --- /dev/null +++ b/CoqOfPython/ethereum/istanbul/trie.v @@ -0,0 +1,1589 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.istanbul.trie". + +Definition expr_1 : Value.t := + Constant.str " +State Trie +^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +The state trie is the structure responsible for storing +`.fork_types.Account` objects. +". + +(* At top_level_stmt: unsupported node type: Import *) + +Axiom dataclasses_imports_dataclass : + IsImported globals "dataclasses" "dataclass". +Axiom dataclasses_imports_field : + IsImported globals "dataclasses" "field". + +Axiom typing_imports_Callable : + IsImported globals "typing" "Callable". +Axiom typing_imports_Dict : + IsImported globals "typing" "Dict". +Axiom typing_imports_Generic : + IsImported globals "typing" "Generic". +Axiom typing_imports_List : + IsImported globals "typing" "List". +Axiom typing_imports_Mapping : + IsImported globals "typing" "Mapping". +Axiom typing_imports_MutableMapping : + IsImported globals "typing" "MutableMapping". +Axiom typing_imports_Optional : + IsImported globals "typing" "Optional". +Axiom typing_imports_Sequence : + IsImported globals "typing" "Sequence". +Axiom typing_imports_TypeVar : + IsImported globals "typing" "TypeVar". +Axiom typing_imports_Union : + IsImported globals "typing" "Union". +Axiom typing_imports_cast : + IsImported globals "typing" "cast". + +Axiom ethereum_constantinople_imports_trie : + IsImported globals "ethereum.constantinople" "trie". + +Axiom ethereum_crypto_hash_imports_keccak256 : + IsImported globals "ethereum.crypto.hash" "keccak256". + +Axiom ethereum_utils_ensure_imports_ensure : + IsImported globals "ethereum.utils.ensure" "ensure". + +Axiom ethereum_utils_hexadecimal_imports_hex_to_bytes : + IsImported globals "ethereum.utils.hexadecimal" "hex_to_bytes". + +Axiom ethereum_imports_rlp : + IsImported globals "ethereum" "rlp". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_Bytes : + IsImported globals "ethereum.base_types" "Bytes". +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". +Axiom ethereum_base_types_imports_slotted_freezable : + IsImported globals "ethereum.base_types" "slotted_freezable". + +Axiom ethereum_istanbul_blocks_imports_Receipt : + IsImported globals "ethereum.istanbul.blocks" "Receipt". + +Axiom ethereum_istanbul_fork_types_imports_Account : + IsImported globals "ethereum.istanbul.fork_types" "Account". +Axiom ethereum_istanbul_fork_types_imports_Address : + IsImported globals "ethereum.istanbul.fork_types" "Address". +Axiom ethereum_istanbul_fork_types_imports_Root : + IsImported globals "ethereum.istanbul.fork_types" "Root". +Axiom ethereum_istanbul_fork_types_imports_encode_account : + IsImported globals "ethereum.istanbul.fork_types" "encode_account". + +Axiom ethereum_istanbul_transactions_imports_Transaction : + IsImported globals "ethereum.istanbul.transactions" "Transaction". + +Definition EMPTY_TRIE_ROOT : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Root" |), + make_list [ + M.call (| + M.get_name (| globals, "hex_to_bytes" |), + make_list [ + Constant.str "56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421" + ], + make_dict [] + |) + ], + make_dict [] + |) +)). + +Definition Node : Value.t := M.run ltac:(M.monadic ( + M.get_subscript (| + M.get_name (| globals, "Union" |), + make_tuple [ M.get_name (| globals, "Account" |); M.get_name (| globals, "Bytes" |); M.get_name (| globals, "Transaction" |); M.get_name (| globals, "Receipt" |); M.get_name (| globals, "Uint" |); M.get_name (| globals, "U256" |); Constant.None_ ] + |) +)). + +Definition K : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "TypeVar" |), + make_list [ + Constant.str "K" + ], + make_dict [] + |) +)). + +Definition V : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "TypeVar" |), + make_list [ + Constant.str "V"; + M.get_subscript (| + M.get_name (| globals, "Optional" |), + M.get_name (| globals, "Account" |) + |); + M.get_subscript (| + M.get_name (| globals, "Optional" |), + M.get_name (| globals, "Bytes" |) + |); + M.get_name (| globals, "Bytes" |); + M.get_subscript (| + M.get_name (| globals, "Optional" |), + M.get_name (| globals, "Transaction" |) + |); + M.get_subscript (| + M.get_name (| globals, "Optional" |), + M.get_name (| globals, "Receipt" |) + |); + M.get_name (| globals, "Uint" |); + M.get_name (| globals, "U256" |) + ], + make_dict [] + |) +)). + +Definition LeafNode : Value.t := + builtins.make_klass + [] + [ + + ] + [ + + ]. + +Definition ExtensionNode : Value.t := + builtins.make_klass + [] + [ + + ] + [ + + ]. + +Definition BranchNode : Value.t := + builtins.make_klass + [] + [ + + ] + [ + + ]. + +Definition InternalNode : Value.t := M.run ltac:(M.monadic ( + M.get_subscript (| + M.get_name (| globals, "Union" |), + make_tuple [ M.get_name (| globals, "LeafNode" |); M.get_name (| globals, "ExtensionNode" |); M.get_name (| globals, "BranchNode" |) ] + |) +)). + +Definition encode_internal_node : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "node" ] |) in + let _ := Constant.str " + Encodes a Merkle Trie node into its RLP form. The RLP will then be + serialized into a `Bytes` and hashed unless it is less that 32 bytes + when serialized. + + This function also accepts `None`, representing the absence of a node, + which is encoded to `b""""`. + + Parameters + ---------- + node : Optional[InternalNode] + The node to encode. + + Returns + ------- + encoded : `rlp.RLP` + The node encoded as RLP. + " in +(* At stmt: unsupported node type: AnnAssign *) + let _ := + (* if *) + M.if_then_else (| + Compare.is (| + M.get_name (| globals, "node" |), + Constant.None_ + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "unencoded" , + Constant.bytes "" + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, "isinstance" |), + make_list [ + M.get_name (| globals, "node" |); + M.get_name (| globals, "LeafNode" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "unencoded" , + make_tuple [ M.call (| + M.get_name (| globals, "nibble_list_to_compact" |), + make_list [ + M.get_field (| M.get_name (| globals, "node" |), "rest_of_key" |); + Constant.bool true + ], + make_dict [] + |); M.get_field (| M.get_name (| globals, "node" |), "value" |) ] + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, "isinstance" |), + make_list [ + M.get_name (| globals, "node" |); + M.get_name (| globals, "ExtensionNode" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "unencoded" , + make_tuple [ M.call (| + M.get_name (| globals, "nibble_list_to_compact" |), + make_list [ + M.get_field (| M.get_name (| globals, "node" |), "key_segment" |); + Constant.bool false + ], + make_dict [] + |); M.get_field (| M.get_name (| globals, "node" |), "subnode" |) ] + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, "isinstance" |), + make_list [ + M.get_name (| globals, "node" |); + M.get_name (| globals, "BranchNode" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "unencoded" , + BinOp.add (| + M.get_field (| M.get_name (| globals, "node" |), "subnodes" |), + make_list [ + M.get_field (| M.get_name (| globals, "node" |), "value" |) + ] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.raise (| Some (M.call (| + M.get_name (| globals, "AssertionError" |), + make_list [ + Constant.str "(* At expr: unsupported node type: JoinedStr *)" + ], + make_dict [] + |)) |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "encoded" , + M.call (| + M.get_field (| M.get_name (| globals, "rlp" |), "encode" |), + make_list [ + M.get_name (| globals, "unencoded" |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.lt (| + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_name (| globals, "encoded" |) + ], + make_dict [] + |), + Constant.int 32 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + M.get_name (| globals, "unencoded" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.return_ (| + M.call (| + M.get_name (| globals, "keccak256" |), + make_list [ + M.get_name (| globals, "encoded" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_)). + +Definition encode_node : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "node"; "storage_root" ] |) in + let _ := Constant.str " + Encode a Node for storage in the Merkle Trie. + + Currently mostly an unimplemented stub. + " in + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, "isinstance" |), + make_list [ + M.get_name (| globals, "node" |); + M.get_name (| globals, "Account" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assert (| Compare.is_not (| + M.get_name (| globals, "storage_root" |), + Constant.None_ + |) |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, "encode_account" |), + make_list [ + M.get_name (| globals, "node" |); + M.get_name (| globals, "storage_root" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, "isinstance" |), + make_list [ + M.get_name (| globals, "node" |); + make_tuple [ M.get_name (| globals, "Transaction" |); M.get_name (| globals, "Receipt" |); M.get_name (| globals, "U256" |) ] + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + M.call (| + M.get_field (| M.get_name (| globals, "rlp" |), "encode" |), + make_list [ + M.call (| + M.get_name (| globals, "cast" |), + make_list [ + M.get_field (| M.get_name (| globals, "rlp" |), "RLP" |); + M.get_name (| globals, "node" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, "isinstance" |), + make_list [ + M.get_name (| globals, "node" |); + M.get_name (| globals, "Bytes" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + M.get_name (| globals, "node" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.return_ (| + M.call (| + M.get_field (| M.get_name (| globals, "previous_trie" |), "encode_node" |), + make_list [ + M.get_name (| globals, "node" |); + M.get_name (| globals, "storage_root" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_)). + +Definition Trie : Value.t := + builtins.make_klass + [(* At base: unsupported node type: Subscript *)] + [ + + ] + [ + + ]. + +Definition copy_trie : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "trie" ] |) in + let _ := Constant.str " + Create a copy of `trie`. Since only frozen objects may be stored in tries, + the contents are reused. + + Parameters + ---------- + trie: `Trie` + Trie to copy. + + Returns + ------- + new_trie : `Trie[K, V]` + A copy of the trie. + " in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, "Trie" |), + make_list [ + M.get_field (| M.get_name (| globals, "trie" |), "secured" |); + M.get_field (| M.get_name (| globals, "trie" |), "default" |); + M.call (| + M.get_field (| M.get_name (| globals, "copy" |), "copy" |), + make_list [ + M.get_field (| M.get_name (| globals, "trie" |), "_data" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Definition trie_set : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "trie"; "key"; "value" ] |) in + let _ := Constant.str " + Stores an item in a Merkle Trie. + + This method deletes the key if `value == trie.default`, because the Merkle + Trie represents the default value by omitting it from the trie. + + Parameters + ---------- + trie: `Trie` + Trie to store in. + key : `Bytes` + Key to lookup. + value : `V` + Node to insert at `key`. + " in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, "value" |), + M.get_field (| M.get_name (| globals, "trie" |), "default" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + Compare.in_ (| + M.get_name (| globals, "key" |), + M.get_field (| M.get_name (| globals, "trie" |), "_data" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.delete (| M.get_subscript (| + M.get_field (| M.get_name (| globals, "trie" |), "_data" |), + M.get_name (| globals, "key" |) + |) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign (| + M.get_subscript (| + M.get_field (| M.get_name (| globals, "trie" |), "_data" |), + M.get_name (| globals, "key" |) + |), + M.get_name (| globals, "value" |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_)). + +Definition trie_get : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "trie"; "key" ] |) in + let _ := Constant.str " + Gets an item from the Merkle Trie. + + This method returns `trie.default` if the key is missing. + + Parameters + ---------- + trie: + Trie to lookup in. + key : + Key to lookup. + + Returns + ------- + node : `V` + Node at `key` in the trie. + " in + let _ := M.return_ (| + M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, "trie" |), "_data" |), "get" |), + make_list [ + M.get_name (| globals, "key" |); + M.get_field (| M.get_name (| globals, "trie" |), "default" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Definition common_prefix_length : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "a"; "b" ] |) in + let _ := Constant.str " + Find the longest common prefix of two sequences. + " in + let _ := + M.for_ (| + M.get_name (| globals, "i" |), + M.call (| + M.get_name (| globals, "range" |), + make_list [ + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_name (| globals, "a" |) + ], + make_dict [] + |) + ], + make_dict [] + |), + ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + BoolOp.or (| + Compare.gt_e (| + M.get_name (| globals, "i" |), + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_name (| globals, "b" |) + ], + make_dict [] + |) + |), + ltac:(M.monadic ( + Compare.not_eq (| + M.get_subscript (| + M.get_name (| globals, "a" |), + M.get_name (| globals, "i" |) + |), + M.get_subscript (| + M.get_name (| globals, "b" |), + M.get_name (| globals, "i" |) + |) + |) + )) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + M.get_name (| globals, "i" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_name (| globals, "a" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Definition nibble_list_to_compact : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "x"; "is_leaf" ] |) in + let _ := Constant.str " + Compresses nibble-list into a standard byte array with a flag. + + A nibble-list is a list of byte values no greater than `15`. The flag is + encoded in high nibble of the highest byte. The flag nibble can be broken + down into two two-bit flags. + + Highest nibble:: + + +---+---+----------+--------+ + | _ | _ | is_leaf | parity | + +---+---+----------+--------+ + 3 2 1 0 + + + The lowest bit of the nibble encodes the parity of the length of the + remaining nibbles -- `0` when even and `1` when odd. The second lowest bit + is used to distinguish leaf and extension nodes. The other two bits are not + used. + + Parameters + ---------- + x : + Array of nibbles. + is_leaf : + True if this is part of a leaf node, or false if it is an extension + node. + + Returns + ------- + compressed : `bytearray` + Compact byte array. + " in + let _ := M.assign_local (| + "compact" , + M.call (| + M.get_name (| globals, "bytearray" |), + make_list [], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + BinOp.mod_ (| + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_name (| globals, "x" |) + ], + make_dict [] + |), + Constant.int 2 + |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_field (| M.get_name (| globals, "compact" |), "append" |), + make_list [ + BinOp.mult (| + Constant.int 16, + BinOp.mult (| + Constant.int 2, + M.get_name (| globals, "is_leaf" |) + |) + |) + ], + make_dict [] + |) in + let _ := + M.for_ (| + M.get_name (| globals, "i" |), + M.call (| + M.get_name (| globals, "range" |), + make_list [ + Constant.int 0; + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_name (| globals, "x" |) + ], + make_dict [] + |); + Constant.int 2 + ], + make_dict [] + |), + ltac:(M.monadic ( + let _ := M.call (| + M.get_field (| M.get_name (| globals, "compact" |), "append" |), + make_list [ + BinOp.add (| + BinOp.mult (| + Constant.int 16, + M.get_subscript (| + M.get_name (| globals, "x" |), + M.get_name (| globals, "i" |) + |) + |), + M.get_subscript (| + M.get_name (| globals, "x" |), + BinOp.add (| + M.get_name (| globals, "i" |), + Constant.int 1 + |) + |) + |) + ], + make_dict [] + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.call (| + M.get_field (| M.get_name (| globals, "compact" |), "append" |), + make_list [ + BinOp.add (| + BinOp.mult (| + Constant.int 16, + BinOp.add (| + BinOp.mult (| + Constant.int 2, + M.get_name (| globals, "is_leaf" |) + |), + Constant.int 1 + |) + |), + M.get_subscript (| + M.get_name (| globals, "x" |), + Constant.int 0 + |) + |) + ], + make_dict [] + |) in + let _ := + M.for_ (| + M.get_name (| globals, "i" |), + M.call (| + M.get_name (| globals, "range" |), + make_list [ + Constant.int 1; + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_name (| globals, "x" |) + ], + make_dict [] + |); + Constant.int 2 + ], + make_dict [] + |), + ltac:(M.monadic ( + let _ := M.call (| + M.get_field (| M.get_name (| globals, "compact" |), "append" |), + make_list [ + BinOp.add (| + BinOp.mult (| + Constant.int 16, + M.get_subscript (| + M.get_name (| globals, "x" |), + M.get_name (| globals, "i" |) + |) + |), + M.get_subscript (| + M.get_name (| globals, "x" |), + BinOp.add (| + M.get_name (| globals, "i" |), + Constant.int 1 + |) + |) + |) + ], + make_dict [] + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + M.pure Constant.None_ + )) |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, "Bytes" |), + make_list [ + M.get_name (| globals, "compact" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Definition bytes_to_nibble_list : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "bytes_" ] |) in + let _ := Constant.str " + Converts a `Bytes` into to a sequence of nibbles (bytes with value < 16). + + Parameters + ---------- + bytes_: + The `Bytes` to convert. + + Returns + ------- + nibble_list : `Bytes` + The `Bytes` in nibble-list format. + " in + let _ := M.assign_local (| + "nibble_list" , + M.call (| + M.get_name (| globals, "bytearray" |), + make_list [ + BinOp.mult (| + Constant.int 2, + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_name (| globals, "bytes_" |) + ], + make_dict [] + |) + |) + ], + make_dict [] + |) + |) in + let _ := + M.for_ (| + make_tuple [ M.get_name (| globals, "byte_index" |); M.get_name (| globals, "byte" |) ], + M.call (| + M.get_name (| globals, "enumerate" |), + make_list [ + M.get_name (| globals, "bytes_" |) + ], + make_dict [] + |), + ltac:(M.monadic ( + let _ := M.assign (| + M.get_subscript (| + M.get_name (| globals, "nibble_list" |), + BinOp.mult (| + M.get_name (| globals, "byte_index" |), + Constant.int 2 + |) + |), + BinOp.r_shift (| + BinOp.bit_and (| + M.get_name (| globals, "byte" |), + Constant.int 240 + |), + Constant.int 4 + |) + |) in + let _ := M.assign (| + M.get_subscript (| + M.get_name (| globals, "nibble_list" |), + BinOp.add (| + BinOp.mult (| + M.get_name (| globals, "byte_index" |), + Constant.int 2 + |), + Constant.int 1 + |) + |), + BinOp.bit_and (| + M.get_name (| globals, "byte" |), + Constant.int 15 + |) + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, "Bytes" |), + make_list [ + M.get_name (| globals, "nibble_list" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Definition _prepare_trie : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "trie"; "get_storage_root" ] |) in + let _ := Constant.str " + Prepares the trie for root calculation. Removes values that are empty, + hashes the keys (if `secured == True`) and encodes all the nodes. + + Parameters + ---------- + trie : + The `Trie` to prepare. + get_storage_root : + Function to get the storage root of an account. Needed to encode + `Account` objects. + + Returns + ------- + out : `Mapping[ethereum.base_types.Bytes, Node]` + Object with keys mapped to nibble-byte form. + " in +(* At stmt: unsupported node type: AnnAssign *) + let _ := + M.for_ (| + make_tuple [ M.get_name (| globals, "preimage" |); M.get_name (| globals, "value" |) ], + M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, "trie" |), "_data" |), "items" |), + make_list [], + make_dict [] + |), + ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, "isinstance" |), + make_list [ + M.get_name (| globals, "value" |); + M.get_name (| globals, "Account" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assert (| Compare.is_not (| + M.get_name (| globals, "get_storage_root" |), + Constant.None_ + |) |) in + let _ := M.assign_local (| + "address" , + M.call (| + M.get_name (| globals, "Address" |), + make_list [ + M.get_name (| globals, "preimage" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "encoded_value" , + M.call (| + M.get_name (| globals, "encode_node" |), + make_list [ + M.get_name (| globals, "value" |); + M.call (| + M.get_name (| globals, "get_storage_root" |), + make_list [ + M.get_name (| globals, "address" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "encoded_value" , + M.call (| + M.get_name (| globals, "encode_node" |), + make_list [ + M.get_name (| globals, "value" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + )) |) in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + Compare.not_eq (| + M.get_name (| globals, "encoded_value" |), + Constant.bytes "" + |); + M.get_name (| globals, "AssertionError" |) + ], + make_dict [] + |) in +(* At stmt: unsupported node type: AnnAssign *) + let _ := + (* if *) + M.if_then_else (| + M.get_field (| M.get_name (| globals, "trie" |), "secured" |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "key" , + M.call (| + M.get_name (| globals, "keccak256" |), + make_list [ + M.get_name (| globals, "preimage" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "key" , + M.get_name (| globals, "preimage" |) + |) in + M.pure Constant.None_ + )) |) in + let _ := M.assign (| + M.get_subscript (| + M.get_name (| globals, "mapped" |), + M.call (| + M.get_name (| globals, "bytes_to_nibble_list" |), + make_list [ + M.get_name (| globals, "key" |) + ], + make_dict [] + |) + |), + M.get_name (| globals, "encoded_value" |) + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := M.return_ (| + M.get_name (| globals, "mapped" |) + |) in + M.pure Constant.None_)). + +Definition root : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "trie"; "get_storage_root" ] |) in + let _ := Constant.str " + Computes the root of a modified merkle patricia trie (MPT). + + Parameters + ---------- + trie : + `Trie` to get the root of. + get_storage_root : + Function to get the storage root of an account. Needed to encode + `Account` objects. + + + Returns + ------- + root : `.fork_types.Root` + MPT root of the underlying key-value pairs. + " in + let _ := M.assign_local (| + "obj" , + M.call (| + M.get_name (| globals, "_prepare_trie" |), + make_list [ + M.get_name (| globals, "trie" |); + M.get_name (| globals, "get_storage_root" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "root_node" , + M.call (| + M.get_name (| globals, "encode_internal_node" |), + make_list [ + M.call (| + M.get_name (| globals, "patricialize" |), + make_list [ + M.get_name (| globals, "obj" |); + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.lt (| + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.call (| + M.get_field (| M.get_name (| globals, "rlp" |), "encode" |), + make_list [ + M.get_name (| globals, "root_node" |) + ], + make_dict [] + |) + ], + make_dict [] + |), + Constant.int 32 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + M.call (| + M.get_name (| globals, "keccak256" |), + make_list [ + M.call (| + M.get_field (| M.get_name (| globals, "rlp" |), "encode" |), + make_list [ + M.get_name (| globals, "root_node" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assert (| M.call (| + M.get_name (| globals, "isinstance" |), + make_list [ + M.get_name (| globals, "root_node" |); + M.get_name (| globals, "Bytes" |) + ], + make_dict [] + |) |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, "Root" |), + make_list [ + M.get_name (| globals, "root_node" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_)). + +Definition patricialize : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "obj"; "level" ] |) in + let _ := Constant.str " + Structural composition function. + + Used to recursively patricialize and merkleize a dictionary. Includes + memoization of the tree structure and hashes. + + Parameters + ---------- + obj : + Underlying trie key-value pairs, with keys in nibble-list format. + level : + Current trie level. + + Returns + ------- + node : `ethereum.base_types.Bytes` + Root node of `obj`. + " in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_name (| globals, "obj" |) + ], + make_dict [] + |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + Constant.None_ + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "arbitrary_key" , + M.call (| + M.get_name (| globals, "next" |), + make_list [ + M.call (| + M.get_name (| globals, "iter" |), + make_list [ + M.get_name (| globals, "obj" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_name (| globals, "obj" |) + ], + make_dict [] + |), + Constant.int 1 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "leaf" , + M.call (| + M.get_name (| globals, "LeafNode" |), + make_list [ + M.slice (| + M.get_name (| globals, "arbitrary_key" |), + M.get_name (| globals, "level" |), + Constant.None_, + Constant.None_ + |); + M.get_subscript (| + M.get_name (| globals, "obj" |), + M.get_name (| globals, "arbitrary_key" |) + |) + ], + make_dict [] + |) + |) in + let _ := M.return_ (| + M.get_name (| globals, "leaf" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "substring" , + M.slice (| + M.get_name (| globals, "arbitrary_key" |), + M.get_name (| globals, "level" |), + Constant.None_, + Constant.None_ + |) + |) in + let _ := M.assign_local (| + "prefix_length" , + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_name (| globals, "substring" |) + ], + make_dict [] + |) + |) in + let _ := + M.for_ (| + M.get_name (| globals, "key" |), + M.get_name (| globals, "obj" |), + ltac:(M.monadic ( + let _ := M.assign_local (| + "prefix_length" , + M.call (| + M.get_name (| globals, "min" |), + make_list [ + M.get_name (| globals, "prefix_length" |); + M.call (| + M.get_name (| globals, "common_prefix_length" |), + make_list [ + M.get_name (| globals, "substring" |); + M.slice (| + M.get_name (| globals, "key" |), + M.get_name (| globals, "level" |), + Constant.None_, + Constant.None_ + |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, "prefix_length" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.break (| |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.gt (| + M.get_name (| globals, "prefix_length" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "prefix" , + M.slice (| + M.get_name (| globals, "arbitrary_key" |), + M.get_name (| globals, "level" |), + BinOp.add (| + M.get_name (| globals, "level" |), + M.get_name (| globals, "prefix_length" |) + |), + Constant.None_ + |) + |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, "ExtensionNode" |), + make_list [ + M.get_name (| globals, "prefix" |); + M.call (| + M.get_name (| globals, "encode_internal_node" |), + make_list [ + M.call (| + M.get_name (| globals, "patricialize" |), + make_list [ + M.get_name (| globals, "obj" |); + BinOp.add (| + M.get_name (| globals, "level" |), + M.get_name (| globals, "prefix_length" |) + |) + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in +(* At stmt: unsupported node type: AnnAssign *) + let _ := + M.for_ (| + M.get_name (| globals, "_" |), + M.call (| + M.get_name (| globals, "range" |), + make_list [ + Constant.int 16 + ], + make_dict [] + |), + ltac:(M.monadic ( + let _ := M.call (| + M.get_field (| M.get_name (| globals, "branches" |), "append" |), + make_list [ + Constant.str "(* At expr: unsupported node type: Dict *)" + ], + make_dict [] + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := M.assign_local (| + "value" , + Constant.bytes "" + |) in + let _ := + M.for_ (| + M.get_name (| globals, "key" |), + M.get_name (| globals, "obj" |), + ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_name (| globals, "key" |) + ], + make_dict [] + |), + M.get_name (| globals, "level" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, "isinstance" |), + make_list [ + M.get_subscript (| + M.get_name (| globals, "obj" |), + M.get_name (| globals, "key" |) + |); + make_tuple [ M.get_name (| globals, "Account" |); M.get_name (| globals, "Receipt" |); M.get_name (| globals, "Uint" |) ] + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, "AssertionError" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "value" , + M.get_subscript (| + M.get_name (| globals, "obj" |), + M.get_name (| globals, "key" |) + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign (| + M.get_subscript (| + M.get_subscript (| + M.get_name (| globals, "branches" |), + M.get_subscript (| + M.get_name (| globals, "key" |), + M.get_name (| globals, "level" |) + |) + |), + M.get_name (| globals, "key" |) + |), + M.get_subscript (| + M.get_name (| globals, "obj" |), + M.get_name (| globals, "key" |) + |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, "BranchNode" |), + make_list [ + Constant.str "(* At expr: unsupported node type: ListComp *)"; + M.get_name (| globals, "value" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). diff --git a/CoqOfPython/ethereum/istanbul/utils/__init__.v b/CoqOfPython/ethereum/istanbul/utils/__init__.v new file mode 100644 index 0000000..bcee1bf --- /dev/null +++ b/CoqOfPython/ethereum/istanbul/utils/__init__.v @@ -0,0 +1,8 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.istanbul.utils.__init__". + +Definition expr_1 : Value.t := + Constant.str " +Utility functions unique to this particular fork. +". diff --git a/CoqOfPython/ethereum/istanbul/utils/address.v b/CoqOfPython/ethereum/istanbul/utils/address.v new file mode 100644 index 0000000..340714a --- /dev/null +++ b/CoqOfPython/ethereum/istanbul/utils/address.v @@ -0,0 +1,227 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.istanbul.utils.address". + +Definition expr_1 : Value.t := + Constant.str " +Hardfork Utility Functions For Addresses +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Address specific functions used in this istanbul version of +specification. +". + +Axiom typing_imports_Union : + IsImported globals "typing" "Union". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_Bytes32 : + IsImported globals "ethereum.base_types" "Bytes32". +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". + +Axiom ethereum_crypto_hash_imports_keccak256 : + IsImported globals "ethereum.crypto.hash" "keccak256". + +Axiom ethereum_utils_byte_imports_left_pad_zero_bytes : + IsImported globals "ethereum.utils.byte" "left_pad_zero_bytes". + +Axiom ethereum_imports_rlp : + IsImported globals "ethereum" "rlp". + +Axiom ethereum_istanbul_fork_types_imports_Address : + IsImported globals "ethereum.istanbul.fork_types" "Address". + +Definition to_address : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "data" ] |) in + let _ := Constant.str " + Convert a Uint or U256 value to a valid address (20 bytes). + + Parameters + ---------- + data : + The string to be converted to bytes. + + Returns + ------- + address : `Address` + The obtained address. + " in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, "Address" |), + make_list [ + M.slice (| + M.call (| + M.get_field (| M.get_name (| globals, "data" |), "to_be_bytes32" |), + make_list [], + make_dict [] + |), + UnOp.sub (| Constant.int 20 |), + Constant.None_, + Constant.None_ + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Definition compute_contract_address : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "address"; "nonce" ] |) in + let _ := Constant.str " + Computes address of the new account that needs to be created. + + Parameters + ---------- + address : + The address of the account that wants to create the new account. + nonce : + The transaction count of the account that wants to create the new + account. + + Returns + ------- + address: `Address` + The computed address of the new account. + " in + let _ := M.assign_local (| + "computed_address" , + M.call (| + M.get_name (| globals, "keccak256" |), + make_list [ + M.call (| + M.get_field (| M.get_name (| globals, "rlp" |), "encode" |), + make_list [ + make_list [ + M.get_name (| globals, "address" |); + M.get_name (| globals, "nonce" |) + ] + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "canonical_address" , + M.slice (| + M.get_name (| globals, "computed_address" |), + UnOp.sub (| Constant.int 20 |), + Constant.None_, + Constant.None_ + |) + |) in + let _ := M.assign_local (| + "padded_address" , + M.call (| + M.get_name (| globals, "left_pad_zero_bytes" |), + make_list [ + M.get_name (| globals, "canonical_address" |); + Constant.int 20 + ], + make_dict [] + |) + |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, "Address" |), + make_list [ + M.get_name (| globals, "padded_address" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Definition compute_create2_contract_address : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "address"; "salt"; "call_data" ] |) in + let _ := Constant.str " + Computes address of the new account that needs to be created, which is + based on the sender address, salt and the call data as well. + + Parameters + ---------- + address : + The address of the account that wants to create the new account. + salt : + Address generation salt. + call_data : + The code of the new account which is to be created. + + Returns + ------- + address: `ethereum.istanbul.fork_types.Address` + The computed address of the new account. + " in + let _ := M.assign_local (| + "preimage" , + BinOp.add (| + BinOp.add (| + BinOp.add (| + Constant.bytes "ff", + M.get_name (| globals, "address" |) + |), + M.get_name (| globals, "salt" |) + |), + M.call (| + M.get_name (| globals, "keccak256" |), + make_list [ + M.get_name (| globals, "call_data" |) + ], + make_dict [] + |) + |) + |) in + let _ := M.assign_local (| + "computed_address" , + M.call (| + M.get_name (| globals, "keccak256" |), + make_list [ + M.get_name (| globals, "preimage" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "canonical_address" , + M.slice (| + M.get_name (| globals, "computed_address" |), + UnOp.sub (| Constant.int 20 |), + Constant.None_, + Constant.None_ + |) + |) in + let _ := M.assign_local (| + "padded_address" , + M.call (| + M.get_name (| globals, "left_pad_zero_bytes" |), + make_list [ + M.get_name (| globals, "canonical_address" |); + Constant.int 20 + ], + make_dict [] + |) + |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, "Address" |), + make_list [ + M.get_name (| globals, "padded_address" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). diff --git a/CoqOfPython/ethereum/istanbul/utils/hexadecimal.v b/CoqOfPython/ethereum/istanbul/utils/hexadecimal.v new file mode 100644 index 0000000..0486e96 --- /dev/null +++ b/CoqOfPython/ethereum/istanbul/utils/hexadecimal.v @@ -0,0 +1,153 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.istanbul.utils.hexadecimal". + +Definition expr_1 : Value.t := + Constant.str " +Utility Functions For Hexadecimal Strings +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Hexadecimal utility functions used in this specification, specific to +Istanbul types. +". + +Axiom ethereum_utils_hexadecimal_imports_remove_hex_prefix : + IsImported globals "ethereum.utils.hexadecimal" "remove_hex_prefix". + +Axiom ethereum_istanbul_fork_types_imports_Address : + IsImported globals "ethereum.istanbul.fork_types" "Address". +Axiom ethereum_istanbul_fork_types_imports_Bloom : + IsImported globals "ethereum.istanbul.fork_types" "Bloom". +Axiom ethereum_istanbul_fork_types_imports_Root : + IsImported globals "ethereum.istanbul.fork_types" "Root". + +Definition hex_to_root : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "hex_string" ] |) in + let _ := Constant.str " + Convert hex string to trie root. + + Parameters + ---------- + hex_string : + The hexadecimal string to be converted to trie root. + + Returns + ------- + root : `Root` + Trie root obtained from the given hexadecimal string. + " in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, "Root" |), + make_list [ + M.call (| + M.get_field (| M.get_name (| globals, "bytes" |), "fromhex" |), + make_list [ + M.call (| + M.get_name (| globals, "remove_hex_prefix" |), + make_list [ + M.get_name (| globals, "hex_string" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Definition hex_to_bloom : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "hex_string" ] |) in + let _ := Constant.str " + Convert hex string to bloom. + + Parameters + ---------- + hex_string : + The hexadecimal string to be converted to bloom. + + Returns + ------- + bloom : `Bloom` + Bloom obtained from the given hexadecimal string. + " in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, "Bloom" |), + make_list [ + M.call (| + M.get_field (| M.get_name (| globals, "bytes" |), "fromhex" |), + make_list [ + M.call (| + M.get_name (| globals, "remove_hex_prefix" |), + make_list [ + M.get_name (| globals, "hex_string" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Definition hex_to_address : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "hex_string" ] |) in + let _ := Constant.str " + Convert hex string to Address (20 bytes). + + Parameters + ---------- + hex_string : + The hexadecimal string to be converted to Address. + + Returns + ------- + address : `Address` + The address obtained from the given hexadecimal string. + " in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, "Address" |), + make_list [ + M.call (| + M.get_field (| M.get_name (| globals, "bytes" |), "fromhex" |), + make_list [ + M.call (| + M.get_field (| M.call (| + M.get_name (| globals, "remove_hex_prefix" |), + make_list [ + M.get_name (| globals, "hex_string" |) + ], + make_dict [] + |), "rjust" |), + make_list [ + Constant.int 40; + Constant.str "0" + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). diff --git a/CoqOfPython/ethereum/istanbul/utils/message.v b/CoqOfPython/ethereum/istanbul/utils/message.v new file mode 100644 index 0000000..2ff4fec --- /dev/null +++ b/CoqOfPython/ethereum/istanbul/utils/message.v @@ -0,0 +1,212 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.istanbul.utils.message". + +Definition expr_1 : Value.t := + Constant.str " +Hardfork Utility Functions For The Message Data-structure +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Message specific functions used in this istanbul version of +specification. +". + +Axiom typing_imports_Optional : + IsImported globals "typing" "Optional". +Axiom typing_imports_Union : + IsImported globals "typing" "Union". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_Bytes : + IsImported globals "ethereum.base_types" "Bytes". +Axiom ethereum_base_types_imports_Bytes0 : + IsImported globals "ethereum.base_types" "Bytes0". +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". + +Axiom ethereum_istanbul_fork_types_imports_Address : + IsImported globals "ethereum.istanbul.fork_types" "Address". + +Axiom ethereum_istanbul_state_imports_get_account : + IsImported globals "ethereum.istanbul.state" "get_account". + +Axiom ethereum_istanbul_vm_imports_Environment : + IsImported globals "ethereum.istanbul.vm" "Environment". +Axiom ethereum_istanbul_vm_imports_Message : + IsImported globals "ethereum.istanbul.vm" "Message". + +Axiom ethereum_istanbul_utils_address_imports_compute_contract_address : + IsImported globals "ethereum.istanbul.utils.address" "compute_contract_address". + +Definition prepare_message : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "caller"; "target"; "value"; "data"; "gas"; "env"; "code_address"; "should_transfer_value"; "is_static" ] |) in + let _ := Constant.str " + Execute a transaction against the provided environment. + + Parameters + ---------- + caller : + Address which initiated the transaction + target : + Address whose code will be executed + value : + Value to be transferred. + data : + Array of bytes provided to the code in `target`. + gas : + Gas provided for the code in `target`. + env : + Environment for the Ethereum Virtual Machine. + code_address : + This is usually same as the `target` address except when an alternative + accounts code needs to be executed. + eg. `CALLCODE` calling a precompile. + should_transfer_value : + if True ETH should be transferred while executing a message call. + is_static: + if True then it prevents all state-changing operations from being + executed. + + Returns + ------- + message: `ethereum.istanbul.vm.Message` + Items containing contract creation or message call specific data. + " in + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, "isinstance" |), + make_list [ + M.get_name (| globals, "target" |); + M.get_name (| globals, "Bytes0" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "current_target" , + M.call (| + M.get_name (| globals, "compute_contract_address" |), + make_list [ + M.get_name (| globals, "caller" |); + BinOp.sub (| + M.get_field (| M.call (| + M.get_name (| globals, "get_account" |), + make_list [ + M.get_field (| M.get_name (| globals, "env" |), "state" |); + M.get_name (| globals, "caller" |) + ], + make_dict [] + |), "nonce" |), + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 1 + ], + make_dict [] + |) + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "msg_data" , + M.call (| + M.get_name (| globals, "Bytes" |), + make_list [ + Constant.bytes "" + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "code" , + M.get_name (| globals, "data" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, "isinstance" |), + make_list [ + M.get_name (| globals, "target" |); + M.get_name (| globals, "Address" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "current_target" , + M.get_name (| globals, "target" |) + |) in + let _ := M.assign_local (| + "msg_data" , + M.get_name (| globals, "data" |) + |) in + let _ := M.assign_local (| + "code" , + M.get_field (| M.call (| + M.get_name (| globals, "get_account" |), + make_list [ + M.get_field (| M.get_name (| globals, "env" |), "state" |); + M.get_name (| globals, "target" |) + ], + make_dict [] + |), "code" |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.is (| + M.get_name (| globals, "code_address" |), + Constant.None_ + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "code_address" , + M.get_name (| globals, "target" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.raise (| Some (M.call (| + M.get_name (| globals, "AssertionError" |), + make_list [ + Constant.str "Target must be address or empty bytes" + ], + make_dict [] + |)) |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )) |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, "Message" |), + make_list [], + make_dict [] + |) + |) in + M.pure Constant.None_)). diff --git a/CoqOfPython/ethereum/istanbul/vm/__init__.v b/CoqOfPython/ethereum/istanbul/vm/__init__.v new file mode 100644 index 0000000..dc4ef8a --- /dev/null +++ b/CoqOfPython/ethereum/istanbul/vm/__init__.v @@ -0,0 +1,244 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.istanbul.vm.__init__". + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +The abstract computer which runs the code stored in an +`.fork_types.Account`. +". + +Axiom dataclasses_imports_dataclass : + IsImported globals "dataclasses" "dataclass". + +Axiom typing_imports_List : + IsImported globals "typing" "List". +Axiom typing_imports_Optional : + IsImported globals "typing" "Optional". +Axiom typing_imports_Set : + IsImported globals "typing" "Set". +Axiom typing_imports_Tuple : + IsImported globals "typing" "Tuple". +Axiom typing_imports_Union : + IsImported globals "typing" "Union". + +Axiom ethereum_base_types_imports_U64 : + IsImported globals "ethereum.base_types" "U64". +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_Bytes : + IsImported globals "ethereum.base_types" "Bytes". +Axiom ethereum_base_types_imports_Bytes0 : + IsImported globals "ethereum.base_types" "Bytes0". +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". + +Axiom ethereum_crypto_hash_imports_Hash32 : + IsImported globals "ethereum.crypto.hash" "Hash32". + +Axiom ethereum_istanbul_blocks_imports_Log : + IsImported globals "ethereum.istanbul.blocks" "Log". + +Axiom ethereum_istanbul_fork_types_imports_Address : + IsImported globals "ethereum.istanbul.fork_types" "Address". + +Axiom ethereum_istanbul_state_imports_State : + IsImported globals "ethereum.istanbul.state" "State". +Axiom ethereum_istanbul_state_imports_account_exists_and_is_empty : + IsImported globals "ethereum.istanbul.state" "account_exists_and_is_empty". + +Axiom ethereum_istanbul_vm_precompiled_contracts_imports_RIPEMD160_ADDRESS : + IsImported globals "ethereum.istanbul.vm.precompiled_contracts" "RIPEMD160_ADDRESS". + +Definition __all__ : Value.t := M.run ltac:(M.monadic ( + make_tuple [ Constant.str "Environment"; Constant.str "Evm"; Constant.str "Message" ] +)). + +Definition Environment : Value.t := + builtins.make_klass + [] + [ + + ] + [ + + ]. + +Definition Message : Value.t := + builtins.make_klass + [] + [ + + ] + [ + + ]. + +Definition Evm : Value.t := + builtins.make_klass + [] + [ + + ] + [ + + ]. + +Definition incorporate_child_on_success : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm"; "child_evm" ] |) in + let _ := Constant.str " + Incorporate the state of a successful `child_evm` into the parent `evm`. + + Parameters + ---------- + evm : + The parent `EVM`. + child_evm : + The child evm to incorporate. + " in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "gas_left" |), + M.get_field (| M.get_name (| globals, "child_evm" |), "gas_left" |) + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "logs" |), + M.get_field (| M.get_name (| globals, "child_evm" |), "logs" |) + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "refund_counter" |), + M.get_field (| M.get_name (| globals, "child_evm" |), "refund_counter" |) + |) in + let _ := M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "accounts_to_delete" |), "update" |), + make_list [ + M.get_field (| M.get_name (| globals, "child_evm" |), "accounts_to_delete" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "touched_accounts" |), "update" |), + make_list [ + M.get_field (| M.get_name (| globals, "child_evm" |), "touched_accounts" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, "account_exists_and_is_empty" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "env" |), "state" |); + M.get_field (| M.get_field (| M.get_name (| globals, "child_evm" |), "message" |), "current_target" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "touched_accounts" |), "add" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "child_evm" |), "message" |), "current_target" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + M.pure Constant.None_)). + +Definition incorporate_child_on_error : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm"; "child_evm" ] |) in + let _ := Constant.str " + Incorporate the state of an unsuccessful `child_evm` into the parent `evm`. + + Parameters + ---------- + evm : + The parent `EVM`. + child_evm : + The child evm to incorporate. + " in + let _ := + (* if *) + M.if_then_else (| + Compare.in_ (| + M.get_name (| globals, "RIPEMD160_ADDRESS" |), + M.get_field (| M.get_name (| globals, "child_evm" |), "touched_accounts" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "touched_accounts" |), "add" |), + make_list [ + M.get_name (| globals, "RIPEMD160_ADDRESS" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_field (| M.get_field (| M.get_name (| globals, "child_evm" |), "message" |), "current_target" |), + M.get_name (| globals, "RIPEMD160_ADDRESS" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, "account_exists_and_is_empty" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "env" |), "state" |); + M.get_field (| M.get_field (| M.get_name (| globals, "child_evm" |), "message" |), "current_target" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "touched_accounts" |), "add" |), + make_list [ + M.get_name (| globals, "RIPEMD160_ADDRESS" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "gas_left" |), + M.get_field (| M.get_name (| globals, "child_evm" |), "gas_left" |) + |) in + M.pure Constant.None_)). diff --git a/CoqOfPython/ethereum/istanbul/vm/exceptions.v b/CoqOfPython/ethereum/istanbul/vm/exceptions.v new file mode 100644 index 0000000..3ba8068 --- /dev/null +++ b/CoqOfPython/ethereum/istanbul/vm/exceptions.v @@ -0,0 +1,161 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.istanbul.vm.exceptions". + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) Exceptions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Exceptions which cause the EVM to halt exceptionally. +". + +Axiom ethereum_exceptions_imports_EthereumException : + IsImported globals "ethereum.exceptions" "EthereumException". + +Definition ExceptionalHalt : Value.t := + builtins.make_klass + [(globals, "EthereumException")] + [ + + ] + [ + + ]. + +Definition Revert : Value.t := + builtins.make_klass + [(globals, "EthereumException")] + [ + + ] + [ + + ]. + +Definition StackUnderflowError : Value.t := + builtins.make_klass + [(globals, "ExceptionalHalt")] + [ + + ] + [ + + ]. + +Definition StackOverflowError : Value.t := + builtins.make_klass + [(globals, "ExceptionalHalt")] + [ + + ] + [ + + ]. + +Definition OutOfGasError : Value.t := + builtins.make_klass + [(globals, "ExceptionalHalt")] + [ + + ] + [ + + ]. + +Definition InvalidOpcode : Value.t := + builtins.make_klass + [(globals, "ExceptionalHalt")] + [ + + ] + [ + ( + "__init__", + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "self"; "code" ] |) in + let _ := M.call (| + M.get_field (| M.call (| + M.get_name (| globals, "super" |), + make_list [], + make_dict [] + |), "__init__" |), + make_list [ + M.get_name (| globals, "code" |) + ], + make_dict [] + |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, "self" |), "code" |), + M.get_name (| globals, "code" |) + |) in + M.pure Constant.None_)) + ) + ]. + +Definition InvalidJumpDestError : Value.t := + builtins.make_klass + [(globals, "ExceptionalHalt")] + [ + + ] + [ + + ]. + +Definition StackDepthLimitError : Value.t := + builtins.make_klass + [(globals, "ExceptionalHalt")] + [ + + ] + [ + + ]. + +Definition WriteInStaticContext : Value.t := + builtins.make_klass + [(globals, "ExceptionalHalt")] + [ + + ] + [ + + ]. + +Definition OutOfBoundsRead : Value.t := + builtins.make_klass + [(globals, "ExceptionalHalt")] + [ + + ] + [ + + ]. + +Definition InvalidParameter : Value.t := + builtins.make_klass + [(globals, "ExceptionalHalt")] + [ + + ] + [ + + ]. + +Definition AddressCollision : Value.t := + builtins.make_klass + [(globals, "ExceptionalHalt")] + [ + + ] + [ + + ]. diff --git a/CoqOfPython/ethereum/istanbul/vm/gas.v b/CoqOfPython/ethereum/istanbul/vm/gas.v new file mode 100644 index 0000000..b2000e8 --- /dev/null +++ b/CoqOfPython/ethereum/istanbul/vm/gas.v @@ -0,0 +1,942 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.istanbul.vm.gas". + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) Gas +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +EVM gas constants and calculators. +". + +Axiom dataclasses_imports_dataclass : + IsImported globals "dataclasses" "dataclass". + +Axiom typing_imports_List : + IsImported globals "typing" "List". +Axiom typing_imports_Tuple : + IsImported globals "typing" "Tuple". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". + +Axiom ethereum_trace_imports_GasAndRefund : + IsImported globals "ethereum.trace" "GasAndRefund". +Axiom ethereum_trace_imports_evm_trace : + IsImported globals "ethereum.trace" "evm_trace". + +Axiom ethereum_utils_numeric_imports_ceil32 : + IsImported globals "ethereum.utils.numeric" "ceil32". + +Axiom ethereum_istanbul_vm_imports_Evm : + IsImported globals "ethereum.istanbul.vm" "Evm". + +Axiom ethereum_istanbul_vm_exceptions_imports_OutOfGasError : + IsImported globals "ethereum.istanbul.vm.exceptions" "OutOfGasError". + +Definition GAS_JUMPDEST : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 1 + ], + make_dict [] + |) +)). + +Definition GAS_BASE : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 2 + ], + make_dict [] + |) +)). + +Definition GAS_VERY_LOW : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 3 + ], + make_dict [] + |) +)). + +Definition GAS_SLOAD : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 800 + ], + make_dict [] + |) +)). + +Definition GAS_STORAGE_SET : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 20000 + ], + make_dict [] + |) +)). + +Definition GAS_STORAGE_UPDATE : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 5000 + ], + make_dict [] + |) +)). + +Definition GAS_STORAGE_CLEAR_REFUND : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 15000 + ], + make_dict [] + |) +)). + +Definition GAS_LOW : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 5 + ], + make_dict [] + |) +)). + +Definition GAS_MID : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 8 + ], + make_dict [] + |) +)). + +Definition GAS_HIGH : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 10 + ], + make_dict [] + |) +)). + +Definition GAS_EXPONENTIATION : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 10 + ], + make_dict [] + |) +)). + +Definition GAS_EXPONENTIATION_PER_BYTE : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 50 + ], + make_dict [] + |) +)). + +Definition GAS_MEMORY : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 3 + ], + make_dict [] + |) +)). + +Definition GAS_KECCAK256 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 30 + ], + make_dict [] + |) +)). + +Definition GAS_KECCAK256_WORD : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 6 + ], + make_dict [] + |) +)). + +Definition GAS_COPY : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 3 + ], + make_dict [] + |) +)). + +Definition GAS_BLOCK_HASH : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 20 + ], + make_dict [] + |) +)). + +Definition GAS_EXTERNAL : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 700 + ], + make_dict [] + |) +)). + +Definition GAS_BALANCE : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 700 + ], + make_dict [] + |) +)). + +Definition GAS_LOG : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 375 + ], + make_dict [] + |) +)). + +Definition GAS_LOG_DATA : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 8 + ], + make_dict [] + |) +)). + +Definition GAS_LOG_TOPIC : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 375 + ], + make_dict [] + |) +)). + +Definition GAS_CREATE : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 32000 + ], + make_dict [] + |) +)). + +Definition GAS_CODE_DEPOSIT : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 200 + ], + make_dict [] + |) +)). + +Definition GAS_ZERO : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) +)). + +Definition GAS_CALL : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 700 + ], + make_dict [] + |) +)). + +Definition GAS_NEW_ACCOUNT : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 25000 + ], + make_dict [] + |) +)). + +Definition GAS_CALL_VALUE : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 9000 + ], + make_dict [] + |) +)). + +Definition GAS_CALL_STIPEND : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 2300 + ], + make_dict [] + |) +)). + +Definition GAS_SELF_DESTRUCT : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 5000 + ], + make_dict [] + |) +)). + +Definition GAS_SELF_DESTRUCT_NEW_ACCOUNT : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 25000 + ], + make_dict [] + |) +)). + +Definition REFUND_SELF_DESTRUCT : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 24000 + ], + make_dict [] + |) +)). + +Definition GAS_ECRECOVER : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 3000 + ], + make_dict [] + |) +)). + +Definition GAS_SHA256 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 60 + ], + make_dict [] + |) +)). + +Definition GAS_SHA256_WORD : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 12 + ], + make_dict [] + |) +)). + +Definition GAS_RIPEMD160 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 600 + ], + make_dict [] + |) +)). + +Definition GAS_RIPEMD160_WORD : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 120 + ], + make_dict [] + |) +)). + +Definition GAS_IDENTITY : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 15 + ], + make_dict [] + |) +)). + +Definition GAS_IDENTITY_WORD : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 3 + ], + make_dict [] + |) +)). + +Definition GAS_RETURN_DATA_COPY : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 3 + ], + make_dict [] + |) +)). + +Definition GAS_CODE_HASH : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 700 + ], + make_dict [] + |) +)). + +Definition GAS_FAST_STEP : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 5 + ], + make_dict [] + |) +)). + +Definition GAS_BLAKE2_PER_ROUND : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 1 + ], + make_dict [] + |) +)). + +Definition ExtendMemory : Value.t := + builtins.make_klass + [] + [ + + ] + [ + + ]. + +Definition MessageCallGas : Value.t := + builtins.make_klass + [] + [ + + ] + [ + + ]. + +Definition charge_gas : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm"; "amount" ] |) in + let _ := Constant.str " + Subtracts `amount` from `evm.gas_left`. + + Parameters + ---------- + evm : + The current EVM. + amount : + The amount of gas the current operation requires. + + " in + let _ := M.call (| + M.get_name (| globals, "evm_trace" |), + make_list [ + M.get_name (| globals, "evm" |); + M.call (| + M.get_name (| globals, "GasAndRefund" |), + make_list [ + M.get_name (| globals, "amount" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.lt (| + M.get_field (| M.get_name (| globals, "evm" |), "gas_left" |), + M.get_name (| globals, "amount" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, "OutOfGasError" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_op (| + BinOp.sub, + M.get_field (| M.get_name (| globals, "evm" |), "gas_left" |), + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + M.get_name (| globals, "amount" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_)). + +Definition calculate_memory_gas_cost : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "size_in_bytes" ] |) in + let _ := Constant.str " + Calculates the gas cost for allocating memory + to the smallest multiple of 32 bytes, + such that the allocated size is at least as big as the given size. + + Parameters + ---------- + size_in_bytes : + The size of the data in bytes. + + Returns + ------- + total_gas_cost : `ethereum.base_types.Uint` + The gas cost for storing data in memory. + " in + let _ := M.assign_local (| + "size_in_words" , + BinOp.floor_div (| + M.call (| + M.get_name (| globals, "ceil32" |), + make_list [ + M.get_name (| globals, "size_in_bytes" |) + ], + make_dict [] + |), + Constant.int 32 + |) + |) in + let _ := M.assign_local (| + "linear_cost" , + BinOp.mult (| + M.get_name (| globals, "size_in_words" |), + M.get_name (| globals, "GAS_MEMORY" |) + |) + |) in + let _ := M.assign_local (| + "quadratic_cost" , + BinOp.floor_div (| + BinOp.pow (| + M.get_name (| globals, "size_in_words" |), + Constant.int 2 + |), + Constant.int 512 + |) + |) in + let _ := M.assign_local (| + "total_gas_cost" , + BinOp.add (| + M.get_name (| globals, "linear_cost" |), + M.get_name (| globals, "quadratic_cost" |) + |) + |) in +(* At stmt: unsupported node type: Try *) + M.pure Constant.None_)). + +Definition calculate_gas_extend_memory : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "memory"; "extensions" ] |) in + let _ := Constant.str " + Calculates the gas amount to extend memory + + Parameters + ---------- + memory : + Memory contents of the EVM. + extensions: + List of extensions to be made to the memory. + Consists of a tuple of start position and size. + + Returns + ------- + extend_memory: `ExtendMemory` + " in + let _ := M.assign_local (| + "size_to_extend" , + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "to_be_paid" , + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "current_size" , + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_name (| globals, "memory" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := + M.for_ (| + make_tuple [ M.get_name (| globals, "start_position" |); M.get_name (| globals, "size" |) ], + M.get_name (| globals, "extensions" |), + ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, "size" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.continue (| |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "before_size" , + M.call (| + M.get_name (| globals, "ceil32" |), + make_list [ + M.get_name (| globals, "current_size" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "after_size" , + M.call (| + M.get_name (| globals, "ceil32" |), + make_list [ + BinOp.add (| + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.get_name (| globals, "start_position" |) + ], + make_dict [] + |), + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.get_name (| globals, "size" |) + ], + make_dict [] + |) + |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.lt_e (| + M.get_name (| globals, "after_size" |), + M.get_name (| globals, "before_size" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.continue (| |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_op_local (| + BinOp.add, + "size_to_extend", + BinOp.sub (| + M.get_name (| globals, "after_size" |), + M.get_name (| globals, "before_size" |) + |) + |) in + let _ := M.assign_local (| + "already_paid" , + M.call (| + M.get_name (| globals, "calculate_memory_gas_cost" |), + make_list [ + M.get_name (| globals, "before_size" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "total_cost" , + M.call (| + M.get_name (| globals, "calculate_memory_gas_cost" |), + make_list [ + M.get_name (| globals, "after_size" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_op_local (| + BinOp.add, + "to_be_paid", + BinOp.sub (| + M.get_name (| globals, "total_cost" |), + M.get_name (| globals, "already_paid" |) + |) + |) in + let _ := M.assign_local (| + "current_size" , + M.get_name (| globals, "after_size" |) + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, "ExtendMemory" |), + make_list [ + M.get_name (| globals, "to_be_paid" |); + M.get_name (| globals, "size_to_extend" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Definition calculate_message_call_gas : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "value"; "gas"; "gas_left"; "memory_cost"; "extra_gas"; "call_stipend" ] |) in + let _ := Constant.str " + Calculates the MessageCallGas (cost and stipend) for + executing call Opcodes. + + Parameters + ---------- + value: + The amount of `ETH` that needs to be transferred. + gas : + The amount of gas provided to the message-call. + gas_left : + The amount of gas left in the current frame. + memory_cost : + The amount needed to extend the memory in the current frame. + extra_gas : + The amount of gas needed for transferring value + creating a new + account inside a message call. + call_stipend : + The amount of stipend provided to a message call to execute code while + transferring value(ETH). + + Returns + ------- + message_call_gas: `MessageCallGas` + " in + let _ := M.assign_local (| + "call_stipend" , + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, "value" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( +M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + (* else *) + )), ltac:(M.monadic ( +M.get_name (| globals, "call_stipend" |) + )) |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.lt (| + M.get_name (| globals, "gas_left" |), + BinOp.add (| + M.get_name (| globals, "extra_gas" |), + M.get_name (| globals, "memory_cost" |) + |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + M.call (| + M.get_name (| globals, "MessageCallGas" |), + make_list [ + BinOp.add (| + M.get_name (| globals, "gas" |), + M.get_name (| globals, "extra_gas" |) + |); + BinOp.add (| + M.get_name (| globals, "gas" |), + M.get_name (| globals, "call_stipend" |) + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "gas" , + M.call (| + M.get_name (| globals, "min" |), + make_list [ + M.get_name (| globals, "gas" |); + M.call (| + M.get_name (| globals, "max_message_call_gas" |), + make_list [ + BinOp.sub (| + BinOp.sub (| + M.get_name (| globals, "gas_left" |), + M.get_name (| globals, "memory_cost" |) + |), + M.get_name (| globals, "extra_gas" |) + |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, "MessageCallGas" |), + make_list [ + BinOp.add (| + M.get_name (| globals, "gas" |), + M.get_name (| globals, "extra_gas" |) + |); + BinOp.add (| + M.get_name (| globals, "gas" |), + M.get_name (| globals, "call_stipend" |) + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Definition max_message_call_gas : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "gas" ] |) in + let _ := Constant.str " + Calculates the maximum gas that is allowed for making a message call + + Parameters + ---------- + gas : + The amount of gas provided to the message-call. + + Returns + ------- + max_allowed_message_call_gas: `ethereum.base_types.Uint` + The maximum gas allowed for making the message-call. + " in + let _ := M.return_ (| + BinOp.sub (| + M.get_name (| globals, "gas" |), + BinOp.floor_div (| + M.get_name (| globals, "gas" |), + Constant.int 64 + |) + |) + |) in + M.pure Constant.None_)). diff --git a/CoqOfPython/ethereum/istanbul/vm/instructions/__init__.v b/CoqOfPython/ethereum/istanbul/vm/instructions/__init__.v new file mode 100644 index 0000000..645b22b --- /dev/null +++ b/CoqOfPython/ethereum/istanbul/vm/instructions/__init__.v @@ -0,0 +1,74 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.istanbul.vm.instructions.__init__". + +Definition expr_1 : Value.t := + Constant.str " +EVM Instruction Encoding (Opcodes) +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Machine readable representations of EVM instructions, and a mapping to their +implementations. +". + +(* At top_level_stmt: unsupported node type: Import *) + +Axiom typing_imports_Callable : + IsImported globals "typing" "Callable". +Axiom typing_imports_Dict : + IsImported globals "typing" "Dict". + +Axiom ethereum_istanbul_vm_instructions_imports_arithmetic : + IsImported globals "ethereum.istanbul.vm.instructions" "arithmetic". + +Axiom ethereum_istanbul_vm_instructions_imports_bitwise : + IsImported globals "ethereum.istanbul.vm.instructions" "bitwise". + +Axiom ethereum_istanbul_vm_instructions_imports_block : + IsImported globals "ethereum.istanbul.vm.instructions" "block". + +Axiom ethereum_istanbul_vm_instructions_imports_comparison : + IsImported globals "ethereum.istanbul.vm.instructions" "comparison". + +Axiom ethereum_istanbul_vm_instructions_imports_control_flow : + IsImported globals "ethereum.istanbul.vm.instructions" "control_flow". + +Axiom ethereum_istanbul_vm_instructions_imports_environment : + IsImported globals "ethereum.istanbul.vm.instructions" "environment". + +Axiom ethereum_istanbul_vm_instructions_imports_keccak : + IsImported globals "ethereum.istanbul.vm.instructions" "keccak". + +Axiom ethereum_istanbul_vm_instructions_imports_log : + IsImported globals "ethereum.istanbul.vm.instructions" "log". + +Axiom ethereum_istanbul_vm_instructions_imports_memory : + IsImported globals "ethereum.istanbul.vm.instructions" "memory". + +Axiom ethereum_istanbul_vm_instructions_imports_stack : + IsImported globals "ethereum.istanbul.vm.instructions" "stack". + +Axiom ethereum_istanbul_vm_instructions_imports_storage : + IsImported globals "ethereum.istanbul.vm.instructions" "storage". + +Axiom ethereum_istanbul_vm_instructions_imports_system : + IsImported globals "ethereum.istanbul.vm.instructions" "system". + +Definition Ops : Value.t := + builtins.make_klass + [(* At base: unsupported node type: Attribute *)] + [ + + ] + [ + + ]. + +(* At top_level_stmt: unsupported node type: AnnAssign *) diff --git a/CoqOfPython/ethereum/istanbul/vm/instructions/arithmetic.v b/CoqOfPython/ethereum/istanbul/vm/instructions/arithmetic.v new file mode 100644 index 0000000..6c1634f --- /dev/null +++ b/CoqOfPython/ethereum/istanbul/vm/instructions/arithmetic.v @@ -0,0 +1,1220 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.istanbul.vm.instructions.arithmetic". + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) Arithmetic Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM Arithmetic instructions. +". + +Axiom ethereum_base_types_imports_U255_CEIL_VALUE : + IsImported globals "ethereum.base_types" "U255_CEIL_VALUE". +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_U256_CEIL_VALUE : + IsImported globals "ethereum.base_types" "U256_CEIL_VALUE". +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". + +Axiom ethereum_utils_numeric_imports_get_sign : + IsImported globals "ethereum.utils.numeric" "get_sign". + +Axiom ethereum_istanbul_vm_imports_Evm : + IsImported globals "ethereum.istanbul.vm" "Evm". + +Axiom ethereum_istanbul_vm_gas_imports_GAS_EXPONENTIATION : + IsImported globals "ethereum.istanbul.vm.gas" "GAS_EXPONENTIATION". +Axiom ethereum_istanbul_vm_gas_imports_GAS_EXPONENTIATION_PER_BYTE : + IsImported globals "ethereum.istanbul.vm.gas" "GAS_EXPONENTIATION_PER_BYTE". +Axiom ethereum_istanbul_vm_gas_imports_GAS_LOW : + IsImported globals "ethereum.istanbul.vm.gas" "GAS_LOW". +Axiom ethereum_istanbul_vm_gas_imports_GAS_MID : + IsImported globals "ethereum.istanbul.vm.gas" "GAS_MID". +Axiom ethereum_istanbul_vm_gas_imports_GAS_VERY_LOW : + IsImported globals "ethereum.istanbul.vm.gas" "GAS_VERY_LOW". +Axiom ethereum_istanbul_vm_gas_imports_charge_gas : + IsImported globals "ethereum.istanbul.vm.gas" "charge_gas". + +Axiom ethereum_istanbul_vm_stack_imports_pop : + IsImported globals "ethereum.istanbul.vm.stack" "pop". +Axiom ethereum_istanbul_vm_stack_imports_push : + IsImported globals "ethereum.istanbul.vm.stack" "push". + +Definition add : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Adds the top two elements of the stack together, and pushes the result back + on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "x" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "y" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_VERY_LOW" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "result" , + M.call (| + M.get_field (| M.get_name (| globals, "x" |), "wrapping_add" |), + make_list [ + M.get_name (| globals, "y" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.get_name (| globals, "result" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition sub : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Subtracts the top two elements of the stack, and pushes the result back + on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "x" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "y" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_VERY_LOW" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "result" , + M.call (| + M.get_field (| M.get_name (| globals, "x" |), "wrapping_sub" |), + make_list [ + M.get_name (| globals, "y" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.get_name (| globals, "result" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition mul : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Multiply the top two elements of the stack, and pushes the result back + on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "x" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "y" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_LOW" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "result" , + M.call (| + M.get_field (| M.get_name (| globals, "x" |), "wrapping_mul" |), + make_list [ + M.get_name (| globals, "y" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.get_name (| globals, "result" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition div : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Integer division of the top two elements of the stack. Pushes the result + back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "dividend" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "divisor" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_LOW" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, "divisor" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "quotient" , + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "quotient" , + BinOp.floor_div (| + M.get_name (| globals, "dividend" |), + M.get_name (| globals, "divisor" |) + |) + |) in + M.pure Constant.None_ + )) |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.get_name (| globals, "quotient" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition sdiv : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Signed integer division of the top two elements of the stack. Pushes the + result back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "dividend" , + M.call (| + M.get_field (| M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |), "to_signed" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "divisor" , + M.call (| + M.get_field (| M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |), "to_signed" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_LOW" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, "divisor" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "quotient" , + Constant.int 0 + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + BoolOp.and (| + Compare.eq (| + M.get_name (| globals, "dividend" |), + UnOp.sub (| M.get_name (| globals, "U255_CEIL_VALUE" |) |) + |), + ltac:(M.monadic ( + Compare.eq (| + M.get_name (| globals, "divisor" |), + UnOp.sub (| Constant.int 1 |) + |) + )) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "quotient" , + UnOp.sub (| M.get_name (| globals, "U255_CEIL_VALUE" |) |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "sign" , + M.call (| + M.get_name (| globals, "get_sign" |), + make_list [ + BinOp.mult (| + M.get_name (| globals, "dividend" |), + M.get_name (| globals, "divisor" |) + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "quotient" , + BinOp.mult (| + M.get_name (| globals, "sign" |), + BinOp.floor_div (| + M.call (| + M.get_name (| globals, "abs" |), + make_list [ + M.get_name (| globals, "dividend" |) + ], + make_dict [] + |), + M.call (| + M.get_name (| globals, "abs" |), + make_list [ + M.get_name (| globals, "divisor" |) + ], + make_dict [] + |) + |) + |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )) |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.call (| + M.get_field (| M.get_name (| globals, "U256" |), "from_signed" |), + make_list [ + M.get_name (| globals, "quotient" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition mod_ : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Modulo remainder of the top two elements of the stack. Pushes the result + back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "x" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "y" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_LOW" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, "y" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "remainder" , + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "remainder" , + BinOp.mod_ (| + M.get_name (| globals, "x" |), + M.get_name (| globals, "y" |) + |) + |) in + M.pure Constant.None_ + )) |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.get_name (| globals, "remainder" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition smod : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Signed modulo remainder of the top two elements of the stack. Pushes the + result back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "x" , + M.call (| + M.get_field (| M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |), "to_signed" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "y" , + M.call (| + M.get_field (| M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |), "to_signed" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_LOW" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, "y" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "remainder" , + Constant.int 0 + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "remainder" , + BinOp.mult (| + M.call (| + M.get_name (| globals, "get_sign" |), + make_list [ + M.get_name (| globals, "x" |) + ], + make_dict [] + |), + BinOp.mod_ (| + M.call (| + M.get_name (| globals, "abs" |), + make_list [ + M.get_name (| globals, "x" |) + ], + make_dict [] + |), + M.call (| + M.get_name (| globals, "abs" |), + make_list [ + M.get_name (| globals, "y" |) + ], + make_dict [] + |) + |) + |) + |) in + M.pure Constant.None_ + )) |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.call (| + M.get_field (| M.get_name (| globals, "U256" |), "from_signed" |), + make_list [ + M.get_name (| globals, "remainder" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition addmod : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Modulo addition of the top 2 elements with the 3rd element. Pushes the + result back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "x" , + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "y" , + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "z" , + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_MID" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, "z" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "result" , + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "result" , + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + BinOp.mod_ (| + BinOp.add (| + M.get_name (| globals, "x" |), + M.get_name (| globals, "y" |) + |), + M.get_name (| globals, "z" |) + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + )) |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.get_name (| globals, "result" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition mulmod : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Modulo multiplication of the top 2 elements with the 3rd element. Pushes + the result back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "x" , + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "y" , + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "z" , + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_MID" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, "z" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "result" , + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "result" , + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + BinOp.mod_ (| + BinOp.mult (| + M.get_name (| globals, "x" |), + M.get_name (| globals, "y" |) + |), + M.get_name (| globals, "z" |) + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + )) |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.get_name (| globals, "result" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition exp : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Exponential operation of the top 2 elements. Pushes the result back on + the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "base" , + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "exponent" , + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "exponent_bits" , + M.call (| + M.get_field (| M.get_name (| globals, "exponent" |), "bit_length" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "exponent_bytes" , + BinOp.floor_div (| + BinOp.add (| + M.get_name (| globals, "exponent_bits" |), + Constant.int 7 + |), + Constant.int 8 + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + BinOp.add (| + M.get_name (| globals, "GAS_EXPONENTIATION" |), + BinOp.mult (| + M.get_name (| globals, "GAS_EXPONENTIATION_PER_BYTE" |), + M.get_name (| globals, "exponent_bytes" |) + |) + |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "result" , + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + M.call (| + M.get_name (| globals, "pow" |), + make_list [ + M.get_name (| globals, "base" |); + M.get_name (| globals, "exponent" |); + M.get_name (| globals, "U256_CEIL_VALUE" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.get_name (| globals, "result" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition signextend : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Sign extend operation. In other words, extend a signed number which + fits in N bytes to 32 bytes. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "byte_num" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "value" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_LOW" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.gt (| + M.get_name (| globals, "byte_num" |), + Constant.int 31 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "result" , + M.get_name (| globals, "value" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "value_bytes" , + M.call (| + M.get_name (| globals, "bytes" |), + make_list [ + M.call (| + M.get_field (| M.get_name (| globals, "value" |), "to_be_bytes32" |), + make_list [], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "value_bytes" , + M.slice (| + M.get_name (| globals, "value_bytes" |), + BinOp.sub (| + Constant.int 31, + M.call (| + M.get_name (| globals, "int" |), + make_list [ + M.get_name (| globals, "byte_num" |) + ], + make_dict [] + |) + |), + Constant.None_, + Constant.None_ + |) + |) in + let _ := M.assign_local (| + "sign_bit" , + BinOp.r_shift (| + M.get_subscript (| + M.get_name (| globals, "value_bytes" |), + Constant.int 0 + |), + Constant.int 7 + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, "sign_bit" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "result" , + M.call (| + M.get_field (| M.get_name (| globals, "U256" |), "from_be_bytes" |), + make_list [ + M.get_name (| globals, "value_bytes" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "num_bytes_prepend" , + BinOp.sub (| + Constant.int 32, + BinOp.add (| + M.get_name (| globals, "byte_num" |), + Constant.int 1 + |) + |) + |) in + let _ := M.assign_local (| + "result" , + M.call (| + M.get_field (| M.get_name (| globals, "U256" |), "from_be_bytes" |), + make_list [ + BinOp.add (| + M.call (| + M.get_name (| globals, "bytearray" |), + make_list [ + BinOp.mult (| + make_list [ + Constant.int 255 + ], + M.get_name (| globals, "num_bytes_prepend" |) + |) + ], + make_dict [] + |), + M.get_name (| globals, "value_bytes" |) + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )) |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.get_name (| globals, "result" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). diff --git a/CoqOfPython/ethereum/istanbul/vm/instructions/bitwise.v b/CoqOfPython/ethereum/istanbul/vm/instructions/bitwise.v new file mode 100644 index 0000000..cf2b256 --- /dev/null +++ b/CoqOfPython/ethereum/istanbul/vm/instructions/bitwise.v @@ -0,0 +1,666 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.istanbul.vm.instructions.bitwise". + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) Bitwise Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM bitwise instructions. +". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_U256_CEIL_VALUE : + IsImported globals "ethereum.base_types" "U256_CEIL_VALUE". + +Axiom ethereum_istanbul_vm_imports_Evm : + IsImported globals "ethereum.istanbul.vm" "Evm". + +Axiom ethereum_istanbul_vm_gas_imports_GAS_VERY_LOW : + IsImported globals "ethereum.istanbul.vm.gas" "GAS_VERY_LOW". +Axiom ethereum_istanbul_vm_gas_imports_charge_gas : + IsImported globals "ethereum.istanbul.vm.gas" "charge_gas". + +Axiom ethereum_istanbul_vm_stack_imports_pop : + IsImported globals "ethereum.istanbul.vm.stack" "pop". +Axiom ethereum_istanbul_vm_stack_imports_push : + IsImported globals "ethereum.istanbul.vm.stack" "push". + +Definition bitwise_and : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Bitwise AND operation of the top 2 elements of the stack. Pushes the + result back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "x" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "y" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_VERY_LOW" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + BinOp.bit_and (| + M.get_name (| globals, "x" |), + M.get_name (| globals, "y" |) + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition bitwise_or : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Bitwise OR operation of the top 2 elements of the stack. Pushes the + result back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "x" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "y" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_VERY_LOW" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + BinOp.bit_or (| + M.get_name (| globals, "x" |), + M.get_name (| globals, "y" |) + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition bitwise_xor : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Bitwise XOR operation of the top 2 elements of the stack. Pushes the + result back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "x" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "y" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_VERY_LOW" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + BinOp.bit_xor (| + M.get_name (| globals, "x" |), + M.get_name (| globals, "y" |) + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition bitwise_not : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Bitwise NOT operation of the top element of the stack. Pushes the + result back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "x" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_VERY_LOW" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + UnOp.invert (| M.get_name (| globals, "x" |) |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition get_byte : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + For a word (defined by next top element of the stack), retrieve the + Nth byte (0-indexed and defined by top element of stack) from the + left (most significant) to right (least significant). + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "byte_index" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "word" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_VERY_LOW" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.gt_e (| + M.get_name (| globals, "byte_index" |), + Constant.int 32 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "result" , + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "extra_bytes_to_right" , + BinOp.sub (| + Constant.int 31, + M.get_name (| globals, "byte_index" |) + |) + |) in + let _ := M.assign_local (| + "word" , + BinOp.r_shift (| + M.get_name (| globals, "word" |), + BinOp.mult (| + M.get_name (| globals, "extra_bytes_to_right" |), + Constant.int 8 + |) + |) + |) in + let _ := M.assign_local (| + "word" , + BinOp.bit_and (| + M.get_name (| globals, "word" |), + Constant.int 255 + |) + |) in + let _ := M.assign_local (| + "result" , + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + M.get_name (| globals, "word" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + )) |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.get_name (| globals, "result" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition bitwise_shl : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Logical shift left (SHL) operation of the top 2 elements of the stack. + Pushes the result back on the stack. + Parameters + ---------- + evm : + The current EVM frame. + " in + let _ := M.assign_local (| + "shift" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "value" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_VERY_LOW" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.lt (| + M.get_name (| globals, "shift" |), + Constant.int 256 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "result" , + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + BinOp.mod_ (| + BinOp.l_shift (| + M.get_name (| globals, "value" |), + M.get_name (| globals, "shift" |) + |), + M.get_name (| globals, "U256_CEIL_VALUE" |) + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "result" , + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + )) |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.get_name (| globals, "result" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition bitwise_shr : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Logical shift right (SHR) operation of the top 2 elements of the stack. + Pushes the result back on the stack. + Parameters + ---------- + evm : + The current EVM frame. + " in + let _ := M.assign_local (| + "shift" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "value" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_VERY_LOW" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.lt (| + M.get_name (| globals, "shift" |), + Constant.int 256 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "result" , + BinOp.r_shift (| + M.get_name (| globals, "value" |), + M.get_name (| globals, "shift" |) + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "result" , + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + )) |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.get_name (| globals, "result" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition bitwise_sar : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Arithmetic shift right (SAR) operation of the top 2 elements of the stack. + Pushes the result back on the stack. + Parameters + ---------- + evm : + The current EVM frame. + " in + let _ := M.assign_local (| + "shift" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "signed_value" , + M.call (| + M.get_field (| M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |), "to_signed" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_VERY_LOW" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.lt (| + M.get_name (| globals, "shift" |), + Constant.int 256 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "result" , + M.call (| + M.get_field (| M.get_name (| globals, "U256" |), "from_signed" |), + make_list [ + BinOp.r_shift (| + M.get_name (| globals, "signed_value" |), + M.get_name (| globals, "shift" |) + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + Compare.gt_e (| + M.get_name (| globals, "signed_value" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "result" , + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "result" , + M.get_field (| M.get_name (| globals, "U256" |), "MAX_VALUE" |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )) |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.get_name (| globals, "result" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). diff --git a/CoqOfPython/ethereum/istanbul/vm/instructions/block.v b/CoqOfPython/ethereum/istanbul/vm/instructions/block.v new file mode 100644 index 0000000..9b0f81f --- /dev/null +++ b/CoqOfPython/ethereum/istanbul/vm/instructions/block.v @@ -0,0 +1,390 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.istanbul.vm.instructions.block". + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) Block Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM block instructions. +". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". + +Axiom ethereum_istanbul_vm_imports_Evm : + IsImported globals "ethereum.istanbul.vm" "Evm". + +Axiom ethereum_istanbul_vm_gas_imports_GAS_BASE : + IsImported globals "ethereum.istanbul.vm.gas" "GAS_BASE". +Axiom ethereum_istanbul_vm_gas_imports_GAS_BLOCK_HASH : + IsImported globals "ethereum.istanbul.vm.gas" "GAS_BLOCK_HASH". +Axiom ethereum_istanbul_vm_gas_imports_charge_gas : + IsImported globals "ethereum.istanbul.vm.gas" "charge_gas". + +Axiom ethereum_istanbul_vm_stack_imports_pop : + IsImported globals "ethereum.istanbul.vm.stack" "pop". +Axiom ethereum_istanbul_vm_stack_imports_push : + IsImported globals "ethereum.istanbul.vm.stack" "push". + +Definition block_hash : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Push the hash of one of the 256 most recent complete blocks onto the + stack. The block number to hash is present at the top of the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "block_number" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_BLOCK_HASH" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + BoolOp.or (| + Compare.lt_e (| + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "env" |), "number" |), + M.get_name (| globals, "block_number" |) + |), + ltac:(M.monadic ( + Compare.gt (| + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "env" |), "number" |), + BinOp.add (| + M.get_name (| globals, "block_number" |), + Constant.int 256 + |) + |) + )) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "hash" , + Constant.bytes "00" + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "hash" , + M.get_subscript (| + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "env" |), "block_hashes" |), + UnOp.sub (| BinOp.sub (| + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "env" |), "number" |), + M.get_name (| globals, "block_number" |) + |) |) + |) + |) in + M.pure Constant.None_ + )) |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.call (| + M.get_field (| M.get_name (| globals, "U256" |), "from_be_bytes" |), + make_list [ + M.get_name (| globals, "hash" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition coinbase : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Push the current block's beneficiary address (address of the block miner) + onto the stack. + + Here the current block refers to the block in which the currently + executing transaction/call resides. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_BASE" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.call (| + M.get_field (| M.get_name (| globals, "U256" |), "from_be_bytes" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "env" |), "coinbase" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition timestamp : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Push the current block's timestamp onto the stack. Here the timestamp + being referred is actually the unix timestamp in seconds. + + Here the current block refers to the block in which the currently + executing transaction/call resides. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_BASE" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "env" |), "time" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition number : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Push the current block's number onto the stack. + + Here the current block refers to the block in which the currently + executing transaction/call resides. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_BASE" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "env" |), "number" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition difficulty : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Push the current block's difficulty onto the stack. + + Here the current block refers to the block in which the currently + executing transaction/call resides. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_BASE" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "env" |), "difficulty" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition gas_limit : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Push the current block's gas limit onto the stack. + + Here the current block refers to the block in which the currently + executing transaction/call resides. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_BASE" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "env" |), "gas_limit" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition chain_id : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Push the chain id onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_BASE" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "env" |), "chain_id" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). diff --git a/CoqOfPython/ethereum/istanbul/vm/instructions/comparison.v b/CoqOfPython/ethereum/istanbul/vm/instructions/comparison.v new file mode 100644 index 0000000..3ddb9b3 --- /dev/null +++ b/CoqOfPython/ethereum/istanbul/vm/instructions/comparison.v @@ -0,0 +1,452 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.istanbul.vm.instructions.comparison". + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) Comparison Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM Comparison instructions. +". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". + +Axiom ethereum_istanbul_vm_imports_Evm : + IsImported globals "ethereum.istanbul.vm" "Evm". + +Axiom ethereum_istanbul_vm_gas_imports_GAS_VERY_LOW : + IsImported globals "ethereum.istanbul.vm.gas" "GAS_VERY_LOW". +Axiom ethereum_istanbul_vm_gas_imports_charge_gas : + IsImported globals "ethereum.istanbul.vm.gas" "charge_gas". + +Axiom ethereum_istanbul_vm_stack_imports_pop : + IsImported globals "ethereum.istanbul.vm.stack" "pop". +Axiom ethereum_istanbul_vm_stack_imports_push : + IsImported globals "ethereum.istanbul.vm.stack" "push". + +Definition less_than : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Checks if the top element is less than the next top element. Pushes the + result back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "left" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "right" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_VERY_LOW" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "result" , + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Compare.lt (| + M.get_name (| globals, "left" |), + M.get_name (| globals, "right" |) + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.get_name (| globals, "result" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition signed_less_than : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Signed less-than comparison. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "left" , + M.call (| + M.get_field (| M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |), "to_signed" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "right" , + M.call (| + M.get_field (| M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |), "to_signed" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_VERY_LOW" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "result" , + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Compare.lt (| + M.get_name (| globals, "left" |), + M.get_name (| globals, "right" |) + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.get_name (| globals, "result" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition greater_than : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Checks if the top element is greater than the next top element. Pushes + the result back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "left" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "right" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_VERY_LOW" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "result" , + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Compare.gt (| + M.get_name (| globals, "left" |), + M.get_name (| globals, "right" |) + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.get_name (| globals, "result" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition signed_greater_than : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Signed greater-than comparison. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "left" , + M.call (| + M.get_field (| M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |), "to_signed" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "right" , + M.call (| + M.get_field (| M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |), "to_signed" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_VERY_LOW" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "result" , + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Compare.gt (| + M.get_name (| globals, "left" |), + M.get_name (| globals, "right" |) + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.get_name (| globals, "result" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition equal : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Checks if the top element is equal to the next top element. Pushes + the result back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "left" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "right" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_VERY_LOW" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "result" , + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Compare.eq (| + M.get_name (| globals, "left" |), + M.get_name (| globals, "right" |) + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.get_name (| globals, "result" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition is_zero : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Checks if the top element is equal to 0. Pushes the result back on the + stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "x" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_VERY_LOW" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "result" , + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Compare.eq (| + M.get_name (| globals, "x" |), + Constant.int 0 + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.get_name (| globals, "result" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). diff --git a/CoqOfPython/ethereum/istanbul/vm/instructions/control_flow.v b/CoqOfPython/ethereum/istanbul/vm/instructions/control_flow.v new file mode 100644 index 0000000..540d4de --- /dev/null +++ b/CoqOfPython/ethereum/istanbul/vm/instructions/control_flow.v @@ -0,0 +1,350 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.istanbul.vm.instructions.control_flow". + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) Control Flow Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM control flow instructions. +". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". + +Axiom ethereum_istanbul_vm_gas_imports_GAS_BASE : + IsImported globals "ethereum.istanbul.vm.gas" "GAS_BASE". +Axiom ethereum_istanbul_vm_gas_imports_GAS_HIGH : + IsImported globals "ethereum.istanbul.vm.gas" "GAS_HIGH". +Axiom ethereum_istanbul_vm_gas_imports_GAS_JUMPDEST : + IsImported globals "ethereum.istanbul.vm.gas" "GAS_JUMPDEST". +Axiom ethereum_istanbul_vm_gas_imports_GAS_MID : + IsImported globals "ethereum.istanbul.vm.gas" "GAS_MID". +Axiom ethereum_istanbul_vm_gas_imports_charge_gas : + IsImported globals "ethereum.istanbul.vm.gas" "charge_gas". + +Axiom ethereum_istanbul_vm_imports_Evm : + IsImported globals "ethereum.istanbul.vm" "Evm". + +Axiom ethereum_istanbul_vm_exceptions_imports_InvalidJumpDestError : + IsImported globals "ethereum.istanbul.vm.exceptions" "InvalidJumpDestError". + +Axiom ethereum_istanbul_vm_stack_imports_pop : + IsImported globals "ethereum.istanbul.vm.stack" "pop". +Axiom ethereum_istanbul_vm_stack_imports_push : + IsImported globals "ethereum.istanbul.vm.stack" "push". + +Definition stop : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Stop further execution of EVM code. + + Parameters + ---------- + evm : + The current EVM frame. + " in + let _ := M.pass (| |) in + let _ := M.pass (| |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, "evm" |), "running" |), + Constant.bool false + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition jump : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Alter the program counter to the location specified by the top of the + stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "jump_dest" , + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_MID" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.not_in (| + M.get_name (| globals, "jump_dest" |), + M.get_field (| M.get_name (| globals, "evm" |), "valid_jump_destinations" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, "InvalidJumpDestError" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.get_name (| globals, "jump_dest" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Definition jumpi : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Alter the program counter to the specified location if and only if a + condition is true. If the condition is not true, then the program counter + would increase only by 1. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "jump_dest" , + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "conditional_value" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_HIGH" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, "conditional_value" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "destination" , + BinOp.add (| + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + Compare.not_in (| + M.get_name (| globals, "jump_dest" |), + M.get_field (| M.get_name (| globals, "evm" |), "valid_jump_destinations" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, "InvalidJumpDestError" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "destination" , + M.get_name (| globals, "jump_dest" |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )) |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.get_name (| globals, "destination" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Definition pc : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Push onto the stack the value of the program counter after reaching the + current instruction and without increasing it for the next instruction. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_BASE" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "pc" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition gas_left : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Push the amount of available gas (including the corresponding reduction + for the cost of this instruction) onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_BASE" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "gas_left" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition jumpdest : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Mark a valid destination for jumps. This is a noop, present only + to be used by `JUMP` and `JUMPI` opcodes to verify that their jump is + valid. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_JUMPDEST" |) + ], + make_dict [] + |) in + let _ := M.pass (| |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). diff --git a/CoqOfPython/ethereum/istanbul/vm/instructions/environment.v b/CoqOfPython/ethereum/istanbul/vm/instructions/environment.v new file mode 100644 index 0000000..6cda0d2 --- /dev/null +++ b/CoqOfPython/ethereum/istanbul/vm/instructions/environment.v @@ -0,0 +1,1367 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.istanbul.vm.instructions.environment". + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) Environmental Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM environment related instructions. +". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". + +Axiom ethereum_crypto_hash_imports_keccak256 : + IsImported globals "ethereum.crypto.hash" "keccak256". + +Axiom ethereum_utils_ensure_imports_ensure : + IsImported globals "ethereum.utils.ensure" "ensure". + +Axiom ethereum_utils_numeric_imports_ceil32 : + IsImported globals "ethereum.utils.numeric" "ceil32". + +Axiom ethereum_istanbul_fork_types_imports_EMPTY_ACCOUNT : + IsImported globals "ethereum.istanbul.fork_types" "EMPTY_ACCOUNT". + +Axiom ethereum_istanbul_state_imports_get_account : + IsImported globals "ethereum.istanbul.state" "get_account". + +Axiom ethereum_istanbul_utils_address_imports_to_address : + IsImported globals "ethereum.istanbul.utils.address" "to_address". + +Axiom ethereum_istanbul_vm_memory_imports_buffer_read : + IsImported globals "ethereum.istanbul.vm.memory" "buffer_read". +Axiom ethereum_istanbul_vm_memory_imports_memory_write : + IsImported globals "ethereum.istanbul.vm.memory" "memory_write". + +Axiom ethereum_istanbul_vm_imports_Evm : + IsImported globals "ethereum.istanbul.vm" "Evm". + +Axiom ethereum_istanbul_vm_exceptions_imports_OutOfBoundsRead : + IsImported globals "ethereum.istanbul.vm.exceptions" "OutOfBoundsRead". + +Axiom ethereum_istanbul_vm_gas_imports_GAS_BALANCE : + IsImported globals "ethereum.istanbul.vm.gas" "GAS_BALANCE". +Axiom ethereum_istanbul_vm_gas_imports_GAS_BASE : + IsImported globals "ethereum.istanbul.vm.gas" "GAS_BASE". +Axiom ethereum_istanbul_vm_gas_imports_GAS_CODE_HASH : + IsImported globals "ethereum.istanbul.vm.gas" "GAS_CODE_HASH". +Axiom ethereum_istanbul_vm_gas_imports_GAS_COPY : + IsImported globals "ethereum.istanbul.vm.gas" "GAS_COPY". +Axiom ethereum_istanbul_vm_gas_imports_GAS_EXTERNAL : + IsImported globals "ethereum.istanbul.vm.gas" "GAS_EXTERNAL". +Axiom ethereum_istanbul_vm_gas_imports_GAS_FAST_STEP : + IsImported globals "ethereum.istanbul.vm.gas" "GAS_FAST_STEP". +Axiom ethereum_istanbul_vm_gas_imports_GAS_RETURN_DATA_COPY : + IsImported globals "ethereum.istanbul.vm.gas" "GAS_RETURN_DATA_COPY". +Axiom ethereum_istanbul_vm_gas_imports_GAS_VERY_LOW : + IsImported globals "ethereum.istanbul.vm.gas" "GAS_VERY_LOW". +Axiom ethereum_istanbul_vm_gas_imports_calculate_gas_extend_memory : + IsImported globals "ethereum.istanbul.vm.gas" "calculate_gas_extend_memory". +Axiom ethereum_istanbul_vm_gas_imports_charge_gas : + IsImported globals "ethereum.istanbul.vm.gas" "charge_gas". + +Axiom ethereum_istanbul_vm_stack_imports_pop : + IsImported globals "ethereum.istanbul.vm.stack" "pop". +Axiom ethereum_istanbul_vm_stack_imports_push : + IsImported globals "ethereum.istanbul.vm.stack" "push". + +Definition address : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Pushes the address of the current executing account to the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_BASE" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.call (| + M.get_field (| M.get_name (| globals, "U256" |), "from_be_bytes" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "current_target" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition balance : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Pushes the balance of the given account onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "address" , + M.call (| + M.get_name (| globals, "to_address" |), + make_list [ + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_BALANCE" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "balance" , + M.get_field (| M.call (| + M.get_name (| globals, "get_account" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "env" |), "state" |); + M.get_name (| globals, "address" |) + ], + make_dict [] + |), "balance" |) + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.get_name (| globals, "balance" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition origin : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Pushes the address of the original transaction sender to the stack. + The origin address can only be an EOA. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_BASE" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.call (| + M.get_field (| M.get_name (| globals, "U256" |), "from_be_bytes" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "env" |), "origin" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition caller : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Pushes the address of the caller onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_BASE" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.call (| + M.get_field (| M.get_name (| globals, "U256" |), "from_be_bytes" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "caller" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition callvalue : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Push the value (in wei) sent with the call onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_BASE" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "value" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition calldataload : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Push a word (32 bytes) of the input data belonging to the current + environment onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "start_index" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_VERY_LOW" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "value" , + M.call (| + M.get_name (| globals, "buffer_read" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "data" |); + M.get_name (| globals, "start_index" |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 32 + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.call (| + M.get_field (| M.get_name (| globals, "U256" |), "from_be_bytes" |), + make_list [ + M.get_name (| globals, "value" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition calldatasize : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Push the size of input data in current environment onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_BASE" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "data" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition calldatacopy : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Copy a portion of the input data in current environment to memory. + + This will also expand the memory, in case that the memory is insufficient + to store the data. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "memory_start_index" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "data_start_index" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "size" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "words" , + BinOp.floor_div (| + M.call (| + M.get_name (| globals, "ceil32" |), + make_list [ + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.get_name (| globals, "size" |) + ], + make_dict [] + |) + ], + make_dict [] + |), + Constant.int 32 + |) + |) in + let _ := M.assign_local (| + "copy_gas_cost" , + BinOp.mult (| + M.get_name (| globals, "GAS_COPY" |), + M.get_name (| globals, "words" |) + |) + |) in + let _ := M.assign_local (| + "extend_memory" , + M.call (| + M.get_name (| globals, "calculate_gas_extend_memory" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "memory" |); + make_list [ + make_tuple [ M.get_name (| globals, "memory_start_index" |); M.get_name (| globals, "size" |) ] + ] + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + BinOp.add (| + BinOp.add (| + M.get_name (| globals, "GAS_VERY_LOW" |), + M.get_name (| globals, "copy_gas_cost" |) + |), + M.get_field (| M.get_name (| globals, "extend_memory" |), "cost" |) + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "memory" |), + BinOp.mult (| + Constant.bytes "00", + M.get_field (| M.get_name (| globals, "extend_memory" |), "expand_by" |) + |) + |) in + let _ := M.assign_local (| + "value" , + M.call (| + M.get_name (| globals, "buffer_read" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "data" |); + M.get_name (| globals, "data_start_index" |); + M.get_name (| globals, "size" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "memory_write" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "memory" |); + M.get_name (| globals, "memory_start_index" |); + M.get_name (| globals, "value" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition codesize : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Push the size of code running in current environment onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_BASE" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "code" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition codecopy : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Copy a portion of the code in current environment to memory. + + This will also expand the memory, in case that the memory is insufficient + to store the data. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "memory_start_index" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "code_start_index" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "size" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "words" , + BinOp.floor_div (| + M.call (| + M.get_name (| globals, "ceil32" |), + make_list [ + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.get_name (| globals, "size" |) + ], + make_dict [] + |) + ], + make_dict [] + |), + Constant.int 32 + |) + |) in + let _ := M.assign_local (| + "copy_gas_cost" , + BinOp.mult (| + M.get_name (| globals, "GAS_COPY" |), + M.get_name (| globals, "words" |) + |) + |) in + let _ := M.assign_local (| + "extend_memory" , + M.call (| + M.get_name (| globals, "calculate_gas_extend_memory" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "memory" |); + make_list [ + make_tuple [ M.get_name (| globals, "memory_start_index" |); M.get_name (| globals, "size" |) ] + ] + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + BinOp.add (| + BinOp.add (| + M.get_name (| globals, "GAS_VERY_LOW" |), + M.get_name (| globals, "copy_gas_cost" |) + |), + M.get_field (| M.get_name (| globals, "extend_memory" |), "cost" |) + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "memory" |), + BinOp.mult (| + Constant.bytes "00", + M.get_field (| M.get_name (| globals, "extend_memory" |), "expand_by" |) + |) + |) in + let _ := M.assign_local (| + "value" , + M.call (| + M.get_name (| globals, "buffer_read" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "code" |); + M.get_name (| globals, "code_start_index" |); + M.get_name (| globals, "size" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "memory_write" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "memory" |); + M.get_name (| globals, "memory_start_index" |); + M.get_name (| globals, "value" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition gasprice : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Push the gas price used in current environment onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_BASE" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "env" |), "gas_price" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition extcodesize : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Push the code size of a given account onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "address" , + M.call (| + M.get_name (| globals, "to_address" |), + make_list [ + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_EXTERNAL" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "codesize" , + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_field (| M.call (| + M.get_name (| globals, "get_account" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "env" |), "state" |); + M.get_name (| globals, "address" |) + ], + make_dict [] + |), "code" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.get_name (| globals, "codesize" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition extcodecopy : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Copy a portion of an account's code to memory. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "address" , + M.call (| + M.get_name (| globals, "to_address" |), + make_list [ + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_start_index" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "code_start_index" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "size" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "words" , + BinOp.floor_div (| + M.call (| + M.get_name (| globals, "ceil32" |), + make_list [ + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.get_name (| globals, "size" |) + ], + make_dict [] + |) + ], + make_dict [] + |), + Constant.int 32 + |) + |) in + let _ := M.assign_local (| + "copy_gas_cost" , + BinOp.mult (| + M.get_name (| globals, "GAS_COPY" |), + M.get_name (| globals, "words" |) + |) + |) in + let _ := M.assign_local (| + "extend_memory" , + M.call (| + M.get_name (| globals, "calculate_gas_extend_memory" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "memory" |); + make_list [ + make_tuple [ M.get_name (| globals, "memory_start_index" |); M.get_name (| globals, "size" |) ] + ] + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + BinOp.add (| + BinOp.add (| + M.get_name (| globals, "GAS_EXTERNAL" |), + M.get_name (| globals, "copy_gas_cost" |) + |), + M.get_field (| M.get_name (| globals, "extend_memory" |), "cost" |) + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "memory" |), + BinOp.mult (| + Constant.bytes "00", + M.get_field (| M.get_name (| globals, "extend_memory" |), "expand_by" |) + |) + |) in + let _ := M.assign_local (| + "code" , + M.get_field (| M.call (| + M.get_name (| globals, "get_account" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "env" |), "state" |); + M.get_name (| globals, "address" |) + ], + make_dict [] + |), "code" |) + |) in + let _ := M.assign_local (| + "value" , + M.call (| + M.get_name (| globals, "buffer_read" |), + make_list [ + M.get_name (| globals, "code" |); + M.get_name (| globals, "code_start_index" |); + M.get_name (| globals, "size" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "memory_write" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "memory" |); + M.get_name (| globals, "memory_start_index" |); + M.get_name (| globals, "value" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition returndatasize : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Pushes the size of the return data buffer onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_BASE" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "return_data" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition returndatacopy : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Copies data from the return data buffer code to memory + + Parameters + ---------- + evm : + The current EVM frame. + " in + let _ := M.assign_local (| + "memory_start_index" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "return_data_start_position" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "size" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "words" , + BinOp.floor_div (| + M.call (| + M.get_name (| globals, "ceil32" |), + make_list [ + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.get_name (| globals, "size" |) + ], + make_dict [] + |) + ], + make_dict [] + |), + Constant.int 32 + |) + |) in + let _ := M.assign_local (| + "copy_gas_cost" , + BinOp.mult (| + M.get_name (| globals, "GAS_RETURN_DATA_COPY" |), + M.get_name (| globals, "words" |) + |) + |) in + let _ := M.assign_local (| + "extend_memory" , + M.call (| + M.get_name (| globals, "calculate_gas_extend_memory" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "memory" |); + make_list [ + make_tuple [ M.get_name (| globals, "memory_start_index" |); M.get_name (| globals, "size" |) ] + ] + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + BinOp.add (| + BinOp.add (| + M.get_name (| globals, "GAS_VERY_LOW" |), + M.get_name (| globals, "copy_gas_cost" |) + |), + M.get_field (| M.get_name (| globals, "extend_memory" |), "cost" |) + |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + Compare.lt_e (| + BinOp.add (| + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.get_name (| globals, "return_data_start_position" |) + ], + make_dict [] + |), + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.get_name (| globals, "size" |) + ], + make_dict [] + |) + |), + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "return_data" |) + ], + make_dict [] + |) + |); + M.get_name (| globals, "OutOfBoundsRead" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "memory" |), + BinOp.mult (| + Constant.bytes "00", + M.get_field (| M.get_name (| globals, "extend_memory" |), "expand_by" |) + |) + |) in + let _ := M.assign_local (| + "value" , + M.slice (| + M.get_field (| M.get_name (| globals, "evm" |), "return_data" |), + M.get_name (| globals, "return_data_start_position" |), + BinOp.add (| + M.get_name (| globals, "return_data_start_position" |), + M.get_name (| globals, "size" |) + |), + Constant.None_ + |) + |) in + let _ := M.call (| + M.get_name (| globals, "memory_write" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "memory" |); + M.get_name (| globals, "memory_start_index" |); + M.get_name (| globals, "value" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition extcodehash : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Returns the keccak256 hash of a contract’s bytecode + Parameters + ---------- + evm : + The current EVM frame. + " in + let _ := M.assign_local (| + "address" , + M.call (| + M.get_name (| globals, "to_address" |), + make_list [ + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_CODE_HASH" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "account" , + M.call (| + M.get_name (| globals, "get_account" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "env" |), "state" |); + M.get_name (| globals, "address" |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, "account" |), + M.get_name (| globals, "EMPTY_ACCOUNT" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "codehash" , + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "codehash" , + M.call (| + M.get_field (| M.get_name (| globals, "U256" |), "from_be_bytes" |), + make_list [ + M.call (| + M.get_name (| globals, "keccak256" |), + make_list [ + M.get_field (| M.get_name (| globals, "account" |), "code" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + )) |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.get_name (| globals, "codehash" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition self_balance : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Pushes the balance of the current address to the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_FAST_STEP" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "balance" , + M.get_field (| M.call (| + M.get_name (| globals, "get_account" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "env" |), "state" |); + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "current_target" |) + ], + make_dict [] + |), "balance" |) + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.get_name (| globals, "balance" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). diff --git a/CoqOfPython/ethereum/istanbul/vm/instructions/keccak.v b/CoqOfPython/ethereum/istanbul/vm/instructions/keccak.v new file mode 100644 index 0000000..e4fa0c2 --- /dev/null +++ b/CoqOfPython/ethereum/istanbul/vm/instructions/keccak.v @@ -0,0 +1,188 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.istanbul.vm.instructions.keccak". + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) Keccak Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM keccak instructions. +". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". + +Axiom ethereum_crypto_hash_imports_keccak256 : + IsImported globals "ethereum.crypto.hash" "keccak256". + +Axiom ethereum_utils_numeric_imports_ceil32 : + IsImported globals "ethereum.utils.numeric" "ceil32". + +Axiom ethereum_istanbul_vm_imports_Evm : + IsImported globals "ethereum.istanbul.vm" "Evm". + +Axiom ethereum_istanbul_vm_gas_imports_GAS_KECCAK256 : + IsImported globals "ethereum.istanbul.vm.gas" "GAS_KECCAK256". +Axiom ethereum_istanbul_vm_gas_imports_GAS_KECCAK256_WORD : + IsImported globals "ethereum.istanbul.vm.gas" "GAS_KECCAK256_WORD". +Axiom ethereum_istanbul_vm_gas_imports_calculate_gas_extend_memory : + IsImported globals "ethereum.istanbul.vm.gas" "calculate_gas_extend_memory". +Axiom ethereum_istanbul_vm_gas_imports_charge_gas : + IsImported globals "ethereum.istanbul.vm.gas" "charge_gas". + +Axiom ethereum_istanbul_vm_memory_imports_memory_read_bytes : + IsImported globals "ethereum.istanbul.vm.memory" "memory_read_bytes". + +Axiom ethereum_istanbul_vm_stack_imports_pop : + IsImported globals "ethereum.istanbul.vm.stack" "pop". +Axiom ethereum_istanbul_vm_stack_imports_push : + IsImported globals "ethereum.istanbul.vm.stack" "push". + +Definition keccak : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Pushes to the stack the Keccak-256 hash of a region of memory. + + This also expands the memory, in case the memory is insufficient to + access the data's memory location. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "memory_start_index" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "size" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "words" , + BinOp.floor_div (| + M.call (| + M.get_name (| globals, "ceil32" |), + make_list [ + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.get_name (| globals, "size" |) + ], + make_dict [] + |) + ], + make_dict [] + |), + Constant.int 32 + |) + |) in + let _ := M.assign_local (| + "word_gas_cost" , + BinOp.mult (| + M.get_name (| globals, "GAS_KECCAK256_WORD" |), + M.get_name (| globals, "words" |) + |) + |) in + let _ := M.assign_local (| + "extend_memory" , + M.call (| + M.get_name (| globals, "calculate_gas_extend_memory" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "memory" |); + make_list [ + make_tuple [ M.get_name (| globals, "memory_start_index" |); M.get_name (| globals, "size" |) ] + ] + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + BinOp.add (| + BinOp.add (| + M.get_name (| globals, "GAS_KECCAK256" |), + M.get_name (| globals, "word_gas_cost" |) + |), + M.get_field (| M.get_name (| globals, "extend_memory" |), "cost" |) + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "memory" |), + BinOp.mult (| + Constant.bytes "00", + M.get_field (| M.get_name (| globals, "extend_memory" |), "expand_by" |) + |) + |) in + let _ := M.assign_local (| + "data" , + M.call (| + M.get_name (| globals, "memory_read_bytes" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "memory" |); + M.get_name (| globals, "memory_start_index" |); + M.get_name (| globals, "size" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "hash" , + M.call (| + M.get_name (| globals, "keccak256" |), + make_list [ + M.get_name (| globals, "data" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.call (| + M.get_field (| M.get_name (| globals, "U256" |), "from_be_bytes" |), + make_list [ + M.get_name (| globals, "hash" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). diff --git a/CoqOfPython/ethereum/istanbul/vm/instructions/log.v b/CoqOfPython/ethereum/istanbul/vm/instructions/log.v new file mode 100644 index 0000000..8471fb8 --- /dev/null +++ b/CoqOfPython/ethereum/istanbul/vm/instructions/log.v @@ -0,0 +1,256 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.istanbul.vm.instructions.log". + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) Logging Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM logging instructions. +". + +Axiom functools_imports_partial : + IsImported globals "functools" "partial". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". + +Axiom ethereum_utils_ensure_imports_ensure : + IsImported globals "ethereum.utils.ensure" "ensure". + +Axiom ethereum_istanbul_blocks_imports_Log : + IsImported globals "ethereum.istanbul.blocks" "Log". + +Axiom ethereum_istanbul_vm_imports_Evm : + IsImported globals "ethereum.istanbul.vm" "Evm". + +Axiom ethereum_istanbul_vm_exceptions_imports_WriteInStaticContext : + IsImported globals "ethereum.istanbul.vm.exceptions" "WriteInStaticContext". + +Axiom ethereum_istanbul_vm_gas_imports_GAS_LOG : + IsImported globals "ethereum.istanbul.vm.gas" "GAS_LOG". +Axiom ethereum_istanbul_vm_gas_imports_GAS_LOG_DATA : + IsImported globals "ethereum.istanbul.vm.gas" "GAS_LOG_DATA". +Axiom ethereum_istanbul_vm_gas_imports_GAS_LOG_TOPIC : + IsImported globals "ethereum.istanbul.vm.gas" "GAS_LOG_TOPIC". +Axiom ethereum_istanbul_vm_gas_imports_calculate_gas_extend_memory : + IsImported globals "ethereum.istanbul.vm.gas" "calculate_gas_extend_memory". +Axiom ethereum_istanbul_vm_gas_imports_charge_gas : + IsImported globals "ethereum.istanbul.vm.gas" "charge_gas". + +Axiom ethereum_istanbul_vm_memory_imports_memory_read_bytes : + IsImported globals "ethereum.istanbul.vm.memory" "memory_read_bytes". + +Axiom ethereum_istanbul_vm_stack_imports_pop : + IsImported globals "ethereum.istanbul.vm.stack" "pop". + +Definition log_n : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm"; "num_topics" ] |) in + let _ := Constant.str " + Appends a log entry, having `num_topics` topics, to the evm logs. + + This will also expand the memory if the data (required by the log entry) + corresponding to the memory is not accessible. + + Parameters + ---------- + evm : + The current EVM frame. + num_topics : + The number of topics to be included in the log entry. + + " in + let _ := M.assign_local (| + "memory_start_index" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "size" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "topics" , + make_list [] + |) in + let _ := + M.for_ (| + M.get_name (| globals, "_" |), + M.call (| + M.get_name (| globals, "range" |), + make_list [ + M.get_name (| globals, "num_topics" |) + ], + make_dict [] + |), + ltac:(M.monadic ( + let _ := M.assign_local (| + "topic" , + M.call (| + M.get_field (| M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |), "to_be_bytes32" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_field (| M.get_name (| globals, "topics" |), "append" |), + make_list [ + M.get_name (| globals, "topic" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := M.assign_local (| + "extend_memory" , + M.call (| + M.get_name (| globals, "calculate_gas_extend_memory" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "memory" |); + make_list [ + make_tuple [ M.get_name (| globals, "memory_start_index" |); M.get_name (| globals, "size" |) ] + ] + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + BinOp.add (| + BinOp.add (| + BinOp.add (| + M.get_name (| globals, "GAS_LOG" |), + BinOp.mult (| + M.get_name (| globals, "GAS_LOG_DATA" |), + M.get_name (| globals, "size" |) + |) + |), + BinOp.mult (| + M.get_name (| globals, "GAS_LOG_TOPIC" |), + M.get_name (| globals, "num_topics" |) + |) + |), + M.get_field (| M.get_name (| globals, "extend_memory" |), "cost" |) + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "memory" |), + BinOp.mult (| + Constant.bytes "00", + M.get_field (| M.get_name (| globals, "extend_memory" |), "expand_by" |) + |) + |) in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + UnOp.not (| M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "is_static" |) |); + M.get_name (| globals, "WriteInStaticContext" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "log_entry" , + M.call (| + M.get_name (| globals, "Log" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, "evm" |), "logs" |), + BinOp.add (| + M.get_field (| M.get_name (| globals, "evm" |), "logs" |), + make_tuple [ M.get_name (| globals, "log_entry" |) ] + |) + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition log0 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "log_n" |) + ], + make_dict [] + |) +)). + +Definition log1 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "log_n" |) + ], + make_dict [] + |) +)). + +Definition log2 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "log_n" |) + ], + make_dict [] + |) +)). + +Definition log3 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "log_n" |) + ], + make_dict [] + |) +)). + +Definition log4 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "log_n" |) + ], + make_dict [] + |) +)). diff --git a/CoqOfPython/ethereum/istanbul/vm/instructions/memory.v b/CoqOfPython/ethereum/istanbul/vm/instructions/memory.v new file mode 100644 index 0000000..139811a --- /dev/null +++ b/CoqOfPython/ethereum/istanbul/vm/instructions/memory.v @@ -0,0 +1,393 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.istanbul.vm.instructions.memory". + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) Memory Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM Memory instructions. +". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_Bytes : + IsImported globals "ethereum.base_types" "Bytes". + +Axiom ethereum_istanbul_vm_imports_Evm : + IsImported globals "ethereum.istanbul.vm" "Evm". + +Axiom ethereum_istanbul_vm_gas_imports_GAS_BASE : + IsImported globals "ethereum.istanbul.vm.gas" "GAS_BASE". +Axiom ethereum_istanbul_vm_gas_imports_GAS_VERY_LOW : + IsImported globals "ethereum.istanbul.vm.gas" "GAS_VERY_LOW". +Axiom ethereum_istanbul_vm_gas_imports_calculate_gas_extend_memory : + IsImported globals "ethereum.istanbul.vm.gas" "calculate_gas_extend_memory". +Axiom ethereum_istanbul_vm_gas_imports_charge_gas : + IsImported globals "ethereum.istanbul.vm.gas" "charge_gas". + +Axiom ethereum_istanbul_vm_memory_imports_memory_read_bytes : + IsImported globals "ethereum.istanbul.vm.memory" "memory_read_bytes". +Axiom ethereum_istanbul_vm_memory_imports_memory_write : + IsImported globals "ethereum.istanbul.vm.memory" "memory_write". + +Axiom ethereum_istanbul_vm_stack_imports_pop : + IsImported globals "ethereum.istanbul.vm.stack" "pop". +Axiom ethereum_istanbul_vm_stack_imports_push : + IsImported globals "ethereum.istanbul.vm.stack" "push". + +Definition mstore : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Stores a word to memory. + This also expands the memory, if the memory is + insufficient to store the word. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "start_position" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "value" , + M.call (| + M.get_field (| M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |), "to_be_bytes32" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "extend_memory" , + M.call (| + M.get_name (| globals, "calculate_gas_extend_memory" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "memory" |); + make_list [ + make_tuple [ M.get_name (| globals, "start_position" |); M.call (| + M.get_name (| globals, "U256" |), + make_list [ + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_name (| globals, "value" |) + ], + make_dict [] + |) + ], + make_dict [] + |) ] + ] + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + BinOp.add (| + M.get_name (| globals, "GAS_VERY_LOW" |), + M.get_field (| M.get_name (| globals, "extend_memory" |), "cost" |) + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "memory" |), + BinOp.mult (| + Constant.bytes "00", + M.get_field (| M.get_name (| globals, "extend_memory" |), "expand_by" |) + |) + |) in + let _ := M.call (| + M.get_name (| globals, "memory_write" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "memory" |); + M.get_name (| globals, "start_position" |); + M.get_name (| globals, "value" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition mstore8 : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Stores a byte to memory. + This also expands the memory, if the memory is + insufficient to store the word. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "start_position" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "value" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "extend_memory" , + M.call (| + M.get_name (| globals, "calculate_gas_extend_memory" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "memory" |); + make_list [ + make_tuple [ M.get_name (| globals, "start_position" |); M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 1 + ], + make_dict [] + |) ] + ] + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + BinOp.add (| + M.get_name (| globals, "GAS_VERY_LOW" |), + M.get_field (| M.get_name (| globals, "extend_memory" |), "cost" |) + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "memory" |), + BinOp.mult (| + Constant.bytes "00", + M.get_field (| M.get_name (| globals, "extend_memory" |), "expand_by" |) + |) + |) in + let _ := M.assign_local (| + "normalized_bytes_value" , + M.call (| + M.get_name (| globals, "Bytes" |), + make_list [ + make_list [ + BinOp.bit_and (| + M.get_name (| globals, "value" |), + Constant.int 255 + |) + ] + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "memory_write" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "memory" |); + M.get_name (| globals, "start_position" |); + M.get_name (| globals, "normalized_bytes_value" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition mload : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Load word from memory. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "start_position" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "extend_memory" , + M.call (| + M.get_name (| globals, "calculate_gas_extend_memory" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "memory" |); + make_list [ + make_tuple [ M.get_name (| globals, "start_position" |); M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 32 + ], + make_dict [] + |) ] + ] + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + BinOp.add (| + M.get_name (| globals, "GAS_VERY_LOW" |), + M.get_field (| M.get_name (| globals, "extend_memory" |), "cost" |) + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "memory" |), + BinOp.mult (| + Constant.bytes "00", + M.get_field (| M.get_name (| globals, "extend_memory" |), "expand_by" |) + |) + |) in + let _ := M.assign_local (| + "value" , + M.call (| + M.get_field (| M.get_name (| globals, "U256" |), "from_be_bytes" |), + make_list [ + M.call (| + M.get_name (| globals, "memory_read_bytes" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "memory" |); + M.get_name (| globals, "start_position" |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 32 + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.get_name (| globals, "value" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition msize : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Push the size of active memory in bytes onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_BASE" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "memory" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). diff --git a/CoqOfPython/ethereum/istanbul/vm/instructions/stack.v b/CoqOfPython/ethereum/istanbul/vm/instructions/stack.v new file mode 100644 index 0000000..36a6974 --- /dev/null +++ b/CoqOfPython/ethereum/istanbul/vm/instructions/stack.v @@ -0,0 +1,947 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.istanbul.vm.instructions.stack". + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) Stack Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM stack related instructions. +". + +Axiom functools_imports_partial : + IsImported globals "functools" "partial". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". + +Axiom ethereum_utils_ensure_imports_ensure : + IsImported globals "ethereum.utils.ensure" "ensure". + +Axiom ethereum_istanbul_vm_imports_Evm : + IsImported globals "ethereum.istanbul.vm" "Evm". +Axiom ethereum_istanbul_vm_imports_stack : + IsImported globals "ethereum.istanbul.vm" "stack". + +Axiom ethereum_istanbul_vm_exceptions_imports_StackUnderflowError : + IsImported globals "ethereum.istanbul.vm.exceptions" "StackUnderflowError". + +Axiom ethereum_istanbul_vm_gas_imports_GAS_BASE : + IsImported globals "ethereum.istanbul.vm.gas" "GAS_BASE". +Axiom ethereum_istanbul_vm_gas_imports_GAS_VERY_LOW : + IsImported globals "ethereum.istanbul.vm.gas" "GAS_VERY_LOW". +Axiom ethereum_istanbul_vm_gas_imports_charge_gas : + IsImported globals "ethereum.istanbul.vm.gas" "charge_gas". + +Axiom ethereum_istanbul_vm_memory_imports_buffer_read : + IsImported globals "ethereum.istanbul.vm.memory" "buffer_read". + +Definition pop : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Remove item from stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.call (| + M.get_field (| M.get_name (| globals, "stack" |), "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_BASE" |) + ], + make_dict [] + |) in + let _ := M.pass (| |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition push_n : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm"; "num_bytes" ] |) in + let _ := Constant.str " + Pushes a N-byte immediate onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + num_bytes : + The number of immediate bytes to be read from the code and pushed to + the stack. + + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_VERY_LOW" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "data_to_push" , + M.call (| + M.get_field (| M.get_name (| globals, "U256" |), "from_be_bytes" |), + make_list [ + M.call (| + M.get_name (| globals, "buffer_read" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "code" |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + BinOp.add (| + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) + ], + make_dict [] + |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + M.get_name (| globals, "num_bytes" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_field (| M.get_name (| globals, "stack" |), "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.get_name (| globals, "data_to_push" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + BinOp.add (| + Constant.int 1, + M.get_name (| globals, "num_bytes" |) + |) + |) in + M.pure Constant.None_)). + +Definition dup_n : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm"; "item_number" ] |) in + let _ := Constant.str " + Duplicate the Nth stack item (from top of the stack) to the top of stack. + + Parameters + ---------- + evm : + The current EVM frame. + + item_number : + The stack item number (0-indexed from top of stack) to be duplicated + to the top of stack. + + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_VERY_LOW" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + Compare.lt (| + M.get_name (| globals, "item_number" |), + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |); + M.get_name (| globals, "StackUnderflowError" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "data_to_duplicate" , + M.get_subscript (| + M.get_field (| M.get_name (| globals, "evm" |), "stack" |), + BinOp.sub (| + BinOp.sub (| + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |), + Constant.int 1 + |), + M.get_name (| globals, "item_number" |) + |) + |) + |) in + let _ := M.call (| + M.get_field (| M.get_name (| globals, "stack" |), "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.get_name (| globals, "data_to_duplicate" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition swap_n : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm"; "item_number" ] |) in + let _ := Constant.str " + Swap the top and the `item_number` element of the stack, where + the top of the stack is position zero. + + If `item_number` is zero, this function does nothing (which should not be + possible, since there is no `SWAP0` instruction). + + Parameters + ---------- + evm : + The current EVM frame. + + item_number : + The stack item number (0-indexed from top of stack) to be swapped + with the top of stack element. + + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_VERY_LOW" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + Compare.lt (| + M.get_name (| globals, "item_number" |), + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |); + M.get_name (| globals, "StackUnderflowError" |) + ], + make_dict [] + |) in + let _ := M.assign (| + make_tuple [ M.get_subscript (| + M.get_field (| M.get_name (| globals, "evm" |), "stack" |), + UnOp.sub (| Constant.int 1 |) + |); M.get_subscript (| + M.get_field (| M.get_name (| globals, "evm" |), "stack" |), + BinOp.sub (| + UnOp.sub (| Constant.int 1 |), + M.get_name (| globals, "item_number" |) + |) + |) ], + make_tuple [ M.get_subscript (| + M.get_field (| M.get_name (| globals, "evm" |), "stack" |), + BinOp.sub (| + UnOp.sub (| Constant.int 1 |), + M.get_name (| globals, "item_number" |) + |) + |); M.get_subscript (| + M.get_field (| M.get_name (| globals, "evm" |), "stack" |), + UnOp.sub (| Constant.int 1 |) + |) ] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition push1 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push2 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push3 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push4 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push5 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push6 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push7 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push8 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push9 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push10 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push11 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push12 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push13 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push14 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push15 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push16 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push17 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push18 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push19 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push20 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push21 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push22 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push23 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push24 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push25 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push26 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push27 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push28 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push29 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push30 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push31 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push32 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "push_n" |) + ], + make_dict [] + |) +)). + +Definition dup1 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "dup_n" |) + ], + make_dict [] + |) +)). + +Definition dup2 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "dup_n" |) + ], + make_dict [] + |) +)). + +Definition dup3 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "dup_n" |) + ], + make_dict [] + |) +)). + +Definition dup4 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "dup_n" |) + ], + make_dict [] + |) +)). + +Definition dup5 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "dup_n" |) + ], + make_dict [] + |) +)). + +Definition dup6 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "dup_n" |) + ], + make_dict [] + |) +)). + +Definition dup7 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "dup_n" |) + ], + make_dict [] + |) +)). + +Definition dup8 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "dup_n" |) + ], + make_dict [] + |) +)). + +Definition dup9 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "dup_n" |) + ], + make_dict [] + |) +)). + +Definition dup10 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "dup_n" |) + ], + make_dict [] + |) +)). + +Definition dup11 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "dup_n" |) + ], + make_dict [] + |) +)). + +Definition dup12 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "dup_n" |) + ], + make_dict [] + |) +)). + +Definition dup13 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "dup_n" |) + ], + make_dict [] + |) +)). + +Definition dup14 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "dup_n" |) + ], + make_dict [] + |) +)). + +Definition dup15 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "dup_n" |) + ], + make_dict [] + |) +)). + +Definition dup16 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "dup_n" |) + ], + make_dict [] + |) +)). + +Definition swap1 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "swap_n" |) + ], + make_dict [] + |) +)). + +Definition swap2 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "swap_n" |) + ], + make_dict [] + |) +)). + +Definition swap3 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "swap_n" |) + ], + make_dict [] + |) +)). + +Definition swap4 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "swap_n" |) + ], + make_dict [] + |) +)). + +Definition swap5 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "swap_n" |) + ], + make_dict [] + |) +)). + +Definition swap6 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "swap_n" |) + ], + make_dict [] + |) +)). + +Definition swap7 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "swap_n" |) + ], + make_dict [] + |) +)). + +Definition swap8 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "swap_n" |) + ], + make_dict [] + |) +)). + +Definition swap9 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "swap_n" |) + ], + make_dict [] + |) +)). + +Definition swap10 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "swap_n" |) + ], + make_dict [] + |) +)). + +Definition swap11 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "swap_n" |) + ], + make_dict [] + |) +)). + +Definition swap12 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "swap_n" |) + ], + make_dict [] + |) +)). + +Definition swap13 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "swap_n" |) + ], + make_dict [] + |) +)). + +Definition swap14 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "swap_n" |) + ], + make_dict [] + |) +)). + +Definition swap15 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "swap_n" |) + ], + make_dict [] + |) +)). + +Definition swap16 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "swap_n" |) + ], + make_dict [] + |) +)). diff --git a/CoqOfPython/ethereum/istanbul/vm/instructions/storage.v b/CoqOfPython/ethereum/istanbul/vm/instructions/storage.v new file mode 100644 index 0000000..e5e7cdf --- /dev/null +++ b/CoqOfPython/ethereum/istanbul/vm/instructions/storage.v @@ -0,0 +1,412 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.istanbul.vm.instructions.storage". + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) Storage Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM storage related instructions. +". + +Axiom ethereum_utils_ensure_imports_ensure : + IsImported globals "ethereum.utils.ensure" "ensure". + +Axiom ethereum_istanbul_state_imports_get_storage : + IsImported globals "ethereum.istanbul.state" "get_storage". +Axiom ethereum_istanbul_state_imports_get_storage_original : + IsImported globals "ethereum.istanbul.state" "get_storage_original". +Axiom ethereum_istanbul_state_imports_set_storage : + IsImported globals "ethereum.istanbul.state" "set_storage". + +Axiom ethereum_istanbul_vm_imports_Evm : + IsImported globals "ethereum.istanbul.vm" "Evm". + +Axiom ethereum_istanbul_vm_exceptions_imports_OutOfGasError : + IsImported globals "ethereum.istanbul.vm.exceptions" "OutOfGasError". +Axiom ethereum_istanbul_vm_exceptions_imports_WriteInStaticContext : + IsImported globals "ethereum.istanbul.vm.exceptions" "WriteInStaticContext". + +Axiom ethereum_istanbul_vm_gas_imports_GAS_CALL_STIPEND : + IsImported globals "ethereum.istanbul.vm.gas" "GAS_CALL_STIPEND". +Axiom ethereum_istanbul_vm_gas_imports_GAS_SLOAD : + IsImported globals "ethereum.istanbul.vm.gas" "GAS_SLOAD". +Axiom ethereum_istanbul_vm_gas_imports_GAS_STORAGE_CLEAR_REFUND : + IsImported globals "ethereum.istanbul.vm.gas" "GAS_STORAGE_CLEAR_REFUND". +Axiom ethereum_istanbul_vm_gas_imports_GAS_STORAGE_SET : + IsImported globals "ethereum.istanbul.vm.gas" "GAS_STORAGE_SET". +Axiom ethereum_istanbul_vm_gas_imports_GAS_STORAGE_UPDATE : + IsImported globals "ethereum.istanbul.vm.gas" "GAS_STORAGE_UPDATE". +Axiom ethereum_istanbul_vm_gas_imports_charge_gas : + IsImported globals "ethereum.istanbul.vm.gas" "charge_gas". + +Axiom ethereum_istanbul_vm_stack_imports_pop : + IsImported globals "ethereum.istanbul.vm.stack" "pop". +Axiom ethereum_istanbul_vm_stack_imports_push : + IsImported globals "ethereum.istanbul.vm.stack" "push". + +Definition sload : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Loads to the stack, the value corresponding to a certain key from the + storage of the current account. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "key" , + M.call (| + M.get_field (| M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |), "to_be_bytes32" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_SLOAD" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "value" , + M.call (| + M.get_name (| globals, "get_storage" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "env" |), "state" |); + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "current_target" |); + M.get_name (| globals, "key" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.get_name (| globals, "value" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition sstore : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Stores a value at a certain key in the current context's storage. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "key" , + M.call (| + M.get_field (| M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |), "to_be_bytes32" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "new_value" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + Compare.gt (| + M.get_field (| M.get_name (| globals, "evm" |), "gas_left" |), + M.get_name (| globals, "GAS_CALL_STIPEND" |) + |); + M.get_name (| globals, "OutOfGasError" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "original_value" , + M.call (| + M.get_name (| globals, "get_storage_original" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "env" |), "state" |); + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "current_target" |); + M.get_name (| globals, "key" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "current_value" , + M.call (| + M.get_name (| globals, "get_storage" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "env" |), "state" |); + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "current_target" |); + M.get_name (| globals, "key" |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + BoolOp.and (| + Compare.eq (| + M.get_name (| globals, "original_value" |), + M.get_name (| globals, "current_value" |) + |), + ltac:(M.monadic ( + Compare.not_eq (| + M.get_name (| globals, "current_value" |), + M.get_name (| globals, "new_value" |) + |) + )) + |), + (* then *) + ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, "original_value" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "gas_cost" , + M.get_name (| globals, "GAS_STORAGE_SET" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "gas_cost" , + M.get_name (| globals, "GAS_STORAGE_UPDATE" |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "gas_cost" , + M.get_name (| globals, "GAS_SLOAD" |) + |) in + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + Compare.not_eq (| + M.get_name (| globals, "current_value" |), + M.get_name (| globals, "new_value" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + BoolOp.and (| + Compare.not_eq (| + M.get_name (| globals, "original_value" |), + Constant.int 0 + |), + ltac:(M.monadic ( + BoolOp.and (| + Compare.not_eq (| + M.get_name (| globals, "current_value" |), + Constant.int 0 + |), + ltac:(M.monadic ( + Compare.eq (| + M.get_name (| globals, "new_value" |), + Constant.int 0 + |) + )) + |) + )) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "refund_counter" |), + M.call (| + M.get_name (| globals, "int" |), + make_list [ + M.get_name (| globals, "GAS_STORAGE_CLEAR_REFUND" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + BoolOp.and (| + Compare.not_eq (| + M.get_name (| globals, "original_value" |), + Constant.int 0 + |), + ltac:(M.monadic ( + Compare.eq (| + M.get_name (| globals, "current_value" |), + Constant.int 0 + |) + )) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_op (| + BinOp.sub, + M.get_field (| M.get_name (| globals, "evm" |), "refund_counter" |), + M.call (| + M.get_name (| globals, "int" |), + make_list [ + M.get_name (| globals, "GAS_STORAGE_CLEAR_REFUND" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, "original_value" |), + M.get_name (| globals, "new_value" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, "original_value" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "refund_counter" |), + M.call (| + M.get_name (| globals, "int" |), + make_list [ + BinOp.sub (| + M.get_name (| globals, "GAS_STORAGE_SET" |), + M.get_name (| globals, "GAS_SLOAD" |) + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "refund_counter" |), + M.call (| + M.get_name (| globals, "int" |), + make_list [ + BinOp.sub (| + M.get_name (| globals, "GAS_STORAGE_UPDATE" |), + M.get_name (| globals, "GAS_SLOAD" |) + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "gas_cost" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + UnOp.not (| M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "is_static" |) |); + M.get_name (| globals, "WriteInStaticContext" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "set_storage" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "env" |), "state" |); + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "current_target" |); + M.get_name (| globals, "key" |); + M.get_name (| globals, "new_value" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). diff --git a/CoqOfPython/ethereum/istanbul/vm/instructions/system.v b/CoqOfPython/ethereum/istanbul/vm/instructions/system.v new file mode 100644 index 0000000..04f4e5a --- /dev/null +++ b/CoqOfPython/ethereum/istanbul/vm/instructions/system.v @@ -0,0 +1,2117 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.istanbul.vm.instructions.system". + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) System Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM system related instructions. +". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_Bytes0 : + IsImported globals "ethereum.base_types" "Bytes0". +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". + +Axiom ethereum_utils_ensure_imports_ensure : + IsImported globals "ethereum.utils.ensure" "ensure". + +Axiom ethereum_utils_numeric_imports_ceil32 : + IsImported globals "ethereum.utils.numeric" "ceil32". + +Axiom ethereum_istanbul_fork_types_imports_Address : + IsImported globals "ethereum.istanbul.fork_types" "Address". + +Axiom ethereum_istanbul_state_imports_account_exists_and_is_empty : + IsImported globals "ethereum.istanbul.state" "account_exists_and_is_empty". +Axiom ethereum_istanbul_state_imports_account_has_code_or_nonce : + IsImported globals "ethereum.istanbul.state" "account_has_code_or_nonce". +Axiom ethereum_istanbul_state_imports_get_account : + IsImported globals "ethereum.istanbul.state" "get_account". +Axiom ethereum_istanbul_state_imports_increment_nonce : + IsImported globals "ethereum.istanbul.state" "increment_nonce". +Axiom ethereum_istanbul_state_imports_is_account_alive : + IsImported globals "ethereum.istanbul.state" "is_account_alive". +Axiom ethereum_istanbul_state_imports_set_account_balance : + IsImported globals "ethereum.istanbul.state" "set_account_balance". + +Axiom ethereum_istanbul_utils_address_imports_compute_contract_address : + IsImported globals "ethereum.istanbul.utils.address" "compute_contract_address". +Axiom ethereum_istanbul_utils_address_imports_compute_create2_contract_address : + IsImported globals "ethereum.istanbul.utils.address" "compute_create2_contract_address". +Axiom ethereum_istanbul_utils_address_imports_to_address : + IsImported globals "ethereum.istanbul.utils.address" "to_address". + +Axiom ethereum_istanbul_vm_imports_Evm : + IsImported globals "ethereum.istanbul.vm" "Evm". +Axiom ethereum_istanbul_vm_imports_Message : + IsImported globals "ethereum.istanbul.vm" "Message". +Axiom ethereum_istanbul_vm_imports_incorporate_child_on_error : + IsImported globals "ethereum.istanbul.vm" "incorporate_child_on_error". +Axiom ethereum_istanbul_vm_imports_incorporate_child_on_success : + IsImported globals "ethereum.istanbul.vm" "incorporate_child_on_success". + +Axiom ethereum_istanbul_vm_exceptions_imports_Revert : + IsImported globals "ethereum.istanbul.vm.exceptions" "Revert". +Axiom ethereum_istanbul_vm_exceptions_imports_WriteInStaticContext : + IsImported globals "ethereum.istanbul.vm.exceptions" "WriteInStaticContext". + +Axiom ethereum_istanbul_vm_gas_imports_GAS_CALL : + IsImported globals "ethereum.istanbul.vm.gas" "GAS_CALL". +Axiom ethereum_istanbul_vm_gas_imports_GAS_CALL_VALUE : + IsImported globals "ethereum.istanbul.vm.gas" "GAS_CALL_VALUE". +Axiom ethereum_istanbul_vm_gas_imports_GAS_CREATE : + IsImported globals "ethereum.istanbul.vm.gas" "GAS_CREATE". +Axiom ethereum_istanbul_vm_gas_imports_GAS_KECCAK256_WORD : + IsImported globals "ethereum.istanbul.vm.gas" "GAS_KECCAK256_WORD". +Axiom ethereum_istanbul_vm_gas_imports_GAS_NEW_ACCOUNT : + IsImported globals "ethereum.istanbul.vm.gas" "GAS_NEW_ACCOUNT". +Axiom ethereum_istanbul_vm_gas_imports_GAS_SELF_DESTRUCT : + IsImported globals "ethereum.istanbul.vm.gas" "GAS_SELF_DESTRUCT". +Axiom ethereum_istanbul_vm_gas_imports_GAS_SELF_DESTRUCT_NEW_ACCOUNT : + IsImported globals "ethereum.istanbul.vm.gas" "GAS_SELF_DESTRUCT_NEW_ACCOUNT". +Axiom ethereum_istanbul_vm_gas_imports_GAS_ZERO : + IsImported globals "ethereum.istanbul.vm.gas" "GAS_ZERO". +Axiom ethereum_istanbul_vm_gas_imports_REFUND_SELF_DESTRUCT : + IsImported globals "ethereum.istanbul.vm.gas" "REFUND_SELF_DESTRUCT". +Axiom ethereum_istanbul_vm_gas_imports_calculate_gas_extend_memory : + IsImported globals "ethereum.istanbul.vm.gas" "calculate_gas_extend_memory". +Axiom ethereum_istanbul_vm_gas_imports_calculate_message_call_gas : + IsImported globals "ethereum.istanbul.vm.gas" "calculate_message_call_gas". +Axiom ethereum_istanbul_vm_gas_imports_charge_gas : + IsImported globals "ethereum.istanbul.vm.gas" "charge_gas". +Axiom ethereum_istanbul_vm_gas_imports_max_message_call_gas : + IsImported globals "ethereum.istanbul.vm.gas" "max_message_call_gas". + +Axiom ethereum_istanbul_vm_memory_imports_memory_read_bytes : + IsImported globals "ethereum.istanbul.vm.memory" "memory_read_bytes". +Axiom ethereum_istanbul_vm_memory_imports_memory_write : + IsImported globals "ethereum.istanbul.vm.memory" "memory_write". + +Axiom ethereum_istanbul_vm_stack_imports_pop : + IsImported globals "ethereum.istanbul.vm.stack" "pop". +Axiom ethereum_istanbul_vm_stack_imports_push : + IsImported globals "ethereum.istanbul.vm.stack" "push". + +Definition generic_create : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm"; "endowment"; "contract_address"; "memory_start_position"; "memory_size" ] |) in + let _ := Constant.str " + Core logic used by the `CREATE*` family of opcodes. + " in +(* At stmt: unsupported node type: ImportFrom *) + let _ := M.assign_local (| + "create_message_gas" , + M.call (| + M.get_name (| globals, "max_message_call_gas" |), + make_list [ + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "gas_left" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_op (| + BinOp.sub, + M.get_field (| M.get_name (| globals, "evm" |), "gas_left" |), + M.get_name (| globals, "create_message_gas" |) + |) in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + UnOp.not (| M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "is_static" |) |); + M.get_name (| globals, "WriteInStaticContext" |) + ], + make_dict [] + |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, "evm" |), "return_data" |), + Constant.bytes "" + |) in + let _ := M.assign_local (| + "sender_address" , + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "current_target" |) + |) in + let _ := M.assign_local (| + "sender" , + M.call (| + M.get_name (| globals, "get_account" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "env" |), "state" |); + M.get_name (| globals, "sender_address" |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + BoolOp.or (| + Compare.lt (| + M.get_field (| M.get_name (| globals, "sender" |), "balance" |), + M.get_name (| globals, "endowment" |) + |), + ltac:(M.monadic ( + BoolOp.or (| + Compare.eq (| + M.get_field (| M.get_name (| globals, "sender" |), "nonce" |), + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + BinOp.sub (| + BinOp.pow (| + Constant.int 2, + Constant.int 64 + |), + Constant.int 1 + |) + ], + make_dict [] + |) + |), + ltac:(M.monadic ( + Compare.gt (| + BinOp.add (| + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "depth" |), + Constant.int 1 + |), + M.get_name (| globals, "STACK_DEPTH_LIMIT" |) + |) + )) + |) + )) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "gas_left" |), + M.get_name (| globals, "create_message_gas" |) + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.return_ (| + Constant.None_ + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, "account_has_code_or_nonce" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "env" |), "state" |); + M.get_name (| globals, "contract_address" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, "increment_nonce" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "env" |), "state" |); + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "current_target" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.return_ (| + Constant.None_ + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "call_data" , + M.call (| + M.get_name (| globals, "memory_read_bytes" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "memory" |); + M.get_name (| globals, "memory_start_position" |); + M.get_name (| globals, "memory_size" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "increment_nonce" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "env" |), "state" |); + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "current_target" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "child_message" , + M.call (| + M.get_name (| globals, "Message" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "child_evm" , + M.call (| + M.get_name (| globals, "process_create_message" |), + make_list [ + M.get_name (| globals, "child_message" |); + M.get_field (| M.get_name (| globals, "evm" |), "env" |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + M.get_field (| M.get_name (| globals, "child_evm" |), "error" |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, "incorporate_child_on_error" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "child_evm" |) + ], + make_dict [] + |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, "evm" |), "return_data" |), + M.get_field (| M.get_name (| globals, "child_evm" |), "output" |) + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + ], + make_dict [] + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, "incorporate_child_on_success" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "child_evm" |) + ], + make_dict [] + |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, "evm" |), "return_data" |), + Constant.bytes "" + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.call (| + M.get_field (| M.get_name (| globals, "U256" |), "from_be_bytes" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "child_evm" |), "message" |), "current_target" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_)). + +Definition create : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Creates a new account with associated code. + + Parameters + ---------- + evm : + The current EVM frame. + " in + let _ := M.assign_local (| + "endowment" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_start_position" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_size" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "extend_memory" , + M.call (| + M.get_name (| globals, "calculate_gas_extend_memory" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "memory" |); + make_list [ + make_tuple [ M.get_name (| globals, "memory_start_position" |); M.get_name (| globals, "memory_size" |) ] + ] + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + BinOp.add (| + M.get_name (| globals, "GAS_CREATE" |), + M.get_field (| M.get_name (| globals, "extend_memory" |), "cost" |) + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "memory" |), + BinOp.mult (| + Constant.bytes "00", + M.get_field (| M.get_name (| globals, "extend_memory" |), "expand_by" |) + |) + |) in + let _ := M.assign_local (| + "contract_address" , + M.call (| + M.get_name (| globals, "compute_contract_address" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "current_target" |); + M.get_field (| M.call (| + M.get_name (| globals, "get_account" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "env" |), "state" |); + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "current_target" |) + ], + make_dict [] + |), "nonce" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "generic_create" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "endowment" |); + M.get_name (| globals, "contract_address" |); + M.get_name (| globals, "memory_start_position" |); + M.get_name (| globals, "memory_size" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition create2 : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Creates a new account with associated code. + + It's similar to CREATE opcode except that the address of new account + depends on the init_code instead of the nonce of sender. + + Parameters + ---------- + evm : + The current EVM frame. + " in + let _ := M.assign_local (| + "endowment" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_start_position" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_size" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "salt" , + M.call (| + M.get_field (| M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |), "to_be_bytes32" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "extend_memory" , + M.call (| + M.get_name (| globals, "calculate_gas_extend_memory" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "memory" |); + make_list [ + make_tuple [ M.get_name (| globals, "memory_start_position" |); M.get_name (| globals, "memory_size" |) ] + ] + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "call_data_words" , + BinOp.floor_div (| + M.call (| + M.get_name (| globals, "ceil32" |), + make_list [ + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.get_name (| globals, "memory_size" |) + ], + make_dict [] + |) + ], + make_dict [] + |), + Constant.int 32 + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + BinOp.add (| + BinOp.add (| + M.get_name (| globals, "GAS_CREATE" |), + BinOp.mult (| + M.get_name (| globals, "GAS_KECCAK256_WORD" |), + M.get_name (| globals, "call_data_words" |) + |) + |), + M.get_field (| M.get_name (| globals, "extend_memory" |), "cost" |) + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "memory" |), + BinOp.mult (| + Constant.bytes "00", + M.get_field (| M.get_name (| globals, "extend_memory" |), "expand_by" |) + |) + |) in + let _ := M.assign_local (| + "contract_address" , + M.call (| + M.get_name (| globals, "compute_create2_contract_address" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "current_target" |); + M.get_name (| globals, "salt" |); + M.call (| + M.get_name (| globals, "memory_read_bytes" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "memory" |); + M.get_name (| globals, "memory_start_position" |); + M.get_name (| globals, "memory_size" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "generic_create" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "endowment" |); + M.get_name (| globals, "contract_address" |); + M.get_name (| globals, "memory_start_position" |); + M.get_name (| globals, "memory_size" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition return_ : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Halts execution returning output data. + + Parameters + ---------- + evm : + The current EVM frame. + " in + let _ := M.assign_local (| + "memory_start_position" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_size" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "extend_memory" , + M.call (| + M.get_name (| globals, "calculate_gas_extend_memory" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "memory" |); + make_list [ + make_tuple [ M.get_name (| globals, "memory_start_position" |); M.get_name (| globals, "memory_size" |) ] + ] + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + BinOp.add (| + M.get_name (| globals, "GAS_ZERO" |), + M.get_field (| M.get_name (| globals, "extend_memory" |), "cost" |) + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "memory" |), + BinOp.mult (| + Constant.bytes "00", + M.get_field (| M.get_name (| globals, "extend_memory" |), "expand_by" |) + |) + |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, "evm" |), "output" |), + M.call (| + M.get_name (| globals, "memory_read_bytes" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "memory" |); + M.get_name (| globals, "memory_start_position" |); + M.get_name (| globals, "memory_size" |) + ], + make_dict [] + |) + |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, "evm" |), "running" |), + Constant.bool false + |) in + let _ := M.pass (| |) in + M.pure Constant.None_)). + +Definition generic_call : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm"; "gas"; "value"; "caller"; "to"; "code_address"; "should_transfer_value"; "is_staticcall"; "memory_input_start_position"; "memory_input_size"; "memory_output_start_position"; "memory_output_size" ] |) in + let _ := Constant.str " + Perform the core logic of the `CALL*` family of opcodes. + " in +(* At stmt: unsupported node type: ImportFrom *) + let _ := M.assign (| + M.get_field (| M.get_name (| globals, "evm" |), "return_data" |), + Constant.bytes "" + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.gt (| + BinOp.add (| + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "depth" |), + Constant.int 1 + |), + M.get_name (| globals, "STACK_DEPTH_LIMIT" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "gas_left" |), + M.get_name (| globals, "gas" |) + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.return_ (| + Constant.None_ + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "call_data" , + M.call (| + M.get_name (| globals, "memory_read_bytes" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "memory" |); + M.get_name (| globals, "memory_input_start_position" |); + M.get_name (| globals, "memory_input_size" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "code" , + M.get_field (| M.call (| + M.get_name (| globals, "get_account" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "env" |), "state" |); + M.get_name (| globals, "code_address" |) + ], + make_dict [] + |), "code" |) + |) in + let _ := M.assign_local (| + "child_message" , + M.call (| + M.get_name (| globals, "Message" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "child_evm" , + M.call (| + M.get_name (| globals, "process_message" |), + make_list [ + M.get_name (| globals, "child_message" |); + M.get_field (| M.get_name (| globals, "evm" |), "env" |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + M.get_field (| M.get_name (| globals, "child_evm" |), "error" |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, "incorporate_child_on_error" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "child_evm" |) + ], + make_dict [] + |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, "evm" |), "return_data" |), + M.get_field (| M.get_name (| globals, "child_evm" |), "output" |) + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + ], + make_dict [] + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, "incorporate_child_on_success" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "child_evm" |) + ], + make_dict [] + |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, "evm" |), "return_data" |), + M.get_field (| M.get_name (| globals, "child_evm" |), "output" |) + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 1 + ], + make_dict [] + |) + ], + make_dict [] + |) in + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "actual_output_size" , + M.call (| + M.get_name (| globals, "min" |), + make_list [ + M.get_name (| globals, "memory_output_size" |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_field (| M.get_name (| globals, "child_evm" |), "output" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "memory_write" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "memory" |); + M.get_name (| globals, "memory_output_start_position" |); + M.slice (| + M.get_field (| M.get_name (| globals, "child_evm" |), "output" |), + Constant.None_, + M.get_name (| globals, "actual_output_size" |), + Constant.None_ + |) + ], + make_dict [] + |) in + M.pure Constant.None_)). + +Definition call : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Message-call into an account. + + Parameters + ---------- + evm : + The current EVM frame. + " in + let _ := M.assign_local (| + "gas" , + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "to" , + M.call (| + M.get_name (| globals, "to_address" |), + make_list [ + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "value" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_input_start_position" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_input_size" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_output_start_position" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_output_size" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "extend_memory" , + M.call (| + M.get_name (| globals, "calculate_gas_extend_memory" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "memory" |); + make_list [ + make_tuple [ M.get_name (| globals, "memory_input_start_position" |); M.get_name (| globals, "memory_input_size" |) ]; + make_tuple [ M.get_name (| globals, "memory_output_start_position" |); M.get_name (| globals, "memory_output_size" |) ] + ] + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "create_gas_cost" , + (* if *) + M.if_then_else (| + BoolOp.or (| + Compare.eq (| + M.get_name (| globals, "value" |), + Constant.int 0 + |), + ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "is_account_alive" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "env" |), "state" |); + M.get_name (| globals, "to" |) + ], + make_dict [] + |) + )) + |), + (* then *) + ltac:(M.monadic ( +M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + (* else *) + )), ltac:(M.monadic ( +M.get_name (| globals, "GAS_NEW_ACCOUNT" |) + )) |) + |) in + let _ := M.assign_local (| + "transfer_gas_cost" , + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, "value" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( +M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + (* else *) + )), ltac:(M.monadic ( +M.get_name (| globals, "GAS_CALL_VALUE" |) + )) |) + |) in + let _ := M.assign_local (| + "message_call_gas" , + M.call (| + M.get_name (| globals, "calculate_message_call_gas" |), + make_list [ + M.get_name (| globals, "value" |); + M.get_name (| globals, "gas" |); + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "gas_left" |) + ], + make_dict [] + |); + M.get_field (| M.get_name (| globals, "extend_memory" |), "cost" |); + BinOp.add (| + BinOp.add (| + M.get_name (| globals, "GAS_CALL" |), + M.get_name (| globals, "create_gas_cost" |) + |), + M.get_name (| globals, "transfer_gas_cost" |) + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + BinOp.add (| + M.get_field (| M.get_name (| globals, "message_call_gas" |), "cost" |), + M.get_field (| M.get_name (| globals, "extend_memory" |), "cost" |) + |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + BoolOp.or (| + UnOp.not (| M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "is_static" |) |), + ltac:(M.monadic ( + Compare.eq (| + M.get_name (| globals, "value" |), + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + |) + )) + |); + M.get_name (| globals, "WriteInStaticContext" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "memory" |), + BinOp.mult (| + Constant.bytes "00", + M.get_field (| M.get_name (| globals, "extend_memory" |), "expand_by" |) + |) + |) in + let _ := M.assign_local (| + "sender_balance" , + M.get_field (| M.call (| + M.get_name (| globals, "get_account" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "env" |), "state" |); + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "current_target" |) + ], + make_dict [] + |), "balance" |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.lt (| + M.get_name (| globals, "sender_balance" |), + M.get_name (| globals, "value" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, "evm" |), "return_data" |), + Constant.bytes "" + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "gas_left" |), + M.get_field (| M.get_name (| globals, "message_call_gas" |), "stipend" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, "generic_call" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_field (| M.get_name (| globals, "message_call_gas" |), "stipend" |); + M.get_name (| globals, "value" |); + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "current_target" |); + M.get_name (| globals, "to" |); + M.get_name (| globals, "to" |); + Constant.bool true; + Constant.bool false; + M.get_name (| globals, "memory_input_start_position" |); + M.get_name (| globals, "memory_input_size" |); + M.get_name (| globals, "memory_output_start_position" |); + M.get_name (| globals, "memory_output_size" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + )) |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition callcode : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Message-call into this account with alternative account’s code. + + Parameters + ---------- + evm : + The current EVM frame. + " in + let _ := M.assign_local (| + "gas" , + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "code_address" , + M.call (| + M.get_name (| globals, "to_address" |), + make_list [ + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "value" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_input_start_position" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_input_size" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_output_start_position" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_output_size" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "to" , + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "current_target" |) + |) in + let _ := M.assign_local (| + "extend_memory" , + M.call (| + M.get_name (| globals, "calculate_gas_extend_memory" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "memory" |); + make_list [ + make_tuple [ M.get_name (| globals, "memory_input_start_position" |); M.get_name (| globals, "memory_input_size" |) ]; + make_tuple [ M.get_name (| globals, "memory_output_start_position" |); M.get_name (| globals, "memory_output_size" |) ] + ] + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "transfer_gas_cost" , + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, "value" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( +M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + (* else *) + )), ltac:(M.monadic ( +M.get_name (| globals, "GAS_CALL_VALUE" |) + )) |) + |) in + let _ := M.assign_local (| + "message_call_gas" , + M.call (| + M.get_name (| globals, "calculate_message_call_gas" |), + make_list [ + M.get_name (| globals, "value" |); + M.get_name (| globals, "gas" |); + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "gas_left" |) + ], + make_dict [] + |); + M.get_field (| M.get_name (| globals, "extend_memory" |), "cost" |); + BinOp.add (| + M.get_name (| globals, "GAS_CALL" |), + M.get_name (| globals, "transfer_gas_cost" |) + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + BinOp.add (| + M.get_field (| M.get_name (| globals, "message_call_gas" |), "cost" |), + M.get_field (| M.get_name (| globals, "extend_memory" |), "cost" |) + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "memory" |), + BinOp.mult (| + Constant.bytes "00", + M.get_field (| M.get_name (| globals, "extend_memory" |), "expand_by" |) + |) + |) in + let _ := M.assign_local (| + "sender_balance" , + M.get_field (| M.call (| + M.get_name (| globals, "get_account" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "env" |), "state" |); + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "current_target" |) + ], + make_dict [] + |), "balance" |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.lt (| + M.get_name (| globals, "sender_balance" |), + M.get_name (| globals, "value" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, "evm" |), "return_data" |), + Constant.bytes "" + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "gas_left" |), + M.get_field (| M.get_name (| globals, "message_call_gas" |), "stipend" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, "generic_call" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_field (| M.get_name (| globals, "message_call_gas" |), "stipend" |); + M.get_name (| globals, "value" |); + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "current_target" |); + M.get_name (| globals, "to" |); + M.get_name (| globals, "code_address" |); + Constant.bool true; + Constant.bool false; + M.get_name (| globals, "memory_input_start_position" |); + M.get_name (| globals, "memory_input_size" |); + M.get_name (| globals, "memory_output_start_position" |); + M.get_name (| globals, "memory_output_size" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + )) |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition selfdestruct : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Halt execution and register account for later deletion. + + Parameters + ---------- + evm : + The current EVM frame. + " in + let _ := M.assign_local (| + "beneficiary" , + M.call (| + M.get_name (| globals, "to_address" |), + make_list [ + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "gas_cost" , + M.get_name (| globals, "GAS_SELF_DESTRUCT" |) + |) in + let _ := + (* if *) + M.if_then_else (| + BoolOp.and (| + UnOp.not (| M.call (| + M.get_name (| globals, "is_account_alive" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "env" |), "state" |); + M.get_name (| globals, "beneficiary" |) + ], + make_dict [] + |) |), + ltac:(M.monadic ( + Compare.not_eq (| + M.get_field (| M.call (| + M.get_name (| globals, "get_account" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "env" |), "state" |); + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "current_target" |) + ], + make_dict [] + |), "balance" |), + Constant.int 0 + |) + )) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_op_local (| + BinOp.add, + "gas_cost", + M.get_name (| globals, "GAS_SELF_DESTRUCT_NEW_ACCOUNT" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "originator" , + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "current_target" |) + |) in + let _ := M.assign_local (| + "refunded_accounts" , + M.get_field (| M.get_name (| globals, "evm" |), "accounts_to_delete" |) + |) in + let _ := M.assign_local (| + "parent_evm" , + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "parent_evm" |) + |) in + let _ := + M.while (| + Compare.is_not (| + M.get_name (| globals, "parent_evm" |), + Constant.None_ + |), + ltac:(M.monadic ( + let _ := M.call (| + M.get_field (| M.get_name (| globals, "refunded_accounts" |), "update" |), + make_list [ + M.get_field (| M.get_name (| globals, "parent_evm" |), "accounts_to_delete" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "parent_evm" , + M.get_field (| M.get_field (| M.get_name (| globals, "parent_evm" |), "message" |), "parent_evm" |) + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.not_in (| + M.get_name (| globals, "originator" |), + M.get_name (| globals, "refunded_accounts" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "refund_counter" |), + M.get_name (| globals, "REFUND_SELF_DESTRUCT" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "gas_cost" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + UnOp.not (| M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "is_static" |) |); + M.get_name (| globals, "WriteInStaticContext" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "beneficiary_balance" , + M.get_field (| M.call (| + M.get_name (| globals, "get_account" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "env" |), "state" |); + M.get_name (| globals, "beneficiary" |) + ], + make_dict [] + |), "balance" |) + |) in + let _ := M.assign_local (| + "originator_balance" , + M.get_field (| M.call (| + M.get_name (| globals, "get_account" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "env" |), "state" |); + M.get_name (| globals, "originator" |) + ], + make_dict [] + |), "balance" |) + |) in + let _ := M.call (| + M.get_name (| globals, "set_account_balance" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "env" |), "state" |); + M.get_name (| globals, "beneficiary" |); + BinOp.add (| + M.get_name (| globals, "beneficiary_balance" |), + M.get_name (| globals, "originator_balance" |) + |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "set_account_balance" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "env" |), "state" |); + M.get_name (| globals, "originator" |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "accounts_to_delete" |), "add" |), + make_list [ + M.get_name (| globals, "originator" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, "account_exists_and_is_empty" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "env" |), "state" |); + M.get_name (| globals, "beneficiary" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "touched_accounts" |), "add" |), + make_list [ + M.get_name (| globals, "beneficiary" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, "evm" |), "running" |), + Constant.bool false + |) in + let _ := M.pass (| |) in + M.pure Constant.None_)). + +Definition delegatecall : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Message-call into an account. + + Parameters + ---------- + evm : + The current EVM frame. + " in + let _ := M.assign_local (| + "gas" , + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "code_address" , + M.call (| + M.get_name (| globals, "to_address" |), + make_list [ + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_input_start_position" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_input_size" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_output_start_position" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_output_size" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "extend_memory" , + M.call (| + M.get_name (| globals, "calculate_gas_extend_memory" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "memory" |); + make_list [ + make_tuple [ M.get_name (| globals, "memory_input_start_position" |); M.get_name (| globals, "memory_input_size" |) ]; + make_tuple [ M.get_name (| globals, "memory_output_start_position" |); M.get_name (| globals, "memory_output_size" |) ] + ] + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "message_call_gas" , + M.call (| + M.get_name (| globals, "calculate_message_call_gas" |), + make_list [ + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |); + M.get_name (| globals, "gas" |); + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "gas_left" |) + ], + make_dict [] + |); + M.get_field (| M.get_name (| globals, "extend_memory" |), "cost" |); + M.get_name (| globals, "GAS_CALL" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + BinOp.add (| + M.get_field (| M.get_name (| globals, "message_call_gas" |), "cost" |), + M.get_field (| M.get_name (| globals, "extend_memory" |), "cost" |) + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "memory" |), + BinOp.mult (| + Constant.bytes "00", + M.get_field (| M.get_name (| globals, "extend_memory" |), "expand_by" |) + |) + |) in + let _ := M.call (| + M.get_name (| globals, "generic_call" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_field (| M.get_name (| globals, "message_call_gas" |), "stipend" |); + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "value" |); + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "caller" |); + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "current_target" |); + M.get_name (| globals, "code_address" |); + Constant.bool false; + Constant.bool false; + M.get_name (| globals, "memory_input_start_position" |); + M.get_name (| globals, "memory_input_size" |); + M.get_name (| globals, "memory_output_start_position" |); + M.get_name (| globals, "memory_output_size" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition staticcall : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Message-call into an account. + + Parameters + ---------- + evm : + The current EVM frame. + " in + let _ := M.assign_local (| + "gas" , + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "to" , + M.call (| + M.get_name (| globals, "to_address" |), + make_list [ + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_input_start_position" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_input_size" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_output_start_position" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_output_size" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "extend_memory" , + M.call (| + M.get_name (| globals, "calculate_gas_extend_memory" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "memory" |); + make_list [ + make_tuple [ M.get_name (| globals, "memory_input_start_position" |); M.get_name (| globals, "memory_input_size" |) ]; + make_tuple [ M.get_name (| globals, "memory_output_start_position" |); M.get_name (| globals, "memory_output_size" |) ] + ] + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "message_call_gas" , + M.call (| + M.get_name (| globals, "calculate_message_call_gas" |), + make_list [ + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |); + M.get_name (| globals, "gas" |); + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "gas_left" |) + ], + make_dict [] + |); + M.get_field (| M.get_name (| globals, "extend_memory" |), "cost" |); + M.get_name (| globals, "GAS_CALL" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + BinOp.add (| + M.get_field (| M.get_name (| globals, "message_call_gas" |), "cost" |), + M.get_field (| M.get_name (| globals, "extend_memory" |), "cost" |) + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "memory" |), + BinOp.mult (| + Constant.bytes "00", + M.get_field (| M.get_name (| globals, "extend_memory" |), "expand_by" |) + |) + |) in + let _ := M.call (| + M.get_name (| globals, "generic_call" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_field (| M.get_name (| globals, "message_call_gas" |), "stipend" |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |); + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "current_target" |); + M.get_name (| globals, "to" |); + M.get_name (| globals, "to" |); + Constant.bool true; + Constant.bool true; + M.get_name (| globals, "memory_input_start_position" |); + M.get_name (| globals, "memory_input_size" |); + M.get_name (| globals, "memory_output_start_position" |); + M.get_name (| globals, "memory_output_size" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition revert : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Stop execution and revert state changes, without consuming all provided gas + and also has the ability to return a reason + Parameters + ---------- + evm : + The current EVM frame. + " in + let _ := M.assign_local (| + "memory_start_index" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "size" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "extend_memory" , + M.call (| + M.get_name (| globals, "calculate_gas_extend_memory" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "memory" |); + make_list [ + make_tuple [ M.get_name (| globals, "memory_start_index" |); M.get_name (| globals, "size" |) ] + ] + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_field (| M.get_name (| globals, "extend_memory" |), "cost" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "memory" |), + BinOp.mult (| + Constant.bytes "00", + M.get_field (| M.get_name (| globals, "extend_memory" |), "expand_by" |) + |) + |) in + let _ := M.assign_local (| + "output" , + M.call (| + M.get_name (| globals, "memory_read_bytes" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "memory" |); + M.get_name (| globals, "memory_start_index" |); + M.get_name (| globals, "size" |) + ], + make_dict [] + |) + |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, "evm" |), "output" |), + M.call (| + M.get_name (| globals, "bytes" |), + make_list [ + M.get_name (| globals, "output" |) + ], + make_dict [] + |) + |) in + let _ := M.raise (| Some (M.get_name (| globals, "Revert" |)) |) in + let _ := M.pass (| |) in + M.pure Constant.None_)). diff --git a/CoqOfPython/ethereum/istanbul/vm/interpreter.v b/CoqOfPython/ethereum/istanbul/vm/interpreter.v new file mode 100644 index 0000000..dc57fbf --- /dev/null +++ b/CoqOfPython/ethereum/istanbul/vm/interpreter.v @@ -0,0 +1,673 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.istanbul.vm.interpreter". + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) Interpreter +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +A straightforward interpreter that executes EVM code. +". + +Axiom dataclasses_imports_dataclass : + IsImported globals "dataclasses" "dataclass". + +Axiom typing_imports_Iterable : + IsImported globals "typing" "Iterable". +Axiom typing_imports_Optional : + IsImported globals "typing" "Optional". +Axiom typing_imports_Set : + IsImported globals "typing" "Set". +Axiom typing_imports_Tuple : + IsImported globals "typing" "Tuple". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_Bytes0 : + IsImported globals "ethereum.base_types" "Bytes0". +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". + +Axiom ethereum_trace_imports_EvmStop : + IsImported globals "ethereum.trace" "EvmStop". +Axiom ethereum_trace_imports_OpEnd : + IsImported globals "ethereum.trace" "OpEnd". +Axiom ethereum_trace_imports_OpException : + IsImported globals "ethereum.trace" "OpException". +Axiom ethereum_trace_imports_OpStart : + IsImported globals "ethereum.trace" "OpStart". +Axiom ethereum_trace_imports_PrecompileEnd : + IsImported globals "ethereum.trace" "PrecompileEnd". +Axiom ethereum_trace_imports_PrecompileStart : + IsImported globals "ethereum.trace" "PrecompileStart". +Axiom ethereum_trace_imports_TransactionEnd : + IsImported globals "ethereum.trace" "TransactionEnd". +Axiom ethereum_trace_imports_evm_trace : + IsImported globals "ethereum.trace" "evm_trace". + +Axiom ethereum_utils_ensure_imports_ensure : + IsImported globals "ethereum.utils.ensure" "ensure". + +Axiom ethereum_istanbul_blocks_imports_Log : + IsImported globals "ethereum.istanbul.blocks" "Log". + +Axiom ethereum_istanbul_fork_types_imports_Address : + IsImported globals "ethereum.istanbul.fork_types" "Address". + +Axiom ethereum_istanbul_state_imports_account_exists_and_is_empty : + IsImported globals "ethereum.istanbul.state" "account_exists_and_is_empty". +Axiom ethereum_istanbul_state_imports_account_has_code_or_nonce : + IsImported globals "ethereum.istanbul.state" "account_has_code_or_nonce". +Axiom ethereum_istanbul_state_imports_begin_transaction : + IsImported globals "ethereum.istanbul.state" "begin_transaction". +Axiom ethereum_istanbul_state_imports_commit_transaction : + IsImported globals "ethereum.istanbul.state" "commit_transaction". +Axiom ethereum_istanbul_state_imports_destroy_storage : + IsImported globals "ethereum.istanbul.state" "destroy_storage". +Axiom ethereum_istanbul_state_imports_increment_nonce : + IsImported globals "ethereum.istanbul.state" "increment_nonce". +Axiom ethereum_istanbul_state_imports_mark_account_created : + IsImported globals "ethereum.istanbul.state" "mark_account_created". +Axiom ethereum_istanbul_state_imports_move_ether : + IsImported globals "ethereum.istanbul.state" "move_ether". +Axiom ethereum_istanbul_state_imports_rollback_transaction : + IsImported globals "ethereum.istanbul.state" "rollback_transaction". +Axiom ethereum_istanbul_state_imports_set_code : + IsImported globals "ethereum.istanbul.state" "set_code". +Axiom ethereum_istanbul_state_imports_touch_account : + IsImported globals "ethereum.istanbul.state" "touch_account". + +Axiom ethereum_istanbul_vm_imports_Message : + IsImported globals "ethereum.istanbul.vm" "Message". + +Axiom ethereum_istanbul_vm_gas_imports_GAS_CODE_DEPOSIT : + IsImported globals "ethereum.istanbul.vm.gas" "GAS_CODE_DEPOSIT". +Axiom ethereum_istanbul_vm_gas_imports_charge_gas : + IsImported globals "ethereum.istanbul.vm.gas" "charge_gas". + +Axiom ethereum_istanbul_vm_precompiled_contracts_mapping_imports_PRE_COMPILED_CONTRACTS : + IsImported globals "ethereum.istanbul.vm.precompiled_contracts.mapping" "PRE_COMPILED_CONTRACTS". + +Axiom ethereum_istanbul_vm_imports_Environment : + IsImported globals "ethereum.istanbul.vm" "Environment". +Axiom ethereum_istanbul_vm_imports_Evm : + IsImported globals "ethereum.istanbul.vm" "Evm". + +Axiom ethereum_istanbul_vm_exceptions_imports_AddressCollision : + IsImported globals "ethereum.istanbul.vm.exceptions" "AddressCollision". +Axiom ethereum_istanbul_vm_exceptions_imports_ExceptionalHalt : + IsImported globals "ethereum.istanbul.vm.exceptions" "ExceptionalHalt". +Axiom ethereum_istanbul_vm_exceptions_imports_InvalidOpcode : + IsImported globals "ethereum.istanbul.vm.exceptions" "InvalidOpcode". +Axiom ethereum_istanbul_vm_exceptions_imports_OutOfGasError : + IsImported globals "ethereum.istanbul.vm.exceptions" "OutOfGasError". +Axiom ethereum_istanbul_vm_exceptions_imports_Revert : + IsImported globals "ethereum.istanbul.vm.exceptions" "Revert". +Axiom ethereum_istanbul_vm_exceptions_imports_StackDepthLimitError : + IsImported globals "ethereum.istanbul.vm.exceptions" "StackDepthLimitError". + +Axiom ethereum_istanbul_vm_instructions_imports_Ops : + IsImported globals "ethereum.istanbul.vm.instructions" "Ops". +Axiom ethereum_istanbul_vm_instructions_imports_op_implementation : + IsImported globals "ethereum.istanbul.vm.instructions" "op_implementation". + +Axiom ethereum_istanbul_vm_runtime_imports_get_valid_jump_destinations : + IsImported globals "ethereum.istanbul.vm.runtime" "get_valid_jump_destinations". + +Definition STACK_DEPTH_LIMIT : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 1024 + ], + make_dict [] + |) +)). + +Definition MAX_CODE_SIZE : Value.t := M.run ltac:(M.monadic ( + Constant.int 24576 +)). + +Definition MessageCallOutput : Value.t := + builtins.make_klass + [] + [ + + ] + [ + + ]. + +Definition process_message_call : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "message"; "env" ] |) in + let _ := Constant.str " + If `message.current` is empty then it creates a smart contract + else it executes a call from the `message.caller` to the `message.target`. + + Parameters + ---------- + message : + Transaction specific items. + + env : + External items required for EVM execution. + + Returns + ------- + output : `MessageCallOutput` + Output of the message call + " in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_field (| M.get_name (| globals, "message" |), "target" |), + M.call (| + M.get_name (| globals, "Bytes0" |), + make_list [ + Constant.bytes "" + ], + make_dict [] + |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "is_collision" , + M.call (| + M.get_name (| globals, "account_has_code_or_nonce" |), + make_list [ + M.get_field (| M.get_name (| globals, "env" |), "state" |); + M.get_field (| M.get_name (| globals, "message" |), "current_target" |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + M.get_name (| globals, "is_collision" |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + M.call (| + M.get_name (| globals, "MessageCallOutput" |), + make_list [ + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |); + M.call (| + M.get_name (| globals, "tuple" |), + make_list [], + make_dict [] + |); + M.call (| + M.get_name (| globals, "set" |), + make_list [], + make_dict [] + |); + M.call (| + M.get_name (| globals, "set" |), + make_list [], + make_dict [] + |); + M.call (| + M.get_name (| globals, "AddressCollision" |), + make_list [], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "evm" , + M.call (| + M.get_name (| globals, "process_create_message" |), + make_list [ + M.get_name (| globals, "message" |); + M.get_name (| globals, "env" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "evm" , + M.call (| + M.get_name (| globals, "process_message" |), + make_list [ + M.get_name (| globals, "message" |); + M.get_name (| globals, "env" |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, "account_exists_and_is_empty" |), + make_list [ + M.get_field (| M.get_name (| globals, "env" |), "state" |); + M.call (| + M.get_name (| globals, "Address" |), + make_list [ + M.get_field (| M.get_name (| globals, "message" |), "target" |) + ], + make_dict [] + |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "touched_accounts" |), "add" |), + make_list [ + M.call (| + M.get_name (| globals, "Address" |), + make_list [ + M.get_field (| M.get_name (| globals, "message" |), "target" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + M.get_field (| M.get_name (| globals, "evm" |), "error" |), + (* then *) + ltac:(M.monadic ( +(* At stmt: unsupported node type: AnnAssign *) + let _ := M.assign_local (| + "accounts_to_delete" , + M.call (| + M.get_name (| globals, "set" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "touched_accounts" , + M.call (| + M.get_name (| globals, "set" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "refund_counter" , + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "logs" , + M.get_field (| M.get_name (| globals, "evm" |), "logs" |) + |) in + let _ := M.assign_local (| + "accounts_to_delete" , + M.get_field (| M.get_name (| globals, "evm" |), "accounts_to_delete" |) + |) in + let _ := M.assign_local (| + "touched_accounts" , + M.get_field (| M.get_name (| globals, "evm" |), "touched_accounts" |) + |) in + let _ := M.assign_local (| + "refund_counter" , + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "refund_counter" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "tx_end" , + M.call (| + M.get_name (| globals, "TransactionEnd" |), + make_list [ + BinOp.sub (| + M.get_field (| M.get_name (| globals, "message" |), "gas" |), + M.get_field (| M.get_name (| globals, "evm" |), "gas_left" |) + |); + M.get_field (| M.get_name (| globals, "evm" |), "output" |); + M.get_field (| M.get_name (| globals, "evm" |), "error" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "evm_trace" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "tx_end" |) + ], + make_dict [] + |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, "MessageCallOutput" |), + make_list [], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Definition process_create_message : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "message"; "env" ] |) in + let _ := Constant.str " + Executes a call to create a smart contract. + + Parameters + ---------- + message : + Transaction specific items. + env : + External items required for EVM execution. + + Returns + ------- + evm: :py:class:`~ethereum.istanbul.vm.Evm` + Items containing execution specific objects. + " in + let _ := M.call (| + M.get_name (| globals, "begin_transaction" |), + make_list [ + M.get_field (| M.get_name (| globals, "env" |), "state" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "destroy_storage" |), + make_list [ + M.get_field (| M.get_name (| globals, "env" |), "state" |); + M.get_field (| M.get_name (| globals, "message" |), "current_target" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "mark_account_created" |), + make_list [ + M.get_field (| M.get_name (| globals, "env" |), "state" |); + M.get_field (| M.get_name (| globals, "message" |), "current_target" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "increment_nonce" |), + make_list [ + M.get_field (| M.get_name (| globals, "env" |), "state" |); + M.get_field (| M.get_name (| globals, "message" |), "current_target" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "evm" , + M.call (| + M.get_name (| globals, "process_message" |), + make_list [ + M.get_name (| globals, "message" |); + M.get_name (| globals, "env" |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + UnOp.not (| M.get_field (| M.get_name (| globals, "evm" |), "error" |) |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "contract_code" , + M.get_field (| M.get_name (| globals, "evm" |), "output" |) + |) in + let _ := M.assign_local (| + "contract_code_gas" , + BinOp.mult (| + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_name (| globals, "contract_code" |) + ], + make_dict [] + |), + M.get_name (| globals, "GAS_CODE_DEPOSIT" |) + |) + |) in +(* At stmt: unsupported node type: Try *) + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, "rollback_transaction" |), + make_list [ + M.get_field (| M.get_name (| globals, "env" |), "state" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + )) |) in + let _ := M.return_ (| + M.get_name (| globals, "evm" |) + |) in + M.pure Constant.None_)). + +Definition process_message : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "message"; "env" ] |) in + let _ := Constant.str " + Executes a call to create a smart contract. + + Parameters + ---------- + message : + Transaction specific items. + env : + External items required for EVM execution. + + Returns + ------- + evm: :py:class:`~ethereum.istanbul.vm.Evm` + Items containing execution specific objects + " in + let _ := + (* if *) + M.if_then_else (| + Compare.gt (| + M.get_field (| M.get_name (| globals, "message" |), "depth" |), + M.get_name (| globals, "STACK_DEPTH_LIMIT" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.call (| + M.get_name (| globals, "StackDepthLimitError" |), + make_list [ + Constant.str "Stack depth limit reached" + ], + make_dict [] + |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.call (| + M.get_name (| globals, "begin_transaction" |), + make_list [ + M.get_field (| M.get_name (| globals, "env" |), "state" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "touch_account" |), + make_list [ + M.get_field (| M.get_name (| globals, "env" |), "state" |); + M.get_field (| M.get_name (| globals, "message" |), "current_target" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + BoolOp.and (| + M.get_field (| M.get_name (| globals, "message" |), "should_transfer_value" |), + ltac:(M.monadic ( + Compare.not_eq (| + M.get_field (| M.get_name (| globals, "message" |), "value" |), + Constant.int 0 + |) + )) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, "move_ether" |), + make_list [ + M.get_field (| M.get_name (| globals, "env" |), "state" |); + M.get_field (| M.get_name (| globals, "message" |), "caller" |); + M.get_field (| M.get_name (| globals, "message" |), "current_target" |); + M.get_field (| M.get_name (| globals, "message" |), "value" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "evm" , + M.call (| + M.get_name (| globals, "execute_code" |), + make_list [ + M.get_name (| globals, "message" |); + M.get_name (| globals, "env" |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + M.get_field (| M.get_name (| globals, "evm" |), "error" |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, "rollback_transaction" |), + make_list [ + M.get_field (| M.get_name (| globals, "env" |), "state" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, "commit_transaction" |), + make_list [ + M.get_field (| M.get_name (| globals, "env" |), "state" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + )) |) in + let _ := M.return_ (| + M.get_name (| globals, "evm" |) + |) in + M.pure Constant.None_)). + +Definition execute_code : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "message"; "env" ] |) in + let _ := Constant.str " + Executes bytecode present in the `message`. + + Parameters + ---------- + message : + Transaction specific items. + env : + External items required for EVM execution. + + Returns + ------- + evm: `ethereum.vm.EVM` + Items containing execution specific objects + " in + let _ := M.assign_local (| + "code" , + M.get_field (| M.get_name (| globals, "message" |), "code" |) + |) in + let _ := M.assign_local (| + "valid_jump_destinations" , + M.call (| + M.get_name (| globals, "get_valid_jump_destinations" |), + make_list [ + M.get_name (| globals, "code" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "evm" , + M.call (| + M.get_name (| globals, "Evm" |), + make_list [], + make_dict [] + |) + |) in +(* At stmt: unsupported node type: Try *) + let _ := M.return_ (| + M.get_name (| globals, "evm" |) + |) in + M.pure Constant.None_)). diff --git a/CoqOfPython/ethereum/istanbul/vm/memory.v b/CoqOfPython/ethereum/istanbul/vm/memory.v new file mode 100644 index 0000000..743e878 --- /dev/null +++ b/CoqOfPython/ethereum/istanbul/vm/memory.v @@ -0,0 +1,166 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.istanbul.vm.memory". + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) Memory +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +EVM memory operations. +". + +Axiom ethereum_utils_byte_imports_right_pad_zero_bytes : + IsImported globals "ethereum.utils.byte" "right_pad_zero_bytes". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_Bytes : + IsImported globals "ethereum.base_types" "Bytes". +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". + +Definition memory_write : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "memory"; "start_position"; "value" ] |) in + let _ := Constant.str " + Writes to memory. + + Parameters + ---------- + memory : + Memory contents of the EVM. + start_position : + Starting pointer to the memory. + value : + Data to write to memory. + " in + let _ := M.assign (| + M.slice (| + M.get_name (| globals, "memory" |), + M.get_name (| globals, "start_position" |), + BinOp.add (| + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.get_name (| globals, "start_position" |) + ], + make_dict [] + |), + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_name (| globals, "value" |) + ], + make_dict [] + |) + |), + Constant.None_ + |), + M.get_name (| globals, "value" |) + |) in + M.pure Constant.None_)). + +Definition memory_read_bytes : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "memory"; "start_position"; "size" ] |) in + let _ := Constant.str " + Read bytes from memory. + + Parameters + ---------- + memory : + Memory contents of the EVM. + start_position : + Starting pointer to the memory. + size : + Size of the data that needs to be read from `start_position`. + + Returns + ------- + data_bytes : + Data read from memory. + " in + let _ := M.return_ (| + M.slice (| + M.get_name (| globals, "memory" |), + M.get_name (| globals, "start_position" |), + BinOp.add (| + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.get_name (| globals, "start_position" |) + ], + make_dict [] + |), + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.get_name (| globals, "size" |) + ], + make_dict [] + |) + |), + Constant.None_ + |) + |) in + M.pure Constant.None_)). + +Definition buffer_read : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "buffer"; "start_position"; "size" ] |) in + let _ := Constant.str " + Read bytes from a buffer. Padding with zeros if necessary. + + Parameters + ---------- + buffer : + Memory contents of the EVM. + start_position : + Starting pointer to the memory. + size : + Size of the data that needs to be read from `start_position`. + + Returns + ------- + data_bytes : + Data read from memory. + " in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, "right_pad_zero_bytes" |), + make_list [ + M.slice (| + M.get_name (| globals, "buffer" |), + M.get_name (| globals, "start_position" |), + BinOp.add (| + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.get_name (| globals, "start_position" |) + ], + make_dict [] + |), + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.get_name (| globals, "size" |) + ], + make_dict [] + |) + |), + Constant.None_ + |); + M.get_name (| globals, "size" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). diff --git a/CoqOfPython/ethereum/istanbul/vm/precompiled_contracts/__init__.v b/CoqOfPython/ethereum/istanbul/vm/precompiled_contracts/__init__.v new file mode 100644 index 0000000..1419ef4 --- /dev/null +++ b/CoqOfPython/ethereum/istanbul/vm/precompiled_contracts/__init__.v @@ -0,0 +1,116 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.istanbul.vm.precompiled_contracts.__init__". + +Definition expr_1 : Value.t := + Constant.str " +Precompiled Contract Addresses +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Addresses of precompiled contracts and mappings to their +implementations. +". + +Axiom ethereum_istanbul_utils_hexadecimal_imports_hex_to_address : + IsImported globals "ethereum.istanbul.utils.hexadecimal" "hex_to_address". + +Definition __all__ : Value.t := M.run ltac:(M.monadic ( + make_tuple [ Constant.str "ECRECOVER_ADDRESS"; Constant.str "SHA256_ADDRESS"; Constant.str "RIPEMD160_ADDRESS"; Constant.str "IDENTITY_ADDRESS"; Constant.str "MODEXP_ADDRESS"; Constant.str "ALT_BN128_ADD_ADDRESS"; Constant.str "ALT_BN128_MUL_ADDRESS"; Constant.str "ALT_BN128_PAIRING_CHECK_ADDRESS"; Constant.str "BLAKE2F_ADDRESS" ] +)). + +Definition ECRECOVER_ADDRESS : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "hex_to_address" |), + make_list [ + Constant.str "0x01" + ], + make_dict [] + |) +)). + +Definition SHA256_ADDRESS : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "hex_to_address" |), + make_list [ + Constant.str "0x02" + ], + make_dict [] + |) +)). + +Definition RIPEMD160_ADDRESS : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "hex_to_address" |), + make_list [ + Constant.str "0x03" + ], + make_dict [] + |) +)). + +Definition IDENTITY_ADDRESS : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "hex_to_address" |), + make_list [ + Constant.str "0x04" + ], + make_dict [] + |) +)). + +Definition MODEXP_ADDRESS : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "hex_to_address" |), + make_list [ + Constant.str "0x05" + ], + make_dict [] + |) +)). + +Definition ALT_BN128_ADD_ADDRESS : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "hex_to_address" |), + make_list [ + Constant.str "0x06" + ], + make_dict [] + |) +)). + +Definition ALT_BN128_MUL_ADDRESS : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "hex_to_address" |), + make_list [ + Constant.str "0x07" + ], + make_dict [] + |) +)). + +Definition ALT_BN128_PAIRING_CHECK_ADDRESS : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "hex_to_address" |), + make_list [ + Constant.str "0x08" + ], + make_dict [] + |) +)). + +Definition BLAKE2F_ADDRESS : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "hex_to_address" |), + make_list [ + Constant.str "0x09" + ], + make_dict [] + |) +)). diff --git a/CoqOfPython/ethereum/istanbul/vm/precompiled_contracts/alt_bn128.v b/CoqOfPython/ethereum/istanbul/vm/precompiled_contracts/alt_bn128.v new file mode 100644 index 0000000..e074092 --- /dev/null +++ b/CoqOfPython/ethereum/istanbul/vm/precompiled_contracts/alt_bn128.v @@ -0,0 +1,778 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.istanbul.vm.precompiled_contracts.alt_bn128". + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) ALT_BN128 CONTRACTS +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementation of the ALT_BN128 precompiled contracts. +". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". + +Axiom ethereum_crypto_alt_bn128_imports_ALT_BN128_CURVE_ORDER : + IsImported globals "ethereum.crypto.alt_bn128" "ALT_BN128_CURVE_ORDER". +Axiom ethereum_crypto_alt_bn128_imports_ALT_BN128_PRIME : + IsImported globals "ethereum.crypto.alt_bn128" "ALT_BN128_PRIME". +Axiom ethereum_crypto_alt_bn128_imports_BNF : + IsImported globals "ethereum.crypto.alt_bn128" "BNF". +Axiom ethereum_crypto_alt_bn128_imports_BNF2 : + IsImported globals "ethereum.crypto.alt_bn128" "BNF2". +Axiom ethereum_crypto_alt_bn128_imports_BNF12 : + IsImported globals "ethereum.crypto.alt_bn128" "BNF12". +Axiom ethereum_crypto_alt_bn128_imports_BNP : + IsImported globals "ethereum.crypto.alt_bn128" "BNP". +Axiom ethereum_crypto_alt_bn128_imports_BNP2 : + IsImported globals "ethereum.crypto.alt_bn128" "BNP2". +Axiom ethereum_crypto_alt_bn128_imports_pairing : + IsImported globals "ethereum.crypto.alt_bn128" "pairing". + +Axiom ethereum_utils_ensure_imports_ensure : + IsImported globals "ethereum.utils.ensure" "ensure". + +Axiom ethereum_istanbul_vm_imports_Evm : + IsImported globals "ethereum.istanbul.vm" "Evm". + +Axiom ethereum_istanbul_vm_gas_imports_charge_gas : + IsImported globals "ethereum.istanbul.vm.gas" "charge_gas". + +Axiom ethereum_istanbul_vm_memory_imports_buffer_read : + IsImported globals "ethereum.istanbul.vm.memory" "buffer_read". + +Axiom ethereum_istanbul_vm_exceptions_imports_OutOfGasError : + IsImported globals "ethereum.istanbul.vm.exceptions" "OutOfGasError". + +Definition alt_bn128_add : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + The ALT_BN128 addition precompiled contract. + + Parameters + ---------- + evm : + The current EVM frame. + " in + let _ := M.assign_local (| + "data" , + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "data" |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 150 + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "x0_bytes" , + M.call (| + M.get_name (| globals, "buffer_read" |), + make_list [ + M.get_name (| globals, "data" |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 32 + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "x0_value" , + M.call (| + M.get_field (| M.get_name (| globals, "U256" |), "from_be_bytes" |), + make_list [ + M.get_name (| globals, "x0_bytes" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "y0_bytes" , + M.call (| + M.get_name (| globals, "buffer_read" |), + make_list [ + M.get_name (| globals, "data" |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 32 + ], + make_dict [] + |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 32 + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "y0_value" , + M.call (| + M.get_field (| M.get_name (| globals, "U256" |), "from_be_bytes" |), + make_list [ + M.get_name (| globals, "y0_bytes" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "x1_bytes" , + M.call (| + M.get_name (| globals, "buffer_read" |), + make_list [ + M.get_name (| globals, "data" |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 64 + ], + make_dict [] + |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 32 + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "x1_value" , + M.call (| + M.get_field (| M.get_name (| globals, "U256" |), "from_be_bytes" |), + make_list [ + M.get_name (| globals, "x1_bytes" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "y1_bytes" , + M.call (| + M.get_name (| globals, "buffer_read" |), + make_list [ + M.get_name (| globals, "data" |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 96 + ], + make_dict [] + |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 32 + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "y1_value" , + M.call (| + M.get_field (| M.get_name (| globals, "U256" |), "from_be_bytes" |), + make_list [ + M.get_name (| globals, "y1_bytes" |) + ], + make_dict [] + |) + |) in + let _ := + M.for_ (| + M.get_name (| globals, "i" |), + make_tuple [ M.get_name (| globals, "x0_value" |); M.get_name (| globals, "y0_value" |); M.get_name (| globals, "x1_value" |); M.get_name (| globals, "y1_value" |) ], + ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + Compare.gt_e (| + M.get_name (| globals, "i" |), + M.get_name (| globals, "ALT_BN128_PRIME" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, "OutOfGasError" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in +(* At stmt: unsupported node type: Try *) + let _ := M.assign_local (| + "p" , + BinOp.add (| + M.get_name (| globals, "p0" |), + M.get_name (| globals, "p1" |) + |) + |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, "evm" |), "output" |), + BinOp.add (| + M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, "p" |), "x" |), "to_be_bytes32" |), + make_list [], + make_dict [] + |), + M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, "p" |), "y" |), "to_be_bytes32" |), + make_list [], + make_dict [] + |) + |) + |) in + M.pure Constant.None_)). + +Definition alt_bn128_mul : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + The ALT_BN128 multiplication precompiled contract. + + Parameters + ---------- + evm : + The current EVM frame. + " in + let _ := M.assign_local (| + "data" , + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "data" |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 6000 + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "x0_bytes" , + M.call (| + M.get_name (| globals, "buffer_read" |), + make_list [ + M.get_name (| globals, "data" |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 32 + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "x0_value" , + M.call (| + M.get_field (| M.get_name (| globals, "U256" |), "from_be_bytes" |), + make_list [ + M.get_name (| globals, "x0_bytes" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "y0_bytes" , + M.call (| + M.get_name (| globals, "buffer_read" |), + make_list [ + M.get_name (| globals, "data" |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 32 + ], + make_dict [] + |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 32 + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "y0_value" , + M.call (| + M.get_field (| M.get_name (| globals, "U256" |), "from_be_bytes" |), + make_list [ + M.get_name (| globals, "y0_bytes" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "n" , + M.call (| + M.get_field (| M.get_name (| globals, "U256" |), "from_be_bytes" |), + make_list [ + M.call (| + M.get_name (| globals, "buffer_read" |), + make_list [ + M.get_name (| globals, "data" |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 64 + ], + make_dict [] + |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 32 + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := + M.for_ (| + M.get_name (| globals, "i" |), + make_tuple [ M.get_name (| globals, "x0_value" |); M.get_name (| globals, "y0_value" |) ], + ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + Compare.gt_e (| + M.get_name (| globals, "i" |), + M.get_name (| globals, "ALT_BN128_PRIME" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, "OutOfGasError" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in +(* At stmt: unsupported node type: Try *) + let _ := M.assign_local (| + "p" , + M.call (| + M.get_field (| M.get_name (| globals, "p0" |), "mul_by" |), + make_list [ + M.get_name (| globals, "n" |) + ], + make_dict [] + |) + |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, "evm" |), "output" |), + BinOp.add (| + M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, "p" |), "x" |), "to_be_bytes32" |), + make_list [], + make_dict [] + |), + M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, "p" |), "y" |), "to_be_bytes32" |), + make_list [], + make_dict [] + |) + |) + |) in + M.pure Constant.None_)). + +Definition alt_bn128_pairing_check : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + The ALT_BN128 pairing check precompiled contract. + + Parameters + ---------- + evm : + The current EVM frame. + " in + let _ := M.assign_local (| + "data" , + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "data" |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + BinOp.add (| + BinOp.mult (| + Constant.int 34000, + BinOp.floor_div (| + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_name (| globals, "data" |) + ], + make_dict [] + |), + Constant.int 192 + |) + |), + Constant.int 45000 + |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.not_eq (| + BinOp.mod_ (| + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_name (| globals, "data" |) + ], + make_dict [] + |), + Constant.int 192 + |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, "OutOfGasError" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "result" , + M.call (| + M.get_field (| M.get_name (| globals, "BNF12" |), "from_int" |), + make_list [ + Constant.int 1 + ], + make_dict [] + |) + |) in + let _ := + M.for_ (| + M.get_name (| globals, "i" |), + M.call (| + M.get_name (| globals, "range" |), + make_list [ + BinOp.floor_div (| + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_name (| globals, "data" |) + ], + make_dict [] + |), + Constant.int 192 + |) + ], + make_dict [] + |), + ltac:(M.monadic ( + let _ := M.assign_local (| + "values" , + make_list [] + |) in + let _ := + M.for_ (| + M.get_name (| globals, "j" |), + M.call (| + M.get_name (| globals, "range" |), + make_list [ + Constant.int 6 + ], + make_dict [] + |), + ltac:(M.monadic ( + let _ := M.assign_local (| + "value" , + M.call (| + M.get_field (| M.get_name (| globals, "U256" |), "from_be_bytes" |), + make_list [ + M.slice (| + M.get_name (| globals, "data" |), + BinOp.add (| + BinOp.mult (| + M.get_name (| globals, "i" |), + Constant.int 192 + |), + BinOp.mult (| + Constant.int 32, + M.get_name (| globals, "j" |) + |) + |), + BinOp.add (| + BinOp.mult (| + M.get_name (| globals, "i" |), + Constant.int 192 + |), + BinOp.mult (| + Constant.int 32, + BinOp.add (| + M.get_name (| globals, "j" |), + Constant.int 1 + |) + |) + |), + Constant.None_ + |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.gt_e (| + M.get_name (| globals, "value" |), + M.get_name (| globals, "ALT_BN128_PRIME" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, "OutOfGasError" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.call (| + M.get_field (| M.get_name (| globals, "values" |), "append" |), + make_list [ + M.call (| + M.get_name (| globals, "int" |), + make_list [ + M.get_name (| globals, "value" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in +(* At stmt: unsupported node type: Try *) + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + Compare.eq (| + M.call (| + M.get_field (| M.get_name (| globals, "p" |), "mul_by" |), + make_list [ + M.get_name (| globals, "ALT_BN128_CURVE_ORDER" |) + ], + make_dict [] + |), + M.call (| + M.get_field (| M.get_name (| globals, "BNP" |), "point_at_infinity" |), + make_list [], + make_dict [] + |) + |); + M.get_name (| globals, "OutOfGasError" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + Compare.eq (| + M.call (| + M.get_field (| M.get_name (| globals, "q" |), "mul_by" |), + make_list [ + M.get_name (| globals, "ALT_BN128_CURVE_ORDER" |) + ], + make_dict [] + |), + M.call (| + M.get_field (| M.get_name (| globals, "BNP2" |), "point_at_infinity" |), + make_list [], + make_dict [] + |) + |); + M.get_name (| globals, "OutOfGasError" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + BoolOp.and (| + Compare.not_eq (| + M.get_name (| globals, "p" |), + M.call (| + M.get_field (| M.get_name (| globals, "BNP" |), "point_at_infinity" |), + make_list [], + make_dict [] + |) + |), + ltac:(M.monadic ( + Compare.not_eq (| + M.get_name (| globals, "q" |), + M.call (| + M.get_field (| M.get_name (| globals, "BNP2" |), "point_at_infinity" |), + make_list [], + make_dict [] + |) + |) + )) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "result" , + BinOp.mult (| + M.get_name (| globals, "result" |), + M.call (| + M.get_name (| globals, "pairing" |), + make_list [ + M.get_name (| globals, "q" |); + M.get_name (| globals, "p" |) + ], + make_dict [] + |) + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, "result" |), + M.call (| + M.get_field (| M.get_name (| globals, "BNF12" |), "from_int" |), + make_list [ + Constant.int 1 + ], + make_dict [] + |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign (| + M.get_field (| M.get_name (| globals, "evm" |), "output" |), + M.call (| + M.get_field (| M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 1 + ], + make_dict [] + |), "to_be_bytes32" |), + make_list [], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign (| + M.get_field (| M.get_name (| globals, "evm" |), "output" |), + M.call (| + M.get_field (| M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |), "to_be_bytes32" |), + make_list [], + make_dict [] + |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_)). diff --git a/CoqOfPython/ethereum/istanbul/vm/precompiled_contracts/blake2f.v b/CoqOfPython/ethereum/istanbul/vm/precompiled_contracts/blake2f.v new file mode 100644 index 0000000..da836ff --- /dev/null +++ b/CoqOfPython/ethereum/istanbul/vm/precompiled_contracts/blake2f.v @@ -0,0 +1,127 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.istanbul.vm.precompiled_contracts.blake2f". + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) Blake2 PRECOMPILED CONTRACT +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementation of the `Blake2` precompiled contract. +". + +Axiom ethereum_crypto_blake2_imports_Blake2b : + IsImported globals "ethereum.crypto.blake2" "Blake2b". + +Axiom ethereum_utils_ensure_imports_ensure : + IsImported globals "ethereum.utils.ensure" "ensure". + +Axiom ethereum_istanbul_vm_imports_Evm : + IsImported globals "ethereum.istanbul.vm" "Evm". + +Axiom ethereum_istanbul_vm_gas_imports_GAS_BLAKE2_PER_ROUND : + IsImported globals "ethereum.istanbul.vm.gas" "GAS_BLAKE2_PER_ROUND". +Axiom ethereum_istanbul_vm_gas_imports_charge_gas : + IsImported globals "ethereum.istanbul.vm.gas" "charge_gas". + +Axiom ethereum_istanbul_vm_exceptions_imports_InvalidParameter : + IsImported globals "ethereum.istanbul.vm.exceptions" "InvalidParameter". + +Definition blake2f : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Writes the Blake2 hash to output. + + Parameters + ---------- + evm : + The current EVM frame. + " in + let _ := M.assign_local (| + "data" , + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "data" |) + |) in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + Compare.eq (| + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_name (| globals, "data" |) + ], + make_dict [] + |), + Constant.int 213 + |); + M.get_name (| globals, "InvalidParameter" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "blake2b" , + M.call (| + M.get_name (| globals, "Blake2b" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.assign (| + make_tuple [ M.get_name (| globals, "rounds" |); M.get_name (| globals, "h" |); M.get_name (| globals, "m" |); M.get_name (| globals, "t_0" |); M.get_name (| globals, "t_1" |); M.get_name (| globals, "f" |) ], + M.call (| + M.get_field (| M.get_name (| globals, "blake2b" |), "get_blake2_parameters" |), + make_list [ + M.get_name (| globals, "data" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + BinOp.mult (| + M.get_name (| globals, "GAS_BLAKE2_PER_ROUND" |), + M.get_name (| globals, "rounds" |) + |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + Compare.in_ (| + M.get_name (| globals, "f" |), + make_list [ + Constant.int 0; + Constant.int 1 + ] + |); + M.get_name (| globals, "InvalidParameter" |) + ], + make_dict [] + |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, "evm" |), "output" |), + M.call (| + M.get_field (| M.get_name (| globals, "blake2b" |), "compress" |), + make_list [ + M.get_name (| globals, "rounds" |); + M.get_name (| globals, "h" |); + M.get_name (| globals, "m" |); + M.get_name (| globals, "t_0" |); + M.get_name (| globals, "t_1" |); + M.get_name (| globals, "f" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). diff --git a/CoqOfPython/ethereum/istanbul/vm/precompiled_contracts/ecrecover.v b/CoqOfPython/ethereum/istanbul/vm/precompiled_contracts/ecrecover.v new file mode 100644 index 0000000..de71626 --- /dev/null +++ b/CoqOfPython/ethereum/istanbul/vm/precompiled_contracts/ecrecover.v @@ -0,0 +1,301 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.istanbul.vm.precompiled_contracts.ecrecover". + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) ECRECOVER PRECOMPILED CONTRACT +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementation of the ECRECOVER precompiled contract. +". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". + +Axiom ethereum_crypto_elliptic_curve_imports_SECP256K1N : + IsImported globals "ethereum.crypto.elliptic_curve" "SECP256K1N". +Axiom ethereum_crypto_elliptic_curve_imports_secp256k1_recover : + IsImported globals "ethereum.crypto.elliptic_curve" "secp256k1_recover". + +Axiom ethereum_crypto_hash_imports_Hash32 : + IsImported globals "ethereum.crypto.hash" "Hash32". +Axiom ethereum_crypto_hash_imports_keccak256 : + IsImported globals "ethereum.crypto.hash" "keccak256". + +Axiom ethereum_utils_byte_imports_left_pad_zero_bytes : + IsImported globals "ethereum.utils.byte" "left_pad_zero_bytes". + +Axiom ethereum_istanbul_vm_imports_Evm : + IsImported globals "ethereum.istanbul.vm" "Evm". + +Axiom ethereum_istanbul_vm_gas_imports_GAS_ECRECOVER : + IsImported globals "ethereum.istanbul.vm.gas" "GAS_ECRECOVER". +Axiom ethereum_istanbul_vm_gas_imports_charge_gas : + IsImported globals "ethereum.istanbul.vm.gas" "charge_gas". + +Axiom ethereum_istanbul_vm_memory_imports_buffer_read : + IsImported globals "ethereum.istanbul.vm.memory" "buffer_read". + +Definition ecrecover : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Decrypts the address using elliptic curve DSA recovery mechanism and writes + the address to output. + + Parameters + ---------- + evm : + The current EVM frame. + " in + let _ := M.assign_local (| + "data" , + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "data" |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_ECRECOVER" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "message_hash_bytes" , + M.call (| + M.get_name (| globals, "buffer_read" |), + make_list [ + M.get_name (| globals, "data" |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 32 + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "message_hash" , + M.call (| + M.get_name (| globals, "Hash32" |), + make_list [ + M.get_name (| globals, "message_hash_bytes" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "v" , + M.call (| + M.get_field (| M.get_name (| globals, "U256" |), "from_be_bytes" |), + make_list [ + M.call (| + M.get_name (| globals, "buffer_read" |), + make_list [ + M.get_name (| globals, "data" |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 32 + ], + make_dict [] + |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 32 + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "r" , + M.call (| + M.get_field (| M.get_name (| globals, "U256" |), "from_be_bytes" |), + make_list [ + M.call (| + M.get_name (| globals, "buffer_read" |), + make_list [ + M.get_name (| globals, "data" |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 64 + ], + make_dict [] + |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 32 + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "s" , + M.call (| + M.get_field (| M.get_name (| globals, "U256" |), "from_be_bytes" |), + make_list [ + M.call (| + M.get_name (| globals, "buffer_read" |), + make_list [ + M.get_name (| globals, "data" |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 96 + ], + make_dict [] + |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 32 + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + BoolOp.and (| + Compare.not_eq (| + M.get_name (| globals, "v" |), + Constant.int 27 + |), + ltac:(M.monadic ( + Compare.not_eq (| + M.get_name (| globals, "v" |), + Constant.int 28 + |) + )) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + Constant.None_ + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + BoolOp.or (| + Compare.gt_e (| + Constant.int 0, + M.get_name (| globals, "r" |) + |), + ltac:(M.monadic ( + Compare.gt_e (| + M.get_name (| globals, "r" |), + M.get_name (| globals, "SECP256K1N" |) + |) + )) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + Constant.None_ + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + BoolOp.or (| + Compare.gt_e (| + Constant.int 0, + M.get_name (| globals, "s" |) + |), + ltac:(M.monadic ( + Compare.gt_e (| + M.get_name (| globals, "s" |), + M.get_name (| globals, "SECP256K1N" |) + |) + )) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + Constant.None_ + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in +(* At stmt: unsupported node type: Try *) + let _ := M.assign_local (| + "address" , + M.slice (| + M.call (| + M.get_name (| globals, "keccak256" |), + make_list [ + M.get_name (| globals, "public_key" |) + ], + make_dict [] + |), + Constant.int 12, + Constant.int 32, + Constant.None_ + |) + |) in + let _ := M.assign_local (| + "padded_address" , + M.call (| + M.get_name (| globals, "left_pad_zero_bytes" |), + make_list [ + M.get_name (| globals, "address" |); + Constant.int 32 + ], + make_dict [] + |) + |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, "evm" |), "output" |), + M.get_name (| globals, "padded_address" |) + |) in + M.pure Constant.None_)). diff --git a/CoqOfPython/ethereum/istanbul/vm/precompiled_contracts/identity.v b/CoqOfPython/ethereum/istanbul/vm/precompiled_contracts/identity.v new file mode 100644 index 0000000..894529f --- /dev/null +++ b/CoqOfPython/ethereum/istanbul/vm/precompiled_contracts/identity.v @@ -0,0 +1,94 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.istanbul.vm.precompiled_contracts.identity". + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) IDENTITY PRECOMPILED CONTRACT +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementation of the `IDENTITY` precompiled contract. +". + +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". + +Axiom ethereum_utils_numeric_imports_ceil32 : + IsImported globals "ethereum.utils.numeric" "ceil32". + +Axiom ethereum_istanbul_vm_imports_Evm : + IsImported globals "ethereum.istanbul.vm" "Evm". + +Axiom ethereum_istanbul_vm_gas_imports_GAS_IDENTITY : + IsImported globals "ethereum.istanbul.vm.gas" "GAS_IDENTITY". +Axiom ethereum_istanbul_vm_gas_imports_GAS_IDENTITY_WORD : + IsImported globals "ethereum.istanbul.vm.gas" "GAS_IDENTITY_WORD". +Axiom ethereum_istanbul_vm_gas_imports_charge_gas : + IsImported globals "ethereum.istanbul.vm.gas" "charge_gas". + +Definition identity : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Writes the message data to output. + + Parameters + ---------- + evm : + The current EVM frame. + " in + let _ := M.assign_local (| + "data" , + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "data" |) + |) in + let _ := M.assign_local (| + "word_count" , + BinOp.floor_div (| + M.call (| + M.get_name (| globals, "ceil32" |), + make_list [ + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_name (| globals, "data" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |), + Constant.int 32 + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + BinOp.add (| + M.get_name (| globals, "GAS_IDENTITY" |), + BinOp.mult (| + M.get_name (| globals, "GAS_IDENTITY_WORD" |), + M.get_name (| globals, "word_count" |) + |) + |) + ], + make_dict [] + |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, "evm" |), "output" |), + M.get_name (| globals, "data" |) + |) in + M.pure Constant.None_)). diff --git a/CoqOfPython/ethereum/istanbul/vm/precompiled_contracts/mapping.v b/CoqOfPython/ethereum/istanbul/vm/precompiled_contracts/mapping.v new file mode 100644 index 0000000..d88667d --- /dev/null +++ b/CoqOfPython/ethereum/istanbul/vm/precompiled_contracts/mapping.v @@ -0,0 +1,72 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.istanbul.vm.precompiled_contracts.mapping". + +Definition expr_1 : Value.t := + Constant.str " +Precompiled Contract Addresses +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Mapping of precompiled contracts their implementations. +". + +Axiom typing_imports_Callable : + IsImported globals "typing" "Callable". +Axiom typing_imports_Dict : + IsImported globals "typing" "Dict". + +Axiom ethereum_istanbul_fork_types_imports_Address : + IsImported globals "ethereum.istanbul.fork_types" "Address". + +Axiom ethereum_istanbul_vm_precompiled_contracts_imports_ALT_BN128_ADD_ADDRESS : + IsImported globals "ethereum.istanbul.vm.precompiled_contracts" "ALT_BN128_ADD_ADDRESS". +Axiom ethereum_istanbul_vm_precompiled_contracts_imports_ALT_BN128_MUL_ADDRESS : + IsImported globals "ethereum.istanbul.vm.precompiled_contracts" "ALT_BN128_MUL_ADDRESS". +Axiom ethereum_istanbul_vm_precompiled_contracts_imports_ALT_BN128_PAIRING_CHECK_ADDRESS : + IsImported globals "ethereum.istanbul.vm.precompiled_contracts" "ALT_BN128_PAIRING_CHECK_ADDRESS". +Axiom ethereum_istanbul_vm_precompiled_contracts_imports_BLAKE2F_ADDRESS : + IsImported globals "ethereum.istanbul.vm.precompiled_contracts" "BLAKE2F_ADDRESS". +Axiom ethereum_istanbul_vm_precompiled_contracts_imports_ECRECOVER_ADDRESS : + IsImported globals "ethereum.istanbul.vm.precompiled_contracts" "ECRECOVER_ADDRESS". +Axiom ethereum_istanbul_vm_precompiled_contracts_imports_IDENTITY_ADDRESS : + IsImported globals "ethereum.istanbul.vm.precompiled_contracts" "IDENTITY_ADDRESS". +Axiom ethereum_istanbul_vm_precompiled_contracts_imports_MODEXP_ADDRESS : + IsImported globals "ethereum.istanbul.vm.precompiled_contracts" "MODEXP_ADDRESS". +Axiom ethereum_istanbul_vm_precompiled_contracts_imports_RIPEMD160_ADDRESS : + IsImported globals "ethereum.istanbul.vm.precompiled_contracts" "RIPEMD160_ADDRESS". +Axiom ethereum_istanbul_vm_precompiled_contracts_imports_SHA256_ADDRESS : + IsImported globals "ethereum.istanbul.vm.precompiled_contracts" "SHA256_ADDRESS". + +Axiom ethereum_istanbul_vm_precompiled_contracts_alt_bn128_imports_alt_bn128_add : + IsImported globals "ethereum.istanbul.vm.precompiled_contracts.alt_bn128" "alt_bn128_add". +Axiom ethereum_istanbul_vm_precompiled_contracts_alt_bn128_imports_alt_bn128_mul : + IsImported globals "ethereum.istanbul.vm.precompiled_contracts.alt_bn128" "alt_bn128_mul". +Axiom ethereum_istanbul_vm_precompiled_contracts_alt_bn128_imports_alt_bn128_pairing_check : + IsImported globals "ethereum.istanbul.vm.precompiled_contracts.alt_bn128" "alt_bn128_pairing_check". + +Axiom ethereum_istanbul_vm_precompiled_contracts_blake2f_imports_blake2f : + IsImported globals "ethereum.istanbul.vm.precompiled_contracts.blake2f" "blake2f". + +Axiom ethereum_istanbul_vm_precompiled_contracts_ecrecover_imports_ecrecover : + IsImported globals "ethereum.istanbul.vm.precompiled_contracts.ecrecover" "ecrecover". + +Axiom ethereum_istanbul_vm_precompiled_contracts_identity_imports_identity : + IsImported globals "ethereum.istanbul.vm.precompiled_contracts.identity" "identity". + +Axiom ethereum_istanbul_vm_precompiled_contracts_modexp_imports_modexp : + IsImported globals "ethereum.istanbul.vm.precompiled_contracts.modexp" "modexp". + +Axiom ethereum_istanbul_vm_precompiled_contracts_ripemd160_imports_ripemd160 : + IsImported globals "ethereum.istanbul.vm.precompiled_contracts.ripemd160" "ripemd160". + +Axiom ethereum_istanbul_vm_precompiled_contracts_sha256_imports_sha256 : + IsImported globals "ethereum.istanbul.vm.precompiled_contracts.sha256" "sha256". + +(* At top_level_stmt: unsupported node type: AnnAssign *) diff --git a/CoqOfPython/ethereum/istanbul/vm/precompiled_contracts/modexp.v b/CoqOfPython/ethereum/istanbul/vm/precompiled_contracts/modexp.v new file mode 100644 index 0000000..6178170 --- /dev/null +++ b/CoqOfPython/ethereum/istanbul/vm/precompiled_contracts/modexp.v @@ -0,0 +1,544 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.istanbul.vm.precompiled_contracts.modexp". + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) MODEXP PRECOMPILED CONTRACT +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementation of the `MODEXP` precompiled contract. +". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_Bytes : + IsImported globals "ethereum.base_types" "Bytes". +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". + +Axiom ethereum_istanbul_vm_imports_Evm : + IsImported globals "ethereum.istanbul.vm" "Evm". + +Axiom ethereum_istanbul_vm_gas_imports_charge_gas : + IsImported globals "ethereum.istanbul.vm.gas" "charge_gas". + +Axiom ethereum_istanbul_vm_memory_imports_buffer_read : + IsImported globals "ethereum.istanbul.vm.memory" "buffer_read". + +Definition GQUADDIVISOR : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 20 + ], + make_dict [] + |) +)). + +Definition modexp : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Calculates `(base**exp) % modulus` for arbitrary sized `base`, `exp` and. + `modulus`. The return value is the same length as the modulus. + " in + let _ := M.assign_local (| + "data" , + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "data" |) + |) in + let _ := M.assign_local (| + "base_length" , + M.call (| + M.get_field (| M.get_name (| globals, "U256" |), "from_be_bytes" |), + make_list [ + M.call (| + M.get_name (| globals, "buffer_read" |), + make_list [ + M.get_name (| globals, "data" |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 32 + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "exp_length" , + M.call (| + M.get_field (| M.get_name (| globals, "U256" |), "from_be_bytes" |), + make_list [ + M.call (| + M.get_name (| globals, "buffer_read" |), + make_list [ + M.get_name (| globals, "data" |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 32 + ], + make_dict [] + |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 32 + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "modulus_length" , + M.call (| + M.get_field (| M.get_name (| globals, "U256" |), "from_be_bytes" |), + make_list [ + M.call (| + M.get_name (| globals, "buffer_read" |), + make_list [ + M.get_name (| globals, "data" |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 64 + ], + make_dict [] + |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 32 + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "exp_start" , + BinOp.add (| + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 96 + ], + make_dict [] + |), + M.get_name (| globals, "base_length" |) + |) + |) in + let _ := M.assign_local (| + "exp_head" , + M.call (| + M.get_field (| M.get_name (| globals, "U256" |), "from_be_bytes" |), + make_list [ + M.call (| + M.get_name (| globals, "buffer_read" |), + make_list [ + M.get_name (| globals, "data" |); + M.get_name (| globals, "exp_start" |); + M.call (| + M.get_name (| globals, "min" |), + make_list [ + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 32 + ], + make_dict [] + |); + M.get_name (| globals, "exp_length" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.lt (| + M.get_name (| globals, "exp_length" |), + Constant.int 32 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "adjusted_exp_length" , + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, "max" |), + make_list [ + Constant.int 0; + BinOp.sub (| + M.call (| + M.get_field (| M.get_name (| globals, "exp_head" |), "bit_length" |), + make_list [], + make_dict [] + |), + Constant.int 1 + |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "adjusted_exp_length" , + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + BinOp.add (| + BinOp.mult (| + Constant.int 8, + BinOp.sub (| + M.call (| + M.get_name (| globals, "int" |), + make_list [ + M.get_name (| globals, "exp_length" |) + ], + make_dict [] + |), + Constant.int 32 + |) + |), + M.call (| + M.get_name (| globals, "max" |), + make_list [ + Constant.int 0; + BinOp.sub (| + M.call (| + M.get_field (| M.get_name (| globals, "exp_head" |), "bit_length" |), + make_list [], + make_dict [] + |), + Constant.int 1 + |) + ], + make_dict [] + |) + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + )) |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + BinOp.floor_div (| + BinOp.mult (| + M.call (| + M.get_name (| globals, "get_mult_complexity" |), + make_list [ + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, "max" |), + make_list [ + M.get_name (| globals, "base_length" |); + M.get_name (| globals, "modulus_length" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |), + M.call (| + M.get_name (| globals, "max" |), + make_list [ + M.get_name (| globals, "adjusted_exp_length" |); + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 1 + ], + make_dict [] + |) + ], + make_dict [] + |) + |), + M.get_name (| globals, "GQUADDIVISOR" |) + |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + BoolOp.and (| + Compare.eq (| + M.get_name (| globals, "base_length" |), + Constant.int 0 + |), + ltac:(M.monadic ( + Compare.eq (| + M.get_name (| globals, "modulus_length" |), + Constant.int 0 + |) + )) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign (| + M.get_field (| M.get_name (| globals, "evm" |), "output" |), + M.call (| + M.get_name (| globals, "Bytes" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.return_ (| + Constant.None_ + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "base" , + M.call (| + M.get_field (| M.get_name (| globals, "Uint" |), "from_be_bytes" |), + make_list [ + M.call (| + M.get_name (| globals, "buffer_read" |), + make_list [ + M.get_name (| globals, "data" |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 96 + ], + make_dict [] + |); + M.get_name (| globals, "base_length" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "exp" , + M.call (| + M.get_field (| M.get_name (| globals, "Uint" |), "from_be_bytes" |), + make_list [ + M.call (| + M.get_name (| globals, "buffer_read" |), + make_list [ + M.get_name (| globals, "data" |); + M.get_name (| globals, "exp_start" |); + M.get_name (| globals, "exp_length" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "modulus_start" , + BinOp.add (| + M.get_name (| globals, "exp_start" |), + M.get_name (| globals, "exp_length" |) + |) + |) in + let _ := M.assign_local (| + "modulus" , + M.call (| + M.get_field (| M.get_name (| globals, "Uint" |), "from_be_bytes" |), + make_list [ + M.call (| + M.get_name (| globals, "buffer_read" |), + make_list [ + M.get_name (| globals, "data" |); + M.get_name (| globals, "modulus_start" |); + M.get_name (| globals, "modulus_length" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, "modulus" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign (| + M.get_field (| M.get_name (| globals, "evm" |), "output" |), + BinOp.mult (| + M.call (| + M.get_name (| globals, "Bytes" |), + make_list [ + Constant.bytes "00" + ], + make_dict [] + |), + M.get_name (| globals, "modulus_length" |) + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign (| + M.get_field (| M.get_name (| globals, "evm" |), "output" |), + M.call (| + M.get_field (| M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, "pow" |), + make_list [ + M.get_name (| globals, "base" |); + M.get_name (| globals, "exp" |); + M.get_name (| globals, "modulus" |) + ], + make_dict [] + |) + ], + make_dict [] + |), "to_bytes" |), + make_list [ + M.get_name (| globals, "modulus_length" |); + Constant.str "big" + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_)). + +Definition get_mult_complexity : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "x" ] |) in + let _ := Constant.str " + Estimate the complexity of performing Karatsuba multiplication. + " in + let _ := + (* if *) + M.if_then_else (| + Compare.lt_e (| + M.get_name (| globals, "x" |), + Constant.int 64 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + BinOp.pow (| + M.get_name (| globals, "x" |), + Constant.int 2 + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + Compare.lt_e (| + M.get_name (| globals, "x" |), + Constant.int 1024 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + BinOp.sub (| + BinOp.add (| + BinOp.floor_div (| + BinOp.pow (| + M.get_name (| globals, "x" |), + Constant.int 2 + |), + Constant.int 4 + |), + BinOp.mult (| + Constant.int 96, + M.get_name (| globals, "x" |) + |) + |), + Constant.int 3072 + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.return_ (| + BinOp.sub (| + BinOp.add (| + BinOp.floor_div (| + BinOp.pow (| + M.get_name (| globals, "x" |), + Constant.int 2 + |), + Constant.int 16 + |), + BinOp.mult (| + Constant.int 480, + M.get_name (| globals, "x" |) + |) + |), + Constant.int 199680 + |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_)). diff --git a/CoqOfPython/ethereum/istanbul/vm/precompiled_contracts/ripemd160.v b/CoqOfPython/ethereum/istanbul/vm/precompiled_contracts/ripemd160.v new file mode 100644 index 0000000..9355562 --- /dev/null +++ b/CoqOfPython/ethereum/istanbul/vm/precompiled_contracts/ripemd160.v @@ -0,0 +1,125 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.istanbul.vm.precompiled_contracts.ripemd160". + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) RIPEMD160 PRECOMPILED CONTRACT +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementation of the `RIPEMD160` precompiled contract. +". + +(* At top_level_stmt: unsupported node type: Import *) + +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". + +Axiom ethereum_utils_byte_imports_left_pad_zero_bytes : + IsImported globals "ethereum.utils.byte" "left_pad_zero_bytes". + +Axiom ethereum_utils_numeric_imports_ceil32 : + IsImported globals "ethereum.utils.numeric" "ceil32". + +Axiom ethereum_istanbul_vm_imports_Evm : + IsImported globals "ethereum.istanbul.vm" "Evm". + +Axiom ethereum_istanbul_vm_gas_imports_GAS_RIPEMD160 : + IsImported globals "ethereum.istanbul.vm.gas" "GAS_RIPEMD160". +Axiom ethereum_istanbul_vm_gas_imports_GAS_RIPEMD160_WORD : + IsImported globals "ethereum.istanbul.vm.gas" "GAS_RIPEMD160_WORD". +Axiom ethereum_istanbul_vm_gas_imports_charge_gas : + IsImported globals "ethereum.istanbul.vm.gas" "charge_gas". + +Definition ripemd160 : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Writes the ripemd160 hash to output. + + Parameters + ---------- + evm : + The current EVM frame. + " in + let _ := M.assign_local (| + "data" , + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "data" |) + |) in + let _ := M.assign_local (| + "word_count" , + BinOp.floor_div (| + M.call (| + M.get_name (| globals, "ceil32" |), + make_list [ + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_name (| globals, "data" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |), + Constant.int 32 + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + BinOp.add (| + M.get_name (| globals, "GAS_RIPEMD160" |), + BinOp.mult (| + M.get_name (| globals, "GAS_RIPEMD160_WORD" |), + M.get_name (| globals, "word_count" |) + |) + |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "hash_bytes" , + M.call (| + M.get_field (| M.call (| + M.get_field (| M.get_name (| globals, "hashlib" |), "new" |), + make_list [ + Constant.str "ripemd160"; + M.get_name (| globals, "data" |) + ], + make_dict [] + |), "digest" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "padded_hash" , + M.call (| + M.get_name (| globals, "left_pad_zero_bytes" |), + make_list [ + M.get_name (| globals, "hash_bytes" |); + Constant.int 32 + ], + make_dict [] + |) + |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, "evm" |), "output" |), + M.get_name (| globals, "padded_hash" |) + |) in + M.pure Constant.None_)). diff --git a/CoqOfPython/ethereum/istanbul/vm/precompiled_contracts/sha256.v b/CoqOfPython/ethereum/istanbul/vm/precompiled_contracts/sha256.v new file mode 100644 index 0000000..36128c8 --- /dev/null +++ b/CoqOfPython/ethereum/istanbul/vm/precompiled_contracts/sha256.v @@ -0,0 +1,106 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.istanbul.vm.precompiled_contracts.sha256". + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) SHA256 PRECOMPILED CONTRACT +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementation of the `SHA256` precompiled contract. +". + +(* At top_level_stmt: unsupported node type: Import *) + +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". + +Axiom ethereum_utils_numeric_imports_ceil32 : + IsImported globals "ethereum.utils.numeric" "ceil32". + +Axiom ethereum_istanbul_vm_imports_Evm : + IsImported globals "ethereum.istanbul.vm" "Evm". + +Axiom ethereum_istanbul_vm_gas_imports_GAS_SHA256 : + IsImported globals "ethereum.istanbul.vm.gas" "GAS_SHA256". +Axiom ethereum_istanbul_vm_gas_imports_GAS_SHA256_WORD : + IsImported globals "ethereum.istanbul.vm.gas" "GAS_SHA256_WORD". +Axiom ethereum_istanbul_vm_gas_imports_charge_gas : + IsImported globals "ethereum.istanbul.vm.gas" "charge_gas". + +Definition sha256 : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Writes the sha256 hash to output. + + Parameters + ---------- + evm : + The current EVM frame. + " in + let _ := M.assign_local (| + "data" , + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "data" |) + |) in + let _ := M.assign_local (| + "word_count" , + BinOp.floor_div (| + M.call (| + M.get_name (| globals, "ceil32" |), + make_list [ + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_name (| globals, "data" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |), + Constant.int 32 + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + BinOp.add (| + M.get_name (| globals, "GAS_SHA256" |), + BinOp.mult (| + M.get_name (| globals, "GAS_SHA256_WORD" |), + M.get_name (| globals, "word_count" |) + |) + |) + ], + make_dict [] + |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, "evm" |), "output" |), + M.call (| + M.get_field (| M.call (| + M.get_field (| M.get_name (| globals, "hashlib" |), "sha256" |), + make_list [ + M.get_name (| globals, "data" |) + ], + make_dict [] + |), "digest" |), + make_list [], + make_dict [] + |) + |) in + M.pure Constant.None_)). diff --git a/CoqOfPython/ethereum/istanbul/vm/runtime.v b/CoqOfPython/ethereum/istanbul/vm/runtime.v new file mode 100644 index 0000000..88abdd0 --- /dev/null +++ b/CoqOfPython/ethereum/istanbul/vm/runtime.v @@ -0,0 +1,157 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.istanbul.vm.runtime". + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) Runtime Operations +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Runtime related operations used while executing EVM code. +". + +Axiom typing_imports_Set : + IsImported globals "typing" "Set". + +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". + +Axiom ethereum_istanbul_vm_instructions_imports_Ops : + IsImported globals "ethereum.istanbul.vm.instructions" "Ops". + +Definition get_valid_jump_destinations : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "code" ] |) in + let _ := Constant.str " + Analyze the evm code to obtain the set of valid jump destinations. + + Valid jump destinations are defined as follows: + * The jump destination is less than the length of the code. + * The jump destination should have the `JUMPDEST` opcode (0x5B). + * The jump destination shouldn't be part of the data corresponding to + `PUSH-N` opcodes. + + Note - Jump destinations are 0-indexed. + + Parameters + ---------- + code : + The EVM code which is to be executed. + + Returns + ------- + valid_jump_destinations: `Set[Uint]` + The set of valid jump destinations in the code. + " in + let _ := M.assign_local (| + "valid_jump_destinations" , + M.call (| + M.get_name (| globals, "set" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "pc" , + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + |) in + let _ := + M.while (| + Compare.lt (| + M.get_name (| globals, "pc" |), + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_name (| globals, "code" |) + ], + make_dict [] + |) + |), + ltac:(M.monadic ( +(* At stmt: unsupported node type: Try *) + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, "current_opcode" |), + M.get_field (| M.get_name (| globals, "Ops" |), "JUMPDEST" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_field (| M.get_name (| globals, "valid_jump_destinations" |), "add" |), + make_list [ + M.get_name (| globals, "pc" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + BoolOp.and (| + Compare.lt_e (| + M.get_field (| M.get_field (| M.get_name (| globals, "Ops" |), "PUSH1" |), "value" |), + M.get_field (| M.get_name (| globals, "current_opcode" |), "value" |) + |), + ltac:(M.monadic ( + Compare.lt_e (| + M.get_field (| M.get_name (| globals, "current_opcode" |), "value" |), + M.get_field (| M.get_field (| M.get_name (| globals, "Ops" |), "PUSH32" |), "value" |) + |) + )) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "push_data_size" , + BinOp.add (| + BinOp.sub (| + M.get_field (| M.get_name (| globals, "current_opcode" |), "value" |), + M.get_field (| M.get_field (| M.get_name (| globals, "Ops" |), "PUSH1" |), "value" |) + |), + Constant.int 1 + |) + |) in + let _ := M.assign_op_local (| + BinOp.add, + "pc", + M.get_name (| globals, "push_data_size" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )) |) in + let _ := M.assign_op_local (| + BinOp.add, + "pc", + Constant.int 1 + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := M.return_ (| + M.get_name (| globals, "valid_jump_destinations" |) + |) in + M.pure Constant.None_)). diff --git a/CoqOfPython/ethereum/istanbul/vm/stack.v b/CoqOfPython/ethereum/istanbul/vm/stack.v new file mode 100644 index 0000000..8a72fb1 --- /dev/null +++ b/CoqOfPython/ethereum/istanbul/vm/stack.v @@ -0,0 +1,123 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.istanbul.vm.stack". + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) Stack +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementation of the stack operators for the EVM. +". + +Axiom typing_imports_List : + IsImported globals "typing" "List". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". + +Axiom ethereum_istanbul_vm_exceptions_imports_StackOverflowError : + IsImported globals "ethereum.istanbul.vm.exceptions" "StackOverflowError". +Axiom ethereum_istanbul_vm_exceptions_imports_StackUnderflowError : + IsImported globals "ethereum.istanbul.vm.exceptions" "StackUnderflowError". + +Definition pop : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "stack" ] |) in + let _ := Constant.str " + Pops the top item off of `stack`. + + Parameters + ---------- + stack : + EVM stack. + + Returns + ------- + value : `U256` + The top element on the stack. + + " in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_name (| globals, "stack" |) + ], + make_dict [] + |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, "StackUnderflowError" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.return_ (| + M.call (| + M.get_field (| M.get_name (| globals, "stack" |), "pop" |), + make_list [], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Definition push : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "stack"; "value" ] |) in + let _ := Constant.str " + Pushes `value` onto `stack`. + + Parameters + ---------- + stack : + EVM stack. + + value : + Item to be pushed onto `stack`. + + " in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_name (| globals, "stack" |) + ], + make_dict [] + |), + Constant.int 1024 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, "StackOverflowError" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.return_ (| + M.call (| + M.get_field (| M.get_name (| globals, "stack" |), "append" |), + make_list [ + M.get_name (| globals, "value" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). diff --git a/CoqOfPython/ethereum/london/__init__.v b/CoqOfPython/ethereum/london/__init__.v new file mode 100644 index 0000000..d0a16e4 --- /dev/null +++ b/CoqOfPython/ethereum/london/__init__.v @@ -0,0 +1,22 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.london.__init__". + +Definition expr_1 : Value.t := + Constant.str " +The London fork overhauls the transaction fee market, changes gas refunds, +reserves a contract prefix for future use, and delays the difficulty bomb. +". + +Axiom ethereum_fork_criteria_imports_ByBlockNumber : + IsImported globals "ethereum.fork_criteria" "ByBlockNumber". + +Definition FORK_CRITERIA : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "ByBlockNumber" |), + make_list [ + Constant.int 12965000 + ], + make_dict [] + |) +)). diff --git a/CoqOfPython/ethereum/london/blocks.v b/CoqOfPython/ethereum/london/blocks.v new file mode 100644 index 0000000..acc6316 --- /dev/null +++ b/CoqOfPython/ethereum/london/blocks.v @@ -0,0 +1,89 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.london.blocks". + +Definition expr_1 : Value.t := + Constant.str " +A `Block` is a single link in the chain that is Ethereum. Each `Block` contains +a `Header` and zero or more transactions. Each `Header` contains associated +metadata like the block number, parent block hash, and how much gas was +consumed by its transactions. + +Together, these blocks form a cryptographically secure journal recording the +history of all state transitions that have happened since the genesis of the +chain. +". + +Axiom dataclasses_imports_dataclass : + IsImported globals "dataclasses" "dataclass". + +Axiom typing_imports_Tuple : + IsImported globals "typing" "Tuple". +Axiom typing_imports_Union : + IsImported globals "typing" "Union". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_Bytes : + IsImported globals "ethereum.base_types" "Bytes". +Axiom ethereum_base_types_imports_Bytes8 : + IsImported globals "ethereum.base_types" "Bytes8". +Axiom ethereum_base_types_imports_Bytes32 : + IsImported globals "ethereum.base_types" "Bytes32". +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". +Axiom ethereum_base_types_imports_slotted_freezable : + IsImported globals "ethereum.base_types" "slotted_freezable". + +Axiom ethereum_crypto_hash_imports_Hash32 : + IsImported globals "ethereum.crypto.hash" "Hash32". + +Axiom ethereum_london_fork_types_imports_Address : + IsImported globals "ethereum.london.fork_types" "Address". +Axiom ethereum_london_fork_types_imports_Bloom : + IsImported globals "ethereum.london.fork_types" "Bloom". +Axiom ethereum_london_fork_types_imports_Root : + IsImported globals "ethereum.london.fork_types" "Root". + +Axiom ethereum_london_transactions_imports_LegacyTransaction : + IsImported globals "ethereum.london.transactions" "LegacyTransaction". + +Definition Header : Value.t := + builtins.make_klass + [] + [ + + ] + [ + + ]. + +Definition Block : Value.t := + builtins.make_klass + [] + [ + + ] + [ + + ]. + +Definition Log : Value.t := + builtins.make_klass + [] + [ + + ] + [ + + ]. + +Definition Receipt : Value.t := + builtins.make_klass + [] + [ + + ] + [ + + ]. diff --git a/CoqOfPython/ethereum/london/bloom.v b/CoqOfPython/ethereum/london/bloom.v new file mode 100644 index 0000000..ede68b4 --- /dev/null +++ b/CoqOfPython/ethereum/london/bloom.v @@ -0,0 +1,207 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.london.bloom". + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Logs Bloom +^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +This modules defines functions for calculating bloom filters of logs. For the +general theory of bloom filters see e.g. `Wikipedia +`_. Bloom filters are used to allow +for efficient searching of logs by address and/or topic, by rapidly +eliminating blocks and receipts from their search. +". + +Axiom typing_imports_Tuple : + IsImported globals "typing" "Tuple". + +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". + +Axiom ethereum_crypto_hash_imports_keccak256 : + IsImported globals "ethereum.crypto.hash" "keccak256". + +Axiom ethereum_london_blocks_imports_Log : + IsImported globals "ethereum.london.blocks" "Log". + +Axiom ethereum_london_fork_types_imports_Bloom : + IsImported globals "ethereum.london.fork_types" "Bloom". + +Definition add_to_bloom : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "bloom"; "bloom_entry" ] |) in + let _ := Constant.str " + Add a bloom entry to the bloom filter (`bloom`). + + The number of hash functions used is 3. They are calculated by taking the + least significant 11 bits from the first 3 16-bit words of the + `keccak_256()` hash of `bloom_entry`. + + Parameters + ---------- + bloom : + The bloom filter. + bloom_entry : + An entry which is to be added to bloom filter. + " in + let _ := M.assign_local (| + "hash" , + M.call (| + M.get_name (| globals, "keccak256" |), + make_list [ + M.get_name (| globals, "bloom_entry" |) + ], + make_dict [] + |) + |) in + let _ := + M.for_ (| + M.get_name (| globals, "idx" |), + make_tuple [ Constant.int 0; Constant.int 2; Constant.int 4 ], + ltac:(M.monadic ( + let _ := M.assign_local (| + "bit_to_set" , + BinOp.bit_and (| + M.call (| + M.get_field (| M.get_name (| globals, "Uint" |), "from_be_bytes" |), + make_list [ + M.slice (| + M.get_name (| globals, "hash" |), + M.get_name (| globals, "idx" |), + BinOp.add (| + M.get_name (| globals, "idx" |), + Constant.int 2 + |), + Constant.None_ + |) + ], + make_dict [] + |), + Constant.int 2047 + |) + |) in + let _ := M.assign_local (| + "bit_index" , + BinOp.sub (| + Constant.int 2047, + M.get_name (| globals, "bit_to_set" |) + |) + |) in + let _ := M.assign_local (| + "byte_index" , + BinOp.floor_div (| + M.get_name (| globals, "bit_index" |), + Constant.int 8 + |) + |) in + let _ := M.assign_local (| + "bit_value" , + BinOp.l_shift (| + Constant.int 1, + BinOp.sub (| + Constant.int 7, + BinOp.mod_ (| + M.get_name (| globals, "bit_index" |), + Constant.int 8 + |) + |) + |) + |) in + let _ := M.assign (| + M.get_subscript (| + M.get_name (| globals, "bloom" |), + M.get_name (| globals, "byte_index" |) + |), + BinOp.bit_or (| + M.get_subscript (| + M.get_name (| globals, "bloom" |), + M.get_name (| globals, "byte_index" |) + |), + M.get_name (| globals, "bit_value" |) + |) + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + M.pure Constant.None_)). + +Definition logs_bloom : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "logs" ] |) in + let _ := Constant.str " + Obtain the logs bloom from a list of log entries. + + The address and each topic of a log are added to the bloom filter. + + Parameters + ---------- + logs : + List of logs for which the logs bloom is to be obtained. + + Returns + ------- + logs_bloom : `Bloom` + The logs bloom obtained which is 256 bytes with some bits set as per + the caller address and the log topics. + " in +(* At stmt: unsupported node type: AnnAssign *) + let _ := + M.for_ (| + M.get_name (| globals, "log" |), + M.get_name (| globals, "logs" |), + ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, "add_to_bloom" |), + make_list [ + M.get_name (| globals, "bloom" |); + M.get_field (| M.get_name (| globals, "log" |), "address" |) + ], + make_dict [] + |) in + let _ := + M.for_ (| + M.get_name (| globals, "topic" |), + M.get_field (| M.get_name (| globals, "log" |), "topics" |), + ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, "add_to_bloom" |), + make_list [ + M.get_name (| globals, "bloom" |); + M.get_name (| globals, "topic" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, "Bloom" |), + make_list [ + M.get_name (| globals, "bloom" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). diff --git a/CoqOfPython/ethereum/london/fork.v b/CoqOfPython/ethereum/london/fork.v new file mode 100644 index 0000000..2a268b2 --- /dev/null +++ b/CoqOfPython/ethereum/london/fork.v @@ -0,0 +1,3389 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.london.fork". + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Specification +^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Entry point for the Ethereum specification. +". + +Axiom dataclasses_imports_dataclass : + IsImported globals "dataclasses" "dataclass". + +Axiom typing_imports_List : + IsImported globals "typing" "List". +Axiom typing_imports_Optional : + IsImported globals "typing" "Optional". +Axiom typing_imports_Set : + IsImported globals "typing" "Set". +Axiom typing_imports_Tuple : + IsImported globals "typing" "Tuple". +Axiom typing_imports_Union : + IsImported globals "typing" "Union". + +Axiom ethereum_base_types_imports_Bytes0 : + IsImported globals "ethereum.base_types" "Bytes0". + +Axiom ethereum_crypto_elliptic_curve_imports_SECP256K1N : + IsImported globals "ethereum.crypto.elliptic_curve" "SECP256K1N". +Axiom ethereum_crypto_elliptic_curve_imports_secp256k1_recover : + IsImported globals "ethereum.crypto.elliptic_curve" "secp256k1_recover". + +Axiom ethereum_crypto_hash_imports_Hash32 : + IsImported globals "ethereum.crypto.hash" "Hash32". +Axiom ethereum_crypto_hash_imports_keccak256 : + IsImported globals "ethereum.crypto.hash" "keccak256". + +Axiom ethereum_ethash_imports_dataset_size : + IsImported globals "ethereum.ethash" "dataset_size". +Axiom ethereum_ethash_imports_generate_cache : + IsImported globals "ethereum.ethash" "generate_cache". +Axiom ethereum_ethash_imports_hashimoto_light : + IsImported globals "ethereum.ethash" "hashimoto_light". + +Axiom ethereum_exceptions_imports_InvalidBlock : + IsImported globals "ethereum.exceptions" "InvalidBlock". + +Axiom ethereum_utils_ensure_imports_ensure : + IsImported globals "ethereum.utils.ensure" "ensure". + +Axiom ethereum_imports_rlp : + IsImported globals "ethereum" "rlp". + +Axiom ethereum_base_types_imports_U64 : + IsImported globals "ethereum.base_types" "U64". +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_U256_CEIL_VALUE : + IsImported globals "ethereum.base_types" "U256_CEIL_VALUE". +Axiom ethereum_base_types_imports_Bytes : + IsImported globals "ethereum.base_types" "Bytes". +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". + +Axiom ethereum_london_imports_FORK_CRITERIA : + IsImported globals "ethereum.london" "FORK_CRITERIA". +Axiom ethereum_london_imports_vm : + IsImported globals "ethereum.london" "vm". + +Axiom ethereum_london_blocks_imports_Block : + IsImported globals "ethereum.london.blocks" "Block". +Axiom ethereum_london_blocks_imports_Header : + IsImported globals "ethereum.london.blocks" "Header". +Axiom ethereum_london_blocks_imports_Log : + IsImported globals "ethereum.london.blocks" "Log". +Axiom ethereum_london_blocks_imports_Receipt : + IsImported globals "ethereum.london.blocks" "Receipt". + +Axiom ethereum_london_bloom_imports_logs_bloom : + IsImported globals "ethereum.london.bloom" "logs_bloom". + +Axiom ethereum_london_fork_types_imports_Address : + IsImported globals "ethereum.london.fork_types" "Address". +Axiom ethereum_london_fork_types_imports_Bloom : + IsImported globals "ethereum.london.fork_types" "Bloom". +Axiom ethereum_london_fork_types_imports_Root : + IsImported globals "ethereum.london.fork_types" "Root". + +Axiom ethereum_london_state_imports_State : + IsImported globals "ethereum.london.state" "State". +Axiom ethereum_london_state_imports_account_exists_and_is_empty : + IsImported globals "ethereum.london.state" "account_exists_and_is_empty". +Axiom ethereum_london_state_imports_create_ether : + IsImported globals "ethereum.london.state" "create_ether". +Axiom ethereum_london_state_imports_destroy_account : + IsImported globals "ethereum.london.state" "destroy_account". +Axiom ethereum_london_state_imports_get_account : + IsImported globals "ethereum.london.state" "get_account". +Axiom ethereum_london_state_imports_increment_nonce : + IsImported globals "ethereum.london.state" "increment_nonce". +Axiom ethereum_london_state_imports_set_account_balance : + IsImported globals "ethereum.london.state" "set_account_balance". +Axiom ethereum_london_state_imports_state_root : + IsImported globals "ethereum.london.state" "state_root". + +Axiom ethereum_london_transactions_imports_TX_ACCESS_LIST_ADDRESS_COST : + IsImported globals "ethereum.london.transactions" "TX_ACCESS_LIST_ADDRESS_COST". +Axiom ethereum_london_transactions_imports_TX_ACCESS_LIST_STORAGE_KEY_COST : + IsImported globals "ethereum.london.transactions" "TX_ACCESS_LIST_STORAGE_KEY_COST". +Axiom ethereum_london_transactions_imports_TX_BASE_COST : + IsImported globals "ethereum.london.transactions" "TX_BASE_COST". +Axiom ethereum_london_transactions_imports_TX_CREATE_COST : + IsImported globals "ethereum.london.transactions" "TX_CREATE_COST". +Axiom ethereum_london_transactions_imports_TX_DATA_COST_PER_NON_ZERO : + IsImported globals "ethereum.london.transactions" "TX_DATA_COST_PER_NON_ZERO". +Axiom ethereum_london_transactions_imports_TX_DATA_COST_PER_ZERO : + IsImported globals "ethereum.london.transactions" "TX_DATA_COST_PER_ZERO". +Axiom ethereum_london_transactions_imports_AccessListTransaction : + IsImported globals "ethereum.london.transactions" "AccessListTransaction". +Axiom ethereum_london_transactions_imports_FeeMarketTransaction : + IsImported globals "ethereum.london.transactions" "FeeMarketTransaction". +Axiom ethereum_london_transactions_imports_LegacyTransaction : + IsImported globals "ethereum.london.transactions" "LegacyTransaction". +Axiom ethereum_london_transactions_imports_Transaction : + IsImported globals "ethereum.london.transactions" "Transaction". +Axiom ethereum_london_transactions_imports_decode_transaction : + IsImported globals "ethereum.london.transactions" "decode_transaction". +Axiom ethereum_london_transactions_imports_encode_transaction : + IsImported globals "ethereum.london.transactions" "encode_transaction". + +Axiom ethereum_london_trie_imports_Trie : + IsImported globals "ethereum.london.trie" "Trie". +Axiom ethereum_london_trie_imports_root : + IsImported globals "ethereum.london.trie" "root". +Axiom ethereum_london_trie_imports_trie_set : + IsImported globals "ethereum.london.trie" "trie_set". + +Axiom ethereum_london_utils_message_imports_prepare_message : + IsImported globals "ethereum.london.utils.message" "prepare_message". + +Axiom ethereum_london_vm_interpreter_imports_process_message_call : + IsImported globals "ethereum.london.vm.interpreter" "process_message_call". + +Definition BLOCK_REWARD : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + BinOp.mult (| + Constant.int 2, + BinOp.pow (| + Constant.int 10, + Constant.int 18 + |) + |) + ], + make_dict [] + |) +)). + +Definition BASE_FEE_MAX_CHANGE_DENOMINATOR : Value.t := M.run ltac:(M.monadic ( + Constant.int 8 +)). + +Definition ELASTICITY_MULTIPLIER : Value.t := M.run ltac:(M.monadic ( + Constant.int 2 +)). + +Definition GAS_LIMIT_ADJUSTMENT_FACTOR : Value.t := M.run ltac:(M.monadic ( + Constant.int 1024 +)). + +Definition GAS_LIMIT_MINIMUM : Value.t := M.run ltac:(M.monadic ( + Constant.int 5000 +)). + +Definition MINIMUM_DIFFICULTY : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 131072 + ], + make_dict [] + |) +)). + +Definition INITIAL_BASE_FEE : Value.t := M.run ltac:(M.monadic ( + Constant.int 1000000000 +)). + +Definition MAX_OMMER_DEPTH : Value.t := M.run ltac:(M.monadic ( + Constant.int 6 +)). + +Definition BOMB_DELAY_BLOCKS : Value.t := M.run ltac:(M.monadic ( + Constant.int 9700000 +)). + +Definition EMPTY_OMMER_HASH : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "keccak256" |), + make_list [ + M.call (| + M.get_field (| M.get_name (| globals, "rlp" |), "encode" |), + make_list [ + make_list [] + ], + make_dict [] + |) + ], + make_dict [] + |) +)). + +Definition BlockChain : Value.t := + builtins.make_klass + [] + [ + + ] + [ + + ]. + +Definition apply_fork : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "old" ] |) in + let _ := Constant.str " + Transforms the state from the previous hard fork (`old`) into the block + chain object for this hard fork and returns it. + + When forks need to implement an irregular state transition, this function + is used to handle the irregularity. See the :ref:`DAO Fork ` for + an example. + + Parameters + ---------- + old : + Previous block chain object. + + Returns + ------- + new : `BlockChain` + Upgraded block chain object for this hard fork. + " in + let _ := M.return_ (| + M.get_name (| globals, "old" |) + |) in + M.pure Constant.None_)). + +Definition get_last_256_block_hashes : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "chain" ] |) in + let _ := Constant.str " + Obtain the list of hashes of the previous 256 blocks in order of + increasing block number. + + This function will return less hashes for the first 256 blocks. + + The ``BLOCKHASH`` opcode needs to access the latest hashes on the chain, + therefore this function retrieves them. + + Parameters + ---------- + chain : + History and current state. + + Returns + ------- + recent_block_hashes : `List[Hash32]` + Hashes of the recent 256 blocks in order of increasing block number. + " in + let _ := M.assign_local (| + "recent_blocks" , + M.slice (| + M.get_field (| M.get_name (| globals, "chain" |), "blocks" |), + UnOp.sub (| Constant.int 255 |), + Constant.None_, + Constant.None_ + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_name (| globals, "recent_blocks" |) + ], + make_dict [] + |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + make_list [] + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "recent_block_hashes" , + make_list [] + |) in + let _ := + M.for_ (| + M.get_name (| globals, "block" |), + M.get_name (| globals, "recent_blocks" |), + ltac:(M.monadic ( + let _ := M.assign_local (| + "prev_block_hash" , + M.get_field (| M.get_field (| M.get_name (| globals, "block" |), "header" |), "parent_hash" |) + |) in + let _ := M.call (| + M.get_field (| M.get_name (| globals, "recent_block_hashes" |), "append" |), + make_list [ + M.get_name (| globals, "prev_block_hash" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := M.assign_local (| + "most_recent_block_hash" , + M.call (| + M.get_name (| globals, "keccak256" |), + make_list [ + M.call (| + M.get_field (| M.get_name (| globals, "rlp" |), "encode" |), + make_list [ + M.get_field (| M.get_subscript (| + M.get_name (| globals, "recent_blocks" |), + UnOp.sub (| Constant.int 1 |) + |), "header" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_field (| M.get_name (| globals, "recent_block_hashes" |), "append" |), + make_list [ + M.get_name (| globals, "most_recent_block_hash" |) + ], + make_dict [] + |) in + let _ := M.return_ (| + M.get_name (| globals, "recent_block_hashes" |) + |) in + M.pure Constant.None_)). + +Definition state_transition : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "chain"; "block" ] |) in + let _ := Constant.str " + Attempts to apply a block to an existing block chain. + + All parts of the block's contents need to be verified before being added + to the chain. Blocks are verified by ensuring that the contents of the + block make logical sense with the contents of the parent block. The + information in the block's header must also match the corresponding + information in the block. + + To implement Ethereum, in theory clients are only required to store the + most recent 255 blocks of the chain since as far as execution is + concerned, only those blocks are accessed. Practically, however, clients + should store more blocks to handle reorgs. + + Parameters + ---------- + chain : + History and current state. + block : + Block to apply to `chain`. + " in + let _ := M.assign_local (| + "parent_header" , + M.get_field (| M.get_subscript (| + M.get_field (| M.get_name (| globals, "chain" |), "blocks" |), + UnOp.sub (| Constant.int 1 |) + |), "header" |) + |) in + let _ := M.call (| + M.get_name (| globals, "validate_header" |), + make_list [ + M.get_field (| M.get_name (| globals, "block" |), "header" |); + M.get_name (| globals, "parent_header" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "validate_ommers" |), + make_list [ + M.get_field (| M.get_name (| globals, "block" |), "ommers" |); + M.get_field (| M.get_name (| globals, "block" |), "header" |); + M.get_name (| globals, "chain" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "apply_body_output" , + M.call (| + M.get_name (| globals, "apply_body" |), + make_list [ + M.get_field (| M.get_name (| globals, "chain" |), "state" |); + M.call (| + M.get_name (| globals, "get_last_256_block_hashes" |), + make_list [ + M.get_name (| globals, "chain" |) + ], + make_dict [] + |); + M.get_field (| M.get_field (| M.get_name (| globals, "block" |), "header" |), "coinbase" |); + M.get_field (| M.get_field (| M.get_name (| globals, "block" |), "header" |), "number" |); + M.get_field (| M.get_field (| M.get_name (| globals, "block" |), "header" |), "base_fee_per_gas" |); + M.get_field (| M.get_field (| M.get_name (| globals, "block" |), "header" |), "gas_limit" |); + M.get_field (| M.get_field (| M.get_name (| globals, "block" |), "header" |), "timestamp" |); + M.get_field (| M.get_field (| M.get_name (| globals, "block" |), "header" |), "difficulty" |); + M.get_field (| M.get_name (| globals, "block" |), "transactions" |); + M.get_field (| M.get_name (| globals, "block" |), "ommers" |); + M.get_field (| M.get_name (| globals, "chain" |), "chain_id" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + Compare.eq (| + M.get_field (| M.get_name (| globals, "apply_body_output" |), "block_gas_used" |), + M.get_field (| M.get_field (| M.get_name (| globals, "block" |), "header" |), "gas_used" |) + |); + M.get_name (| globals, "InvalidBlock" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + Compare.eq (| + M.get_field (| M.get_name (| globals, "apply_body_output" |), "transactions_root" |), + M.get_field (| M.get_field (| M.get_name (| globals, "block" |), "header" |), "transactions_root" |) + |); + M.get_name (| globals, "InvalidBlock" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + Compare.eq (| + M.get_field (| M.get_name (| globals, "apply_body_output" |), "state_root" |), + M.get_field (| M.get_field (| M.get_name (| globals, "block" |), "header" |), "state_root" |) + |); + M.get_name (| globals, "InvalidBlock" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + Compare.eq (| + M.get_field (| M.get_name (| globals, "apply_body_output" |), "receipt_root" |), + M.get_field (| M.get_field (| M.get_name (| globals, "block" |), "header" |), "receipt_root" |) + |); + M.get_name (| globals, "InvalidBlock" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + Compare.eq (| + M.get_field (| M.get_name (| globals, "apply_body_output" |), "block_logs_bloom" |), + M.get_field (| M.get_field (| M.get_name (| globals, "block" |), "header" |), "bloom" |) + |); + M.get_name (| globals, "InvalidBlock" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, "chain" |), "blocks" |), "append" |), + make_list [ + M.get_name (| globals, "block" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.gt (| + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_field (| M.get_name (| globals, "chain" |), "blocks" |) + ], + make_dict [] + |), + Constant.int 255 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign (| + M.get_field (| M.get_name (| globals, "chain" |), "blocks" |), + M.slice (| + M.get_field (| M.get_name (| globals, "chain" |), "blocks" |), + UnOp.sub (| Constant.int 255 |), + Constant.None_, + Constant.None_ + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + M.pure Constant.None_)). + +Definition calculate_base_fee_per_gas : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "block_gas_limit"; "parent_gas_limit"; "parent_gas_used"; "parent_base_fee_per_gas"; "is_fork_block" ] |) in + let _ := Constant.str " + Calculates the base fee per gas for the block. + + Parameters + ---------- + block_gas_limit : + Gas limit of the block for which the base fee is being calculated. + parent_gas_limit : + Gas limit of the parent block. + parent_gas_used : + Gas used in the parent block. + parent_base_fee_per_gas : + Base fee per gas of the parent block. + is_fork_block : + Whether the block is the fork block. + + Returns + ------- + base_fee_per_gas : `Uint` + Base fee per gas for the block. + " in + let _ := + (* if *) + M.if_then_else (| + M.get_name (| globals, "is_fork_block" |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.get_name (| globals, "INITIAL_BASE_FEE" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "parent_gas_target" , + BinOp.floor_div (| + M.get_name (| globals, "parent_gas_limit" |), + M.get_name (| globals, "ELASTICITY_MULTIPLIER" |) + |) + |) in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + M.call (| + M.get_name (| globals, "check_gas_limit" |), + make_list [ + M.get_name (| globals, "block_gas_limit" |); + M.get_name (| globals, "parent_gas_limit" |) + ], + make_dict [] + |); + M.get_name (| globals, "InvalidBlock" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, "parent_gas_used" |), + M.get_name (| globals, "parent_gas_target" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "expected_base_fee_per_gas" , + M.get_name (| globals, "parent_base_fee_per_gas" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + Compare.gt (| + M.get_name (| globals, "parent_gas_used" |), + M.get_name (| globals, "parent_gas_target" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "gas_used_delta" , + BinOp.sub (| + M.get_name (| globals, "parent_gas_used" |), + M.get_name (| globals, "parent_gas_target" |) + |) + |) in + let _ := M.assign_local (| + "parent_fee_gas_delta" , + BinOp.mult (| + M.get_name (| globals, "parent_base_fee_per_gas" |), + M.get_name (| globals, "gas_used_delta" |) + |) + |) in + let _ := M.assign_local (| + "target_fee_gas_delta" , + BinOp.floor_div (| + M.get_name (| globals, "parent_fee_gas_delta" |), + M.get_name (| globals, "parent_gas_target" |) + |) + |) in + let _ := M.assign_local (| + "base_fee_per_gas_delta" , + M.call (| + M.get_name (| globals, "max" |), + make_list [ + BinOp.floor_div (| + M.get_name (| globals, "target_fee_gas_delta" |), + M.get_name (| globals, "BASE_FEE_MAX_CHANGE_DENOMINATOR" |) + |); + Constant.int 1 + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "expected_base_fee_per_gas" , + BinOp.add (| + M.get_name (| globals, "parent_base_fee_per_gas" |), + M.get_name (| globals, "base_fee_per_gas_delta" |) + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "gas_used_delta" , + BinOp.sub (| + M.get_name (| globals, "parent_gas_target" |), + M.get_name (| globals, "parent_gas_used" |) + |) + |) in + let _ := M.assign_local (| + "parent_fee_gas_delta" , + BinOp.mult (| + M.get_name (| globals, "parent_base_fee_per_gas" |), + M.get_name (| globals, "gas_used_delta" |) + |) + |) in + let _ := M.assign_local (| + "target_fee_gas_delta" , + BinOp.floor_div (| + M.get_name (| globals, "parent_fee_gas_delta" |), + M.get_name (| globals, "parent_gas_target" |) + |) + |) in + let _ := M.assign_local (| + "base_fee_per_gas_delta" , + BinOp.floor_div (| + M.get_name (| globals, "target_fee_gas_delta" |), + M.get_name (| globals, "BASE_FEE_MAX_CHANGE_DENOMINATOR" |) + |) + |) in + let _ := M.assign_local (| + "expected_base_fee_per_gas" , + BinOp.sub (| + M.get_name (| globals, "parent_base_fee_per_gas" |), + M.get_name (| globals, "base_fee_per_gas_delta" |) + |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )) |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.get_name (| globals, "expected_base_fee_per_gas" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Definition validate_header : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "header"; "parent_header" ] |) in + let _ := Constant.str " + Verifies a block header. + + In order to consider a block's header valid, the logic for the + quantities in the header should match the logic for the block itself. + For example the header timestamp should be greater than the block's parent + timestamp because the block was created *after* the parent block. + Additionally, the block's number should be directly following the parent + block's number since it is the next block in the sequence. + + Parameters + ---------- + header : + Header to check for correctness. + parent_header : + Parent Header of the header to check for correctness + " in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + Compare.lt_e (| + M.get_field (| M.get_name (| globals, "header" |), "gas_used" |), + M.get_field (| M.get_name (| globals, "header" |), "gas_limit" |) + |); + M.get_name (| globals, "InvalidBlock" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "is_fork_block" , + Compare.eq (| + M.get_field (| M.get_name (| globals, "header" |), "number" |), + M.get_field (| M.get_name (| globals, "FORK_CRITERIA" |), "block_number" |) + |) + |) in + let _ := M.assign_local (| + "expected_base_fee_per_gas" , + M.call (| + M.get_name (| globals, "calculate_base_fee_per_gas" |), + make_list [ + M.get_field (| M.get_name (| globals, "header" |), "gas_limit" |); + M.get_field (| M.get_name (| globals, "parent_header" |), "gas_limit" |); + M.get_field (| M.get_name (| globals, "parent_header" |), "gas_used" |); + M.get_field (| M.get_name (| globals, "parent_header" |), "base_fee_per_gas" |); + M.get_name (| globals, "is_fork_block" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + Compare.eq (| + M.get_name (| globals, "expected_base_fee_per_gas" |), + M.get_field (| M.get_name (| globals, "header" |), "base_fee_per_gas" |) + |); + M.get_name (| globals, "InvalidBlock" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "parent_has_ommers" , + Compare.not_eq (| + M.get_field (| M.get_name (| globals, "parent_header" |), "ommers_hash" |), + M.get_name (| globals, "EMPTY_OMMER_HASH" |) + |) + |) in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + Compare.gt (| + M.get_field (| M.get_name (| globals, "header" |), "timestamp" |), + M.get_field (| M.get_name (| globals, "parent_header" |), "timestamp" |) + |); + M.get_name (| globals, "InvalidBlock" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + Compare.eq (| + M.get_field (| M.get_name (| globals, "header" |), "number" |), + BinOp.add (| + M.get_field (| M.get_name (| globals, "parent_header" |), "number" |), + Constant.int 1 + |) + |); + M.get_name (| globals, "InvalidBlock" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + Compare.lt_e (| + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_field (| M.get_name (| globals, "header" |), "extra_data" |) + ], + make_dict [] + |), + Constant.int 32 + |); + M.get_name (| globals, "InvalidBlock" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "block_difficulty" , + M.call (| + M.get_name (| globals, "calculate_block_difficulty" |), + make_list [ + M.get_field (| M.get_name (| globals, "header" |), "number" |); + M.get_field (| M.get_name (| globals, "header" |), "timestamp" |); + M.get_field (| M.get_name (| globals, "parent_header" |), "timestamp" |); + M.get_field (| M.get_name (| globals, "parent_header" |), "difficulty" |); + M.get_name (| globals, "parent_has_ommers" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + Compare.eq (| + M.get_field (| M.get_name (| globals, "header" |), "difficulty" |), + M.get_name (| globals, "block_difficulty" |) + |); + M.get_name (| globals, "InvalidBlock" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "block_parent_hash" , + M.call (| + M.get_name (| globals, "keccak256" |), + make_list [ + M.call (| + M.get_field (| M.get_name (| globals, "rlp" |), "encode" |), + make_list [ + M.get_name (| globals, "parent_header" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + Compare.eq (| + M.get_field (| M.get_name (| globals, "header" |), "parent_hash" |), + M.get_name (| globals, "block_parent_hash" |) + |); + M.get_name (| globals, "InvalidBlock" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "validate_proof_of_work" |), + make_list [ + M.get_name (| globals, "header" |) + ], + make_dict [] + |) in + M.pure Constant.None_)). + +Definition generate_header_hash_for_pow : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "header" ] |) in + let _ := Constant.str " + Generate rlp hash of the header which is to be used for Proof-of-Work + verification. + + In other words, the PoW artefacts `mix_digest` and `nonce` are ignored + while calculating this hash. + + A particular PoW is valid for a single hash, that hash is computed by + this function. The `nonce` and `mix_digest` are omitted from this hash + because they are being changed by miners in their search for a sufficient + proof-of-work. + + Parameters + ---------- + header : + The header object for which the hash is to be generated. + + Returns + ------- + hash : `Hash32` + The PoW valid rlp hash of the passed in header. + " in + let _ := M.assign_local (| + "header_data_without_pow_artefacts" , + make_list [ + M.get_field (| M.get_name (| globals, "header" |), "parent_hash" |); + M.get_field (| M.get_name (| globals, "header" |), "ommers_hash" |); + M.get_field (| M.get_name (| globals, "header" |), "coinbase" |); + M.get_field (| M.get_name (| globals, "header" |), "state_root" |); + M.get_field (| M.get_name (| globals, "header" |), "transactions_root" |); + M.get_field (| M.get_name (| globals, "header" |), "receipt_root" |); + M.get_field (| M.get_name (| globals, "header" |), "bloom" |); + M.get_field (| M.get_name (| globals, "header" |), "difficulty" |); + M.get_field (| M.get_name (| globals, "header" |), "number" |); + M.get_field (| M.get_name (| globals, "header" |), "gas_limit" |); + M.get_field (| M.get_name (| globals, "header" |), "gas_used" |); + M.get_field (| M.get_name (| globals, "header" |), "timestamp" |); + M.get_field (| M.get_name (| globals, "header" |), "extra_data" |); + M.get_field (| M.get_name (| globals, "header" |), "base_fee_per_gas" |) + ] + |) in + let _ := M.return_ (| + M.call (| + M.get_field (| M.get_name (| globals, "rlp" |), "rlp_hash" |), + make_list [ + M.get_name (| globals, "header_data_without_pow_artefacts" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Definition validate_proof_of_work : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "header" ] |) in + let _ := Constant.str " + Validates the Proof of Work constraints. + + In order to verify that a miner's proof-of-work is valid for a block, a + ``mix-digest`` and ``result`` are calculated using the ``hashimoto_light`` + hash function. The mix digest is a hash of the header and the nonce that + is passed through and it confirms whether or not proof-of-work was done + on the correct block. The result is the actual hash value of the block. + + Parameters + ---------- + header : + Header of interest. + " in + let _ := M.assign_local (| + "header_hash" , + M.call (| + M.get_name (| globals, "generate_header_hash_for_pow" |), + make_list [ + M.get_name (| globals, "header" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "cache" , + M.call (| + M.get_name (| globals, "generate_cache" |), + make_list [ + M.get_field (| M.get_name (| globals, "header" |), "number" |) + ], + make_dict [] + |) + |) in + let _ := M.assign (| + make_tuple [ M.get_name (| globals, "mix_digest" |); M.get_name (| globals, "result" |) ], + M.call (| + M.get_name (| globals, "hashimoto_light" |), + make_list [ + M.get_name (| globals, "header_hash" |); + M.get_field (| M.get_name (| globals, "header" |), "nonce" |); + M.get_name (| globals, "cache" |); + M.call (| + M.get_name (| globals, "dataset_size" |), + make_list [ + M.get_field (| M.get_name (| globals, "header" |), "number" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + Compare.eq (| + M.get_name (| globals, "mix_digest" |), + M.get_field (| M.get_name (| globals, "header" |), "mix_digest" |) + |); + M.get_name (| globals, "InvalidBlock" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + Compare.lt_e (| + M.call (| + M.get_field (| M.get_name (| globals, "Uint" |), "from_be_bytes" |), + make_list [ + M.get_name (| globals, "result" |) + ], + make_dict [] + |), + BinOp.floor_div (| + M.get_name (| globals, "U256_CEIL_VALUE" |), + M.get_field (| M.get_name (| globals, "header" |), "difficulty" |) + |) + |); + M.get_name (| globals, "InvalidBlock" |) + ], + make_dict [] + |) in + M.pure Constant.None_)). + +Definition check_transaction : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "tx"; "base_fee_per_gas"; "gas_available"; "chain_id" ] |) in + let _ := Constant.str " + Check if the transaction is includable in the block. + + Parameters + ---------- + tx : + The transaction. + base_fee_per_gas : + The block base fee. + gas_available : + The gas remaining in the block. + chain_id : + The ID of the current chain. + + Returns + ------- + sender_address : + The sender of the transaction. + effective_gas_price : + The price to charge for gas when the transaction is executed. + + Raises + ------ + InvalidBlock : + If the transaction is not includable. + " in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + Compare.lt_e (| + M.get_field (| M.get_name (| globals, "tx" |), "gas" |), + M.get_name (| globals, "gas_available" |) + |); + M.get_name (| globals, "InvalidBlock" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "sender_address" , + M.call (| + M.get_name (| globals, "recover_sender" |), + make_list [ + M.get_name (| globals, "chain_id" |); + M.get_name (| globals, "tx" |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, "isinstance" |), + make_list [ + M.get_name (| globals, "tx" |); + M.get_name (| globals, "FeeMarketTransaction" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + Compare.gt_e (| + M.get_field (| M.get_name (| globals, "tx" |), "max_fee_per_gas" |), + M.get_field (| M.get_name (| globals, "tx" |), "max_priority_fee_per_gas" |) + |); + M.get_name (| globals, "InvalidBlock" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + Compare.gt_e (| + M.get_field (| M.get_name (| globals, "tx" |), "max_fee_per_gas" |), + M.get_name (| globals, "base_fee_per_gas" |) + |); + M.get_name (| globals, "InvalidBlock" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "priority_fee_per_gas" , + M.call (| + M.get_name (| globals, "min" |), + make_list [ + M.get_field (| M.get_name (| globals, "tx" |), "max_priority_fee_per_gas" |); + BinOp.sub (| + M.get_field (| M.get_name (| globals, "tx" |), "max_fee_per_gas" |), + M.get_name (| globals, "base_fee_per_gas" |) + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "effective_gas_price" , + BinOp.add (| + M.get_name (| globals, "priority_fee_per_gas" |), + M.get_name (| globals, "base_fee_per_gas" |) + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + Compare.gt_e (| + M.get_field (| M.get_name (| globals, "tx" |), "gas_price" |), + M.get_name (| globals, "base_fee_per_gas" |) + |); + M.get_name (| globals, "InvalidBlock" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "effective_gas_price" , + M.get_field (| M.get_name (| globals, "tx" |), "gas_price" |) + |) in + M.pure Constant.None_ + )) |) in + let _ := M.return_ (| + make_tuple [ M.get_name (| globals, "sender_address" |); M.get_name (| globals, "effective_gas_price" |) ] + |) in + M.pure Constant.None_)). + +Definition make_receipt : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "tx"; "error"; "cumulative_gas_used"; "logs" ] |) in + let _ := Constant.str " + Make the receipt for a transaction that was executed. + + Parameters + ---------- + tx : + The executed transaction. + error : + Error in the top level frame of the transaction, if any. + cumulative_gas_used : + The total gas used so far in the block after the transaction was + executed. + logs : + The logs produced by the transaction. + + Returns + ------- + receipt : + The receipt for the transaction. + " in + let _ := M.assign_local (| + "receipt" , + M.call (| + M.get_name (| globals, "Receipt" |), + make_list [], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, "isinstance" |), + make_list [ + M.get_name (| globals, "tx" |); + M.get_name (| globals, "AccessListTransaction" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + BinOp.add (| + Constant.bytes "01", + M.call (| + M.get_field (| M.get_name (| globals, "rlp" |), "encode" |), + make_list [ + M.get_name (| globals, "receipt" |) + ], + make_dict [] + |) + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, "isinstance" |), + make_list [ + M.get_name (| globals, "tx" |); + M.get_name (| globals, "FeeMarketTransaction" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + BinOp.add (| + Constant.bytes "02", + M.call (| + M.get_field (| M.get_name (| globals, "rlp" |), "encode" |), + make_list [ + M.get_name (| globals, "receipt" |) + ], + make_dict [] + |) + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.return_ (| + M.get_name (| globals, "receipt" |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_)). + +Definition ApplyBodyOutput : Value.t := + builtins.make_klass + [] + [ + + ] + [ + + ]. + +Definition apply_body : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "state"; "block_hashes"; "coinbase"; "block_number"; "base_fee_per_gas"; "block_gas_limit"; "block_time"; "block_difficulty"; "transactions"; "ommers"; "chain_id" ] |) in + let _ := Constant.str " + Executes a block. + + Many of the contents of a block are stored in data structures called + tries. There is a transactions trie which is similar to a ledger of the + transactions stored in the current block. There is also a receipts trie + which stores the results of executing a transaction, like the post state + and gas used. This function creates and executes the block that is to be + added to the chain. + + Parameters + ---------- + state : + Current account state. + block_hashes : + List of hashes of the previous 256 blocks in the order of + increasing block number. + coinbase : + Address of account which receives block reward and transaction fees. + block_number : + Position of the block within the chain. + base_fee_per_gas : + Base fee per gas of within the block. + block_gas_limit : + Initial amount of gas available for execution in this block. + block_time : + Time the block was produced, measured in seconds since the epoch. + block_difficulty : + Difficulty of the block. + transactions : + Transactions included in the block. + ommers : + Headers of ancestor blocks which are not direct parents (formerly + uncles.) + chain_id : + ID of the executing chain. + + Returns + ------- + apply_body_output : `ApplyBodyOutput` + Output of applying the block body to the state. + " in + let _ := M.assign_local (| + "gas_available" , + M.get_name (| globals, "block_gas_limit" |) + |) in +(* At stmt: unsupported node type: AnnAssign *) +(* At stmt: unsupported node type: AnnAssign *) +(* At stmt: unsupported node type: AnnAssign *) + let _ := + M.for_ (| + make_tuple [ M.get_name (| globals, "i" |); M.get_name (| globals, "tx" |) ], + M.call (| + M.get_name (| globals, "enumerate" |), + make_list [ + M.call (| + M.get_name (| globals, "map" |), + make_list [ + M.get_name (| globals, "decode_transaction" |); + M.get_name (| globals, "transactions" |) + ], + make_dict [] + |) + ], + make_dict [] + |), + ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, "trie_set" |), + make_list [ + M.get_name (| globals, "transactions_trie" |); + M.call (| + M.get_field (| M.get_name (| globals, "rlp" |), "encode" |), + make_list [ + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.get_name (| globals, "i" |) + ], + make_dict [] + |) + ], + make_dict [] + |); + M.call (| + M.get_name (| globals, "encode_transaction" |), + make_list [ + M.get_name (| globals, "tx" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign (| + make_tuple [ M.get_name (| globals, "sender_address" |); M.get_name (| globals, "effective_gas_price" |) ], + M.call (| + M.get_name (| globals, "check_transaction" |), + make_list [ + M.get_name (| globals, "tx" |); + M.get_name (| globals, "base_fee_per_gas" |); + M.get_name (| globals, "gas_available" |); + M.get_name (| globals, "chain_id" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "env" , + M.call (| + M.get_field (| M.get_name (| globals, "vm" |), "Environment" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.assign (| + make_tuple [ M.get_name (| globals, "gas_used" |); M.get_name (| globals, "logs" |); M.get_name (| globals, "error" |) ], + M.call (| + M.get_name (| globals, "process_transaction" |), + make_list [ + M.get_name (| globals, "env" |); + M.get_name (| globals, "tx" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_op_local (| + BinOp.sub, + "gas_available", + M.get_name (| globals, "gas_used" |) + |) in + let _ := M.assign_local (| + "receipt" , + M.call (| + M.get_name (| globals, "make_receipt" |), + make_list [ + M.get_name (| globals, "tx" |); + M.get_name (| globals, "error" |); + BinOp.sub (| + M.get_name (| globals, "block_gas_limit" |), + M.get_name (| globals, "gas_available" |) + |); + M.get_name (| globals, "logs" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "trie_set" |), + make_list [ + M.get_name (| globals, "receipts_trie" |); + M.call (| + M.get_field (| M.get_name (| globals, "rlp" |), "encode" |), + make_list [ + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.get_name (| globals, "i" |) + ], + make_dict [] + |) + ], + make_dict [] + |); + M.get_name (| globals, "receipt" |) + ], + make_dict [] + |) in + let _ := M.assign_op_local (| + BinOp.add, + "block_logs", + M.get_name (| globals, "logs" |) + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := M.call (| + M.get_name (| globals, "pay_rewards" |), + make_list [ + M.get_name (| globals, "state" |); + M.get_name (| globals, "block_number" |); + M.get_name (| globals, "coinbase" |); + M.get_name (| globals, "ommers" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "block_gas_used" , + BinOp.sub (| + M.get_name (| globals, "block_gas_limit" |), + M.get_name (| globals, "gas_available" |) + |) + |) in + let _ := M.assign_local (| + "block_logs_bloom" , + M.call (| + M.get_name (| globals, "logs_bloom" |), + make_list [ + M.get_name (| globals, "block_logs" |) + ], + make_dict [] + |) + |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, "ApplyBodyOutput" |), + make_list [ + M.get_name (| globals, "block_gas_used" |); + M.call (| + M.get_name (| globals, "root" |), + make_list [ + M.get_name (| globals, "transactions_trie" |) + ], + make_dict [] + |); + M.call (| + M.get_name (| globals, "root" |), + make_list [ + M.get_name (| globals, "receipts_trie" |) + ], + make_dict [] + |); + M.get_name (| globals, "block_logs_bloom" |); + M.call (| + M.get_name (| globals, "state_root" |), + make_list [ + M.get_name (| globals, "state" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Definition validate_ommers : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "ommers"; "block_header"; "chain" ] |) in + let _ := Constant.str " + Validates the ommers mentioned in the block. + + An ommer block is a block that wasn't canonically added to the + blockchain because it wasn't validated as fast as the canonical block + but was mined at the same time. + + To be considered valid, the ommers must adhere to the rules defined in + the Ethereum protocol. The maximum amount of ommers is 2 per block and + there cannot be duplicate ommers in a block. Many of the other ommer + constraints are listed in the in-line comments of this function. + + Parameters + ---------- + ommers : + List of ommers mentioned in the current block. + block_header: + The header of current block. + chain : + History and current state. + " in + let _ := M.assign_local (| + "block_hash" , + M.call (| + M.get_field (| M.get_name (| globals, "rlp" |), "rlp_hash" |), + make_list [ + M.get_name (| globals, "block_header" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + Compare.eq (| + M.call (| + M.get_field (| M.get_name (| globals, "rlp" |), "rlp_hash" |), + make_list [ + M.get_name (| globals, "ommers" |) + ], + make_dict [] + |), + M.get_field (| M.get_name (| globals, "block_header" |), "ommers_hash" |) + |); + M.get_name (| globals, "InvalidBlock" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_name (| globals, "ommers" |) + ], + make_dict [] + |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + Constant.None_ + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + M.for_ (| + M.get_name (| globals, "ommer" |), + M.get_name (| globals, "ommers" |), + ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + BoolOp.and (| + Compare.lt_e (| + Constant.int 1, + M.get_field (| M.get_name (| globals, "ommer" |), "number" |) + |), + ltac:(M.monadic ( + Compare.lt (| + M.get_field (| M.get_name (| globals, "ommer" |), "number" |), + M.get_field (| M.get_name (| globals, "block_header" |), "number" |) + |) + )) + |); + M.get_name (| globals, "InvalidBlock" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "ommer_parent_header" , + M.get_field (| M.get_subscript (| + M.get_field (| M.get_name (| globals, "chain" |), "blocks" |), + BinOp.sub (| + UnOp.sub (| BinOp.sub (| + M.get_field (| M.get_name (| globals, "block_header" |), "number" |), + M.get_field (| M.get_name (| globals, "ommer" |), "number" |) + |) |), + Constant.int 1 + |) + |), "header" |) + |) in + let _ := M.call (| + M.get_name (| globals, "validate_header" |), + make_list [ + M.get_name (| globals, "ommer" |); + M.get_name (| globals, "ommer_parent_header" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + Compare.lt_e (| + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_name (| globals, "ommers" |) + ], + make_dict [] + |), + Constant.int 2 + |); + M.get_name (| globals, "InvalidBlock" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "ommers_hashes" , + Constant.str "(* At expr: unsupported node type: ListComp *)" + |) in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + Compare.eq (| + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_name (| globals, "ommers_hashes" |) + ], + make_dict [] + |), + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.call (| + M.get_name (| globals, "set" |), + make_list [ + M.get_name (| globals, "ommers_hashes" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |); + M.get_name (| globals, "InvalidBlock" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "recent_canonical_blocks" , + M.slice (| + M.get_field (| M.get_name (| globals, "chain" |), "blocks" |), + UnOp.sub (| BinOp.add (| + M.get_name (| globals, "MAX_OMMER_DEPTH" |), + Constant.int 1 + |) |), + Constant.None_, + Constant.None_ + |) + |) in + let _ := M.assign_local (| + "recent_canonical_block_hashes" , + Constant.str "(* At expr: unsupported node type: SetComp *)" + |) in +(* At stmt: unsupported node type: AnnAssign *) + let _ := + M.for_ (| + M.get_name (| globals, "block" |), + M.get_name (| globals, "recent_canonical_blocks" |), + ltac:(M.monadic ( + let _ := M.assign_local (| + "recent_ommers_hashes" , + M.call (| + M.get_field (| M.get_name (| globals, "recent_ommers_hashes" |), "union" |), + make_list [ + Constant.str "(* At expr: unsupported node type: SetComp *)" + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := + M.for_ (| + make_tuple [ M.get_name (| globals, "ommer_index" |); M.get_name (| globals, "ommer" |) ], + M.call (| + M.get_name (| globals, "enumerate" |), + make_list [ + M.get_name (| globals, "ommers" |) + ], + make_dict [] + |), + ltac:(M.monadic ( + let _ := M.assign_local (| + "ommer_hash" , + M.get_subscript (| + M.get_name (| globals, "ommers_hashes" |), + M.get_name (| globals, "ommer_index" |) + |) + |) in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + Compare.not_eq (| + M.get_name (| globals, "ommer_hash" |), + M.get_name (| globals, "block_hash" |) + |); + M.get_name (| globals, "InvalidBlock" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + Compare.not_in (| + M.get_name (| globals, "ommer_hash" |), + M.get_name (| globals, "recent_canonical_block_hashes" |) + |); + M.get_name (| globals, "InvalidBlock" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + Compare.not_in (| + M.get_name (| globals, "ommer_hash" |), + M.get_name (| globals, "recent_ommers_hashes" |) + |); + M.get_name (| globals, "InvalidBlock" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "ommer_age" , + BinOp.sub (| + M.get_field (| M.get_name (| globals, "block_header" |), "number" |), + M.get_field (| M.get_name (| globals, "ommer" |), "number" |) + |) + |) in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + BoolOp.and (| + Compare.lt_e (| + Constant.int 1, + M.get_name (| globals, "ommer_age" |) + |), + ltac:(M.monadic ( + Compare.lt_e (| + M.get_name (| globals, "ommer_age" |), + M.get_name (| globals, "MAX_OMMER_DEPTH" |) + |) + )) + |); + M.get_name (| globals, "InvalidBlock" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + Compare.in_ (| + M.get_field (| M.get_name (| globals, "ommer" |), "parent_hash" |), + M.get_name (| globals, "recent_canonical_block_hashes" |) + |); + M.get_name (| globals, "InvalidBlock" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + Compare.not_eq (| + M.get_field (| M.get_name (| globals, "ommer" |), "parent_hash" |), + M.get_field (| M.get_name (| globals, "block_header" |), "parent_hash" |) + |); + M.get_name (| globals, "InvalidBlock" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + M.pure Constant.None_)). + +Definition pay_rewards : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "state"; "block_number"; "coinbase"; "ommers" ] |) in + let _ := Constant.str " + Pay rewards to the block miner as well as the ommers miners. + + The miner of the canonical block is rewarded with the predetermined + block reward, ``BLOCK_REWARD``, plus a variable award based off of the + number of ommer blocks that were mined around the same time, and included + in the canonical block's header. An ommer block is a block that wasn't + added to the canonical blockchain because it wasn't validated as fast as + the accepted block but was mined at the same time. Although not all blocks + that are mined are added to the canonical chain, miners are still paid a + reward for their efforts. This reward is called an ommer reward and is + calculated based on the number associated with the ommer block that they + mined. + + Parameters + ---------- + state : + Current account state. + block_number : + Position of the block within the chain. + coinbase : + Address of account which receives block reward and transaction fees. + ommers : + List of ommers mentioned in the current block. + " in + let _ := M.assign_local (| + "miner_reward" , + BinOp.add (| + M.get_name (| globals, "BLOCK_REWARD" |), + BinOp.mult (| + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_name (| globals, "ommers" |) + ], + make_dict [] + |), + BinOp.floor_div (| + M.get_name (| globals, "BLOCK_REWARD" |), + Constant.int 32 + |) + |) + |) + |) in + let _ := M.call (| + M.get_name (| globals, "create_ether" |), + make_list [ + M.get_name (| globals, "state" |); + M.get_name (| globals, "coinbase" |); + M.get_name (| globals, "miner_reward" |) + ], + make_dict [] + |) in + let _ := + M.for_ (| + M.get_name (| globals, "ommer" |), + M.get_name (| globals, "ommers" |), + ltac:(M.monadic ( + let _ := M.assign_local (| + "ommer_age" , + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + BinOp.sub (| + M.get_name (| globals, "block_number" |), + M.get_field (| M.get_name (| globals, "ommer" |), "number" |) + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "ommer_miner_reward" , + BinOp.floor_div (| + BinOp.mult (| + BinOp.sub (| + Constant.int 8, + M.get_name (| globals, "ommer_age" |) + |), + M.get_name (| globals, "BLOCK_REWARD" |) + |), + Constant.int 8 + |) + |) in + let _ := M.call (| + M.get_name (| globals, "create_ether" |), + make_list [ + M.get_name (| globals, "state" |); + M.get_field (| M.get_name (| globals, "ommer" |), "coinbase" |); + M.get_name (| globals, "ommer_miner_reward" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + M.pure Constant.None_)). + +Definition process_transaction : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "env"; "tx" ] |) in + let _ := Constant.str " + Execute a transaction against the provided environment. + + This function processes the actions needed to execute a transaction. + It decrements the sender's account after calculating the gas fee and + refunds them the proper amount after execution. Calling contracts, + deploying code, and incrementing nonces are all examples of actions that + happen within this function or from a call made within this function. + + Accounts that are marked for deletion are processed and destroyed after + execution. + + Parameters + ---------- + env : + Environment for the Ethereum Virtual Machine. + tx : + Transaction to execute. + + Returns + ------- + gas_left : `ethereum.base_types.U256` + Remaining gas after execution. + logs : `Tuple[ethereum.blocks.Log, ...]` + Logs generated during execution. + " in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + M.call (| + M.get_name (| globals, "validate_transaction" |), + make_list [ + M.get_name (| globals, "tx" |) + ], + make_dict [] + |); + M.get_name (| globals, "InvalidBlock" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "sender" , + M.get_field (| M.get_name (| globals, "env" |), "origin" |) + |) in + let _ := M.assign_local (| + "sender_account" , + M.call (| + M.get_name (| globals, "get_account" |), + make_list [ + M.get_field (| M.get_name (| globals, "env" |), "state" |); + M.get_name (| globals, "sender" |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, "isinstance" |), + make_list [ + M.get_name (| globals, "tx" |); + M.get_name (| globals, "FeeMarketTransaction" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "max_gas_fee" , + BinOp.mult (| + M.get_field (| M.get_name (| globals, "tx" |), "gas" |), + M.get_field (| M.get_name (| globals, "tx" |), "max_fee_per_gas" |) + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "max_gas_fee" , + BinOp.mult (| + M.get_field (| M.get_name (| globals, "tx" |), "gas" |), + M.get_field (| M.get_name (| globals, "tx" |), "gas_price" |) + |) + |) in + M.pure Constant.None_ + )) |) in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + Compare.eq (| + M.get_field (| M.get_name (| globals, "sender_account" |), "nonce" |), + M.get_field (| M.get_name (| globals, "tx" |), "nonce" |) + |); + M.get_name (| globals, "InvalidBlock" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + Compare.gt_e (| + M.get_field (| M.get_name (| globals, "sender_account" |), "balance" |), + BinOp.add (| + M.get_name (| globals, "max_gas_fee" |), + M.get_field (| M.get_name (| globals, "tx" |), "value" |) + |) + |); + M.get_name (| globals, "InvalidBlock" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + Compare.eq (| + M.get_field (| M.get_name (| globals, "sender_account" |), "code" |), + M.call (| + M.get_name (| globals, "bytearray" |), + make_list [], + make_dict [] + |) + |); + M.get_name (| globals, "InvalidBlock" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "effective_gas_fee" , + BinOp.mult (| + M.get_field (| M.get_name (| globals, "tx" |), "gas" |), + M.get_field (| M.get_name (| globals, "env" |), "gas_price" |) + |) + |) in + let _ := M.assign_local (| + "gas" , + BinOp.sub (| + M.get_field (| M.get_name (| globals, "tx" |), "gas" |), + M.call (| + M.get_name (| globals, "calculate_intrinsic_cost" |), + make_list [ + M.get_name (| globals, "tx" |) + ], + make_dict [] + |) + |) + |) in + let _ := M.call (| + M.get_name (| globals, "increment_nonce" |), + make_list [ + M.get_field (| M.get_name (| globals, "env" |), "state" |); + M.get_name (| globals, "sender" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "sender_balance_after_gas_fee" , + BinOp.sub (| + M.get_field (| M.get_name (| globals, "sender_account" |), "balance" |), + M.get_name (| globals, "effective_gas_fee" |) + |) + |) in + let _ := M.call (| + M.get_name (| globals, "set_account_balance" |), + make_list [ + M.get_field (| M.get_name (| globals, "env" |), "state" |); + M.get_name (| globals, "sender" |); + M.get_name (| globals, "sender_balance_after_gas_fee" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "preaccessed_addresses" , + M.call (| + M.get_name (| globals, "set" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "preaccessed_storage_keys" , + M.call (| + M.get_name (| globals, "set" |), + make_list [], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, "isinstance" |), + make_list [ + M.get_name (| globals, "tx" |); + make_tuple [ M.get_name (| globals, "AccessListTransaction" |); M.get_name (| globals, "FeeMarketTransaction" |) ] + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := + M.for_ (| + make_tuple [ M.get_name (| globals, "address" |); M.get_name (| globals, "keys" |) ], + M.get_field (| M.get_name (| globals, "tx" |), "access_list" |), + ltac:(M.monadic ( + let _ := M.call (| + M.get_field (| M.get_name (| globals, "preaccessed_addresses" |), "add" |), + make_list [ + M.get_name (| globals, "address" |) + ], + make_dict [] + |) in + let _ := + M.for_ (| + M.get_name (| globals, "key" |), + M.get_name (| globals, "keys" |), + ltac:(M.monadic ( + let _ := M.call (| + M.get_field (| M.get_name (| globals, "preaccessed_storage_keys" |), "add" |), + make_list [ + make_tuple [ M.get_name (| globals, "address" |); M.get_name (| globals, "key" |) ] + ], + make_dict [] + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "message" , + M.call (| + M.get_name (| globals, "prepare_message" |), + make_list [ + M.get_name (| globals, "sender" |); + M.get_field (| M.get_name (| globals, "tx" |), "to" |); + M.get_field (| M.get_name (| globals, "tx" |), "value" |); + M.get_field (| M.get_name (| globals, "tx" |), "data" |); + M.get_name (| globals, "gas" |); + M.get_name (| globals, "env" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "output" , + M.call (| + M.get_name (| globals, "process_message_call" |), + make_list [ + M.get_name (| globals, "message" |); + M.get_name (| globals, "env" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "gas_used" , + BinOp.sub (| + M.get_field (| M.get_name (| globals, "tx" |), "gas" |), + M.get_field (| M.get_name (| globals, "output" |), "gas_left" |) + |) + |) in + let _ := M.assign_local (| + "gas_refund" , + M.call (| + M.get_name (| globals, "min" |), + make_list [ + BinOp.floor_div (| + M.get_name (| globals, "gas_used" |), + Constant.int 5 + |); + M.get_field (| M.get_name (| globals, "output" |), "refund_counter" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "gas_refund_amount" , + BinOp.mult (| + BinOp.add (| + M.get_field (| M.get_name (| globals, "output" |), "gas_left" |), + M.get_name (| globals, "gas_refund" |) + |), + M.get_field (| M.get_name (| globals, "env" |), "gas_price" |) + |) + |) in + let _ := M.assign_local (| + "priority_fee_per_gas" , + BinOp.sub (| + M.get_field (| M.get_name (| globals, "env" |), "gas_price" |), + M.get_field (| M.get_name (| globals, "env" |), "base_fee_per_gas" |) + |) + |) in + let _ := M.assign_local (| + "transaction_fee" , + BinOp.mult (| + BinOp.sub (| + BinOp.sub (| + M.get_field (| M.get_name (| globals, "tx" |), "gas" |), + M.get_field (| M.get_name (| globals, "output" |), "gas_left" |) + |), + M.get_name (| globals, "gas_refund" |) + |), + M.get_name (| globals, "priority_fee_per_gas" |) + |) + |) in + let _ := M.assign_local (| + "total_gas_used" , + BinOp.sub (| + M.get_name (| globals, "gas_used" |), + M.get_name (| globals, "gas_refund" |) + |) + |) in + let _ := M.assign_local (| + "sender_balance_after_refund" , + BinOp.add (| + M.get_field (| M.call (| + M.get_name (| globals, "get_account" |), + make_list [ + M.get_field (| M.get_name (| globals, "env" |), "state" |); + M.get_name (| globals, "sender" |) + ], + make_dict [] + |), "balance" |), + M.get_name (| globals, "gas_refund_amount" |) + |) + |) in + let _ := M.call (| + M.get_name (| globals, "set_account_balance" |), + make_list [ + M.get_field (| M.get_name (| globals, "env" |), "state" |); + M.get_name (| globals, "sender" |); + M.get_name (| globals, "sender_balance_after_refund" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "coinbase_balance_after_mining_fee" , + BinOp.add (| + M.get_field (| M.call (| + M.get_name (| globals, "get_account" |), + make_list [ + M.get_field (| M.get_name (| globals, "env" |), "state" |); + M.get_field (| M.get_name (| globals, "env" |), "coinbase" |) + ], + make_dict [] + |), "balance" |), + M.get_name (| globals, "transaction_fee" |) + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.not_eq (| + M.get_name (| globals, "coinbase_balance_after_mining_fee" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, "set_account_balance" |), + make_list [ + M.get_field (| M.get_name (| globals, "env" |), "state" |); + M.get_field (| M.get_name (| globals, "env" |), "coinbase" |); + M.get_name (| globals, "coinbase_balance_after_mining_fee" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, "account_exists_and_is_empty" |), + make_list [ + M.get_field (| M.get_name (| globals, "env" |), "state" |); + M.get_field (| M.get_name (| globals, "env" |), "coinbase" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, "destroy_account" |), + make_list [ + M.get_field (| M.get_name (| globals, "env" |), "state" |); + M.get_field (| M.get_name (| globals, "env" |), "coinbase" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )) |) in + let _ := + M.for_ (| + M.get_name (| globals, "address" |), + M.get_field (| M.get_name (| globals, "output" |), "accounts_to_delete" |), + ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, "destroy_account" |), + make_list [ + M.get_field (| M.get_name (| globals, "env" |), "state" |); + M.get_name (| globals, "address" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := + M.for_ (| + M.get_name (| globals, "address" |), + M.get_field (| M.get_name (| globals, "output" |), "touched_accounts" |), + ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, "account_exists_and_is_empty" |), + make_list [ + M.get_field (| M.get_name (| globals, "env" |), "state" |); + M.get_name (| globals, "address" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, "destroy_account" |), + make_list [ + M.get_field (| M.get_name (| globals, "env" |), "state" |); + M.get_name (| globals, "address" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := M.return_ (| + make_tuple [ M.get_name (| globals, "total_gas_used" |); M.get_field (| M.get_name (| globals, "output" |), "logs" |); M.get_field (| M.get_name (| globals, "output" |), "error" |) ] + |) in + M.pure Constant.None_)). + +Definition validate_transaction : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "tx" ] |) in + let _ := Constant.str " + Verifies a transaction. + + The gas in a transaction gets used to pay for the intrinsic cost of + operations, therefore if there is insufficient gas then it would not + be possible to execute a transaction and it will be declared invalid. + + Additionally, the nonce of a transaction must not equal or exceed the + limit defined in `EIP-2681 `_. + In practice, defining the limit as ``2**64-1`` has no impact because + sending ``2**64-1`` transactions is improbable. It's not strictly + impossible though, ``2**64-1`` transactions is the entire capacity of the + Ethereum blockchain at 2022 gas limits for a little over 22 years. + + Parameters + ---------- + tx : + Transaction to validate. + + Returns + ------- + verified : `bool` + True if the transaction can be executed, or False otherwise. + " in + let _ := M.return_ (| + BoolOp.and (| + Compare.lt_e (| + M.call (| + M.get_name (| globals, "calculate_intrinsic_cost" |), + make_list [ + M.get_name (| globals, "tx" |) + ], + make_dict [] + |), + M.get_field (| M.get_name (| globals, "tx" |), "gas" |) + |), + ltac:(M.monadic ( + Compare.lt (| + M.get_field (| M.get_name (| globals, "tx" |), "nonce" |), + BinOp.sub (| + BinOp.pow (| + Constant.int 2, + Constant.int 64 + |), + Constant.int 1 + |) + |) + )) + |) + |) in + M.pure Constant.None_)). + +Definition calculate_intrinsic_cost : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "tx" ] |) in + let _ := Constant.str " + Calculates the gas that is charged before execution is started. + + The intrinsic cost of the transaction is charged before execution has + begun. Functions/operations in the EVM cost money to execute so this + intrinsic cost is for the operations that need to be paid for as part of + the transaction. Data transfer, for example, is part of this intrinsic + cost. It costs ether to send data over the wire and that ether is + accounted for in the intrinsic cost calculated in this function. This + intrinsic cost must be calculated and paid for before execution in order + for all operations to be implemented. + + Parameters + ---------- + tx : + Transaction to compute the intrinsic cost of. + + Returns + ------- + verified : `ethereum.base_types.Uint` + The intrinsic cost of the transaction. + " in + let _ := M.assign_local (| + "data_cost" , + Constant.int 0 + |) in + let _ := + M.for_ (| + M.get_name (| globals, "byte" |), + M.get_field (| M.get_name (| globals, "tx" |), "data" |), + ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, "byte" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_op_local (| + BinOp.add, + "data_cost", + M.get_name (| globals, "TX_DATA_COST_PER_ZERO" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_op_local (| + BinOp.add, + "data_cost", + M.get_name (| globals, "TX_DATA_COST_PER_NON_ZERO" |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_field (| M.get_name (| globals, "tx" |), "to" |), + M.call (| + M.get_name (| globals, "Bytes0" |), + make_list [ + Constant.bytes "" + ], + make_dict [] + |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "create_cost" , + M.get_name (| globals, "TX_CREATE_COST" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "create_cost" , + Constant.int 0 + |) in + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "access_list_cost" , + Constant.int 0 + |) in + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, "isinstance" |), + make_list [ + M.get_name (| globals, "tx" |); + make_tuple [ M.get_name (| globals, "AccessListTransaction" |); M.get_name (| globals, "FeeMarketTransaction" |) ] + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := + M.for_ (| + make_tuple [ M.get_name (| globals, "_address" |); M.get_name (| globals, "keys" |) ], + M.get_field (| M.get_name (| globals, "tx" |), "access_list" |), + ltac:(M.monadic ( + let _ := M.assign_op_local (| + BinOp.add, + "access_list_cost", + M.get_name (| globals, "TX_ACCESS_LIST_ADDRESS_COST" |) + |) in + let _ := M.assign_op_local (| + BinOp.add, + "access_list_cost", + BinOp.mult (| + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_name (| globals, "keys" |) + ], + make_dict [] + |), + M.get_name (| globals, "TX_ACCESS_LIST_STORAGE_KEY_COST" |) + |) + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + BinOp.add (| + BinOp.add (| + BinOp.add (| + M.get_name (| globals, "TX_BASE_COST" |), + M.get_name (| globals, "data_cost" |) + |), + M.get_name (| globals, "create_cost" |) + |), + M.get_name (| globals, "access_list_cost" |) + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Definition recover_sender : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "chain_id"; "tx" ] |) in + let _ := Constant.str " + Extracts the sender address from a transaction. + + The v, r, and s values are the three parts that make up the signature + of a transaction. In order to recover the sender of a transaction the two + components needed are the signature (``v``, ``r``, and ``s``) and the + signing hash of the transaction. The sender's public key can be obtained + with these two values and therefore the sender address can be retrieved. + + Parameters + ---------- + tx : + Transaction of interest. + chain_id : + ID of the executing chain. + + Returns + ------- + sender : `ethereum.fork_types.Address` + The address of the account that signed the transaction. + " in + let _ := M.assign (| + make_tuple [ M.get_name (| globals, "r" |); M.get_name (| globals, "s" |) ], + make_tuple [ M.get_field (| M.get_name (| globals, "tx" |), "r" |); M.get_field (| M.get_name (| globals, "tx" |), "s" |) ] + |) in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + BoolOp.and (| + Compare.lt (| + Constant.int 0, + M.get_name (| globals, "r" |) + |), + ltac:(M.monadic ( + Compare.lt (| + M.get_name (| globals, "r" |), + M.get_name (| globals, "SECP256K1N" |) + |) + )) + |); + M.get_name (| globals, "InvalidBlock" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + BoolOp.and (| + Compare.lt (| + Constant.int 0, + M.get_name (| globals, "s" |) + |), + ltac:(M.monadic ( + Compare.lt_e (| + M.get_name (| globals, "s" |), + BinOp.floor_div (| + M.get_name (| globals, "SECP256K1N" |), + Constant.int 2 + |) + |) + )) + |); + M.get_name (| globals, "InvalidBlock" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, "isinstance" |), + make_list [ + M.get_name (| globals, "tx" |); + M.get_name (| globals, "LegacyTransaction" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "v" , + M.get_field (| M.get_name (| globals, "tx" |), "v" |) + |) in + let _ := + (* if *) + M.if_then_else (| + BoolOp.or (| + Compare.eq (| + M.get_name (| globals, "v" |), + Constant.int 27 + |), + ltac:(M.monadic ( + Compare.eq (| + M.get_name (| globals, "v" |), + Constant.int 28 + |) + )) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "public_key" , + M.call (| + M.get_name (| globals, "secp256k1_recover" |), + make_list [ + M.get_name (| globals, "r" |); + M.get_name (| globals, "s" |); + BinOp.sub (| + M.get_name (| globals, "v" |), + Constant.int 27 + |); + M.call (| + M.get_name (| globals, "signing_hash_pre155" |), + make_list [ + M.get_name (| globals, "tx" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + BoolOp.or (| + Compare.eq (| + M.get_name (| globals, "v" |), + BinOp.add (| + Constant.int 35, + BinOp.mult (| + M.get_name (| globals, "chain_id" |), + Constant.int 2 + |) + |) + |), + ltac:(M.monadic ( + Compare.eq (| + M.get_name (| globals, "v" |), + BinOp.add (| + Constant.int 36, + BinOp.mult (| + M.get_name (| globals, "chain_id" |), + Constant.int 2 + |) + |) + |) + )) + |); + M.get_name (| globals, "InvalidBlock" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "public_key" , + M.call (| + M.get_name (| globals, "secp256k1_recover" |), + make_list [ + M.get_name (| globals, "r" |); + M.get_name (| globals, "s" |); + BinOp.sub (| + BinOp.sub (| + M.get_name (| globals, "v" |), + Constant.int 35 + |), + BinOp.mult (| + M.get_name (| globals, "chain_id" |), + Constant.int 2 + |) + |); + M.call (| + M.get_name (| globals, "signing_hash_155" |), + make_list [ + M.get_name (| globals, "tx" |); + M.get_name (| globals, "chain_id" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, "isinstance" |), + make_list [ + M.get_name (| globals, "tx" |); + M.get_name (| globals, "AccessListTransaction" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "public_key" , + M.call (| + M.get_name (| globals, "secp256k1_recover" |), + make_list [ + M.get_name (| globals, "r" |); + M.get_name (| globals, "s" |); + M.get_field (| M.get_name (| globals, "tx" |), "y_parity" |); + M.call (| + M.get_name (| globals, "signing_hash_2930" |), + make_list [ + M.get_name (| globals, "tx" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, "isinstance" |), + make_list [ + M.get_name (| globals, "tx" |); + M.get_name (| globals, "FeeMarketTransaction" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "public_key" , + M.call (| + M.get_name (| globals, "secp256k1_recover" |), + make_list [ + M.get_name (| globals, "r" |); + M.get_name (| globals, "s" |); + M.get_field (| M.get_name (| globals, "tx" |), "y_parity" |); + M.call (| + M.get_name (| globals, "signing_hash_1559" |), + make_list [ + M.get_name (| globals, "tx" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )) |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, "Address" |), + make_list [ + M.slice (| + M.call (| + M.get_name (| globals, "keccak256" |), + make_list [ + M.get_name (| globals, "public_key" |) + ], + make_dict [] + |), + Constant.int 12, + Constant.int 32, + Constant.None_ + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Definition signing_hash_pre155 : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "tx" ] |) in + let _ := Constant.str " + Compute the hash of a transaction used in a legacy (pre EIP 155) signature. + + Parameters + ---------- + tx : + Transaction of interest. + + Returns + ------- + hash : `ethereum.crypto.hash.Hash32` + Hash of the transaction. + " in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, "keccak256" |), + make_list [ + M.call (| + M.get_field (| M.get_name (| globals, "rlp" |), "encode" |), + make_list [ + make_tuple [ M.get_field (| M.get_name (| globals, "tx" |), "nonce" |); M.get_field (| M.get_name (| globals, "tx" |), "gas_price" |); M.get_field (| M.get_name (| globals, "tx" |), "gas" |); M.get_field (| M.get_name (| globals, "tx" |), "to" |); M.get_field (| M.get_name (| globals, "tx" |), "value" |); M.get_field (| M.get_name (| globals, "tx" |), "data" |) ] + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Definition signing_hash_155 : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "tx"; "chain_id" ] |) in + let _ := Constant.str " + Compute the hash of a transaction used in a EIP 155 signature. + + Parameters + ---------- + tx : + Transaction of interest. + chain_id : + The id of the current chain. + + Returns + ------- + hash : `ethereum.crypto.hash.Hash32` + Hash of the transaction. + " in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, "keccak256" |), + make_list [ + M.call (| + M.get_field (| M.get_name (| globals, "rlp" |), "encode" |), + make_list [ + make_tuple [ M.get_field (| M.get_name (| globals, "tx" |), "nonce" |); M.get_field (| M.get_name (| globals, "tx" |), "gas_price" |); M.get_field (| M.get_name (| globals, "tx" |), "gas" |); M.get_field (| M.get_name (| globals, "tx" |), "to" |); M.get_field (| M.get_name (| globals, "tx" |), "value" |); M.get_field (| M.get_name (| globals, "tx" |), "data" |); M.get_name (| globals, "chain_id" |); M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |); M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) ] + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Definition signing_hash_2930 : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "tx" ] |) in + let _ := Constant.str " + Compute the hash of a transaction used in a EIP 2930 signature. + + Parameters + ---------- + tx : + Transaction of interest. + + Returns + ------- + hash : `ethereum.crypto.hash.Hash32` + Hash of the transaction. + " in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, "keccak256" |), + make_list [ + BinOp.add (| + Constant.bytes "01", + M.call (| + M.get_field (| M.get_name (| globals, "rlp" |), "encode" |), + make_list [ + make_tuple [ M.get_field (| M.get_name (| globals, "tx" |), "chain_id" |); M.get_field (| M.get_name (| globals, "tx" |), "nonce" |); M.get_field (| M.get_name (| globals, "tx" |), "gas_price" |); M.get_field (| M.get_name (| globals, "tx" |), "gas" |); M.get_field (| M.get_name (| globals, "tx" |), "to" |); M.get_field (| M.get_name (| globals, "tx" |), "value" |); M.get_field (| M.get_name (| globals, "tx" |), "data" |); M.get_field (| M.get_name (| globals, "tx" |), "access_list" |) ] + ], + make_dict [] + |) + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Definition signing_hash_1559 : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "tx" ] |) in + let _ := Constant.str " + Compute the hash of a transaction used in a EIP 1559 signature. + + Parameters + ---------- + tx : + Transaction of interest. + + Returns + ------- + hash : `ethereum.crypto.hash.Hash32` + Hash of the transaction. + " in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, "keccak256" |), + make_list [ + BinOp.add (| + Constant.bytes "02", + M.call (| + M.get_field (| M.get_name (| globals, "rlp" |), "encode" |), + make_list [ + make_tuple [ M.get_field (| M.get_name (| globals, "tx" |), "chain_id" |); M.get_field (| M.get_name (| globals, "tx" |), "nonce" |); M.get_field (| M.get_name (| globals, "tx" |), "max_priority_fee_per_gas" |); M.get_field (| M.get_name (| globals, "tx" |), "max_fee_per_gas" |); M.get_field (| M.get_name (| globals, "tx" |), "gas" |); M.get_field (| M.get_name (| globals, "tx" |), "to" |); M.get_field (| M.get_name (| globals, "tx" |), "value" |); M.get_field (| M.get_name (| globals, "tx" |), "data" |); M.get_field (| M.get_name (| globals, "tx" |), "access_list" |) ] + ], + make_dict [] + |) + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Definition compute_header_hash : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "header" ] |) in + let _ := Constant.str " + Computes the hash of a block header. + + The header hash of a block is the canonical hash that is used to refer + to a specific block and completely distinguishes a block from another. + + ``keccak256`` is a function that produces a 256 bit hash of any input. + It also takes in any number of bytes as an input and produces a single + hash for them. A hash is a completely unique output for a single input. + So an input corresponds to one unique hash that can be used to identify + the input exactly. + + Prior to using the ``keccak256`` hash function, the header must be + encoded using the Recursive-Length Prefix. See :ref:`rlp`. + RLP encoding the header converts it into a space-efficient format that + allows for easy transfer of data between nodes. The purpose of RLP is to + encode arbitrarily nested arrays of binary data, and RLP is the primary + encoding method used to serialize objects in Ethereum's execution layer. + The only purpose of RLP is to encode structure; encoding specific data + types (e.g. strings, floats) is left up to higher-order protocols. + + Parameters + ---------- + header : + Header of interest. + + Returns + ------- + hash : `ethereum.crypto.hash.Hash32` + Hash of the header. + " in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, "keccak256" |), + make_list [ + M.call (| + M.get_field (| M.get_name (| globals, "rlp" |), "encode" |), + make_list [ + M.get_name (| globals, "header" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Definition check_gas_limit : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "gas_limit"; "parent_gas_limit" ] |) in + let _ := Constant.str " + Validates the gas limit for a block. + + The bounds of the gas limit, ``max_adjustment_delta``, is set as the + quotient of the parent block's gas limit and the + ``GAS_LIMIT_ADJUSTMENT_FACTOR``. Therefore, if the gas limit that is + passed through as a parameter is greater than or equal to the *sum* of + the parent's gas and the adjustment delta then the limit for gas is too + high and fails this function's check. Similarly, if the limit is less + than or equal to the *difference* of the parent's gas and the adjustment + delta *or* the predefined ``GAS_LIMIT_MINIMUM`` then this function's + check fails because the gas limit doesn't allow for a sufficient or + reasonable amount of gas to be used on a block. + + Parameters + ---------- + gas_limit : + Gas limit to validate. + + parent_gas_limit : + Gas limit of the parent block. + + Returns + ------- + check : `bool` + True if gas limit constraints are satisfied, False otherwise. + " in + let _ := M.assign_local (| + "max_adjustment_delta" , + BinOp.floor_div (| + M.get_name (| globals, "parent_gas_limit" |), + M.get_name (| globals, "GAS_LIMIT_ADJUSTMENT_FACTOR" |) + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.gt_e (| + M.get_name (| globals, "gas_limit" |), + BinOp.add (| + M.get_name (| globals, "parent_gas_limit" |), + M.get_name (| globals, "max_adjustment_delta" |) + |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + Constant.bool false + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + Compare.lt_e (| + M.get_name (| globals, "gas_limit" |), + BinOp.sub (| + M.get_name (| globals, "parent_gas_limit" |), + M.get_name (| globals, "max_adjustment_delta" |) + |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + Constant.bool false + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + Compare.lt (| + M.get_name (| globals, "gas_limit" |), + M.get_name (| globals, "GAS_LIMIT_MINIMUM" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + Constant.bool false + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.return_ (| + Constant.bool true + |) in + M.pure Constant.None_)). + +Definition calculate_block_difficulty : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "block_number"; "block_timestamp"; "parent_timestamp"; "parent_difficulty"; "parent_has_ommers" ] |) in + let _ := Constant.str " + Computes difficulty of a block using its header and parent header. + + The difficulty is determined by the time the block was created after its + parent. The ``offset`` is calculated using the parent block's difficulty, + ``parent_difficulty``, and the timestamp between blocks. This offset is + then added to the parent difficulty and is stored as the ``difficulty`` + variable. If the time between the block and its parent is too short, the + offset will result in a positive number thus making the sum of + ``parent_difficulty`` and ``offset`` to be a greater value in order to + avoid mass forking. But, if the time is long enough, then the offset + results in a negative value making the block less difficult than + its parent. + + The base standard for a block's difficulty is the predefined value + set for the genesis block since it has no parent. So, a block + can't be less difficult than the genesis block, therefore each block's + difficulty is set to the maximum value between the calculated + difficulty and the ``GENESIS_DIFFICULTY``. + + Parameters + ---------- + block_number : + Block number of the block. + block_timestamp : + Timestamp of the block. + parent_timestamp : + Timestamp of the parent block. + parent_difficulty : + difficulty of the parent block. + parent_has_ommers: + does the parent have ommers. + + Returns + ------- + difficulty : `ethereum.base_types.Uint` + Computed difficulty for a block. + " in + let _ := M.assign_local (| + "offset" , + BinOp.mult (| + BinOp.floor_div (| + M.call (| + M.get_name (| globals, "int" |), + make_list [ + M.get_name (| globals, "parent_difficulty" |) + ], + make_dict [] + |), + Constant.int 2048 + |), + M.call (| + M.get_name (| globals, "max" |), + make_list [ + BinOp.sub (| + (* if *) + M.if_then_else (| + M.get_name (| globals, "parent_has_ommers" |), + (* then *) + ltac:(M.monadic ( +Constant.int 2 + (* else *) + )), ltac:(M.monadic ( +Constant.int 1 + )) |), + BinOp.floor_div (| + M.call (| + M.get_name (| globals, "int" |), + make_list [ + BinOp.sub (| + M.get_name (| globals, "block_timestamp" |), + M.get_name (| globals, "parent_timestamp" |) + |) + ], + make_dict [] + |), + Constant.int 9 + |) + |); + UnOp.sub (| Constant.int 99 |) + ], + make_dict [] + |) + |) + |) in + let _ := M.assign_local (| + "difficulty" , + BinOp.add (| + M.call (| + M.get_name (| globals, "int" |), + make_list [ + M.get_name (| globals, "parent_difficulty" |) + ], + make_dict [] + |), + M.get_name (| globals, "offset" |) + |) + |) in + let _ := M.assign_local (| + "num_bomb_periods" , + BinOp.sub (| + BinOp.floor_div (| + BinOp.sub (| + M.call (| + M.get_name (| globals, "int" |), + make_list [ + M.get_name (| globals, "block_number" |) + ], + make_dict [] + |), + M.get_name (| globals, "BOMB_DELAY_BLOCKS" |) + |), + Constant.int 100000 + |), + Constant.int 2 + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.gt_e (| + M.get_name (| globals, "num_bomb_periods" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_op_local (| + BinOp.add, + "difficulty", + BinOp.pow (| + Constant.int 2, + M.get_name (| globals, "num_bomb_periods" |) + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, "max" |), + make_list [ + M.get_name (| globals, "difficulty" |); + M.get_name (| globals, "MINIMUM_DIFFICULTY" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). diff --git a/CoqOfPython/ethereum/london/fork_types.v b/CoqOfPython/ethereum/london/fork_types.v new file mode 100644 index 0000000..3c5e125 --- /dev/null +++ b/CoqOfPython/ethereum/london/fork_types.v @@ -0,0 +1,98 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.london.fork_types". + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Types +^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Types re-used throughout the specification, which are specific to Ethereum. +". + +Axiom dataclasses_imports_dataclass : + IsImported globals "dataclasses" "dataclass". + +Axiom ethereum_imports_rlp : + IsImported globals "ethereum" "rlp". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_Bytes : + IsImported globals "ethereum.base_types" "Bytes". +Axiom ethereum_base_types_imports_Bytes20 : + IsImported globals "ethereum.base_types" "Bytes20". +Axiom ethereum_base_types_imports_Bytes256 : + IsImported globals "ethereum.base_types" "Bytes256". +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". +Axiom ethereum_base_types_imports_slotted_freezable : + IsImported globals "ethereum.base_types" "slotted_freezable". + +Axiom ethereum_crypto_hash_imports_Hash32 : + IsImported globals "ethereum.crypto.hash" "Hash32". +Axiom ethereum_crypto_hash_imports_keccak256 : + IsImported globals "ethereum.crypto.hash" "keccak256". + +Definition Address : Value.t := M.run ltac:(M.monadic ( + M.get_name (| globals, "Bytes20" |) +)). + +Definition Root : Value.t := M.run ltac:(M.monadic ( + M.get_name (| globals, "Hash32" |) +)). + +Definition Bloom : Value.t := M.run ltac:(M.monadic ( + M.get_name (| globals, "Bytes256" |) +)). + +Definition Account : Value.t := + builtins.make_klass + [] + [ + + ] + [ + + ]. + +Definition EMPTY_ACCOUNT : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Account" |), + make_list [], + make_dict [] + |) +)). + +Definition encode_account : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "raw_account_data"; "storage_root" ] |) in + let _ := Constant.str " + Encode `Account` dataclass. + + Storage is not stored in the `Account` dataclass, so `Accounts` cannot be + encoded with providing a storage root. + " in + let _ := M.return_ (| + M.call (| + M.get_field (| M.get_name (| globals, "rlp" |), "encode" |), + make_list [ + make_tuple [ M.get_field (| M.get_name (| globals, "raw_account_data" |), "nonce" |); M.get_field (| M.get_name (| globals, "raw_account_data" |), "balance" |); M.get_name (| globals, "storage_root" |); M.call (| + M.get_name (| globals, "keccak256" |), + make_list [ + M.get_field (| M.get_name (| globals, "raw_account_data" |), "code" |) + ], + make_dict [] + |) ] + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). diff --git a/CoqOfPython/ethereum/london/state.v b/CoqOfPython/ethereum/london/state.v new file mode 100644 index 0000000..afa32da --- /dev/null +++ b/CoqOfPython/ethereum/london/state.v @@ -0,0 +1,1279 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.london.state". + +Definition expr_1 : Value.t := + Constant.str " +State +^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +The state contains all information that is preserved between transactions. + +It consists of a main account trie and storage tries for each contract. + +There is a distinction between an account that does not exist and +`EMPTY_ACCOUNT`. +". + +Axiom dataclasses_imports_dataclass : + IsImported globals "dataclasses" "dataclass". +Axiom dataclasses_imports_field : + IsImported globals "dataclasses" "field". + +Axiom typing_imports_Callable : + IsImported globals "typing" "Callable". +Axiom typing_imports_Dict : + IsImported globals "typing" "Dict". +Axiom typing_imports_List : + IsImported globals "typing" "List". +Axiom typing_imports_Optional : + IsImported globals "typing" "Optional". +Axiom typing_imports_Set : + IsImported globals "typing" "Set". +Axiom typing_imports_Tuple : + IsImported globals "typing" "Tuple". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_Bytes : + IsImported globals "ethereum.base_types" "Bytes". +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". +Axiom ethereum_base_types_imports_modify : + IsImported globals "ethereum.base_types" "modify". + +Axiom ethereum_utils_ensure_imports_ensure : + IsImported globals "ethereum.utils.ensure" "ensure". + +Axiom ethereum_london_fork_types_imports_EMPTY_ACCOUNT : + IsImported globals "ethereum.london.fork_types" "EMPTY_ACCOUNT". +Axiom ethereum_london_fork_types_imports_Account : + IsImported globals "ethereum.london.fork_types" "Account". +Axiom ethereum_london_fork_types_imports_Address : + IsImported globals "ethereum.london.fork_types" "Address". +Axiom ethereum_london_fork_types_imports_Root : + IsImported globals "ethereum.london.fork_types" "Root". + +Axiom ethereum_london_trie_imports_EMPTY_TRIE_ROOT : + IsImported globals "ethereum.london.trie" "EMPTY_TRIE_ROOT". +Axiom ethereum_london_trie_imports_Trie : + IsImported globals "ethereum.london.trie" "Trie". +Axiom ethereum_london_trie_imports_copy_trie : + IsImported globals "ethereum.london.trie" "copy_trie". +Axiom ethereum_london_trie_imports_root : + IsImported globals "ethereum.london.trie" "root". +Axiom ethereum_london_trie_imports_trie_get : + IsImported globals "ethereum.london.trie" "trie_get". +Axiom ethereum_london_trie_imports_trie_set : + IsImported globals "ethereum.london.trie" "trie_set". + +Definition State : Value.t := + builtins.make_klass + [] + [ + + ] + [ + + ]. + +Definition close_state : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "state" ] |) in + let _ := Constant.str " + Free resources held by the state. Used by optimized implementations to + release file descriptors. + " in + let _ := M.delete (| M.get_field (| M.get_name (| globals, "state" |), "_main_trie" |) |) in + let _ := M.delete (| M.get_field (| M.get_name (| globals, "state" |), "_storage_tries" |) |) in + let _ := M.delete (| M.get_field (| M.get_name (| globals, "state" |), "_snapshots" |) |) in + let _ := M.delete (| M.get_field (| M.get_name (| globals, "state" |), "_created_accounts" |) |) in + M.pure Constant.None_)). + +Definition begin_transaction : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "state" ] |) in + let _ := Constant.str " + Start a state transaction. + + Transactions are entirely implicit and can be nested. It is not possible to + calculate the state root during a transaction. + + Parameters + ---------- + state : State + The state. + " in + let _ := M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, "state" |), "_snapshots" |), "append" |), + make_list [ + make_tuple [ M.call (| + M.get_name (| globals, "copy_trie" |), + make_list [ + M.get_field (| M.get_name (| globals, "state" |), "_main_trie" |) + ], + make_dict [] + |); Constant.str "(* At expr: unsupported node type: DictComp *)" ] + ], + make_dict [] + |) in + M.pure Constant.None_)). + +Definition commit_transaction : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "state" ] |) in + let _ := Constant.str " + Commit a state transaction. + + Parameters + ---------- + state : State + The state. + " in + let _ := M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, "state" |), "_snapshots" |), "pop" |), + make_list [], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + UnOp.not (| M.get_field (| M.get_name (| globals, "state" |), "_snapshots" |) |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, "state" |), "_created_accounts" |), "clear" |), + make_list [], + make_dict [] + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + M.pure Constant.None_)). + +Definition rollback_transaction : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "state" ] |) in + let _ := Constant.str " + Rollback a state transaction, resetting the state to the point when the + corresponding `start_transaction()` call was made. + + Parameters + ---------- + state : State + The state. + " in + let _ := M.assign (| + make_tuple [ M.get_field (| M.get_name (| globals, "state" |), "_main_trie" |); M.get_field (| M.get_name (| globals, "state" |), "_storage_tries" |) ], + M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, "state" |), "_snapshots" |), "pop" |), + make_list [], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + UnOp.not (| M.get_field (| M.get_name (| globals, "state" |), "_snapshots" |) |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, "state" |), "_created_accounts" |), "clear" |), + make_list [], + make_dict [] + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + M.pure Constant.None_)). + +Definition get_account : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "state"; "address" ] |) in + let _ := Constant.str " + Get the `Account` object at an address. Returns `EMPTY_ACCOUNT` if there + is no account at the address. + + Use `get_account_optional()` if you care about the difference between a + non-existent account and `EMPTY_ACCOUNT`. + + Parameters + ---------- + state: `State` + The state + address : `Address` + Address to lookup. + + Returns + ------- + account : `Account` + Account at address. + " in + let _ := M.assign_local (| + "account" , + M.call (| + M.get_name (| globals, "get_account_optional" |), + make_list [ + M.get_name (| globals, "state" |); + M.get_name (| globals, "address" |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, "isinstance" |), + make_list [ + M.get_name (| globals, "account" |); + M.get_name (| globals, "Account" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + M.get_name (| globals, "account" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.return_ (| + M.get_name (| globals, "EMPTY_ACCOUNT" |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_)). + +Definition get_account_optional : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "state"; "address" ] |) in + let _ := Constant.str " + Get the `Account` object at an address. Returns `None` (rather than + `EMPTY_ACCOUNT`) if there is no account at the address. + + Parameters + ---------- + state: `State` + The state + address : `Address` + Address to lookup. + + Returns + ------- + account : `Account` + Account at address. + " in + let _ := M.assign_local (| + "account" , + M.call (| + M.get_name (| globals, "trie_get" |), + make_list [ + M.get_field (| M.get_name (| globals, "state" |), "_main_trie" |); + M.get_name (| globals, "address" |) + ], + make_dict [] + |) + |) in + let _ := M.return_ (| + M.get_name (| globals, "account" |) + |) in + M.pure Constant.None_)). + +Definition set_account : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "state"; "address"; "account" ] |) in + let _ := Constant.str " + Set the `Account` object at an address. Setting to `None` deletes + the account (but not its storage, see `destroy_account()`). + + Parameters + ---------- + state: `State` + The state + address : `Address` + Address to set. + account : `Account` + Account to set at address. + " in + let _ := M.call (| + M.get_name (| globals, "trie_set" |), + make_list [ + M.get_field (| M.get_name (| globals, "state" |), "_main_trie" |); + M.get_name (| globals, "address" |); + M.get_name (| globals, "account" |) + ], + make_dict [] + |) in + M.pure Constant.None_)). + +Definition destroy_account : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "state"; "address" ] |) in + let _ := Constant.str " + Completely remove the account at `address` and all of its storage. + + This function is made available exclusively for the `SELFDESTRUCT` + opcode. It is expected that `SELFDESTRUCT` will be disabled in a future + hardfork and this function will be removed. + + Parameters + ---------- + state: `State` + The state + address : `Address` + Address of account to destroy. + " in + let _ := M.call (| + M.get_name (| globals, "destroy_storage" |), + make_list [ + M.get_name (| globals, "state" |); + M.get_name (| globals, "address" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "set_account" |), + make_list [ + M.get_name (| globals, "state" |); + M.get_name (| globals, "address" |); + Constant.None_ + ], + make_dict [] + |) in + M.pure Constant.None_)). + +Definition destroy_storage : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "state"; "address" ] |) in + let _ := Constant.str " + Completely remove the storage at `address`. + + Parameters + ---------- + state: `State` + The state + address : `Address` + Address of account whose storage is to be deleted. + " in + let _ := + (* if *) + M.if_then_else (| + Compare.in_ (| + M.get_name (| globals, "address" |), + M.get_field (| M.get_name (| globals, "state" |), "_storage_tries" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.delete (| M.get_subscript (| + M.get_field (| M.get_name (| globals, "state" |), "_storage_tries" |), + M.get_name (| globals, "address" |) + |) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + M.pure Constant.None_)). + +Definition mark_account_created : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "state"; "address" ] |) in + let _ := Constant.str " + Mark an account as having been created in the current transaction. + This information is used by `get_storage_original()` to handle an obscure + edgecase. + + The marker is not removed even if the account creation reverts. Since the + account cannot have had code prior to its creation and can't call + `get_storage_original()`, this is harmless. + + Parameters + ---------- + state: `State` + The state + address : `Address` + Address of the account that has been created. + " in + let _ := M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, "state" |), "_created_accounts" |), "add" |), + make_list [ + M.get_name (| globals, "address" |) + ], + make_dict [] + |) in + M.pure Constant.None_)). + +Definition get_storage : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "state"; "address"; "key" ] |) in + let _ := Constant.str " + Get a value at a storage key on an account. Returns `U256(0)` if the + storage key has not been set previously. + + Parameters + ---------- + state: `State` + The state + address : `Address` + Address of the account. + key : `Bytes` + Key to lookup. + + Returns + ------- + value : `U256` + Value at the key. + " in + let _ := M.assign_local (| + "trie" , + M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, "state" |), "_storage_tries" |), "get" |), + make_list [ + M.get_name (| globals, "address" |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.is (| + M.get_name (| globals, "trie" |), + Constant.None_ + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "value" , + M.call (| + M.get_name (| globals, "trie_get" |), + make_list [ + M.get_name (| globals, "trie" |); + M.get_name (| globals, "key" |) + ], + make_dict [] + |) + |) in + let _ := M.assert (| M.call (| + M.get_name (| globals, "isinstance" |), + make_list [ + M.get_name (| globals, "value" |); + M.get_name (| globals, "U256" |) + ], + make_dict [] + |) |) in + let _ := M.return_ (| + M.get_name (| globals, "value" |) + |) in + M.pure Constant.None_)). + +Definition set_storage : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "state"; "address"; "key"; "value" ] |) in + let _ := Constant.str " + Set a value at a storage key on an account. Setting to `U256(0)` deletes + the key. + + Parameters + ---------- + state: `State` + The state + address : `Address` + Address of the account. + key : `Bytes` + Key to set. + value : `U256` + Value to set at the key. + " in + let _ := M.assert (| Compare.is_not (| + M.call (| + M.get_name (| globals, "trie_get" |), + make_list [ + M.get_field (| M.get_name (| globals, "state" |), "_main_trie" |); + M.get_name (| globals, "address" |) + ], + make_dict [] + |), + Constant.None_ + |) |) in + let _ := M.assign_local (| + "trie" , + M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, "state" |), "_storage_tries" |), "get" |), + make_list [ + M.get_name (| globals, "address" |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.is (| + M.get_name (| globals, "trie" |), + Constant.None_ + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "trie" , + M.call (| + M.get_name (| globals, "Trie" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.assign (| + M.get_subscript (| + M.get_field (| M.get_name (| globals, "state" |), "_storage_tries" |), + M.get_name (| globals, "address" |) + |), + M.get_name (| globals, "trie" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.call (| + M.get_name (| globals, "trie_set" |), + make_list [ + M.get_name (| globals, "trie" |); + M.get_name (| globals, "key" |); + M.get_name (| globals, "value" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_field (| M.get_name (| globals, "trie" |), "_data" |), + Constant.str "(* At expr: unsupported node type: Dict *)" + |), + (* then *) + ltac:(M.monadic ( + let _ := M.delete (| M.get_subscript (| + M.get_field (| M.get_name (| globals, "state" |), "_storage_tries" |), + M.get_name (| globals, "address" |) + |) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + M.pure Constant.None_)). + +Definition storage_root : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "state"; "address" ] |) in + let _ := Constant.str " + Calculate the storage root of an account. + + Parameters + ---------- + state: + The state + address : + Address of the account. + + Returns + ------- + root : `Root` + Storage root of the account. + " in + let _ := M.assert (| UnOp.not (| M.get_field (| M.get_name (| globals, "state" |), "_snapshots" |) |) |) in + let _ := + (* if *) + M.if_then_else (| + Compare.in_ (| + M.get_name (| globals, "address" |), + M.get_field (| M.get_name (| globals, "state" |), "_storage_tries" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + M.call (| + M.get_name (| globals, "root" |), + make_list [ + M.get_subscript (| + M.get_field (| M.get_name (| globals, "state" |), "_storage_tries" |), + M.get_name (| globals, "address" |) + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.return_ (| + M.get_name (| globals, "EMPTY_TRIE_ROOT" |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_)). + +Definition state_root : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "state" ] |) in + let _ := Constant.str " + Calculate the state root. + + Parameters + ---------- + state: + The current state. + + Returns + ------- + root : `Root` + The state root. + " in + let _ := M.assert (| UnOp.not (| M.get_field (| M.get_name (| globals, "state" |), "_snapshots" |) |) |) in +(* At stmt: unsupported node type: FunctionDef *) + let _ := M.return_ (| + M.call (| + M.get_name (| globals, "root" |), + make_list [ + M.get_field (| M.get_name (| globals, "state" |), "_main_trie" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Definition account_exists : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "state"; "address" ] |) in + let _ := Constant.str " + Checks if an account exists in the state trie + + Parameters + ---------- + state: + The state + address: + Address of the account that needs to be checked. + + Returns + ------- + account_exists : `bool` + True if account exists in the state trie, False otherwise + " in + let _ := M.return_ (| + Compare.is_not (| + M.call (| + M.get_name (| globals, "get_account_optional" |), + make_list [ + M.get_name (| globals, "state" |); + M.get_name (| globals, "address" |) + ], + make_dict [] + |), + Constant.None_ + |) + |) in + M.pure Constant.None_)). + +Definition account_has_code_or_nonce : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "state"; "address" ] |) in + let _ := Constant.str " + Checks if an account has non zero nonce or non empty code + + Parameters + ---------- + state: + The state + address: + Address of the account that needs to be checked. + + Returns + ------- + has_code_or_nonce : `bool` + True if if an account has non zero nonce or non empty code, + False otherwise. + " in + let _ := M.assign_local (| + "account" , + M.call (| + M.get_name (| globals, "get_account" |), + make_list [ + M.get_name (| globals, "state" |); + M.get_name (| globals, "address" |) + ], + make_dict [] + |) + |) in + let _ := M.return_ (| + BoolOp.or (| + Compare.not_eq (| + M.get_field (| M.get_name (| globals, "account" |), "nonce" |), + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + |), + ltac:(M.monadic ( + Compare.not_eq (| + M.get_field (| M.get_name (| globals, "account" |), "code" |), + Constant.bytes "" + |) + )) + |) + |) in + M.pure Constant.None_)). + +Definition is_account_empty : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "state"; "address" ] |) in + let _ := Constant.str " + Checks if an account has zero nonce, empty code and zero balance. + + Parameters + ---------- + state: + The state + address: + Address of the account that needs to be checked. + + Returns + ------- + is_empty : `bool` + True if if an account has zero nonce, empty code and zero balance, + False otherwise. + " in + let _ := M.assign_local (| + "account" , + M.call (| + M.get_name (| globals, "get_account" |), + make_list [ + M.get_name (| globals, "state" |); + M.get_name (| globals, "address" |) + ], + make_dict [] + |) + |) in + let _ := M.return_ (| + BoolOp.and (| + Compare.eq (| + M.get_field (| M.get_name (| globals, "account" |), "nonce" |), + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + |), + ltac:(M.monadic ( + BoolOp.and (| + Compare.eq (| + M.get_field (| M.get_name (| globals, "account" |), "code" |), + Constant.bytes "" + |), + ltac:(M.monadic ( + Compare.eq (| + M.get_field (| M.get_name (| globals, "account" |), "balance" |), + Constant.int 0 + |) + )) + |) + )) + |) + |) in + M.pure Constant.None_)). + +Definition account_exists_and_is_empty : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "state"; "address" ] |) in + let _ := Constant.str " + Checks if an account exists and has zero nonce, empty code and zero + balance. + + Parameters + ---------- + state: + The state + address: + Address of the account that needs to be checked. + + Returns + ------- + exists_and_is_empty : `bool` + True if an account exists and has zero nonce, empty code and zero + balance, False otherwise. + " in + let _ := M.assign_local (| + "account" , + M.call (| + M.get_name (| globals, "get_account_optional" |), + make_list [ + M.get_name (| globals, "state" |); + M.get_name (| globals, "address" |) + ], + make_dict [] + |) + |) in + let _ := M.return_ (| + BoolOp.and (| + Compare.is_not (| + M.get_name (| globals, "account" |), + Constant.None_ + |), + ltac:(M.monadic ( + BoolOp.and (| + Compare.eq (| + M.get_field (| M.get_name (| globals, "account" |), "nonce" |), + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + |), + ltac:(M.monadic ( + BoolOp.and (| + Compare.eq (| + M.get_field (| M.get_name (| globals, "account" |), "code" |), + Constant.bytes "" + |), + ltac:(M.monadic ( + Compare.eq (| + M.get_field (| M.get_name (| globals, "account" |), "balance" |), + Constant.int 0 + |) + )) + |) + )) + |) + )) + |) + |) in + M.pure Constant.None_)). + +Definition is_account_alive : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "state"; "address" ] |) in + let _ := Constant.str " + Check whether is an account is both in the state and non empty. + + Parameters + ---------- + state: + The state + address: + Address of the account that needs to be checked. + + Returns + ------- + is_alive : `bool` + True if the account is alive. + " in + let _ := M.assign_local (| + "account" , + M.call (| + M.get_name (| globals, "get_account_optional" |), + make_list [ + M.get_name (| globals, "state" |); + M.get_name (| globals, "address" |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.is (| + M.get_name (| globals, "account" |), + Constant.None_ + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + Constant.bool false + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.return_ (| + UnOp.not (| BoolOp.and (| + Compare.eq (| + M.get_field (| M.get_name (| globals, "account" |), "nonce" |), + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + |), + ltac:(M.monadic ( + BoolOp.and (| + Compare.eq (| + M.get_field (| M.get_name (| globals, "account" |), "code" |), + Constant.bytes "" + |), + ltac:(M.monadic ( + Compare.eq (| + M.get_field (| M.get_name (| globals, "account" |), "balance" |), + Constant.int 0 + |) + )) + |) + )) + |) |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_)). + +Definition modify_state : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "state"; "address"; "f" ] |) in + let _ := Constant.str " + Modify an `Account` in the `State`. + " in + let _ := M.call (| + M.get_name (| globals, "set_account" |), + make_list [ + M.get_name (| globals, "state" |); + M.get_name (| globals, "address" |); + M.call (| + M.get_name (| globals, "modify" |), + make_list [ + M.call (| + M.get_name (| globals, "get_account" |), + make_list [ + M.get_name (| globals, "state" |); + M.get_name (| globals, "address" |) + ], + make_dict [] + |); + M.get_name (| globals, "f" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + M.pure Constant.None_)). + +Definition move_ether : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "state"; "sender_address"; "recipient_address"; "amount" ] |) in + let _ := Constant.str " + Move funds between accounts. + " in +(* At stmt: unsupported node type: FunctionDef *) +(* At stmt: unsupported node type: FunctionDef *) + let _ := M.call (| + M.get_name (| globals, "modify_state" |), + make_list [ + M.get_name (| globals, "state" |); + M.get_name (| globals, "sender_address" |); + M.get_name (| globals, "reduce_sender_balance" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "modify_state" |), + make_list [ + M.get_name (| globals, "state" |); + M.get_name (| globals, "recipient_address" |); + M.get_name (| globals, "increase_recipient_balance" |) + ], + make_dict [] + |) in + M.pure Constant.None_)). + +Definition set_account_balance : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "state"; "address"; "amount" ] |) in + let _ := Constant.str " + Sets the balance of an account. + + Parameters + ---------- + state: + The current state. + + address: + Address of the account whose nonce needs to be incremented. + + amount: + The amount that needs to set in balance. + " in +(* At stmt: unsupported node type: FunctionDef *) + let _ := M.call (| + M.get_name (| globals, "modify_state" |), + make_list [ + M.get_name (| globals, "state" |); + M.get_name (| globals, "address" |); + M.get_name (| globals, "set_balance" |) + ], + make_dict [] + |) in + M.pure Constant.None_)). + +Definition touch_account : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "state"; "address" ] |) in + let _ := Constant.str " + Initializes an account to state. + + Parameters + ---------- + state: + The current state. + + address: + The address of the account that need to initialised. + " in + let _ := + (* if *) + M.if_then_else (| + UnOp.not (| M.call (| + M.get_name (| globals, "account_exists" |), + make_list [ + M.get_name (| globals, "state" |); + M.get_name (| globals, "address" |) + ], + make_dict [] + |) |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, "set_account" |), + make_list [ + M.get_name (| globals, "state" |); + M.get_name (| globals, "address" |); + M.get_name (| globals, "EMPTY_ACCOUNT" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + M.pure Constant.None_)). + +Definition increment_nonce : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "state"; "address" ] |) in + let _ := Constant.str " + Increments the nonce of an account. + + Parameters + ---------- + state: + The current state. + + address: + Address of the account whose nonce needs to be incremented. + " in +(* At stmt: unsupported node type: FunctionDef *) + let _ := M.call (| + M.get_name (| globals, "modify_state" |), + make_list [ + M.get_name (| globals, "state" |); + M.get_name (| globals, "address" |); + M.get_name (| globals, "increase_nonce" |) + ], + make_dict [] + |) in + M.pure Constant.None_)). + +Definition set_code : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "state"; "address"; "code" ] |) in + let _ := Constant.str " + Sets Account code. + + Parameters + ---------- + state: + The current state. + + address: + Address of the account whose code needs to be update. + + code: + The bytecode that needs to be set. + " in +(* At stmt: unsupported node type: FunctionDef *) + let _ := M.call (| + M.get_name (| globals, "modify_state" |), + make_list [ + M.get_name (| globals, "state" |); + M.get_name (| globals, "address" |); + M.get_name (| globals, "write_code" |) + ], + make_dict [] + |) in + M.pure Constant.None_)). + +Definition create_ether : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "state"; "address"; "amount" ] |) in + let _ := Constant.str " + Add newly created ether to an account. + + Parameters + ---------- + state: + The current state. + address: + Address of the account to which ether is added. + amount: + The amount of ether to be added to the account of interest. + " in +(* At stmt: unsupported node type: FunctionDef *) + let _ := M.call (| + M.get_name (| globals, "modify_state" |), + make_list [ + M.get_name (| globals, "state" |); + M.get_name (| globals, "address" |); + M.get_name (| globals, "increase_balance" |) + ], + make_dict [] + |) in + M.pure Constant.None_)). + +Definition get_storage_original : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "state"; "address"; "key" ] |) in + let _ := Constant.str " + Get the original value in a storage slot i.e. the value before the current + transaction began. This function reads the value from the snapshots taken + before executing the transaction. + + Parameters + ---------- + state: + The current state. + address: + Address of the account to read the value from. + key: + Key of the storage slot. + " in + let _ := + (* if *) + M.if_then_else (| + Compare.in_ (| + M.get_name (| globals, "address" |), + M.get_field (| M.get_name (| globals, "state" |), "_created_accounts" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign (| + make_tuple [ M.get_name (| globals, "_" |); M.get_name (| globals, "original_trie" |) ], + M.get_subscript (| + M.get_field (| M.get_name (| globals, "state" |), "_snapshots" |), + Constant.int 0 + |) + |) in + let _ := M.assign_local (| + "original_account_trie" , + M.call (| + M.get_field (| M.get_name (| globals, "original_trie" |), "get" |), + make_list [ + M.get_name (| globals, "address" |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.is (| + M.get_name (| globals, "original_account_trie" |), + Constant.None_ + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "original_value" , + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "original_value" , + M.call (| + M.get_name (| globals, "trie_get" |), + make_list [ + M.get_name (| globals, "original_account_trie" |); + M.get_name (| globals, "key" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + )) |) in + let _ := M.assert (| M.call (| + M.get_name (| globals, "isinstance" |), + make_list [ + M.get_name (| globals, "original_value" |); + M.get_name (| globals, "U256" |) + ], + make_dict [] + |) |) in + let _ := M.return_ (| + M.get_name (| globals, "original_value" |) + |) in + M.pure Constant.None_)). diff --git a/CoqOfPython/ethereum/london/transactions.v b/CoqOfPython/ethereum/london/transactions.v new file mode 100644 index 0000000..432578b --- /dev/null +++ b/CoqOfPython/ethereum/london/transactions.v @@ -0,0 +1,293 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.london.transactions". + +Definition expr_1 : Value.t := + Constant.str " +Transactions are atomic units of work created externally to Ethereum and +submitted to be executed. If Ethereum is viewed as a state machine, +transactions are the events that move between states. +". + +Axiom dataclasses_imports_dataclass : + IsImported globals "dataclasses" "dataclass". + +Axiom typing_imports_Tuple : + IsImported globals "typing" "Tuple". +Axiom typing_imports_Union : + IsImported globals "typing" "Union". + +Axiom ethereum_imports_rlp : + IsImported globals "ethereum" "rlp". + +Axiom ethereum_base_types_imports_U64 : + IsImported globals "ethereum.base_types" "U64". +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_Bytes : + IsImported globals "ethereum.base_types" "Bytes". +Axiom ethereum_base_types_imports_Bytes0 : + IsImported globals "ethereum.base_types" "Bytes0". +Axiom ethereum_base_types_imports_Bytes32 : + IsImported globals "ethereum.base_types" "Bytes32". +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". +Axiom ethereum_base_types_imports_slotted_freezable : + IsImported globals "ethereum.base_types" "slotted_freezable". + +Axiom ethereum_exceptions_imports_InvalidBlock : + IsImported globals "ethereum.exceptions" "InvalidBlock". + +Axiom ethereum_london_fork_types_imports_Address : + IsImported globals "ethereum.london.fork_types" "Address". + +Definition TX_BASE_COST : Value.t := M.run ltac:(M.monadic ( + Constant.int 21000 +)). + +Definition TX_DATA_COST_PER_NON_ZERO : Value.t := M.run ltac:(M.monadic ( + Constant.int 16 +)). + +Definition TX_DATA_COST_PER_ZERO : Value.t := M.run ltac:(M.monadic ( + Constant.int 4 +)). + +Definition TX_CREATE_COST : Value.t := M.run ltac:(M.monadic ( + Constant.int 32000 +)). + +Definition TX_ACCESS_LIST_ADDRESS_COST : Value.t := M.run ltac:(M.monadic ( + Constant.int 2400 +)). + +Definition TX_ACCESS_LIST_STORAGE_KEY_COST : Value.t := M.run ltac:(M.monadic ( + Constant.int 1900 +)). + +Definition LegacyTransaction : Value.t := + builtins.make_klass + [] + [ + + ] + [ + + ]. + +Definition AccessListTransaction : Value.t := + builtins.make_klass + [] + [ + + ] + [ + + ]. + +Definition FeeMarketTransaction : Value.t := + builtins.make_klass + [] + [ + + ] + [ + + ]. + +Definition Transaction : Value.t := M.run ltac:(M.monadic ( + M.get_subscript (| + M.get_name (| globals, "Union" |), + make_tuple [ M.get_name (| globals, "LegacyTransaction" |); M.get_name (| globals, "AccessListTransaction" |); M.get_name (| globals, "FeeMarketTransaction" |) ] + |) +)). + +Definition encode_transaction : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "tx" ] |) in + let _ := Constant.str " + Encode a transaction. Needed because non-legacy transactions aren't RLP. + " in + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, "isinstance" |), + make_list [ + M.get_name (| globals, "tx" |); + M.get_name (| globals, "LegacyTransaction" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + M.get_name (| globals, "tx" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, "isinstance" |), + make_list [ + M.get_name (| globals, "tx" |); + M.get_name (| globals, "AccessListTransaction" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + BinOp.add (| + Constant.bytes "01", + M.call (| + M.get_field (| M.get_name (| globals, "rlp" |), "encode" |), + make_list [ + M.get_name (| globals, "tx" |) + ], + make_dict [] + |) + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, "isinstance" |), + make_list [ + M.get_name (| globals, "tx" |); + M.get_name (| globals, "FeeMarketTransaction" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + BinOp.add (| + Constant.bytes "02", + M.call (| + M.get_field (| M.get_name (| globals, "rlp" |), "encode" |), + make_list [ + M.get_name (| globals, "tx" |) + ], + make_dict [] + |) + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.raise (| Some (M.call (| + M.get_name (| globals, "Exception" |), + make_list [ + Constant.str "(* At expr: unsupported node type: JoinedStr *)" + ], + make_dict [] + |)) |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_)). + +Definition decode_transaction : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "tx" ] |) in + let _ := Constant.str " + Decode a transaction. Needed because non-legacy transactions aren't RLP. + " in + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, "isinstance" |), + make_list [ + M.get_name (| globals, "tx" |); + M.get_name (| globals, "Bytes" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_subscript (| + M.get_name (| globals, "tx" |), + Constant.int 0 + |), + Constant.int 1 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + M.call (| + M.get_field (| M.get_name (| globals, "rlp" |), "decode_to" |), + make_list [ + M.get_name (| globals, "AccessListTransaction" |); + M.slice (| + M.get_name (| globals, "tx" |), + Constant.int 1, + Constant.None_, + Constant.None_ + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_subscript (| + M.get_name (| globals, "tx" |), + Constant.int 0 + |), + Constant.int 2 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + M.call (| + M.get_field (| M.get_name (| globals, "rlp" |), "decode_to" |), + make_list [ + M.get_name (| globals, "FeeMarketTransaction" |); + M.slice (| + M.get_name (| globals, "tx" |), + Constant.int 1, + Constant.None_, + Constant.None_ + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, "InvalidBlock" |)) |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.return_ (| + M.get_name (| globals, "tx" |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_)). diff --git a/CoqOfPython/ethereum/london/trie.v b/CoqOfPython/ethereum/london/trie.v new file mode 100644 index 0000000..dac8ce1 --- /dev/null +++ b/CoqOfPython/ethereum/london/trie.v @@ -0,0 +1,1595 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.london.trie". + +Definition expr_1 : Value.t := + Constant.str " +State Trie +^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +The state trie is the structure responsible for storing +`.fork_types.Account` objects. +". + +(* At top_level_stmt: unsupported node type: Import *) + +Axiom dataclasses_imports_dataclass : + IsImported globals "dataclasses" "dataclass". +Axiom dataclasses_imports_field : + IsImported globals "dataclasses" "field". + +Axiom typing_imports_Callable : + IsImported globals "typing" "Callable". +Axiom typing_imports_Dict : + IsImported globals "typing" "Dict". +Axiom typing_imports_Generic : + IsImported globals "typing" "Generic". +Axiom typing_imports_List : + IsImported globals "typing" "List". +Axiom typing_imports_Mapping : + IsImported globals "typing" "Mapping". +Axiom typing_imports_MutableMapping : + IsImported globals "typing" "MutableMapping". +Axiom typing_imports_Optional : + IsImported globals "typing" "Optional". +Axiom typing_imports_Sequence : + IsImported globals "typing" "Sequence". +Axiom typing_imports_TypeVar : + IsImported globals "typing" "TypeVar". +Axiom typing_imports_Union : + IsImported globals "typing" "Union". +Axiom typing_imports_cast : + IsImported globals "typing" "cast". + +Axiom ethereum_berlin_imports_trie : + IsImported globals "ethereum.berlin" "trie". + +Axiom ethereum_crypto_hash_imports_keccak256 : + IsImported globals "ethereum.crypto.hash" "keccak256". + +Axiom ethereum_utils_ensure_imports_ensure : + IsImported globals "ethereum.utils.ensure" "ensure". + +Axiom ethereum_utils_hexadecimal_imports_hex_to_bytes : + IsImported globals "ethereum.utils.hexadecimal" "hex_to_bytes". + +Axiom ethereum_imports_rlp : + IsImported globals "ethereum" "rlp". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_Bytes : + IsImported globals "ethereum.base_types" "Bytes". +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". +Axiom ethereum_base_types_imports_slotted_freezable : + IsImported globals "ethereum.base_types" "slotted_freezable". + +Axiom ethereum_london_blocks_imports_Receipt : + IsImported globals "ethereum.london.blocks" "Receipt". + +Axiom ethereum_london_fork_types_imports_Account : + IsImported globals "ethereum.london.fork_types" "Account". +Axiom ethereum_london_fork_types_imports_Address : + IsImported globals "ethereum.london.fork_types" "Address". +Axiom ethereum_london_fork_types_imports_Root : + IsImported globals "ethereum.london.fork_types" "Root". +Axiom ethereum_london_fork_types_imports_encode_account : + IsImported globals "ethereum.london.fork_types" "encode_account". + +Axiom ethereum_london_transactions_imports_LegacyTransaction : + IsImported globals "ethereum.london.transactions" "LegacyTransaction". + +Definition EMPTY_TRIE_ROOT : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Root" |), + make_list [ + M.call (| + M.get_name (| globals, "hex_to_bytes" |), + make_list [ + Constant.str "56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421" + ], + make_dict [] + |) + ], + make_dict [] + |) +)). + +Definition Node : Value.t := M.run ltac:(M.monadic ( + M.get_subscript (| + M.get_name (| globals, "Union" |), + make_tuple [ M.get_name (| globals, "Account" |); M.get_name (| globals, "Bytes" |); M.get_name (| globals, "LegacyTransaction" |); M.get_name (| globals, "Receipt" |); M.get_name (| globals, "Uint" |); M.get_name (| globals, "U256" |); Constant.None_ ] + |) +)). + +Definition K : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "TypeVar" |), + make_list [ + Constant.str "K" + ], + make_dict [] + |) +)). + +Definition V : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "TypeVar" |), + make_list [ + Constant.str "V"; + M.get_subscript (| + M.get_name (| globals, "Optional" |), + M.get_name (| globals, "Account" |) + |); + M.get_subscript (| + M.get_name (| globals, "Optional" |), + M.get_name (| globals, "Bytes" |) + |); + M.get_name (| globals, "Bytes" |); + M.get_subscript (| + M.get_name (| globals, "Optional" |), + M.get_subscript (| + M.get_name (| globals, "Union" |), + make_tuple [ M.get_name (| globals, "LegacyTransaction" |); M.get_name (| globals, "Bytes" |) ] + |) + |); + M.get_subscript (| + M.get_name (| globals, "Optional" |), + M.get_subscript (| + M.get_name (| globals, "Union" |), + make_tuple [ M.get_name (| globals, "Receipt" |); M.get_name (| globals, "Bytes" |) ] + |) + |); + M.get_name (| globals, "Uint" |); + M.get_name (| globals, "U256" |) + ], + make_dict [] + |) +)). + +Definition LeafNode : Value.t := + builtins.make_klass + [] + [ + + ] + [ + + ]. + +Definition ExtensionNode : Value.t := + builtins.make_klass + [] + [ + + ] + [ + + ]. + +Definition BranchNode : Value.t := + builtins.make_klass + [] + [ + + ] + [ + + ]. + +Definition InternalNode : Value.t := M.run ltac:(M.monadic ( + M.get_subscript (| + M.get_name (| globals, "Union" |), + make_tuple [ M.get_name (| globals, "LeafNode" |); M.get_name (| globals, "ExtensionNode" |); M.get_name (| globals, "BranchNode" |) ] + |) +)). + +Definition encode_internal_node : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "node" ] |) in + let _ := Constant.str " + Encodes a Merkle Trie node into its RLP form. The RLP will then be + serialized into a `Bytes` and hashed unless it is less that 32 bytes + when serialized. + + This function also accepts `None`, representing the absence of a node, + which is encoded to `b""""`. + + Parameters + ---------- + node : Optional[InternalNode] + The node to encode. + + Returns + ------- + encoded : `rlp.RLP` + The node encoded as RLP. + " in +(* At stmt: unsupported node type: AnnAssign *) + let _ := + (* if *) + M.if_then_else (| + Compare.is (| + M.get_name (| globals, "node" |), + Constant.None_ + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "unencoded" , + Constant.bytes "" + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, "isinstance" |), + make_list [ + M.get_name (| globals, "node" |); + M.get_name (| globals, "LeafNode" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "unencoded" , + make_tuple [ M.call (| + M.get_name (| globals, "nibble_list_to_compact" |), + make_list [ + M.get_field (| M.get_name (| globals, "node" |), "rest_of_key" |); + Constant.bool true + ], + make_dict [] + |); M.get_field (| M.get_name (| globals, "node" |), "value" |) ] + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, "isinstance" |), + make_list [ + M.get_name (| globals, "node" |); + M.get_name (| globals, "ExtensionNode" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "unencoded" , + make_tuple [ M.call (| + M.get_name (| globals, "nibble_list_to_compact" |), + make_list [ + M.get_field (| M.get_name (| globals, "node" |), "key_segment" |); + Constant.bool false + ], + make_dict [] + |); M.get_field (| M.get_name (| globals, "node" |), "subnode" |) ] + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, "isinstance" |), + make_list [ + M.get_name (| globals, "node" |); + M.get_name (| globals, "BranchNode" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "unencoded" , + BinOp.add (| + M.get_field (| M.get_name (| globals, "node" |), "subnodes" |), + make_list [ + M.get_field (| M.get_name (| globals, "node" |), "value" |) + ] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.raise (| Some (M.call (| + M.get_name (| globals, "AssertionError" |), + make_list [ + Constant.str "(* At expr: unsupported node type: JoinedStr *)" + ], + make_dict [] + |)) |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "encoded" , + M.call (| + M.get_field (| M.get_name (| globals, "rlp" |), "encode" |), + make_list [ + M.get_name (| globals, "unencoded" |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.lt (| + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_name (| globals, "encoded" |) + ], + make_dict [] + |), + Constant.int 32 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + M.get_name (| globals, "unencoded" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.return_ (| + M.call (| + M.get_name (| globals, "keccak256" |), + make_list [ + M.get_name (| globals, "encoded" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_)). + +Definition encode_node : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "node"; "storage_root" ] |) in + let _ := Constant.str " + Encode a Node for storage in the Merkle Trie. + + Currently mostly an unimplemented stub. + " in + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, "isinstance" |), + make_list [ + M.get_name (| globals, "node" |); + M.get_name (| globals, "Account" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assert (| Compare.is_not (| + M.get_name (| globals, "storage_root" |), + Constant.None_ + |) |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, "encode_account" |), + make_list [ + M.get_name (| globals, "node" |); + M.get_name (| globals, "storage_root" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, "isinstance" |), + make_list [ + M.get_name (| globals, "node" |); + make_tuple [ M.get_name (| globals, "LegacyTransaction" |); M.get_name (| globals, "Receipt" |); M.get_name (| globals, "U256" |) ] + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + M.call (| + M.get_field (| M.get_name (| globals, "rlp" |), "encode" |), + make_list [ + M.call (| + M.get_name (| globals, "cast" |), + make_list [ + M.get_field (| M.get_name (| globals, "rlp" |), "RLP" |); + M.get_name (| globals, "node" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, "isinstance" |), + make_list [ + M.get_name (| globals, "node" |); + M.get_name (| globals, "Bytes" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + M.get_name (| globals, "node" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.return_ (| + M.call (| + M.get_field (| M.get_name (| globals, "previous_trie" |), "encode_node" |), + make_list [ + M.get_name (| globals, "node" |); + M.get_name (| globals, "storage_root" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_)). + +Definition Trie : Value.t := + builtins.make_klass + [(* At base: unsupported node type: Subscript *)] + [ + + ] + [ + + ]. + +Definition copy_trie : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "trie" ] |) in + let _ := Constant.str " + Create a copy of `trie`. Since only frozen objects may be stored in tries, + the contents are reused. + + Parameters + ---------- + trie: `Trie` + Trie to copy. + + Returns + ------- + new_trie : `Trie[K, V]` + A copy of the trie. + " in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, "Trie" |), + make_list [ + M.get_field (| M.get_name (| globals, "trie" |), "secured" |); + M.get_field (| M.get_name (| globals, "trie" |), "default" |); + M.call (| + M.get_field (| M.get_name (| globals, "copy" |), "copy" |), + make_list [ + M.get_field (| M.get_name (| globals, "trie" |), "_data" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Definition trie_set : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "trie"; "key"; "value" ] |) in + let _ := Constant.str " + Stores an item in a Merkle Trie. + + This method deletes the key if `value == trie.default`, because the Merkle + Trie represents the default value by omitting it from the trie. + + Parameters + ---------- + trie: `Trie` + Trie to store in. + key : `Bytes` + Key to lookup. + value : `V` + Node to insert at `key`. + " in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, "value" |), + M.get_field (| M.get_name (| globals, "trie" |), "default" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + Compare.in_ (| + M.get_name (| globals, "key" |), + M.get_field (| M.get_name (| globals, "trie" |), "_data" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.delete (| M.get_subscript (| + M.get_field (| M.get_name (| globals, "trie" |), "_data" |), + M.get_name (| globals, "key" |) + |) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign (| + M.get_subscript (| + M.get_field (| M.get_name (| globals, "trie" |), "_data" |), + M.get_name (| globals, "key" |) + |), + M.get_name (| globals, "value" |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_)). + +Definition trie_get : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "trie"; "key" ] |) in + let _ := Constant.str " + Gets an item from the Merkle Trie. + + This method returns `trie.default` if the key is missing. + + Parameters + ---------- + trie: + Trie to lookup in. + key : + Key to lookup. + + Returns + ------- + node : `V` + Node at `key` in the trie. + " in + let _ := M.return_ (| + M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, "trie" |), "_data" |), "get" |), + make_list [ + M.get_name (| globals, "key" |); + M.get_field (| M.get_name (| globals, "trie" |), "default" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Definition common_prefix_length : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "a"; "b" ] |) in + let _ := Constant.str " + Find the longest common prefix of two sequences. + " in + let _ := + M.for_ (| + M.get_name (| globals, "i" |), + M.call (| + M.get_name (| globals, "range" |), + make_list [ + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_name (| globals, "a" |) + ], + make_dict [] + |) + ], + make_dict [] + |), + ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + BoolOp.or (| + Compare.gt_e (| + M.get_name (| globals, "i" |), + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_name (| globals, "b" |) + ], + make_dict [] + |) + |), + ltac:(M.monadic ( + Compare.not_eq (| + M.get_subscript (| + M.get_name (| globals, "a" |), + M.get_name (| globals, "i" |) + |), + M.get_subscript (| + M.get_name (| globals, "b" |), + M.get_name (| globals, "i" |) + |) + |) + )) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + M.get_name (| globals, "i" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_name (| globals, "a" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Definition nibble_list_to_compact : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "x"; "is_leaf" ] |) in + let _ := Constant.str " + Compresses nibble-list into a standard byte array with a flag. + + A nibble-list is a list of byte values no greater than `15`. The flag is + encoded in high nibble of the highest byte. The flag nibble can be broken + down into two two-bit flags. + + Highest nibble:: + + +---+---+----------+--------+ + | _ | _ | is_leaf | parity | + +---+---+----------+--------+ + 3 2 1 0 + + + The lowest bit of the nibble encodes the parity of the length of the + remaining nibbles -- `0` when even and `1` when odd. The second lowest bit + is used to distinguish leaf and extension nodes. The other two bits are not + used. + + Parameters + ---------- + x : + Array of nibbles. + is_leaf : + True if this is part of a leaf node, or false if it is an extension + node. + + Returns + ------- + compressed : `bytearray` + Compact byte array. + " in + let _ := M.assign_local (| + "compact" , + M.call (| + M.get_name (| globals, "bytearray" |), + make_list [], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + BinOp.mod_ (| + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_name (| globals, "x" |) + ], + make_dict [] + |), + Constant.int 2 + |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_field (| M.get_name (| globals, "compact" |), "append" |), + make_list [ + BinOp.mult (| + Constant.int 16, + BinOp.mult (| + Constant.int 2, + M.get_name (| globals, "is_leaf" |) + |) + |) + ], + make_dict [] + |) in + let _ := + M.for_ (| + M.get_name (| globals, "i" |), + M.call (| + M.get_name (| globals, "range" |), + make_list [ + Constant.int 0; + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_name (| globals, "x" |) + ], + make_dict [] + |); + Constant.int 2 + ], + make_dict [] + |), + ltac:(M.monadic ( + let _ := M.call (| + M.get_field (| M.get_name (| globals, "compact" |), "append" |), + make_list [ + BinOp.add (| + BinOp.mult (| + Constant.int 16, + M.get_subscript (| + M.get_name (| globals, "x" |), + M.get_name (| globals, "i" |) + |) + |), + M.get_subscript (| + M.get_name (| globals, "x" |), + BinOp.add (| + M.get_name (| globals, "i" |), + Constant.int 1 + |) + |) + |) + ], + make_dict [] + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.call (| + M.get_field (| M.get_name (| globals, "compact" |), "append" |), + make_list [ + BinOp.add (| + BinOp.mult (| + Constant.int 16, + BinOp.add (| + BinOp.mult (| + Constant.int 2, + M.get_name (| globals, "is_leaf" |) + |), + Constant.int 1 + |) + |), + M.get_subscript (| + M.get_name (| globals, "x" |), + Constant.int 0 + |) + |) + ], + make_dict [] + |) in + let _ := + M.for_ (| + M.get_name (| globals, "i" |), + M.call (| + M.get_name (| globals, "range" |), + make_list [ + Constant.int 1; + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_name (| globals, "x" |) + ], + make_dict [] + |); + Constant.int 2 + ], + make_dict [] + |), + ltac:(M.monadic ( + let _ := M.call (| + M.get_field (| M.get_name (| globals, "compact" |), "append" |), + make_list [ + BinOp.add (| + BinOp.mult (| + Constant.int 16, + M.get_subscript (| + M.get_name (| globals, "x" |), + M.get_name (| globals, "i" |) + |) + |), + M.get_subscript (| + M.get_name (| globals, "x" |), + BinOp.add (| + M.get_name (| globals, "i" |), + Constant.int 1 + |) + |) + |) + ], + make_dict [] + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + M.pure Constant.None_ + )) |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, "Bytes" |), + make_list [ + M.get_name (| globals, "compact" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Definition bytes_to_nibble_list : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "bytes_" ] |) in + let _ := Constant.str " + Converts a `Bytes` into to a sequence of nibbles (bytes with value < 16). + + Parameters + ---------- + bytes_: + The `Bytes` to convert. + + Returns + ------- + nibble_list : `Bytes` + The `Bytes` in nibble-list format. + " in + let _ := M.assign_local (| + "nibble_list" , + M.call (| + M.get_name (| globals, "bytearray" |), + make_list [ + BinOp.mult (| + Constant.int 2, + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_name (| globals, "bytes_" |) + ], + make_dict [] + |) + |) + ], + make_dict [] + |) + |) in + let _ := + M.for_ (| + make_tuple [ M.get_name (| globals, "byte_index" |); M.get_name (| globals, "byte" |) ], + M.call (| + M.get_name (| globals, "enumerate" |), + make_list [ + M.get_name (| globals, "bytes_" |) + ], + make_dict [] + |), + ltac:(M.monadic ( + let _ := M.assign (| + M.get_subscript (| + M.get_name (| globals, "nibble_list" |), + BinOp.mult (| + M.get_name (| globals, "byte_index" |), + Constant.int 2 + |) + |), + BinOp.r_shift (| + BinOp.bit_and (| + M.get_name (| globals, "byte" |), + Constant.int 240 + |), + Constant.int 4 + |) + |) in + let _ := M.assign (| + M.get_subscript (| + M.get_name (| globals, "nibble_list" |), + BinOp.add (| + BinOp.mult (| + M.get_name (| globals, "byte_index" |), + Constant.int 2 + |), + Constant.int 1 + |) + |), + BinOp.bit_and (| + M.get_name (| globals, "byte" |), + Constant.int 15 + |) + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, "Bytes" |), + make_list [ + M.get_name (| globals, "nibble_list" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Definition _prepare_trie : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "trie"; "get_storage_root" ] |) in + let _ := Constant.str " + Prepares the trie for root calculation. Removes values that are empty, + hashes the keys (if `secured == True`) and encodes all the nodes. + + Parameters + ---------- + trie : + The `Trie` to prepare. + get_storage_root : + Function to get the storage root of an account. Needed to encode + `Account` objects. + + Returns + ------- + out : `Mapping[ethereum.base_types.Bytes, Node]` + Object with keys mapped to nibble-byte form. + " in +(* At stmt: unsupported node type: AnnAssign *) + let _ := + M.for_ (| + make_tuple [ M.get_name (| globals, "preimage" |); M.get_name (| globals, "value" |) ], + M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, "trie" |), "_data" |), "items" |), + make_list [], + make_dict [] + |), + ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, "isinstance" |), + make_list [ + M.get_name (| globals, "value" |); + M.get_name (| globals, "Account" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assert (| Compare.is_not (| + M.get_name (| globals, "get_storage_root" |), + Constant.None_ + |) |) in + let _ := M.assign_local (| + "address" , + M.call (| + M.get_name (| globals, "Address" |), + make_list [ + M.get_name (| globals, "preimage" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "encoded_value" , + M.call (| + M.get_name (| globals, "encode_node" |), + make_list [ + M.get_name (| globals, "value" |); + M.call (| + M.get_name (| globals, "get_storage_root" |), + make_list [ + M.get_name (| globals, "address" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "encoded_value" , + M.call (| + M.get_name (| globals, "encode_node" |), + make_list [ + M.get_name (| globals, "value" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + )) |) in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + Compare.not_eq (| + M.get_name (| globals, "encoded_value" |), + Constant.bytes "" + |); + M.get_name (| globals, "AssertionError" |) + ], + make_dict [] + |) in +(* At stmt: unsupported node type: AnnAssign *) + let _ := + (* if *) + M.if_then_else (| + M.get_field (| M.get_name (| globals, "trie" |), "secured" |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "key" , + M.call (| + M.get_name (| globals, "keccak256" |), + make_list [ + M.get_name (| globals, "preimage" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "key" , + M.get_name (| globals, "preimage" |) + |) in + M.pure Constant.None_ + )) |) in + let _ := M.assign (| + M.get_subscript (| + M.get_name (| globals, "mapped" |), + M.call (| + M.get_name (| globals, "bytes_to_nibble_list" |), + make_list [ + M.get_name (| globals, "key" |) + ], + make_dict [] + |) + |), + M.get_name (| globals, "encoded_value" |) + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := M.return_ (| + M.get_name (| globals, "mapped" |) + |) in + M.pure Constant.None_)). + +Definition root : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "trie"; "get_storage_root" ] |) in + let _ := Constant.str " + Computes the root of a modified merkle patricia trie (MPT). + + Parameters + ---------- + trie : + `Trie` to get the root of. + get_storage_root : + Function to get the storage root of an account. Needed to encode + `Account` objects. + + + Returns + ------- + root : `.fork_types.Root` + MPT root of the underlying key-value pairs. + " in + let _ := M.assign_local (| + "obj" , + M.call (| + M.get_name (| globals, "_prepare_trie" |), + make_list [ + M.get_name (| globals, "trie" |); + M.get_name (| globals, "get_storage_root" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "root_node" , + M.call (| + M.get_name (| globals, "encode_internal_node" |), + make_list [ + M.call (| + M.get_name (| globals, "patricialize" |), + make_list [ + M.get_name (| globals, "obj" |); + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.lt (| + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.call (| + M.get_field (| M.get_name (| globals, "rlp" |), "encode" |), + make_list [ + M.get_name (| globals, "root_node" |) + ], + make_dict [] + |) + ], + make_dict [] + |), + Constant.int 32 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + M.call (| + M.get_name (| globals, "keccak256" |), + make_list [ + M.call (| + M.get_field (| M.get_name (| globals, "rlp" |), "encode" |), + make_list [ + M.get_name (| globals, "root_node" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assert (| M.call (| + M.get_name (| globals, "isinstance" |), + make_list [ + M.get_name (| globals, "root_node" |); + M.get_name (| globals, "Bytes" |) + ], + make_dict [] + |) |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, "Root" |), + make_list [ + M.get_name (| globals, "root_node" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_)). + +Definition patricialize : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "obj"; "level" ] |) in + let _ := Constant.str " + Structural composition function. + + Used to recursively patricialize and merkleize a dictionary. Includes + memoization of the tree structure and hashes. + + Parameters + ---------- + obj : + Underlying trie key-value pairs, with keys in nibble-list format. + level : + Current trie level. + + Returns + ------- + node : `ethereum.base_types.Bytes` + Root node of `obj`. + " in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_name (| globals, "obj" |) + ], + make_dict [] + |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + Constant.None_ + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "arbitrary_key" , + M.call (| + M.get_name (| globals, "next" |), + make_list [ + M.call (| + M.get_name (| globals, "iter" |), + make_list [ + M.get_name (| globals, "obj" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_name (| globals, "obj" |) + ], + make_dict [] + |), + Constant.int 1 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "leaf" , + M.call (| + M.get_name (| globals, "LeafNode" |), + make_list [ + M.slice (| + M.get_name (| globals, "arbitrary_key" |), + M.get_name (| globals, "level" |), + Constant.None_, + Constant.None_ + |); + M.get_subscript (| + M.get_name (| globals, "obj" |), + M.get_name (| globals, "arbitrary_key" |) + |) + ], + make_dict [] + |) + |) in + let _ := M.return_ (| + M.get_name (| globals, "leaf" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "substring" , + M.slice (| + M.get_name (| globals, "arbitrary_key" |), + M.get_name (| globals, "level" |), + Constant.None_, + Constant.None_ + |) + |) in + let _ := M.assign_local (| + "prefix_length" , + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_name (| globals, "substring" |) + ], + make_dict [] + |) + |) in + let _ := + M.for_ (| + M.get_name (| globals, "key" |), + M.get_name (| globals, "obj" |), + ltac:(M.monadic ( + let _ := M.assign_local (| + "prefix_length" , + M.call (| + M.get_name (| globals, "min" |), + make_list [ + M.get_name (| globals, "prefix_length" |); + M.call (| + M.get_name (| globals, "common_prefix_length" |), + make_list [ + M.get_name (| globals, "substring" |); + M.slice (| + M.get_name (| globals, "key" |), + M.get_name (| globals, "level" |), + Constant.None_, + Constant.None_ + |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, "prefix_length" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.break (| |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.gt (| + M.get_name (| globals, "prefix_length" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "prefix" , + M.slice (| + M.get_name (| globals, "arbitrary_key" |), + M.get_name (| globals, "level" |), + BinOp.add (| + M.get_name (| globals, "level" |), + M.get_name (| globals, "prefix_length" |) + |), + Constant.None_ + |) + |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, "ExtensionNode" |), + make_list [ + M.get_name (| globals, "prefix" |); + M.call (| + M.get_name (| globals, "encode_internal_node" |), + make_list [ + M.call (| + M.get_name (| globals, "patricialize" |), + make_list [ + M.get_name (| globals, "obj" |); + BinOp.add (| + M.get_name (| globals, "level" |), + M.get_name (| globals, "prefix_length" |) + |) + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in +(* At stmt: unsupported node type: AnnAssign *) + let _ := + M.for_ (| + M.get_name (| globals, "_" |), + M.call (| + M.get_name (| globals, "range" |), + make_list [ + Constant.int 16 + ], + make_dict [] + |), + ltac:(M.monadic ( + let _ := M.call (| + M.get_field (| M.get_name (| globals, "branches" |), "append" |), + make_list [ + Constant.str "(* At expr: unsupported node type: Dict *)" + ], + make_dict [] + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := M.assign_local (| + "value" , + Constant.bytes "" + |) in + let _ := + M.for_ (| + M.get_name (| globals, "key" |), + M.get_name (| globals, "obj" |), + ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_name (| globals, "key" |) + ], + make_dict [] + |), + M.get_name (| globals, "level" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, "isinstance" |), + make_list [ + M.get_subscript (| + M.get_name (| globals, "obj" |), + M.get_name (| globals, "key" |) + |); + make_tuple [ M.get_name (| globals, "Account" |); M.get_name (| globals, "Receipt" |); M.get_name (| globals, "Uint" |) ] + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, "AssertionError" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "value" , + M.get_subscript (| + M.get_name (| globals, "obj" |), + M.get_name (| globals, "key" |) + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign (| + M.get_subscript (| + M.get_subscript (| + M.get_name (| globals, "branches" |), + M.get_subscript (| + M.get_name (| globals, "key" |), + M.get_name (| globals, "level" |) + |) + |), + M.get_name (| globals, "key" |) + |), + M.get_subscript (| + M.get_name (| globals, "obj" |), + M.get_name (| globals, "key" |) + |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, "BranchNode" |), + make_list [ + Constant.str "(* At expr: unsupported node type: ListComp *)"; + M.get_name (| globals, "value" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). diff --git a/CoqOfPython/ethereum/london/utils/__init__.v b/CoqOfPython/ethereum/london/utils/__init__.v new file mode 100644 index 0000000..3cb26eb --- /dev/null +++ b/CoqOfPython/ethereum/london/utils/__init__.v @@ -0,0 +1,8 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.london.utils.__init__". + +Definition expr_1 : Value.t := + Constant.str " +Utility functions unique to this particular fork. +". diff --git a/CoqOfPython/ethereum/london/utils/address.v b/CoqOfPython/ethereum/london/utils/address.v new file mode 100644 index 0000000..f43bd88 --- /dev/null +++ b/CoqOfPython/ethereum/london/utils/address.v @@ -0,0 +1,227 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.london.utils.address". + +Definition expr_1 : Value.t := + Constant.str " +Hardfork Utility Functions For Addresses +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Address specific functions used in this london version of +specification. +". + +Axiom typing_imports_Union : + IsImported globals "typing" "Union". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_Bytes32 : + IsImported globals "ethereum.base_types" "Bytes32". +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". + +Axiom ethereum_crypto_hash_imports_keccak256 : + IsImported globals "ethereum.crypto.hash" "keccak256". + +Axiom ethereum_utils_byte_imports_left_pad_zero_bytes : + IsImported globals "ethereum.utils.byte" "left_pad_zero_bytes". + +Axiom ethereum_imports_rlp : + IsImported globals "ethereum" "rlp". + +Axiom ethereum_london_fork_types_imports_Address : + IsImported globals "ethereum.london.fork_types" "Address". + +Definition to_address : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "data" ] |) in + let _ := Constant.str " + Convert a Uint or U256 value to a valid address (20 bytes). + + Parameters + ---------- + data : + The string to be converted to bytes. + + Returns + ------- + address : `Address` + The obtained address. + " in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, "Address" |), + make_list [ + M.slice (| + M.call (| + M.get_field (| M.get_name (| globals, "data" |), "to_be_bytes32" |), + make_list [], + make_dict [] + |), + UnOp.sub (| Constant.int 20 |), + Constant.None_, + Constant.None_ + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Definition compute_contract_address : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "address"; "nonce" ] |) in + let _ := Constant.str " + Computes address of the new account that needs to be created. + + Parameters + ---------- + address : + The address of the account that wants to create the new account. + nonce : + The transaction count of the account that wants to create the new + account. + + Returns + ------- + address: `Address` + The computed address of the new account. + " in + let _ := M.assign_local (| + "computed_address" , + M.call (| + M.get_name (| globals, "keccak256" |), + make_list [ + M.call (| + M.get_field (| M.get_name (| globals, "rlp" |), "encode" |), + make_list [ + make_list [ + M.get_name (| globals, "address" |); + M.get_name (| globals, "nonce" |) + ] + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "canonical_address" , + M.slice (| + M.get_name (| globals, "computed_address" |), + UnOp.sub (| Constant.int 20 |), + Constant.None_, + Constant.None_ + |) + |) in + let _ := M.assign_local (| + "padded_address" , + M.call (| + M.get_name (| globals, "left_pad_zero_bytes" |), + make_list [ + M.get_name (| globals, "canonical_address" |); + Constant.int 20 + ], + make_dict [] + |) + |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, "Address" |), + make_list [ + M.get_name (| globals, "padded_address" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Definition compute_create2_contract_address : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "address"; "salt"; "call_data" ] |) in + let _ := Constant.str " + Computes address of the new account that needs to be created, which is + based on the sender address, salt and the call data as well. + + Parameters + ---------- + address : + The address of the account that wants to create the new account. + salt : + Address generation salt. + call_data : + The code of the new account which is to be created. + + Returns + ------- + address: `ethereum.london.fork_types.Address` + The computed address of the new account. + " in + let _ := M.assign_local (| + "preimage" , + BinOp.add (| + BinOp.add (| + BinOp.add (| + Constant.bytes "ff", + M.get_name (| globals, "address" |) + |), + M.get_name (| globals, "salt" |) + |), + M.call (| + M.get_name (| globals, "keccak256" |), + make_list [ + M.get_name (| globals, "call_data" |) + ], + make_dict [] + |) + |) + |) in + let _ := M.assign_local (| + "computed_address" , + M.call (| + M.get_name (| globals, "keccak256" |), + make_list [ + M.get_name (| globals, "preimage" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "canonical_address" , + M.slice (| + M.get_name (| globals, "computed_address" |), + UnOp.sub (| Constant.int 20 |), + Constant.None_, + Constant.None_ + |) + |) in + let _ := M.assign_local (| + "padded_address" , + M.call (| + M.get_name (| globals, "left_pad_zero_bytes" |), + make_list [ + M.get_name (| globals, "canonical_address" |); + Constant.int 20 + ], + make_dict [] + |) + |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, "Address" |), + make_list [ + M.get_name (| globals, "padded_address" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). diff --git a/CoqOfPython/ethereum/london/utils/hexadecimal.v b/CoqOfPython/ethereum/london/utils/hexadecimal.v new file mode 100644 index 0000000..94f210a --- /dev/null +++ b/CoqOfPython/ethereum/london/utils/hexadecimal.v @@ -0,0 +1,153 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.london.utils.hexadecimal". + +Definition expr_1 : Value.t := + Constant.str " +Utility Functions For Hexadecimal Strings +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Hexadecimal utility functions used in this specification, specific to +London types. +". + +Axiom ethereum_utils_hexadecimal_imports_remove_hex_prefix : + IsImported globals "ethereum.utils.hexadecimal" "remove_hex_prefix". + +Axiom ethereum_london_fork_types_imports_Address : + IsImported globals "ethereum.london.fork_types" "Address". +Axiom ethereum_london_fork_types_imports_Bloom : + IsImported globals "ethereum.london.fork_types" "Bloom". +Axiom ethereum_london_fork_types_imports_Root : + IsImported globals "ethereum.london.fork_types" "Root". + +Definition hex_to_root : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "hex_string" ] |) in + let _ := Constant.str " + Convert hex string to trie root. + + Parameters + ---------- + hex_string : + The hexadecimal string to be converted to trie root. + + Returns + ------- + root : `Root` + Trie root obtained from the given hexadecimal string. + " in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, "Root" |), + make_list [ + M.call (| + M.get_field (| M.get_name (| globals, "bytes" |), "fromhex" |), + make_list [ + M.call (| + M.get_name (| globals, "remove_hex_prefix" |), + make_list [ + M.get_name (| globals, "hex_string" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Definition hex_to_bloom : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "hex_string" ] |) in + let _ := Constant.str " + Convert hex string to bloom. + + Parameters + ---------- + hex_string : + The hexadecimal string to be converted to bloom. + + Returns + ------- + bloom : `Bloom` + Bloom obtained from the given hexadecimal string. + " in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, "Bloom" |), + make_list [ + M.call (| + M.get_field (| M.get_name (| globals, "bytes" |), "fromhex" |), + make_list [ + M.call (| + M.get_name (| globals, "remove_hex_prefix" |), + make_list [ + M.get_name (| globals, "hex_string" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Definition hex_to_address : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "hex_string" ] |) in + let _ := Constant.str " + Convert hex string to Address (20 bytes). + + Parameters + ---------- + hex_string : + The hexadecimal string to be converted to Address. + + Returns + ------- + address : `Address` + The address obtained from the given hexadecimal string. + " in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, "Address" |), + make_list [ + M.call (| + M.get_field (| M.get_name (| globals, "bytes" |), "fromhex" |), + make_list [ + M.call (| + M.get_field (| M.call (| + M.get_name (| globals, "remove_hex_prefix" |), + make_list [ + M.get_name (| globals, "hex_string" |) + ], + make_dict [] + |), "rjust" |), + make_list [ + Constant.int 40; + Constant.str "0" + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). diff --git a/CoqOfPython/ethereum/london/utils/message.v b/CoqOfPython/ethereum/london/utils/message.v new file mode 100644 index 0000000..573dcf4 --- /dev/null +++ b/CoqOfPython/ethereum/london/utils/message.v @@ -0,0 +1,266 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.london.utils.message". + +Definition expr_1 : Value.t := + Constant.str " +Hardfork Utility Functions For The Message Data-structure +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Message specific functions used in this london version of +specification. +". + +Axiom typing_imports_FrozenSet : + IsImported globals "typing" "FrozenSet". +Axiom typing_imports_Optional : + IsImported globals "typing" "Optional". +Axiom typing_imports_Tuple : + IsImported globals "typing" "Tuple". +Axiom typing_imports_Union : + IsImported globals "typing" "Union". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_Bytes : + IsImported globals "ethereum.base_types" "Bytes". +Axiom ethereum_base_types_imports_Bytes0 : + IsImported globals "ethereum.base_types" "Bytes0". +Axiom ethereum_base_types_imports_Bytes32 : + IsImported globals "ethereum.base_types" "Bytes32". +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". + +Axiom ethereum_london_fork_types_imports_Address : + IsImported globals "ethereum.london.fork_types" "Address". + +Axiom ethereum_london_state_imports_get_account : + IsImported globals "ethereum.london.state" "get_account". + +Axiom ethereum_london_vm_imports_Environment : + IsImported globals "ethereum.london.vm" "Environment". +Axiom ethereum_london_vm_imports_Message : + IsImported globals "ethereum.london.vm" "Message". + +Axiom ethereum_london_vm_precompiled_contracts_mapping_imports_PRE_COMPILED_CONTRACTS : + IsImported globals "ethereum.london.vm.precompiled_contracts.mapping" "PRE_COMPILED_CONTRACTS". + +Axiom ethereum_london_utils_address_imports_compute_contract_address : + IsImported globals "ethereum.london.utils.address" "compute_contract_address". + +Definition prepare_message : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "caller"; "target"; "value"; "data"; "gas"; "env"; "code_address"; "should_transfer_value"; "is_static"; "preaccessed_addresses"; "preaccessed_storage_keys" ] |) in + let _ := Constant.str " + Execute a transaction against the provided environment. + + Parameters + ---------- + caller : + Address which initiated the transaction + target : + Address whose code will be executed + value : + Value to be transferred. + data : + Array of bytes provided to the code in `target`. + gas : + Gas provided for the code in `target`. + env : + Environment for the Ethereum Virtual Machine. + code_address : + This is usually same as the `target` address except when an alternative + accounts code needs to be executed. + eg. `CALLCODE` calling a precompile. + should_transfer_value : + if True ETH should be transferred while executing a message call. + is_static: + if True then it prevents all state-changing operations from being + executed. + preaccessed_addresses: + Addresses that should be marked as accessed prior to the message call + preaccessed_storage_keys: + Storage keys that should be marked as accessed prior to the message + call + + Returns + ------- + message: `ethereum.london.vm.Message` + Items containing contract creation or message call specific data. + " in + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, "isinstance" |), + make_list [ + M.get_name (| globals, "target" |); + M.get_name (| globals, "Bytes0" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "current_target" , + M.call (| + M.get_name (| globals, "compute_contract_address" |), + make_list [ + M.get_name (| globals, "caller" |); + BinOp.sub (| + M.get_field (| M.call (| + M.get_name (| globals, "get_account" |), + make_list [ + M.get_field (| M.get_name (| globals, "env" |), "state" |); + M.get_name (| globals, "caller" |) + ], + make_dict [] + |), "nonce" |), + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 1 + ], + make_dict [] + |) + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "msg_data" , + M.call (| + M.get_name (| globals, "Bytes" |), + make_list [ + Constant.bytes "" + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "code" , + M.get_name (| globals, "data" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, "isinstance" |), + make_list [ + M.get_name (| globals, "target" |); + M.get_name (| globals, "Address" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "current_target" , + M.get_name (| globals, "target" |) + |) in + let _ := M.assign_local (| + "msg_data" , + M.get_name (| globals, "data" |) + |) in + let _ := M.assign_local (| + "code" , + M.get_field (| M.call (| + M.get_name (| globals, "get_account" |), + make_list [ + M.get_field (| M.get_name (| globals, "env" |), "state" |); + M.get_name (| globals, "target" |) + ], + make_dict [] + |), "code" |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.is (| + M.get_name (| globals, "code_address" |), + Constant.None_ + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "code_address" , + M.get_name (| globals, "target" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.raise (| Some (M.call (| + M.get_name (| globals, "AssertionError" |), + make_list [ + Constant.str "Target must be address or empty bytes" + ], + make_dict [] + |)) |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "accessed_addresses" , + M.call (| + M.get_name (| globals, "set" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_field (| M.get_name (| globals, "accessed_addresses" |), "add" |), + make_list [ + M.get_name (| globals, "current_target" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_field (| M.get_name (| globals, "accessed_addresses" |), "add" |), + make_list [ + M.get_name (| globals, "caller" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_field (| M.get_name (| globals, "accessed_addresses" |), "update" |), + make_list [ + M.call (| + M.get_field (| M.get_name (| globals, "PRE_COMPILED_CONTRACTS" |), "keys" |), + make_list [], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_field (| M.get_name (| globals, "accessed_addresses" |), "update" |), + make_list [ + M.get_name (| globals, "preaccessed_addresses" |) + ], + make_dict [] + |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, "Message" |), + make_list [], + make_dict [] + |) + |) in + M.pure Constant.None_)). diff --git a/CoqOfPython/ethereum/london/vm/__init__.v b/CoqOfPython/ethereum/london/vm/__init__.v new file mode 100644 index 0000000..9d60f4a --- /dev/null +++ b/CoqOfPython/ethereum/london/vm/__init__.v @@ -0,0 +1,260 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.london.vm.__init__". + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +The abstract computer which runs the code stored in an +`.fork_types.Account`. +". + +Axiom dataclasses_imports_dataclass : + IsImported globals "dataclasses" "dataclass". + +Axiom typing_imports_List : + IsImported globals "typing" "List". +Axiom typing_imports_Optional : + IsImported globals "typing" "Optional". +Axiom typing_imports_Set : + IsImported globals "typing" "Set". +Axiom typing_imports_Tuple : + IsImported globals "typing" "Tuple". +Axiom typing_imports_Union : + IsImported globals "typing" "Union". + +Axiom ethereum_base_types_imports_U64 : + IsImported globals "ethereum.base_types" "U64". +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_Bytes : + IsImported globals "ethereum.base_types" "Bytes". +Axiom ethereum_base_types_imports_Bytes0 : + IsImported globals "ethereum.base_types" "Bytes0". +Axiom ethereum_base_types_imports_Bytes32 : + IsImported globals "ethereum.base_types" "Bytes32". +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". + +Axiom ethereum_crypto_hash_imports_Hash32 : + IsImported globals "ethereum.crypto.hash" "Hash32". + +Axiom ethereum_london_blocks_imports_Log : + IsImported globals "ethereum.london.blocks" "Log". + +Axiom ethereum_london_fork_types_imports_Address : + IsImported globals "ethereum.london.fork_types" "Address". + +Axiom ethereum_london_state_imports_State : + IsImported globals "ethereum.london.state" "State". +Axiom ethereum_london_state_imports_account_exists_and_is_empty : + IsImported globals "ethereum.london.state" "account_exists_and_is_empty". + +Axiom ethereum_london_vm_precompiled_contracts_imports_RIPEMD160_ADDRESS : + IsImported globals "ethereum.london.vm.precompiled_contracts" "RIPEMD160_ADDRESS". + +Definition __all__ : Value.t := M.run ltac:(M.monadic ( + make_tuple [ Constant.str "Environment"; Constant.str "Evm"; Constant.str "Message" ] +)). + +Definition Environment : Value.t := + builtins.make_klass + [] + [ + + ] + [ + + ]. + +Definition Message : Value.t := + builtins.make_klass + [] + [ + + ] + [ + + ]. + +Definition Evm : Value.t := + builtins.make_klass + [] + [ + + ] + [ + + ]. + +Definition incorporate_child_on_success : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm"; "child_evm" ] |) in + let _ := Constant.str " + Incorporate the state of a successful `child_evm` into the parent `evm`. + + Parameters + ---------- + evm : + The parent `EVM`. + child_evm : + The child evm to incorporate. + " in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "gas_left" |), + M.get_field (| M.get_name (| globals, "child_evm" |), "gas_left" |) + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "logs" |), + M.get_field (| M.get_name (| globals, "child_evm" |), "logs" |) + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "refund_counter" |), + M.get_field (| M.get_name (| globals, "child_evm" |), "refund_counter" |) + |) in + let _ := M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "accounts_to_delete" |), "update" |), + make_list [ + M.get_field (| M.get_name (| globals, "child_evm" |), "accounts_to_delete" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "touched_accounts" |), "update" |), + make_list [ + M.get_field (| M.get_name (| globals, "child_evm" |), "touched_accounts" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, "account_exists_and_is_empty" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "env" |), "state" |); + M.get_field (| M.get_field (| M.get_name (| globals, "child_evm" |), "message" |), "current_target" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "touched_accounts" |), "add" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "child_evm" |), "message" |), "current_target" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "accessed_addresses" |), "update" |), + make_list [ + M.get_field (| M.get_name (| globals, "child_evm" |), "accessed_addresses" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "accessed_storage_keys" |), "update" |), + make_list [ + M.get_field (| M.get_name (| globals, "child_evm" |), "accessed_storage_keys" |) + ], + make_dict [] + |) in + M.pure Constant.None_)). + +Definition incorporate_child_on_error : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm"; "child_evm" ] |) in + let _ := Constant.str " + Incorporate the state of an unsuccessful `child_evm` into the parent `evm`. + + Parameters + ---------- + evm : + The parent `EVM`. + child_evm : + The child evm to incorporate. + " in + let _ := + (* if *) + M.if_then_else (| + Compare.in_ (| + M.get_name (| globals, "RIPEMD160_ADDRESS" |), + M.get_field (| M.get_name (| globals, "child_evm" |), "touched_accounts" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "touched_accounts" |), "add" |), + make_list [ + M.get_name (| globals, "RIPEMD160_ADDRESS" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_field (| M.get_field (| M.get_name (| globals, "child_evm" |), "message" |), "current_target" |), + M.get_name (| globals, "RIPEMD160_ADDRESS" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, "account_exists_and_is_empty" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "env" |), "state" |); + M.get_field (| M.get_field (| M.get_name (| globals, "child_evm" |), "message" |), "current_target" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "touched_accounts" |), "add" |), + make_list [ + M.get_name (| globals, "RIPEMD160_ADDRESS" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "gas_left" |), + M.get_field (| M.get_name (| globals, "child_evm" |), "gas_left" |) + |) in + M.pure Constant.None_)). diff --git a/CoqOfPython/ethereum/london/vm/exceptions.v b/CoqOfPython/ethereum/london/vm/exceptions.v new file mode 100644 index 0000000..277efd6 --- /dev/null +++ b/CoqOfPython/ethereum/london/vm/exceptions.v @@ -0,0 +1,171 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.london.vm.exceptions". + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) Exceptions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Exceptions which cause the EVM to halt exceptionally. +". + +Axiom ethereum_exceptions_imports_EthereumException : + IsImported globals "ethereum.exceptions" "EthereumException". + +Definition ExceptionalHalt : Value.t := + builtins.make_klass + [(globals, "EthereumException")] + [ + + ] + [ + + ]. + +Definition Revert : Value.t := + builtins.make_klass + [(globals, "EthereumException")] + [ + + ] + [ + + ]. + +Definition StackUnderflowError : Value.t := + builtins.make_klass + [(globals, "ExceptionalHalt")] + [ + + ] + [ + + ]. + +Definition StackOverflowError : Value.t := + builtins.make_klass + [(globals, "ExceptionalHalt")] + [ + + ] + [ + + ]. + +Definition OutOfGasError : Value.t := + builtins.make_klass + [(globals, "ExceptionalHalt")] + [ + + ] + [ + + ]. + +Definition InvalidOpcode : Value.t := + builtins.make_klass + [(globals, "ExceptionalHalt")] + [ + + ] + [ + ( + "__init__", + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "self"; "code" ] |) in + let _ := M.call (| + M.get_field (| M.call (| + M.get_name (| globals, "super" |), + make_list [], + make_dict [] + |), "__init__" |), + make_list [ + M.get_name (| globals, "code" |) + ], + make_dict [] + |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, "self" |), "code" |), + M.get_name (| globals, "code" |) + |) in + M.pure Constant.None_)) + ) + ]. + +Definition InvalidJumpDestError : Value.t := + builtins.make_klass + [(globals, "ExceptionalHalt")] + [ + + ] + [ + + ]. + +Definition StackDepthLimitError : Value.t := + builtins.make_klass + [(globals, "ExceptionalHalt")] + [ + + ] + [ + + ]. + +Definition WriteInStaticContext : Value.t := + builtins.make_klass + [(globals, "ExceptionalHalt")] + [ + + ] + [ + + ]. + +Definition OutOfBoundsRead : Value.t := + builtins.make_klass + [(globals, "ExceptionalHalt")] + [ + + ] + [ + + ]. + +Definition InvalidParameter : Value.t := + builtins.make_klass + [(globals, "ExceptionalHalt")] + [ + + ] + [ + + ]. + +Definition InvalidContractPrefix : Value.t := + builtins.make_klass + [(globals, "ExceptionalHalt")] + [ + + ] + [ + + ]. + +Definition AddressCollision : Value.t := + builtins.make_klass + [(globals, "ExceptionalHalt")] + [ + + ] + [ + + ]. diff --git a/CoqOfPython/ethereum/london/vm/gas.v b/CoqOfPython/ethereum/london/vm/gas.v new file mode 100644 index 0000000..08eb313 --- /dev/null +++ b/CoqOfPython/ethereum/london/vm/gas.v @@ -0,0 +1,912 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.london.vm.gas". + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) Gas +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +EVM gas constants and calculators. +". + +Axiom dataclasses_imports_dataclass : + IsImported globals "dataclasses" "dataclass". + +Axiom typing_imports_List : + IsImported globals "typing" "List". +Axiom typing_imports_Tuple : + IsImported globals "typing" "Tuple". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". + +Axiom ethereum_trace_imports_GasAndRefund : + IsImported globals "ethereum.trace" "GasAndRefund". +Axiom ethereum_trace_imports_evm_trace : + IsImported globals "ethereum.trace" "evm_trace". + +Axiom ethereum_utils_numeric_imports_ceil32 : + IsImported globals "ethereum.utils.numeric" "ceil32". + +Axiom ethereum_london_vm_imports_Evm : + IsImported globals "ethereum.london.vm" "Evm". + +Axiom ethereum_london_vm_exceptions_imports_OutOfGasError : + IsImported globals "ethereum.london.vm.exceptions" "OutOfGasError". + +Definition GAS_JUMPDEST : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 1 + ], + make_dict [] + |) +)). + +Definition GAS_BASE : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 2 + ], + make_dict [] + |) +)). + +Definition GAS_VERY_LOW : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 3 + ], + make_dict [] + |) +)). + +Definition GAS_STORAGE_SET : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 20000 + ], + make_dict [] + |) +)). + +Definition GAS_STORAGE_UPDATE : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 5000 + ], + make_dict [] + |) +)). + +Definition GAS_STORAGE_CLEAR_REFUND : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 4800 + ], + make_dict [] + |) +)). + +Definition GAS_LOW : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 5 + ], + make_dict [] + |) +)). + +Definition GAS_MID : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 8 + ], + make_dict [] + |) +)). + +Definition GAS_HIGH : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 10 + ], + make_dict [] + |) +)). + +Definition GAS_EXPONENTIATION : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 10 + ], + make_dict [] + |) +)). + +Definition GAS_EXPONENTIATION_PER_BYTE : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 50 + ], + make_dict [] + |) +)). + +Definition GAS_MEMORY : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 3 + ], + make_dict [] + |) +)). + +Definition GAS_KECCAK256 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 30 + ], + make_dict [] + |) +)). + +Definition GAS_KECCAK256_WORD : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 6 + ], + make_dict [] + |) +)). + +Definition GAS_COPY : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 3 + ], + make_dict [] + |) +)). + +Definition GAS_BLOCK_HASH : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 20 + ], + make_dict [] + |) +)). + +Definition GAS_LOG : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 375 + ], + make_dict [] + |) +)). + +Definition GAS_LOG_DATA : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 8 + ], + make_dict [] + |) +)). + +Definition GAS_LOG_TOPIC : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 375 + ], + make_dict [] + |) +)). + +Definition GAS_CREATE : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 32000 + ], + make_dict [] + |) +)). + +Definition GAS_CODE_DEPOSIT : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 200 + ], + make_dict [] + |) +)). + +Definition GAS_ZERO : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) +)). + +Definition GAS_NEW_ACCOUNT : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 25000 + ], + make_dict [] + |) +)). + +Definition GAS_CALL_VALUE : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 9000 + ], + make_dict [] + |) +)). + +Definition GAS_CALL_STIPEND : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 2300 + ], + make_dict [] + |) +)). + +Definition GAS_SELF_DESTRUCT : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 5000 + ], + make_dict [] + |) +)). + +Definition GAS_SELF_DESTRUCT_NEW_ACCOUNT : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 25000 + ], + make_dict [] + |) +)). + +Definition GAS_ECRECOVER : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 3000 + ], + make_dict [] + |) +)). + +Definition GAS_SHA256 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 60 + ], + make_dict [] + |) +)). + +Definition GAS_SHA256_WORD : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 12 + ], + make_dict [] + |) +)). + +Definition GAS_RIPEMD160 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 600 + ], + make_dict [] + |) +)). + +Definition GAS_RIPEMD160_WORD : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 120 + ], + make_dict [] + |) +)). + +Definition GAS_IDENTITY : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 15 + ], + make_dict [] + |) +)). + +Definition GAS_IDENTITY_WORD : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 3 + ], + make_dict [] + |) +)). + +Definition GAS_RETURN_DATA_COPY : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 3 + ], + make_dict [] + |) +)). + +Definition GAS_FAST_STEP : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 5 + ], + make_dict [] + |) +)). + +Definition GAS_BLAKE2_PER_ROUND : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 1 + ], + make_dict [] + |) +)). + +Definition GAS_COLD_SLOAD : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 2100 + ], + make_dict [] + |) +)). + +Definition GAS_COLD_ACCOUNT_ACCESS : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 2600 + ], + make_dict [] + |) +)). + +Definition GAS_WARM_ACCESS : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 100 + ], + make_dict [] + |) +)). + +Definition ExtendMemory : Value.t := + builtins.make_klass + [] + [ + + ] + [ + + ]. + +Definition MessageCallGas : Value.t := + builtins.make_klass + [] + [ + + ] + [ + + ]. + +Definition charge_gas : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm"; "amount" ] |) in + let _ := Constant.str " + Subtracts `amount` from `evm.gas_left`. + + Parameters + ---------- + evm : + The current EVM. + amount : + The amount of gas the current operation requires. + + " in + let _ := M.call (| + M.get_name (| globals, "evm_trace" |), + make_list [ + M.get_name (| globals, "evm" |); + M.call (| + M.get_name (| globals, "GasAndRefund" |), + make_list [ + M.get_name (| globals, "amount" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.lt (| + M.get_field (| M.get_name (| globals, "evm" |), "gas_left" |), + M.get_name (| globals, "amount" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, "OutOfGasError" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_op (| + BinOp.sub, + M.get_field (| M.get_name (| globals, "evm" |), "gas_left" |), + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + M.get_name (| globals, "amount" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_)). + +Definition calculate_memory_gas_cost : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "size_in_bytes" ] |) in + let _ := Constant.str " + Calculates the gas cost for allocating memory + to the smallest multiple of 32 bytes, + such that the allocated size is at least as big as the given size. + + Parameters + ---------- + size_in_bytes : + The size of the data in bytes. + + Returns + ------- + total_gas_cost : `ethereum.base_types.Uint` + The gas cost for storing data in memory. + " in + let _ := M.assign_local (| + "size_in_words" , + BinOp.floor_div (| + M.call (| + M.get_name (| globals, "ceil32" |), + make_list [ + M.get_name (| globals, "size_in_bytes" |) + ], + make_dict [] + |), + Constant.int 32 + |) + |) in + let _ := M.assign_local (| + "linear_cost" , + BinOp.mult (| + M.get_name (| globals, "size_in_words" |), + M.get_name (| globals, "GAS_MEMORY" |) + |) + |) in + let _ := M.assign_local (| + "quadratic_cost" , + BinOp.floor_div (| + BinOp.pow (| + M.get_name (| globals, "size_in_words" |), + Constant.int 2 + |), + Constant.int 512 + |) + |) in + let _ := M.assign_local (| + "total_gas_cost" , + BinOp.add (| + M.get_name (| globals, "linear_cost" |), + M.get_name (| globals, "quadratic_cost" |) + |) + |) in +(* At stmt: unsupported node type: Try *) + M.pure Constant.None_)). + +Definition calculate_gas_extend_memory : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "memory"; "extensions" ] |) in + let _ := Constant.str " + Calculates the gas amount to extend memory + + Parameters + ---------- + memory : + Memory contents of the EVM. + extensions: + List of extensions to be made to the memory. + Consists of a tuple of start position and size. + + Returns + ------- + extend_memory: `ExtendMemory` + " in + let _ := M.assign_local (| + "size_to_extend" , + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "to_be_paid" , + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "current_size" , + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_name (| globals, "memory" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := + M.for_ (| + make_tuple [ M.get_name (| globals, "start_position" |); M.get_name (| globals, "size" |) ], + M.get_name (| globals, "extensions" |), + ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, "size" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.continue (| |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "before_size" , + M.call (| + M.get_name (| globals, "ceil32" |), + make_list [ + M.get_name (| globals, "current_size" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "after_size" , + M.call (| + M.get_name (| globals, "ceil32" |), + make_list [ + BinOp.add (| + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.get_name (| globals, "start_position" |) + ], + make_dict [] + |), + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.get_name (| globals, "size" |) + ], + make_dict [] + |) + |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.lt_e (| + M.get_name (| globals, "after_size" |), + M.get_name (| globals, "before_size" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.continue (| |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_op_local (| + BinOp.add, + "size_to_extend", + BinOp.sub (| + M.get_name (| globals, "after_size" |), + M.get_name (| globals, "before_size" |) + |) + |) in + let _ := M.assign_local (| + "already_paid" , + M.call (| + M.get_name (| globals, "calculate_memory_gas_cost" |), + make_list [ + M.get_name (| globals, "before_size" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "total_cost" , + M.call (| + M.get_name (| globals, "calculate_memory_gas_cost" |), + make_list [ + M.get_name (| globals, "after_size" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_op_local (| + BinOp.add, + "to_be_paid", + BinOp.sub (| + M.get_name (| globals, "total_cost" |), + M.get_name (| globals, "already_paid" |) + |) + |) in + let _ := M.assign_local (| + "current_size" , + M.get_name (| globals, "after_size" |) + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, "ExtendMemory" |), + make_list [ + M.get_name (| globals, "to_be_paid" |); + M.get_name (| globals, "size_to_extend" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Definition calculate_message_call_gas : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "value"; "gas"; "gas_left"; "memory_cost"; "extra_gas"; "call_stipend" ] |) in + let _ := Constant.str " + Calculates the MessageCallGas (cost and stipend) for + executing call Opcodes. + + Parameters + ---------- + value: + The amount of `ETH` that needs to be transferred. + gas : + The amount of gas provided to the message-call. + gas_left : + The amount of gas left in the current frame. + memory_cost : + The amount needed to extend the memory in the current frame. + extra_gas : + The amount of gas needed for transferring value + creating a new + account inside a message call. + call_stipend : + The amount of stipend provided to a message call to execute code while + transferring value(ETH). + + Returns + ------- + message_call_gas: `MessageCallGas` + " in + let _ := M.assign_local (| + "call_stipend" , + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, "value" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( +M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + (* else *) + )), ltac:(M.monadic ( +M.get_name (| globals, "call_stipend" |) + )) |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.lt (| + M.get_name (| globals, "gas_left" |), + BinOp.add (| + M.get_name (| globals, "extra_gas" |), + M.get_name (| globals, "memory_cost" |) + |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + M.call (| + M.get_name (| globals, "MessageCallGas" |), + make_list [ + BinOp.add (| + M.get_name (| globals, "gas" |), + M.get_name (| globals, "extra_gas" |) + |); + BinOp.add (| + M.get_name (| globals, "gas" |), + M.get_name (| globals, "call_stipend" |) + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "gas" , + M.call (| + M.get_name (| globals, "min" |), + make_list [ + M.get_name (| globals, "gas" |); + M.call (| + M.get_name (| globals, "max_message_call_gas" |), + make_list [ + BinOp.sub (| + BinOp.sub (| + M.get_name (| globals, "gas_left" |), + M.get_name (| globals, "memory_cost" |) + |), + M.get_name (| globals, "extra_gas" |) + |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, "MessageCallGas" |), + make_list [ + BinOp.add (| + M.get_name (| globals, "gas" |), + M.get_name (| globals, "extra_gas" |) + |); + BinOp.add (| + M.get_name (| globals, "gas" |), + M.get_name (| globals, "call_stipend" |) + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Definition max_message_call_gas : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "gas" ] |) in + let _ := Constant.str " + Calculates the maximum gas that is allowed for making a message call + + Parameters + ---------- + gas : + The amount of gas provided to the message-call. + + Returns + ------- + max_allowed_message_call_gas: `ethereum.base_types.Uint` + The maximum gas allowed for making the message-call. + " in + let _ := M.return_ (| + BinOp.sub (| + M.get_name (| globals, "gas" |), + BinOp.floor_div (| + M.get_name (| globals, "gas" |), + Constant.int 64 + |) + |) + |) in + M.pure Constant.None_)). diff --git a/CoqOfPython/ethereum/london/vm/instructions/__init__.v b/CoqOfPython/ethereum/london/vm/instructions/__init__.v new file mode 100644 index 0000000..ed385be --- /dev/null +++ b/CoqOfPython/ethereum/london/vm/instructions/__init__.v @@ -0,0 +1,74 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.london.vm.instructions.__init__". + +Definition expr_1 : Value.t := + Constant.str " +EVM Instruction Encoding (Opcodes) +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Machine readable representations of EVM instructions, and a mapping to their +implementations. +". + +(* At top_level_stmt: unsupported node type: Import *) + +Axiom typing_imports_Callable : + IsImported globals "typing" "Callable". +Axiom typing_imports_Dict : + IsImported globals "typing" "Dict". + +Axiom ethereum_london_vm_instructions_imports_arithmetic : + IsImported globals "ethereum.london.vm.instructions" "arithmetic". + +Axiom ethereum_london_vm_instructions_imports_bitwise : + IsImported globals "ethereum.london.vm.instructions" "bitwise". + +Axiom ethereum_london_vm_instructions_imports_block : + IsImported globals "ethereum.london.vm.instructions" "block". + +Axiom ethereum_london_vm_instructions_imports_comparison : + IsImported globals "ethereum.london.vm.instructions" "comparison". + +Axiom ethereum_london_vm_instructions_imports_control_flow : + IsImported globals "ethereum.london.vm.instructions" "control_flow". + +Axiom ethereum_london_vm_instructions_imports_environment : + IsImported globals "ethereum.london.vm.instructions" "environment". + +Axiom ethereum_london_vm_instructions_imports_keccak : + IsImported globals "ethereum.london.vm.instructions" "keccak". + +Axiom ethereum_london_vm_instructions_imports_log : + IsImported globals "ethereum.london.vm.instructions" "log". + +Axiom ethereum_london_vm_instructions_imports_memory : + IsImported globals "ethereum.london.vm.instructions" "memory". + +Axiom ethereum_london_vm_instructions_imports_stack : + IsImported globals "ethereum.london.vm.instructions" "stack". + +Axiom ethereum_london_vm_instructions_imports_storage : + IsImported globals "ethereum.london.vm.instructions" "storage". + +Axiom ethereum_london_vm_instructions_imports_system : + IsImported globals "ethereum.london.vm.instructions" "system". + +Definition Ops : Value.t := + builtins.make_klass + [(* At base: unsupported node type: Attribute *)] + [ + + ] + [ + + ]. + +(* At top_level_stmt: unsupported node type: AnnAssign *) diff --git a/CoqOfPython/ethereum/london/vm/instructions/arithmetic.v b/CoqOfPython/ethereum/london/vm/instructions/arithmetic.v new file mode 100644 index 0000000..1b66ceb --- /dev/null +++ b/CoqOfPython/ethereum/london/vm/instructions/arithmetic.v @@ -0,0 +1,1220 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.london.vm.instructions.arithmetic". + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) Arithmetic Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM Arithmetic instructions. +". + +Axiom ethereum_base_types_imports_U255_CEIL_VALUE : + IsImported globals "ethereum.base_types" "U255_CEIL_VALUE". +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_U256_CEIL_VALUE : + IsImported globals "ethereum.base_types" "U256_CEIL_VALUE". +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". + +Axiom ethereum_utils_numeric_imports_get_sign : + IsImported globals "ethereum.utils.numeric" "get_sign". + +Axiom ethereum_london_vm_imports_Evm : + IsImported globals "ethereum.london.vm" "Evm". + +Axiom ethereum_london_vm_gas_imports_GAS_EXPONENTIATION : + IsImported globals "ethereum.london.vm.gas" "GAS_EXPONENTIATION". +Axiom ethereum_london_vm_gas_imports_GAS_EXPONENTIATION_PER_BYTE : + IsImported globals "ethereum.london.vm.gas" "GAS_EXPONENTIATION_PER_BYTE". +Axiom ethereum_london_vm_gas_imports_GAS_LOW : + IsImported globals "ethereum.london.vm.gas" "GAS_LOW". +Axiom ethereum_london_vm_gas_imports_GAS_MID : + IsImported globals "ethereum.london.vm.gas" "GAS_MID". +Axiom ethereum_london_vm_gas_imports_GAS_VERY_LOW : + IsImported globals "ethereum.london.vm.gas" "GAS_VERY_LOW". +Axiom ethereum_london_vm_gas_imports_charge_gas : + IsImported globals "ethereum.london.vm.gas" "charge_gas". + +Axiom ethereum_london_vm_stack_imports_pop : + IsImported globals "ethereum.london.vm.stack" "pop". +Axiom ethereum_london_vm_stack_imports_push : + IsImported globals "ethereum.london.vm.stack" "push". + +Definition add : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Adds the top two elements of the stack together, and pushes the result back + on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "x" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "y" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_VERY_LOW" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "result" , + M.call (| + M.get_field (| M.get_name (| globals, "x" |), "wrapping_add" |), + make_list [ + M.get_name (| globals, "y" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.get_name (| globals, "result" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition sub : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Subtracts the top two elements of the stack, and pushes the result back + on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "x" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "y" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_VERY_LOW" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "result" , + M.call (| + M.get_field (| M.get_name (| globals, "x" |), "wrapping_sub" |), + make_list [ + M.get_name (| globals, "y" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.get_name (| globals, "result" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition mul : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Multiply the top two elements of the stack, and pushes the result back + on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "x" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "y" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_LOW" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "result" , + M.call (| + M.get_field (| M.get_name (| globals, "x" |), "wrapping_mul" |), + make_list [ + M.get_name (| globals, "y" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.get_name (| globals, "result" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition div : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Integer division of the top two elements of the stack. Pushes the result + back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "dividend" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "divisor" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_LOW" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, "divisor" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "quotient" , + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "quotient" , + BinOp.floor_div (| + M.get_name (| globals, "dividend" |), + M.get_name (| globals, "divisor" |) + |) + |) in + M.pure Constant.None_ + )) |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.get_name (| globals, "quotient" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition sdiv : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Signed integer division of the top two elements of the stack. Pushes the + result back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "dividend" , + M.call (| + M.get_field (| M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |), "to_signed" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "divisor" , + M.call (| + M.get_field (| M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |), "to_signed" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_LOW" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, "divisor" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "quotient" , + Constant.int 0 + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + BoolOp.and (| + Compare.eq (| + M.get_name (| globals, "dividend" |), + UnOp.sub (| M.get_name (| globals, "U255_CEIL_VALUE" |) |) + |), + ltac:(M.monadic ( + Compare.eq (| + M.get_name (| globals, "divisor" |), + UnOp.sub (| Constant.int 1 |) + |) + )) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "quotient" , + UnOp.sub (| M.get_name (| globals, "U255_CEIL_VALUE" |) |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "sign" , + M.call (| + M.get_name (| globals, "get_sign" |), + make_list [ + BinOp.mult (| + M.get_name (| globals, "dividend" |), + M.get_name (| globals, "divisor" |) + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "quotient" , + BinOp.mult (| + M.get_name (| globals, "sign" |), + BinOp.floor_div (| + M.call (| + M.get_name (| globals, "abs" |), + make_list [ + M.get_name (| globals, "dividend" |) + ], + make_dict [] + |), + M.call (| + M.get_name (| globals, "abs" |), + make_list [ + M.get_name (| globals, "divisor" |) + ], + make_dict [] + |) + |) + |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )) |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.call (| + M.get_field (| M.get_name (| globals, "U256" |), "from_signed" |), + make_list [ + M.get_name (| globals, "quotient" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition mod_ : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Modulo remainder of the top two elements of the stack. Pushes the result + back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "x" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "y" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_LOW" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, "y" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "remainder" , + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "remainder" , + BinOp.mod_ (| + M.get_name (| globals, "x" |), + M.get_name (| globals, "y" |) + |) + |) in + M.pure Constant.None_ + )) |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.get_name (| globals, "remainder" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition smod : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Signed modulo remainder of the top two elements of the stack. Pushes the + result back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "x" , + M.call (| + M.get_field (| M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |), "to_signed" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "y" , + M.call (| + M.get_field (| M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |), "to_signed" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_LOW" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, "y" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "remainder" , + Constant.int 0 + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "remainder" , + BinOp.mult (| + M.call (| + M.get_name (| globals, "get_sign" |), + make_list [ + M.get_name (| globals, "x" |) + ], + make_dict [] + |), + BinOp.mod_ (| + M.call (| + M.get_name (| globals, "abs" |), + make_list [ + M.get_name (| globals, "x" |) + ], + make_dict [] + |), + M.call (| + M.get_name (| globals, "abs" |), + make_list [ + M.get_name (| globals, "y" |) + ], + make_dict [] + |) + |) + |) + |) in + M.pure Constant.None_ + )) |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.call (| + M.get_field (| M.get_name (| globals, "U256" |), "from_signed" |), + make_list [ + M.get_name (| globals, "remainder" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition addmod : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Modulo addition of the top 2 elements with the 3rd element. Pushes the + result back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "x" , + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "y" , + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "z" , + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_MID" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, "z" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "result" , + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "result" , + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + BinOp.mod_ (| + BinOp.add (| + M.get_name (| globals, "x" |), + M.get_name (| globals, "y" |) + |), + M.get_name (| globals, "z" |) + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + )) |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.get_name (| globals, "result" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition mulmod : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Modulo multiplication of the top 2 elements with the 3rd element. Pushes + the result back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "x" , + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "y" , + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "z" , + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_MID" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, "z" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "result" , + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "result" , + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + BinOp.mod_ (| + BinOp.mult (| + M.get_name (| globals, "x" |), + M.get_name (| globals, "y" |) + |), + M.get_name (| globals, "z" |) + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + )) |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.get_name (| globals, "result" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition exp : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Exponential operation of the top 2 elements. Pushes the result back on + the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "base" , + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "exponent" , + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "exponent_bits" , + M.call (| + M.get_field (| M.get_name (| globals, "exponent" |), "bit_length" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "exponent_bytes" , + BinOp.floor_div (| + BinOp.add (| + M.get_name (| globals, "exponent_bits" |), + Constant.int 7 + |), + Constant.int 8 + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + BinOp.add (| + M.get_name (| globals, "GAS_EXPONENTIATION" |), + BinOp.mult (| + M.get_name (| globals, "GAS_EXPONENTIATION_PER_BYTE" |), + M.get_name (| globals, "exponent_bytes" |) + |) + |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "result" , + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + M.call (| + M.get_name (| globals, "pow" |), + make_list [ + M.get_name (| globals, "base" |); + M.get_name (| globals, "exponent" |); + M.get_name (| globals, "U256_CEIL_VALUE" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.get_name (| globals, "result" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition signextend : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Sign extend operation. In other words, extend a signed number which + fits in N bytes to 32 bytes. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "byte_num" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "value" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_LOW" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.gt (| + M.get_name (| globals, "byte_num" |), + Constant.int 31 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "result" , + M.get_name (| globals, "value" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "value_bytes" , + M.call (| + M.get_name (| globals, "bytes" |), + make_list [ + M.call (| + M.get_field (| M.get_name (| globals, "value" |), "to_be_bytes32" |), + make_list [], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "value_bytes" , + M.slice (| + M.get_name (| globals, "value_bytes" |), + BinOp.sub (| + Constant.int 31, + M.call (| + M.get_name (| globals, "int" |), + make_list [ + M.get_name (| globals, "byte_num" |) + ], + make_dict [] + |) + |), + Constant.None_, + Constant.None_ + |) + |) in + let _ := M.assign_local (| + "sign_bit" , + BinOp.r_shift (| + M.get_subscript (| + M.get_name (| globals, "value_bytes" |), + Constant.int 0 + |), + Constant.int 7 + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, "sign_bit" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "result" , + M.call (| + M.get_field (| M.get_name (| globals, "U256" |), "from_be_bytes" |), + make_list [ + M.get_name (| globals, "value_bytes" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "num_bytes_prepend" , + BinOp.sub (| + Constant.int 32, + BinOp.add (| + M.get_name (| globals, "byte_num" |), + Constant.int 1 + |) + |) + |) in + let _ := M.assign_local (| + "result" , + M.call (| + M.get_field (| M.get_name (| globals, "U256" |), "from_be_bytes" |), + make_list [ + BinOp.add (| + M.call (| + M.get_name (| globals, "bytearray" |), + make_list [ + BinOp.mult (| + make_list [ + Constant.int 255 + ], + M.get_name (| globals, "num_bytes_prepend" |) + |) + ], + make_dict [] + |), + M.get_name (| globals, "value_bytes" |) + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )) |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.get_name (| globals, "result" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). diff --git a/CoqOfPython/ethereum/london/vm/instructions/bitwise.v b/CoqOfPython/ethereum/london/vm/instructions/bitwise.v new file mode 100644 index 0000000..02bebb6 --- /dev/null +++ b/CoqOfPython/ethereum/london/vm/instructions/bitwise.v @@ -0,0 +1,666 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.london.vm.instructions.bitwise". + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) Bitwise Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM bitwise instructions. +". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_U256_CEIL_VALUE : + IsImported globals "ethereum.base_types" "U256_CEIL_VALUE". + +Axiom ethereum_london_vm_imports_Evm : + IsImported globals "ethereum.london.vm" "Evm". + +Axiom ethereum_london_vm_gas_imports_GAS_VERY_LOW : + IsImported globals "ethereum.london.vm.gas" "GAS_VERY_LOW". +Axiom ethereum_london_vm_gas_imports_charge_gas : + IsImported globals "ethereum.london.vm.gas" "charge_gas". + +Axiom ethereum_london_vm_stack_imports_pop : + IsImported globals "ethereum.london.vm.stack" "pop". +Axiom ethereum_london_vm_stack_imports_push : + IsImported globals "ethereum.london.vm.stack" "push". + +Definition bitwise_and : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Bitwise AND operation of the top 2 elements of the stack. Pushes the + result back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "x" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "y" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_VERY_LOW" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + BinOp.bit_and (| + M.get_name (| globals, "x" |), + M.get_name (| globals, "y" |) + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition bitwise_or : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Bitwise OR operation of the top 2 elements of the stack. Pushes the + result back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "x" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "y" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_VERY_LOW" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + BinOp.bit_or (| + M.get_name (| globals, "x" |), + M.get_name (| globals, "y" |) + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition bitwise_xor : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Bitwise XOR operation of the top 2 elements of the stack. Pushes the + result back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "x" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "y" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_VERY_LOW" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + BinOp.bit_xor (| + M.get_name (| globals, "x" |), + M.get_name (| globals, "y" |) + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition bitwise_not : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Bitwise NOT operation of the top element of the stack. Pushes the + result back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "x" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_VERY_LOW" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + UnOp.invert (| M.get_name (| globals, "x" |) |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition get_byte : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + For a word (defined by next top element of the stack), retrieve the + Nth byte (0-indexed and defined by top element of stack) from the + left (most significant) to right (least significant). + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "byte_index" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "word" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_VERY_LOW" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.gt_e (| + M.get_name (| globals, "byte_index" |), + Constant.int 32 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "result" , + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "extra_bytes_to_right" , + BinOp.sub (| + Constant.int 31, + M.get_name (| globals, "byte_index" |) + |) + |) in + let _ := M.assign_local (| + "word" , + BinOp.r_shift (| + M.get_name (| globals, "word" |), + BinOp.mult (| + M.get_name (| globals, "extra_bytes_to_right" |), + Constant.int 8 + |) + |) + |) in + let _ := M.assign_local (| + "word" , + BinOp.bit_and (| + M.get_name (| globals, "word" |), + Constant.int 255 + |) + |) in + let _ := M.assign_local (| + "result" , + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + M.get_name (| globals, "word" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + )) |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.get_name (| globals, "result" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition bitwise_shl : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Logical shift left (SHL) operation of the top 2 elements of the stack. + Pushes the result back on the stack. + Parameters + ---------- + evm : + The current EVM frame. + " in + let _ := M.assign_local (| + "shift" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "value" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_VERY_LOW" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.lt (| + M.get_name (| globals, "shift" |), + Constant.int 256 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "result" , + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + BinOp.mod_ (| + BinOp.l_shift (| + M.get_name (| globals, "value" |), + M.get_name (| globals, "shift" |) + |), + M.get_name (| globals, "U256_CEIL_VALUE" |) + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "result" , + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + )) |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.get_name (| globals, "result" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition bitwise_shr : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Logical shift right (SHR) operation of the top 2 elements of the stack. + Pushes the result back on the stack. + Parameters + ---------- + evm : + The current EVM frame. + " in + let _ := M.assign_local (| + "shift" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "value" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_VERY_LOW" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.lt (| + M.get_name (| globals, "shift" |), + Constant.int 256 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "result" , + BinOp.r_shift (| + M.get_name (| globals, "value" |), + M.get_name (| globals, "shift" |) + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "result" , + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + )) |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.get_name (| globals, "result" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition bitwise_sar : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Arithmetic shift right (SAR) operation of the top 2 elements of the stack. + Pushes the result back on the stack. + Parameters + ---------- + evm : + The current EVM frame. + " in + let _ := M.assign_local (| + "shift" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "signed_value" , + M.call (| + M.get_field (| M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |), "to_signed" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_VERY_LOW" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.lt (| + M.get_name (| globals, "shift" |), + Constant.int 256 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "result" , + M.call (| + M.get_field (| M.get_name (| globals, "U256" |), "from_signed" |), + make_list [ + BinOp.r_shift (| + M.get_name (| globals, "signed_value" |), + M.get_name (| globals, "shift" |) + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + Compare.gt_e (| + M.get_name (| globals, "signed_value" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "result" , + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "result" , + M.get_field (| M.get_name (| globals, "U256" |), "MAX_VALUE" |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )) |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.get_name (| globals, "result" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). diff --git a/CoqOfPython/ethereum/london/vm/instructions/block.v b/CoqOfPython/ethereum/london/vm/instructions/block.v new file mode 100644 index 0000000..e3bee4c --- /dev/null +++ b/CoqOfPython/ethereum/london/vm/instructions/block.v @@ -0,0 +1,390 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.london.vm.instructions.block". + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) Block Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM block instructions. +". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". + +Axiom ethereum_london_vm_imports_Evm : + IsImported globals "ethereum.london.vm" "Evm". + +Axiom ethereum_london_vm_gas_imports_GAS_BASE : + IsImported globals "ethereum.london.vm.gas" "GAS_BASE". +Axiom ethereum_london_vm_gas_imports_GAS_BLOCK_HASH : + IsImported globals "ethereum.london.vm.gas" "GAS_BLOCK_HASH". +Axiom ethereum_london_vm_gas_imports_charge_gas : + IsImported globals "ethereum.london.vm.gas" "charge_gas". + +Axiom ethereum_london_vm_stack_imports_pop : + IsImported globals "ethereum.london.vm.stack" "pop". +Axiom ethereum_london_vm_stack_imports_push : + IsImported globals "ethereum.london.vm.stack" "push". + +Definition block_hash : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Push the hash of one of the 256 most recent complete blocks onto the + stack. The block number to hash is present at the top of the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "block_number" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_BLOCK_HASH" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + BoolOp.or (| + Compare.lt_e (| + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "env" |), "number" |), + M.get_name (| globals, "block_number" |) + |), + ltac:(M.monadic ( + Compare.gt (| + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "env" |), "number" |), + BinOp.add (| + M.get_name (| globals, "block_number" |), + Constant.int 256 + |) + |) + )) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "hash" , + Constant.bytes "00" + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "hash" , + M.get_subscript (| + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "env" |), "block_hashes" |), + UnOp.sub (| BinOp.sub (| + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "env" |), "number" |), + M.get_name (| globals, "block_number" |) + |) |) + |) + |) in + M.pure Constant.None_ + )) |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.call (| + M.get_field (| M.get_name (| globals, "U256" |), "from_be_bytes" |), + make_list [ + M.get_name (| globals, "hash" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition coinbase : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Push the current block's beneficiary address (address of the block miner) + onto the stack. + + Here the current block refers to the block in which the currently + executing transaction/call resides. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_BASE" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.call (| + M.get_field (| M.get_name (| globals, "U256" |), "from_be_bytes" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "env" |), "coinbase" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition timestamp : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Push the current block's timestamp onto the stack. Here the timestamp + being referred is actually the unix timestamp in seconds. + + Here the current block refers to the block in which the currently + executing transaction/call resides. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_BASE" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "env" |), "time" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition number : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Push the current block's number onto the stack. + + Here the current block refers to the block in which the currently + executing transaction/call resides. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_BASE" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "env" |), "number" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition difficulty : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Push the current block's difficulty onto the stack. + + Here the current block refers to the block in which the currently + executing transaction/call resides. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_BASE" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "env" |), "difficulty" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition gas_limit : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Push the current block's gas limit onto the stack. + + Here the current block refers to the block in which the currently + executing transaction/call resides. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_BASE" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "env" |), "gas_limit" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition chain_id : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Push the chain id onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_BASE" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "env" |), "chain_id" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). diff --git a/CoqOfPython/ethereum/london/vm/instructions/comparison.v b/CoqOfPython/ethereum/london/vm/instructions/comparison.v new file mode 100644 index 0000000..4a78f2d --- /dev/null +++ b/CoqOfPython/ethereum/london/vm/instructions/comparison.v @@ -0,0 +1,452 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.london.vm.instructions.comparison". + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) Comparison Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM Comparison instructions. +". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". + +Axiom ethereum_london_vm_imports_Evm : + IsImported globals "ethereum.london.vm" "Evm". + +Axiom ethereum_london_vm_gas_imports_GAS_VERY_LOW : + IsImported globals "ethereum.london.vm.gas" "GAS_VERY_LOW". +Axiom ethereum_london_vm_gas_imports_charge_gas : + IsImported globals "ethereum.london.vm.gas" "charge_gas". + +Axiom ethereum_london_vm_stack_imports_pop : + IsImported globals "ethereum.london.vm.stack" "pop". +Axiom ethereum_london_vm_stack_imports_push : + IsImported globals "ethereum.london.vm.stack" "push". + +Definition less_than : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Checks if the top element is less than the next top element. Pushes the + result back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "left" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "right" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_VERY_LOW" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "result" , + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Compare.lt (| + M.get_name (| globals, "left" |), + M.get_name (| globals, "right" |) + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.get_name (| globals, "result" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition signed_less_than : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Signed less-than comparison. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "left" , + M.call (| + M.get_field (| M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |), "to_signed" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "right" , + M.call (| + M.get_field (| M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |), "to_signed" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_VERY_LOW" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "result" , + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Compare.lt (| + M.get_name (| globals, "left" |), + M.get_name (| globals, "right" |) + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.get_name (| globals, "result" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition greater_than : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Checks if the top element is greater than the next top element. Pushes + the result back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "left" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "right" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_VERY_LOW" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "result" , + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Compare.gt (| + M.get_name (| globals, "left" |), + M.get_name (| globals, "right" |) + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.get_name (| globals, "result" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition signed_greater_than : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Signed greater-than comparison. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "left" , + M.call (| + M.get_field (| M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |), "to_signed" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "right" , + M.call (| + M.get_field (| M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |), "to_signed" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_VERY_LOW" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "result" , + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Compare.gt (| + M.get_name (| globals, "left" |), + M.get_name (| globals, "right" |) + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.get_name (| globals, "result" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition equal : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Checks if the top element is equal to the next top element. Pushes + the result back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "left" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "right" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_VERY_LOW" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "result" , + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Compare.eq (| + M.get_name (| globals, "left" |), + M.get_name (| globals, "right" |) + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.get_name (| globals, "result" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition is_zero : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Checks if the top element is equal to 0. Pushes the result back on the + stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "x" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_VERY_LOW" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "result" , + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Compare.eq (| + M.get_name (| globals, "x" |), + Constant.int 0 + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.get_name (| globals, "result" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). diff --git a/CoqOfPython/ethereum/london/vm/instructions/control_flow.v b/CoqOfPython/ethereum/london/vm/instructions/control_flow.v new file mode 100644 index 0000000..263e036 --- /dev/null +++ b/CoqOfPython/ethereum/london/vm/instructions/control_flow.v @@ -0,0 +1,350 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.london.vm.instructions.control_flow". + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) Control Flow Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM control flow instructions. +". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". + +Axiom ethereum_london_vm_gas_imports_GAS_BASE : + IsImported globals "ethereum.london.vm.gas" "GAS_BASE". +Axiom ethereum_london_vm_gas_imports_GAS_HIGH : + IsImported globals "ethereum.london.vm.gas" "GAS_HIGH". +Axiom ethereum_london_vm_gas_imports_GAS_JUMPDEST : + IsImported globals "ethereum.london.vm.gas" "GAS_JUMPDEST". +Axiom ethereum_london_vm_gas_imports_GAS_MID : + IsImported globals "ethereum.london.vm.gas" "GAS_MID". +Axiom ethereum_london_vm_gas_imports_charge_gas : + IsImported globals "ethereum.london.vm.gas" "charge_gas". + +Axiom ethereum_london_vm_imports_Evm : + IsImported globals "ethereum.london.vm" "Evm". + +Axiom ethereum_london_vm_exceptions_imports_InvalidJumpDestError : + IsImported globals "ethereum.london.vm.exceptions" "InvalidJumpDestError". + +Axiom ethereum_london_vm_stack_imports_pop : + IsImported globals "ethereum.london.vm.stack" "pop". +Axiom ethereum_london_vm_stack_imports_push : + IsImported globals "ethereum.london.vm.stack" "push". + +Definition stop : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Stop further execution of EVM code. + + Parameters + ---------- + evm : + The current EVM frame. + " in + let _ := M.pass (| |) in + let _ := M.pass (| |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, "evm" |), "running" |), + Constant.bool false + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition jump : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Alter the program counter to the location specified by the top of the + stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "jump_dest" , + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_MID" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.not_in (| + M.get_name (| globals, "jump_dest" |), + M.get_field (| M.get_name (| globals, "evm" |), "valid_jump_destinations" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, "InvalidJumpDestError" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.get_name (| globals, "jump_dest" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Definition jumpi : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Alter the program counter to the specified location if and only if a + condition is true. If the condition is not true, then the program counter + would increase only by 1. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "jump_dest" , + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "conditional_value" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_HIGH" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, "conditional_value" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "destination" , + BinOp.add (| + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + Compare.not_in (| + M.get_name (| globals, "jump_dest" |), + M.get_field (| M.get_name (| globals, "evm" |), "valid_jump_destinations" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, "InvalidJumpDestError" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "destination" , + M.get_name (| globals, "jump_dest" |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )) |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.get_name (| globals, "destination" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Definition pc : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Push onto the stack the value of the program counter after reaching the + current instruction and without increasing it for the next instruction. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_BASE" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "pc" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition gas_left : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Push the amount of available gas (including the corresponding reduction + for the cost of this instruction) onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_BASE" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "gas_left" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition jumpdest : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Mark a valid destination for jumps. This is a noop, present only + to be used by `JUMP` and `JUMPI` opcodes to verify that their jump is + valid. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_JUMPDEST" |) + ], + make_dict [] + |) in + let _ := M.pass (| |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). diff --git a/CoqOfPython/ethereum/london/vm/instructions/environment.v b/CoqOfPython/ethereum/london/vm/instructions/environment.v new file mode 100644 index 0000000..f91ee73 --- /dev/null +++ b/CoqOfPython/ethereum/london/vm/instructions/environment.v @@ -0,0 +1,1529 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.london.vm.instructions.environment". + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) Environmental Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM environment related instructions. +". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". + +Axiom ethereum_crypto_hash_imports_keccak256 : + IsImported globals "ethereum.crypto.hash" "keccak256". + +Axiom ethereum_utils_ensure_imports_ensure : + IsImported globals "ethereum.utils.ensure" "ensure". + +Axiom ethereum_utils_numeric_imports_ceil32 : + IsImported globals "ethereum.utils.numeric" "ceil32". + +Axiom ethereum_london_fork_types_imports_EMPTY_ACCOUNT : + IsImported globals "ethereum.london.fork_types" "EMPTY_ACCOUNT". + +Axiom ethereum_london_state_imports_get_account : + IsImported globals "ethereum.london.state" "get_account". + +Axiom ethereum_london_utils_address_imports_to_address : + IsImported globals "ethereum.london.utils.address" "to_address". + +Axiom ethereum_london_vm_memory_imports_buffer_read : + IsImported globals "ethereum.london.vm.memory" "buffer_read". +Axiom ethereum_london_vm_memory_imports_memory_write : + IsImported globals "ethereum.london.vm.memory" "memory_write". + +Axiom ethereum_london_vm_imports_Evm : + IsImported globals "ethereum.london.vm" "Evm". + +Axiom ethereum_london_vm_exceptions_imports_OutOfBoundsRead : + IsImported globals "ethereum.london.vm.exceptions" "OutOfBoundsRead". + +Axiom ethereum_london_vm_gas_imports_GAS_BASE : + IsImported globals "ethereum.london.vm.gas" "GAS_BASE". +Axiom ethereum_london_vm_gas_imports_GAS_COLD_ACCOUNT_ACCESS : + IsImported globals "ethereum.london.vm.gas" "GAS_COLD_ACCOUNT_ACCESS". +Axiom ethereum_london_vm_gas_imports_GAS_COPY : + IsImported globals "ethereum.london.vm.gas" "GAS_COPY". +Axiom ethereum_london_vm_gas_imports_GAS_FAST_STEP : + IsImported globals "ethereum.london.vm.gas" "GAS_FAST_STEP". +Axiom ethereum_london_vm_gas_imports_GAS_RETURN_DATA_COPY : + IsImported globals "ethereum.london.vm.gas" "GAS_RETURN_DATA_COPY". +Axiom ethereum_london_vm_gas_imports_GAS_VERY_LOW : + IsImported globals "ethereum.london.vm.gas" "GAS_VERY_LOW". +Axiom ethereum_london_vm_gas_imports_GAS_WARM_ACCESS : + IsImported globals "ethereum.london.vm.gas" "GAS_WARM_ACCESS". +Axiom ethereum_london_vm_gas_imports_calculate_gas_extend_memory : + IsImported globals "ethereum.london.vm.gas" "calculate_gas_extend_memory". +Axiom ethereum_london_vm_gas_imports_charge_gas : + IsImported globals "ethereum.london.vm.gas" "charge_gas". + +Axiom ethereum_london_vm_stack_imports_pop : + IsImported globals "ethereum.london.vm.stack" "pop". +Axiom ethereum_london_vm_stack_imports_push : + IsImported globals "ethereum.london.vm.stack" "push". + +Definition address : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Pushes the address of the current executing account to the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_BASE" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.call (| + M.get_field (| M.get_name (| globals, "U256" |), "from_be_bytes" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "current_target" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition balance : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Pushes the balance of the given account onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "address" , + M.call (| + M.get_name (| globals, "to_address" |), + make_list [ + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.in_ (| + M.get_name (| globals, "address" |), + M.get_field (| M.get_name (| globals, "evm" |), "accessed_addresses" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_WARM_ACCESS" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "accessed_addresses" |), "add" |), + make_list [ + M.get_name (| globals, "address" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_COLD_ACCOUNT_ACCESS" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "balance" , + M.get_field (| M.call (| + M.get_name (| globals, "get_account" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "env" |), "state" |); + M.get_name (| globals, "address" |) + ], + make_dict [] + |), "balance" |) + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.get_name (| globals, "balance" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition origin : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Pushes the address of the original transaction sender to the stack. + The origin address can only be an EOA. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_BASE" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.call (| + M.get_field (| M.get_name (| globals, "U256" |), "from_be_bytes" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "env" |), "origin" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition caller : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Pushes the address of the caller onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_BASE" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.call (| + M.get_field (| M.get_name (| globals, "U256" |), "from_be_bytes" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "caller" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition callvalue : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Push the value (in wei) sent with the call onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_BASE" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "value" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition calldataload : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Push a word (32 bytes) of the input data belonging to the current + environment onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "start_index" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_VERY_LOW" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "value" , + M.call (| + M.get_name (| globals, "buffer_read" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "data" |); + M.get_name (| globals, "start_index" |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 32 + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.call (| + M.get_field (| M.get_name (| globals, "U256" |), "from_be_bytes" |), + make_list [ + M.get_name (| globals, "value" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition calldatasize : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Push the size of input data in current environment onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_BASE" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "data" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition calldatacopy : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Copy a portion of the input data in current environment to memory. + + This will also expand the memory, in case that the memory is insufficient + to store the data. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "memory_start_index" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "data_start_index" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "size" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "words" , + BinOp.floor_div (| + M.call (| + M.get_name (| globals, "ceil32" |), + make_list [ + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.get_name (| globals, "size" |) + ], + make_dict [] + |) + ], + make_dict [] + |), + Constant.int 32 + |) + |) in + let _ := M.assign_local (| + "copy_gas_cost" , + BinOp.mult (| + M.get_name (| globals, "GAS_COPY" |), + M.get_name (| globals, "words" |) + |) + |) in + let _ := M.assign_local (| + "extend_memory" , + M.call (| + M.get_name (| globals, "calculate_gas_extend_memory" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "memory" |); + make_list [ + make_tuple [ M.get_name (| globals, "memory_start_index" |); M.get_name (| globals, "size" |) ] + ] + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + BinOp.add (| + BinOp.add (| + M.get_name (| globals, "GAS_VERY_LOW" |), + M.get_name (| globals, "copy_gas_cost" |) + |), + M.get_field (| M.get_name (| globals, "extend_memory" |), "cost" |) + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "memory" |), + BinOp.mult (| + Constant.bytes "00", + M.get_field (| M.get_name (| globals, "extend_memory" |), "expand_by" |) + |) + |) in + let _ := M.assign_local (| + "value" , + M.call (| + M.get_name (| globals, "buffer_read" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "data" |); + M.get_name (| globals, "data_start_index" |); + M.get_name (| globals, "size" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "memory_write" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "memory" |); + M.get_name (| globals, "memory_start_index" |); + M.get_name (| globals, "value" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition codesize : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Push the size of code running in current environment onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_BASE" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "code" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition codecopy : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Copy a portion of the code in current environment to memory. + + This will also expand the memory, in case that the memory is insufficient + to store the data. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "memory_start_index" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "code_start_index" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "size" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "words" , + BinOp.floor_div (| + M.call (| + M.get_name (| globals, "ceil32" |), + make_list [ + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.get_name (| globals, "size" |) + ], + make_dict [] + |) + ], + make_dict [] + |), + Constant.int 32 + |) + |) in + let _ := M.assign_local (| + "copy_gas_cost" , + BinOp.mult (| + M.get_name (| globals, "GAS_COPY" |), + M.get_name (| globals, "words" |) + |) + |) in + let _ := M.assign_local (| + "extend_memory" , + M.call (| + M.get_name (| globals, "calculate_gas_extend_memory" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "memory" |); + make_list [ + make_tuple [ M.get_name (| globals, "memory_start_index" |); M.get_name (| globals, "size" |) ] + ] + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + BinOp.add (| + BinOp.add (| + M.get_name (| globals, "GAS_VERY_LOW" |), + M.get_name (| globals, "copy_gas_cost" |) + |), + M.get_field (| M.get_name (| globals, "extend_memory" |), "cost" |) + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "memory" |), + BinOp.mult (| + Constant.bytes "00", + M.get_field (| M.get_name (| globals, "extend_memory" |), "expand_by" |) + |) + |) in + let _ := M.assign_local (| + "value" , + M.call (| + M.get_name (| globals, "buffer_read" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "code" |); + M.get_name (| globals, "code_start_index" |); + M.get_name (| globals, "size" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "memory_write" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "memory" |); + M.get_name (| globals, "memory_start_index" |); + M.get_name (| globals, "value" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition gasprice : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Push the gas price used in current environment onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_BASE" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "env" |), "gas_price" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition extcodesize : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Push the code size of a given account onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "address" , + M.call (| + M.get_name (| globals, "to_address" |), + make_list [ + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.in_ (| + M.get_name (| globals, "address" |), + M.get_field (| M.get_name (| globals, "evm" |), "accessed_addresses" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_WARM_ACCESS" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "accessed_addresses" |), "add" |), + make_list [ + M.get_name (| globals, "address" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_COLD_ACCOUNT_ACCESS" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "codesize" , + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_field (| M.call (| + M.get_name (| globals, "get_account" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "env" |), "state" |); + M.get_name (| globals, "address" |) + ], + make_dict [] + |), "code" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.get_name (| globals, "codesize" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition extcodecopy : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Copy a portion of an account's code to memory. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "address" , + M.call (| + M.get_name (| globals, "to_address" |), + make_list [ + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_start_index" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "code_start_index" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "size" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "words" , + BinOp.floor_div (| + M.call (| + M.get_name (| globals, "ceil32" |), + make_list [ + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.get_name (| globals, "size" |) + ], + make_dict [] + |) + ], + make_dict [] + |), + Constant.int 32 + |) + |) in + let _ := M.assign_local (| + "copy_gas_cost" , + BinOp.mult (| + M.get_name (| globals, "GAS_COPY" |), + M.get_name (| globals, "words" |) + |) + |) in + let _ := M.assign_local (| + "extend_memory" , + M.call (| + M.get_name (| globals, "calculate_gas_extend_memory" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "memory" |); + make_list [ + make_tuple [ M.get_name (| globals, "memory_start_index" |); M.get_name (| globals, "size" |) ] + ] + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.in_ (| + M.get_name (| globals, "address" |), + M.get_field (| M.get_name (| globals, "evm" |), "accessed_addresses" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + BinOp.add (| + BinOp.add (| + M.get_name (| globals, "GAS_WARM_ACCESS" |), + M.get_name (| globals, "copy_gas_cost" |) + |), + M.get_field (| M.get_name (| globals, "extend_memory" |), "cost" |) + |) + ], + make_dict [] + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "accessed_addresses" |), "add" |), + make_list [ + M.get_name (| globals, "address" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + BinOp.add (| + BinOp.add (| + M.get_name (| globals, "GAS_COLD_ACCOUNT_ACCESS" |), + M.get_name (| globals, "copy_gas_cost" |) + |), + M.get_field (| M.get_name (| globals, "extend_memory" |), "cost" |) + |) + ], + make_dict [] + |) in + M.pure Constant.None_ + )) |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "memory" |), + BinOp.mult (| + Constant.bytes "00", + M.get_field (| M.get_name (| globals, "extend_memory" |), "expand_by" |) + |) + |) in + let _ := M.assign_local (| + "code" , + M.get_field (| M.call (| + M.get_name (| globals, "get_account" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "env" |), "state" |); + M.get_name (| globals, "address" |) + ], + make_dict [] + |), "code" |) + |) in + let _ := M.assign_local (| + "value" , + M.call (| + M.get_name (| globals, "buffer_read" |), + make_list [ + M.get_name (| globals, "code" |); + M.get_name (| globals, "code_start_index" |); + M.get_name (| globals, "size" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "memory_write" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "memory" |); + M.get_name (| globals, "memory_start_index" |); + M.get_name (| globals, "value" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition returndatasize : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Pushes the size of the return data buffer onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_BASE" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "return_data" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition returndatacopy : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Copies data from the return data buffer code to memory + + Parameters + ---------- + evm : + The current EVM frame. + " in + let _ := M.assign_local (| + "memory_start_index" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "return_data_start_position" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "size" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "words" , + BinOp.floor_div (| + M.call (| + M.get_name (| globals, "ceil32" |), + make_list [ + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.get_name (| globals, "size" |) + ], + make_dict [] + |) + ], + make_dict [] + |), + Constant.int 32 + |) + |) in + let _ := M.assign_local (| + "copy_gas_cost" , + BinOp.mult (| + M.get_name (| globals, "GAS_RETURN_DATA_COPY" |), + M.get_name (| globals, "words" |) + |) + |) in + let _ := M.assign_local (| + "extend_memory" , + M.call (| + M.get_name (| globals, "calculate_gas_extend_memory" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "memory" |); + make_list [ + make_tuple [ M.get_name (| globals, "memory_start_index" |); M.get_name (| globals, "size" |) ] + ] + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + BinOp.add (| + BinOp.add (| + M.get_name (| globals, "GAS_VERY_LOW" |), + M.get_name (| globals, "copy_gas_cost" |) + |), + M.get_field (| M.get_name (| globals, "extend_memory" |), "cost" |) + |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + Compare.lt_e (| + BinOp.add (| + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.get_name (| globals, "return_data_start_position" |) + ], + make_dict [] + |), + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.get_name (| globals, "size" |) + ], + make_dict [] + |) + |), + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "return_data" |) + ], + make_dict [] + |) + |); + M.get_name (| globals, "OutOfBoundsRead" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "memory" |), + BinOp.mult (| + Constant.bytes "00", + M.get_field (| M.get_name (| globals, "extend_memory" |), "expand_by" |) + |) + |) in + let _ := M.assign_local (| + "value" , + M.slice (| + M.get_field (| M.get_name (| globals, "evm" |), "return_data" |), + M.get_name (| globals, "return_data_start_position" |), + BinOp.add (| + M.get_name (| globals, "return_data_start_position" |), + M.get_name (| globals, "size" |) + |), + Constant.None_ + |) + |) in + let _ := M.call (| + M.get_name (| globals, "memory_write" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "memory" |); + M.get_name (| globals, "memory_start_index" |); + M.get_name (| globals, "value" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition extcodehash : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Returns the keccak256 hash of a contract’s bytecode + Parameters + ---------- + evm : + The current EVM frame. + " in + let _ := M.assign_local (| + "address" , + M.call (| + M.get_name (| globals, "to_address" |), + make_list [ + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.in_ (| + M.get_name (| globals, "address" |), + M.get_field (| M.get_name (| globals, "evm" |), "accessed_addresses" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_WARM_ACCESS" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "accessed_addresses" |), "add" |), + make_list [ + M.get_name (| globals, "address" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_COLD_ACCOUNT_ACCESS" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "account" , + M.call (| + M.get_name (| globals, "get_account" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "env" |), "state" |); + M.get_name (| globals, "address" |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, "account" |), + M.get_name (| globals, "EMPTY_ACCOUNT" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "codehash" , + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "codehash" , + M.call (| + M.get_field (| M.get_name (| globals, "U256" |), "from_be_bytes" |), + make_list [ + M.call (| + M.get_name (| globals, "keccak256" |), + make_list [ + M.get_field (| M.get_name (| globals, "account" |), "code" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + )) |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.get_name (| globals, "codehash" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition self_balance : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Pushes the balance of the current address to the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_FAST_STEP" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "balance" , + M.get_field (| M.call (| + M.get_name (| globals, "get_account" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "env" |), "state" |); + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "current_target" |) + ], + make_dict [] + |), "balance" |) + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.get_name (| globals, "balance" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition base_fee : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Pushes the base fee of the current block on to the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_BASE" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "env" |), "base_fee_per_gas" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). diff --git a/CoqOfPython/ethereum/london/vm/instructions/keccak.v b/CoqOfPython/ethereum/london/vm/instructions/keccak.v new file mode 100644 index 0000000..ddef676 --- /dev/null +++ b/CoqOfPython/ethereum/london/vm/instructions/keccak.v @@ -0,0 +1,188 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.london.vm.instructions.keccak". + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) Keccak Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM keccak instructions. +". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". + +Axiom ethereum_crypto_hash_imports_keccak256 : + IsImported globals "ethereum.crypto.hash" "keccak256". + +Axiom ethereum_utils_numeric_imports_ceil32 : + IsImported globals "ethereum.utils.numeric" "ceil32". + +Axiom ethereum_london_vm_imports_Evm : + IsImported globals "ethereum.london.vm" "Evm". + +Axiom ethereum_london_vm_gas_imports_GAS_KECCAK256 : + IsImported globals "ethereum.london.vm.gas" "GAS_KECCAK256". +Axiom ethereum_london_vm_gas_imports_GAS_KECCAK256_WORD : + IsImported globals "ethereum.london.vm.gas" "GAS_KECCAK256_WORD". +Axiom ethereum_london_vm_gas_imports_calculate_gas_extend_memory : + IsImported globals "ethereum.london.vm.gas" "calculate_gas_extend_memory". +Axiom ethereum_london_vm_gas_imports_charge_gas : + IsImported globals "ethereum.london.vm.gas" "charge_gas". + +Axiom ethereum_london_vm_memory_imports_memory_read_bytes : + IsImported globals "ethereum.london.vm.memory" "memory_read_bytes". + +Axiom ethereum_london_vm_stack_imports_pop : + IsImported globals "ethereum.london.vm.stack" "pop". +Axiom ethereum_london_vm_stack_imports_push : + IsImported globals "ethereum.london.vm.stack" "push". + +Definition keccak : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Pushes to the stack the Keccak-256 hash of a region of memory. + + This also expands the memory, in case the memory is insufficient to + access the data's memory location. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "memory_start_index" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "size" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "words" , + BinOp.floor_div (| + M.call (| + M.get_name (| globals, "ceil32" |), + make_list [ + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.get_name (| globals, "size" |) + ], + make_dict [] + |) + ], + make_dict [] + |), + Constant.int 32 + |) + |) in + let _ := M.assign_local (| + "word_gas_cost" , + BinOp.mult (| + M.get_name (| globals, "GAS_KECCAK256_WORD" |), + M.get_name (| globals, "words" |) + |) + |) in + let _ := M.assign_local (| + "extend_memory" , + M.call (| + M.get_name (| globals, "calculate_gas_extend_memory" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "memory" |); + make_list [ + make_tuple [ M.get_name (| globals, "memory_start_index" |); M.get_name (| globals, "size" |) ] + ] + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + BinOp.add (| + BinOp.add (| + M.get_name (| globals, "GAS_KECCAK256" |), + M.get_name (| globals, "word_gas_cost" |) + |), + M.get_field (| M.get_name (| globals, "extend_memory" |), "cost" |) + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "memory" |), + BinOp.mult (| + Constant.bytes "00", + M.get_field (| M.get_name (| globals, "extend_memory" |), "expand_by" |) + |) + |) in + let _ := M.assign_local (| + "data" , + M.call (| + M.get_name (| globals, "memory_read_bytes" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "memory" |); + M.get_name (| globals, "memory_start_index" |); + M.get_name (| globals, "size" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "hash" , + M.call (| + M.get_name (| globals, "keccak256" |), + make_list [ + M.get_name (| globals, "data" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.call (| + M.get_field (| M.get_name (| globals, "U256" |), "from_be_bytes" |), + make_list [ + M.get_name (| globals, "hash" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). diff --git a/CoqOfPython/ethereum/london/vm/instructions/log.v b/CoqOfPython/ethereum/london/vm/instructions/log.v new file mode 100644 index 0000000..8122664 --- /dev/null +++ b/CoqOfPython/ethereum/london/vm/instructions/log.v @@ -0,0 +1,256 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.london.vm.instructions.log". + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) Logging Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM logging instructions. +". + +Axiom functools_imports_partial : + IsImported globals "functools" "partial". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". + +Axiom ethereum_utils_ensure_imports_ensure : + IsImported globals "ethereum.utils.ensure" "ensure". + +Axiom ethereum_london_blocks_imports_Log : + IsImported globals "ethereum.london.blocks" "Log". + +Axiom ethereum_london_vm_imports_Evm : + IsImported globals "ethereum.london.vm" "Evm". + +Axiom ethereum_london_vm_exceptions_imports_WriteInStaticContext : + IsImported globals "ethereum.london.vm.exceptions" "WriteInStaticContext". + +Axiom ethereum_london_vm_gas_imports_GAS_LOG : + IsImported globals "ethereum.london.vm.gas" "GAS_LOG". +Axiom ethereum_london_vm_gas_imports_GAS_LOG_DATA : + IsImported globals "ethereum.london.vm.gas" "GAS_LOG_DATA". +Axiom ethereum_london_vm_gas_imports_GAS_LOG_TOPIC : + IsImported globals "ethereum.london.vm.gas" "GAS_LOG_TOPIC". +Axiom ethereum_london_vm_gas_imports_calculate_gas_extend_memory : + IsImported globals "ethereum.london.vm.gas" "calculate_gas_extend_memory". +Axiom ethereum_london_vm_gas_imports_charge_gas : + IsImported globals "ethereum.london.vm.gas" "charge_gas". + +Axiom ethereum_london_vm_memory_imports_memory_read_bytes : + IsImported globals "ethereum.london.vm.memory" "memory_read_bytes". + +Axiom ethereum_london_vm_stack_imports_pop : + IsImported globals "ethereum.london.vm.stack" "pop". + +Definition log_n : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm"; "num_topics" ] |) in + let _ := Constant.str " + Appends a log entry, having `num_topics` topics, to the evm logs. + + This will also expand the memory if the data (required by the log entry) + corresponding to the memory is not accessible. + + Parameters + ---------- + evm : + The current EVM frame. + num_topics : + The number of topics to be included in the log entry. + + " in + let _ := M.assign_local (| + "memory_start_index" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "size" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "topics" , + make_list [] + |) in + let _ := + M.for_ (| + M.get_name (| globals, "_" |), + M.call (| + M.get_name (| globals, "range" |), + make_list [ + M.get_name (| globals, "num_topics" |) + ], + make_dict [] + |), + ltac:(M.monadic ( + let _ := M.assign_local (| + "topic" , + M.call (| + M.get_field (| M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |), "to_be_bytes32" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_field (| M.get_name (| globals, "topics" |), "append" |), + make_list [ + M.get_name (| globals, "topic" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := M.assign_local (| + "extend_memory" , + M.call (| + M.get_name (| globals, "calculate_gas_extend_memory" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "memory" |); + make_list [ + make_tuple [ M.get_name (| globals, "memory_start_index" |); M.get_name (| globals, "size" |) ] + ] + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + BinOp.add (| + BinOp.add (| + BinOp.add (| + M.get_name (| globals, "GAS_LOG" |), + BinOp.mult (| + M.get_name (| globals, "GAS_LOG_DATA" |), + M.get_name (| globals, "size" |) + |) + |), + BinOp.mult (| + M.get_name (| globals, "GAS_LOG_TOPIC" |), + M.get_name (| globals, "num_topics" |) + |) + |), + M.get_field (| M.get_name (| globals, "extend_memory" |), "cost" |) + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "memory" |), + BinOp.mult (| + Constant.bytes "00", + M.get_field (| M.get_name (| globals, "extend_memory" |), "expand_by" |) + |) + |) in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + UnOp.not (| M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "is_static" |) |); + M.get_name (| globals, "WriteInStaticContext" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "log_entry" , + M.call (| + M.get_name (| globals, "Log" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, "evm" |), "logs" |), + BinOp.add (| + M.get_field (| M.get_name (| globals, "evm" |), "logs" |), + make_tuple [ M.get_name (| globals, "log_entry" |) ] + |) + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition log0 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "log_n" |) + ], + make_dict [] + |) +)). + +Definition log1 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "log_n" |) + ], + make_dict [] + |) +)). + +Definition log2 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "log_n" |) + ], + make_dict [] + |) +)). + +Definition log3 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "log_n" |) + ], + make_dict [] + |) +)). + +Definition log4 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "log_n" |) + ], + make_dict [] + |) +)). diff --git a/CoqOfPython/ethereum/london/vm/instructions/memory.v b/CoqOfPython/ethereum/london/vm/instructions/memory.v new file mode 100644 index 0000000..494a8b3 --- /dev/null +++ b/CoqOfPython/ethereum/london/vm/instructions/memory.v @@ -0,0 +1,393 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.london.vm.instructions.memory". + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) Memory Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM Memory instructions. +". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_Bytes : + IsImported globals "ethereum.base_types" "Bytes". + +Axiom ethereum_london_vm_imports_Evm : + IsImported globals "ethereum.london.vm" "Evm". + +Axiom ethereum_london_vm_gas_imports_GAS_BASE : + IsImported globals "ethereum.london.vm.gas" "GAS_BASE". +Axiom ethereum_london_vm_gas_imports_GAS_VERY_LOW : + IsImported globals "ethereum.london.vm.gas" "GAS_VERY_LOW". +Axiom ethereum_london_vm_gas_imports_calculate_gas_extend_memory : + IsImported globals "ethereum.london.vm.gas" "calculate_gas_extend_memory". +Axiom ethereum_london_vm_gas_imports_charge_gas : + IsImported globals "ethereum.london.vm.gas" "charge_gas". + +Axiom ethereum_london_vm_memory_imports_memory_read_bytes : + IsImported globals "ethereum.london.vm.memory" "memory_read_bytes". +Axiom ethereum_london_vm_memory_imports_memory_write : + IsImported globals "ethereum.london.vm.memory" "memory_write". + +Axiom ethereum_london_vm_stack_imports_pop : + IsImported globals "ethereum.london.vm.stack" "pop". +Axiom ethereum_london_vm_stack_imports_push : + IsImported globals "ethereum.london.vm.stack" "push". + +Definition mstore : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Stores a word to memory. + This also expands the memory, if the memory is + insufficient to store the word. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "start_position" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "value" , + M.call (| + M.get_field (| M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |), "to_be_bytes32" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "extend_memory" , + M.call (| + M.get_name (| globals, "calculate_gas_extend_memory" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "memory" |); + make_list [ + make_tuple [ M.get_name (| globals, "start_position" |); M.call (| + M.get_name (| globals, "U256" |), + make_list [ + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_name (| globals, "value" |) + ], + make_dict [] + |) + ], + make_dict [] + |) ] + ] + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + BinOp.add (| + M.get_name (| globals, "GAS_VERY_LOW" |), + M.get_field (| M.get_name (| globals, "extend_memory" |), "cost" |) + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "memory" |), + BinOp.mult (| + Constant.bytes "00", + M.get_field (| M.get_name (| globals, "extend_memory" |), "expand_by" |) + |) + |) in + let _ := M.call (| + M.get_name (| globals, "memory_write" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "memory" |); + M.get_name (| globals, "start_position" |); + M.get_name (| globals, "value" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition mstore8 : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Stores a byte to memory. + This also expands the memory, if the memory is + insufficient to store the word. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "start_position" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "value" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "extend_memory" , + M.call (| + M.get_name (| globals, "calculate_gas_extend_memory" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "memory" |); + make_list [ + make_tuple [ M.get_name (| globals, "start_position" |); M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 1 + ], + make_dict [] + |) ] + ] + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + BinOp.add (| + M.get_name (| globals, "GAS_VERY_LOW" |), + M.get_field (| M.get_name (| globals, "extend_memory" |), "cost" |) + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "memory" |), + BinOp.mult (| + Constant.bytes "00", + M.get_field (| M.get_name (| globals, "extend_memory" |), "expand_by" |) + |) + |) in + let _ := M.assign_local (| + "normalized_bytes_value" , + M.call (| + M.get_name (| globals, "Bytes" |), + make_list [ + make_list [ + BinOp.bit_and (| + M.get_name (| globals, "value" |), + Constant.int 255 + |) + ] + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "memory_write" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "memory" |); + M.get_name (| globals, "start_position" |); + M.get_name (| globals, "normalized_bytes_value" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition mload : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Load word from memory. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "start_position" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "extend_memory" , + M.call (| + M.get_name (| globals, "calculate_gas_extend_memory" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "memory" |); + make_list [ + make_tuple [ M.get_name (| globals, "start_position" |); M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 32 + ], + make_dict [] + |) ] + ] + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + BinOp.add (| + M.get_name (| globals, "GAS_VERY_LOW" |), + M.get_field (| M.get_name (| globals, "extend_memory" |), "cost" |) + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "memory" |), + BinOp.mult (| + Constant.bytes "00", + M.get_field (| M.get_name (| globals, "extend_memory" |), "expand_by" |) + |) + |) in + let _ := M.assign_local (| + "value" , + M.call (| + M.get_field (| M.get_name (| globals, "U256" |), "from_be_bytes" |), + make_list [ + M.call (| + M.get_name (| globals, "memory_read_bytes" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "memory" |); + M.get_name (| globals, "start_position" |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 32 + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.get_name (| globals, "value" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition msize : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Push the size of active memory in bytes onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_BASE" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "memory" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). diff --git a/CoqOfPython/ethereum/london/vm/instructions/stack.v b/CoqOfPython/ethereum/london/vm/instructions/stack.v new file mode 100644 index 0000000..b5976e8 --- /dev/null +++ b/CoqOfPython/ethereum/london/vm/instructions/stack.v @@ -0,0 +1,947 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.london.vm.instructions.stack". + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) Stack Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM stack related instructions. +". + +Axiom functools_imports_partial : + IsImported globals "functools" "partial". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". + +Axiom ethereum_utils_ensure_imports_ensure : + IsImported globals "ethereum.utils.ensure" "ensure". + +Axiom ethereum_london_vm_imports_Evm : + IsImported globals "ethereum.london.vm" "Evm". +Axiom ethereum_london_vm_imports_stack : + IsImported globals "ethereum.london.vm" "stack". + +Axiom ethereum_london_vm_exceptions_imports_StackUnderflowError : + IsImported globals "ethereum.london.vm.exceptions" "StackUnderflowError". + +Axiom ethereum_london_vm_gas_imports_GAS_BASE : + IsImported globals "ethereum.london.vm.gas" "GAS_BASE". +Axiom ethereum_london_vm_gas_imports_GAS_VERY_LOW : + IsImported globals "ethereum.london.vm.gas" "GAS_VERY_LOW". +Axiom ethereum_london_vm_gas_imports_charge_gas : + IsImported globals "ethereum.london.vm.gas" "charge_gas". + +Axiom ethereum_london_vm_memory_imports_buffer_read : + IsImported globals "ethereum.london.vm.memory" "buffer_read". + +Definition pop : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Remove item from stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.call (| + M.get_field (| M.get_name (| globals, "stack" |), "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_BASE" |) + ], + make_dict [] + |) in + let _ := M.pass (| |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition push_n : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm"; "num_bytes" ] |) in + let _ := Constant.str " + Pushes a N-byte immediate onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + num_bytes : + The number of immediate bytes to be read from the code and pushed to + the stack. + + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_VERY_LOW" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "data_to_push" , + M.call (| + M.get_field (| M.get_name (| globals, "U256" |), "from_be_bytes" |), + make_list [ + M.call (| + M.get_name (| globals, "buffer_read" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "code" |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + BinOp.add (| + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) + ], + make_dict [] + |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + M.get_name (| globals, "num_bytes" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_field (| M.get_name (| globals, "stack" |), "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.get_name (| globals, "data_to_push" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + BinOp.add (| + Constant.int 1, + M.get_name (| globals, "num_bytes" |) + |) + |) in + M.pure Constant.None_)). + +Definition dup_n : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm"; "item_number" ] |) in + let _ := Constant.str " + Duplicate the Nth stack item (from top of the stack) to the top of stack. + + Parameters + ---------- + evm : + The current EVM frame. + + item_number : + The stack item number (0-indexed from top of stack) to be duplicated + to the top of stack. + + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_VERY_LOW" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + Compare.lt (| + M.get_name (| globals, "item_number" |), + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |); + M.get_name (| globals, "StackUnderflowError" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "data_to_duplicate" , + M.get_subscript (| + M.get_field (| M.get_name (| globals, "evm" |), "stack" |), + BinOp.sub (| + BinOp.sub (| + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |), + Constant.int 1 + |), + M.get_name (| globals, "item_number" |) + |) + |) + |) in + let _ := M.call (| + M.get_field (| M.get_name (| globals, "stack" |), "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.get_name (| globals, "data_to_duplicate" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition swap_n : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm"; "item_number" ] |) in + let _ := Constant.str " + Swap the top and the `item_number` element of the stack, where + the top of the stack is position zero. + + If `item_number` is zero, this function does nothing (which should not be + possible, since there is no `SWAP0` instruction). + + Parameters + ---------- + evm : + The current EVM frame. + + item_number : + The stack item number (0-indexed from top of stack) to be swapped + with the top of stack element. + + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_VERY_LOW" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + Compare.lt (| + M.get_name (| globals, "item_number" |), + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |); + M.get_name (| globals, "StackUnderflowError" |) + ], + make_dict [] + |) in + let _ := M.assign (| + make_tuple [ M.get_subscript (| + M.get_field (| M.get_name (| globals, "evm" |), "stack" |), + UnOp.sub (| Constant.int 1 |) + |); M.get_subscript (| + M.get_field (| M.get_name (| globals, "evm" |), "stack" |), + BinOp.sub (| + UnOp.sub (| Constant.int 1 |), + M.get_name (| globals, "item_number" |) + |) + |) ], + make_tuple [ M.get_subscript (| + M.get_field (| M.get_name (| globals, "evm" |), "stack" |), + BinOp.sub (| + UnOp.sub (| Constant.int 1 |), + M.get_name (| globals, "item_number" |) + |) + |); M.get_subscript (| + M.get_field (| M.get_name (| globals, "evm" |), "stack" |), + UnOp.sub (| Constant.int 1 |) + |) ] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition push1 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push2 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push3 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push4 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push5 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push6 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push7 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push8 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push9 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push10 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push11 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push12 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push13 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push14 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push15 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push16 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push17 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push18 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push19 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push20 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push21 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push22 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push23 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push24 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push25 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push26 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push27 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push28 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push29 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push30 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push31 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push32 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "push_n" |) + ], + make_dict [] + |) +)). + +Definition dup1 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "dup_n" |) + ], + make_dict [] + |) +)). + +Definition dup2 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "dup_n" |) + ], + make_dict [] + |) +)). + +Definition dup3 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "dup_n" |) + ], + make_dict [] + |) +)). + +Definition dup4 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "dup_n" |) + ], + make_dict [] + |) +)). + +Definition dup5 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "dup_n" |) + ], + make_dict [] + |) +)). + +Definition dup6 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "dup_n" |) + ], + make_dict [] + |) +)). + +Definition dup7 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "dup_n" |) + ], + make_dict [] + |) +)). + +Definition dup8 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "dup_n" |) + ], + make_dict [] + |) +)). + +Definition dup9 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "dup_n" |) + ], + make_dict [] + |) +)). + +Definition dup10 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "dup_n" |) + ], + make_dict [] + |) +)). + +Definition dup11 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "dup_n" |) + ], + make_dict [] + |) +)). + +Definition dup12 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "dup_n" |) + ], + make_dict [] + |) +)). + +Definition dup13 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "dup_n" |) + ], + make_dict [] + |) +)). + +Definition dup14 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "dup_n" |) + ], + make_dict [] + |) +)). + +Definition dup15 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "dup_n" |) + ], + make_dict [] + |) +)). + +Definition dup16 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "dup_n" |) + ], + make_dict [] + |) +)). + +Definition swap1 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "swap_n" |) + ], + make_dict [] + |) +)). + +Definition swap2 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "swap_n" |) + ], + make_dict [] + |) +)). + +Definition swap3 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "swap_n" |) + ], + make_dict [] + |) +)). + +Definition swap4 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "swap_n" |) + ], + make_dict [] + |) +)). + +Definition swap5 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "swap_n" |) + ], + make_dict [] + |) +)). + +Definition swap6 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "swap_n" |) + ], + make_dict [] + |) +)). + +Definition swap7 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "swap_n" |) + ], + make_dict [] + |) +)). + +Definition swap8 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "swap_n" |) + ], + make_dict [] + |) +)). + +Definition swap9 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "swap_n" |) + ], + make_dict [] + |) +)). + +Definition swap10 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "swap_n" |) + ], + make_dict [] + |) +)). + +Definition swap11 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "swap_n" |) + ], + make_dict [] + |) +)). + +Definition swap12 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "swap_n" |) + ], + make_dict [] + |) +)). + +Definition swap13 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "swap_n" |) + ], + make_dict [] + |) +)). + +Definition swap14 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "swap_n" |) + ], + make_dict [] + |) +)). + +Definition swap15 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "swap_n" |) + ], + make_dict [] + |) +)). + +Definition swap16 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "swap_n" |) + ], + make_dict [] + |) +)). diff --git a/CoqOfPython/ethereum/london/vm/instructions/storage.v b/CoqOfPython/ethereum/london/vm/instructions/storage.v new file mode 100644 index 0000000..ed374ae --- /dev/null +++ b/CoqOfPython/ethereum/london/vm/instructions/storage.v @@ -0,0 +1,491 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.london.vm.instructions.storage". + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) Storage Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM storage related instructions. +". + +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". + +Axiom ethereum_utils_ensure_imports_ensure : + IsImported globals "ethereum.utils.ensure" "ensure". + +Axiom ethereum_london_state_imports_get_storage : + IsImported globals "ethereum.london.state" "get_storage". +Axiom ethereum_london_state_imports_get_storage_original : + IsImported globals "ethereum.london.state" "get_storage_original". +Axiom ethereum_london_state_imports_set_storage : + IsImported globals "ethereum.london.state" "set_storage". + +Axiom ethereum_london_vm_imports_Evm : + IsImported globals "ethereum.london.vm" "Evm". + +Axiom ethereum_london_vm_exceptions_imports_OutOfGasError : + IsImported globals "ethereum.london.vm.exceptions" "OutOfGasError". +Axiom ethereum_london_vm_exceptions_imports_WriteInStaticContext : + IsImported globals "ethereum.london.vm.exceptions" "WriteInStaticContext". + +Axiom ethereum_london_vm_gas_imports_GAS_CALL_STIPEND : + IsImported globals "ethereum.london.vm.gas" "GAS_CALL_STIPEND". +Axiom ethereum_london_vm_gas_imports_GAS_COLD_SLOAD : + IsImported globals "ethereum.london.vm.gas" "GAS_COLD_SLOAD". +Axiom ethereum_london_vm_gas_imports_GAS_STORAGE_CLEAR_REFUND : + IsImported globals "ethereum.london.vm.gas" "GAS_STORAGE_CLEAR_REFUND". +Axiom ethereum_london_vm_gas_imports_GAS_STORAGE_SET : + IsImported globals "ethereum.london.vm.gas" "GAS_STORAGE_SET". +Axiom ethereum_london_vm_gas_imports_GAS_STORAGE_UPDATE : + IsImported globals "ethereum.london.vm.gas" "GAS_STORAGE_UPDATE". +Axiom ethereum_london_vm_gas_imports_GAS_WARM_ACCESS : + IsImported globals "ethereum.london.vm.gas" "GAS_WARM_ACCESS". +Axiom ethereum_london_vm_gas_imports_charge_gas : + IsImported globals "ethereum.london.vm.gas" "charge_gas". + +Axiom ethereum_london_vm_stack_imports_pop : + IsImported globals "ethereum.london.vm.stack" "pop". +Axiom ethereum_london_vm_stack_imports_push : + IsImported globals "ethereum.london.vm.stack" "push". + +Definition sload : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Loads to the stack, the value corresponding to a certain key from the + storage of the current account. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "key" , + M.call (| + M.get_field (| M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |), "to_be_bytes32" |), + make_list [], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.in_ (| + make_tuple [ M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "current_target" |); M.get_name (| globals, "key" |) ], + M.get_field (| M.get_name (| globals, "evm" |), "accessed_storage_keys" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_WARM_ACCESS" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "accessed_storage_keys" |), "add" |), + make_list [ + make_tuple [ M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "current_target" |); M.get_name (| globals, "key" |) ] + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_COLD_SLOAD" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "value" , + M.call (| + M.get_name (| globals, "get_storage" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "env" |), "state" |); + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "current_target" |); + M.get_name (| globals, "key" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.get_name (| globals, "value" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition sstore : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Stores a value at a certain key in the current context's storage. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "key" , + M.call (| + M.get_field (| M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |), "to_be_bytes32" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "new_value" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + Compare.gt (| + M.get_field (| M.get_name (| globals, "evm" |), "gas_left" |), + M.get_name (| globals, "GAS_CALL_STIPEND" |) + |); + M.get_name (| globals, "OutOfGasError" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "original_value" , + M.call (| + M.get_name (| globals, "get_storage_original" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "env" |), "state" |); + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "current_target" |); + M.get_name (| globals, "key" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "current_value" , + M.call (| + M.get_name (| globals, "get_storage" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "env" |), "state" |); + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "current_target" |); + M.get_name (| globals, "key" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "gas_cost" , + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.not_in (| + make_tuple [ M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "current_target" |); M.get_name (| globals, "key" |) ], + M.get_field (| M.get_name (| globals, "evm" |), "accessed_storage_keys" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "accessed_storage_keys" |), "add" |), + make_list [ + make_tuple [ M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "current_target" |); M.get_name (| globals, "key" |) ] + ], + make_dict [] + |) in + let _ := M.assign_op_local (| + BinOp.add, + "gas_cost", + M.get_name (| globals, "GAS_COLD_SLOAD" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + BoolOp.and (| + Compare.eq (| + M.get_name (| globals, "original_value" |), + M.get_name (| globals, "current_value" |) + |), + ltac:(M.monadic ( + Compare.not_eq (| + M.get_name (| globals, "current_value" |), + M.get_name (| globals, "new_value" |) + |) + )) + |), + (* then *) + ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, "original_value" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_op_local (| + BinOp.add, + "gas_cost", + M.get_name (| globals, "GAS_STORAGE_SET" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_op_local (| + BinOp.add, + "gas_cost", + BinOp.sub (| + M.get_name (| globals, "GAS_STORAGE_UPDATE" |), + M.get_name (| globals, "GAS_COLD_SLOAD" |) + |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_op_local (| + BinOp.add, + "gas_cost", + M.get_name (| globals, "GAS_WARM_ACCESS" |) + |) in + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + Compare.not_eq (| + M.get_name (| globals, "current_value" |), + M.get_name (| globals, "new_value" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + BoolOp.and (| + Compare.not_eq (| + M.get_name (| globals, "original_value" |), + Constant.int 0 + |), + ltac:(M.monadic ( + BoolOp.and (| + Compare.not_eq (| + M.get_name (| globals, "current_value" |), + Constant.int 0 + |), + ltac:(M.monadic ( + Compare.eq (| + M.get_name (| globals, "new_value" |), + Constant.int 0 + |) + )) + |) + )) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "refund_counter" |), + M.call (| + M.get_name (| globals, "int" |), + make_list [ + M.get_name (| globals, "GAS_STORAGE_CLEAR_REFUND" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + BoolOp.and (| + Compare.not_eq (| + M.get_name (| globals, "original_value" |), + Constant.int 0 + |), + ltac:(M.monadic ( + Compare.eq (| + M.get_name (| globals, "current_value" |), + Constant.int 0 + |) + )) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_op (| + BinOp.sub, + M.get_field (| M.get_name (| globals, "evm" |), "refund_counter" |), + M.call (| + M.get_name (| globals, "int" |), + make_list [ + M.get_name (| globals, "GAS_STORAGE_CLEAR_REFUND" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, "original_value" |), + M.get_name (| globals, "new_value" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, "original_value" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "refund_counter" |), + M.call (| + M.get_name (| globals, "int" |), + make_list [ + BinOp.sub (| + M.get_name (| globals, "GAS_STORAGE_SET" |), + M.get_name (| globals, "GAS_WARM_ACCESS" |) + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "refund_counter" |), + M.call (| + M.get_name (| globals, "int" |), + make_list [ + BinOp.sub (| + BinOp.sub (| + M.get_name (| globals, "GAS_STORAGE_UPDATE" |), + M.get_name (| globals, "GAS_COLD_SLOAD" |) + |), + M.get_name (| globals, "GAS_WARM_ACCESS" |) + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "gas_cost" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + UnOp.not (| M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "is_static" |) |); + M.get_name (| globals, "WriteInStaticContext" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "set_storage" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "env" |), "state" |); + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "current_target" |); + M.get_name (| globals, "key" |); + M.get_name (| globals, "new_value" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). diff --git a/CoqOfPython/ethereum/london/vm/instructions/system.v b/CoqOfPython/ethereum/london/vm/instructions/system.v new file mode 100644 index 0000000..a747adf --- /dev/null +++ b/CoqOfPython/ethereum/london/vm/instructions/system.v @@ -0,0 +1,2215 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.london.vm.instructions.system". + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) System Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM system related instructions. +". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_Bytes0 : + IsImported globals "ethereum.base_types" "Bytes0". +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". + +Axiom ethereum_utils_ensure_imports_ensure : + IsImported globals "ethereum.utils.ensure" "ensure". + +Axiom ethereum_utils_numeric_imports_ceil32 : + IsImported globals "ethereum.utils.numeric" "ceil32". + +Axiom ethereum_london_fork_types_imports_Address : + IsImported globals "ethereum.london.fork_types" "Address". + +Axiom ethereum_london_state_imports_account_exists_and_is_empty : + IsImported globals "ethereum.london.state" "account_exists_and_is_empty". +Axiom ethereum_london_state_imports_account_has_code_or_nonce : + IsImported globals "ethereum.london.state" "account_has_code_or_nonce". +Axiom ethereum_london_state_imports_get_account : + IsImported globals "ethereum.london.state" "get_account". +Axiom ethereum_london_state_imports_increment_nonce : + IsImported globals "ethereum.london.state" "increment_nonce". +Axiom ethereum_london_state_imports_is_account_alive : + IsImported globals "ethereum.london.state" "is_account_alive". +Axiom ethereum_london_state_imports_set_account_balance : + IsImported globals "ethereum.london.state" "set_account_balance". + +Axiom ethereum_london_utils_address_imports_compute_contract_address : + IsImported globals "ethereum.london.utils.address" "compute_contract_address". +Axiom ethereum_london_utils_address_imports_compute_create2_contract_address : + IsImported globals "ethereum.london.utils.address" "compute_create2_contract_address". +Axiom ethereum_london_utils_address_imports_to_address : + IsImported globals "ethereum.london.utils.address" "to_address". + +Axiom ethereum_london_vm_imports_Evm : + IsImported globals "ethereum.london.vm" "Evm". +Axiom ethereum_london_vm_imports_Message : + IsImported globals "ethereum.london.vm" "Message". +Axiom ethereum_london_vm_imports_incorporate_child_on_error : + IsImported globals "ethereum.london.vm" "incorporate_child_on_error". +Axiom ethereum_london_vm_imports_incorporate_child_on_success : + IsImported globals "ethereum.london.vm" "incorporate_child_on_success". + +Axiom ethereum_london_vm_exceptions_imports_Revert : + IsImported globals "ethereum.london.vm.exceptions" "Revert". +Axiom ethereum_london_vm_exceptions_imports_WriteInStaticContext : + IsImported globals "ethereum.london.vm.exceptions" "WriteInStaticContext". + +Axiom ethereum_london_vm_gas_imports_GAS_CALL_VALUE : + IsImported globals "ethereum.london.vm.gas" "GAS_CALL_VALUE". +Axiom ethereum_london_vm_gas_imports_GAS_COLD_ACCOUNT_ACCESS : + IsImported globals "ethereum.london.vm.gas" "GAS_COLD_ACCOUNT_ACCESS". +Axiom ethereum_london_vm_gas_imports_GAS_CREATE : + IsImported globals "ethereum.london.vm.gas" "GAS_CREATE". +Axiom ethereum_london_vm_gas_imports_GAS_KECCAK256_WORD : + IsImported globals "ethereum.london.vm.gas" "GAS_KECCAK256_WORD". +Axiom ethereum_london_vm_gas_imports_GAS_NEW_ACCOUNT : + IsImported globals "ethereum.london.vm.gas" "GAS_NEW_ACCOUNT". +Axiom ethereum_london_vm_gas_imports_GAS_SELF_DESTRUCT : + IsImported globals "ethereum.london.vm.gas" "GAS_SELF_DESTRUCT". +Axiom ethereum_london_vm_gas_imports_GAS_SELF_DESTRUCT_NEW_ACCOUNT : + IsImported globals "ethereum.london.vm.gas" "GAS_SELF_DESTRUCT_NEW_ACCOUNT". +Axiom ethereum_london_vm_gas_imports_GAS_WARM_ACCESS : + IsImported globals "ethereum.london.vm.gas" "GAS_WARM_ACCESS". +Axiom ethereum_london_vm_gas_imports_GAS_ZERO : + IsImported globals "ethereum.london.vm.gas" "GAS_ZERO". +Axiom ethereum_london_vm_gas_imports_calculate_gas_extend_memory : + IsImported globals "ethereum.london.vm.gas" "calculate_gas_extend_memory". +Axiom ethereum_london_vm_gas_imports_calculate_message_call_gas : + IsImported globals "ethereum.london.vm.gas" "calculate_message_call_gas". +Axiom ethereum_london_vm_gas_imports_charge_gas : + IsImported globals "ethereum.london.vm.gas" "charge_gas". +Axiom ethereum_london_vm_gas_imports_max_message_call_gas : + IsImported globals "ethereum.london.vm.gas" "max_message_call_gas". + +Axiom ethereum_london_vm_memory_imports_memory_read_bytes : + IsImported globals "ethereum.london.vm.memory" "memory_read_bytes". +Axiom ethereum_london_vm_memory_imports_memory_write : + IsImported globals "ethereum.london.vm.memory" "memory_write". + +Axiom ethereum_london_vm_stack_imports_pop : + IsImported globals "ethereum.london.vm.stack" "pop". +Axiom ethereum_london_vm_stack_imports_push : + IsImported globals "ethereum.london.vm.stack" "push". + +Definition generic_create : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm"; "endowment"; "contract_address"; "memory_start_position"; "memory_size" ] |) in + let _ := Constant.str " + Core logic used by the `CREATE*` family of opcodes. + " in +(* At stmt: unsupported node type: ImportFrom *) + let _ := M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "accessed_addresses" |), "add" |), + make_list [ + M.get_name (| globals, "contract_address" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "create_message_gas" , + M.call (| + M.get_name (| globals, "max_message_call_gas" |), + make_list [ + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "gas_left" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_op (| + BinOp.sub, + M.get_field (| M.get_name (| globals, "evm" |), "gas_left" |), + M.get_name (| globals, "create_message_gas" |) + |) in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + UnOp.not (| M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "is_static" |) |); + M.get_name (| globals, "WriteInStaticContext" |) + ], + make_dict [] + |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, "evm" |), "return_data" |), + Constant.bytes "" + |) in + let _ := M.assign_local (| + "sender_address" , + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "current_target" |) + |) in + let _ := M.assign_local (| + "sender" , + M.call (| + M.get_name (| globals, "get_account" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "env" |), "state" |); + M.get_name (| globals, "sender_address" |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + BoolOp.or (| + Compare.lt (| + M.get_field (| M.get_name (| globals, "sender" |), "balance" |), + M.get_name (| globals, "endowment" |) + |), + ltac:(M.monadic ( + BoolOp.or (| + Compare.eq (| + M.get_field (| M.get_name (| globals, "sender" |), "nonce" |), + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + BinOp.sub (| + BinOp.pow (| + Constant.int 2, + Constant.int 64 + |), + Constant.int 1 + |) + ], + make_dict [] + |) + |), + ltac:(M.monadic ( + Compare.gt (| + BinOp.add (| + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "depth" |), + Constant.int 1 + |), + M.get_name (| globals, "STACK_DEPTH_LIMIT" |) + |) + )) + |) + )) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "gas_left" |), + M.get_name (| globals, "create_message_gas" |) + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.return_ (| + Constant.None_ + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, "account_has_code_or_nonce" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "env" |), "state" |); + M.get_name (| globals, "contract_address" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, "increment_nonce" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "env" |), "state" |); + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "current_target" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.return_ (| + Constant.None_ + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "call_data" , + M.call (| + M.get_name (| globals, "memory_read_bytes" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "memory" |); + M.get_name (| globals, "memory_start_position" |); + M.get_name (| globals, "memory_size" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "increment_nonce" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "env" |), "state" |); + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "current_target" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "child_message" , + M.call (| + M.get_name (| globals, "Message" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "child_evm" , + M.call (| + M.get_name (| globals, "process_create_message" |), + make_list [ + M.get_name (| globals, "child_message" |); + M.get_field (| M.get_name (| globals, "evm" |), "env" |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + M.get_field (| M.get_name (| globals, "child_evm" |), "error" |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, "incorporate_child_on_error" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "child_evm" |) + ], + make_dict [] + |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, "evm" |), "return_data" |), + M.get_field (| M.get_name (| globals, "child_evm" |), "output" |) + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + ], + make_dict [] + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, "incorporate_child_on_success" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "child_evm" |) + ], + make_dict [] + |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, "evm" |), "return_data" |), + Constant.bytes "" + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.call (| + M.get_field (| M.get_name (| globals, "U256" |), "from_be_bytes" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "child_evm" |), "message" |), "current_target" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_)). + +Definition create : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Creates a new account with associated code. + + Parameters + ---------- + evm : + The current EVM frame. + " in + let _ := M.assign_local (| + "endowment" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_start_position" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_size" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "extend_memory" , + M.call (| + M.get_name (| globals, "calculate_gas_extend_memory" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "memory" |); + make_list [ + make_tuple [ M.get_name (| globals, "memory_start_position" |); M.get_name (| globals, "memory_size" |) ] + ] + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + BinOp.add (| + M.get_name (| globals, "GAS_CREATE" |), + M.get_field (| M.get_name (| globals, "extend_memory" |), "cost" |) + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "memory" |), + BinOp.mult (| + Constant.bytes "00", + M.get_field (| M.get_name (| globals, "extend_memory" |), "expand_by" |) + |) + |) in + let _ := M.assign_local (| + "contract_address" , + M.call (| + M.get_name (| globals, "compute_contract_address" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "current_target" |); + M.get_field (| M.call (| + M.get_name (| globals, "get_account" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "env" |), "state" |); + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "current_target" |) + ], + make_dict [] + |), "nonce" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "generic_create" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "endowment" |); + M.get_name (| globals, "contract_address" |); + M.get_name (| globals, "memory_start_position" |); + M.get_name (| globals, "memory_size" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition create2 : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Creates a new account with associated code. + + It's similar to CREATE opcode except that the address of new account + depends on the init_code instead of the nonce of sender. + + Parameters + ---------- + evm : + The current EVM frame. + " in + let _ := M.assign_local (| + "endowment" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_start_position" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_size" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "salt" , + M.call (| + M.get_field (| M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |), "to_be_bytes32" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "extend_memory" , + M.call (| + M.get_name (| globals, "calculate_gas_extend_memory" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "memory" |); + make_list [ + make_tuple [ M.get_name (| globals, "memory_start_position" |); M.get_name (| globals, "memory_size" |) ] + ] + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "call_data_words" , + BinOp.floor_div (| + M.call (| + M.get_name (| globals, "ceil32" |), + make_list [ + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.get_name (| globals, "memory_size" |) + ], + make_dict [] + |) + ], + make_dict [] + |), + Constant.int 32 + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + BinOp.add (| + BinOp.add (| + M.get_name (| globals, "GAS_CREATE" |), + BinOp.mult (| + M.get_name (| globals, "GAS_KECCAK256_WORD" |), + M.get_name (| globals, "call_data_words" |) + |) + |), + M.get_field (| M.get_name (| globals, "extend_memory" |), "cost" |) + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "memory" |), + BinOp.mult (| + Constant.bytes "00", + M.get_field (| M.get_name (| globals, "extend_memory" |), "expand_by" |) + |) + |) in + let _ := M.assign_local (| + "contract_address" , + M.call (| + M.get_name (| globals, "compute_create2_contract_address" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "current_target" |); + M.get_name (| globals, "salt" |); + M.call (| + M.get_name (| globals, "memory_read_bytes" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "memory" |); + M.get_name (| globals, "memory_start_position" |); + M.get_name (| globals, "memory_size" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "generic_create" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "endowment" |); + M.get_name (| globals, "contract_address" |); + M.get_name (| globals, "memory_start_position" |); + M.get_name (| globals, "memory_size" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition return_ : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Halts execution returning output data. + + Parameters + ---------- + evm : + The current EVM frame. + " in + let _ := M.assign_local (| + "memory_start_position" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_size" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "extend_memory" , + M.call (| + M.get_name (| globals, "calculate_gas_extend_memory" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "memory" |); + make_list [ + make_tuple [ M.get_name (| globals, "memory_start_position" |); M.get_name (| globals, "memory_size" |) ] + ] + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + BinOp.add (| + M.get_name (| globals, "GAS_ZERO" |), + M.get_field (| M.get_name (| globals, "extend_memory" |), "cost" |) + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "memory" |), + BinOp.mult (| + Constant.bytes "00", + M.get_field (| M.get_name (| globals, "extend_memory" |), "expand_by" |) + |) + |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, "evm" |), "output" |), + M.call (| + M.get_name (| globals, "memory_read_bytes" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "memory" |); + M.get_name (| globals, "memory_start_position" |); + M.get_name (| globals, "memory_size" |) + ], + make_dict [] + |) + |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, "evm" |), "running" |), + Constant.bool false + |) in + let _ := M.pass (| |) in + M.pure Constant.None_)). + +Definition generic_call : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm"; "gas"; "value"; "caller"; "to"; "code_address"; "should_transfer_value"; "is_staticcall"; "memory_input_start_position"; "memory_input_size"; "memory_output_start_position"; "memory_output_size" ] |) in + let _ := Constant.str " + Perform the core logic of the `CALL*` family of opcodes. + " in +(* At stmt: unsupported node type: ImportFrom *) + let _ := M.assign (| + M.get_field (| M.get_name (| globals, "evm" |), "return_data" |), + Constant.bytes "" + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.gt (| + BinOp.add (| + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "depth" |), + Constant.int 1 + |), + M.get_name (| globals, "STACK_DEPTH_LIMIT" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "gas_left" |), + M.get_name (| globals, "gas" |) + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.return_ (| + Constant.None_ + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "call_data" , + M.call (| + M.get_name (| globals, "memory_read_bytes" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "memory" |); + M.get_name (| globals, "memory_input_start_position" |); + M.get_name (| globals, "memory_input_size" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "code" , + M.get_field (| M.call (| + M.get_name (| globals, "get_account" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "env" |), "state" |); + M.get_name (| globals, "code_address" |) + ], + make_dict [] + |), "code" |) + |) in + let _ := M.assign_local (| + "child_message" , + M.call (| + M.get_name (| globals, "Message" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "child_evm" , + M.call (| + M.get_name (| globals, "process_message" |), + make_list [ + M.get_name (| globals, "child_message" |); + M.get_field (| M.get_name (| globals, "evm" |), "env" |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + M.get_field (| M.get_name (| globals, "child_evm" |), "error" |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, "incorporate_child_on_error" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "child_evm" |) + ], + make_dict [] + |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, "evm" |), "return_data" |), + M.get_field (| M.get_name (| globals, "child_evm" |), "output" |) + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + ], + make_dict [] + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, "incorporate_child_on_success" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "child_evm" |) + ], + make_dict [] + |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, "evm" |), "return_data" |), + M.get_field (| M.get_name (| globals, "child_evm" |), "output" |) + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 1 + ], + make_dict [] + |) + ], + make_dict [] + |) in + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "actual_output_size" , + M.call (| + M.get_name (| globals, "min" |), + make_list [ + M.get_name (| globals, "memory_output_size" |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_field (| M.get_name (| globals, "child_evm" |), "output" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "memory_write" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "memory" |); + M.get_name (| globals, "memory_output_start_position" |); + M.slice (| + M.get_field (| M.get_name (| globals, "child_evm" |), "output" |), + Constant.None_, + M.get_name (| globals, "actual_output_size" |), + Constant.None_ + |) + ], + make_dict [] + |) in + M.pure Constant.None_)). + +Definition call : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Message-call into an account. + + Parameters + ---------- + evm : + The current EVM frame. + " in + let _ := M.assign_local (| + "gas" , + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "to" , + M.call (| + M.get_name (| globals, "to_address" |), + make_list [ + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "value" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_input_start_position" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_input_size" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_output_start_position" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_output_size" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "extend_memory" , + M.call (| + M.get_name (| globals, "calculate_gas_extend_memory" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "memory" |); + make_list [ + make_tuple [ M.get_name (| globals, "memory_input_start_position" |); M.get_name (| globals, "memory_input_size" |) ]; + make_tuple [ M.get_name (| globals, "memory_output_start_position" |); M.get_name (| globals, "memory_output_size" |) ] + ] + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.in_ (| + M.get_name (| globals, "to" |), + M.get_field (| M.get_name (| globals, "evm" |), "accessed_addresses" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "access_gas_cost" , + M.get_name (| globals, "GAS_WARM_ACCESS" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "accessed_addresses" |), "add" |), + make_list [ + M.get_name (| globals, "to" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "access_gas_cost" , + M.get_name (| globals, "GAS_COLD_ACCOUNT_ACCESS" |) + |) in + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "create_gas_cost" , + (* if *) + M.if_then_else (| + BoolOp.or (| + M.call (| + M.get_name (| globals, "is_account_alive" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "env" |), "state" |); + M.get_name (| globals, "to" |) + ], + make_dict [] + |), + ltac:(M.monadic ( + Compare.eq (| + M.get_name (| globals, "value" |), + Constant.int 0 + |) + )) + |), + (* then *) + ltac:(M.monadic ( +M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + (* else *) + )), ltac:(M.monadic ( +M.get_name (| globals, "GAS_NEW_ACCOUNT" |) + )) |) + |) in + let _ := M.assign_local (| + "transfer_gas_cost" , + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, "value" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( +M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + (* else *) + )), ltac:(M.monadic ( +M.get_name (| globals, "GAS_CALL_VALUE" |) + )) |) + |) in + let _ := M.assign_local (| + "message_call_gas" , + M.call (| + M.get_name (| globals, "calculate_message_call_gas" |), + make_list [ + M.get_name (| globals, "value" |); + M.get_name (| globals, "gas" |); + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "gas_left" |) + ], + make_dict [] + |); + M.get_field (| M.get_name (| globals, "extend_memory" |), "cost" |); + BinOp.add (| + BinOp.add (| + M.get_name (| globals, "access_gas_cost" |), + M.get_name (| globals, "create_gas_cost" |) + |), + M.get_name (| globals, "transfer_gas_cost" |) + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + BinOp.add (| + M.get_field (| M.get_name (| globals, "message_call_gas" |), "cost" |), + M.get_field (| M.get_name (| globals, "extend_memory" |), "cost" |) + |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + BoolOp.or (| + UnOp.not (| M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "is_static" |) |), + ltac:(M.monadic ( + Compare.eq (| + M.get_name (| globals, "value" |), + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + |) + )) + |); + M.get_name (| globals, "WriteInStaticContext" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "memory" |), + BinOp.mult (| + Constant.bytes "00", + M.get_field (| M.get_name (| globals, "extend_memory" |), "expand_by" |) + |) + |) in + let _ := M.assign_local (| + "sender_balance" , + M.get_field (| M.call (| + M.get_name (| globals, "get_account" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "env" |), "state" |); + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "current_target" |) + ], + make_dict [] + |), "balance" |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.lt (| + M.get_name (| globals, "sender_balance" |), + M.get_name (| globals, "value" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, "evm" |), "return_data" |), + Constant.bytes "" + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "gas_left" |), + M.get_field (| M.get_name (| globals, "message_call_gas" |), "stipend" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, "generic_call" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_field (| M.get_name (| globals, "message_call_gas" |), "stipend" |); + M.get_name (| globals, "value" |); + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "current_target" |); + M.get_name (| globals, "to" |); + M.get_name (| globals, "to" |); + Constant.bool true; + Constant.bool false; + M.get_name (| globals, "memory_input_start_position" |); + M.get_name (| globals, "memory_input_size" |); + M.get_name (| globals, "memory_output_start_position" |); + M.get_name (| globals, "memory_output_size" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + )) |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition callcode : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Message-call into this account with alternative account’s code. + + Parameters + ---------- + evm : + The current EVM frame. + " in + let _ := M.assign_local (| + "gas" , + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "code_address" , + M.call (| + M.get_name (| globals, "to_address" |), + make_list [ + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "value" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_input_start_position" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_input_size" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_output_start_position" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_output_size" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "to" , + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "current_target" |) + |) in + let _ := M.assign_local (| + "extend_memory" , + M.call (| + M.get_name (| globals, "calculate_gas_extend_memory" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "memory" |); + make_list [ + make_tuple [ M.get_name (| globals, "memory_input_start_position" |); M.get_name (| globals, "memory_input_size" |) ]; + make_tuple [ M.get_name (| globals, "memory_output_start_position" |); M.get_name (| globals, "memory_output_size" |) ] + ] + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.in_ (| + M.get_name (| globals, "code_address" |), + M.get_field (| M.get_name (| globals, "evm" |), "accessed_addresses" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "access_gas_cost" , + M.get_name (| globals, "GAS_WARM_ACCESS" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "accessed_addresses" |), "add" |), + make_list [ + M.get_name (| globals, "code_address" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "access_gas_cost" , + M.get_name (| globals, "GAS_COLD_ACCOUNT_ACCESS" |) + |) in + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "transfer_gas_cost" , + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, "value" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( +M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + (* else *) + )), ltac:(M.monadic ( +M.get_name (| globals, "GAS_CALL_VALUE" |) + )) |) + |) in + let _ := M.assign_local (| + "message_call_gas" , + M.call (| + M.get_name (| globals, "calculate_message_call_gas" |), + make_list [ + M.get_name (| globals, "value" |); + M.get_name (| globals, "gas" |); + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "gas_left" |) + ], + make_dict [] + |); + M.get_field (| M.get_name (| globals, "extend_memory" |), "cost" |); + BinOp.add (| + M.get_name (| globals, "access_gas_cost" |), + M.get_name (| globals, "transfer_gas_cost" |) + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + BinOp.add (| + M.get_field (| M.get_name (| globals, "message_call_gas" |), "cost" |), + M.get_field (| M.get_name (| globals, "extend_memory" |), "cost" |) + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "memory" |), + BinOp.mult (| + Constant.bytes "00", + M.get_field (| M.get_name (| globals, "extend_memory" |), "expand_by" |) + |) + |) in + let _ := M.assign_local (| + "sender_balance" , + M.get_field (| M.call (| + M.get_name (| globals, "get_account" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "env" |), "state" |); + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "current_target" |) + ], + make_dict [] + |), "balance" |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.lt (| + M.get_name (| globals, "sender_balance" |), + M.get_name (| globals, "value" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, "evm" |), "return_data" |), + Constant.bytes "" + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "gas_left" |), + M.get_field (| M.get_name (| globals, "message_call_gas" |), "stipend" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, "generic_call" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_field (| M.get_name (| globals, "message_call_gas" |), "stipend" |); + M.get_name (| globals, "value" |); + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "current_target" |); + M.get_name (| globals, "to" |); + M.get_name (| globals, "code_address" |); + Constant.bool true; + Constant.bool false; + M.get_name (| globals, "memory_input_start_position" |); + M.get_name (| globals, "memory_input_size" |); + M.get_name (| globals, "memory_output_start_position" |); + M.get_name (| globals, "memory_output_size" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + )) |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition selfdestruct : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Halt execution and register account for later deletion. + + Parameters + ---------- + evm : + The current EVM frame. + " in + let _ := M.assign_local (| + "beneficiary" , + M.call (| + M.get_name (| globals, "to_address" |), + make_list [ + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "gas_cost" , + M.get_name (| globals, "GAS_SELF_DESTRUCT" |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.not_in (| + M.get_name (| globals, "beneficiary" |), + M.get_field (| M.get_name (| globals, "evm" |), "accessed_addresses" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "accessed_addresses" |), "add" |), + make_list [ + M.get_name (| globals, "beneficiary" |) + ], + make_dict [] + |) in + let _ := M.assign_op_local (| + BinOp.add, + "gas_cost", + M.get_name (| globals, "GAS_COLD_ACCOUNT_ACCESS" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + BoolOp.and (| + UnOp.not (| M.call (| + M.get_name (| globals, "is_account_alive" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "env" |), "state" |); + M.get_name (| globals, "beneficiary" |) + ], + make_dict [] + |) |), + ltac:(M.monadic ( + Compare.not_eq (| + M.get_field (| M.call (| + M.get_name (| globals, "get_account" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "env" |), "state" |); + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "current_target" |) + ], + make_dict [] + |), "balance" |), + Constant.int 0 + |) + )) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_op_local (| + BinOp.add, + "gas_cost", + M.get_name (| globals, "GAS_SELF_DESTRUCT_NEW_ACCOUNT" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "gas_cost" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + UnOp.not (| M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "is_static" |) |); + M.get_name (| globals, "WriteInStaticContext" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "originator" , + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "current_target" |) + |) in + let _ := M.assign_local (| + "beneficiary_balance" , + M.get_field (| M.call (| + M.get_name (| globals, "get_account" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "env" |), "state" |); + M.get_name (| globals, "beneficiary" |) + ], + make_dict [] + |), "balance" |) + |) in + let _ := M.assign_local (| + "originator_balance" , + M.get_field (| M.call (| + M.get_name (| globals, "get_account" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "env" |), "state" |); + M.get_name (| globals, "originator" |) + ], + make_dict [] + |), "balance" |) + |) in + let _ := M.call (| + M.get_name (| globals, "set_account_balance" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "env" |), "state" |); + M.get_name (| globals, "beneficiary" |); + BinOp.add (| + M.get_name (| globals, "beneficiary_balance" |), + M.get_name (| globals, "originator_balance" |) + |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "set_account_balance" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "env" |), "state" |); + M.get_name (| globals, "originator" |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "accounts_to_delete" |), "add" |), + make_list [ + M.get_name (| globals, "originator" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, "account_exists_and_is_empty" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "env" |), "state" |); + M.get_name (| globals, "beneficiary" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "touched_accounts" |), "add" |), + make_list [ + M.get_name (| globals, "beneficiary" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, "evm" |), "running" |), + Constant.bool false + |) in + let _ := M.pass (| |) in + M.pure Constant.None_)). + +Definition delegatecall : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Message-call into an account. + + Parameters + ---------- + evm : + The current EVM frame. + " in + let _ := M.assign_local (| + "gas" , + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "code_address" , + M.call (| + M.get_name (| globals, "to_address" |), + make_list [ + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_input_start_position" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_input_size" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_output_start_position" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_output_size" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "extend_memory" , + M.call (| + M.get_name (| globals, "calculate_gas_extend_memory" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "memory" |); + make_list [ + make_tuple [ M.get_name (| globals, "memory_input_start_position" |); M.get_name (| globals, "memory_input_size" |) ]; + make_tuple [ M.get_name (| globals, "memory_output_start_position" |); M.get_name (| globals, "memory_output_size" |) ] + ] + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.in_ (| + M.get_name (| globals, "code_address" |), + M.get_field (| M.get_name (| globals, "evm" |), "accessed_addresses" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "access_gas_cost" , + M.get_name (| globals, "GAS_WARM_ACCESS" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "accessed_addresses" |), "add" |), + make_list [ + M.get_name (| globals, "code_address" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "access_gas_cost" , + M.get_name (| globals, "GAS_COLD_ACCOUNT_ACCESS" |) + |) in + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "message_call_gas" , + M.call (| + M.get_name (| globals, "calculate_message_call_gas" |), + make_list [ + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |); + M.get_name (| globals, "gas" |); + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "gas_left" |) + ], + make_dict [] + |); + M.get_field (| M.get_name (| globals, "extend_memory" |), "cost" |); + M.get_name (| globals, "access_gas_cost" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + BinOp.add (| + M.get_field (| M.get_name (| globals, "message_call_gas" |), "cost" |), + M.get_field (| M.get_name (| globals, "extend_memory" |), "cost" |) + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "memory" |), + BinOp.mult (| + Constant.bytes "00", + M.get_field (| M.get_name (| globals, "extend_memory" |), "expand_by" |) + |) + |) in + let _ := M.call (| + M.get_name (| globals, "generic_call" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_field (| M.get_name (| globals, "message_call_gas" |), "stipend" |); + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "value" |); + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "caller" |); + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "current_target" |); + M.get_name (| globals, "code_address" |); + Constant.bool false; + Constant.bool false; + M.get_name (| globals, "memory_input_start_position" |); + M.get_name (| globals, "memory_input_size" |); + M.get_name (| globals, "memory_output_start_position" |); + M.get_name (| globals, "memory_output_size" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition staticcall : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Message-call into an account. + + Parameters + ---------- + evm : + The current EVM frame. + " in + let _ := M.assign_local (| + "gas" , + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "to" , + M.call (| + M.get_name (| globals, "to_address" |), + make_list [ + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_input_start_position" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_input_size" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_output_start_position" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_output_size" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "extend_memory" , + M.call (| + M.get_name (| globals, "calculate_gas_extend_memory" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "memory" |); + make_list [ + make_tuple [ M.get_name (| globals, "memory_input_start_position" |); M.get_name (| globals, "memory_input_size" |) ]; + make_tuple [ M.get_name (| globals, "memory_output_start_position" |); M.get_name (| globals, "memory_output_size" |) ] + ] + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.in_ (| + M.get_name (| globals, "to" |), + M.get_field (| M.get_name (| globals, "evm" |), "accessed_addresses" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "access_gas_cost" , + M.get_name (| globals, "GAS_WARM_ACCESS" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "accessed_addresses" |), "add" |), + make_list [ + M.get_name (| globals, "to" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "access_gas_cost" , + M.get_name (| globals, "GAS_COLD_ACCOUNT_ACCESS" |) + |) in + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "message_call_gas" , + M.call (| + M.get_name (| globals, "calculate_message_call_gas" |), + make_list [ + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |); + M.get_name (| globals, "gas" |); + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "gas_left" |) + ], + make_dict [] + |); + M.get_field (| M.get_name (| globals, "extend_memory" |), "cost" |); + M.get_name (| globals, "access_gas_cost" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + BinOp.add (| + M.get_field (| M.get_name (| globals, "message_call_gas" |), "cost" |), + M.get_field (| M.get_name (| globals, "extend_memory" |), "cost" |) + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "memory" |), + BinOp.mult (| + Constant.bytes "00", + M.get_field (| M.get_name (| globals, "extend_memory" |), "expand_by" |) + |) + |) in + let _ := M.call (| + M.get_name (| globals, "generic_call" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_field (| M.get_name (| globals, "message_call_gas" |), "stipend" |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |); + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "current_target" |); + M.get_name (| globals, "to" |); + M.get_name (| globals, "to" |); + Constant.bool true; + Constant.bool true; + M.get_name (| globals, "memory_input_start_position" |); + M.get_name (| globals, "memory_input_size" |); + M.get_name (| globals, "memory_output_start_position" |); + M.get_name (| globals, "memory_output_size" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition revert : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Stop execution and revert state changes, without consuming all provided gas + and also has the ability to return a reason + Parameters + ---------- + evm : + The current EVM frame. + " in + let _ := M.assign_local (| + "memory_start_index" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "size" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "extend_memory" , + M.call (| + M.get_name (| globals, "calculate_gas_extend_memory" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "memory" |); + make_list [ + make_tuple [ M.get_name (| globals, "memory_start_index" |); M.get_name (| globals, "size" |) ] + ] + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_field (| M.get_name (| globals, "extend_memory" |), "cost" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "memory" |), + BinOp.mult (| + Constant.bytes "00", + M.get_field (| M.get_name (| globals, "extend_memory" |), "expand_by" |) + |) + |) in + let _ := M.assign_local (| + "output" , + M.call (| + M.get_name (| globals, "memory_read_bytes" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "memory" |); + M.get_name (| globals, "memory_start_index" |); + M.get_name (| globals, "size" |) + ], + make_dict [] + |) + |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, "evm" |), "output" |), + M.call (| + M.get_name (| globals, "bytes" |), + make_list [ + M.get_name (| globals, "output" |) + ], + make_dict [] + |) + |) in + let _ := M.raise (| Some (M.get_name (| globals, "Revert" |)) |) in + let _ := M.pass (| |) in + M.pure Constant.None_)). diff --git a/CoqOfPython/ethereum/london/vm/interpreter.v b/CoqOfPython/ethereum/london/vm/interpreter.v new file mode 100644 index 0000000..6398f45 --- /dev/null +++ b/CoqOfPython/ethereum/london/vm/interpreter.v @@ -0,0 +1,675 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.london.vm.interpreter". + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) Interpreter +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +A straightforward interpreter that executes EVM code. +". + +Axiom dataclasses_imports_dataclass : + IsImported globals "dataclasses" "dataclass". + +Axiom typing_imports_Iterable : + IsImported globals "typing" "Iterable". +Axiom typing_imports_Optional : + IsImported globals "typing" "Optional". +Axiom typing_imports_Set : + IsImported globals "typing" "Set". +Axiom typing_imports_Tuple : + IsImported globals "typing" "Tuple". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_Bytes0 : + IsImported globals "ethereum.base_types" "Bytes0". +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". + +Axiom ethereum_trace_imports_EvmStop : + IsImported globals "ethereum.trace" "EvmStop". +Axiom ethereum_trace_imports_OpEnd : + IsImported globals "ethereum.trace" "OpEnd". +Axiom ethereum_trace_imports_OpException : + IsImported globals "ethereum.trace" "OpException". +Axiom ethereum_trace_imports_OpStart : + IsImported globals "ethereum.trace" "OpStart". +Axiom ethereum_trace_imports_PrecompileEnd : + IsImported globals "ethereum.trace" "PrecompileEnd". +Axiom ethereum_trace_imports_PrecompileStart : + IsImported globals "ethereum.trace" "PrecompileStart". +Axiom ethereum_trace_imports_TransactionEnd : + IsImported globals "ethereum.trace" "TransactionEnd". +Axiom ethereum_trace_imports_evm_trace : + IsImported globals "ethereum.trace" "evm_trace". + +Axiom ethereum_utils_ensure_imports_ensure : + IsImported globals "ethereum.utils.ensure" "ensure". + +Axiom ethereum_london_blocks_imports_Log : + IsImported globals "ethereum.london.blocks" "Log". + +Axiom ethereum_london_fork_types_imports_Address : + IsImported globals "ethereum.london.fork_types" "Address". + +Axiom ethereum_london_state_imports_account_exists_and_is_empty : + IsImported globals "ethereum.london.state" "account_exists_and_is_empty". +Axiom ethereum_london_state_imports_account_has_code_or_nonce : + IsImported globals "ethereum.london.state" "account_has_code_or_nonce". +Axiom ethereum_london_state_imports_begin_transaction : + IsImported globals "ethereum.london.state" "begin_transaction". +Axiom ethereum_london_state_imports_commit_transaction : + IsImported globals "ethereum.london.state" "commit_transaction". +Axiom ethereum_london_state_imports_destroy_storage : + IsImported globals "ethereum.london.state" "destroy_storage". +Axiom ethereum_london_state_imports_increment_nonce : + IsImported globals "ethereum.london.state" "increment_nonce". +Axiom ethereum_london_state_imports_mark_account_created : + IsImported globals "ethereum.london.state" "mark_account_created". +Axiom ethereum_london_state_imports_move_ether : + IsImported globals "ethereum.london.state" "move_ether". +Axiom ethereum_london_state_imports_rollback_transaction : + IsImported globals "ethereum.london.state" "rollback_transaction". +Axiom ethereum_london_state_imports_set_code : + IsImported globals "ethereum.london.state" "set_code". +Axiom ethereum_london_state_imports_touch_account : + IsImported globals "ethereum.london.state" "touch_account". + +Axiom ethereum_london_vm_imports_Message : + IsImported globals "ethereum.london.vm" "Message". + +Axiom ethereum_london_vm_gas_imports_GAS_CODE_DEPOSIT : + IsImported globals "ethereum.london.vm.gas" "GAS_CODE_DEPOSIT". +Axiom ethereum_london_vm_gas_imports_charge_gas : + IsImported globals "ethereum.london.vm.gas" "charge_gas". + +Axiom ethereum_london_vm_precompiled_contracts_mapping_imports_PRE_COMPILED_CONTRACTS : + IsImported globals "ethereum.london.vm.precompiled_contracts.mapping" "PRE_COMPILED_CONTRACTS". + +Axiom ethereum_london_vm_imports_Environment : + IsImported globals "ethereum.london.vm" "Environment". +Axiom ethereum_london_vm_imports_Evm : + IsImported globals "ethereum.london.vm" "Evm". + +Axiom ethereum_london_vm_exceptions_imports_AddressCollision : + IsImported globals "ethereum.london.vm.exceptions" "AddressCollision". +Axiom ethereum_london_vm_exceptions_imports_ExceptionalHalt : + IsImported globals "ethereum.london.vm.exceptions" "ExceptionalHalt". +Axiom ethereum_london_vm_exceptions_imports_InvalidContractPrefix : + IsImported globals "ethereum.london.vm.exceptions" "InvalidContractPrefix". +Axiom ethereum_london_vm_exceptions_imports_InvalidOpcode : + IsImported globals "ethereum.london.vm.exceptions" "InvalidOpcode". +Axiom ethereum_london_vm_exceptions_imports_OutOfGasError : + IsImported globals "ethereum.london.vm.exceptions" "OutOfGasError". +Axiom ethereum_london_vm_exceptions_imports_Revert : + IsImported globals "ethereum.london.vm.exceptions" "Revert". +Axiom ethereum_london_vm_exceptions_imports_StackDepthLimitError : + IsImported globals "ethereum.london.vm.exceptions" "StackDepthLimitError". + +Axiom ethereum_london_vm_instructions_imports_Ops : + IsImported globals "ethereum.london.vm.instructions" "Ops". +Axiom ethereum_london_vm_instructions_imports_op_implementation : + IsImported globals "ethereum.london.vm.instructions" "op_implementation". + +Axiom ethereum_london_vm_runtime_imports_get_valid_jump_destinations : + IsImported globals "ethereum.london.vm.runtime" "get_valid_jump_destinations". + +Definition STACK_DEPTH_LIMIT : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 1024 + ], + make_dict [] + |) +)). + +Definition MAX_CODE_SIZE : Value.t := M.run ltac:(M.monadic ( + Constant.int 24576 +)). + +Definition MessageCallOutput : Value.t := + builtins.make_klass + [] + [ + + ] + [ + + ]. + +Definition process_message_call : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "message"; "env" ] |) in + let _ := Constant.str " + If `message.current` is empty then it creates a smart contract + else it executes a call from the `message.caller` to the `message.target`. + + Parameters + ---------- + message : + Transaction specific items. + + env : + External items required for EVM execution. + + Returns + ------- + output : `MessageCallOutput` + Output of the message call + " in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_field (| M.get_name (| globals, "message" |), "target" |), + M.call (| + M.get_name (| globals, "Bytes0" |), + make_list [ + Constant.bytes "" + ], + make_dict [] + |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "is_collision" , + M.call (| + M.get_name (| globals, "account_has_code_or_nonce" |), + make_list [ + M.get_field (| M.get_name (| globals, "env" |), "state" |); + M.get_field (| M.get_name (| globals, "message" |), "current_target" |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + M.get_name (| globals, "is_collision" |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + M.call (| + M.get_name (| globals, "MessageCallOutput" |), + make_list [ + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |); + M.call (| + M.get_name (| globals, "tuple" |), + make_list [], + make_dict [] + |); + M.call (| + M.get_name (| globals, "set" |), + make_list [], + make_dict [] + |); + M.call (| + M.get_name (| globals, "set" |), + make_list [], + make_dict [] + |); + M.call (| + M.get_name (| globals, "AddressCollision" |), + make_list [], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "evm" , + M.call (| + M.get_name (| globals, "process_create_message" |), + make_list [ + M.get_name (| globals, "message" |); + M.get_name (| globals, "env" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "evm" , + M.call (| + M.get_name (| globals, "process_message" |), + make_list [ + M.get_name (| globals, "message" |); + M.get_name (| globals, "env" |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, "account_exists_and_is_empty" |), + make_list [ + M.get_field (| M.get_name (| globals, "env" |), "state" |); + M.call (| + M.get_name (| globals, "Address" |), + make_list [ + M.get_field (| M.get_name (| globals, "message" |), "target" |) + ], + make_dict [] + |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "touched_accounts" |), "add" |), + make_list [ + M.call (| + M.get_name (| globals, "Address" |), + make_list [ + M.get_field (| M.get_name (| globals, "message" |), "target" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + M.get_field (| M.get_name (| globals, "evm" |), "error" |), + (* then *) + ltac:(M.monadic ( +(* At stmt: unsupported node type: AnnAssign *) + let _ := M.assign_local (| + "accounts_to_delete" , + M.call (| + M.get_name (| globals, "set" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "touched_accounts" , + M.call (| + M.get_name (| globals, "set" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "refund_counter" , + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "logs" , + M.get_field (| M.get_name (| globals, "evm" |), "logs" |) + |) in + let _ := M.assign_local (| + "accounts_to_delete" , + M.get_field (| M.get_name (| globals, "evm" |), "accounts_to_delete" |) + |) in + let _ := M.assign_local (| + "touched_accounts" , + M.get_field (| M.get_name (| globals, "evm" |), "touched_accounts" |) + |) in + let _ := M.assign_local (| + "refund_counter" , + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "refund_counter" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "tx_end" , + M.call (| + M.get_name (| globals, "TransactionEnd" |), + make_list [ + BinOp.sub (| + M.get_field (| M.get_name (| globals, "message" |), "gas" |), + M.get_field (| M.get_name (| globals, "evm" |), "gas_left" |) + |); + M.get_field (| M.get_name (| globals, "evm" |), "output" |); + M.get_field (| M.get_name (| globals, "evm" |), "error" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "evm_trace" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "tx_end" |) + ], + make_dict [] + |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, "MessageCallOutput" |), + make_list [], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Definition process_create_message : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "message"; "env" ] |) in + let _ := Constant.str " + Executes a call to create a smart contract. + + Parameters + ---------- + message : + Transaction specific items. + env : + External items required for EVM execution. + + Returns + ------- + evm: :py:class:`~ethereum.london.vm.Evm` + Items containing execution specific objects. + " in + let _ := M.call (| + M.get_name (| globals, "begin_transaction" |), + make_list [ + M.get_field (| M.get_name (| globals, "env" |), "state" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "destroy_storage" |), + make_list [ + M.get_field (| M.get_name (| globals, "env" |), "state" |); + M.get_field (| M.get_name (| globals, "message" |), "current_target" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "mark_account_created" |), + make_list [ + M.get_field (| M.get_name (| globals, "env" |), "state" |); + M.get_field (| M.get_name (| globals, "message" |), "current_target" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "increment_nonce" |), + make_list [ + M.get_field (| M.get_name (| globals, "env" |), "state" |); + M.get_field (| M.get_name (| globals, "message" |), "current_target" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "evm" , + M.call (| + M.get_name (| globals, "process_message" |), + make_list [ + M.get_name (| globals, "message" |); + M.get_name (| globals, "env" |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + UnOp.not (| M.get_field (| M.get_name (| globals, "evm" |), "error" |) |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "contract_code" , + M.get_field (| M.get_name (| globals, "evm" |), "output" |) + |) in + let _ := M.assign_local (| + "contract_code_gas" , + BinOp.mult (| + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_name (| globals, "contract_code" |) + ], + make_dict [] + |), + M.get_name (| globals, "GAS_CODE_DEPOSIT" |) + |) + |) in +(* At stmt: unsupported node type: Try *) + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, "rollback_transaction" |), + make_list [ + M.get_field (| M.get_name (| globals, "env" |), "state" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + )) |) in + let _ := M.return_ (| + M.get_name (| globals, "evm" |) + |) in + M.pure Constant.None_)). + +Definition process_message : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "message"; "env" ] |) in + let _ := Constant.str " + Executes a call to create a smart contract. + + Parameters + ---------- + message : + Transaction specific items. + env : + External items required for EVM execution. + + Returns + ------- + evm: :py:class:`~ethereum.london.vm.Evm` + Items containing execution specific objects + " in + let _ := + (* if *) + M.if_then_else (| + Compare.gt (| + M.get_field (| M.get_name (| globals, "message" |), "depth" |), + M.get_name (| globals, "STACK_DEPTH_LIMIT" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.call (| + M.get_name (| globals, "StackDepthLimitError" |), + make_list [ + Constant.str "Stack depth limit reached" + ], + make_dict [] + |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.call (| + M.get_name (| globals, "begin_transaction" |), + make_list [ + M.get_field (| M.get_name (| globals, "env" |), "state" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "touch_account" |), + make_list [ + M.get_field (| M.get_name (| globals, "env" |), "state" |); + M.get_field (| M.get_name (| globals, "message" |), "current_target" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + BoolOp.and (| + M.get_field (| M.get_name (| globals, "message" |), "should_transfer_value" |), + ltac:(M.monadic ( + Compare.not_eq (| + M.get_field (| M.get_name (| globals, "message" |), "value" |), + Constant.int 0 + |) + )) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, "move_ether" |), + make_list [ + M.get_field (| M.get_name (| globals, "env" |), "state" |); + M.get_field (| M.get_name (| globals, "message" |), "caller" |); + M.get_field (| M.get_name (| globals, "message" |), "current_target" |); + M.get_field (| M.get_name (| globals, "message" |), "value" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "evm" , + M.call (| + M.get_name (| globals, "execute_code" |), + make_list [ + M.get_name (| globals, "message" |); + M.get_name (| globals, "env" |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + M.get_field (| M.get_name (| globals, "evm" |), "error" |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, "rollback_transaction" |), + make_list [ + M.get_field (| M.get_name (| globals, "env" |), "state" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, "commit_transaction" |), + make_list [ + M.get_field (| M.get_name (| globals, "env" |), "state" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + )) |) in + let _ := M.return_ (| + M.get_name (| globals, "evm" |) + |) in + M.pure Constant.None_)). + +Definition execute_code : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "message"; "env" ] |) in + let _ := Constant.str " + Executes bytecode present in the `message`. + + Parameters + ---------- + message : + Transaction specific items. + env : + External items required for EVM execution. + + Returns + ------- + evm: `ethereum.vm.EVM` + Items containing execution specific objects + " in + let _ := M.assign_local (| + "code" , + M.get_field (| M.get_name (| globals, "message" |), "code" |) + |) in + let _ := M.assign_local (| + "valid_jump_destinations" , + M.call (| + M.get_name (| globals, "get_valid_jump_destinations" |), + make_list [ + M.get_name (| globals, "code" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "evm" , + M.call (| + M.get_name (| globals, "Evm" |), + make_list [], + make_dict [] + |) + |) in +(* At stmt: unsupported node type: Try *) + let _ := M.return_ (| + M.get_name (| globals, "evm" |) + |) in + M.pure Constant.None_)). diff --git a/CoqOfPython/ethereum/london/vm/memory.v b/CoqOfPython/ethereum/london/vm/memory.v new file mode 100644 index 0000000..69b3e08 --- /dev/null +++ b/CoqOfPython/ethereum/london/vm/memory.v @@ -0,0 +1,166 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.london.vm.memory". + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) Memory +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +EVM memory operations. +". + +Axiom ethereum_utils_byte_imports_right_pad_zero_bytes : + IsImported globals "ethereum.utils.byte" "right_pad_zero_bytes". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_Bytes : + IsImported globals "ethereum.base_types" "Bytes". +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". + +Definition memory_write : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "memory"; "start_position"; "value" ] |) in + let _ := Constant.str " + Writes to memory. + + Parameters + ---------- + memory : + Memory contents of the EVM. + start_position : + Starting pointer to the memory. + value : + Data to write to memory. + " in + let _ := M.assign (| + M.slice (| + M.get_name (| globals, "memory" |), + M.get_name (| globals, "start_position" |), + BinOp.add (| + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.get_name (| globals, "start_position" |) + ], + make_dict [] + |), + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_name (| globals, "value" |) + ], + make_dict [] + |) + |), + Constant.None_ + |), + M.get_name (| globals, "value" |) + |) in + M.pure Constant.None_)). + +Definition memory_read_bytes : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "memory"; "start_position"; "size" ] |) in + let _ := Constant.str " + Read bytes from memory. + + Parameters + ---------- + memory : + Memory contents of the EVM. + start_position : + Starting pointer to the memory. + size : + Size of the data that needs to be read from `start_position`. + + Returns + ------- + data_bytes : + Data read from memory. + " in + let _ := M.return_ (| + M.slice (| + M.get_name (| globals, "memory" |), + M.get_name (| globals, "start_position" |), + BinOp.add (| + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.get_name (| globals, "start_position" |) + ], + make_dict [] + |), + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.get_name (| globals, "size" |) + ], + make_dict [] + |) + |), + Constant.None_ + |) + |) in + M.pure Constant.None_)). + +Definition buffer_read : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "buffer"; "start_position"; "size" ] |) in + let _ := Constant.str " + Read bytes from a buffer. Padding with zeros if necessary. + + Parameters + ---------- + buffer : + Memory contents of the EVM. + start_position : + Starting pointer to the memory. + size : + Size of the data that needs to be read from `start_position`. + + Returns + ------- + data_bytes : + Data read from memory. + " in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, "right_pad_zero_bytes" |), + make_list [ + M.slice (| + M.get_name (| globals, "buffer" |), + M.get_name (| globals, "start_position" |), + BinOp.add (| + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.get_name (| globals, "start_position" |) + ], + make_dict [] + |), + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.get_name (| globals, "size" |) + ], + make_dict [] + |) + |), + Constant.None_ + |); + M.get_name (| globals, "size" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). diff --git a/CoqOfPython/ethereum/london/vm/precompiled_contracts/__init__.v b/CoqOfPython/ethereum/london/vm/precompiled_contracts/__init__.v new file mode 100644 index 0000000..3866316 --- /dev/null +++ b/CoqOfPython/ethereum/london/vm/precompiled_contracts/__init__.v @@ -0,0 +1,116 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.london.vm.precompiled_contracts.__init__". + +Definition expr_1 : Value.t := + Constant.str " +Precompiled Contract Addresses +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Addresses of precompiled contracts and mappings to their +implementations. +". + +Axiom ethereum_london_utils_hexadecimal_imports_hex_to_address : + IsImported globals "ethereum.london.utils.hexadecimal" "hex_to_address". + +Definition __all__ : Value.t := M.run ltac:(M.monadic ( + make_tuple [ Constant.str "ECRECOVER_ADDRESS"; Constant.str "SHA256_ADDRESS"; Constant.str "RIPEMD160_ADDRESS"; Constant.str "IDENTITY_ADDRESS"; Constant.str "MODEXP_ADDRESS"; Constant.str "ALT_BN128_ADD_ADDRESS"; Constant.str "ALT_BN128_MUL_ADDRESS"; Constant.str "ALT_BN128_PAIRING_CHECK_ADDRESS"; Constant.str "BLAKE2F_ADDRESS" ] +)). + +Definition ECRECOVER_ADDRESS : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "hex_to_address" |), + make_list [ + Constant.str "0x01" + ], + make_dict [] + |) +)). + +Definition SHA256_ADDRESS : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "hex_to_address" |), + make_list [ + Constant.str "0x02" + ], + make_dict [] + |) +)). + +Definition RIPEMD160_ADDRESS : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "hex_to_address" |), + make_list [ + Constant.str "0x03" + ], + make_dict [] + |) +)). + +Definition IDENTITY_ADDRESS : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "hex_to_address" |), + make_list [ + Constant.str "0x04" + ], + make_dict [] + |) +)). + +Definition MODEXP_ADDRESS : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "hex_to_address" |), + make_list [ + Constant.str "0x05" + ], + make_dict [] + |) +)). + +Definition ALT_BN128_ADD_ADDRESS : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "hex_to_address" |), + make_list [ + Constant.str "0x06" + ], + make_dict [] + |) +)). + +Definition ALT_BN128_MUL_ADDRESS : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "hex_to_address" |), + make_list [ + Constant.str "0x07" + ], + make_dict [] + |) +)). + +Definition ALT_BN128_PAIRING_CHECK_ADDRESS : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "hex_to_address" |), + make_list [ + Constant.str "0x08" + ], + make_dict [] + |) +)). + +Definition BLAKE2F_ADDRESS : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "hex_to_address" |), + make_list [ + Constant.str "0x09" + ], + make_dict [] + |) +)). diff --git a/CoqOfPython/ethereum/london/vm/precompiled_contracts/alt_bn128.v b/CoqOfPython/ethereum/london/vm/precompiled_contracts/alt_bn128.v new file mode 100644 index 0000000..40ca063 --- /dev/null +++ b/CoqOfPython/ethereum/london/vm/precompiled_contracts/alt_bn128.v @@ -0,0 +1,778 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.london.vm.precompiled_contracts.alt_bn128". + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) ALT_BN128 CONTRACTS +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementation of the ALT_BN128 precompiled contracts. +". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". + +Axiom ethereum_crypto_alt_bn128_imports_ALT_BN128_CURVE_ORDER : + IsImported globals "ethereum.crypto.alt_bn128" "ALT_BN128_CURVE_ORDER". +Axiom ethereum_crypto_alt_bn128_imports_ALT_BN128_PRIME : + IsImported globals "ethereum.crypto.alt_bn128" "ALT_BN128_PRIME". +Axiom ethereum_crypto_alt_bn128_imports_BNF : + IsImported globals "ethereum.crypto.alt_bn128" "BNF". +Axiom ethereum_crypto_alt_bn128_imports_BNF2 : + IsImported globals "ethereum.crypto.alt_bn128" "BNF2". +Axiom ethereum_crypto_alt_bn128_imports_BNF12 : + IsImported globals "ethereum.crypto.alt_bn128" "BNF12". +Axiom ethereum_crypto_alt_bn128_imports_BNP : + IsImported globals "ethereum.crypto.alt_bn128" "BNP". +Axiom ethereum_crypto_alt_bn128_imports_BNP2 : + IsImported globals "ethereum.crypto.alt_bn128" "BNP2". +Axiom ethereum_crypto_alt_bn128_imports_pairing : + IsImported globals "ethereum.crypto.alt_bn128" "pairing". + +Axiom ethereum_utils_ensure_imports_ensure : + IsImported globals "ethereum.utils.ensure" "ensure". + +Axiom ethereum_london_vm_imports_Evm : + IsImported globals "ethereum.london.vm" "Evm". + +Axiom ethereum_london_vm_gas_imports_charge_gas : + IsImported globals "ethereum.london.vm.gas" "charge_gas". + +Axiom ethereum_london_vm_memory_imports_buffer_read : + IsImported globals "ethereum.london.vm.memory" "buffer_read". + +Axiom ethereum_london_vm_exceptions_imports_OutOfGasError : + IsImported globals "ethereum.london.vm.exceptions" "OutOfGasError". + +Definition alt_bn128_add : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + The ALT_BN128 addition precompiled contract. + + Parameters + ---------- + evm : + The current EVM frame. + " in + let _ := M.assign_local (| + "data" , + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "data" |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 150 + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "x0_bytes" , + M.call (| + M.get_name (| globals, "buffer_read" |), + make_list [ + M.get_name (| globals, "data" |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 32 + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "x0_value" , + M.call (| + M.get_field (| M.get_name (| globals, "U256" |), "from_be_bytes" |), + make_list [ + M.get_name (| globals, "x0_bytes" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "y0_bytes" , + M.call (| + M.get_name (| globals, "buffer_read" |), + make_list [ + M.get_name (| globals, "data" |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 32 + ], + make_dict [] + |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 32 + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "y0_value" , + M.call (| + M.get_field (| M.get_name (| globals, "U256" |), "from_be_bytes" |), + make_list [ + M.get_name (| globals, "y0_bytes" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "x1_bytes" , + M.call (| + M.get_name (| globals, "buffer_read" |), + make_list [ + M.get_name (| globals, "data" |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 64 + ], + make_dict [] + |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 32 + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "x1_value" , + M.call (| + M.get_field (| M.get_name (| globals, "U256" |), "from_be_bytes" |), + make_list [ + M.get_name (| globals, "x1_bytes" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "y1_bytes" , + M.call (| + M.get_name (| globals, "buffer_read" |), + make_list [ + M.get_name (| globals, "data" |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 96 + ], + make_dict [] + |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 32 + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "y1_value" , + M.call (| + M.get_field (| M.get_name (| globals, "U256" |), "from_be_bytes" |), + make_list [ + M.get_name (| globals, "y1_bytes" |) + ], + make_dict [] + |) + |) in + let _ := + M.for_ (| + M.get_name (| globals, "i" |), + make_tuple [ M.get_name (| globals, "x0_value" |); M.get_name (| globals, "y0_value" |); M.get_name (| globals, "x1_value" |); M.get_name (| globals, "y1_value" |) ], + ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + Compare.gt_e (| + M.get_name (| globals, "i" |), + M.get_name (| globals, "ALT_BN128_PRIME" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, "OutOfGasError" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in +(* At stmt: unsupported node type: Try *) + let _ := M.assign_local (| + "p" , + BinOp.add (| + M.get_name (| globals, "p0" |), + M.get_name (| globals, "p1" |) + |) + |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, "evm" |), "output" |), + BinOp.add (| + M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, "p" |), "x" |), "to_be_bytes32" |), + make_list [], + make_dict [] + |), + M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, "p" |), "y" |), "to_be_bytes32" |), + make_list [], + make_dict [] + |) + |) + |) in + M.pure Constant.None_)). + +Definition alt_bn128_mul : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + The ALT_BN128 multiplication precompiled contract. + + Parameters + ---------- + evm : + The current EVM frame. + " in + let _ := M.assign_local (| + "data" , + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "data" |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 6000 + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "x0_bytes" , + M.call (| + M.get_name (| globals, "buffer_read" |), + make_list [ + M.get_name (| globals, "data" |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 32 + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "x0_value" , + M.call (| + M.get_field (| M.get_name (| globals, "U256" |), "from_be_bytes" |), + make_list [ + M.get_name (| globals, "x0_bytes" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "y0_bytes" , + M.call (| + M.get_name (| globals, "buffer_read" |), + make_list [ + M.get_name (| globals, "data" |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 32 + ], + make_dict [] + |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 32 + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "y0_value" , + M.call (| + M.get_field (| M.get_name (| globals, "U256" |), "from_be_bytes" |), + make_list [ + M.get_name (| globals, "y0_bytes" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "n" , + M.call (| + M.get_field (| M.get_name (| globals, "U256" |), "from_be_bytes" |), + make_list [ + M.call (| + M.get_name (| globals, "buffer_read" |), + make_list [ + M.get_name (| globals, "data" |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 64 + ], + make_dict [] + |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 32 + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := + M.for_ (| + M.get_name (| globals, "i" |), + make_tuple [ M.get_name (| globals, "x0_value" |); M.get_name (| globals, "y0_value" |) ], + ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + Compare.gt_e (| + M.get_name (| globals, "i" |), + M.get_name (| globals, "ALT_BN128_PRIME" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, "OutOfGasError" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in +(* At stmt: unsupported node type: Try *) + let _ := M.assign_local (| + "p" , + M.call (| + M.get_field (| M.get_name (| globals, "p0" |), "mul_by" |), + make_list [ + M.get_name (| globals, "n" |) + ], + make_dict [] + |) + |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, "evm" |), "output" |), + BinOp.add (| + M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, "p" |), "x" |), "to_be_bytes32" |), + make_list [], + make_dict [] + |), + M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, "p" |), "y" |), "to_be_bytes32" |), + make_list [], + make_dict [] + |) + |) + |) in + M.pure Constant.None_)). + +Definition alt_bn128_pairing_check : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + The ALT_BN128 pairing check precompiled contract. + + Parameters + ---------- + evm : + The current EVM frame. + " in + let _ := M.assign_local (| + "data" , + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "data" |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + BinOp.add (| + BinOp.mult (| + Constant.int 34000, + BinOp.floor_div (| + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_name (| globals, "data" |) + ], + make_dict [] + |), + Constant.int 192 + |) + |), + Constant.int 45000 + |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.not_eq (| + BinOp.mod_ (| + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_name (| globals, "data" |) + ], + make_dict [] + |), + Constant.int 192 + |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, "OutOfGasError" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "result" , + M.call (| + M.get_field (| M.get_name (| globals, "BNF12" |), "from_int" |), + make_list [ + Constant.int 1 + ], + make_dict [] + |) + |) in + let _ := + M.for_ (| + M.get_name (| globals, "i" |), + M.call (| + M.get_name (| globals, "range" |), + make_list [ + BinOp.floor_div (| + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_name (| globals, "data" |) + ], + make_dict [] + |), + Constant.int 192 + |) + ], + make_dict [] + |), + ltac:(M.monadic ( + let _ := M.assign_local (| + "values" , + make_list [] + |) in + let _ := + M.for_ (| + M.get_name (| globals, "j" |), + M.call (| + M.get_name (| globals, "range" |), + make_list [ + Constant.int 6 + ], + make_dict [] + |), + ltac:(M.monadic ( + let _ := M.assign_local (| + "value" , + M.call (| + M.get_field (| M.get_name (| globals, "U256" |), "from_be_bytes" |), + make_list [ + M.slice (| + M.get_name (| globals, "data" |), + BinOp.add (| + BinOp.mult (| + M.get_name (| globals, "i" |), + Constant.int 192 + |), + BinOp.mult (| + Constant.int 32, + M.get_name (| globals, "j" |) + |) + |), + BinOp.add (| + BinOp.mult (| + M.get_name (| globals, "i" |), + Constant.int 192 + |), + BinOp.mult (| + Constant.int 32, + BinOp.add (| + M.get_name (| globals, "j" |), + Constant.int 1 + |) + |) + |), + Constant.None_ + |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.gt_e (| + M.get_name (| globals, "value" |), + M.get_name (| globals, "ALT_BN128_PRIME" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, "OutOfGasError" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.call (| + M.get_field (| M.get_name (| globals, "values" |), "append" |), + make_list [ + M.call (| + M.get_name (| globals, "int" |), + make_list [ + M.get_name (| globals, "value" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in +(* At stmt: unsupported node type: Try *) + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + Compare.eq (| + M.call (| + M.get_field (| M.get_name (| globals, "p" |), "mul_by" |), + make_list [ + M.get_name (| globals, "ALT_BN128_CURVE_ORDER" |) + ], + make_dict [] + |), + M.call (| + M.get_field (| M.get_name (| globals, "BNP" |), "point_at_infinity" |), + make_list [], + make_dict [] + |) + |); + M.get_name (| globals, "OutOfGasError" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + Compare.eq (| + M.call (| + M.get_field (| M.get_name (| globals, "q" |), "mul_by" |), + make_list [ + M.get_name (| globals, "ALT_BN128_CURVE_ORDER" |) + ], + make_dict [] + |), + M.call (| + M.get_field (| M.get_name (| globals, "BNP2" |), "point_at_infinity" |), + make_list [], + make_dict [] + |) + |); + M.get_name (| globals, "OutOfGasError" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + BoolOp.and (| + Compare.not_eq (| + M.get_name (| globals, "p" |), + M.call (| + M.get_field (| M.get_name (| globals, "BNP" |), "point_at_infinity" |), + make_list [], + make_dict [] + |) + |), + ltac:(M.monadic ( + Compare.not_eq (| + M.get_name (| globals, "q" |), + M.call (| + M.get_field (| M.get_name (| globals, "BNP2" |), "point_at_infinity" |), + make_list [], + make_dict [] + |) + |) + )) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "result" , + BinOp.mult (| + M.get_name (| globals, "result" |), + M.call (| + M.get_name (| globals, "pairing" |), + make_list [ + M.get_name (| globals, "q" |); + M.get_name (| globals, "p" |) + ], + make_dict [] + |) + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, "result" |), + M.call (| + M.get_field (| M.get_name (| globals, "BNF12" |), "from_int" |), + make_list [ + Constant.int 1 + ], + make_dict [] + |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign (| + M.get_field (| M.get_name (| globals, "evm" |), "output" |), + M.call (| + M.get_field (| M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 1 + ], + make_dict [] + |), "to_be_bytes32" |), + make_list [], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign (| + M.get_field (| M.get_name (| globals, "evm" |), "output" |), + M.call (| + M.get_field (| M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |), "to_be_bytes32" |), + make_list [], + make_dict [] + |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_)). diff --git a/CoqOfPython/ethereum/london/vm/precompiled_contracts/blake2f.v b/CoqOfPython/ethereum/london/vm/precompiled_contracts/blake2f.v new file mode 100644 index 0000000..19507e0 --- /dev/null +++ b/CoqOfPython/ethereum/london/vm/precompiled_contracts/blake2f.v @@ -0,0 +1,127 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.london.vm.precompiled_contracts.blake2f". + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) Blake2 PRECOMPILED CONTRACT +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementation of the `Blake2` precompiled contract. +". + +Axiom ethereum_crypto_blake2_imports_Blake2b : + IsImported globals "ethereum.crypto.blake2" "Blake2b". + +Axiom ethereum_utils_ensure_imports_ensure : + IsImported globals "ethereum.utils.ensure" "ensure". + +Axiom ethereum_london_vm_imports_Evm : + IsImported globals "ethereum.london.vm" "Evm". + +Axiom ethereum_london_vm_gas_imports_GAS_BLAKE2_PER_ROUND : + IsImported globals "ethereum.london.vm.gas" "GAS_BLAKE2_PER_ROUND". +Axiom ethereum_london_vm_gas_imports_charge_gas : + IsImported globals "ethereum.london.vm.gas" "charge_gas". + +Axiom ethereum_london_vm_exceptions_imports_InvalidParameter : + IsImported globals "ethereum.london.vm.exceptions" "InvalidParameter". + +Definition blake2f : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Writes the Blake2 hash to output. + + Parameters + ---------- + evm : + The current EVM frame. + " in + let _ := M.assign_local (| + "data" , + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "data" |) + |) in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + Compare.eq (| + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_name (| globals, "data" |) + ], + make_dict [] + |), + Constant.int 213 + |); + M.get_name (| globals, "InvalidParameter" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "blake2b" , + M.call (| + M.get_name (| globals, "Blake2b" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.assign (| + make_tuple [ M.get_name (| globals, "rounds" |); M.get_name (| globals, "h" |); M.get_name (| globals, "m" |); M.get_name (| globals, "t_0" |); M.get_name (| globals, "t_1" |); M.get_name (| globals, "f" |) ], + M.call (| + M.get_field (| M.get_name (| globals, "blake2b" |), "get_blake2_parameters" |), + make_list [ + M.get_name (| globals, "data" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + BinOp.mult (| + M.get_name (| globals, "GAS_BLAKE2_PER_ROUND" |), + M.get_name (| globals, "rounds" |) + |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + Compare.in_ (| + M.get_name (| globals, "f" |), + make_list [ + Constant.int 0; + Constant.int 1 + ] + |); + M.get_name (| globals, "InvalidParameter" |) + ], + make_dict [] + |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, "evm" |), "output" |), + M.call (| + M.get_field (| M.get_name (| globals, "blake2b" |), "compress" |), + make_list [ + M.get_name (| globals, "rounds" |); + M.get_name (| globals, "h" |); + M.get_name (| globals, "m" |); + M.get_name (| globals, "t_0" |); + M.get_name (| globals, "t_1" |); + M.get_name (| globals, "f" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). diff --git a/CoqOfPython/ethereum/london/vm/precompiled_contracts/ecrecover.v b/CoqOfPython/ethereum/london/vm/precompiled_contracts/ecrecover.v new file mode 100644 index 0000000..30d0b1a --- /dev/null +++ b/CoqOfPython/ethereum/london/vm/precompiled_contracts/ecrecover.v @@ -0,0 +1,301 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.london.vm.precompiled_contracts.ecrecover". + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) ECRECOVER PRECOMPILED CONTRACT +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementation of the ECRECOVER precompiled contract. +". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". + +Axiom ethereum_crypto_elliptic_curve_imports_SECP256K1N : + IsImported globals "ethereum.crypto.elliptic_curve" "SECP256K1N". +Axiom ethereum_crypto_elliptic_curve_imports_secp256k1_recover : + IsImported globals "ethereum.crypto.elliptic_curve" "secp256k1_recover". + +Axiom ethereum_crypto_hash_imports_Hash32 : + IsImported globals "ethereum.crypto.hash" "Hash32". +Axiom ethereum_crypto_hash_imports_keccak256 : + IsImported globals "ethereum.crypto.hash" "keccak256". + +Axiom ethereum_utils_byte_imports_left_pad_zero_bytes : + IsImported globals "ethereum.utils.byte" "left_pad_zero_bytes". + +Axiom ethereum_london_vm_imports_Evm : + IsImported globals "ethereum.london.vm" "Evm". + +Axiom ethereum_london_vm_gas_imports_GAS_ECRECOVER : + IsImported globals "ethereum.london.vm.gas" "GAS_ECRECOVER". +Axiom ethereum_london_vm_gas_imports_charge_gas : + IsImported globals "ethereum.london.vm.gas" "charge_gas". + +Axiom ethereum_london_vm_memory_imports_buffer_read : + IsImported globals "ethereum.london.vm.memory" "buffer_read". + +Definition ecrecover : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Decrypts the address using elliptic curve DSA recovery mechanism and writes + the address to output. + + Parameters + ---------- + evm : + The current EVM frame. + " in + let _ := M.assign_local (| + "data" , + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "data" |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_ECRECOVER" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "message_hash_bytes" , + M.call (| + M.get_name (| globals, "buffer_read" |), + make_list [ + M.get_name (| globals, "data" |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 32 + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "message_hash" , + M.call (| + M.get_name (| globals, "Hash32" |), + make_list [ + M.get_name (| globals, "message_hash_bytes" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "v" , + M.call (| + M.get_field (| M.get_name (| globals, "U256" |), "from_be_bytes" |), + make_list [ + M.call (| + M.get_name (| globals, "buffer_read" |), + make_list [ + M.get_name (| globals, "data" |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 32 + ], + make_dict [] + |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 32 + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "r" , + M.call (| + M.get_field (| M.get_name (| globals, "U256" |), "from_be_bytes" |), + make_list [ + M.call (| + M.get_name (| globals, "buffer_read" |), + make_list [ + M.get_name (| globals, "data" |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 64 + ], + make_dict [] + |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 32 + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "s" , + M.call (| + M.get_field (| M.get_name (| globals, "U256" |), "from_be_bytes" |), + make_list [ + M.call (| + M.get_name (| globals, "buffer_read" |), + make_list [ + M.get_name (| globals, "data" |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 96 + ], + make_dict [] + |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 32 + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + BoolOp.and (| + Compare.not_eq (| + M.get_name (| globals, "v" |), + Constant.int 27 + |), + ltac:(M.monadic ( + Compare.not_eq (| + M.get_name (| globals, "v" |), + Constant.int 28 + |) + )) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + Constant.None_ + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + BoolOp.or (| + Compare.gt_e (| + Constant.int 0, + M.get_name (| globals, "r" |) + |), + ltac:(M.monadic ( + Compare.gt_e (| + M.get_name (| globals, "r" |), + M.get_name (| globals, "SECP256K1N" |) + |) + )) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + Constant.None_ + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + BoolOp.or (| + Compare.gt_e (| + Constant.int 0, + M.get_name (| globals, "s" |) + |), + ltac:(M.monadic ( + Compare.gt_e (| + M.get_name (| globals, "s" |), + M.get_name (| globals, "SECP256K1N" |) + |) + )) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + Constant.None_ + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in +(* At stmt: unsupported node type: Try *) + let _ := M.assign_local (| + "address" , + M.slice (| + M.call (| + M.get_name (| globals, "keccak256" |), + make_list [ + M.get_name (| globals, "public_key" |) + ], + make_dict [] + |), + Constant.int 12, + Constant.int 32, + Constant.None_ + |) + |) in + let _ := M.assign_local (| + "padded_address" , + M.call (| + M.get_name (| globals, "left_pad_zero_bytes" |), + make_list [ + M.get_name (| globals, "address" |); + Constant.int 32 + ], + make_dict [] + |) + |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, "evm" |), "output" |), + M.get_name (| globals, "padded_address" |) + |) in + M.pure Constant.None_)). diff --git a/CoqOfPython/ethereum/london/vm/precompiled_contracts/identity.v b/CoqOfPython/ethereum/london/vm/precompiled_contracts/identity.v new file mode 100644 index 0000000..df382e7 --- /dev/null +++ b/CoqOfPython/ethereum/london/vm/precompiled_contracts/identity.v @@ -0,0 +1,94 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.london.vm.precompiled_contracts.identity". + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) IDENTITY PRECOMPILED CONTRACT +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementation of the `IDENTITY` precompiled contract. +". + +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". + +Axiom ethereum_utils_numeric_imports_ceil32 : + IsImported globals "ethereum.utils.numeric" "ceil32". + +Axiom ethereum_london_vm_imports_Evm : + IsImported globals "ethereum.london.vm" "Evm". + +Axiom ethereum_london_vm_gas_imports_GAS_IDENTITY : + IsImported globals "ethereum.london.vm.gas" "GAS_IDENTITY". +Axiom ethereum_london_vm_gas_imports_GAS_IDENTITY_WORD : + IsImported globals "ethereum.london.vm.gas" "GAS_IDENTITY_WORD". +Axiom ethereum_london_vm_gas_imports_charge_gas : + IsImported globals "ethereum.london.vm.gas" "charge_gas". + +Definition identity : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Writes the message data to output. + + Parameters + ---------- + evm : + The current EVM frame. + " in + let _ := M.assign_local (| + "data" , + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "data" |) + |) in + let _ := M.assign_local (| + "word_count" , + BinOp.floor_div (| + M.call (| + M.get_name (| globals, "ceil32" |), + make_list [ + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_name (| globals, "data" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |), + Constant.int 32 + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + BinOp.add (| + M.get_name (| globals, "GAS_IDENTITY" |), + BinOp.mult (| + M.get_name (| globals, "GAS_IDENTITY_WORD" |), + M.get_name (| globals, "word_count" |) + |) + |) + ], + make_dict [] + |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, "evm" |), "output" |), + M.get_name (| globals, "data" |) + |) in + M.pure Constant.None_)). diff --git a/CoqOfPython/ethereum/london/vm/precompiled_contracts/mapping.v b/CoqOfPython/ethereum/london/vm/precompiled_contracts/mapping.v new file mode 100644 index 0000000..021da76 --- /dev/null +++ b/CoqOfPython/ethereum/london/vm/precompiled_contracts/mapping.v @@ -0,0 +1,72 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.london.vm.precompiled_contracts.mapping". + +Definition expr_1 : Value.t := + Constant.str " +Precompiled Contract Addresses +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Mapping of precompiled contracts their implementations. +". + +Axiom typing_imports_Callable : + IsImported globals "typing" "Callable". +Axiom typing_imports_Dict : + IsImported globals "typing" "Dict". + +Axiom ethereum_london_fork_types_imports_Address : + IsImported globals "ethereum.london.fork_types" "Address". + +Axiom ethereum_london_vm_precompiled_contracts_imports_ALT_BN128_ADD_ADDRESS : + IsImported globals "ethereum.london.vm.precompiled_contracts" "ALT_BN128_ADD_ADDRESS". +Axiom ethereum_london_vm_precompiled_contracts_imports_ALT_BN128_MUL_ADDRESS : + IsImported globals "ethereum.london.vm.precompiled_contracts" "ALT_BN128_MUL_ADDRESS". +Axiom ethereum_london_vm_precompiled_contracts_imports_ALT_BN128_PAIRING_CHECK_ADDRESS : + IsImported globals "ethereum.london.vm.precompiled_contracts" "ALT_BN128_PAIRING_CHECK_ADDRESS". +Axiom ethereum_london_vm_precompiled_contracts_imports_BLAKE2F_ADDRESS : + IsImported globals "ethereum.london.vm.precompiled_contracts" "BLAKE2F_ADDRESS". +Axiom ethereum_london_vm_precompiled_contracts_imports_ECRECOVER_ADDRESS : + IsImported globals "ethereum.london.vm.precompiled_contracts" "ECRECOVER_ADDRESS". +Axiom ethereum_london_vm_precompiled_contracts_imports_IDENTITY_ADDRESS : + IsImported globals "ethereum.london.vm.precompiled_contracts" "IDENTITY_ADDRESS". +Axiom ethereum_london_vm_precompiled_contracts_imports_MODEXP_ADDRESS : + IsImported globals "ethereum.london.vm.precompiled_contracts" "MODEXP_ADDRESS". +Axiom ethereum_london_vm_precompiled_contracts_imports_RIPEMD160_ADDRESS : + IsImported globals "ethereum.london.vm.precompiled_contracts" "RIPEMD160_ADDRESS". +Axiom ethereum_london_vm_precompiled_contracts_imports_SHA256_ADDRESS : + IsImported globals "ethereum.london.vm.precompiled_contracts" "SHA256_ADDRESS". + +Axiom ethereum_london_vm_precompiled_contracts_alt_bn128_imports_alt_bn128_add : + IsImported globals "ethereum.london.vm.precompiled_contracts.alt_bn128" "alt_bn128_add". +Axiom ethereum_london_vm_precompiled_contracts_alt_bn128_imports_alt_bn128_mul : + IsImported globals "ethereum.london.vm.precompiled_contracts.alt_bn128" "alt_bn128_mul". +Axiom ethereum_london_vm_precompiled_contracts_alt_bn128_imports_alt_bn128_pairing_check : + IsImported globals "ethereum.london.vm.precompiled_contracts.alt_bn128" "alt_bn128_pairing_check". + +Axiom ethereum_london_vm_precompiled_contracts_blake2f_imports_blake2f : + IsImported globals "ethereum.london.vm.precompiled_contracts.blake2f" "blake2f". + +Axiom ethereum_london_vm_precompiled_contracts_ecrecover_imports_ecrecover : + IsImported globals "ethereum.london.vm.precompiled_contracts.ecrecover" "ecrecover". + +Axiom ethereum_london_vm_precompiled_contracts_identity_imports_identity : + IsImported globals "ethereum.london.vm.precompiled_contracts.identity" "identity". + +Axiom ethereum_london_vm_precompiled_contracts_modexp_imports_modexp : + IsImported globals "ethereum.london.vm.precompiled_contracts.modexp" "modexp". + +Axiom ethereum_london_vm_precompiled_contracts_ripemd160_imports_ripemd160 : + IsImported globals "ethereum.london.vm.precompiled_contracts.ripemd160" "ripemd160". + +Axiom ethereum_london_vm_precompiled_contracts_sha256_imports_sha256 : + IsImported globals "ethereum.london.vm.precompiled_contracts.sha256" "sha256". + +(* At top_level_stmt: unsupported node type: AnnAssign *) diff --git a/CoqOfPython/ethereum/london/vm/precompiled_contracts/modexp.v b/CoqOfPython/ethereum/london/vm/precompiled_contracts/modexp.v new file mode 100644 index 0000000..638770d --- /dev/null +++ b/CoqOfPython/ethereum/london/vm/precompiled_contracts/modexp.v @@ -0,0 +1,676 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.london.vm.precompiled_contracts.modexp". + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) MODEXP PRECOMPILED CONTRACT +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementation of the `MODEXP` precompiled contract. +". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_Bytes : + IsImported globals "ethereum.base_types" "Bytes". +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". + +Axiom ethereum_london_vm_imports_Evm : + IsImported globals "ethereum.london.vm" "Evm". + +Axiom ethereum_london_vm_gas_imports_charge_gas : + IsImported globals "ethereum.london.vm.gas" "charge_gas". + +Axiom ethereum_london_vm_memory_imports_buffer_read : + IsImported globals "ethereum.london.vm.memory" "buffer_read". + +Definition GQUADDIVISOR : Value.t := M.run ltac:(M.monadic ( + Constant.int 3 +)). + +Definition modexp : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Calculates `(base**exp) % modulus` for arbitrary sized `base`, `exp` and. + `modulus`. The return value is the same length as the modulus. + " in + let _ := M.assign_local (| + "data" , + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "data" |) + |) in + let _ := M.assign_local (| + "base_length" , + M.call (| + M.get_field (| M.get_name (| globals, "U256" |), "from_be_bytes" |), + make_list [ + M.call (| + M.get_name (| globals, "buffer_read" |), + make_list [ + M.get_name (| globals, "data" |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 32 + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "exp_length" , + M.call (| + M.get_field (| M.get_name (| globals, "U256" |), "from_be_bytes" |), + make_list [ + M.call (| + M.get_name (| globals, "buffer_read" |), + make_list [ + M.get_name (| globals, "data" |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 32 + ], + make_dict [] + |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 32 + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "modulus_length" , + M.call (| + M.get_field (| M.get_name (| globals, "U256" |), "from_be_bytes" |), + make_list [ + M.call (| + M.get_name (| globals, "buffer_read" |), + make_list [ + M.get_name (| globals, "data" |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 64 + ], + make_dict [] + |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 32 + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "exp_start" , + BinOp.add (| + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 96 + ], + make_dict [] + |), + M.get_name (| globals, "base_length" |) + |) + |) in + let _ := M.assign_local (| + "exp_head" , + M.call (| + M.get_field (| M.get_name (| globals, "Uint" |), "from_be_bytes" |), + make_list [ + M.call (| + M.get_name (| globals, "buffer_read" |), + make_list [ + M.get_name (| globals, "data" |); + M.get_name (| globals, "exp_start" |); + M.call (| + M.get_name (| globals, "min" |), + make_list [ + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 32 + ], + make_dict [] + |); + M.get_name (| globals, "exp_length" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.call (| + M.get_name (| globals, "gas_cost" |), + make_list [ + M.get_name (| globals, "base_length" |); + M.get_name (| globals, "modulus_length" |); + M.get_name (| globals, "exp_length" |); + M.get_name (| globals, "exp_head" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + BoolOp.and (| + Compare.eq (| + M.get_name (| globals, "base_length" |), + Constant.int 0 + |), + ltac:(M.monadic ( + Compare.eq (| + M.get_name (| globals, "modulus_length" |), + Constant.int 0 + |) + )) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign (| + M.get_field (| M.get_name (| globals, "evm" |), "output" |), + M.call (| + M.get_name (| globals, "Bytes" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.return_ (| + Constant.None_ + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "base" , + M.call (| + M.get_field (| M.get_name (| globals, "Uint" |), "from_be_bytes" |), + make_list [ + M.call (| + M.get_name (| globals, "buffer_read" |), + make_list [ + M.get_name (| globals, "data" |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 96 + ], + make_dict [] + |); + M.get_name (| globals, "base_length" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "exp" , + M.call (| + M.get_field (| M.get_name (| globals, "Uint" |), "from_be_bytes" |), + make_list [ + M.call (| + M.get_name (| globals, "buffer_read" |), + make_list [ + M.get_name (| globals, "data" |); + M.get_name (| globals, "exp_start" |); + M.get_name (| globals, "exp_length" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "modulus_start" , + BinOp.add (| + M.get_name (| globals, "exp_start" |), + M.get_name (| globals, "exp_length" |) + |) + |) in + let _ := M.assign_local (| + "modulus" , + M.call (| + M.get_field (| M.get_name (| globals, "Uint" |), "from_be_bytes" |), + make_list [ + M.call (| + M.get_name (| globals, "buffer_read" |), + make_list [ + M.get_name (| globals, "data" |); + M.get_name (| globals, "modulus_start" |); + M.get_name (| globals, "modulus_length" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, "modulus" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign (| + M.get_field (| M.get_name (| globals, "evm" |), "output" |), + BinOp.mult (| + M.call (| + M.get_name (| globals, "Bytes" |), + make_list [ + Constant.bytes "00" + ], + make_dict [] + |), + M.get_name (| globals, "modulus_length" |) + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign (| + M.get_field (| M.get_name (| globals, "evm" |), "output" |), + M.call (| + M.get_field (| M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, "pow" |), + make_list [ + M.get_name (| globals, "base" |); + M.get_name (| globals, "exp" |); + M.get_name (| globals, "modulus" |) + ], + make_dict [] + |) + ], + make_dict [] + |), "to_bytes" |), + make_list [ + M.get_name (| globals, "modulus_length" |); + Constant.str "big" + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_)). + +Definition complexity : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "base_length"; "modulus_length" ] |) in + let _ := Constant.str " + Estimate the complexity of performing a modular exponentiation. + + Parameters + ---------- + + base_length : + Length of the array representing the base integer. + + modulus_length : + Length of the array representing the modulus integer. + + Returns + ------- + + complexity : `Uint` + Complexity of performing the operation. + " in + let _ := M.assign_local (| + "max_length" , + M.call (| + M.get_name (| globals, "max" |), + make_list [ + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.get_name (| globals, "base_length" |) + ], + make_dict [] + |); + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.get_name (| globals, "modulus_length" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "words" , + BinOp.floor_div (| + BinOp.add (| + M.get_name (| globals, "max_length" |), + Constant.int 7 + |), + Constant.int 8 + |) + |) in + let _ := M.return_ (| + BinOp.pow (| + M.get_name (| globals, "words" |), + Constant.int 2 + |) + |) in + M.pure Constant.None_)). + +Definition iterations : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "exponent_length"; "exponent_head" ] |) in + let _ := Constant.str " + Calculate the number of iterations required to perform a modular + exponentiation. + + Parameters + ---------- + + exponent_length : + Length of the array representing the exponent integer. + + exponent_head : + First 32 bytes of the exponent (with leading zero padding if it is + shorter than 32 bytes), as an unsigned integer. + + Returns + ------- + + iterations : `Uint` + Number of iterations. + " in + let _ := + (* if *) + M.if_then_else (| + BoolOp.and (| + Compare.lt_e (| + M.get_name (| globals, "exponent_length" |), + Constant.int 32 + |), + ltac:(M.monadic ( + Compare.eq (| + M.get_name (| globals, "exponent_head" |), + Constant.int 0 + |) + )) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "count" , + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + Compare.lt_e (| + M.get_name (| globals, "exponent_length" |), + Constant.int 32 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "bit_length" , + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.call (| + M.get_field (| M.get_name (| globals, "exponent_head" |), "bit_length" |), + make_list [], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.gt (| + M.get_name (| globals, "bit_length" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_op_local (| + BinOp.sub, + "bit_length", + Constant.int 1 + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "count" , + M.get_name (| globals, "bit_length" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "length_part" , + BinOp.mult (| + Constant.int 8, + BinOp.sub (| + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.get_name (| globals, "exponent_length" |) + ], + make_dict [] + |), + Constant.int 32 + |) + |) + |) in + let _ := M.assign_local (| + "bits_part" , + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.call (| + M.get_field (| M.get_name (| globals, "exponent_head" |), "bit_length" |), + make_list [], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.gt (| + M.get_name (| globals, "bits_part" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_op_local (| + BinOp.sub, + "bits_part", + Constant.int 1 + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "count" , + BinOp.add (| + M.get_name (| globals, "length_part" |), + M.get_name (| globals, "bits_part" |) + |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )) |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, "max" |), + make_list [ + M.get_name (| globals, "count" |); + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 1 + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Definition gas_cost : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "base_length"; "modulus_length"; "exponent_length"; "exponent_head" ] |) in + let _ := Constant.str " + Calculate the gas cost of performing a modular exponentiation. + + Parameters + ---------- + + base_length : + Length of the array representing the base integer. + + modulus_length : + Length of the array representing the modulus integer. + + exponent_length : + Length of the array representing the exponent integer. + + exponent_head : + First 32 bytes of the exponent (with leading zero padding if it is + shorter than 32 bytes), as an unsigned integer. + + Returns + ------- + + gas_cost : `Uint` + Gas required for performing the operation. + " in + let _ := M.assign_local (| + "multiplication_complexity" , + M.call (| + M.get_name (| globals, "complexity" |), + make_list [ + M.get_name (| globals, "base_length" |); + M.get_name (| globals, "modulus_length" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "iteration_count" , + M.call (| + M.get_name (| globals, "iterations" |), + make_list [ + M.get_name (| globals, "exponent_length" |); + M.get_name (| globals, "exponent_head" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "cost" , + BinOp.mult (| + M.get_name (| globals, "multiplication_complexity" |), + M.get_name (| globals, "iteration_count" |) + |) + |) in + let _ := M.assign_op_local (| + BinOp.floor_div, + "cost", + M.get_name (| globals, "GQUADDIVISOR" |) + |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, "max" |), + make_list [ + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 200 + ], + make_dict [] + |); + M.get_name (| globals, "cost" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). diff --git a/CoqOfPython/ethereum/london/vm/precompiled_contracts/ripemd160.v b/CoqOfPython/ethereum/london/vm/precompiled_contracts/ripemd160.v new file mode 100644 index 0000000..9c8567e --- /dev/null +++ b/CoqOfPython/ethereum/london/vm/precompiled_contracts/ripemd160.v @@ -0,0 +1,125 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.london.vm.precompiled_contracts.ripemd160". + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) RIPEMD160 PRECOMPILED CONTRACT +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementation of the `RIPEMD160` precompiled contract. +". + +(* At top_level_stmt: unsupported node type: Import *) + +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". + +Axiom ethereum_utils_byte_imports_left_pad_zero_bytes : + IsImported globals "ethereum.utils.byte" "left_pad_zero_bytes". + +Axiom ethereum_utils_numeric_imports_ceil32 : + IsImported globals "ethereum.utils.numeric" "ceil32". + +Axiom ethereum_london_vm_imports_Evm : + IsImported globals "ethereum.london.vm" "Evm". + +Axiom ethereum_london_vm_gas_imports_GAS_RIPEMD160 : + IsImported globals "ethereum.london.vm.gas" "GAS_RIPEMD160". +Axiom ethereum_london_vm_gas_imports_GAS_RIPEMD160_WORD : + IsImported globals "ethereum.london.vm.gas" "GAS_RIPEMD160_WORD". +Axiom ethereum_london_vm_gas_imports_charge_gas : + IsImported globals "ethereum.london.vm.gas" "charge_gas". + +Definition ripemd160 : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Writes the ripemd160 hash to output. + + Parameters + ---------- + evm : + The current EVM frame. + " in + let _ := M.assign_local (| + "data" , + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "data" |) + |) in + let _ := M.assign_local (| + "word_count" , + BinOp.floor_div (| + M.call (| + M.get_name (| globals, "ceil32" |), + make_list [ + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_name (| globals, "data" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |), + Constant.int 32 + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + BinOp.add (| + M.get_name (| globals, "GAS_RIPEMD160" |), + BinOp.mult (| + M.get_name (| globals, "GAS_RIPEMD160_WORD" |), + M.get_name (| globals, "word_count" |) + |) + |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "hash_bytes" , + M.call (| + M.get_field (| M.call (| + M.get_field (| M.get_name (| globals, "hashlib" |), "new" |), + make_list [ + Constant.str "ripemd160"; + M.get_name (| globals, "data" |) + ], + make_dict [] + |), "digest" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "padded_hash" , + M.call (| + M.get_name (| globals, "left_pad_zero_bytes" |), + make_list [ + M.get_name (| globals, "hash_bytes" |); + Constant.int 32 + ], + make_dict [] + |) + |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, "evm" |), "output" |), + M.get_name (| globals, "padded_hash" |) + |) in + M.pure Constant.None_)). diff --git a/CoqOfPython/ethereum/london/vm/precompiled_contracts/sha256.v b/CoqOfPython/ethereum/london/vm/precompiled_contracts/sha256.v new file mode 100644 index 0000000..ea0b74a --- /dev/null +++ b/CoqOfPython/ethereum/london/vm/precompiled_contracts/sha256.v @@ -0,0 +1,106 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.london.vm.precompiled_contracts.sha256". + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) SHA256 PRECOMPILED CONTRACT +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementation of the `SHA256` precompiled contract. +". + +(* At top_level_stmt: unsupported node type: Import *) + +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". + +Axiom ethereum_utils_numeric_imports_ceil32 : + IsImported globals "ethereum.utils.numeric" "ceil32". + +Axiom ethereum_london_vm_imports_Evm : + IsImported globals "ethereum.london.vm" "Evm". + +Axiom ethereum_london_vm_gas_imports_GAS_SHA256 : + IsImported globals "ethereum.london.vm.gas" "GAS_SHA256". +Axiom ethereum_london_vm_gas_imports_GAS_SHA256_WORD : + IsImported globals "ethereum.london.vm.gas" "GAS_SHA256_WORD". +Axiom ethereum_london_vm_gas_imports_charge_gas : + IsImported globals "ethereum.london.vm.gas" "charge_gas". + +Definition sha256 : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Writes the sha256 hash to output. + + Parameters + ---------- + evm : + The current EVM frame. + " in + let _ := M.assign_local (| + "data" , + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "data" |) + |) in + let _ := M.assign_local (| + "word_count" , + BinOp.floor_div (| + M.call (| + M.get_name (| globals, "ceil32" |), + make_list [ + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_name (| globals, "data" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |), + Constant.int 32 + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + BinOp.add (| + M.get_name (| globals, "GAS_SHA256" |), + BinOp.mult (| + M.get_name (| globals, "GAS_SHA256_WORD" |), + M.get_name (| globals, "word_count" |) + |) + |) + ], + make_dict [] + |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, "evm" |), "output" |), + M.call (| + M.get_field (| M.call (| + M.get_field (| M.get_name (| globals, "hashlib" |), "sha256" |), + make_list [ + M.get_name (| globals, "data" |) + ], + make_dict [] + |), "digest" |), + make_list [], + make_dict [] + |) + |) in + M.pure Constant.None_)). diff --git a/CoqOfPython/ethereum/london/vm/runtime.v b/CoqOfPython/ethereum/london/vm/runtime.v new file mode 100644 index 0000000..0b7292e --- /dev/null +++ b/CoqOfPython/ethereum/london/vm/runtime.v @@ -0,0 +1,157 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.london.vm.runtime". + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) Runtime Operations +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Runtime related operations used while executing EVM code. +". + +Axiom typing_imports_Set : + IsImported globals "typing" "Set". + +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". + +Axiom ethereum_london_vm_instructions_imports_Ops : + IsImported globals "ethereum.london.vm.instructions" "Ops". + +Definition get_valid_jump_destinations : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "code" ] |) in + let _ := Constant.str " + Analyze the evm code to obtain the set of valid jump destinations. + + Valid jump destinations are defined as follows: + * The jump destination is less than the length of the code. + * The jump destination should have the `JUMPDEST` opcode (0x5B). + * The jump destination shouldn't be part of the data corresponding to + `PUSH-N` opcodes. + + Note - Jump destinations are 0-indexed. + + Parameters + ---------- + code : + The EVM code which is to be executed. + + Returns + ------- + valid_jump_destinations: `Set[Uint]` + The set of valid jump destinations in the code. + " in + let _ := M.assign_local (| + "valid_jump_destinations" , + M.call (| + M.get_name (| globals, "set" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "pc" , + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + |) in + let _ := + M.while (| + Compare.lt (| + M.get_name (| globals, "pc" |), + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_name (| globals, "code" |) + ], + make_dict [] + |) + |), + ltac:(M.monadic ( +(* At stmt: unsupported node type: Try *) + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, "current_opcode" |), + M.get_field (| M.get_name (| globals, "Ops" |), "JUMPDEST" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_field (| M.get_name (| globals, "valid_jump_destinations" |), "add" |), + make_list [ + M.get_name (| globals, "pc" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + BoolOp.and (| + Compare.lt_e (| + M.get_field (| M.get_field (| M.get_name (| globals, "Ops" |), "PUSH1" |), "value" |), + M.get_field (| M.get_name (| globals, "current_opcode" |), "value" |) + |), + ltac:(M.monadic ( + Compare.lt_e (| + M.get_field (| M.get_name (| globals, "current_opcode" |), "value" |), + M.get_field (| M.get_field (| M.get_name (| globals, "Ops" |), "PUSH32" |), "value" |) + |) + )) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "push_data_size" , + BinOp.add (| + BinOp.sub (| + M.get_field (| M.get_name (| globals, "current_opcode" |), "value" |), + M.get_field (| M.get_field (| M.get_name (| globals, "Ops" |), "PUSH1" |), "value" |) + |), + Constant.int 1 + |) + |) in + let _ := M.assign_op_local (| + BinOp.add, + "pc", + M.get_name (| globals, "push_data_size" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )) |) in + let _ := M.assign_op_local (| + BinOp.add, + "pc", + Constant.int 1 + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := M.return_ (| + M.get_name (| globals, "valid_jump_destinations" |) + |) in + M.pure Constant.None_)). diff --git a/CoqOfPython/ethereum/london/vm/stack.v b/CoqOfPython/ethereum/london/vm/stack.v new file mode 100644 index 0000000..745ac5c --- /dev/null +++ b/CoqOfPython/ethereum/london/vm/stack.v @@ -0,0 +1,123 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.london.vm.stack". + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) Stack +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementation of the stack operators for the EVM. +". + +Axiom typing_imports_List : + IsImported globals "typing" "List". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". + +Axiom ethereum_london_vm_exceptions_imports_StackOverflowError : + IsImported globals "ethereum.london.vm.exceptions" "StackOverflowError". +Axiom ethereum_london_vm_exceptions_imports_StackUnderflowError : + IsImported globals "ethereum.london.vm.exceptions" "StackUnderflowError". + +Definition pop : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "stack" ] |) in + let _ := Constant.str " + Pops the top item off of `stack`. + + Parameters + ---------- + stack : + EVM stack. + + Returns + ------- + value : `U256` + The top element on the stack. + + " in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_name (| globals, "stack" |) + ], + make_dict [] + |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, "StackUnderflowError" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.return_ (| + M.call (| + M.get_field (| M.get_name (| globals, "stack" |), "pop" |), + make_list [], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Definition push : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "stack"; "value" ] |) in + let _ := Constant.str " + Pushes `value` onto `stack`. + + Parameters + ---------- + stack : + EVM stack. + + value : + Item to be pushed onto `stack`. + + " in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_name (| globals, "stack" |) + ], + make_dict [] + |), + Constant.int 1024 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, "StackOverflowError" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.return_ (| + M.call (| + M.get_field (| M.get_name (| globals, "stack" |), "append" |), + make_list [ + M.get_name (| globals, "value" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). diff --git a/CoqOfPython/ethereum/muir_glacier/__init__.v b/CoqOfPython/ethereum/muir_glacier/__init__.v new file mode 100644 index 0000000..bb77935 --- /dev/null +++ b/CoqOfPython/ethereum/muir_glacier/__init__.v @@ -0,0 +1,22 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.muir_glacier.__init__". + +Definition expr_1 : Value.t := + Constant.str " +The Muir Glacier fork delays the difficulty bomb. There are no other changes +in this fork. +". + +Axiom ethereum_fork_criteria_imports_ByBlockNumber : + IsImported globals "ethereum.fork_criteria" "ByBlockNumber". + +Definition FORK_CRITERIA : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "ByBlockNumber" |), + make_list [ + Constant.int 9200000 + ], + make_dict [] + |) +)). diff --git a/CoqOfPython/ethereum/muir_glacier/blocks.v b/CoqOfPython/ethereum/muir_glacier/blocks.v new file mode 100644 index 0000000..2a404eb --- /dev/null +++ b/CoqOfPython/ethereum/muir_glacier/blocks.v @@ -0,0 +1,87 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.muir_glacier.blocks". + +Definition expr_1 : Value.t := + Constant.str " +A `Block` is a single link in the chain that is Ethereum. Each `Block` contains +a `Header` and zero or more transactions. Each `Header` contains associated +metadata like the block number, parent block hash, and how much gas was +consumed by its transactions. + +Together, these blocks form a cryptographically secure journal recording the +history of all state transitions that have happened since the genesis of the +chain. +". + +Axiom dataclasses_imports_dataclass : + IsImported globals "dataclasses" "dataclass". + +Axiom typing_imports_Tuple : + IsImported globals "typing" "Tuple". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_Bytes : + IsImported globals "ethereum.base_types" "Bytes". +Axiom ethereum_base_types_imports_Bytes8 : + IsImported globals "ethereum.base_types" "Bytes8". +Axiom ethereum_base_types_imports_Bytes32 : + IsImported globals "ethereum.base_types" "Bytes32". +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". +Axiom ethereum_base_types_imports_slotted_freezable : + IsImported globals "ethereum.base_types" "slotted_freezable". + +Axiom ethereum_crypto_hash_imports_Hash32 : + IsImported globals "ethereum.crypto.hash" "Hash32". + +Axiom ethereum_muir_glacier_fork_types_imports_Address : + IsImported globals "ethereum.muir_glacier.fork_types" "Address". +Axiom ethereum_muir_glacier_fork_types_imports_Bloom : + IsImported globals "ethereum.muir_glacier.fork_types" "Bloom". +Axiom ethereum_muir_glacier_fork_types_imports_Root : + IsImported globals "ethereum.muir_glacier.fork_types" "Root". + +Axiom ethereum_muir_glacier_transactions_imports_Transaction : + IsImported globals "ethereum.muir_glacier.transactions" "Transaction". + +Definition Header : Value.t := + builtins.make_klass + [] + [ + + ] + [ + + ]. + +Definition Block : Value.t := + builtins.make_klass + [] + [ + + ] + [ + + ]. + +Definition Log : Value.t := + builtins.make_klass + [] + [ + + ] + [ + + ]. + +Definition Receipt : Value.t := + builtins.make_klass + [] + [ + + ] + [ + + ]. diff --git a/CoqOfPython/ethereum/muir_glacier/bloom.v b/CoqOfPython/ethereum/muir_glacier/bloom.v new file mode 100644 index 0000000..ee72a93 --- /dev/null +++ b/CoqOfPython/ethereum/muir_glacier/bloom.v @@ -0,0 +1,207 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.muir_glacier.bloom". + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Logs Bloom +^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +This modules defines functions for calculating bloom filters of logs. For the +general theory of bloom filters see e.g. `Wikipedia +`_. Bloom filters are used to allow +for efficient searching of logs by address and/or topic, by rapidly +eliminating blocks and receipts from their search. +". + +Axiom typing_imports_Tuple : + IsImported globals "typing" "Tuple". + +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". + +Axiom ethereum_crypto_hash_imports_keccak256 : + IsImported globals "ethereum.crypto.hash" "keccak256". + +Axiom ethereum_muir_glacier_blocks_imports_Log : + IsImported globals "ethereum.muir_glacier.blocks" "Log". + +Axiom ethereum_muir_glacier_fork_types_imports_Bloom : + IsImported globals "ethereum.muir_glacier.fork_types" "Bloom". + +Definition add_to_bloom : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "bloom"; "bloom_entry" ] |) in + let _ := Constant.str " + Add a bloom entry to the bloom filter (`bloom`). + + The number of hash functions used is 3. They are calculated by taking the + least significant 11 bits from the first 3 16-bit words of the + `keccak_256()` hash of `bloom_entry`. + + Parameters + ---------- + bloom : + The bloom filter. + bloom_entry : + An entry which is to be added to bloom filter. + " in + let _ := M.assign_local (| + "hash" , + M.call (| + M.get_name (| globals, "keccak256" |), + make_list [ + M.get_name (| globals, "bloom_entry" |) + ], + make_dict [] + |) + |) in + let _ := + M.for_ (| + M.get_name (| globals, "idx" |), + make_tuple [ Constant.int 0; Constant.int 2; Constant.int 4 ], + ltac:(M.monadic ( + let _ := M.assign_local (| + "bit_to_set" , + BinOp.bit_and (| + M.call (| + M.get_field (| M.get_name (| globals, "Uint" |), "from_be_bytes" |), + make_list [ + M.slice (| + M.get_name (| globals, "hash" |), + M.get_name (| globals, "idx" |), + BinOp.add (| + M.get_name (| globals, "idx" |), + Constant.int 2 + |), + Constant.None_ + |) + ], + make_dict [] + |), + Constant.int 2047 + |) + |) in + let _ := M.assign_local (| + "bit_index" , + BinOp.sub (| + Constant.int 2047, + M.get_name (| globals, "bit_to_set" |) + |) + |) in + let _ := M.assign_local (| + "byte_index" , + BinOp.floor_div (| + M.get_name (| globals, "bit_index" |), + Constant.int 8 + |) + |) in + let _ := M.assign_local (| + "bit_value" , + BinOp.l_shift (| + Constant.int 1, + BinOp.sub (| + Constant.int 7, + BinOp.mod_ (| + M.get_name (| globals, "bit_index" |), + Constant.int 8 + |) + |) + |) + |) in + let _ := M.assign (| + M.get_subscript (| + M.get_name (| globals, "bloom" |), + M.get_name (| globals, "byte_index" |) + |), + BinOp.bit_or (| + M.get_subscript (| + M.get_name (| globals, "bloom" |), + M.get_name (| globals, "byte_index" |) + |), + M.get_name (| globals, "bit_value" |) + |) + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + M.pure Constant.None_)). + +Definition logs_bloom : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "logs" ] |) in + let _ := Constant.str " + Obtain the logs bloom from a list of log entries. + + The address and each topic of a log are added to the bloom filter. + + Parameters + ---------- + logs : + List of logs for which the logs bloom is to be obtained. + + Returns + ------- + logs_bloom : `Bloom` + The logs bloom obtained which is 256 bytes with some bits set as per + the caller address and the log topics. + " in +(* At stmt: unsupported node type: AnnAssign *) + let _ := + M.for_ (| + M.get_name (| globals, "log" |), + M.get_name (| globals, "logs" |), + ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, "add_to_bloom" |), + make_list [ + M.get_name (| globals, "bloom" |); + M.get_field (| M.get_name (| globals, "log" |), "address" |) + ], + make_dict [] + |) in + let _ := + M.for_ (| + M.get_name (| globals, "topic" |), + M.get_field (| M.get_name (| globals, "log" |), "topics" |), + ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, "add_to_bloom" |), + make_list [ + M.get_name (| globals, "bloom" |); + M.get_name (| globals, "topic" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, "Bloom" |), + make_list [ + M.get_name (| globals, "bloom" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). diff --git a/CoqOfPython/ethereum/muir_glacier/fork.v b/CoqOfPython/ethereum/muir_glacier/fork.v new file mode 100644 index 0000000..7b80d97 --- /dev/null +++ b/CoqOfPython/ethereum/muir_glacier/fork.v @@ -0,0 +1,2655 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.muir_glacier.fork". + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Specification +^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Entry point for the Ethereum specification. +". + +Axiom dataclasses_imports_dataclass : + IsImported globals "dataclasses" "dataclass". + +Axiom typing_imports_List : + IsImported globals "typing" "List". +Axiom typing_imports_Optional : + IsImported globals "typing" "Optional". +Axiom typing_imports_Set : + IsImported globals "typing" "Set". +Axiom typing_imports_Tuple : + IsImported globals "typing" "Tuple". + +Axiom ethereum_base_types_imports_Bytes0 : + IsImported globals "ethereum.base_types" "Bytes0". + +Axiom ethereum_crypto_elliptic_curve_imports_SECP256K1N : + IsImported globals "ethereum.crypto.elliptic_curve" "SECP256K1N". +Axiom ethereum_crypto_elliptic_curve_imports_secp256k1_recover : + IsImported globals "ethereum.crypto.elliptic_curve" "secp256k1_recover". + +Axiom ethereum_crypto_hash_imports_Hash32 : + IsImported globals "ethereum.crypto.hash" "Hash32". +Axiom ethereum_crypto_hash_imports_keccak256 : + IsImported globals "ethereum.crypto.hash" "keccak256". + +Axiom ethereum_ethash_imports_dataset_size : + IsImported globals "ethereum.ethash" "dataset_size". +Axiom ethereum_ethash_imports_generate_cache : + IsImported globals "ethereum.ethash" "generate_cache". +Axiom ethereum_ethash_imports_hashimoto_light : + IsImported globals "ethereum.ethash" "hashimoto_light". + +Axiom ethereum_exceptions_imports_InvalidBlock : + IsImported globals "ethereum.exceptions" "InvalidBlock". + +Axiom ethereum_utils_ensure_imports_ensure : + IsImported globals "ethereum.utils.ensure" "ensure". + +Axiom ethereum_imports_rlp : + IsImported globals "ethereum" "rlp". + +Axiom ethereum_base_types_imports_U64 : + IsImported globals "ethereum.base_types" "U64". +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_U256_CEIL_VALUE : + IsImported globals "ethereum.base_types" "U256_CEIL_VALUE". +Axiom ethereum_base_types_imports_Bytes : + IsImported globals "ethereum.base_types" "Bytes". +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". + +Axiom ethereum_muir_glacier_imports_vm : + IsImported globals "ethereum.muir_glacier" "vm". + +Axiom ethereum_muir_glacier_blocks_imports_Block : + IsImported globals "ethereum.muir_glacier.blocks" "Block". +Axiom ethereum_muir_glacier_blocks_imports_Header : + IsImported globals "ethereum.muir_glacier.blocks" "Header". +Axiom ethereum_muir_glacier_blocks_imports_Log : + IsImported globals "ethereum.muir_glacier.blocks" "Log". +Axiom ethereum_muir_glacier_blocks_imports_Receipt : + IsImported globals "ethereum.muir_glacier.blocks" "Receipt". + +Axiom ethereum_muir_glacier_bloom_imports_logs_bloom : + IsImported globals "ethereum.muir_glacier.bloom" "logs_bloom". + +Axiom ethereum_muir_glacier_fork_types_imports_Address : + IsImported globals "ethereum.muir_glacier.fork_types" "Address". +Axiom ethereum_muir_glacier_fork_types_imports_Bloom : + IsImported globals "ethereum.muir_glacier.fork_types" "Bloom". +Axiom ethereum_muir_glacier_fork_types_imports_Root : + IsImported globals "ethereum.muir_glacier.fork_types" "Root". + +Axiom ethereum_muir_glacier_state_imports_State : + IsImported globals "ethereum.muir_glacier.state" "State". +Axiom ethereum_muir_glacier_state_imports_account_exists_and_is_empty : + IsImported globals "ethereum.muir_glacier.state" "account_exists_and_is_empty". +Axiom ethereum_muir_glacier_state_imports_create_ether : + IsImported globals "ethereum.muir_glacier.state" "create_ether". +Axiom ethereum_muir_glacier_state_imports_destroy_account : + IsImported globals "ethereum.muir_glacier.state" "destroy_account". +Axiom ethereum_muir_glacier_state_imports_get_account : + IsImported globals "ethereum.muir_glacier.state" "get_account". +Axiom ethereum_muir_glacier_state_imports_increment_nonce : + IsImported globals "ethereum.muir_glacier.state" "increment_nonce". +Axiom ethereum_muir_glacier_state_imports_set_account_balance : + IsImported globals "ethereum.muir_glacier.state" "set_account_balance". +Axiom ethereum_muir_glacier_state_imports_state_root : + IsImported globals "ethereum.muir_glacier.state" "state_root". + +Axiom ethereum_muir_glacier_transactions_imports_TX_BASE_COST : + IsImported globals "ethereum.muir_glacier.transactions" "TX_BASE_COST". +Axiom ethereum_muir_glacier_transactions_imports_TX_CREATE_COST : + IsImported globals "ethereum.muir_glacier.transactions" "TX_CREATE_COST". +Axiom ethereum_muir_glacier_transactions_imports_TX_DATA_COST_PER_NON_ZERO : + IsImported globals "ethereum.muir_glacier.transactions" "TX_DATA_COST_PER_NON_ZERO". +Axiom ethereum_muir_glacier_transactions_imports_TX_DATA_COST_PER_ZERO : + IsImported globals "ethereum.muir_glacier.transactions" "TX_DATA_COST_PER_ZERO". +Axiom ethereum_muir_glacier_transactions_imports_Transaction : + IsImported globals "ethereum.muir_glacier.transactions" "Transaction". + +Axiom ethereum_muir_glacier_trie_imports_Trie : + IsImported globals "ethereum.muir_glacier.trie" "Trie". +Axiom ethereum_muir_glacier_trie_imports_root : + IsImported globals "ethereum.muir_glacier.trie" "root". +Axiom ethereum_muir_glacier_trie_imports_trie_set : + IsImported globals "ethereum.muir_glacier.trie" "trie_set". + +Axiom ethereum_muir_glacier_utils_message_imports_prepare_message : + IsImported globals "ethereum.muir_glacier.utils.message" "prepare_message". + +Axiom ethereum_muir_glacier_vm_interpreter_imports_process_message_call : + IsImported globals "ethereum.muir_glacier.vm.interpreter" "process_message_call". + +Definition BLOCK_REWARD : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + BinOp.mult (| + Constant.int 2, + BinOp.pow (| + Constant.int 10, + Constant.int 18 + |) + |) + ], + make_dict [] + |) +)). + +Definition GAS_LIMIT_ADJUSTMENT_FACTOR : Value.t := M.run ltac:(M.monadic ( + Constant.int 1024 +)). + +Definition GAS_LIMIT_MINIMUM : Value.t := M.run ltac:(M.monadic ( + Constant.int 5000 +)). + +Definition MINIMUM_DIFFICULTY : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 131072 + ], + make_dict [] + |) +)). + +Definition MAX_OMMER_DEPTH : Value.t := M.run ltac:(M.monadic ( + Constant.int 6 +)). + +Definition BOMB_DELAY_BLOCKS : Value.t := M.run ltac:(M.monadic ( + Constant.int 9000000 +)). + +Definition EMPTY_OMMER_HASH : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "keccak256" |), + make_list [ + M.call (| + M.get_field (| M.get_name (| globals, "rlp" |), "encode" |), + make_list [ + make_list [] + ], + make_dict [] + |) + ], + make_dict [] + |) +)). + +Definition BlockChain : Value.t := + builtins.make_klass + [] + [ + + ] + [ + + ]. + +Definition apply_fork : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "old" ] |) in + let _ := Constant.str " + Transforms the state from the previous hard fork (`old`) into the block + chain object for this hard fork and returns it. + + When forks need to implement an irregular state transition, this function + is used to handle the irregularity. See the :ref:`DAO Fork ` for + an example. + + Parameters + ---------- + old : + Previous block chain object. + + Returns + ------- + new : `BlockChain` + Upgraded block chain object for this hard fork. + " in + let _ := M.return_ (| + M.get_name (| globals, "old" |) + |) in + M.pure Constant.None_)). + +Definition get_last_256_block_hashes : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "chain" ] |) in + let _ := Constant.str " + Obtain the list of hashes of the previous 256 blocks in order of + increasing block number. + + This function will return less hashes for the first 256 blocks. + + The ``BLOCKHASH`` opcode needs to access the latest hashes on the chain, + therefore this function retrieves them. + + Parameters + ---------- + chain : + History and current state. + + Returns + ------- + recent_block_hashes : `List[Hash32]` + Hashes of the recent 256 blocks in order of increasing block number. + " in + let _ := M.assign_local (| + "recent_blocks" , + M.slice (| + M.get_field (| M.get_name (| globals, "chain" |), "blocks" |), + UnOp.sub (| Constant.int 255 |), + Constant.None_, + Constant.None_ + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_name (| globals, "recent_blocks" |) + ], + make_dict [] + |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + make_list [] + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "recent_block_hashes" , + make_list [] + |) in + let _ := + M.for_ (| + M.get_name (| globals, "block" |), + M.get_name (| globals, "recent_blocks" |), + ltac:(M.monadic ( + let _ := M.assign_local (| + "prev_block_hash" , + M.get_field (| M.get_field (| M.get_name (| globals, "block" |), "header" |), "parent_hash" |) + |) in + let _ := M.call (| + M.get_field (| M.get_name (| globals, "recent_block_hashes" |), "append" |), + make_list [ + M.get_name (| globals, "prev_block_hash" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := M.assign_local (| + "most_recent_block_hash" , + M.call (| + M.get_name (| globals, "keccak256" |), + make_list [ + M.call (| + M.get_field (| M.get_name (| globals, "rlp" |), "encode" |), + make_list [ + M.get_field (| M.get_subscript (| + M.get_name (| globals, "recent_blocks" |), + UnOp.sub (| Constant.int 1 |) + |), "header" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_field (| M.get_name (| globals, "recent_block_hashes" |), "append" |), + make_list [ + M.get_name (| globals, "most_recent_block_hash" |) + ], + make_dict [] + |) in + let _ := M.return_ (| + M.get_name (| globals, "recent_block_hashes" |) + |) in + M.pure Constant.None_)). + +Definition state_transition : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "chain"; "block" ] |) in + let _ := Constant.str " + Attempts to apply a block to an existing block chain. + + All parts of the block's contents need to be verified before being added + to the chain. Blocks are verified by ensuring that the contents of the + block make logical sense with the contents of the parent block. The + information in the block's header must also match the corresponding + information in the block. + + To implement Ethereum, in theory clients are only required to store the + most recent 255 blocks of the chain since as far as execution is + concerned, only those blocks are accessed. Practically, however, clients + should store more blocks to handle reorgs. + + Parameters + ---------- + chain : + History and current state. + block : + Block to apply to `chain`. + " in + let _ := M.assign_local (| + "parent_header" , + M.get_field (| M.get_subscript (| + M.get_field (| M.get_name (| globals, "chain" |), "blocks" |), + UnOp.sub (| Constant.int 1 |) + |), "header" |) + |) in + let _ := M.call (| + M.get_name (| globals, "validate_header" |), + make_list [ + M.get_field (| M.get_name (| globals, "block" |), "header" |); + M.get_name (| globals, "parent_header" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "validate_ommers" |), + make_list [ + M.get_field (| M.get_name (| globals, "block" |), "ommers" |); + M.get_field (| M.get_name (| globals, "block" |), "header" |); + M.get_name (| globals, "chain" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "apply_body_output" , + M.call (| + M.get_name (| globals, "apply_body" |), + make_list [ + M.get_field (| M.get_name (| globals, "chain" |), "state" |); + M.call (| + M.get_name (| globals, "get_last_256_block_hashes" |), + make_list [ + M.get_name (| globals, "chain" |) + ], + make_dict [] + |); + M.get_field (| M.get_field (| M.get_name (| globals, "block" |), "header" |), "coinbase" |); + M.get_field (| M.get_field (| M.get_name (| globals, "block" |), "header" |), "number" |); + M.get_field (| M.get_field (| M.get_name (| globals, "block" |), "header" |), "gas_limit" |); + M.get_field (| M.get_field (| M.get_name (| globals, "block" |), "header" |), "timestamp" |); + M.get_field (| M.get_field (| M.get_name (| globals, "block" |), "header" |), "difficulty" |); + M.get_field (| M.get_name (| globals, "block" |), "transactions" |); + M.get_field (| M.get_name (| globals, "block" |), "ommers" |); + M.get_field (| M.get_name (| globals, "chain" |), "chain_id" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + Compare.eq (| + M.get_field (| M.get_name (| globals, "apply_body_output" |), "block_gas_used" |), + M.get_field (| M.get_field (| M.get_name (| globals, "block" |), "header" |), "gas_used" |) + |); + M.get_name (| globals, "InvalidBlock" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + Compare.eq (| + M.get_field (| M.get_name (| globals, "apply_body_output" |), "transactions_root" |), + M.get_field (| M.get_field (| M.get_name (| globals, "block" |), "header" |), "transactions_root" |) + |); + M.get_name (| globals, "InvalidBlock" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + Compare.eq (| + M.get_field (| M.get_name (| globals, "apply_body_output" |), "state_root" |), + M.get_field (| M.get_field (| M.get_name (| globals, "block" |), "header" |), "state_root" |) + |); + M.get_name (| globals, "InvalidBlock" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + Compare.eq (| + M.get_field (| M.get_name (| globals, "apply_body_output" |), "receipt_root" |), + M.get_field (| M.get_field (| M.get_name (| globals, "block" |), "header" |), "receipt_root" |) + |); + M.get_name (| globals, "InvalidBlock" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + Compare.eq (| + M.get_field (| M.get_name (| globals, "apply_body_output" |), "block_logs_bloom" |), + M.get_field (| M.get_field (| M.get_name (| globals, "block" |), "header" |), "bloom" |) + |); + M.get_name (| globals, "InvalidBlock" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, "chain" |), "blocks" |), "append" |), + make_list [ + M.get_name (| globals, "block" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.gt (| + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_field (| M.get_name (| globals, "chain" |), "blocks" |) + ], + make_dict [] + |), + Constant.int 255 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign (| + M.get_field (| M.get_name (| globals, "chain" |), "blocks" |), + M.slice (| + M.get_field (| M.get_name (| globals, "chain" |), "blocks" |), + UnOp.sub (| Constant.int 255 |), + Constant.None_, + Constant.None_ + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + M.pure Constant.None_)). + +Definition validate_header : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "header"; "parent_header" ] |) in + let _ := Constant.str " + Verifies a block header. + + In order to consider a block's header valid, the logic for the + quantities in the header should match the logic for the block itself. + For example the header timestamp should be greater than the block's parent + timestamp because the block was created *after* the parent block. + Additionally, the block's number should be directly following the parent + block's number since it is the next block in the sequence. + + Parameters + ---------- + header : + Header to check for correctness. + parent_header : + Parent Header of the header to check for correctness + " in + let _ := M.assign_local (| + "parent_has_ommers" , + Compare.not_eq (| + M.get_field (| M.get_name (| globals, "parent_header" |), "ommers_hash" |), + M.get_name (| globals, "EMPTY_OMMER_HASH" |) + |) + |) in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + Compare.gt (| + M.get_field (| M.get_name (| globals, "header" |), "timestamp" |), + M.get_field (| M.get_name (| globals, "parent_header" |), "timestamp" |) + |); + M.get_name (| globals, "InvalidBlock" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + Compare.eq (| + M.get_field (| M.get_name (| globals, "header" |), "number" |), + BinOp.add (| + M.get_field (| M.get_name (| globals, "parent_header" |), "number" |), + Constant.int 1 + |) + |); + M.get_name (| globals, "InvalidBlock" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + M.call (| + M.get_name (| globals, "check_gas_limit" |), + make_list [ + M.get_field (| M.get_name (| globals, "header" |), "gas_limit" |); + M.get_field (| M.get_name (| globals, "parent_header" |), "gas_limit" |) + ], + make_dict [] + |); + M.get_name (| globals, "InvalidBlock" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + Compare.lt_e (| + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_field (| M.get_name (| globals, "header" |), "extra_data" |) + ], + make_dict [] + |), + Constant.int 32 + |); + M.get_name (| globals, "InvalidBlock" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "block_difficulty" , + M.call (| + M.get_name (| globals, "calculate_block_difficulty" |), + make_list [ + M.get_field (| M.get_name (| globals, "header" |), "number" |); + M.get_field (| M.get_name (| globals, "header" |), "timestamp" |); + M.get_field (| M.get_name (| globals, "parent_header" |), "timestamp" |); + M.get_field (| M.get_name (| globals, "parent_header" |), "difficulty" |); + M.get_name (| globals, "parent_has_ommers" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + Compare.eq (| + M.get_field (| M.get_name (| globals, "header" |), "difficulty" |), + M.get_name (| globals, "block_difficulty" |) + |); + M.get_name (| globals, "InvalidBlock" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "block_parent_hash" , + M.call (| + M.get_name (| globals, "keccak256" |), + make_list [ + M.call (| + M.get_field (| M.get_name (| globals, "rlp" |), "encode" |), + make_list [ + M.get_name (| globals, "parent_header" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + Compare.eq (| + M.get_field (| M.get_name (| globals, "header" |), "parent_hash" |), + M.get_name (| globals, "block_parent_hash" |) + |); + M.get_name (| globals, "InvalidBlock" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "validate_proof_of_work" |), + make_list [ + M.get_name (| globals, "header" |) + ], + make_dict [] + |) in + M.pure Constant.None_)). + +Definition generate_header_hash_for_pow : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "header" ] |) in + let _ := Constant.str " + Generate rlp hash of the header which is to be used for Proof-of-Work + verification. + + In other words, the PoW artefacts `mix_digest` and `nonce` are ignored + while calculating this hash. + + A particular PoW is valid for a single hash, that hash is computed by + this function. The `nonce` and `mix_digest` are omitted from this hash + because they are being changed by miners in their search for a sufficient + proof-of-work. + + Parameters + ---------- + header : + The header object for which the hash is to be generated. + + Returns + ------- + hash : `Hash32` + The PoW valid rlp hash of the passed in header. + " in + let _ := M.assign_local (| + "header_data_without_pow_artefacts" , + make_list [ + M.get_field (| M.get_name (| globals, "header" |), "parent_hash" |); + M.get_field (| M.get_name (| globals, "header" |), "ommers_hash" |); + M.get_field (| M.get_name (| globals, "header" |), "coinbase" |); + M.get_field (| M.get_name (| globals, "header" |), "state_root" |); + M.get_field (| M.get_name (| globals, "header" |), "transactions_root" |); + M.get_field (| M.get_name (| globals, "header" |), "receipt_root" |); + M.get_field (| M.get_name (| globals, "header" |), "bloom" |); + M.get_field (| M.get_name (| globals, "header" |), "difficulty" |); + M.get_field (| M.get_name (| globals, "header" |), "number" |); + M.get_field (| M.get_name (| globals, "header" |), "gas_limit" |); + M.get_field (| M.get_name (| globals, "header" |), "gas_used" |); + M.get_field (| M.get_name (| globals, "header" |), "timestamp" |); + M.get_field (| M.get_name (| globals, "header" |), "extra_data" |) + ] + |) in + let _ := M.return_ (| + M.call (| + M.get_field (| M.get_name (| globals, "rlp" |), "rlp_hash" |), + make_list [ + M.get_name (| globals, "header_data_without_pow_artefacts" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Definition validate_proof_of_work : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "header" ] |) in + let _ := Constant.str " + Validates the Proof of Work constraints. + + In order to verify that a miner's proof-of-work is valid for a block, a + ``mix-digest`` and ``result`` are calculated using the ``hashimoto_light`` + hash function. The mix digest is a hash of the header and the nonce that + is passed through and it confirms whether or not proof-of-work was done + on the correct block. The result is the actual hash value of the block. + + Parameters + ---------- + header : + Header of interest. + " in + let _ := M.assign_local (| + "header_hash" , + M.call (| + M.get_name (| globals, "generate_header_hash_for_pow" |), + make_list [ + M.get_name (| globals, "header" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "cache" , + M.call (| + M.get_name (| globals, "generate_cache" |), + make_list [ + M.get_field (| M.get_name (| globals, "header" |), "number" |) + ], + make_dict [] + |) + |) in + let _ := M.assign (| + make_tuple [ M.get_name (| globals, "mix_digest" |); M.get_name (| globals, "result" |) ], + M.call (| + M.get_name (| globals, "hashimoto_light" |), + make_list [ + M.get_name (| globals, "header_hash" |); + M.get_field (| M.get_name (| globals, "header" |), "nonce" |); + M.get_name (| globals, "cache" |); + M.call (| + M.get_name (| globals, "dataset_size" |), + make_list [ + M.get_field (| M.get_name (| globals, "header" |), "number" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + Compare.eq (| + M.get_name (| globals, "mix_digest" |), + M.get_field (| M.get_name (| globals, "header" |), "mix_digest" |) + |); + M.get_name (| globals, "InvalidBlock" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + Compare.lt_e (| + M.call (| + M.get_field (| M.get_name (| globals, "Uint" |), "from_be_bytes" |), + make_list [ + M.get_name (| globals, "result" |) + ], + make_dict [] + |), + BinOp.floor_div (| + M.get_name (| globals, "U256_CEIL_VALUE" |), + M.get_field (| M.get_name (| globals, "header" |), "difficulty" |) + |) + |); + M.get_name (| globals, "InvalidBlock" |) + ], + make_dict [] + |) in + M.pure Constant.None_)). + +Definition check_transaction : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "tx"; "gas_available"; "chain_id" ] |) in + let _ := Constant.str " + Check if the transaction is includable in the block. + + Parameters + ---------- + tx : + The transaction. + gas_available : + The gas remaining in the block. + chain_id : + The ID of the current chain. + + Returns + ------- + sender_address : + The sender of the transaction. + + Raises + ------ + InvalidBlock : + If the transaction is not includable. + " in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + Compare.lt_e (| + M.get_field (| M.get_name (| globals, "tx" |), "gas" |), + M.get_name (| globals, "gas_available" |) + |); + M.get_name (| globals, "InvalidBlock" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "sender_address" , + M.call (| + M.get_name (| globals, "recover_sender" |), + make_list [ + M.get_name (| globals, "chain_id" |); + M.get_name (| globals, "tx" |) + ], + make_dict [] + |) + |) in + let _ := M.return_ (| + M.get_name (| globals, "sender_address" |) + |) in + M.pure Constant.None_)). + +Definition make_receipt : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "tx"; "error"; "cumulative_gas_used"; "logs" ] |) in + let _ := Constant.str " + Make the receipt for a transaction that was executed. + + Parameters + ---------- + tx : + The executed transaction. + error : + Error in the top level frame of the transaction, if any. + cumulative_gas_used : + The total gas used so far in the block after the transaction was + executed. + logs : + The logs produced by the transaction. + + Returns + ------- + receipt : + The receipt for the transaction. + " in + let _ := M.assign_local (| + "receipt" , + M.call (| + M.get_name (| globals, "Receipt" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.return_ (| + M.get_name (| globals, "receipt" |) + |) in + M.pure Constant.None_)). + +Definition ApplyBodyOutput : Value.t := + builtins.make_klass + [] + [ + + ] + [ + + ]. + +Definition apply_body : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "state"; "block_hashes"; "coinbase"; "block_number"; "block_gas_limit"; "block_time"; "block_difficulty"; "transactions"; "ommers"; "chain_id" ] |) in + let _ := Constant.str " + Executes a block. + + Many of the contents of a block are stored in data structures called + tries. There is a transactions trie which is similar to a ledger of the + transactions stored in the current block. There is also a receipts trie + which stores the results of executing a transaction, like the post state + and gas used. This function creates and executes the block that is to be + added to the chain. + + Parameters + ---------- + state : + Current account state. + block_hashes : + List of hashes of the previous 256 blocks in the order of + increasing block number. + coinbase : + Address of account which receives block reward and transaction fees. + block_number : + Position of the block within the chain. + block_gas_limit : + Initial amount of gas available for execution in this block. + block_time : + Time the block was produced, measured in seconds since the epoch. + block_difficulty : + Difficulty of the block. + transactions : + Transactions included in the block. + ommers : + Headers of ancestor blocks which are not direct parents (formerly + uncles.) + chain_id : + ID of the executing chain. + + Returns + ------- + apply_body_output : `ApplyBodyOutput` + Output of applying the block body to the state. + " in + let _ := M.assign_local (| + "gas_available" , + M.get_name (| globals, "block_gas_limit" |) + |) in +(* At stmt: unsupported node type: AnnAssign *) +(* At stmt: unsupported node type: AnnAssign *) +(* At stmt: unsupported node type: AnnAssign *) + let _ := + M.for_ (| + make_tuple [ M.get_name (| globals, "i" |); M.get_name (| globals, "tx" |) ], + M.call (| + M.get_name (| globals, "enumerate" |), + make_list [ + M.get_name (| globals, "transactions" |) + ], + make_dict [] + |), + ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, "trie_set" |), + make_list [ + M.get_name (| globals, "transactions_trie" |); + M.call (| + M.get_field (| M.get_name (| globals, "rlp" |), "encode" |), + make_list [ + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.get_name (| globals, "i" |) + ], + make_dict [] + |) + ], + make_dict [] + |); + M.get_name (| globals, "tx" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "sender_address" , + M.call (| + M.get_name (| globals, "check_transaction" |), + make_list [ + M.get_name (| globals, "tx" |); + M.get_name (| globals, "gas_available" |); + M.get_name (| globals, "chain_id" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "env" , + M.call (| + M.get_field (| M.get_name (| globals, "vm" |), "Environment" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.assign (| + make_tuple [ M.get_name (| globals, "gas_used" |); M.get_name (| globals, "logs" |); M.get_name (| globals, "error" |) ], + M.call (| + M.get_name (| globals, "process_transaction" |), + make_list [ + M.get_name (| globals, "env" |); + M.get_name (| globals, "tx" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_op_local (| + BinOp.sub, + "gas_available", + M.get_name (| globals, "gas_used" |) + |) in + let _ := M.assign_local (| + "receipt" , + M.call (| + M.get_name (| globals, "make_receipt" |), + make_list [ + M.get_name (| globals, "tx" |); + M.get_name (| globals, "error" |); + BinOp.sub (| + M.get_name (| globals, "block_gas_limit" |), + M.get_name (| globals, "gas_available" |) + |); + M.get_name (| globals, "logs" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "trie_set" |), + make_list [ + M.get_name (| globals, "receipts_trie" |); + M.call (| + M.get_field (| M.get_name (| globals, "rlp" |), "encode" |), + make_list [ + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.get_name (| globals, "i" |) + ], + make_dict [] + |) + ], + make_dict [] + |); + M.get_name (| globals, "receipt" |) + ], + make_dict [] + |) in + let _ := M.assign_op_local (| + BinOp.add, + "block_logs", + M.get_name (| globals, "logs" |) + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := M.call (| + M.get_name (| globals, "pay_rewards" |), + make_list [ + M.get_name (| globals, "state" |); + M.get_name (| globals, "block_number" |); + M.get_name (| globals, "coinbase" |); + M.get_name (| globals, "ommers" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "block_gas_used" , + BinOp.sub (| + M.get_name (| globals, "block_gas_limit" |), + M.get_name (| globals, "gas_available" |) + |) + |) in + let _ := M.assign_local (| + "block_logs_bloom" , + M.call (| + M.get_name (| globals, "logs_bloom" |), + make_list [ + M.get_name (| globals, "block_logs" |) + ], + make_dict [] + |) + |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, "ApplyBodyOutput" |), + make_list [ + M.get_name (| globals, "block_gas_used" |); + M.call (| + M.get_name (| globals, "root" |), + make_list [ + M.get_name (| globals, "transactions_trie" |) + ], + make_dict [] + |); + M.call (| + M.get_name (| globals, "root" |), + make_list [ + M.get_name (| globals, "receipts_trie" |) + ], + make_dict [] + |); + M.get_name (| globals, "block_logs_bloom" |); + M.call (| + M.get_name (| globals, "state_root" |), + make_list [ + M.get_name (| globals, "state" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Definition validate_ommers : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "ommers"; "block_header"; "chain" ] |) in + let _ := Constant.str " + Validates the ommers mentioned in the block. + + An ommer block is a block that wasn't canonically added to the + blockchain because it wasn't validated as fast as the canonical block + but was mined at the same time. + + To be considered valid, the ommers must adhere to the rules defined in + the Ethereum protocol. The maximum amount of ommers is 2 per block and + there cannot be duplicate ommers in a block. Many of the other ommer + constraints are listed in the in-line comments of this function. + + Parameters + ---------- + ommers : + List of ommers mentioned in the current block. + block_header: + The header of current block. + chain : + History and current state. + " in + let _ := M.assign_local (| + "block_hash" , + M.call (| + M.get_field (| M.get_name (| globals, "rlp" |), "rlp_hash" |), + make_list [ + M.get_name (| globals, "block_header" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + Compare.eq (| + M.call (| + M.get_field (| M.get_name (| globals, "rlp" |), "rlp_hash" |), + make_list [ + M.get_name (| globals, "ommers" |) + ], + make_dict [] + |), + M.get_field (| M.get_name (| globals, "block_header" |), "ommers_hash" |) + |); + M.get_name (| globals, "InvalidBlock" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_name (| globals, "ommers" |) + ], + make_dict [] + |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + Constant.None_ + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + M.for_ (| + M.get_name (| globals, "ommer" |), + M.get_name (| globals, "ommers" |), + ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + BoolOp.and (| + Compare.lt_e (| + Constant.int 1, + M.get_field (| M.get_name (| globals, "ommer" |), "number" |) + |), + ltac:(M.monadic ( + Compare.lt (| + M.get_field (| M.get_name (| globals, "ommer" |), "number" |), + M.get_field (| M.get_name (| globals, "block_header" |), "number" |) + |) + )) + |); + M.get_name (| globals, "InvalidBlock" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "ommer_parent_header" , + M.get_field (| M.get_subscript (| + M.get_field (| M.get_name (| globals, "chain" |), "blocks" |), + BinOp.sub (| + UnOp.sub (| BinOp.sub (| + M.get_field (| M.get_name (| globals, "block_header" |), "number" |), + M.get_field (| M.get_name (| globals, "ommer" |), "number" |) + |) |), + Constant.int 1 + |) + |), "header" |) + |) in + let _ := M.call (| + M.get_name (| globals, "validate_header" |), + make_list [ + M.get_name (| globals, "ommer" |); + M.get_name (| globals, "ommer_parent_header" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + Compare.lt_e (| + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_name (| globals, "ommers" |) + ], + make_dict [] + |), + Constant.int 2 + |); + M.get_name (| globals, "InvalidBlock" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "ommers_hashes" , + Constant.str "(* At expr: unsupported node type: ListComp *)" + |) in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + Compare.eq (| + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_name (| globals, "ommers_hashes" |) + ], + make_dict [] + |), + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.call (| + M.get_name (| globals, "set" |), + make_list [ + M.get_name (| globals, "ommers_hashes" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |); + M.get_name (| globals, "InvalidBlock" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "recent_canonical_blocks" , + M.slice (| + M.get_field (| M.get_name (| globals, "chain" |), "blocks" |), + UnOp.sub (| BinOp.add (| + M.get_name (| globals, "MAX_OMMER_DEPTH" |), + Constant.int 1 + |) |), + Constant.None_, + Constant.None_ + |) + |) in + let _ := M.assign_local (| + "recent_canonical_block_hashes" , + Constant.str "(* At expr: unsupported node type: SetComp *)" + |) in +(* At stmt: unsupported node type: AnnAssign *) + let _ := + M.for_ (| + M.get_name (| globals, "block" |), + M.get_name (| globals, "recent_canonical_blocks" |), + ltac:(M.monadic ( + let _ := M.assign_local (| + "recent_ommers_hashes" , + M.call (| + M.get_field (| M.get_name (| globals, "recent_ommers_hashes" |), "union" |), + make_list [ + Constant.str "(* At expr: unsupported node type: SetComp *)" + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := + M.for_ (| + make_tuple [ M.get_name (| globals, "ommer_index" |); M.get_name (| globals, "ommer" |) ], + M.call (| + M.get_name (| globals, "enumerate" |), + make_list [ + M.get_name (| globals, "ommers" |) + ], + make_dict [] + |), + ltac:(M.monadic ( + let _ := M.assign_local (| + "ommer_hash" , + M.get_subscript (| + M.get_name (| globals, "ommers_hashes" |), + M.get_name (| globals, "ommer_index" |) + |) + |) in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + Compare.not_eq (| + M.get_name (| globals, "ommer_hash" |), + M.get_name (| globals, "block_hash" |) + |); + M.get_name (| globals, "InvalidBlock" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + Compare.not_in (| + M.get_name (| globals, "ommer_hash" |), + M.get_name (| globals, "recent_canonical_block_hashes" |) + |); + M.get_name (| globals, "InvalidBlock" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + Compare.not_in (| + M.get_name (| globals, "ommer_hash" |), + M.get_name (| globals, "recent_ommers_hashes" |) + |); + M.get_name (| globals, "InvalidBlock" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "ommer_age" , + BinOp.sub (| + M.get_field (| M.get_name (| globals, "block_header" |), "number" |), + M.get_field (| M.get_name (| globals, "ommer" |), "number" |) + |) + |) in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + BoolOp.and (| + Compare.lt_e (| + Constant.int 1, + M.get_name (| globals, "ommer_age" |) + |), + ltac:(M.monadic ( + Compare.lt_e (| + M.get_name (| globals, "ommer_age" |), + M.get_name (| globals, "MAX_OMMER_DEPTH" |) + |) + )) + |); + M.get_name (| globals, "InvalidBlock" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + Compare.in_ (| + M.get_field (| M.get_name (| globals, "ommer" |), "parent_hash" |), + M.get_name (| globals, "recent_canonical_block_hashes" |) + |); + M.get_name (| globals, "InvalidBlock" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + Compare.not_eq (| + M.get_field (| M.get_name (| globals, "ommer" |), "parent_hash" |), + M.get_field (| M.get_name (| globals, "block_header" |), "parent_hash" |) + |); + M.get_name (| globals, "InvalidBlock" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + M.pure Constant.None_)). + +Definition pay_rewards : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "state"; "block_number"; "coinbase"; "ommers" ] |) in + let _ := Constant.str " + Pay rewards to the block miner as well as the ommers miners. + + The miner of the canonical block is rewarded with the predetermined + block reward, ``BLOCK_REWARD``, plus a variable award based off of the + number of ommer blocks that were mined around the same time, and included + in the canonical block's header. An ommer block is a block that wasn't + added to the canonical blockchain because it wasn't validated as fast as + the accepted block but was mined at the same time. Although not all blocks + that are mined are added to the canonical chain, miners are still paid a + reward for their efforts. This reward is called an ommer reward and is + calculated based on the number associated with the ommer block that they + mined. + + Parameters + ---------- + state : + Current account state. + block_number : + Position of the block within the chain. + coinbase : + Address of account which receives block reward and transaction fees. + ommers : + List of ommers mentioned in the current block. + " in + let _ := M.assign_local (| + "miner_reward" , + BinOp.add (| + M.get_name (| globals, "BLOCK_REWARD" |), + BinOp.mult (| + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_name (| globals, "ommers" |) + ], + make_dict [] + |), + BinOp.floor_div (| + M.get_name (| globals, "BLOCK_REWARD" |), + Constant.int 32 + |) + |) + |) + |) in + let _ := M.call (| + M.get_name (| globals, "create_ether" |), + make_list [ + M.get_name (| globals, "state" |); + M.get_name (| globals, "coinbase" |); + M.get_name (| globals, "miner_reward" |) + ], + make_dict [] + |) in + let _ := + M.for_ (| + M.get_name (| globals, "ommer" |), + M.get_name (| globals, "ommers" |), + ltac:(M.monadic ( + let _ := M.assign_local (| + "ommer_age" , + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + BinOp.sub (| + M.get_name (| globals, "block_number" |), + M.get_field (| M.get_name (| globals, "ommer" |), "number" |) + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "ommer_miner_reward" , + BinOp.floor_div (| + BinOp.mult (| + BinOp.sub (| + Constant.int 8, + M.get_name (| globals, "ommer_age" |) + |), + M.get_name (| globals, "BLOCK_REWARD" |) + |), + Constant.int 8 + |) + |) in + let _ := M.call (| + M.get_name (| globals, "create_ether" |), + make_list [ + M.get_name (| globals, "state" |); + M.get_field (| M.get_name (| globals, "ommer" |), "coinbase" |); + M.get_name (| globals, "ommer_miner_reward" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + M.pure Constant.None_)). + +Definition process_transaction : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "env"; "tx" ] |) in + let _ := Constant.str " + Execute a transaction against the provided environment. + + This function processes the actions needed to execute a transaction. + It decrements the sender's account after calculating the gas fee and + refunds them the proper amount after execution. Calling contracts, + deploying code, and incrementing nonces are all examples of actions that + happen within this function or from a call made within this function. + + Accounts that are marked for deletion are processed and destroyed after + execution. + + Parameters + ---------- + env : + Environment for the Ethereum Virtual Machine. + tx : + Transaction to execute. + + Returns + ------- + gas_left : `ethereum.base_types.U256` + Remaining gas after execution. + logs : `Tuple[ethereum.blocks.Log, ...]` + Logs generated during execution. + " in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + M.call (| + M.get_name (| globals, "validate_transaction" |), + make_list [ + M.get_name (| globals, "tx" |) + ], + make_dict [] + |); + M.get_name (| globals, "InvalidBlock" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "sender" , + M.get_field (| M.get_name (| globals, "env" |), "origin" |) + |) in + let _ := M.assign_local (| + "sender_account" , + M.call (| + M.get_name (| globals, "get_account" |), + make_list [ + M.get_field (| M.get_name (| globals, "env" |), "state" |); + M.get_name (| globals, "sender" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "gas_fee" , + BinOp.mult (| + M.get_field (| M.get_name (| globals, "tx" |), "gas" |), + M.get_field (| M.get_name (| globals, "tx" |), "gas_price" |) + |) + |) in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + Compare.eq (| + M.get_field (| M.get_name (| globals, "sender_account" |), "nonce" |), + M.get_field (| M.get_name (| globals, "tx" |), "nonce" |) + |); + M.get_name (| globals, "InvalidBlock" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + Compare.gt_e (| + M.get_field (| M.get_name (| globals, "sender_account" |), "balance" |), + BinOp.add (| + M.get_name (| globals, "gas_fee" |), + M.get_field (| M.get_name (| globals, "tx" |), "value" |) + |) + |); + M.get_name (| globals, "InvalidBlock" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + Compare.eq (| + M.get_field (| M.get_name (| globals, "sender_account" |), "code" |), + M.call (| + M.get_name (| globals, "bytearray" |), + make_list [], + make_dict [] + |) + |); + M.get_name (| globals, "InvalidBlock" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "gas" , + BinOp.sub (| + M.get_field (| M.get_name (| globals, "tx" |), "gas" |), + M.call (| + M.get_name (| globals, "calculate_intrinsic_cost" |), + make_list [ + M.get_name (| globals, "tx" |) + ], + make_dict [] + |) + |) + |) in + let _ := M.call (| + M.get_name (| globals, "increment_nonce" |), + make_list [ + M.get_field (| M.get_name (| globals, "env" |), "state" |); + M.get_name (| globals, "sender" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "sender_balance_after_gas_fee" , + BinOp.sub (| + M.get_field (| M.get_name (| globals, "sender_account" |), "balance" |), + M.get_name (| globals, "gas_fee" |) + |) + |) in + let _ := M.call (| + M.get_name (| globals, "set_account_balance" |), + make_list [ + M.get_field (| M.get_name (| globals, "env" |), "state" |); + M.get_name (| globals, "sender" |); + M.get_name (| globals, "sender_balance_after_gas_fee" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "message" , + M.call (| + M.get_name (| globals, "prepare_message" |), + make_list [ + M.get_name (| globals, "sender" |); + M.get_field (| M.get_name (| globals, "tx" |), "to" |); + M.get_field (| M.get_name (| globals, "tx" |), "value" |); + M.get_field (| M.get_name (| globals, "tx" |), "data" |); + M.get_name (| globals, "gas" |); + M.get_name (| globals, "env" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "output" , + M.call (| + M.get_name (| globals, "process_message_call" |), + make_list [ + M.get_name (| globals, "message" |); + M.get_name (| globals, "env" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "gas_used" , + BinOp.sub (| + M.get_field (| M.get_name (| globals, "tx" |), "gas" |), + M.get_field (| M.get_name (| globals, "output" |), "gas_left" |) + |) + |) in + let _ := M.assign_local (| + "gas_refund" , + M.call (| + M.get_name (| globals, "min" |), + make_list [ + BinOp.floor_div (| + M.get_name (| globals, "gas_used" |), + Constant.int 2 + |); + M.get_field (| M.get_name (| globals, "output" |), "refund_counter" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "gas_refund_amount" , + BinOp.mult (| + BinOp.add (| + M.get_field (| M.get_name (| globals, "output" |), "gas_left" |), + M.get_name (| globals, "gas_refund" |) + |), + M.get_field (| M.get_name (| globals, "tx" |), "gas_price" |) + |) + |) in + let _ := M.assign_local (| + "transaction_fee" , + BinOp.mult (| + BinOp.sub (| + BinOp.sub (| + M.get_field (| M.get_name (| globals, "tx" |), "gas" |), + M.get_field (| M.get_name (| globals, "output" |), "gas_left" |) + |), + M.get_name (| globals, "gas_refund" |) + |), + M.get_field (| M.get_name (| globals, "tx" |), "gas_price" |) + |) + |) in + let _ := M.assign_local (| + "total_gas_used" , + BinOp.sub (| + M.get_name (| globals, "gas_used" |), + M.get_name (| globals, "gas_refund" |) + |) + |) in + let _ := M.assign_local (| + "sender_balance_after_refund" , + BinOp.add (| + M.get_field (| M.call (| + M.get_name (| globals, "get_account" |), + make_list [ + M.get_field (| M.get_name (| globals, "env" |), "state" |); + M.get_name (| globals, "sender" |) + ], + make_dict [] + |), "balance" |), + M.get_name (| globals, "gas_refund_amount" |) + |) + |) in + let _ := M.call (| + M.get_name (| globals, "set_account_balance" |), + make_list [ + M.get_field (| M.get_name (| globals, "env" |), "state" |); + M.get_name (| globals, "sender" |); + M.get_name (| globals, "sender_balance_after_refund" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "coinbase_balance_after_mining_fee" , + BinOp.add (| + M.get_field (| M.call (| + M.get_name (| globals, "get_account" |), + make_list [ + M.get_field (| M.get_name (| globals, "env" |), "state" |); + M.get_field (| M.get_name (| globals, "env" |), "coinbase" |) + ], + make_dict [] + |), "balance" |), + M.get_name (| globals, "transaction_fee" |) + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.not_eq (| + M.get_name (| globals, "coinbase_balance_after_mining_fee" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, "set_account_balance" |), + make_list [ + M.get_field (| M.get_name (| globals, "env" |), "state" |); + M.get_field (| M.get_name (| globals, "env" |), "coinbase" |); + M.get_name (| globals, "coinbase_balance_after_mining_fee" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, "account_exists_and_is_empty" |), + make_list [ + M.get_field (| M.get_name (| globals, "env" |), "state" |); + M.get_field (| M.get_name (| globals, "env" |), "coinbase" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, "destroy_account" |), + make_list [ + M.get_field (| M.get_name (| globals, "env" |), "state" |); + M.get_field (| M.get_name (| globals, "env" |), "coinbase" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )) |) in + let _ := + M.for_ (| + M.get_name (| globals, "address" |), + M.get_field (| M.get_name (| globals, "output" |), "accounts_to_delete" |), + ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, "destroy_account" |), + make_list [ + M.get_field (| M.get_name (| globals, "env" |), "state" |); + M.get_name (| globals, "address" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := + M.for_ (| + M.get_name (| globals, "address" |), + M.get_field (| M.get_name (| globals, "output" |), "touched_accounts" |), + ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, "account_exists_and_is_empty" |), + make_list [ + M.get_field (| M.get_name (| globals, "env" |), "state" |); + M.get_name (| globals, "address" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, "destroy_account" |), + make_list [ + M.get_field (| M.get_name (| globals, "env" |), "state" |); + M.get_name (| globals, "address" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := M.return_ (| + make_tuple [ M.get_name (| globals, "total_gas_used" |); M.get_field (| M.get_name (| globals, "output" |), "logs" |); M.get_field (| M.get_name (| globals, "output" |), "error" |) ] + |) in + M.pure Constant.None_)). + +Definition validate_transaction : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "tx" ] |) in + let _ := Constant.str " + Verifies a transaction. + + The gas in a transaction gets used to pay for the intrinsic cost of + operations, therefore if there is insufficient gas then it would not + be possible to execute a transaction and it will be declared invalid. + + Additionally, the nonce of a transaction must not equal or exceed the + limit defined in `EIP-2681 `_. + In practice, defining the limit as ``2**64-1`` has no impact because + sending ``2**64-1`` transactions is improbable. It's not strictly + impossible though, ``2**64-1`` transactions is the entire capacity of the + Ethereum blockchain at 2022 gas limits for a little over 22 years. + + Parameters + ---------- + tx : + Transaction to validate. + + Returns + ------- + verified : `bool` + True if the transaction can be executed, or False otherwise. + " in + let _ := M.return_ (| + BoolOp.and (| + Compare.lt_e (| + M.call (| + M.get_name (| globals, "calculate_intrinsic_cost" |), + make_list [ + M.get_name (| globals, "tx" |) + ], + make_dict [] + |), + M.get_field (| M.get_name (| globals, "tx" |), "gas" |) + |), + ltac:(M.monadic ( + Compare.lt (| + M.get_field (| M.get_name (| globals, "tx" |), "nonce" |), + BinOp.sub (| + BinOp.pow (| + Constant.int 2, + Constant.int 64 + |), + Constant.int 1 + |) + |) + )) + |) + |) in + M.pure Constant.None_)). + +Definition calculate_intrinsic_cost : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "tx" ] |) in + let _ := Constant.str " + Calculates the gas that is charged before execution is started. + + The intrinsic cost of the transaction is charged before execution has + begun. Functions/operations in the EVM cost money to execute so this + intrinsic cost is for the operations that need to be paid for as part of + the transaction. Data transfer, for example, is part of this intrinsic + cost. It costs ether to send data over the wire and that ether is + accounted for in the intrinsic cost calculated in this function. This + intrinsic cost must be calculated and paid for before execution in order + for all operations to be implemented. + + Parameters + ---------- + tx : + Transaction to compute the intrinsic cost of. + + Returns + ------- + verified : `ethereum.base_types.Uint` + The intrinsic cost of the transaction. + " in + let _ := M.assign_local (| + "data_cost" , + Constant.int 0 + |) in + let _ := + M.for_ (| + M.get_name (| globals, "byte" |), + M.get_field (| M.get_name (| globals, "tx" |), "data" |), + ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, "byte" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_op_local (| + BinOp.add, + "data_cost", + M.get_name (| globals, "TX_DATA_COST_PER_ZERO" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_op_local (| + BinOp.add, + "data_cost", + M.get_name (| globals, "TX_DATA_COST_PER_NON_ZERO" |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_field (| M.get_name (| globals, "tx" |), "to" |), + M.call (| + M.get_name (| globals, "Bytes0" |), + make_list [ + Constant.bytes "" + ], + make_dict [] + |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "create_cost" , + M.get_name (| globals, "TX_CREATE_COST" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "create_cost" , + Constant.int 0 + |) in + M.pure Constant.None_ + )) |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + BinOp.add (| + BinOp.add (| + M.get_name (| globals, "TX_BASE_COST" |), + M.get_name (| globals, "data_cost" |) + |), + M.get_name (| globals, "create_cost" |) + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Definition recover_sender : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "chain_id"; "tx" ] |) in + let _ := Constant.str " + Extracts the sender address from a transaction. + + The v, r, and s values are the three parts that make up the signature + of a transaction. In order to recover the sender of a transaction the two + components needed are the signature (``v``, ``r``, and ``s``) and the + signing hash of the transaction. The sender's public key can be obtained + with these two values and therefore the sender address can be retrieved. + + Parameters + ---------- + tx : + Transaction of interest. + chain_id : + ID of the executing chain. + + Returns + ------- + sender : `ethereum.fork_types.Address` + The address of the account that signed the transaction. + " in + let _ := M.assign (| + make_tuple [ M.get_name (| globals, "v" |); M.get_name (| globals, "r" |); M.get_name (| globals, "s" |) ], + make_tuple [ M.get_field (| M.get_name (| globals, "tx" |), "v" |); M.get_field (| M.get_name (| globals, "tx" |), "r" |); M.get_field (| M.get_name (| globals, "tx" |), "s" |) ] + |) in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + BoolOp.and (| + Compare.lt (| + Constant.int 0, + M.get_name (| globals, "r" |) + |), + ltac:(M.monadic ( + Compare.lt (| + M.get_name (| globals, "r" |), + M.get_name (| globals, "SECP256K1N" |) + |) + )) + |); + M.get_name (| globals, "InvalidBlock" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + BoolOp.and (| + Compare.lt (| + Constant.int 0, + M.get_name (| globals, "s" |) + |), + ltac:(M.monadic ( + Compare.lt_e (| + M.get_name (| globals, "s" |), + BinOp.floor_div (| + M.get_name (| globals, "SECP256K1N" |), + Constant.int 2 + |) + |) + )) + |); + M.get_name (| globals, "InvalidBlock" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + BoolOp.or (| + Compare.eq (| + M.get_name (| globals, "v" |), + Constant.int 27 + |), + ltac:(M.monadic ( + Compare.eq (| + M.get_name (| globals, "v" |), + Constant.int 28 + |) + )) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "public_key" , + M.call (| + M.get_name (| globals, "secp256k1_recover" |), + make_list [ + M.get_name (| globals, "r" |); + M.get_name (| globals, "s" |); + BinOp.sub (| + M.get_name (| globals, "v" |), + Constant.int 27 + |); + M.call (| + M.get_name (| globals, "signing_hash_pre155" |), + make_list [ + M.get_name (| globals, "tx" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + BoolOp.or (| + Compare.eq (| + M.get_name (| globals, "v" |), + BinOp.add (| + Constant.int 35, + BinOp.mult (| + M.get_name (| globals, "chain_id" |), + Constant.int 2 + |) + |) + |), + ltac:(M.monadic ( + Compare.eq (| + M.get_name (| globals, "v" |), + BinOp.add (| + Constant.int 36, + BinOp.mult (| + M.get_name (| globals, "chain_id" |), + Constant.int 2 + |) + |) + |) + )) + |); + M.get_name (| globals, "InvalidBlock" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "public_key" , + M.call (| + M.get_name (| globals, "secp256k1_recover" |), + make_list [ + M.get_name (| globals, "r" |); + M.get_name (| globals, "s" |); + BinOp.sub (| + BinOp.sub (| + M.get_name (| globals, "v" |), + Constant.int 35 + |), + BinOp.mult (| + M.get_name (| globals, "chain_id" |), + Constant.int 2 + |) + |); + M.call (| + M.get_name (| globals, "signing_hash_155" |), + make_list [ + M.get_name (| globals, "tx" |); + M.get_name (| globals, "chain_id" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + )) |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, "Address" |), + make_list [ + M.slice (| + M.call (| + M.get_name (| globals, "keccak256" |), + make_list [ + M.get_name (| globals, "public_key" |) + ], + make_dict [] + |), + Constant.int 12, + Constant.int 32, + Constant.None_ + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Definition signing_hash_pre155 : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "tx" ] |) in + let _ := Constant.str " + Compute the hash of a transaction used in a legacy (pre EIP 155) signature. + + Parameters + ---------- + tx : + Transaction of interest. + + Returns + ------- + hash : `ethereum.crypto.hash.Hash32` + Hash of the transaction. + " in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, "keccak256" |), + make_list [ + M.call (| + M.get_field (| M.get_name (| globals, "rlp" |), "encode" |), + make_list [ + make_tuple [ M.get_field (| M.get_name (| globals, "tx" |), "nonce" |); M.get_field (| M.get_name (| globals, "tx" |), "gas_price" |); M.get_field (| M.get_name (| globals, "tx" |), "gas" |); M.get_field (| M.get_name (| globals, "tx" |), "to" |); M.get_field (| M.get_name (| globals, "tx" |), "value" |); M.get_field (| M.get_name (| globals, "tx" |), "data" |) ] + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Definition signing_hash_155 : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "tx"; "chain_id" ] |) in + let _ := Constant.str " + Compute the hash of a transaction used in a EIP 155 signature. + + Parameters + ---------- + tx : + Transaction of interest. + chain_id : + The id of the current chain. + + Returns + ------- + hash : `ethereum.crypto.hash.Hash32` + Hash of the transaction. + " in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, "keccak256" |), + make_list [ + M.call (| + M.get_field (| M.get_name (| globals, "rlp" |), "encode" |), + make_list [ + make_tuple [ M.get_field (| M.get_name (| globals, "tx" |), "nonce" |); M.get_field (| M.get_name (| globals, "tx" |), "gas_price" |); M.get_field (| M.get_name (| globals, "tx" |), "gas" |); M.get_field (| M.get_name (| globals, "tx" |), "to" |); M.get_field (| M.get_name (| globals, "tx" |), "value" |); M.get_field (| M.get_name (| globals, "tx" |), "data" |); M.get_name (| globals, "chain_id" |); M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |); M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) ] + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Definition compute_header_hash : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "header" ] |) in + let _ := Constant.str " + Computes the hash of a block header. + + The header hash of a block is the canonical hash that is used to refer + to a specific block and completely distinguishes a block from another. + + ``keccak256`` is a function that produces a 256 bit hash of any input. + It also takes in any number of bytes as an input and produces a single + hash for them. A hash is a completely unique output for a single input. + So an input corresponds to one unique hash that can be used to identify + the input exactly. + + Prior to using the ``keccak256`` hash function, the header must be + encoded using the Recursive-Length Prefix. See :ref:`rlp`. + RLP encoding the header converts it into a space-efficient format that + allows for easy transfer of data between nodes. The purpose of RLP is to + encode arbitrarily nested arrays of binary data, and RLP is the primary + encoding method used to serialize objects in Ethereum's execution layer. + The only purpose of RLP is to encode structure; encoding specific data + types (e.g. strings, floats) is left up to higher-order protocols. + + Parameters + ---------- + header : + Header of interest. + + Returns + ------- + hash : `ethereum.crypto.hash.Hash32` + Hash of the header. + " in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, "keccak256" |), + make_list [ + M.call (| + M.get_field (| M.get_name (| globals, "rlp" |), "encode" |), + make_list [ + M.get_name (| globals, "header" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Definition check_gas_limit : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "gas_limit"; "parent_gas_limit" ] |) in + let _ := Constant.str " + Validates the gas limit for a block. + + The bounds of the gas limit, ``max_adjustment_delta``, is set as the + quotient of the parent block's gas limit and the + ``GAS_LIMIT_ADJUSTMENT_FACTOR``. Therefore, if the gas limit that is + passed through as a parameter is greater than or equal to the *sum* of + the parent's gas and the adjustment delta then the limit for gas is too + high and fails this function's check. Similarly, if the limit is less + than or equal to the *difference* of the parent's gas and the adjustment + delta *or* the predefined ``GAS_LIMIT_MINIMUM`` then this function's + check fails because the gas limit doesn't allow for a sufficient or + reasonable amount of gas to be used on a block. + + Parameters + ---------- + gas_limit : + Gas limit to validate. + + parent_gas_limit : + Gas limit of the parent block. + + Returns + ------- + check : `bool` + True if gas limit constraints are satisfied, False otherwise. + " in + let _ := M.assign_local (| + "max_adjustment_delta" , + BinOp.floor_div (| + M.get_name (| globals, "parent_gas_limit" |), + M.get_name (| globals, "GAS_LIMIT_ADJUSTMENT_FACTOR" |) + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.gt_e (| + M.get_name (| globals, "gas_limit" |), + BinOp.add (| + M.get_name (| globals, "parent_gas_limit" |), + M.get_name (| globals, "max_adjustment_delta" |) + |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + Constant.bool false + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + Compare.lt_e (| + M.get_name (| globals, "gas_limit" |), + BinOp.sub (| + M.get_name (| globals, "parent_gas_limit" |), + M.get_name (| globals, "max_adjustment_delta" |) + |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + Constant.bool false + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + Compare.lt (| + M.get_name (| globals, "gas_limit" |), + M.get_name (| globals, "GAS_LIMIT_MINIMUM" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + Constant.bool false + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.return_ (| + Constant.bool true + |) in + M.pure Constant.None_)). + +Definition calculate_block_difficulty : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "block_number"; "block_timestamp"; "parent_timestamp"; "parent_difficulty"; "parent_has_ommers" ] |) in + let _ := Constant.str " + Computes difficulty of a block using its header and parent header. + + The difficulty is determined by the time the block was created after its + parent. The ``offset`` is calculated using the parent block's difficulty, + ``parent_difficulty``, and the timestamp between blocks. This offset is + then added to the parent difficulty and is stored as the ``difficulty`` + variable. If the time between the block and its parent is too short, the + offset will result in a positive number thus making the sum of + ``parent_difficulty`` and ``offset`` to be a greater value in order to + avoid mass forking. But, if the time is long enough, then the offset + results in a negative value making the block less difficult than + its parent. + + The base standard for a block's difficulty is the predefined value + set for the genesis block since it has no parent. So, a block + can't be less difficult than the genesis block, therefore each block's + difficulty is set to the maximum value between the calculated + difficulty and the ``GENESIS_DIFFICULTY``. + + Parameters + ---------- + block_number : + Block number of the block. + block_timestamp : + Timestamp of the block. + parent_timestamp : + Timestamp of the parent block. + parent_difficulty : + difficulty of the parent block. + parent_has_ommers: + does the parent have ommers. + + Returns + ------- + difficulty : `ethereum.base_types.Uint` + Computed difficulty for a block. + " in + let _ := M.assign_local (| + "offset" , + BinOp.mult (| + BinOp.floor_div (| + M.call (| + M.get_name (| globals, "int" |), + make_list [ + M.get_name (| globals, "parent_difficulty" |) + ], + make_dict [] + |), + Constant.int 2048 + |), + M.call (| + M.get_name (| globals, "max" |), + make_list [ + BinOp.sub (| + (* if *) + M.if_then_else (| + M.get_name (| globals, "parent_has_ommers" |), + (* then *) + ltac:(M.monadic ( +Constant.int 2 + (* else *) + )), ltac:(M.monadic ( +Constant.int 1 + )) |), + BinOp.floor_div (| + M.call (| + M.get_name (| globals, "int" |), + make_list [ + BinOp.sub (| + M.get_name (| globals, "block_timestamp" |), + M.get_name (| globals, "parent_timestamp" |) + |) + ], + make_dict [] + |), + Constant.int 9 + |) + |); + UnOp.sub (| Constant.int 99 |) + ], + make_dict [] + |) + |) + |) in + let _ := M.assign_local (| + "difficulty" , + BinOp.add (| + M.call (| + M.get_name (| globals, "int" |), + make_list [ + M.get_name (| globals, "parent_difficulty" |) + ], + make_dict [] + |), + M.get_name (| globals, "offset" |) + |) + |) in + let _ := M.assign_local (| + "num_bomb_periods" , + BinOp.sub (| + BinOp.floor_div (| + BinOp.sub (| + M.call (| + M.get_name (| globals, "int" |), + make_list [ + M.get_name (| globals, "block_number" |) + ], + make_dict [] + |), + M.get_name (| globals, "BOMB_DELAY_BLOCKS" |) + |), + Constant.int 100000 + |), + Constant.int 2 + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.gt_e (| + M.get_name (| globals, "num_bomb_periods" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_op_local (| + BinOp.add, + "difficulty", + BinOp.pow (| + Constant.int 2, + M.get_name (| globals, "num_bomb_periods" |) + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, "max" |), + make_list [ + M.get_name (| globals, "difficulty" |); + M.get_name (| globals, "MINIMUM_DIFFICULTY" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). diff --git a/CoqOfPython/ethereum/muir_glacier/fork_types.v b/CoqOfPython/ethereum/muir_glacier/fork_types.v new file mode 100644 index 0000000..100f313 --- /dev/null +++ b/CoqOfPython/ethereum/muir_glacier/fork_types.v @@ -0,0 +1,98 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.muir_glacier.fork_types". + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Types +^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Types re-used throughout the specification, which are specific to Ethereum. +". + +Axiom dataclasses_imports_dataclass : + IsImported globals "dataclasses" "dataclass". + +Axiom ethereum_imports_rlp : + IsImported globals "ethereum" "rlp". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_Bytes : + IsImported globals "ethereum.base_types" "Bytes". +Axiom ethereum_base_types_imports_Bytes20 : + IsImported globals "ethereum.base_types" "Bytes20". +Axiom ethereum_base_types_imports_Bytes256 : + IsImported globals "ethereum.base_types" "Bytes256". +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". +Axiom ethereum_base_types_imports_slotted_freezable : + IsImported globals "ethereum.base_types" "slotted_freezable". + +Axiom ethereum_crypto_hash_imports_Hash32 : + IsImported globals "ethereum.crypto.hash" "Hash32". +Axiom ethereum_crypto_hash_imports_keccak256 : + IsImported globals "ethereum.crypto.hash" "keccak256". + +Definition Address : Value.t := M.run ltac:(M.monadic ( + M.get_name (| globals, "Bytes20" |) +)). + +Definition Root : Value.t := M.run ltac:(M.monadic ( + M.get_name (| globals, "Hash32" |) +)). + +Definition Bloom : Value.t := M.run ltac:(M.monadic ( + M.get_name (| globals, "Bytes256" |) +)). + +Definition Account : Value.t := + builtins.make_klass + [] + [ + + ] + [ + + ]. + +Definition EMPTY_ACCOUNT : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Account" |), + make_list [], + make_dict [] + |) +)). + +Definition encode_account : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "raw_account_data"; "storage_root" ] |) in + let _ := Constant.str " + Encode `Account` dataclass. + + Storage is not stored in the `Account` dataclass, so `Accounts` cannot be + encoded with providing a storage root. + " in + let _ := M.return_ (| + M.call (| + M.get_field (| M.get_name (| globals, "rlp" |), "encode" |), + make_list [ + make_tuple [ M.get_field (| M.get_name (| globals, "raw_account_data" |), "nonce" |); M.get_field (| M.get_name (| globals, "raw_account_data" |), "balance" |); M.get_name (| globals, "storage_root" |); M.call (| + M.get_name (| globals, "keccak256" |), + make_list [ + M.get_field (| M.get_name (| globals, "raw_account_data" |), "code" |) + ], + make_dict [] + |) ] + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). diff --git a/CoqOfPython/ethereum/muir_glacier/state.v b/CoqOfPython/ethereum/muir_glacier/state.v new file mode 100644 index 0000000..28df1ec --- /dev/null +++ b/CoqOfPython/ethereum/muir_glacier/state.v @@ -0,0 +1,1279 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.muir_glacier.state". + +Definition expr_1 : Value.t := + Constant.str " +State +^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +The state contains all information that is preserved between transactions. + +It consists of a main account trie and storage tries for each contract. + +There is a distinction between an account that does not exist and +`EMPTY_ACCOUNT`. +". + +Axiom dataclasses_imports_dataclass : + IsImported globals "dataclasses" "dataclass". +Axiom dataclasses_imports_field : + IsImported globals "dataclasses" "field". + +Axiom typing_imports_Callable : + IsImported globals "typing" "Callable". +Axiom typing_imports_Dict : + IsImported globals "typing" "Dict". +Axiom typing_imports_List : + IsImported globals "typing" "List". +Axiom typing_imports_Optional : + IsImported globals "typing" "Optional". +Axiom typing_imports_Set : + IsImported globals "typing" "Set". +Axiom typing_imports_Tuple : + IsImported globals "typing" "Tuple". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_Bytes : + IsImported globals "ethereum.base_types" "Bytes". +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". +Axiom ethereum_base_types_imports_modify : + IsImported globals "ethereum.base_types" "modify". + +Axiom ethereum_utils_ensure_imports_ensure : + IsImported globals "ethereum.utils.ensure" "ensure". + +Axiom ethereum_muir_glacier_fork_types_imports_EMPTY_ACCOUNT : + IsImported globals "ethereum.muir_glacier.fork_types" "EMPTY_ACCOUNT". +Axiom ethereum_muir_glacier_fork_types_imports_Account : + IsImported globals "ethereum.muir_glacier.fork_types" "Account". +Axiom ethereum_muir_glacier_fork_types_imports_Address : + IsImported globals "ethereum.muir_glacier.fork_types" "Address". +Axiom ethereum_muir_glacier_fork_types_imports_Root : + IsImported globals "ethereum.muir_glacier.fork_types" "Root". + +Axiom ethereum_muir_glacier_trie_imports_EMPTY_TRIE_ROOT : + IsImported globals "ethereum.muir_glacier.trie" "EMPTY_TRIE_ROOT". +Axiom ethereum_muir_glacier_trie_imports_Trie : + IsImported globals "ethereum.muir_glacier.trie" "Trie". +Axiom ethereum_muir_glacier_trie_imports_copy_trie : + IsImported globals "ethereum.muir_glacier.trie" "copy_trie". +Axiom ethereum_muir_glacier_trie_imports_root : + IsImported globals "ethereum.muir_glacier.trie" "root". +Axiom ethereum_muir_glacier_trie_imports_trie_get : + IsImported globals "ethereum.muir_glacier.trie" "trie_get". +Axiom ethereum_muir_glacier_trie_imports_trie_set : + IsImported globals "ethereum.muir_glacier.trie" "trie_set". + +Definition State : Value.t := + builtins.make_klass + [] + [ + + ] + [ + + ]. + +Definition close_state : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "state" ] |) in + let _ := Constant.str " + Free resources held by the state. Used by optimized implementations to + release file descriptors. + " in + let _ := M.delete (| M.get_field (| M.get_name (| globals, "state" |), "_main_trie" |) |) in + let _ := M.delete (| M.get_field (| M.get_name (| globals, "state" |), "_storage_tries" |) |) in + let _ := M.delete (| M.get_field (| M.get_name (| globals, "state" |), "_snapshots" |) |) in + let _ := M.delete (| M.get_field (| M.get_name (| globals, "state" |), "_created_accounts" |) |) in + M.pure Constant.None_)). + +Definition begin_transaction : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "state" ] |) in + let _ := Constant.str " + Start a state transaction. + + Transactions are entirely implicit and can be nested. It is not possible to + calculate the state root during a transaction. + + Parameters + ---------- + state : State + The state. + " in + let _ := M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, "state" |), "_snapshots" |), "append" |), + make_list [ + make_tuple [ M.call (| + M.get_name (| globals, "copy_trie" |), + make_list [ + M.get_field (| M.get_name (| globals, "state" |), "_main_trie" |) + ], + make_dict [] + |); Constant.str "(* At expr: unsupported node type: DictComp *)" ] + ], + make_dict [] + |) in + M.pure Constant.None_)). + +Definition commit_transaction : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "state" ] |) in + let _ := Constant.str " + Commit a state transaction. + + Parameters + ---------- + state : State + The state. + " in + let _ := M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, "state" |), "_snapshots" |), "pop" |), + make_list [], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + UnOp.not (| M.get_field (| M.get_name (| globals, "state" |), "_snapshots" |) |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, "state" |), "_created_accounts" |), "clear" |), + make_list [], + make_dict [] + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + M.pure Constant.None_)). + +Definition rollback_transaction : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "state" ] |) in + let _ := Constant.str " + Rollback a state transaction, resetting the state to the point when the + corresponding `start_transaction()` call was made. + + Parameters + ---------- + state : State + The state. + " in + let _ := M.assign (| + make_tuple [ M.get_field (| M.get_name (| globals, "state" |), "_main_trie" |); M.get_field (| M.get_name (| globals, "state" |), "_storage_tries" |) ], + M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, "state" |), "_snapshots" |), "pop" |), + make_list [], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + UnOp.not (| M.get_field (| M.get_name (| globals, "state" |), "_snapshots" |) |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, "state" |), "_created_accounts" |), "clear" |), + make_list [], + make_dict [] + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + M.pure Constant.None_)). + +Definition get_account : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "state"; "address" ] |) in + let _ := Constant.str " + Get the `Account` object at an address. Returns `EMPTY_ACCOUNT` if there + is no account at the address. + + Use `get_account_optional()` if you care about the difference between a + non-existent account and `EMPTY_ACCOUNT`. + + Parameters + ---------- + state: `State` + The state + address : `Address` + Address to lookup. + + Returns + ------- + account : `Account` + Account at address. + " in + let _ := M.assign_local (| + "account" , + M.call (| + M.get_name (| globals, "get_account_optional" |), + make_list [ + M.get_name (| globals, "state" |); + M.get_name (| globals, "address" |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, "isinstance" |), + make_list [ + M.get_name (| globals, "account" |); + M.get_name (| globals, "Account" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + M.get_name (| globals, "account" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.return_ (| + M.get_name (| globals, "EMPTY_ACCOUNT" |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_)). + +Definition get_account_optional : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "state"; "address" ] |) in + let _ := Constant.str " + Get the `Account` object at an address. Returns `None` (rather than + `EMPTY_ACCOUNT`) if there is no account at the address. + + Parameters + ---------- + state: `State` + The state + address : `Address` + Address to lookup. + + Returns + ------- + account : `Account` + Account at address. + " in + let _ := M.assign_local (| + "account" , + M.call (| + M.get_name (| globals, "trie_get" |), + make_list [ + M.get_field (| M.get_name (| globals, "state" |), "_main_trie" |); + M.get_name (| globals, "address" |) + ], + make_dict [] + |) + |) in + let _ := M.return_ (| + M.get_name (| globals, "account" |) + |) in + M.pure Constant.None_)). + +Definition set_account : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "state"; "address"; "account" ] |) in + let _ := Constant.str " + Set the `Account` object at an address. Setting to `None` deletes + the account (but not its storage, see `destroy_account()`). + + Parameters + ---------- + state: `State` + The state + address : `Address` + Address to set. + account : `Account` + Account to set at address. + " in + let _ := M.call (| + M.get_name (| globals, "trie_set" |), + make_list [ + M.get_field (| M.get_name (| globals, "state" |), "_main_trie" |); + M.get_name (| globals, "address" |); + M.get_name (| globals, "account" |) + ], + make_dict [] + |) in + M.pure Constant.None_)). + +Definition destroy_account : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "state"; "address" ] |) in + let _ := Constant.str " + Completely remove the account at `address` and all of its storage. + + This function is made available exclusively for the `SELFDESTRUCT` + opcode. It is expected that `SELFDESTRUCT` will be disabled in a future + hardfork and this function will be removed. + + Parameters + ---------- + state: `State` + The state + address : `Address` + Address of account to destroy. + " in + let _ := M.call (| + M.get_name (| globals, "destroy_storage" |), + make_list [ + M.get_name (| globals, "state" |); + M.get_name (| globals, "address" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "set_account" |), + make_list [ + M.get_name (| globals, "state" |); + M.get_name (| globals, "address" |); + Constant.None_ + ], + make_dict [] + |) in + M.pure Constant.None_)). + +Definition destroy_storage : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "state"; "address" ] |) in + let _ := Constant.str " + Completely remove the storage at `address`. + + Parameters + ---------- + state: `State` + The state + address : `Address` + Address of account whose storage is to be deleted. + " in + let _ := + (* if *) + M.if_then_else (| + Compare.in_ (| + M.get_name (| globals, "address" |), + M.get_field (| M.get_name (| globals, "state" |), "_storage_tries" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.delete (| M.get_subscript (| + M.get_field (| M.get_name (| globals, "state" |), "_storage_tries" |), + M.get_name (| globals, "address" |) + |) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + M.pure Constant.None_)). + +Definition mark_account_created : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "state"; "address" ] |) in + let _ := Constant.str " + Mark an account as having been created in the current transaction. + This information is used by `get_storage_original()` to handle an obscure + edgecase. + + The marker is not removed even if the account creation reverts. Since the + account cannot have had code prior to its creation and can't call + `get_storage_original()`, this is harmless. + + Parameters + ---------- + state: `State` + The state + address : `Address` + Address of the account that has been created. + " in + let _ := M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, "state" |), "_created_accounts" |), "add" |), + make_list [ + M.get_name (| globals, "address" |) + ], + make_dict [] + |) in + M.pure Constant.None_)). + +Definition get_storage : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "state"; "address"; "key" ] |) in + let _ := Constant.str " + Get a value at a storage key on an account. Returns `U256(0)` if the + storage key has not been set previously. + + Parameters + ---------- + state: `State` + The state + address : `Address` + Address of the account. + key : `Bytes` + Key to lookup. + + Returns + ------- + value : `U256` + Value at the key. + " in + let _ := M.assign_local (| + "trie" , + M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, "state" |), "_storage_tries" |), "get" |), + make_list [ + M.get_name (| globals, "address" |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.is (| + M.get_name (| globals, "trie" |), + Constant.None_ + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "value" , + M.call (| + M.get_name (| globals, "trie_get" |), + make_list [ + M.get_name (| globals, "trie" |); + M.get_name (| globals, "key" |) + ], + make_dict [] + |) + |) in + let _ := M.assert (| M.call (| + M.get_name (| globals, "isinstance" |), + make_list [ + M.get_name (| globals, "value" |); + M.get_name (| globals, "U256" |) + ], + make_dict [] + |) |) in + let _ := M.return_ (| + M.get_name (| globals, "value" |) + |) in + M.pure Constant.None_)). + +Definition set_storage : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "state"; "address"; "key"; "value" ] |) in + let _ := Constant.str " + Set a value at a storage key on an account. Setting to `U256(0)` deletes + the key. + + Parameters + ---------- + state: `State` + The state + address : `Address` + Address of the account. + key : `Bytes` + Key to set. + value : `U256` + Value to set at the key. + " in + let _ := M.assert (| Compare.is_not (| + M.call (| + M.get_name (| globals, "trie_get" |), + make_list [ + M.get_field (| M.get_name (| globals, "state" |), "_main_trie" |); + M.get_name (| globals, "address" |) + ], + make_dict [] + |), + Constant.None_ + |) |) in + let _ := M.assign_local (| + "trie" , + M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, "state" |), "_storage_tries" |), "get" |), + make_list [ + M.get_name (| globals, "address" |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.is (| + M.get_name (| globals, "trie" |), + Constant.None_ + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "trie" , + M.call (| + M.get_name (| globals, "Trie" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.assign (| + M.get_subscript (| + M.get_field (| M.get_name (| globals, "state" |), "_storage_tries" |), + M.get_name (| globals, "address" |) + |), + M.get_name (| globals, "trie" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.call (| + M.get_name (| globals, "trie_set" |), + make_list [ + M.get_name (| globals, "trie" |); + M.get_name (| globals, "key" |); + M.get_name (| globals, "value" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_field (| M.get_name (| globals, "trie" |), "_data" |), + Constant.str "(* At expr: unsupported node type: Dict *)" + |), + (* then *) + ltac:(M.monadic ( + let _ := M.delete (| M.get_subscript (| + M.get_field (| M.get_name (| globals, "state" |), "_storage_tries" |), + M.get_name (| globals, "address" |) + |) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + M.pure Constant.None_)). + +Definition storage_root : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "state"; "address" ] |) in + let _ := Constant.str " + Calculate the storage root of an account. + + Parameters + ---------- + state: + The state + address : + Address of the account. + + Returns + ------- + root : `Root` + Storage root of the account. + " in + let _ := M.assert (| UnOp.not (| M.get_field (| M.get_name (| globals, "state" |), "_snapshots" |) |) |) in + let _ := + (* if *) + M.if_then_else (| + Compare.in_ (| + M.get_name (| globals, "address" |), + M.get_field (| M.get_name (| globals, "state" |), "_storage_tries" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + M.call (| + M.get_name (| globals, "root" |), + make_list [ + M.get_subscript (| + M.get_field (| M.get_name (| globals, "state" |), "_storage_tries" |), + M.get_name (| globals, "address" |) + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.return_ (| + M.get_name (| globals, "EMPTY_TRIE_ROOT" |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_)). + +Definition state_root : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "state" ] |) in + let _ := Constant.str " + Calculate the state root. + + Parameters + ---------- + state: + The current state. + + Returns + ------- + root : `Root` + The state root. + " in + let _ := M.assert (| UnOp.not (| M.get_field (| M.get_name (| globals, "state" |), "_snapshots" |) |) |) in +(* At stmt: unsupported node type: FunctionDef *) + let _ := M.return_ (| + M.call (| + M.get_name (| globals, "root" |), + make_list [ + M.get_field (| M.get_name (| globals, "state" |), "_main_trie" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Definition account_exists : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "state"; "address" ] |) in + let _ := Constant.str " + Checks if an account exists in the state trie + + Parameters + ---------- + state: + The state + address: + Address of the account that needs to be checked. + + Returns + ------- + account_exists : `bool` + True if account exists in the state trie, False otherwise + " in + let _ := M.return_ (| + Compare.is_not (| + M.call (| + M.get_name (| globals, "get_account_optional" |), + make_list [ + M.get_name (| globals, "state" |); + M.get_name (| globals, "address" |) + ], + make_dict [] + |), + Constant.None_ + |) + |) in + M.pure Constant.None_)). + +Definition account_has_code_or_nonce : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "state"; "address" ] |) in + let _ := Constant.str " + Checks if an account has non zero nonce or non empty code + + Parameters + ---------- + state: + The state + address: + Address of the account that needs to be checked. + + Returns + ------- + has_code_or_nonce : `bool` + True if if an account has non zero nonce or non empty code, + False otherwise. + " in + let _ := M.assign_local (| + "account" , + M.call (| + M.get_name (| globals, "get_account" |), + make_list [ + M.get_name (| globals, "state" |); + M.get_name (| globals, "address" |) + ], + make_dict [] + |) + |) in + let _ := M.return_ (| + BoolOp.or (| + Compare.not_eq (| + M.get_field (| M.get_name (| globals, "account" |), "nonce" |), + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + |), + ltac:(M.monadic ( + Compare.not_eq (| + M.get_field (| M.get_name (| globals, "account" |), "code" |), + Constant.bytes "" + |) + )) + |) + |) in + M.pure Constant.None_)). + +Definition is_account_empty : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "state"; "address" ] |) in + let _ := Constant.str " + Checks if an account has zero nonce, empty code and zero balance. + + Parameters + ---------- + state: + The state + address: + Address of the account that needs to be checked. + + Returns + ------- + is_empty : `bool` + True if if an account has zero nonce, empty code and zero balance, + False otherwise. + " in + let _ := M.assign_local (| + "account" , + M.call (| + M.get_name (| globals, "get_account" |), + make_list [ + M.get_name (| globals, "state" |); + M.get_name (| globals, "address" |) + ], + make_dict [] + |) + |) in + let _ := M.return_ (| + BoolOp.and (| + Compare.eq (| + M.get_field (| M.get_name (| globals, "account" |), "nonce" |), + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + |), + ltac:(M.monadic ( + BoolOp.and (| + Compare.eq (| + M.get_field (| M.get_name (| globals, "account" |), "code" |), + Constant.bytes "" + |), + ltac:(M.monadic ( + Compare.eq (| + M.get_field (| M.get_name (| globals, "account" |), "balance" |), + Constant.int 0 + |) + )) + |) + )) + |) + |) in + M.pure Constant.None_)). + +Definition account_exists_and_is_empty : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "state"; "address" ] |) in + let _ := Constant.str " + Checks if an account exists and has zero nonce, empty code and zero + balance. + + Parameters + ---------- + state: + The state + address: + Address of the account that needs to be checked. + + Returns + ------- + exists_and_is_empty : `bool` + True if an account exists and has zero nonce, empty code and zero + balance, False otherwise. + " in + let _ := M.assign_local (| + "account" , + M.call (| + M.get_name (| globals, "get_account_optional" |), + make_list [ + M.get_name (| globals, "state" |); + M.get_name (| globals, "address" |) + ], + make_dict [] + |) + |) in + let _ := M.return_ (| + BoolOp.and (| + Compare.is_not (| + M.get_name (| globals, "account" |), + Constant.None_ + |), + ltac:(M.monadic ( + BoolOp.and (| + Compare.eq (| + M.get_field (| M.get_name (| globals, "account" |), "nonce" |), + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + |), + ltac:(M.monadic ( + BoolOp.and (| + Compare.eq (| + M.get_field (| M.get_name (| globals, "account" |), "code" |), + Constant.bytes "" + |), + ltac:(M.monadic ( + Compare.eq (| + M.get_field (| M.get_name (| globals, "account" |), "balance" |), + Constant.int 0 + |) + )) + |) + )) + |) + )) + |) + |) in + M.pure Constant.None_)). + +Definition is_account_alive : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "state"; "address" ] |) in + let _ := Constant.str " + Check whether is an account is both in the state and non empty. + + Parameters + ---------- + state: + The state + address: + Address of the account that needs to be checked. + + Returns + ------- + is_alive : `bool` + True if the account is alive. + " in + let _ := M.assign_local (| + "account" , + M.call (| + M.get_name (| globals, "get_account_optional" |), + make_list [ + M.get_name (| globals, "state" |); + M.get_name (| globals, "address" |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.is (| + M.get_name (| globals, "account" |), + Constant.None_ + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + Constant.bool false + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.return_ (| + UnOp.not (| BoolOp.and (| + Compare.eq (| + M.get_field (| M.get_name (| globals, "account" |), "nonce" |), + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + |), + ltac:(M.monadic ( + BoolOp.and (| + Compare.eq (| + M.get_field (| M.get_name (| globals, "account" |), "code" |), + Constant.bytes "" + |), + ltac:(M.monadic ( + Compare.eq (| + M.get_field (| M.get_name (| globals, "account" |), "balance" |), + Constant.int 0 + |) + )) + |) + )) + |) |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_)). + +Definition modify_state : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "state"; "address"; "f" ] |) in + let _ := Constant.str " + Modify an `Account` in the `State`. + " in + let _ := M.call (| + M.get_name (| globals, "set_account" |), + make_list [ + M.get_name (| globals, "state" |); + M.get_name (| globals, "address" |); + M.call (| + M.get_name (| globals, "modify" |), + make_list [ + M.call (| + M.get_name (| globals, "get_account" |), + make_list [ + M.get_name (| globals, "state" |); + M.get_name (| globals, "address" |) + ], + make_dict [] + |); + M.get_name (| globals, "f" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + M.pure Constant.None_)). + +Definition move_ether : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "state"; "sender_address"; "recipient_address"; "amount" ] |) in + let _ := Constant.str " + Move funds between accounts. + " in +(* At stmt: unsupported node type: FunctionDef *) +(* At stmt: unsupported node type: FunctionDef *) + let _ := M.call (| + M.get_name (| globals, "modify_state" |), + make_list [ + M.get_name (| globals, "state" |); + M.get_name (| globals, "sender_address" |); + M.get_name (| globals, "reduce_sender_balance" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "modify_state" |), + make_list [ + M.get_name (| globals, "state" |); + M.get_name (| globals, "recipient_address" |); + M.get_name (| globals, "increase_recipient_balance" |) + ], + make_dict [] + |) in + M.pure Constant.None_)). + +Definition set_account_balance : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "state"; "address"; "amount" ] |) in + let _ := Constant.str " + Sets the balance of an account. + + Parameters + ---------- + state: + The current state. + + address: + Address of the account whose nonce needs to be incremented. + + amount: + The amount that needs to set in balance. + " in +(* At stmt: unsupported node type: FunctionDef *) + let _ := M.call (| + M.get_name (| globals, "modify_state" |), + make_list [ + M.get_name (| globals, "state" |); + M.get_name (| globals, "address" |); + M.get_name (| globals, "set_balance" |) + ], + make_dict [] + |) in + M.pure Constant.None_)). + +Definition touch_account : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "state"; "address" ] |) in + let _ := Constant.str " + Initializes an account to state. + + Parameters + ---------- + state: + The current state. + + address: + The address of the account that need to initialised. + " in + let _ := + (* if *) + M.if_then_else (| + UnOp.not (| M.call (| + M.get_name (| globals, "account_exists" |), + make_list [ + M.get_name (| globals, "state" |); + M.get_name (| globals, "address" |) + ], + make_dict [] + |) |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, "set_account" |), + make_list [ + M.get_name (| globals, "state" |); + M.get_name (| globals, "address" |); + M.get_name (| globals, "EMPTY_ACCOUNT" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + M.pure Constant.None_)). + +Definition increment_nonce : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "state"; "address" ] |) in + let _ := Constant.str " + Increments the nonce of an account. + + Parameters + ---------- + state: + The current state. + + address: + Address of the account whose nonce needs to be incremented. + " in +(* At stmt: unsupported node type: FunctionDef *) + let _ := M.call (| + M.get_name (| globals, "modify_state" |), + make_list [ + M.get_name (| globals, "state" |); + M.get_name (| globals, "address" |); + M.get_name (| globals, "increase_nonce" |) + ], + make_dict [] + |) in + M.pure Constant.None_)). + +Definition set_code : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "state"; "address"; "code" ] |) in + let _ := Constant.str " + Sets Account code. + + Parameters + ---------- + state: + The current state. + + address: + Address of the account whose code needs to be update. + + code: + The bytecode that needs to be set. + " in +(* At stmt: unsupported node type: FunctionDef *) + let _ := M.call (| + M.get_name (| globals, "modify_state" |), + make_list [ + M.get_name (| globals, "state" |); + M.get_name (| globals, "address" |); + M.get_name (| globals, "write_code" |) + ], + make_dict [] + |) in + M.pure Constant.None_)). + +Definition create_ether : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "state"; "address"; "amount" ] |) in + let _ := Constant.str " + Add newly created ether to an account. + + Parameters + ---------- + state: + The current state. + address: + Address of the account to which ether is added. + amount: + The amount of ether to be added to the account of interest. + " in +(* At stmt: unsupported node type: FunctionDef *) + let _ := M.call (| + M.get_name (| globals, "modify_state" |), + make_list [ + M.get_name (| globals, "state" |); + M.get_name (| globals, "address" |); + M.get_name (| globals, "increase_balance" |) + ], + make_dict [] + |) in + M.pure Constant.None_)). + +Definition get_storage_original : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "state"; "address"; "key" ] |) in + let _ := Constant.str " + Get the original value in a storage slot i.e. the value before the current + transaction began. This function reads the value from the snapshots taken + before executing the transaction. + + Parameters + ---------- + state: + The current state. + address: + Address of the account to read the value from. + key: + Key of the storage slot. + " in + let _ := + (* if *) + M.if_then_else (| + Compare.in_ (| + M.get_name (| globals, "address" |), + M.get_field (| M.get_name (| globals, "state" |), "_created_accounts" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign (| + make_tuple [ M.get_name (| globals, "_" |); M.get_name (| globals, "original_trie" |) ], + M.get_subscript (| + M.get_field (| M.get_name (| globals, "state" |), "_snapshots" |), + Constant.int 0 + |) + |) in + let _ := M.assign_local (| + "original_account_trie" , + M.call (| + M.get_field (| M.get_name (| globals, "original_trie" |), "get" |), + make_list [ + M.get_name (| globals, "address" |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.is (| + M.get_name (| globals, "original_account_trie" |), + Constant.None_ + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "original_value" , + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "original_value" , + M.call (| + M.get_name (| globals, "trie_get" |), + make_list [ + M.get_name (| globals, "original_account_trie" |); + M.get_name (| globals, "key" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + )) |) in + let _ := M.assert (| M.call (| + M.get_name (| globals, "isinstance" |), + make_list [ + M.get_name (| globals, "original_value" |); + M.get_name (| globals, "U256" |) + ], + make_dict [] + |) |) in + let _ := M.return_ (| + M.get_name (| globals, "original_value" |) + |) in + M.pure Constant.None_)). diff --git a/CoqOfPython/ethereum/muir_glacier/transactions.v b/CoqOfPython/ethereum/muir_glacier/transactions.v new file mode 100644 index 0000000..0443ebc --- /dev/null +++ b/CoqOfPython/ethereum/muir_glacier/transactions.v @@ -0,0 +1,56 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.muir_glacier.transactions". + +Definition expr_1 : Value.t := + Constant.str " +Transactions are atomic units of work created externally to Ethereum and +submitted to be executed. If Ethereum is viewed as a state machine, +transactions are the events that move between states. +". + +Axiom dataclasses_imports_dataclass : + IsImported globals "dataclasses" "dataclass". + +Axiom typing_imports_Union : + IsImported globals "typing" "Union". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_Bytes : + IsImported globals "ethereum.base_types" "Bytes". +Axiom ethereum_base_types_imports_Bytes0 : + IsImported globals "ethereum.base_types" "Bytes0". +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". +Axiom ethereum_base_types_imports_slotted_freezable : + IsImported globals "ethereum.base_types" "slotted_freezable". + +Axiom ethereum_muir_glacier_fork_types_imports_Address : + IsImported globals "ethereum.muir_glacier.fork_types" "Address". + +Definition TX_BASE_COST : Value.t := M.run ltac:(M.monadic ( + Constant.int 21000 +)). + +Definition TX_DATA_COST_PER_NON_ZERO : Value.t := M.run ltac:(M.monadic ( + Constant.int 16 +)). + +Definition TX_DATA_COST_PER_ZERO : Value.t := M.run ltac:(M.monadic ( + Constant.int 4 +)). + +Definition TX_CREATE_COST : Value.t := M.run ltac:(M.monadic ( + Constant.int 32000 +)). + +Definition Transaction : Value.t := + builtins.make_klass + [] + [ + + ] + [ + + ]. diff --git a/CoqOfPython/ethereum/muir_glacier/trie.v b/CoqOfPython/ethereum/muir_glacier/trie.v new file mode 100644 index 0000000..5e9b0cd --- /dev/null +++ b/CoqOfPython/ethereum/muir_glacier/trie.v @@ -0,0 +1,1589 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.muir_glacier.trie". + +Definition expr_1 : Value.t := + Constant.str " +State Trie +^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +The state trie is the structure responsible for storing +`.fork_types.Account` objects. +". + +(* At top_level_stmt: unsupported node type: Import *) + +Axiom dataclasses_imports_dataclass : + IsImported globals "dataclasses" "dataclass". +Axiom dataclasses_imports_field : + IsImported globals "dataclasses" "field". + +Axiom typing_imports_Callable : + IsImported globals "typing" "Callable". +Axiom typing_imports_Dict : + IsImported globals "typing" "Dict". +Axiom typing_imports_Generic : + IsImported globals "typing" "Generic". +Axiom typing_imports_List : + IsImported globals "typing" "List". +Axiom typing_imports_Mapping : + IsImported globals "typing" "Mapping". +Axiom typing_imports_MutableMapping : + IsImported globals "typing" "MutableMapping". +Axiom typing_imports_Optional : + IsImported globals "typing" "Optional". +Axiom typing_imports_Sequence : + IsImported globals "typing" "Sequence". +Axiom typing_imports_TypeVar : + IsImported globals "typing" "TypeVar". +Axiom typing_imports_Union : + IsImported globals "typing" "Union". +Axiom typing_imports_cast : + IsImported globals "typing" "cast". + +Axiom ethereum_crypto_hash_imports_keccak256 : + IsImported globals "ethereum.crypto.hash" "keccak256". + +Axiom ethereum_istanbul_imports_trie : + IsImported globals "ethereum.istanbul" "trie". + +Axiom ethereum_utils_ensure_imports_ensure : + IsImported globals "ethereum.utils.ensure" "ensure". + +Axiom ethereum_utils_hexadecimal_imports_hex_to_bytes : + IsImported globals "ethereum.utils.hexadecimal" "hex_to_bytes". + +Axiom ethereum_imports_rlp : + IsImported globals "ethereum" "rlp". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_Bytes : + IsImported globals "ethereum.base_types" "Bytes". +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". +Axiom ethereum_base_types_imports_slotted_freezable : + IsImported globals "ethereum.base_types" "slotted_freezable". + +Axiom ethereum_muir_glacier_blocks_imports_Receipt : + IsImported globals "ethereum.muir_glacier.blocks" "Receipt". + +Axiom ethereum_muir_glacier_fork_types_imports_Account : + IsImported globals "ethereum.muir_glacier.fork_types" "Account". +Axiom ethereum_muir_glacier_fork_types_imports_Address : + IsImported globals "ethereum.muir_glacier.fork_types" "Address". +Axiom ethereum_muir_glacier_fork_types_imports_Root : + IsImported globals "ethereum.muir_glacier.fork_types" "Root". +Axiom ethereum_muir_glacier_fork_types_imports_encode_account : + IsImported globals "ethereum.muir_glacier.fork_types" "encode_account". + +Axiom ethereum_muir_glacier_transactions_imports_Transaction : + IsImported globals "ethereum.muir_glacier.transactions" "Transaction". + +Definition EMPTY_TRIE_ROOT : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Root" |), + make_list [ + M.call (| + M.get_name (| globals, "hex_to_bytes" |), + make_list [ + Constant.str "56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421" + ], + make_dict [] + |) + ], + make_dict [] + |) +)). + +Definition Node : Value.t := M.run ltac:(M.monadic ( + M.get_subscript (| + M.get_name (| globals, "Union" |), + make_tuple [ M.get_name (| globals, "Account" |); M.get_name (| globals, "Bytes" |); M.get_name (| globals, "Transaction" |); M.get_name (| globals, "Receipt" |); M.get_name (| globals, "Uint" |); M.get_name (| globals, "U256" |); Constant.None_ ] + |) +)). + +Definition K : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "TypeVar" |), + make_list [ + Constant.str "K" + ], + make_dict [] + |) +)). + +Definition V : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "TypeVar" |), + make_list [ + Constant.str "V"; + M.get_subscript (| + M.get_name (| globals, "Optional" |), + M.get_name (| globals, "Account" |) + |); + M.get_subscript (| + M.get_name (| globals, "Optional" |), + M.get_name (| globals, "Bytes" |) + |); + M.get_name (| globals, "Bytes" |); + M.get_subscript (| + M.get_name (| globals, "Optional" |), + M.get_name (| globals, "Transaction" |) + |); + M.get_subscript (| + M.get_name (| globals, "Optional" |), + M.get_name (| globals, "Receipt" |) + |); + M.get_name (| globals, "Uint" |); + M.get_name (| globals, "U256" |) + ], + make_dict [] + |) +)). + +Definition LeafNode : Value.t := + builtins.make_klass + [] + [ + + ] + [ + + ]. + +Definition ExtensionNode : Value.t := + builtins.make_klass + [] + [ + + ] + [ + + ]. + +Definition BranchNode : Value.t := + builtins.make_klass + [] + [ + + ] + [ + + ]. + +Definition InternalNode : Value.t := M.run ltac:(M.monadic ( + M.get_subscript (| + M.get_name (| globals, "Union" |), + make_tuple [ M.get_name (| globals, "LeafNode" |); M.get_name (| globals, "ExtensionNode" |); M.get_name (| globals, "BranchNode" |) ] + |) +)). + +Definition encode_internal_node : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "node" ] |) in + let _ := Constant.str " + Encodes a Merkle Trie node into its RLP form. The RLP will then be + serialized into a `Bytes` and hashed unless it is less that 32 bytes + when serialized. + + This function also accepts `None`, representing the absence of a node, + which is encoded to `b""""`. + + Parameters + ---------- + node : Optional[InternalNode] + The node to encode. + + Returns + ------- + encoded : `rlp.RLP` + The node encoded as RLP. + " in +(* At stmt: unsupported node type: AnnAssign *) + let _ := + (* if *) + M.if_then_else (| + Compare.is (| + M.get_name (| globals, "node" |), + Constant.None_ + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "unencoded" , + Constant.bytes "" + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, "isinstance" |), + make_list [ + M.get_name (| globals, "node" |); + M.get_name (| globals, "LeafNode" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "unencoded" , + make_tuple [ M.call (| + M.get_name (| globals, "nibble_list_to_compact" |), + make_list [ + M.get_field (| M.get_name (| globals, "node" |), "rest_of_key" |); + Constant.bool true + ], + make_dict [] + |); M.get_field (| M.get_name (| globals, "node" |), "value" |) ] + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, "isinstance" |), + make_list [ + M.get_name (| globals, "node" |); + M.get_name (| globals, "ExtensionNode" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "unencoded" , + make_tuple [ M.call (| + M.get_name (| globals, "nibble_list_to_compact" |), + make_list [ + M.get_field (| M.get_name (| globals, "node" |), "key_segment" |); + Constant.bool false + ], + make_dict [] + |); M.get_field (| M.get_name (| globals, "node" |), "subnode" |) ] + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, "isinstance" |), + make_list [ + M.get_name (| globals, "node" |); + M.get_name (| globals, "BranchNode" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "unencoded" , + BinOp.add (| + M.get_field (| M.get_name (| globals, "node" |), "subnodes" |), + make_list [ + M.get_field (| M.get_name (| globals, "node" |), "value" |) + ] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.raise (| Some (M.call (| + M.get_name (| globals, "AssertionError" |), + make_list [ + Constant.str "(* At expr: unsupported node type: JoinedStr *)" + ], + make_dict [] + |)) |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "encoded" , + M.call (| + M.get_field (| M.get_name (| globals, "rlp" |), "encode" |), + make_list [ + M.get_name (| globals, "unencoded" |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.lt (| + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_name (| globals, "encoded" |) + ], + make_dict [] + |), + Constant.int 32 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + M.get_name (| globals, "unencoded" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.return_ (| + M.call (| + M.get_name (| globals, "keccak256" |), + make_list [ + M.get_name (| globals, "encoded" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_)). + +Definition encode_node : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "node"; "storage_root" ] |) in + let _ := Constant.str " + Encode a Node for storage in the Merkle Trie. + + Currently mostly an unimplemented stub. + " in + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, "isinstance" |), + make_list [ + M.get_name (| globals, "node" |); + M.get_name (| globals, "Account" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assert (| Compare.is_not (| + M.get_name (| globals, "storage_root" |), + Constant.None_ + |) |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, "encode_account" |), + make_list [ + M.get_name (| globals, "node" |); + M.get_name (| globals, "storage_root" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, "isinstance" |), + make_list [ + M.get_name (| globals, "node" |); + make_tuple [ M.get_name (| globals, "Transaction" |); M.get_name (| globals, "Receipt" |); M.get_name (| globals, "U256" |) ] + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + M.call (| + M.get_field (| M.get_name (| globals, "rlp" |), "encode" |), + make_list [ + M.call (| + M.get_name (| globals, "cast" |), + make_list [ + M.get_field (| M.get_name (| globals, "rlp" |), "RLP" |); + M.get_name (| globals, "node" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, "isinstance" |), + make_list [ + M.get_name (| globals, "node" |); + M.get_name (| globals, "Bytes" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + M.get_name (| globals, "node" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.return_ (| + M.call (| + M.get_field (| M.get_name (| globals, "previous_trie" |), "encode_node" |), + make_list [ + M.get_name (| globals, "node" |); + M.get_name (| globals, "storage_root" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_)). + +Definition Trie : Value.t := + builtins.make_klass + [(* At base: unsupported node type: Subscript *)] + [ + + ] + [ + + ]. + +Definition copy_trie : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "trie" ] |) in + let _ := Constant.str " + Create a copy of `trie`. Since only frozen objects may be stored in tries, + the contents are reused. + + Parameters + ---------- + trie: `Trie` + Trie to copy. + + Returns + ------- + new_trie : `Trie[K, V]` + A copy of the trie. + " in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, "Trie" |), + make_list [ + M.get_field (| M.get_name (| globals, "trie" |), "secured" |); + M.get_field (| M.get_name (| globals, "trie" |), "default" |); + M.call (| + M.get_field (| M.get_name (| globals, "copy" |), "copy" |), + make_list [ + M.get_field (| M.get_name (| globals, "trie" |), "_data" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Definition trie_set : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "trie"; "key"; "value" ] |) in + let _ := Constant.str " + Stores an item in a Merkle Trie. + + This method deletes the key if `value == trie.default`, because the Merkle + Trie represents the default value by omitting it from the trie. + + Parameters + ---------- + trie: `Trie` + Trie to store in. + key : `Bytes` + Key to lookup. + value : `V` + Node to insert at `key`. + " in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, "value" |), + M.get_field (| M.get_name (| globals, "trie" |), "default" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + Compare.in_ (| + M.get_name (| globals, "key" |), + M.get_field (| M.get_name (| globals, "trie" |), "_data" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.delete (| M.get_subscript (| + M.get_field (| M.get_name (| globals, "trie" |), "_data" |), + M.get_name (| globals, "key" |) + |) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign (| + M.get_subscript (| + M.get_field (| M.get_name (| globals, "trie" |), "_data" |), + M.get_name (| globals, "key" |) + |), + M.get_name (| globals, "value" |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_)). + +Definition trie_get : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "trie"; "key" ] |) in + let _ := Constant.str " + Gets an item from the Merkle Trie. + + This method returns `trie.default` if the key is missing. + + Parameters + ---------- + trie: + Trie to lookup in. + key : + Key to lookup. + + Returns + ------- + node : `V` + Node at `key` in the trie. + " in + let _ := M.return_ (| + M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, "trie" |), "_data" |), "get" |), + make_list [ + M.get_name (| globals, "key" |); + M.get_field (| M.get_name (| globals, "trie" |), "default" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Definition common_prefix_length : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "a"; "b" ] |) in + let _ := Constant.str " + Find the longest common prefix of two sequences. + " in + let _ := + M.for_ (| + M.get_name (| globals, "i" |), + M.call (| + M.get_name (| globals, "range" |), + make_list [ + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_name (| globals, "a" |) + ], + make_dict [] + |) + ], + make_dict [] + |), + ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + BoolOp.or (| + Compare.gt_e (| + M.get_name (| globals, "i" |), + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_name (| globals, "b" |) + ], + make_dict [] + |) + |), + ltac:(M.monadic ( + Compare.not_eq (| + M.get_subscript (| + M.get_name (| globals, "a" |), + M.get_name (| globals, "i" |) + |), + M.get_subscript (| + M.get_name (| globals, "b" |), + M.get_name (| globals, "i" |) + |) + |) + )) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + M.get_name (| globals, "i" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_name (| globals, "a" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Definition nibble_list_to_compact : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "x"; "is_leaf" ] |) in + let _ := Constant.str " + Compresses nibble-list into a standard byte array with a flag. + + A nibble-list is a list of byte values no greater than `15`. The flag is + encoded in high nibble of the highest byte. The flag nibble can be broken + down into two two-bit flags. + + Highest nibble:: + + +---+---+----------+--------+ + | _ | _ | is_leaf | parity | + +---+---+----------+--------+ + 3 2 1 0 + + + The lowest bit of the nibble encodes the parity of the length of the + remaining nibbles -- `0` when even and `1` when odd. The second lowest bit + is used to distinguish leaf and extension nodes. The other two bits are not + used. + + Parameters + ---------- + x : + Array of nibbles. + is_leaf : + True if this is part of a leaf node, or false if it is an extension + node. + + Returns + ------- + compressed : `bytearray` + Compact byte array. + " in + let _ := M.assign_local (| + "compact" , + M.call (| + M.get_name (| globals, "bytearray" |), + make_list [], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + BinOp.mod_ (| + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_name (| globals, "x" |) + ], + make_dict [] + |), + Constant.int 2 + |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_field (| M.get_name (| globals, "compact" |), "append" |), + make_list [ + BinOp.mult (| + Constant.int 16, + BinOp.mult (| + Constant.int 2, + M.get_name (| globals, "is_leaf" |) + |) + |) + ], + make_dict [] + |) in + let _ := + M.for_ (| + M.get_name (| globals, "i" |), + M.call (| + M.get_name (| globals, "range" |), + make_list [ + Constant.int 0; + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_name (| globals, "x" |) + ], + make_dict [] + |); + Constant.int 2 + ], + make_dict [] + |), + ltac:(M.monadic ( + let _ := M.call (| + M.get_field (| M.get_name (| globals, "compact" |), "append" |), + make_list [ + BinOp.add (| + BinOp.mult (| + Constant.int 16, + M.get_subscript (| + M.get_name (| globals, "x" |), + M.get_name (| globals, "i" |) + |) + |), + M.get_subscript (| + M.get_name (| globals, "x" |), + BinOp.add (| + M.get_name (| globals, "i" |), + Constant.int 1 + |) + |) + |) + ], + make_dict [] + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.call (| + M.get_field (| M.get_name (| globals, "compact" |), "append" |), + make_list [ + BinOp.add (| + BinOp.mult (| + Constant.int 16, + BinOp.add (| + BinOp.mult (| + Constant.int 2, + M.get_name (| globals, "is_leaf" |) + |), + Constant.int 1 + |) + |), + M.get_subscript (| + M.get_name (| globals, "x" |), + Constant.int 0 + |) + |) + ], + make_dict [] + |) in + let _ := + M.for_ (| + M.get_name (| globals, "i" |), + M.call (| + M.get_name (| globals, "range" |), + make_list [ + Constant.int 1; + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_name (| globals, "x" |) + ], + make_dict [] + |); + Constant.int 2 + ], + make_dict [] + |), + ltac:(M.monadic ( + let _ := M.call (| + M.get_field (| M.get_name (| globals, "compact" |), "append" |), + make_list [ + BinOp.add (| + BinOp.mult (| + Constant.int 16, + M.get_subscript (| + M.get_name (| globals, "x" |), + M.get_name (| globals, "i" |) + |) + |), + M.get_subscript (| + M.get_name (| globals, "x" |), + BinOp.add (| + M.get_name (| globals, "i" |), + Constant.int 1 + |) + |) + |) + ], + make_dict [] + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + M.pure Constant.None_ + )) |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, "Bytes" |), + make_list [ + M.get_name (| globals, "compact" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Definition bytes_to_nibble_list : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "bytes_" ] |) in + let _ := Constant.str " + Converts a `Bytes` into to a sequence of nibbles (bytes with value < 16). + + Parameters + ---------- + bytes_: + The `Bytes` to convert. + + Returns + ------- + nibble_list : `Bytes` + The `Bytes` in nibble-list format. + " in + let _ := M.assign_local (| + "nibble_list" , + M.call (| + M.get_name (| globals, "bytearray" |), + make_list [ + BinOp.mult (| + Constant.int 2, + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_name (| globals, "bytes_" |) + ], + make_dict [] + |) + |) + ], + make_dict [] + |) + |) in + let _ := + M.for_ (| + make_tuple [ M.get_name (| globals, "byte_index" |); M.get_name (| globals, "byte" |) ], + M.call (| + M.get_name (| globals, "enumerate" |), + make_list [ + M.get_name (| globals, "bytes_" |) + ], + make_dict [] + |), + ltac:(M.monadic ( + let _ := M.assign (| + M.get_subscript (| + M.get_name (| globals, "nibble_list" |), + BinOp.mult (| + M.get_name (| globals, "byte_index" |), + Constant.int 2 + |) + |), + BinOp.r_shift (| + BinOp.bit_and (| + M.get_name (| globals, "byte" |), + Constant.int 240 + |), + Constant.int 4 + |) + |) in + let _ := M.assign (| + M.get_subscript (| + M.get_name (| globals, "nibble_list" |), + BinOp.add (| + BinOp.mult (| + M.get_name (| globals, "byte_index" |), + Constant.int 2 + |), + Constant.int 1 + |) + |), + BinOp.bit_and (| + M.get_name (| globals, "byte" |), + Constant.int 15 + |) + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, "Bytes" |), + make_list [ + M.get_name (| globals, "nibble_list" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Definition _prepare_trie : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "trie"; "get_storage_root" ] |) in + let _ := Constant.str " + Prepares the trie for root calculation. Removes values that are empty, + hashes the keys (if `secured == True`) and encodes all the nodes. + + Parameters + ---------- + trie : + The `Trie` to prepare. + get_storage_root : + Function to get the storage root of an account. Needed to encode + `Account` objects. + + Returns + ------- + out : `Mapping[ethereum.base_types.Bytes, Node]` + Object with keys mapped to nibble-byte form. + " in +(* At stmt: unsupported node type: AnnAssign *) + let _ := + M.for_ (| + make_tuple [ M.get_name (| globals, "preimage" |); M.get_name (| globals, "value" |) ], + M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, "trie" |), "_data" |), "items" |), + make_list [], + make_dict [] + |), + ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, "isinstance" |), + make_list [ + M.get_name (| globals, "value" |); + M.get_name (| globals, "Account" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assert (| Compare.is_not (| + M.get_name (| globals, "get_storage_root" |), + Constant.None_ + |) |) in + let _ := M.assign_local (| + "address" , + M.call (| + M.get_name (| globals, "Address" |), + make_list [ + M.get_name (| globals, "preimage" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "encoded_value" , + M.call (| + M.get_name (| globals, "encode_node" |), + make_list [ + M.get_name (| globals, "value" |); + M.call (| + M.get_name (| globals, "get_storage_root" |), + make_list [ + M.get_name (| globals, "address" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "encoded_value" , + M.call (| + M.get_name (| globals, "encode_node" |), + make_list [ + M.get_name (| globals, "value" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + )) |) in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + Compare.not_eq (| + M.get_name (| globals, "encoded_value" |), + Constant.bytes "" + |); + M.get_name (| globals, "AssertionError" |) + ], + make_dict [] + |) in +(* At stmt: unsupported node type: AnnAssign *) + let _ := + (* if *) + M.if_then_else (| + M.get_field (| M.get_name (| globals, "trie" |), "secured" |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "key" , + M.call (| + M.get_name (| globals, "keccak256" |), + make_list [ + M.get_name (| globals, "preimage" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "key" , + M.get_name (| globals, "preimage" |) + |) in + M.pure Constant.None_ + )) |) in + let _ := M.assign (| + M.get_subscript (| + M.get_name (| globals, "mapped" |), + M.call (| + M.get_name (| globals, "bytes_to_nibble_list" |), + make_list [ + M.get_name (| globals, "key" |) + ], + make_dict [] + |) + |), + M.get_name (| globals, "encoded_value" |) + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := M.return_ (| + M.get_name (| globals, "mapped" |) + |) in + M.pure Constant.None_)). + +Definition root : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "trie"; "get_storage_root" ] |) in + let _ := Constant.str " + Computes the root of a modified merkle patricia trie (MPT). + + Parameters + ---------- + trie : + `Trie` to get the root of. + get_storage_root : + Function to get the storage root of an account. Needed to encode + `Account` objects. + + + Returns + ------- + root : `.fork_types.Root` + MPT root of the underlying key-value pairs. + " in + let _ := M.assign_local (| + "obj" , + M.call (| + M.get_name (| globals, "_prepare_trie" |), + make_list [ + M.get_name (| globals, "trie" |); + M.get_name (| globals, "get_storage_root" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "root_node" , + M.call (| + M.get_name (| globals, "encode_internal_node" |), + make_list [ + M.call (| + M.get_name (| globals, "patricialize" |), + make_list [ + M.get_name (| globals, "obj" |); + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.lt (| + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.call (| + M.get_field (| M.get_name (| globals, "rlp" |), "encode" |), + make_list [ + M.get_name (| globals, "root_node" |) + ], + make_dict [] + |) + ], + make_dict [] + |), + Constant.int 32 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + M.call (| + M.get_name (| globals, "keccak256" |), + make_list [ + M.call (| + M.get_field (| M.get_name (| globals, "rlp" |), "encode" |), + make_list [ + M.get_name (| globals, "root_node" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assert (| M.call (| + M.get_name (| globals, "isinstance" |), + make_list [ + M.get_name (| globals, "root_node" |); + M.get_name (| globals, "Bytes" |) + ], + make_dict [] + |) |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, "Root" |), + make_list [ + M.get_name (| globals, "root_node" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_)). + +Definition patricialize : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "obj"; "level" ] |) in + let _ := Constant.str " + Structural composition function. + + Used to recursively patricialize and merkleize a dictionary. Includes + memoization of the tree structure and hashes. + + Parameters + ---------- + obj : + Underlying trie key-value pairs, with keys in nibble-list format. + level : + Current trie level. + + Returns + ------- + node : `ethereum.base_types.Bytes` + Root node of `obj`. + " in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_name (| globals, "obj" |) + ], + make_dict [] + |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + Constant.None_ + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "arbitrary_key" , + M.call (| + M.get_name (| globals, "next" |), + make_list [ + M.call (| + M.get_name (| globals, "iter" |), + make_list [ + M.get_name (| globals, "obj" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_name (| globals, "obj" |) + ], + make_dict [] + |), + Constant.int 1 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "leaf" , + M.call (| + M.get_name (| globals, "LeafNode" |), + make_list [ + M.slice (| + M.get_name (| globals, "arbitrary_key" |), + M.get_name (| globals, "level" |), + Constant.None_, + Constant.None_ + |); + M.get_subscript (| + M.get_name (| globals, "obj" |), + M.get_name (| globals, "arbitrary_key" |) + |) + ], + make_dict [] + |) + |) in + let _ := M.return_ (| + M.get_name (| globals, "leaf" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "substring" , + M.slice (| + M.get_name (| globals, "arbitrary_key" |), + M.get_name (| globals, "level" |), + Constant.None_, + Constant.None_ + |) + |) in + let _ := M.assign_local (| + "prefix_length" , + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_name (| globals, "substring" |) + ], + make_dict [] + |) + |) in + let _ := + M.for_ (| + M.get_name (| globals, "key" |), + M.get_name (| globals, "obj" |), + ltac:(M.monadic ( + let _ := M.assign_local (| + "prefix_length" , + M.call (| + M.get_name (| globals, "min" |), + make_list [ + M.get_name (| globals, "prefix_length" |); + M.call (| + M.get_name (| globals, "common_prefix_length" |), + make_list [ + M.get_name (| globals, "substring" |); + M.slice (| + M.get_name (| globals, "key" |), + M.get_name (| globals, "level" |), + Constant.None_, + Constant.None_ + |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, "prefix_length" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.break (| |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.gt (| + M.get_name (| globals, "prefix_length" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "prefix" , + M.slice (| + M.get_name (| globals, "arbitrary_key" |), + M.get_name (| globals, "level" |), + BinOp.add (| + M.get_name (| globals, "level" |), + M.get_name (| globals, "prefix_length" |) + |), + Constant.None_ + |) + |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, "ExtensionNode" |), + make_list [ + M.get_name (| globals, "prefix" |); + M.call (| + M.get_name (| globals, "encode_internal_node" |), + make_list [ + M.call (| + M.get_name (| globals, "patricialize" |), + make_list [ + M.get_name (| globals, "obj" |); + BinOp.add (| + M.get_name (| globals, "level" |), + M.get_name (| globals, "prefix_length" |) + |) + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in +(* At stmt: unsupported node type: AnnAssign *) + let _ := + M.for_ (| + M.get_name (| globals, "_" |), + M.call (| + M.get_name (| globals, "range" |), + make_list [ + Constant.int 16 + ], + make_dict [] + |), + ltac:(M.monadic ( + let _ := M.call (| + M.get_field (| M.get_name (| globals, "branches" |), "append" |), + make_list [ + Constant.str "(* At expr: unsupported node type: Dict *)" + ], + make_dict [] + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := M.assign_local (| + "value" , + Constant.bytes "" + |) in + let _ := + M.for_ (| + M.get_name (| globals, "key" |), + M.get_name (| globals, "obj" |), + ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_name (| globals, "key" |) + ], + make_dict [] + |), + M.get_name (| globals, "level" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, "isinstance" |), + make_list [ + M.get_subscript (| + M.get_name (| globals, "obj" |), + M.get_name (| globals, "key" |) + |); + make_tuple [ M.get_name (| globals, "Account" |); M.get_name (| globals, "Receipt" |); M.get_name (| globals, "Uint" |) ] + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, "AssertionError" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "value" , + M.get_subscript (| + M.get_name (| globals, "obj" |), + M.get_name (| globals, "key" |) + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign (| + M.get_subscript (| + M.get_subscript (| + M.get_name (| globals, "branches" |), + M.get_subscript (| + M.get_name (| globals, "key" |), + M.get_name (| globals, "level" |) + |) + |), + M.get_name (| globals, "key" |) + |), + M.get_subscript (| + M.get_name (| globals, "obj" |), + M.get_name (| globals, "key" |) + |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, "BranchNode" |), + make_list [ + Constant.str "(* At expr: unsupported node type: ListComp *)"; + M.get_name (| globals, "value" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). diff --git a/CoqOfPython/ethereum/muir_glacier/utils/__init__.v b/CoqOfPython/ethereum/muir_glacier/utils/__init__.v new file mode 100644 index 0000000..d8eb235 --- /dev/null +++ b/CoqOfPython/ethereum/muir_glacier/utils/__init__.v @@ -0,0 +1,8 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.muir_glacier.utils.__init__". + +Definition expr_1 : Value.t := + Constant.str " +Utility functions unique to this particular fork. +". diff --git a/CoqOfPython/ethereum/muir_glacier/utils/address.v b/CoqOfPython/ethereum/muir_glacier/utils/address.v new file mode 100644 index 0000000..7c8c1f0 --- /dev/null +++ b/CoqOfPython/ethereum/muir_glacier/utils/address.v @@ -0,0 +1,227 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.muir_glacier.utils.address". + +Definition expr_1 : Value.t := + Constant.str " +Hardfork Utility Functions For Addresses +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Address specific functions used in this muir_glacier version of +specification. +". + +Axiom typing_imports_Union : + IsImported globals "typing" "Union". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_Bytes32 : + IsImported globals "ethereum.base_types" "Bytes32". +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". + +Axiom ethereum_crypto_hash_imports_keccak256 : + IsImported globals "ethereum.crypto.hash" "keccak256". + +Axiom ethereum_utils_byte_imports_left_pad_zero_bytes : + IsImported globals "ethereum.utils.byte" "left_pad_zero_bytes". + +Axiom ethereum_imports_rlp : + IsImported globals "ethereum" "rlp". + +Axiom ethereum_muir_glacier_fork_types_imports_Address : + IsImported globals "ethereum.muir_glacier.fork_types" "Address". + +Definition to_address : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "data" ] |) in + let _ := Constant.str " + Convert a Uint or U256 value to a valid address (20 bytes). + + Parameters + ---------- + data : + The string to be converted to bytes. + + Returns + ------- + address : `Address` + The obtained address. + " in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, "Address" |), + make_list [ + M.slice (| + M.call (| + M.get_field (| M.get_name (| globals, "data" |), "to_be_bytes32" |), + make_list [], + make_dict [] + |), + UnOp.sub (| Constant.int 20 |), + Constant.None_, + Constant.None_ + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Definition compute_contract_address : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "address"; "nonce" ] |) in + let _ := Constant.str " + Computes address of the new account that needs to be created. + + Parameters + ---------- + address : + The address of the account that wants to create the new account. + nonce : + The transaction count of the account that wants to create the new + account. + + Returns + ------- + address: `Address` + The computed address of the new account. + " in + let _ := M.assign_local (| + "computed_address" , + M.call (| + M.get_name (| globals, "keccak256" |), + make_list [ + M.call (| + M.get_field (| M.get_name (| globals, "rlp" |), "encode" |), + make_list [ + make_list [ + M.get_name (| globals, "address" |); + M.get_name (| globals, "nonce" |) + ] + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "canonical_address" , + M.slice (| + M.get_name (| globals, "computed_address" |), + UnOp.sub (| Constant.int 20 |), + Constant.None_, + Constant.None_ + |) + |) in + let _ := M.assign_local (| + "padded_address" , + M.call (| + M.get_name (| globals, "left_pad_zero_bytes" |), + make_list [ + M.get_name (| globals, "canonical_address" |); + Constant.int 20 + ], + make_dict [] + |) + |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, "Address" |), + make_list [ + M.get_name (| globals, "padded_address" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Definition compute_create2_contract_address : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "address"; "salt"; "call_data" ] |) in + let _ := Constant.str " + Computes address of the new account that needs to be created, which is + based on the sender address, salt and the call data as well. + + Parameters + ---------- + address : + The address of the account that wants to create the new account. + salt : + Address generation salt. + call_data : + The code of the new account which is to be created. + + Returns + ------- + address: `ethereum.muir_glacier.fork_types.Address` + The computed address of the new account. + " in + let _ := M.assign_local (| + "preimage" , + BinOp.add (| + BinOp.add (| + BinOp.add (| + Constant.bytes "ff", + M.get_name (| globals, "address" |) + |), + M.get_name (| globals, "salt" |) + |), + M.call (| + M.get_name (| globals, "keccak256" |), + make_list [ + M.get_name (| globals, "call_data" |) + ], + make_dict [] + |) + |) + |) in + let _ := M.assign_local (| + "computed_address" , + M.call (| + M.get_name (| globals, "keccak256" |), + make_list [ + M.get_name (| globals, "preimage" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "canonical_address" , + M.slice (| + M.get_name (| globals, "computed_address" |), + UnOp.sub (| Constant.int 20 |), + Constant.None_, + Constant.None_ + |) + |) in + let _ := M.assign_local (| + "padded_address" , + M.call (| + M.get_name (| globals, "left_pad_zero_bytes" |), + make_list [ + M.get_name (| globals, "canonical_address" |); + Constant.int 20 + ], + make_dict [] + |) + |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, "Address" |), + make_list [ + M.get_name (| globals, "padded_address" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). diff --git a/CoqOfPython/ethereum/muir_glacier/utils/hexadecimal.v b/CoqOfPython/ethereum/muir_glacier/utils/hexadecimal.v new file mode 100644 index 0000000..56e0dcc --- /dev/null +++ b/CoqOfPython/ethereum/muir_glacier/utils/hexadecimal.v @@ -0,0 +1,153 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.muir_glacier.utils.hexadecimal". + +Definition expr_1 : Value.t := + Constant.str " +Utility Functions For Hexadecimal Strings +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Hexadecimal utility functions used in this specification, specific to +Muir Glacier types. +". + +Axiom ethereum_utils_hexadecimal_imports_remove_hex_prefix : + IsImported globals "ethereum.utils.hexadecimal" "remove_hex_prefix". + +Axiom ethereum_muir_glacier_fork_types_imports_Address : + IsImported globals "ethereum.muir_glacier.fork_types" "Address". +Axiom ethereum_muir_glacier_fork_types_imports_Bloom : + IsImported globals "ethereum.muir_glacier.fork_types" "Bloom". +Axiom ethereum_muir_glacier_fork_types_imports_Root : + IsImported globals "ethereum.muir_glacier.fork_types" "Root". + +Definition hex_to_root : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "hex_string" ] |) in + let _ := Constant.str " + Convert hex string to trie root. + + Parameters + ---------- + hex_string : + The hexadecimal string to be converted to trie root. + + Returns + ------- + root : `Root` + Trie root obtained from the given hexadecimal string. + " in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, "Root" |), + make_list [ + M.call (| + M.get_field (| M.get_name (| globals, "bytes" |), "fromhex" |), + make_list [ + M.call (| + M.get_name (| globals, "remove_hex_prefix" |), + make_list [ + M.get_name (| globals, "hex_string" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Definition hex_to_bloom : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "hex_string" ] |) in + let _ := Constant.str " + Convert hex string to bloom. + + Parameters + ---------- + hex_string : + The hexadecimal string to be converted to bloom. + + Returns + ------- + bloom : `Bloom` + Bloom obtained from the given hexadecimal string. + " in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, "Bloom" |), + make_list [ + M.call (| + M.get_field (| M.get_name (| globals, "bytes" |), "fromhex" |), + make_list [ + M.call (| + M.get_name (| globals, "remove_hex_prefix" |), + make_list [ + M.get_name (| globals, "hex_string" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Definition hex_to_address : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "hex_string" ] |) in + let _ := Constant.str " + Convert hex string to Address (20 bytes). + + Parameters + ---------- + hex_string : + The hexadecimal string to be converted to Address. + + Returns + ------- + address : `Address` + The address obtained from the given hexadecimal string. + " in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, "Address" |), + make_list [ + M.call (| + M.get_field (| M.get_name (| globals, "bytes" |), "fromhex" |), + make_list [ + M.call (| + M.get_field (| M.call (| + M.get_name (| globals, "remove_hex_prefix" |), + make_list [ + M.get_name (| globals, "hex_string" |) + ], + make_dict [] + |), "rjust" |), + make_list [ + Constant.int 40; + Constant.str "0" + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). diff --git a/CoqOfPython/ethereum/muir_glacier/utils/message.v b/CoqOfPython/ethereum/muir_glacier/utils/message.v new file mode 100644 index 0000000..e7c7551 --- /dev/null +++ b/CoqOfPython/ethereum/muir_glacier/utils/message.v @@ -0,0 +1,212 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.muir_glacier.utils.message". + +Definition expr_1 : Value.t := + Constant.str " +Hardfork Utility Functions For The Message Data-structure +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Message specific functions used in this muir_glacier version of +specification. +". + +Axiom typing_imports_Optional : + IsImported globals "typing" "Optional". +Axiom typing_imports_Union : + IsImported globals "typing" "Union". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_Bytes : + IsImported globals "ethereum.base_types" "Bytes". +Axiom ethereum_base_types_imports_Bytes0 : + IsImported globals "ethereum.base_types" "Bytes0". +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". + +Axiom ethereum_muir_glacier_fork_types_imports_Address : + IsImported globals "ethereum.muir_glacier.fork_types" "Address". + +Axiom ethereum_muir_glacier_state_imports_get_account : + IsImported globals "ethereum.muir_glacier.state" "get_account". + +Axiom ethereum_muir_glacier_vm_imports_Environment : + IsImported globals "ethereum.muir_glacier.vm" "Environment". +Axiom ethereum_muir_glacier_vm_imports_Message : + IsImported globals "ethereum.muir_glacier.vm" "Message". + +Axiom ethereum_muir_glacier_utils_address_imports_compute_contract_address : + IsImported globals "ethereum.muir_glacier.utils.address" "compute_contract_address". + +Definition prepare_message : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "caller"; "target"; "value"; "data"; "gas"; "env"; "code_address"; "should_transfer_value"; "is_static" ] |) in + let _ := Constant.str " + Execute a transaction against the provided environment. + + Parameters + ---------- + caller : + Address which initiated the transaction + target : + Address whose code will be executed + value : + Value to be transferred. + data : + Array of bytes provided to the code in `target`. + gas : + Gas provided for the code in `target`. + env : + Environment for the Ethereum Virtual Machine. + code_address : + This is usually same as the `target` address except when an alternative + accounts code needs to be executed. + eg. `CALLCODE` calling a precompile. + should_transfer_value : + if True ETH should be transferred while executing a message call. + is_static: + if True then it prevents all state-changing operations from being + executed. + + Returns + ------- + message: `ethereum.muir_glacier.vm.Message` + Items containing contract creation or message call specific data. + " in + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, "isinstance" |), + make_list [ + M.get_name (| globals, "target" |); + M.get_name (| globals, "Bytes0" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "current_target" , + M.call (| + M.get_name (| globals, "compute_contract_address" |), + make_list [ + M.get_name (| globals, "caller" |); + BinOp.sub (| + M.get_field (| M.call (| + M.get_name (| globals, "get_account" |), + make_list [ + M.get_field (| M.get_name (| globals, "env" |), "state" |); + M.get_name (| globals, "caller" |) + ], + make_dict [] + |), "nonce" |), + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 1 + ], + make_dict [] + |) + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "msg_data" , + M.call (| + M.get_name (| globals, "Bytes" |), + make_list [ + Constant.bytes "" + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "code" , + M.get_name (| globals, "data" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, "isinstance" |), + make_list [ + M.get_name (| globals, "target" |); + M.get_name (| globals, "Address" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "current_target" , + M.get_name (| globals, "target" |) + |) in + let _ := M.assign_local (| + "msg_data" , + M.get_name (| globals, "data" |) + |) in + let _ := M.assign_local (| + "code" , + M.get_field (| M.call (| + M.get_name (| globals, "get_account" |), + make_list [ + M.get_field (| M.get_name (| globals, "env" |), "state" |); + M.get_name (| globals, "target" |) + ], + make_dict [] + |), "code" |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.is (| + M.get_name (| globals, "code_address" |), + Constant.None_ + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "code_address" , + M.get_name (| globals, "target" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.raise (| Some (M.call (| + M.get_name (| globals, "AssertionError" |), + make_list [ + Constant.str "Target must be address or empty bytes" + ], + make_dict [] + |)) |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )) |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, "Message" |), + make_list [], + make_dict [] + |) + |) in + M.pure Constant.None_)). diff --git a/CoqOfPython/ethereum/muir_glacier/vm/__init__.v b/CoqOfPython/ethereum/muir_glacier/vm/__init__.v new file mode 100644 index 0000000..e34d6a5 --- /dev/null +++ b/CoqOfPython/ethereum/muir_glacier/vm/__init__.v @@ -0,0 +1,244 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.muir_glacier.vm.__init__". + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +The abstract computer which runs the code stored in an +`.fork_types.Account`. +". + +Axiom dataclasses_imports_dataclass : + IsImported globals "dataclasses" "dataclass". + +Axiom typing_imports_List : + IsImported globals "typing" "List". +Axiom typing_imports_Optional : + IsImported globals "typing" "Optional". +Axiom typing_imports_Set : + IsImported globals "typing" "Set". +Axiom typing_imports_Tuple : + IsImported globals "typing" "Tuple". +Axiom typing_imports_Union : + IsImported globals "typing" "Union". + +Axiom ethereum_base_types_imports_U64 : + IsImported globals "ethereum.base_types" "U64". +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_Bytes : + IsImported globals "ethereum.base_types" "Bytes". +Axiom ethereum_base_types_imports_Bytes0 : + IsImported globals "ethereum.base_types" "Bytes0". +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". + +Axiom ethereum_crypto_hash_imports_Hash32 : + IsImported globals "ethereum.crypto.hash" "Hash32". + +Axiom ethereum_muir_glacier_blocks_imports_Log : + IsImported globals "ethereum.muir_glacier.blocks" "Log". + +Axiom ethereum_muir_glacier_fork_types_imports_Address : + IsImported globals "ethereum.muir_glacier.fork_types" "Address". + +Axiom ethereum_muir_glacier_state_imports_State : + IsImported globals "ethereum.muir_glacier.state" "State". +Axiom ethereum_muir_glacier_state_imports_account_exists_and_is_empty : + IsImported globals "ethereum.muir_glacier.state" "account_exists_and_is_empty". + +Axiom ethereum_muir_glacier_vm_precompiled_contracts_imports_RIPEMD160_ADDRESS : + IsImported globals "ethereum.muir_glacier.vm.precompiled_contracts" "RIPEMD160_ADDRESS". + +Definition __all__ : Value.t := M.run ltac:(M.monadic ( + make_tuple [ Constant.str "Environment"; Constant.str "Evm"; Constant.str "Message" ] +)). + +Definition Environment : Value.t := + builtins.make_klass + [] + [ + + ] + [ + + ]. + +Definition Message : Value.t := + builtins.make_klass + [] + [ + + ] + [ + + ]. + +Definition Evm : Value.t := + builtins.make_klass + [] + [ + + ] + [ + + ]. + +Definition incorporate_child_on_success : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm"; "child_evm" ] |) in + let _ := Constant.str " + Incorporate the state of a successful `child_evm` into the parent `evm`. + + Parameters + ---------- + evm : + The parent `EVM`. + child_evm : + The child evm to incorporate. + " in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "gas_left" |), + M.get_field (| M.get_name (| globals, "child_evm" |), "gas_left" |) + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "logs" |), + M.get_field (| M.get_name (| globals, "child_evm" |), "logs" |) + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "refund_counter" |), + M.get_field (| M.get_name (| globals, "child_evm" |), "refund_counter" |) + |) in + let _ := M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "accounts_to_delete" |), "update" |), + make_list [ + M.get_field (| M.get_name (| globals, "child_evm" |), "accounts_to_delete" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "touched_accounts" |), "update" |), + make_list [ + M.get_field (| M.get_name (| globals, "child_evm" |), "touched_accounts" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, "account_exists_and_is_empty" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "env" |), "state" |); + M.get_field (| M.get_field (| M.get_name (| globals, "child_evm" |), "message" |), "current_target" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "touched_accounts" |), "add" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "child_evm" |), "message" |), "current_target" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + M.pure Constant.None_)). + +Definition incorporate_child_on_error : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm"; "child_evm" ] |) in + let _ := Constant.str " + Incorporate the state of an unsuccessful `child_evm` into the parent `evm`. + + Parameters + ---------- + evm : + The parent `EVM`. + child_evm : + The child evm to incorporate. + " in + let _ := + (* if *) + M.if_then_else (| + Compare.in_ (| + M.get_name (| globals, "RIPEMD160_ADDRESS" |), + M.get_field (| M.get_name (| globals, "child_evm" |), "touched_accounts" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "touched_accounts" |), "add" |), + make_list [ + M.get_name (| globals, "RIPEMD160_ADDRESS" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_field (| M.get_field (| M.get_name (| globals, "child_evm" |), "message" |), "current_target" |), + M.get_name (| globals, "RIPEMD160_ADDRESS" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, "account_exists_and_is_empty" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "env" |), "state" |); + M.get_field (| M.get_field (| M.get_name (| globals, "child_evm" |), "message" |), "current_target" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "touched_accounts" |), "add" |), + make_list [ + M.get_name (| globals, "RIPEMD160_ADDRESS" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "gas_left" |), + M.get_field (| M.get_name (| globals, "child_evm" |), "gas_left" |) + |) in + M.pure Constant.None_)). diff --git a/CoqOfPython/ethereum/muir_glacier/vm/exceptions.v b/CoqOfPython/ethereum/muir_glacier/vm/exceptions.v new file mode 100644 index 0000000..9843a2b --- /dev/null +++ b/CoqOfPython/ethereum/muir_glacier/vm/exceptions.v @@ -0,0 +1,161 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.muir_glacier.vm.exceptions". + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) Exceptions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Exceptions which cause the EVM to halt exceptionally. +". + +Axiom ethereum_exceptions_imports_EthereumException : + IsImported globals "ethereum.exceptions" "EthereumException". + +Definition ExceptionalHalt : Value.t := + builtins.make_klass + [(globals, "EthereumException")] + [ + + ] + [ + + ]. + +Definition Revert : Value.t := + builtins.make_klass + [(globals, "EthereumException")] + [ + + ] + [ + + ]. + +Definition StackUnderflowError : Value.t := + builtins.make_klass + [(globals, "ExceptionalHalt")] + [ + + ] + [ + + ]. + +Definition StackOverflowError : Value.t := + builtins.make_klass + [(globals, "ExceptionalHalt")] + [ + + ] + [ + + ]. + +Definition OutOfGasError : Value.t := + builtins.make_klass + [(globals, "ExceptionalHalt")] + [ + + ] + [ + + ]. + +Definition InvalidOpcode : Value.t := + builtins.make_klass + [(globals, "ExceptionalHalt")] + [ + + ] + [ + ( + "__init__", + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "self"; "code" ] |) in + let _ := M.call (| + M.get_field (| M.call (| + M.get_name (| globals, "super" |), + make_list [], + make_dict [] + |), "__init__" |), + make_list [ + M.get_name (| globals, "code" |) + ], + make_dict [] + |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, "self" |), "code" |), + M.get_name (| globals, "code" |) + |) in + M.pure Constant.None_)) + ) + ]. + +Definition InvalidJumpDestError : Value.t := + builtins.make_klass + [(globals, "ExceptionalHalt")] + [ + + ] + [ + + ]. + +Definition StackDepthLimitError : Value.t := + builtins.make_klass + [(globals, "ExceptionalHalt")] + [ + + ] + [ + + ]. + +Definition WriteInStaticContext : Value.t := + builtins.make_klass + [(globals, "ExceptionalHalt")] + [ + + ] + [ + + ]. + +Definition OutOfBoundsRead : Value.t := + builtins.make_klass + [(globals, "ExceptionalHalt")] + [ + + ] + [ + + ]. + +Definition InvalidParameter : Value.t := + builtins.make_klass + [(globals, "ExceptionalHalt")] + [ + + ] + [ + + ]. + +Definition AddressCollision : Value.t := + builtins.make_klass + [(globals, "ExceptionalHalt")] + [ + + ] + [ + + ]. diff --git a/CoqOfPython/ethereum/muir_glacier/vm/gas.v b/CoqOfPython/ethereum/muir_glacier/vm/gas.v new file mode 100644 index 0000000..6ebc8c4 --- /dev/null +++ b/CoqOfPython/ethereum/muir_glacier/vm/gas.v @@ -0,0 +1,942 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.muir_glacier.vm.gas". + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) Gas +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +EVM gas constants and calculators. +". + +Axiom dataclasses_imports_dataclass : + IsImported globals "dataclasses" "dataclass". + +Axiom typing_imports_List : + IsImported globals "typing" "List". +Axiom typing_imports_Tuple : + IsImported globals "typing" "Tuple". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". + +Axiom ethereum_trace_imports_GasAndRefund : + IsImported globals "ethereum.trace" "GasAndRefund". +Axiom ethereum_trace_imports_evm_trace : + IsImported globals "ethereum.trace" "evm_trace". + +Axiom ethereum_utils_numeric_imports_ceil32 : + IsImported globals "ethereum.utils.numeric" "ceil32". + +Axiom ethereum_muir_glacier_vm_imports_Evm : + IsImported globals "ethereum.muir_glacier.vm" "Evm". + +Axiom ethereum_muir_glacier_vm_exceptions_imports_OutOfGasError : + IsImported globals "ethereum.muir_glacier.vm.exceptions" "OutOfGasError". + +Definition GAS_JUMPDEST : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 1 + ], + make_dict [] + |) +)). + +Definition GAS_BASE : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 2 + ], + make_dict [] + |) +)). + +Definition GAS_VERY_LOW : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 3 + ], + make_dict [] + |) +)). + +Definition GAS_SLOAD : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 800 + ], + make_dict [] + |) +)). + +Definition GAS_STORAGE_SET : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 20000 + ], + make_dict [] + |) +)). + +Definition GAS_STORAGE_UPDATE : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 5000 + ], + make_dict [] + |) +)). + +Definition GAS_STORAGE_CLEAR_REFUND : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 15000 + ], + make_dict [] + |) +)). + +Definition GAS_LOW : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 5 + ], + make_dict [] + |) +)). + +Definition GAS_MID : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 8 + ], + make_dict [] + |) +)). + +Definition GAS_HIGH : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 10 + ], + make_dict [] + |) +)). + +Definition GAS_EXPONENTIATION : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 10 + ], + make_dict [] + |) +)). + +Definition GAS_EXPONENTIATION_PER_BYTE : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 50 + ], + make_dict [] + |) +)). + +Definition GAS_MEMORY : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 3 + ], + make_dict [] + |) +)). + +Definition GAS_KECCAK256 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 30 + ], + make_dict [] + |) +)). + +Definition GAS_KECCAK256_WORD : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 6 + ], + make_dict [] + |) +)). + +Definition GAS_COPY : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 3 + ], + make_dict [] + |) +)). + +Definition GAS_BLOCK_HASH : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 20 + ], + make_dict [] + |) +)). + +Definition GAS_EXTERNAL : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 700 + ], + make_dict [] + |) +)). + +Definition GAS_BALANCE : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 700 + ], + make_dict [] + |) +)). + +Definition GAS_LOG : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 375 + ], + make_dict [] + |) +)). + +Definition GAS_LOG_DATA : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 8 + ], + make_dict [] + |) +)). + +Definition GAS_LOG_TOPIC : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 375 + ], + make_dict [] + |) +)). + +Definition GAS_CREATE : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 32000 + ], + make_dict [] + |) +)). + +Definition GAS_CODE_DEPOSIT : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 200 + ], + make_dict [] + |) +)). + +Definition GAS_ZERO : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) +)). + +Definition GAS_CALL : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 700 + ], + make_dict [] + |) +)). + +Definition GAS_NEW_ACCOUNT : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 25000 + ], + make_dict [] + |) +)). + +Definition GAS_CALL_VALUE : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 9000 + ], + make_dict [] + |) +)). + +Definition GAS_CALL_STIPEND : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 2300 + ], + make_dict [] + |) +)). + +Definition GAS_SELF_DESTRUCT : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 5000 + ], + make_dict [] + |) +)). + +Definition GAS_SELF_DESTRUCT_NEW_ACCOUNT : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 25000 + ], + make_dict [] + |) +)). + +Definition REFUND_SELF_DESTRUCT : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 24000 + ], + make_dict [] + |) +)). + +Definition GAS_ECRECOVER : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 3000 + ], + make_dict [] + |) +)). + +Definition GAS_SHA256 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 60 + ], + make_dict [] + |) +)). + +Definition GAS_SHA256_WORD : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 12 + ], + make_dict [] + |) +)). + +Definition GAS_RIPEMD160 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 600 + ], + make_dict [] + |) +)). + +Definition GAS_RIPEMD160_WORD : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 120 + ], + make_dict [] + |) +)). + +Definition GAS_IDENTITY : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 15 + ], + make_dict [] + |) +)). + +Definition GAS_IDENTITY_WORD : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 3 + ], + make_dict [] + |) +)). + +Definition GAS_RETURN_DATA_COPY : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 3 + ], + make_dict [] + |) +)). + +Definition GAS_CODE_HASH : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 700 + ], + make_dict [] + |) +)). + +Definition GAS_FAST_STEP : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 5 + ], + make_dict [] + |) +)). + +Definition GAS_BLAKE2_PER_ROUND : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 1 + ], + make_dict [] + |) +)). + +Definition ExtendMemory : Value.t := + builtins.make_klass + [] + [ + + ] + [ + + ]. + +Definition MessageCallGas : Value.t := + builtins.make_klass + [] + [ + + ] + [ + + ]. + +Definition charge_gas : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm"; "amount" ] |) in + let _ := Constant.str " + Subtracts `amount` from `evm.gas_left`. + + Parameters + ---------- + evm : + The current EVM. + amount : + The amount of gas the current operation requires. + + " in + let _ := M.call (| + M.get_name (| globals, "evm_trace" |), + make_list [ + M.get_name (| globals, "evm" |); + M.call (| + M.get_name (| globals, "GasAndRefund" |), + make_list [ + M.get_name (| globals, "amount" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.lt (| + M.get_field (| M.get_name (| globals, "evm" |), "gas_left" |), + M.get_name (| globals, "amount" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, "OutOfGasError" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_op (| + BinOp.sub, + M.get_field (| M.get_name (| globals, "evm" |), "gas_left" |), + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + M.get_name (| globals, "amount" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_)). + +Definition calculate_memory_gas_cost : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "size_in_bytes" ] |) in + let _ := Constant.str " + Calculates the gas cost for allocating memory + to the smallest multiple of 32 bytes, + such that the allocated size is at least as big as the given size. + + Parameters + ---------- + size_in_bytes : + The size of the data in bytes. + + Returns + ------- + total_gas_cost : `ethereum.base_types.Uint` + The gas cost for storing data in memory. + " in + let _ := M.assign_local (| + "size_in_words" , + BinOp.floor_div (| + M.call (| + M.get_name (| globals, "ceil32" |), + make_list [ + M.get_name (| globals, "size_in_bytes" |) + ], + make_dict [] + |), + Constant.int 32 + |) + |) in + let _ := M.assign_local (| + "linear_cost" , + BinOp.mult (| + M.get_name (| globals, "size_in_words" |), + M.get_name (| globals, "GAS_MEMORY" |) + |) + |) in + let _ := M.assign_local (| + "quadratic_cost" , + BinOp.floor_div (| + BinOp.pow (| + M.get_name (| globals, "size_in_words" |), + Constant.int 2 + |), + Constant.int 512 + |) + |) in + let _ := M.assign_local (| + "total_gas_cost" , + BinOp.add (| + M.get_name (| globals, "linear_cost" |), + M.get_name (| globals, "quadratic_cost" |) + |) + |) in +(* At stmt: unsupported node type: Try *) + M.pure Constant.None_)). + +Definition calculate_gas_extend_memory : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "memory"; "extensions" ] |) in + let _ := Constant.str " + Calculates the gas amount to extend memory + + Parameters + ---------- + memory : + Memory contents of the EVM. + extensions: + List of extensions to be made to the memory. + Consists of a tuple of start position and size. + + Returns + ------- + extend_memory: `ExtendMemory` + " in + let _ := M.assign_local (| + "size_to_extend" , + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "to_be_paid" , + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "current_size" , + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_name (| globals, "memory" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := + M.for_ (| + make_tuple [ M.get_name (| globals, "start_position" |); M.get_name (| globals, "size" |) ], + M.get_name (| globals, "extensions" |), + ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, "size" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.continue (| |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "before_size" , + M.call (| + M.get_name (| globals, "ceil32" |), + make_list [ + M.get_name (| globals, "current_size" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "after_size" , + M.call (| + M.get_name (| globals, "ceil32" |), + make_list [ + BinOp.add (| + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.get_name (| globals, "start_position" |) + ], + make_dict [] + |), + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.get_name (| globals, "size" |) + ], + make_dict [] + |) + |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.lt_e (| + M.get_name (| globals, "after_size" |), + M.get_name (| globals, "before_size" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.continue (| |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_op_local (| + BinOp.add, + "size_to_extend", + BinOp.sub (| + M.get_name (| globals, "after_size" |), + M.get_name (| globals, "before_size" |) + |) + |) in + let _ := M.assign_local (| + "already_paid" , + M.call (| + M.get_name (| globals, "calculate_memory_gas_cost" |), + make_list [ + M.get_name (| globals, "before_size" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "total_cost" , + M.call (| + M.get_name (| globals, "calculate_memory_gas_cost" |), + make_list [ + M.get_name (| globals, "after_size" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_op_local (| + BinOp.add, + "to_be_paid", + BinOp.sub (| + M.get_name (| globals, "total_cost" |), + M.get_name (| globals, "already_paid" |) + |) + |) in + let _ := M.assign_local (| + "current_size" , + M.get_name (| globals, "after_size" |) + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, "ExtendMemory" |), + make_list [ + M.get_name (| globals, "to_be_paid" |); + M.get_name (| globals, "size_to_extend" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Definition calculate_message_call_gas : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "value"; "gas"; "gas_left"; "memory_cost"; "extra_gas"; "call_stipend" ] |) in + let _ := Constant.str " + Calculates the MessageCallGas (cost and stipend) for + executing call Opcodes. + + Parameters + ---------- + value: + The amount of `ETH` that needs to be transferred. + gas : + The amount of gas provided to the message-call. + gas_left : + The amount of gas left in the current frame. + memory_cost : + The amount needed to extend the memory in the current frame. + extra_gas : + The amount of gas needed for transferring value + creating a new + account inside a message call. + call_stipend : + The amount of stipend provided to a message call to execute code while + transferring value(ETH). + + Returns + ------- + message_call_gas: `MessageCallGas` + " in + let _ := M.assign_local (| + "call_stipend" , + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, "value" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( +M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + (* else *) + )), ltac:(M.monadic ( +M.get_name (| globals, "call_stipend" |) + )) |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.lt (| + M.get_name (| globals, "gas_left" |), + BinOp.add (| + M.get_name (| globals, "extra_gas" |), + M.get_name (| globals, "memory_cost" |) + |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + M.call (| + M.get_name (| globals, "MessageCallGas" |), + make_list [ + BinOp.add (| + M.get_name (| globals, "gas" |), + M.get_name (| globals, "extra_gas" |) + |); + BinOp.add (| + M.get_name (| globals, "gas" |), + M.get_name (| globals, "call_stipend" |) + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "gas" , + M.call (| + M.get_name (| globals, "min" |), + make_list [ + M.get_name (| globals, "gas" |); + M.call (| + M.get_name (| globals, "max_message_call_gas" |), + make_list [ + BinOp.sub (| + BinOp.sub (| + M.get_name (| globals, "gas_left" |), + M.get_name (| globals, "memory_cost" |) + |), + M.get_name (| globals, "extra_gas" |) + |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, "MessageCallGas" |), + make_list [ + BinOp.add (| + M.get_name (| globals, "gas" |), + M.get_name (| globals, "extra_gas" |) + |); + BinOp.add (| + M.get_name (| globals, "gas" |), + M.get_name (| globals, "call_stipend" |) + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Definition max_message_call_gas : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "gas" ] |) in + let _ := Constant.str " + Calculates the maximum gas that is allowed for making a message call + + Parameters + ---------- + gas : + The amount of gas provided to the message-call. + + Returns + ------- + max_allowed_message_call_gas: `ethereum.base_types.Uint` + The maximum gas allowed for making the message-call. + " in + let _ := M.return_ (| + BinOp.sub (| + M.get_name (| globals, "gas" |), + BinOp.floor_div (| + M.get_name (| globals, "gas" |), + Constant.int 64 + |) + |) + |) in + M.pure Constant.None_)). diff --git a/CoqOfPython/ethereum/muir_glacier/vm/instructions/__init__.v b/CoqOfPython/ethereum/muir_glacier/vm/instructions/__init__.v new file mode 100644 index 0000000..d7a2ea0 --- /dev/null +++ b/CoqOfPython/ethereum/muir_glacier/vm/instructions/__init__.v @@ -0,0 +1,74 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.muir_glacier.vm.instructions.__init__". + +Definition expr_1 : Value.t := + Constant.str " +EVM Instruction Encoding (Opcodes) +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Machine readable representations of EVM instructions, and a mapping to their +implementations. +". + +(* At top_level_stmt: unsupported node type: Import *) + +Axiom typing_imports_Callable : + IsImported globals "typing" "Callable". +Axiom typing_imports_Dict : + IsImported globals "typing" "Dict". + +Axiom ethereum_muir_glacier_vm_instructions_imports_arithmetic : + IsImported globals "ethereum.muir_glacier.vm.instructions" "arithmetic". + +Axiom ethereum_muir_glacier_vm_instructions_imports_bitwise : + IsImported globals "ethereum.muir_glacier.vm.instructions" "bitwise". + +Axiom ethereum_muir_glacier_vm_instructions_imports_block : + IsImported globals "ethereum.muir_glacier.vm.instructions" "block". + +Axiom ethereum_muir_glacier_vm_instructions_imports_comparison : + IsImported globals "ethereum.muir_glacier.vm.instructions" "comparison". + +Axiom ethereum_muir_glacier_vm_instructions_imports_control_flow : + IsImported globals "ethereum.muir_glacier.vm.instructions" "control_flow". + +Axiom ethereum_muir_glacier_vm_instructions_imports_environment : + IsImported globals "ethereum.muir_glacier.vm.instructions" "environment". + +Axiom ethereum_muir_glacier_vm_instructions_imports_keccak : + IsImported globals "ethereum.muir_glacier.vm.instructions" "keccak". + +Axiom ethereum_muir_glacier_vm_instructions_imports_log : + IsImported globals "ethereum.muir_glacier.vm.instructions" "log". + +Axiom ethereum_muir_glacier_vm_instructions_imports_memory : + IsImported globals "ethereum.muir_glacier.vm.instructions" "memory". + +Axiom ethereum_muir_glacier_vm_instructions_imports_stack : + IsImported globals "ethereum.muir_glacier.vm.instructions" "stack". + +Axiom ethereum_muir_glacier_vm_instructions_imports_storage : + IsImported globals "ethereum.muir_glacier.vm.instructions" "storage". + +Axiom ethereum_muir_glacier_vm_instructions_imports_system : + IsImported globals "ethereum.muir_glacier.vm.instructions" "system". + +Definition Ops : Value.t := + builtins.make_klass + [(* At base: unsupported node type: Attribute *)] + [ + + ] + [ + + ]. + +(* At top_level_stmt: unsupported node type: AnnAssign *) diff --git a/CoqOfPython/ethereum/muir_glacier/vm/instructions/arithmetic.v b/CoqOfPython/ethereum/muir_glacier/vm/instructions/arithmetic.v new file mode 100644 index 0000000..6e651f5 --- /dev/null +++ b/CoqOfPython/ethereum/muir_glacier/vm/instructions/arithmetic.v @@ -0,0 +1,1220 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.muir_glacier.vm.instructions.arithmetic". + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) Arithmetic Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM Arithmetic instructions. +". + +Axiom ethereum_base_types_imports_U255_CEIL_VALUE : + IsImported globals "ethereum.base_types" "U255_CEIL_VALUE". +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_U256_CEIL_VALUE : + IsImported globals "ethereum.base_types" "U256_CEIL_VALUE". +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". + +Axiom ethereum_utils_numeric_imports_get_sign : + IsImported globals "ethereum.utils.numeric" "get_sign". + +Axiom ethereum_muir_glacier_vm_imports_Evm : + IsImported globals "ethereum.muir_glacier.vm" "Evm". + +Axiom ethereum_muir_glacier_vm_gas_imports_GAS_EXPONENTIATION : + IsImported globals "ethereum.muir_glacier.vm.gas" "GAS_EXPONENTIATION". +Axiom ethereum_muir_glacier_vm_gas_imports_GAS_EXPONENTIATION_PER_BYTE : + IsImported globals "ethereum.muir_glacier.vm.gas" "GAS_EXPONENTIATION_PER_BYTE". +Axiom ethereum_muir_glacier_vm_gas_imports_GAS_LOW : + IsImported globals "ethereum.muir_glacier.vm.gas" "GAS_LOW". +Axiom ethereum_muir_glacier_vm_gas_imports_GAS_MID : + IsImported globals "ethereum.muir_glacier.vm.gas" "GAS_MID". +Axiom ethereum_muir_glacier_vm_gas_imports_GAS_VERY_LOW : + IsImported globals "ethereum.muir_glacier.vm.gas" "GAS_VERY_LOW". +Axiom ethereum_muir_glacier_vm_gas_imports_charge_gas : + IsImported globals "ethereum.muir_glacier.vm.gas" "charge_gas". + +Axiom ethereum_muir_glacier_vm_stack_imports_pop : + IsImported globals "ethereum.muir_glacier.vm.stack" "pop". +Axiom ethereum_muir_glacier_vm_stack_imports_push : + IsImported globals "ethereum.muir_glacier.vm.stack" "push". + +Definition add : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Adds the top two elements of the stack together, and pushes the result back + on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "x" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "y" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_VERY_LOW" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "result" , + M.call (| + M.get_field (| M.get_name (| globals, "x" |), "wrapping_add" |), + make_list [ + M.get_name (| globals, "y" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.get_name (| globals, "result" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition sub : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Subtracts the top two elements of the stack, and pushes the result back + on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "x" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "y" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_VERY_LOW" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "result" , + M.call (| + M.get_field (| M.get_name (| globals, "x" |), "wrapping_sub" |), + make_list [ + M.get_name (| globals, "y" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.get_name (| globals, "result" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition mul : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Multiply the top two elements of the stack, and pushes the result back + on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "x" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "y" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_LOW" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "result" , + M.call (| + M.get_field (| M.get_name (| globals, "x" |), "wrapping_mul" |), + make_list [ + M.get_name (| globals, "y" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.get_name (| globals, "result" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition div : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Integer division of the top two elements of the stack. Pushes the result + back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "dividend" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "divisor" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_LOW" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, "divisor" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "quotient" , + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "quotient" , + BinOp.floor_div (| + M.get_name (| globals, "dividend" |), + M.get_name (| globals, "divisor" |) + |) + |) in + M.pure Constant.None_ + )) |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.get_name (| globals, "quotient" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition sdiv : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Signed integer division of the top two elements of the stack. Pushes the + result back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "dividend" , + M.call (| + M.get_field (| M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |), "to_signed" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "divisor" , + M.call (| + M.get_field (| M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |), "to_signed" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_LOW" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, "divisor" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "quotient" , + Constant.int 0 + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + BoolOp.and (| + Compare.eq (| + M.get_name (| globals, "dividend" |), + UnOp.sub (| M.get_name (| globals, "U255_CEIL_VALUE" |) |) + |), + ltac:(M.monadic ( + Compare.eq (| + M.get_name (| globals, "divisor" |), + UnOp.sub (| Constant.int 1 |) + |) + )) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "quotient" , + UnOp.sub (| M.get_name (| globals, "U255_CEIL_VALUE" |) |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "sign" , + M.call (| + M.get_name (| globals, "get_sign" |), + make_list [ + BinOp.mult (| + M.get_name (| globals, "dividend" |), + M.get_name (| globals, "divisor" |) + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "quotient" , + BinOp.mult (| + M.get_name (| globals, "sign" |), + BinOp.floor_div (| + M.call (| + M.get_name (| globals, "abs" |), + make_list [ + M.get_name (| globals, "dividend" |) + ], + make_dict [] + |), + M.call (| + M.get_name (| globals, "abs" |), + make_list [ + M.get_name (| globals, "divisor" |) + ], + make_dict [] + |) + |) + |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )) |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.call (| + M.get_field (| M.get_name (| globals, "U256" |), "from_signed" |), + make_list [ + M.get_name (| globals, "quotient" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition mod_ : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Modulo remainder of the top two elements of the stack. Pushes the result + back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "x" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "y" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_LOW" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, "y" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "remainder" , + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "remainder" , + BinOp.mod_ (| + M.get_name (| globals, "x" |), + M.get_name (| globals, "y" |) + |) + |) in + M.pure Constant.None_ + )) |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.get_name (| globals, "remainder" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition smod : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Signed modulo remainder of the top two elements of the stack. Pushes the + result back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "x" , + M.call (| + M.get_field (| M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |), "to_signed" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "y" , + M.call (| + M.get_field (| M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |), "to_signed" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_LOW" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, "y" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "remainder" , + Constant.int 0 + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "remainder" , + BinOp.mult (| + M.call (| + M.get_name (| globals, "get_sign" |), + make_list [ + M.get_name (| globals, "x" |) + ], + make_dict [] + |), + BinOp.mod_ (| + M.call (| + M.get_name (| globals, "abs" |), + make_list [ + M.get_name (| globals, "x" |) + ], + make_dict [] + |), + M.call (| + M.get_name (| globals, "abs" |), + make_list [ + M.get_name (| globals, "y" |) + ], + make_dict [] + |) + |) + |) + |) in + M.pure Constant.None_ + )) |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.call (| + M.get_field (| M.get_name (| globals, "U256" |), "from_signed" |), + make_list [ + M.get_name (| globals, "remainder" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition addmod : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Modulo addition of the top 2 elements with the 3rd element. Pushes the + result back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "x" , + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "y" , + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "z" , + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_MID" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, "z" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "result" , + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "result" , + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + BinOp.mod_ (| + BinOp.add (| + M.get_name (| globals, "x" |), + M.get_name (| globals, "y" |) + |), + M.get_name (| globals, "z" |) + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + )) |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.get_name (| globals, "result" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition mulmod : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Modulo multiplication of the top 2 elements with the 3rd element. Pushes + the result back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "x" , + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "y" , + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "z" , + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_MID" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, "z" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "result" , + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "result" , + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + BinOp.mod_ (| + BinOp.mult (| + M.get_name (| globals, "x" |), + M.get_name (| globals, "y" |) + |), + M.get_name (| globals, "z" |) + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + )) |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.get_name (| globals, "result" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition exp : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Exponential operation of the top 2 elements. Pushes the result back on + the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "base" , + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "exponent" , + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "exponent_bits" , + M.call (| + M.get_field (| M.get_name (| globals, "exponent" |), "bit_length" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "exponent_bytes" , + BinOp.floor_div (| + BinOp.add (| + M.get_name (| globals, "exponent_bits" |), + Constant.int 7 + |), + Constant.int 8 + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + BinOp.add (| + M.get_name (| globals, "GAS_EXPONENTIATION" |), + BinOp.mult (| + M.get_name (| globals, "GAS_EXPONENTIATION_PER_BYTE" |), + M.get_name (| globals, "exponent_bytes" |) + |) + |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "result" , + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + M.call (| + M.get_name (| globals, "pow" |), + make_list [ + M.get_name (| globals, "base" |); + M.get_name (| globals, "exponent" |); + M.get_name (| globals, "U256_CEIL_VALUE" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.get_name (| globals, "result" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition signextend : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Sign extend operation. In other words, extend a signed number which + fits in N bytes to 32 bytes. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "byte_num" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "value" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_LOW" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.gt (| + M.get_name (| globals, "byte_num" |), + Constant.int 31 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "result" , + M.get_name (| globals, "value" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "value_bytes" , + M.call (| + M.get_name (| globals, "bytes" |), + make_list [ + M.call (| + M.get_field (| M.get_name (| globals, "value" |), "to_be_bytes32" |), + make_list [], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "value_bytes" , + M.slice (| + M.get_name (| globals, "value_bytes" |), + BinOp.sub (| + Constant.int 31, + M.call (| + M.get_name (| globals, "int" |), + make_list [ + M.get_name (| globals, "byte_num" |) + ], + make_dict [] + |) + |), + Constant.None_, + Constant.None_ + |) + |) in + let _ := M.assign_local (| + "sign_bit" , + BinOp.r_shift (| + M.get_subscript (| + M.get_name (| globals, "value_bytes" |), + Constant.int 0 + |), + Constant.int 7 + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, "sign_bit" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "result" , + M.call (| + M.get_field (| M.get_name (| globals, "U256" |), "from_be_bytes" |), + make_list [ + M.get_name (| globals, "value_bytes" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "num_bytes_prepend" , + BinOp.sub (| + Constant.int 32, + BinOp.add (| + M.get_name (| globals, "byte_num" |), + Constant.int 1 + |) + |) + |) in + let _ := M.assign_local (| + "result" , + M.call (| + M.get_field (| M.get_name (| globals, "U256" |), "from_be_bytes" |), + make_list [ + BinOp.add (| + M.call (| + M.get_name (| globals, "bytearray" |), + make_list [ + BinOp.mult (| + make_list [ + Constant.int 255 + ], + M.get_name (| globals, "num_bytes_prepend" |) + |) + ], + make_dict [] + |), + M.get_name (| globals, "value_bytes" |) + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )) |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.get_name (| globals, "result" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). diff --git a/CoqOfPython/ethereum/muir_glacier/vm/instructions/bitwise.v b/CoqOfPython/ethereum/muir_glacier/vm/instructions/bitwise.v new file mode 100644 index 0000000..7fff3d6 --- /dev/null +++ b/CoqOfPython/ethereum/muir_glacier/vm/instructions/bitwise.v @@ -0,0 +1,666 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.muir_glacier.vm.instructions.bitwise". + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) Bitwise Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM bitwise instructions. +". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_U256_CEIL_VALUE : + IsImported globals "ethereum.base_types" "U256_CEIL_VALUE". + +Axiom ethereum_muir_glacier_vm_imports_Evm : + IsImported globals "ethereum.muir_glacier.vm" "Evm". + +Axiom ethereum_muir_glacier_vm_gas_imports_GAS_VERY_LOW : + IsImported globals "ethereum.muir_glacier.vm.gas" "GAS_VERY_LOW". +Axiom ethereum_muir_glacier_vm_gas_imports_charge_gas : + IsImported globals "ethereum.muir_glacier.vm.gas" "charge_gas". + +Axiom ethereum_muir_glacier_vm_stack_imports_pop : + IsImported globals "ethereum.muir_glacier.vm.stack" "pop". +Axiom ethereum_muir_glacier_vm_stack_imports_push : + IsImported globals "ethereum.muir_glacier.vm.stack" "push". + +Definition bitwise_and : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Bitwise AND operation of the top 2 elements of the stack. Pushes the + result back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "x" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "y" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_VERY_LOW" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + BinOp.bit_and (| + M.get_name (| globals, "x" |), + M.get_name (| globals, "y" |) + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition bitwise_or : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Bitwise OR operation of the top 2 elements of the stack. Pushes the + result back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "x" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "y" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_VERY_LOW" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + BinOp.bit_or (| + M.get_name (| globals, "x" |), + M.get_name (| globals, "y" |) + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition bitwise_xor : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Bitwise XOR operation of the top 2 elements of the stack. Pushes the + result back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "x" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "y" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_VERY_LOW" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + BinOp.bit_xor (| + M.get_name (| globals, "x" |), + M.get_name (| globals, "y" |) + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition bitwise_not : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Bitwise NOT operation of the top element of the stack. Pushes the + result back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "x" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_VERY_LOW" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + UnOp.invert (| M.get_name (| globals, "x" |) |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition get_byte : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + For a word (defined by next top element of the stack), retrieve the + Nth byte (0-indexed and defined by top element of stack) from the + left (most significant) to right (least significant). + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "byte_index" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "word" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_VERY_LOW" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.gt_e (| + M.get_name (| globals, "byte_index" |), + Constant.int 32 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "result" , + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "extra_bytes_to_right" , + BinOp.sub (| + Constant.int 31, + M.get_name (| globals, "byte_index" |) + |) + |) in + let _ := M.assign_local (| + "word" , + BinOp.r_shift (| + M.get_name (| globals, "word" |), + BinOp.mult (| + M.get_name (| globals, "extra_bytes_to_right" |), + Constant.int 8 + |) + |) + |) in + let _ := M.assign_local (| + "word" , + BinOp.bit_and (| + M.get_name (| globals, "word" |), + Constant.int 255 + |) + |) in + let _ := M.assign_local (| + "result" , + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + M.get_name (| globals, "word" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + )) |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.get_name (| globals, "result" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition bitwise_shl : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Logical shift left (SHL) operation of the top 2 elements of the stack. + Pushes the result back on the stack. + Parameters + ---------- + evm : + The current EVM frame. + " in + let _ := M.assign_local (| + "shift" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "value" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_VERY_LOW" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.lt (| + M.get_name (| globals, "shift" |), + Constant.int 256 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "result" , + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + BinOp.mod_ (| + BinOp.l_shift (| + M.get_name (| globals, "value" |), + M.get_name (| globals, "shift" |) + |), + M.get_name (| globals, "U256_CEIL_VALUE" |) + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "result" , + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + )) |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.get_name (| globals, "result" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition bitwise_shr : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Logical shift right (SHR) operation of the top 2 elements of the stack. + Pushes the result back on the stack. + Parameters + ---------- + evm : + The current EVM frame. + " in + let _ := M.assign_local (| + "shift" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "value" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_VERY_LOW" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.lt (| + M.get_name (| globals, "shift" |), + Constant.int 256 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "result" , + BinOp.r_shift (| + M.get_name (| globals, "value" |), + M.get_name (| globals, "shift" |) + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "result" , + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + )) |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.get_name (| globals, "result" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition bitwise_sar : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Arithmetic shift right (SAR) operation of the top 2 elements of the stack. + Pushes the result back on the stack. + Parameters + ---------- + evm : + The current EVM frame. + " in + let _ := M.assign_local (| + "shift" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "signed_value" , + M.call (| + M.get_field (| M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |), "to_signed" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_VERY_LOW" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.lt (| + M.get_name (| globals, "shift" |), + Constant.int 256 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "result" , + M.call (| + M.get_field (| M.get_name (| globals, "U256" |), "from_signed" |), + make_list [ + BinOp.r_shift (| + M.get_name (| globals, "signed_value" |), + M.get_name (| globals, "shift" |) + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + Compare.gt_e (| + M.get_name (| globals, "signed_value" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "result" , + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "result" , + M.get_field (| M.get_name (| globals, "U256" |), "MAX_VALUE" |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )) |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.get_name (| globals, "result" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). diff --git a/CoqOfPython/ethereum/muir_glacier/vm/instructions/block.v b/CoqOfPython/ethereum/muir_glacier/vm/instructions/block.v new file mode 100644 index 0000000..167e4e0 --- /dev/null +++ b/CoqOfPython/ethereum/muir_glacier/vm/instructions/block.v @@ -0,0 +1,390 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.muir_glacier.vm.instructions.block". + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) Block Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM block instructions. +". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". + +Axiom ethereum_muir_glacier_vm_imports_Evm : + IsImported globals "ethereum.muir_glacier.vm" "Evm". + +Axiom ethereum_muir_glacier_vm_gas_imports_GAS_BASE : + IsImported globals "ethereum.muir_glacier.vm.gas" "GAS_BASE". +Axiom ethereum_muir_glacier_vm_gas_imports_GAS_BLOCK_HASH : + IsImported globals "ethereum.muir_glacier.vm.gas" "GAS_BLOCK_HASH". +Axiom ethereum_muir_glacier_vm_gas_imports_charge_gas : + IsImported globals "ethereum.muir_glacier.vm.gas" "charge_gas". + +Axiom ethereum_muir_glacier_vm_stack_imports_pop : + IsImported globals "ethereum.muir_glacier.vm.stack" "pop". +Axiom ethereum_muir_glacier_vm_stack_imports_push : + IsImported globals "ethereum.muir_glacier.vm.stack" "push". + +Definition block_hash : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Push the hash of one of the 256 most recent complete blocks onto the + stack. The block number to hash is present at the top of the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "block_number" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_BLOCK_HASH" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + BoolOp.or (| + Compare.lt_e (| + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "env" |), "number" |), + M.get_name (| globals, "block_number" |) + |), + ltac:(M.monadic ( + Compare.gt (| + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "env" |), "number" |), + BinOp.add (| + M.get_name (| globals, "block_number" |), + Constant.int 256 + |) + |) + )) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "hash" , + Constant.bytes "00" + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "hash" , + M.get_subscript (| + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "env" |), "block_hashes" |), + UnOp.sub (| BinOp.sub (| + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "env" |), "number" |), + M.get_name (| globals, "block_number" |) + |) |) + |) + |) in + M.pure Constant.None_ + )) |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.call (| + M.get_field (| M.get_name (| globals, "U256" |), "from_be_bytes" |), + make_list [ + M.get_name (| globals, "hash" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition coinbase : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Push the current block's beneficiary address (address of the block miner) + onto the stack. + + Here the current block refers to the block in which the currently + executing transaction/call resides. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_BASE" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.call (| + M.get_field (| M.get_name (| globals, "U256" |), "from_be_bytes" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "env" |), "coinbase" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition timestamp : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Push the current block's timestamp onto the stack. Here the timestamp + being referred is actually the unix timestamp in seconds. + + Here the current block refers to the block in which the currently + executing transaction/call resides. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_BASE" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "env" |), "time" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition number : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Push the current block's number onto the stack. + + Here the current block refers to the block in which the currently + executing transaction/call resides. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_BASE" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "env" |), "number" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition difficulty : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Push the current block's difficulty onto the stack. + + Here the current block refers to the block in which the currently + executing transaction/call resides. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_BASE" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "env" |), "difficulty" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition gas_limit : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Push the current block's gas limit onto the stack. + + Here the current block refers to the block in which the currently + executing transaction/call resides. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_BASE" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "env" |), "gas_limit" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition chain_id : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Push the chain id onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_BASE" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "env" |), "chain_id" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). diff --git a/CoqOfPython/ethereum/muir_glacier/vm/instructions/comparison.v b/CoqOfPython/ethereum/muir_glacier/vm/instructions/comparison.v new file mode 100644 index 0000000..63bffa3 --- /dev/null +++ b/CoqOfPython/ethereum/muir_glacier/vm/instructions/comparison.v @@ -0,0 +1,452 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.muir_glacier.vm.instructions.comparison". + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) Comparison Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM Comparison instructions. +". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". + +Axiom ethereum_muir_glacier_vm_imports_Evm : + IsImported globals "ethereum.muir_glacier.vm" "Evm". + +Axiom ethereum_muir_glacier_vm_gas_imports_GAS_VERY_LOW : + IsImported globals "ethereum.muir_glacier.vm.gas" "GAS_VERY_LOW". +Axiom ethereum_muir_glacier_vm_gas_imports_charge_gas : + IsImported globals "ethereum.muir_glacier.vm.gas" "charge_gas". + +Axiom ethereum_muir_glacier_vm_stack_imports_pop : + IsImported globals "ethereum.muir_glacier.vm.stack" "pop". +Axiom ethereum_muir_glacier_vm_stack_imports_push : + IsImported globals "ethereum.muir_glacier.vm.stack" "push". + +Definition less_than : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Checks if the top element is less than the next top element. Pushes the + result back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "left" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "right" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_VERY_LOW" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "result" , + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Compare.lt (| + M.get_name (| globals, "left" |), + M.get_name (| globals, "right" |) + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.get_name (| globals, "result" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition signed_less_than : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Signed less-than comparison. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "left" , + M.call (| + M.get_field (| M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |), "to_signed" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "right" , + M.call (| + M.get_field (| M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |), "to_signed" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_VERY_LOW" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "result" , + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Compare.lt (| + M.get_name (| globals, "left" |), + M.get_name (| globals, "right" |) + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.get_name (| globals, "result" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition greater_than : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Checks if the top element is greater than the next top element. Pushes + the result back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "left" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "right" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_VERY_LOW" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "result" , + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Compare.gt (| + M.get_name (| globals, "left" |), + M.get_name (| globals, "right" |) + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.get_name (| globals, "result" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition signed_greater_than : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Signed greater-than comparison. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "left" , + M.call (| + M.get_field (| M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |), "to_signed" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "right" , + M.call (| + M.get_field (| M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |), "to_signed" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_VERY_LOW" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "result" , + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Compare.gt (| + M.get_name (| globals, "left" |), + M.get_name (| globals, "right" |) + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.get_name (| globals, "result" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition equal : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Checks if the top element is equal to the next top element. Pushes + the result back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "left" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "right" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_VERY_LOW" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "result" , + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Compare.eq (| + M.get_name (| globals, "left" |), + M.get_name (| globals, "right" |) + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.get_name (| globals, "result" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition is_zero : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Checks if the top element is equal to 0. Pushes the result back on the + stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "x" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_VERY_LOW" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "result" , + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Compare.eq (| + M.get_name (| globals, "x" |), + Constant.int 0 + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.get_name (| globals, "result" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). diff --git a/CoqOfPython/ethereum/muir_glacier/vm/instructions/control_flow.v b/CoqOfPython/ethereum/muir_glacier/vm/instructions/control_flow.v new file mode 100644 index 0000000..50f5c02 --- /dev/null +++ b/CoqOfPython/ethereum/muir_glacier/vm/instructions/control_flow.v @@ -0,0 +1,350 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.muir_glacier.vm.instructions.control_flow". + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) Control Flow Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM control flow instructions. +". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". + +Axiom ethereum_muir_glacier_vm_gas_imports_GAS_BASE : + IsImported globals "ethereum.muir_glacier.vm.gas" "GAS_BASE". +Axiom ethereum_muir_glacier_vm_gas_imports_GAS_HIGH : + IsImported globals "ethereum.muir_glacier.vm.gas" "GAS_HIGH". +Axiom ethereum_muir_glacier_vm_gas_imports_GAS_JUMPDEST : + IsImported globals "ethereum.muir_glacier.vm.gas" "GAS_JUMPDEST". +Axiom ethereum_muir_glacier_vm_gas_imports_GAS_MID : + IsImported globals "ethereum.muir_glacier.vm.gas" "GAS_MID". +Axiom ethereum_muir_glacier_vm_gas_imports_charge_gas : + IsImported globals "ethereum.muir_glacier.vm.gas" "charge_gas". + +Axiom ethereum_muir_glacier_vm_imports_Evm : + IsImported globals "ethereum.muir_glacier.vm" "Evm". + +Axiom ethereum_muir_glacier_vm_exceptions_imports_InvalidJumpDestError : + IsImported globals "ethereum.muir_glacier.vm.exceptions" "InvalidJumpDestError". + +Axiom ethereum_muir_glacier_vm_stack_imports_pop : + IsImported globals "ethereum.muir_glacier.vm.stack" "pop". +Axiom ethereum_muir_glacier_vm_stack_imports_push : + IsImported globals "ethereum.muir_glacier.vm.stack" "push". + +Definition stop : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Stop further execution of EVM code. + + Parameters + ---------- + evm : + The current EVM frame. + " in + let _ := M.pass (| |) in + let _ := M.pass (| |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, "evm" |), "running" |), + Constant.bool false + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition jump : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Alter the program counter to the location specified by the top of the + stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "jump_dest" , + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_MID" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.not_in (| + M.get_name (| globals, "jump_dest" |), + M.get_field (| M.get_name (| globals, "evm" |), "valid_jump_destinations" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, "InvalidJumpDestError" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.get_name (| globals, "jump_dest" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Definition jumpi : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Alter the program counter to the specified location if and only if a + condition is true. If the condition is not true, then the program counter + would increase only by 1. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "jump_dest" , + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "conditional_value" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_HIGH" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, "conditional_value" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "destination" , + BinOp.add (| + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + Compare.not_in (| + M.get_name (| globals, "jump_dest" |), + M.get_field (| M.get_name (| globals, "evm" |), "valid_jump_destinations" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, "InvalidJumpDestError" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "destination" , + M.get_name (| globals, "jump_dest" |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )) |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.get_name (| globals, "destination" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Definition pc : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Push onto the stack the value of the program counter after reaching the + current instruction and without increasing it for the next instruction. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_BASE" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "pc" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition gas_left : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Push the amount of available gas (including the corresponding reduction + for the cost of this instruction) onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_BASE" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "gas_left" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition jumpdest : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Mark a valid destination for jumps. This is a noop, present only + to be used by `JUMP` and `JUMPI` opcodes to verify that their jump is + valid. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_JUMPDEST" |) + ], + make_dict [] + |) in + let _ := M.pass (| |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). diff --git a/CoqOfPython/ethereum/muir_glacier/vm/instructions/environment.v b/CoqOfPython/ethereum/muir_glacier/vm/instructions/environment.v new file mode 100644 index 0000000..dc3f915 --- /dev/null +++ b/CoqOfPython/ethereum/muir_glacier/vm/instructions/environment.v @@ -0,0 +1,1367 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.muir_glacier.vm.instructions.environment". + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) Environmental Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM environment related instructions. +". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". + +Axiom ethereum_crypto_hash_imports_keccak256 : + IsImported globals "ethereum.crypto.hash" "keccak256". + +Axiom ethereum_utils_ensure_imports_ensure : + IsImported globals "ethereum.utils.ensure" "ensure". + +Axiom ethereum_utils_numeric_imports_ceil32 : + IsImported globals "ethereum.utils.numeric" "ceil32". + +Axiom ethereum_muir_glacier_fork_types_imports_EMPTY_ACCOUNT : + IsImported globals "ethereum.muir_glacier.fork_types" "EMPTY_ACCOUNT". + +Axiom ethereum_muir_glacier_state_imports_get_account : + IsImported globals "ethereum.muir_glacier.state" "get_account". + +Axiom ethereum_muir_glacier_utils_address_imports_to_address : + IsImported globals "ethereum.muir_glacier.utils.address" "to_address". + +Axiom ethereum_muir_glacier_vm_memory_imports_buffer_read : + IsImported globals "ethereum.muir_glacier.vm.memory" "buffer_read". +Axiom ethereum_muir_glacier_vm_memory_imports_memory_write : + IsImported globals "ethereum.muir_glacier.vm.memory" "memory_write". + +Axiom ethereum_muir_glacier_vm_imports_Evm : + IsImported globals "ethereum.muir_glacier.vm" "Evm". + +Axiom ethereum_muir_glacier_vm_exceptions_imports_OutOfBoundsRead : + IsImported globals "ethereum.muir_glacier.vm.exceptions" "OutOfBoundsRead". + +Axiom ethereum_muir_glacier_vm_gas_imports_GAS_BALANCE : + IsImported globals "ethereum.muir_glacier.vm.gas" "GAS_BALANCE". +Axiom ethereum_muir_glacier_vm_gas_imports_GAS_BASE : + IsImported globals "ethereum.muir_glacier.vm.gas" "GAS_BASE". +Axiom ethereum_muir_glacier_vm_gas_imports_GAS_CODE_HASH : + IsImported globals "ethereum.muir_glacier.vm.gas" "GAS_CODE_HASH". +Axiom ethereum_muir_glacier_vm_gas_imports_GAS_COPY : + IsImported globals "ethereum.muir_glacier.vm.gas" "GAS_COPY". +Axiom ethereum_muir_glacier_vm_gas_imports_GAS_EXTERNAL : + IsImported globals "ethereum.muir_glacier.vm.gas" "GAS_EXTERNAL". +Axiom ethereum_muir_glacier_vm_gas_imports_GAS_FAST_STEP : + IsImported globals "ethereum.muir_glacier.vm.gas" "GAS_FAST_STEP". +Axiom ethereum_muir_glacier_vm_gas_imports_GAS_RETURN_DATA_COPY : + IsImported globals "ethereum.muir_glacier.vm.gas" "GAS_RETURN_DATA_COPY". +Axiom ethereum_muir_glacier_vm_gas_imports_GAS_VERY_LOW : + IsImported globals "ethereum.muir_glacier.vm.gas" "GAS_VERY_LOW". +Axiom ethereum_muir_glacier_vm_gas_imports_calculate_gas_extend_memory : + IsImported globals "ethereum.muir_glacier.vm.gas" "calculate_gas_extend_memory". +Axiom ethereum_muir_glacier_vm_gas_imports_charge_gas : + IsImported globals "ethereum.muir_glacier.vm.gas" "charge_gas". + +Axiom ethereum_muir_glacier_vm_stack_imports_pop : + IsImported globals "ethereum.muir_glacier.vm.stack" "pop". +Axiom ethereum_muir_glacier_vm_stack_imports_push : + IsImported globals "ethereum.muir_glacier.vm.stack" "push". + +Definition address : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Pushes the address of the current executing account to the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_BASE" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.call (| + M.get_field (| M.get_name (| globals, "U256" |), "from_be_bytes" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "current_target" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition balance : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Pushes the balance of the given account onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "address" , + M.call (| + M.get_name (| globals, "to_address" |), + make_list [ + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_BALANCE" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "balance" , + M.get_field (| M.call (| + M.get_name (| globals, "get_account" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "env" |), "state" |); + M.get_name (| globals, "address" |) + ], + make_dict [] + |), "balance" |) + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.get_name (| globals, "balance" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition origin : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Pushes the address of the original transaction sender to the stack. + The origin address can only be an EOA. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_BASE" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.call (| + M.get_field (| M.get_name (| globals, "U256" |), "from_be_bytes" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "env" |), "origin" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition caller : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Pushes the address of the caller onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_BASE" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.call (| + M.get_field (| M.get_name (| globals, "U256" |), "from_be_bytes" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "caller" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition callvalue : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Push the value (in wei) sent with the call onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_BASE" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "value" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition calldataload : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Push a word (32 bytes) of the input data belonging to the current + environment onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "start_index" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_VERY_LOW" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "value" , + M.call (| + M.get_name (| globals, "buffer_read" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "data" |); + M.get_name (| globals, "start_index" |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 32 + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.call (| + M.get_field (| M.get_name (| globals, "U256" |), "from_be_bytes" |), + make_list [ + M.get_name (| globals, "value" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition calldatasize : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Push the size of input data in current environment onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_BASE" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "data" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition calldatacopy : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Copy a portion of the input data in current environment to memory. + + This will also expand the memory, in case that the memory is insufficient + to store the data. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "memory_start_index" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "data_start_index" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "size" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "words" , + BinOp.floor_div (| + M.call (| + M.get_name (| globals, "ceil32" |), + make_list [ + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.get_name (| globals, "size" |) + ], + make_dict [] + |) + ], + make_dict [] + |), + Constant.int 32 + |) + |) in + let _ := M.assign_local (| + "copy_gas_cost" , + BinOp.mult (| + M.get_name (| globals, "GAS_COPY" |), + M.get_name (| globals, "words" |) + |) + |) in + let _ := M.assign_local (| + "extend_memory" , + M.call (| + M.get_name (| globals, "calculate_gas_extend_memory" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "memory" |); + make_list [ + make_tuple [ M.get_name (| globals, "memory_start_index" |); M.get_name (| globals, "size" |) ] + ] + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + BinOp.add (| + BinOp.add (| + M.get_name (| globals, "GAS_VERY_LOW" |), + M.get_name (| globals, "copy_gas_cost" |) + |), + M.get_field (| M.get_name (| globals, "extend_memory" |), "cost" |) + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "memory" |), + BinOp.mult (| + Constant.bytes "00", + M.get_field (| M.get_name (| globals, "extend_memory" |), "expand_by" |) + |) + |) in + let _ := M.assign_local (| + "value" , + M.call (| + M.get_name (| globals, "buffer_read" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "data" |); + M.get_name (| globals, "data_start_index" |); + M.get_name (| globals, "size" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "memory_write" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "memory" |); + M.get_name (| globals, "memory_start_index" |); + M.get_name (| globals, "value" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition codesize : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Push the size of code running in current environment onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_BASE" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "code" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition codecopy : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Copy a portion of the code in current environment to memory. + + This will also expand the memory, in case that the memory is insufficient + to store the data. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "memory_start_index" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "code_start_index" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "size" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "words" , + BinOp.floor_div (| + M.call (| + M.get_name (| globals, "ceil32" |), + make_list [ + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.get_name (| globals, "size" |) + ], + make_dict [] + |) + ], + make_dict [] + |), + Constant.int 32 + |) + |) in + let _ := M.assign_local (| + "copy_gas_cost" , + BinOp.mult (| + M.get_name (| globals, "GAS_COPY" |), + M.get_name (| globals, "words" |) + |) + |) in + let _ := M.assign_local (| + "extend_memory" , + M.call (| + M.get_name (| globals, "calculate_gas_extend_memory" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "memory" |); + make_list [ + make_tuple [ M.get_name (| globals, "memory_start_index" |); M.get_name (| globals, "size" |) ] + ] + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + BinOp.add (| + BinOp.add (| + M.get_name (| globals, "GAS_VERY_LOW" |), + M.get_name (| globals, "copy_gas_cost" |) + |), + M.get_field (| M.get_name (| globals, "extend_memory" |), "cost" |) + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "memory" |), + BinOp.mult (| + Constant.bytes "00", + M.get_field (| M.get_name (| globals, "extend_memory" |), "expand_by" |) + |) + |) in + let _ := M.assign_local (| + "value" , + M.call (| + M.get_name (| globals, "buffer_read" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "code" |); + M.get_name (| globals, "code_start_index" |); + M.get_name (| globals, "size" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "memory_write" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "memory" |); + M.get_name (| globals, "memory_start_index" |); + M.get_name (| globals, "value" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition gasprice : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Push the gas price used in current environment onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_BASE" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "env" |), "gas_price" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition extcodesize : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Push the code size of a given account onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "address" , + M.call (| + M.get_name (| globals, "to_address" |), + make_list [ + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_EXTERNAL" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "codesize" , + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_field (| M.call (| + M.get_name (| globals, "get_account" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "env" |), "state" |); + M.get_name (| globals, "address" |) + ], + make_dict [] + |), "code" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.get_name (| globals, "codesize" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition extcodecopy : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Copy a portion of an account's code to memory. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "address" , + M.call (| + M.get_name (| globals, "to_address" |), + make_list [ + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_start_index" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "code_start_index" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "size" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "words" , + BinOp.floor_div (| + M.call (| + M.get_name (| globals, "ceil32" |), + make_list [ + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.get_name (| globals, "size" |) + ], + make_dict [] + |) + ], + make_dict [] + |), + Constant.int 32 + |) + |) in + let _ := M.assign_local (| + "copy_gas_cost" , + BinOp.mult (| + M.get_name (| globals, "GAS_COPY" |), + M.get_name (| globals, "words" |) + |) + |) in + let _ := M.assign_local (| + "extend_memory" , + M.call (| + M.get_name (| globals, "calculate_gas_extend_memory" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "memory" |); + make_list [ + make_tuple [ M.get_name (| globals, "memory_start_index" |); M.get_name (| globals, "size" |) ] + ] + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + BinOp.add (| + BinOp.add (| + M.get_name (| globals, "GAS_EXTERNAL" |), + M.get_name (| globals, "copy_gas_cost" |) + |), + M.get_field (| M.get_name (| globals, "extend_memory" |), "cost" |) + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "memory" |), + BinOp.mult (| + Constant.bytes "00", + M.get_field (| M.get_name (| globals, "extend_memory" |), "expand_by" |) + |) + |) in + let _ := M.assign_local (| + "code" , + M.get_field (| M.call (| + M.get_name (| globals, "get_account" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "env" |), "state" |); + M.get_name (| globals, "address" |) + ], + make_dict [] + |), "code" |) + |) in + let _ := M.assign_local (| + "value" , + M.call (| + M.get_name (| globals, "buffer_read" |), + make_list [ + M.get_name (| globals, "code" |); + M.get_name (| globals, "code_start_index" |); + M.get_name (| globals, "size" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "memory_write" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "memory" |); + M.get_name (| globals, "memory_start_index" |); + M.get_name (| globals, "value" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition returndatasize : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Pushes the size of the return data buffer onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_BASE" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "return_data" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition returndatacopy : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Copies data from the return data buffer code to memory + + Parameters + ---------- + evm : + The current EVM frame. + " in + let _ := M.assign_local (| + "memory_start_index" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "return_data_start_position" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "size" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "words" , + BinOp.floor_div (| + M.call (| + M.get_name (| globals, "ceil32" |), + make_list [ + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.get_name (| globals, "size" |) + ], + make_dict [] + |) + ], + make_dict [] + |), + Constant.int 32 + |) + |) in + let _ := M.assign_local (| + "copy_gas_cost" , + BinOp.mult (| + M.get_name (| globals, "GAS_RETURN_DATA_COPY" |), + M.get_name (| globals, "words" |) + |) + |) in + let _ := M.assign_local (| + "extend_memory" , + M.call (| + M.get_name (| globals, "calculate_gas_extend_memory" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "memory" |); + make_list [ + make_tuple [ M.get_name (| globals, "memory_start_index" |); M.get_name (| globals, "size" |) ] + ] + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + BinOp.add (| + BinOp.add (| + M.get_name (| globals, "GAS_VERY_LOW" |), + M.get_name (| globals, "copy_gas_cost" |) + |), + M.get_field (| M.get_name (| globals, "extend_memory" |), "cost" |) + |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + Compare.lt_e (| + BinOp.add (| + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.get_name (| globals, "return_data_start_position" |) + ], + make_dict [] + |), + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.get_name (| globals, "size" |) + ], + make_dict [] + |) + |), + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "return_data" |) + ], + make_dict [] + |) + |); + M.get_name (| globals, "OutOfBoundsRead" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "memory" |), + BinOp.mult (| + Constant.bytes "00", + M.get_field (| M.get_name (| globals, "extend_memory" |), "expand_by" |) + |) + |) in + let _ := M.assign_local (| + "value" , + M.slice (| + M.get_field (| M.get_name (| globals, "evm" |), "return_data" |), + M.get_name (| globals, "return_data_start_position" |), + BinOp.add (| + M.get_name (| globals, "return_data_start_position" |), + M.get_name (| globals, "size" |) + |), + Constant.None_ + |) + |) in + let _ := M.call (| + M.get_name (| globals, "memory_write" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "memory" |); + M.get_name (| globals, "memory_start_index" |); + M.get_name (| globals, "value" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition extcodehash : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Returns the keccak256 hash of a contract’s bytecode + Parameters + ---------- + evm : + The current EVM frame. + " in + let _ := M.assign_local (| + "address" , + M.call (| + M.get_name (| globals, "to_address" |), + make_list [ + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_CODE_HASH" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "account" , + M.call (| + M.get_name (| globals, "get_account" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "env" |), "state" |); + M.get_name (| globals, "address" |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, "account" |), + M.get_name (| globals, "EMPTY_ACCOUNT" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "codehash" , + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "codehash" , + M.call (| + M.get_field (| M.get_name (| globals, "U256" |), "from_be_bytes" |), + make_list [ + M.call (| + M.get_name (| globals, "keccak256" |), + make_list [ + M.get_field (| M.get_name (| globals, "account" |), "code" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + )) |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.get_name (| globals, "codehash" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition self_balance : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Pushes the balance of the current address to the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_FAST_STEP" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "balance" , + M.get_field (| M.call (| + M.get_name (| globals, "get_account" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "env" |), "state" |); + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "current_target" |) + ], + make_dict [] + |), "balance" |) + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.get_name (| globals, "balance" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). diff --git a/CoqOfPython/ethereum/muir_glacier/vm/instructions/keccak.v b/CoqOfPython/ethereum/muir_glacier/vm/instructions/keccak.v new file mode 100644 index 0000000..a317bc4 --- /dev/null +++ b/CoqOfPython/ethereum/muir_glacier/vm/instructions/keccak.v @@ -0,0 +1,188 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.muir_glacier.vm.instructions.keccak". + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) Keccak Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM keccak instructions. +". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". + +Axiom ethereum_crypto_hash_imports_keccak256 : + IsImported globals "ethereum.crypto.hash" "keccak256". + +Axiom ethereum_utils_numeric_imports_ceil32 : + IsImported globals "ethereum.utils.numeric" "ceil32". + +Axiom ethereum_muir_glacier_vm_imports_Evm : + IsImported globals "ethereum.muir_glacier.vm" "Evm". + +Axiom ethereum_muir_glacier_vm_gas_imports_GAS_KECCAK256 : + IsImported globals "ethereum.muir_glacier.vm.gas" "GAS_KECCAK256". +Axiom ethereum_muir_glacier_vm_gas_imports_GAS_KECCAK256_WORD : + IsImported globals "ethereum.muir_glacier.vm.gas" "GAS_KECCAK256_WORD". +Axiom ethereum_muir_glacier_vm_gas_imports_calculate_gas_extend_memory : + IsImported globals "ethereum.muir_glacier.vm.gas" "calculate_gas_extend_memory". +Axiom ethereum_muir_glacier_vm_gas_imports_charge_gas : + IsImported globals "ethereum.muir_glacier.vm.gas" "charge_gas". + +Axiom ethereum_muir_glacier_vm_memory_imports_memory_read_bytes : + IsImported globals "ethereum.muir_glacier.vm.memory" "memory_read_bytes". + +Axiom ethereum_muir_glacier_vm_stack_imports_pop : + IsImported globals "ethereum.muir_glacier.vm.stack" "pop". +Axiom ethereum_muir_glacier_vm_stack_imports_push : + IsImported globals "ethereum.muir_glacier.vm.stack" "push". + +Definition keccak : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Pushes to the stack the Keccak-256 hash of a region of memory. + + This also expands the memory, in case the memory is insufficient to + access the data's memory location. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "memory_start_index" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "size" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "words" , + BinOp.floor_div (| + M.call (| + M.get_name (| globals, "ceil32" |), + make_list [ + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.get_name (| globals, "size" |) + ], + make_dict [] + |) + ], + make_dict [] + |), + Constant.int 32 + |) + |) in + let _ := M.assign_local (| + "word_gas_cost" , + BinOp.mult (| + M.get_name (| globals, "GAS_KECCAK256_WORD" |), + M.get_name (| globals, "words" |) + |) + |) in + let _ := M.assign_local (| + "extend_memory" , + M.call (| + M.get_name (| globals, "calculate_gas_extend_memory" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "memory" |); + make_list [ + make_tuple [ M.get_name (| globals, "memory_start_index" |); M.get_name (| globals, "size" |) ] + ] + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + BinOp.add (| + BinOp.add (| + M.get_name (| globals, "GAS_KECCAK256" |), + M.get_name (| globals, "word_gas_cost" |) + |), + M.get_field (| M.get_name (| globals, "extend_memory" |), "cost" |) + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "memory" |), + BinOp.mult (| + Constant.bytes "00", + M.get_field (| M.get_name (| globals, "extend_memory" |), "expand_by" |) + |) + |) in + let _ := M.assign_local (| + "data" , + M.call (| + M.get_name (| globals, "memory_read_bytes" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "memory" |); + M.get_name (| globals, "memory_start_index" |); + M.get_name (| globals, "size" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "hash" , + M.call (| + M.get_name (| globals, "keccak256" |), + make_list [ + M.get_name (| globals, "data" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.call (| + M.get_field (| M.get_name (| globals, "U256" |), "from_be_bytes" |), + make_list [ + M.get_name (| globals, "hash" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). diff --git a/CoqOfPython/ethereum/muir_glacier/vm/instructions/log.v b/CoqOfPython/ethereum/muir_glacier/vm/instructions/log.v new file mode 100644 index 0000000..6d8d000 --- /dev/null +++ b/CoqOfPython/ethereum/muir_glacier/vm/instructions/log.v @@ -0,0 +1,256 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.muir_glacier.vm.instructions.log". + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) Logging Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM logging instructions. +". + +Axiom functools_imports_partial : + IsImported globals "functools" "partial". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". + +Axiom ethereum_utils_ensure_imports_ensure : + IsImported globals "ethereum.utils.ensure" "ensure". + +Axiom ethereum_muir_glacier_blocks_imports_Log : + IsImported globals "ethereum.muir_glacier.blocks" "Log". + +Axiom ethereum_muir_glacier_vm_imports_Evm : + IsImported globals "ethereum.muir_glacier.vm" "Evm". + +Axiom ethereum_muir_glacier_vm_exceptions_imports_WriteInStaticContext : + IsImported globals "ethereum.muir_glacier.vm.exceptions" "WriteInStaticContext". + +Axiom ethereum_muir_glacier_vm_gas_imports_GAS_LOG : + IsImported globals "ethereum.muir_glacier.vm.gas" "GAS_LOG". +Axiom ethereum_muir_glacier_vm_gas_imports_GAS_LOG_DATA : + IsImported globals "ethereum.muir_glacier.vm.gas" "GAS_LOG_DATA". +Axiom ethereum_muir_glacier_vm_gas_imports_GAS_LOG_TOPIC : + IsImported globals "ethereum.muir_glacier.vm.gas" "GAS_LOG_TOPIC". +Axiom ethereum_muir_glacier_vm_gas_imports_calculate_gas_extend_memory : + IsImported globals "ethereum.muir_glacier.vm.gas" "calculate_gas_extend_memory". +Axiom ethereum_muir_glacier_vm_gas_imports_charge_gas : + IsImported globals "ethereum.muir_glacier.vm.gas" "charge_gas". + +Axiom ethereum_muir_glacier_vm_memory_imports_memory_read_bytes : + IsImported globals "ethereum.muir_glacier.vm.memory" "memory_read_bytes". + +Axiom ethereum_muir_glacier_vm_stack_imports_pop : + IsImported globals "ethereum.muir_glacier.vm.stack" "pop". + +Definition log_n : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm"; "num_topics" ] |) in + let _ := Constant.str " + Appends a log entry, having `num_topics` topics, to the evm logs. + + This will also expand the memory if the data (required by the log entry) + corresponding to the memory is not accessible. + + Parameters + ---------- + evm : + The current EVM frame. + num_topics : + The number of topics to be included in the log entry. + + " in + let _ := M.assign_local (| + "memory_start_index" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "size" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "topics" , + make_list [] + |) in + let _ := + M.for_ (| + M.get_name (| globals, "_" |), + M.call (| + M.get_name (| globals, "range" |), + make_list [ + M.get_name (| globals, "num_topics" |) + ], + make_dict [] + |), + ltac:(M.monadic ( + let _ := M.assign_local (| + "topic" , + M.call (| + M.get_field (| M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |), "to_be_bytes32" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_field (| M.get_name (| globals, "topics" |), "append" |), + make_list [ + M.get_name (| globals, "topic" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := M.assign_local (| + "extend_memory" , + M.call (| + M.get_name (| globals, "calculate_gas_extend_memory" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "memory" |); + make_list [ + make_tuple [ M.get_name (| globals, "memory_start_index" |); M.get_name (| globals, "size" |) ] + ] + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + BinOp.add (| + BinOp.add (| + BinOp.add (| + M.get_name (| globals, "GAS_LOG" |), + BinOp.mult (| + M.get_name (| globals, "GAS_LOG_DATA" |), + M.get_name (| globals, "size" |) + |) + |), + BinOp.mult (| + M.get_name (| globals, "GAS_LOG_TOPIC" |), + M.get_name (| globals, "num_topics" |) + |) + |), + M.get_field (| M.get_name (| globals, "extend_memory" |), "cost" |) + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "memory" |), + BinOp.mult (| + Constant.bytes "00", + M.get_field (| M.get_name (| globals, "extend_memory" |), "expand_by" |) + |) + |) in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + UnOp.not (| M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "is_static" |) |); + M.get_name (| globals, "WriteInStaticContext" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "log_entry" , + M.call (| + M.get_name (| globals, "Log" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, "evm" |), "logs" |), + BinOp.add (| + M.get_field (| M.get_name (| globals, "evm" |), "logs" |), + make_tuple [ M.get_name (| globals, "log_entry" |) ] + |) + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition log0 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "log_n" |) + ], + make_dict [] + |) +)). + +Definition log1 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "log_n" |) + ], + make_dict [] + |) +)). + +Definition log2 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "log_n" |) + ], + make_dict [] + |) +)). + +Definition log3 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "log_n" |) + ], + make_dict [] + |) +)). + +Definition log4 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "log_n" |) + ], + make_dict [] + |) +)). diff --git a/CoqOfPython/ethereum/muir_glacier/vm/instructions/memory.v b/CoqOfPython/ethereum/muir_glacier/vm/instructions/memory.v new file mode 100644 index 0000000..c12ac45 --- /dev/null +++ b/CoqOfPython/ethereum/muir_glacier/vm/instructions/memory.v @@ -0,0 +1,393 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.muir_glacier.vm.instructions.memory". + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) Memory Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM Memory instructions. +". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_Bytes : + IsImported globals "ethereum.base_types" "Bytes". + +Axiom ethereum_muir_glacier_vm_imports_Evm : + IsImported globals "ethereum.muir_glacier.vm" "Evm". + +Axiom ethereum_muir_glacier_vm_gas_imports_GAS_BASE : + IsImported globals "ethereum.muir_glacier.vm.gas" "GAS_BASE". +Axiom ethereum_muir_glacier_vm_gas_imports_GAS_VERY_LOW : + IsImported globals "ethereum.muir_glacier.vm.gas" "GAS_VERY_LOW". +Axiom ethereum_muir_glacier_vm_gas_imports_calculate_gas_extend_memory : + IsImported globals "ethereum.muir_glacier.vm.gas" "calculate_gas_extend_memory". +Axiom ethereum_muir_glacier_vm_gas_imports_charge_gas : + IsImported globals "ethereum.muir_glacier.vm.gas" "charge_gas". + +Axiom ethereum_muir_glacier_vm_memory_imports_memory_read_bytes : + IsImported globals "ethereum.muir_glacier.vm.memory" "memory_read_bytes". +Axiom ethereum_muir_glacier_vm_memory_imports_memory_write : + IsImported globals "ethereum.muir_glacier.vm.memory" "memory_write". + +Axiom ethereum_muir_glacier_vm_stack_imports_pop : + IsImported globals "ethereum.muir_glacier.vm.stack" "pop". +Axiom ethereum_muir_glacier_vm_stack_imports_push : + IsImported globals "ethereum.muir_glacier.vm.stack" "push". + +Definition mstore : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Stores a word to memory. + This also expands the memory, if the memory is + insufficient to store the word. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "start_position" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "value" , + M.call (| + M.get_field (| M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |), "to_be_bytes32" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "extend_memory" , + M.call (| + M.get_name (| globals, "calculate_gas_extend_memory" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "memory" |); + make_list [ + make_tuple [ M.get_name (| globals, "start_position" |); M.call (| + M.get_name (| globals, "U256" |), + make_list [ + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_name (| globals, "value" |) + ], + make_dict [] + |) + ], + make_dict [] + |) ] + ] + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + BinOp.add (| + M.get_name (| globals, "GAS_VERY_LOW" |), + M.get_field (| M.get_name (| globals, "extend_memory" |), "cost" |) + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "memory" |), + BinOp.mult (| + Constant.bytes "00", + M.get_field (| M.get_name (| globals, "extend_memory" |), "expand_by" |) + |) + |) in + let _ := M.call (| + M.get_name (| globals, "memory_write" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "memory" |); + M.get_name (| globals, "start_position" |); + M.get_name (| globals, "value" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition mstore8 : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Stores a byte to memory. + This also expands the memory, if the memory is + insufficient to store the word. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "start_position" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "value" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "extend_memory" , + M.call (| + M.get_name (| globals, "calculate_gas_extend_memory" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "memory" |); + make_list [ + make_tuple [ M.get_name (| globals, "start_position" |); M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 1 + ], + make_dict [] + |) ] + ] + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + BinOp.add (| + M.get_name (| globals, "GAS_VERY_LOW" |), + M.get_field (| M.get_name (| globals, "extend_memory" |), "cost" |) + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "memory" |), + BinOp.mult (| + Constant.bytes "00", + M.get_field (| M.get_name (| globals, "extend_memory" |), "expand_by" |) + |) + |) in + let _ := M.assign_local (| + "normalized_bytes_value" , + M.call (| + M.get_name (| globals, "Bytes" |), + make_list [ + make_list [ + BinOp.bit_and (| + M.get_name (| globals, "value" |), + Constant.int 255 + |) + ] + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "memory_write" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "memory" |); + M.get_name (| globals, "start_position" |); + M.get_name (| globals, "normalized_bytes_value" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition mload : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Load word from memory. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "start_position" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "extend_memory" , + M.call (| + M.get_name (| globals, "calculate_gas_extend_memory" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "memory" |); + make_list [ + make_tuple [ M.get_name (| globals, "start_position" |); M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 32 + ], + make_dict [] + |) ] + ] + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + BinOp.add (| + M.get_name (| globals, "GAS_VERY_LOW" |), + M.get_field (| M.get_name (| globals, "extend_memory" |), "cost" |) + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "memory" |), + BinOp.mult (| + Constant.bytes "00", + M.get_field (| M.get_name (| globals, "extend_memory" |), "expand_by" |) + |) + |) in + let _ := M.assign_local (| + "value" , + M.call (| + M.get_field (| M.get_name (| globals, "U256" |), "from_be_bytes" |), + make_list [ + M.call (| + M.get_name (| globals, "memory_read_bytes" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "memory" |); + M.get_name (| globals, "start_position" |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 32 + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.get_name (| globals, "value" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition msize : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Push the size of active memory in bytes onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_BASE" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "memory" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). diff --git a/CoqOfPython/ethereum/muir_glacier/vm/instructions/stack.v b/CoqOfPython/ethereum/muir_glacier/vm/instructions/stack.v new file mode 100644 index 0000000..c20b432 --- /dev/null +++ b/CoqOfPython/ethereum/muir_glacier/vm/instructions/stack.v @@ -0,0 +1,947 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.muir_glacier.vm.instructions.stack". + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) Stack Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM stack related instructions. +". + +Axiom functools_imports_partial : + IsImported globals "functools" "partial". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". + +Axiom ethereum_utils_ensure_imports_ensure : + IsImported globals "ethereum.utils.ensure" "ensure". + +Axiom ethereum_muir_glacier_vm_imports_Evm : + IsImported globals "ethereum.muir_glacier.vm" "Evm". +Axiom ethereum_muir_glacier_vm_imports_stack : + IsImported globals "ethereum.muir_glacier.vm" "stack". + +Axiom ethereum_muir_glacier_vm_exceptions_imports_StackUnderflowError : + IsImported globals "ethereum.muir_glacier.vm.exceptions" "StackUnderflowError". + +Axiom ethereum_muir_glacier_vm_gas_imports_GAS_BASE : + IsImported globals "ethereum.muir_glacier.vm.gas" "GAS_BASE". +Axiom ethereum_muir_glacier_vm_gas_imports_GAS_VERY_LOW : + IsImported globals "ethereum.muir_glacier.vm.gas" "GAS_VERY_LOW". +Axiom ethereum_muir_glacier_vm_gas_imports_charge_gas : + IsImported globals "ethereum.muir_glacier.vm.gas" "charge_gas". + +Axiom ethereum_muir_glacier_vm_memory_imports_buffer_read : + IsImported globals "ethereum.muir_glacier.vm.memory" "buffer_read". + +Definition pop : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Remove item from stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.call (| + M.get_field (| M.get_name (| globals, "stack" |), "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_BASE" |) + ], + make_dict [] + |) in + let _ := M.pass (| |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition push_n : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm"; "num_bytes" ] |) in + let _ := Constant.str " + Pushes a N-byte immediate onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + num_bytes : + The number of immediate bytes to be read from the code and pushed to + the stack. + + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_VERY_LOW" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "data_to_push" , + M.call (| + M.get_field (| M.get_name (| globals, "U256" |), "from_be_bytes" |), + make_list [ + M.call (| + M.get_name (| globals, "buffer_read" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "code" |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + BinOp.add (| + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) + ], + make_dict [] + |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + M.get_name (| globals, "num_bytes" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_field (| M.get_name (| globals, "stack" |), "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.get_name (| globals, "data_to_push" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + BinOp.add (| + Constant.int 1, + M.get_name (| globals, "num_bytes" |) + |) + |) in + M.pure Constant.None_)). + +Definition dup_n : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm"; "item_number" ] |) in + let _ := Constant.str " + Duplicate the Nth stack item (from top of the stack) to the top of stack. + + Parameters + ---------- + evm : + The current EVM frame. + + item_number : + The stack item number (0-indexed from top of stack) to be duplicated + to the top of stack. + + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_VERY_LOW" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + Compare.lt (| + M.get_name (| globals, "item_number" |), + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |); + M.get_name (| globals, "StackUnderflowError" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "data_to_duplicate" , + M.get_subscript (| + M.get_field (| M.get_name (| globals, "evm" |), "stack" |), + BinOp.sub (| + BinOp.sub (| + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |), + Constant.int 1 + |), + M.get_name (| globals, "item_number" |) + |) + |) + |) in + let _ := M.call (| + M.get_field (| M.get_name (| globals, "stack" |), "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.get_name (| globals, "data_to_duplicate" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition swap_n : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm"; "item_number" ] |) in + let _ := Constant.str " + Swap the top and the `item_number` element of the stack, where + the top of the stack is position zero. + + If `item_number` is zero, this function does nothing (which should not be + possible, since there is no `SWAP0` instruction). + + Parameters + ---------- + evm : + The current EVM frame. + + item_number : + The stack item number (0-indexed from top of stack) to be swapped + with the top of stack element. + + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_VERY_LOW" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + Compare.lt (| + M.get_name (| globals, "item_number" |), + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |); + M.get_name (| globals, "StackUnderflowError" |) + ], + make_dict [] + |) in + let _ := M.assign (| + make_tuple [ M.get_subscript (| + M.get_field (| M.get_name (| globals, "evm" |), "stack" |), + UnOp.sub (| Constant.int 1 |) + |); M.get_subscript (| + M.get_field (| M.get_name (| globals, "evm" |), "stack" |), + BinOp.sub (| + UnOp.sub (| Constant.int 1 |), + M.get_name (| globals, "item_number" |) + |) + |) ], + make_tuple [ M.get_subscript (| + M.get_field (| M.get_name (| globals, "evm" |), "stack" |), + BinOp.sub (| + UnOp.sub (| Constant.int 1 |), + M.get_name (| globals, "item_number" |) + |) + |); M.get_subscript (| + M.get_field (| M.get_name (| globals, "evm" |), "stack" |), + UnOp.sub (| Constant.int 1 |) + |) ] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition push1 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push2 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push3 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push4 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push5 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push6 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push7 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push8 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push9 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push10 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push11 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push12 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push13 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push14 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push15 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push16 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push17 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push18 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push19 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push20 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push21 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push22 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push23 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push24 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push25 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push26 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push27 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push28 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push29 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push30 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push31 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push32 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "push_n" |) + ], + make_dict [] + |) +)). + +Definition dup1 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "dup_n" |) + ], + make_dict [] + |) +)). + +Definition dup2 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "dup_n" |) + ], + make_dict [] + |) +)). + +Definition dup3 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "dup_n" |) + ], + make_dict [] + |) +)). + +Definition dup4 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "dup_n" |) + ], + make_dict [] + |) +)). + +Definition dup5 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "dup_n" |) + ], + make_dict [] + |) +)). + +Definition dup6 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "dup_n" |) + ], + make_dict [] + |) +)). + +Definition dup7 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "dup_n" |) + ], + make_dict [] + |) +)). + +Definition dup8 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "dup_n" |) + ], + make_dict [] + |) +)). + +Definition dup9 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "dup_n" |) + ], + make_dict [] + |) +)). + +Definition dup10 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "dup_n" |) + ], + make_dict [] + |) +)). + +Definition dup11 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "dup_n" |) + ], + make_dict [] + |) +)). + +Definition dup12 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "dup_n" |) + ], + make_dict [] + |) +)). + +Definition dup13 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "dup_n" |) + ], + make_dict [] + |) +)). + +Definition dup14 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "dup_n" |) + ], + make_dict [] + |) +)). + +Definition dup15 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "dup_n" |) + ], + make_dict [] + |) +)). + +Definition dup16 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "dup_n" |) + ], + make_dict [] + |) +)). + +Definition swap1 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "swap_n" |) + ], + make_dict [] + |) +)). + +Definition swap2 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "swap_n" |) + ], + make_dict [] + |) +)). + +Definition swap3 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "swap_n" |) + ], + make_dict [] + |) +)). + +Definition swap4 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "swap_n" |) + ], + make_dict [] + |) +)). + +Definition swap5 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "swap_n" |) + ], + make_dict [] + |) +)). + +Definition swap6 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "swap_n" |) + ], + make_dict [] + |) +)). + +Definition swap7 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "swap_n" |) + ], + make_dict [] + |) +)). + +Definition swap8 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "swap_n" |) + ], + make_dict [] + |) +)). + +Definition swap9 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "swap_n" |) + ], + make_dict [] + |) +)). + +Definition swap10 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "swap_n" |) + ], + make_dict [] + |) +)). + +Definition swap11 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "swap_n" |) + ], + make_dict [] + |) +)). + +Definition swap12 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "swap_n" |) + ], + make_dict [] + |) +)). + +Definition swap13 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "swap_n" |) + ], + make_dict [] + |) +)). + +Definition swap14 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "swap_n" |) + ], + make_dict [] + |) +)). + +Definition swap15 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "swap_n" |) + ], + make_dict [] + |) +)). + +Definition swap16 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "swap_n" |) + ], + make_dict [] + |) +)). diff --git a/CoqOfPython/ethereum/muir_glacier/vm/instructions/storage.v b/CoqOfPython/ethereum/muir_glacier/vm/instructions/storage.v new file mode 100644 index 0000000..dd601c1 --- /dev/null +++ b/CoqOfPython/ethereum/muir_glacier/vm/instructions/storage.v @@ -0,0 +1,412 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.muir_glacier.vm.instructions.storage". + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) Storage Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM storage related instructions. +". + +Axiom ethereum_utils_ensure_imports_ensure : + IsImported globals "ethereum.utils.ensure" "ensure". + +Axiom ethereum_muir_glacier_state_imports_get_storage : + IsImported globals "ethereum.muir_glacier.state" "get_storage". +Axiom ethereum_muir_glacier_state_imports_get_storage_original : + IsImported globals "ethereum.muir_glacier.state" "get_storage_original". +Axiom ethereum_muir_glacier_state_imports_set_storage : + IsImported globals "ethereum.muir_glacier.state" "set_storage". + +Axiom ethereum_muir_glacier_vm_imports_Evm : + IsImported globals "ethereum.muir_glacier.vm" "Evm". + +Axiom ethereum_muir_glacier_vm_exceptions_imports_OutOfGasError : + IsImported globals "ethereum.muir_glacier.vm.exceptions" "OutOfGasError". +Axiom ethereum_muir_glacier_vm_exceptions_imports_WriteInStaticContext : + IsImported globals "ethereum.muir_glacier.vm.exceptions" "WriteInStaticContext". + +Axiom ethereum_muir_glacier_vm_gas_imports_GAS_CALL_STIPEND : + IsImported globals "ethereum.muir_glacier.vm.gas" "GAS_CALL_STIPEND". +Axiom ethereum_muir_glacier_vm_gas_imports_GAS_SLOAD : + IsImported globals "ethereum.muir_glacier.vm.gas" "GAS_SLOAD". +Axiom ethereum_muir_glacier_vm_gas_imports_GAS_STORAGE_CLEAR_REFUND : + IsImported globals "ethereum.muir_glacier.vm.gas" "GAS_STORAGE_CLEAR_REFUND". +Axiom ethereum_muir_glacier_vm_gas_imports_GAS_STORAGE_SET : + IsImported globals "ethereum.muir_glacier.vm.gas" "GAS_STORAGE_SET". +Axiom ethereum_muir_glacier_vm_gas_imports_GAS_STORAGE_UPDATE : + IsImported globals "ethereum.muir_glacier.vm.gas" "GAS_STORAGE_UPDATE". +Axiom ethereum_muir_glacier_vm_gas_imports_charge_gas : + IsImported globals "ethereum.muir_glacier.vm.gas" "charge_gas". + +Axiom ethereum_muir_glacier_vm_stack_imports_pop : + IsImported globals "ethereum.muir_glacier.vm.stack" "pop". +Axiom ethereum_muir_glacier_vm_stack_imports_push : + IsImported globals "ethereum.muir_glacier.vm.stack" "push". + +Definition sload : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Loads to the stack, the value corresponding to a certain key from the + storage of the current account. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "key" , + M.call (| + M.get_field (| M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |), "to_be_bytes32" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_SLOAD" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "value" , + M.call (| + M.get_name (| globals, "get_storage" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "env" |), "state" |); + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "current_target" |); + M.get_name (| globals, "key" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.get_name (| globals, "value" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition sstore : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Stores a value at a certain key in the current context's storage. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "key" , + M.call (| + M.get_field (| M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |), "to_be_bytes32" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "new_value" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + Compare.gt (| + M.get_field (| M.get_name (| globals, "evm" |), "gas_left" |), + M.get_name (| globals, "GAS_CALL_STIPEND" |) + |); + M.get_name (| globals, "OutOfGasError" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "original_value" , + M.call (| + M.get_name (| globals, "get_storage_original" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "env" |), "state" |); + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "current_target" |); + M.get_name (| globals, "key" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "current_value" , + M.call (| + M.get_name (| globals, "get_storage" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "env" |), "state" |); + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "current_target" |); + M.get_name (| globals, "key" |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + BoolOp.and (| + Compare.eq (| + M.get_name (| globals, "original_value" |), + M.get_name (| globals, "current_value" |) + |), + ltac:(M.monadic ( + Compare.not_eq (| + M.get_name (| globals, "current_value" |), + M.get_name (| globals, "new_value" |) + |) + )) + |), + (* then *) + ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, "original_value" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "gas_cost" , + M.get_name (| globals, "GAS_STORAGE_SET" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "gas_cost" , + M.get_name (| globals, "GAS_STORAGE_UPDATE" |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "gas_cost" , + M.get_name (| globals, "GAS_SLOAD" |) + |) in + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + Compare.not_eq (| + M.get_name (| globals, "current_value" |), + M.get_name (| globals, "new_value" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + BoolOp.and (| + Compare.not_eq (| + M.get_name (| globals, "original_value" |), + Constant.int 0 + |), + ltac:(M.monadic ( + BoolOp.and (| + Compare.not_eq (| + M.get_name (| globals, "current_value" |), + Constant.int 0 + |), + ltac:(M.monadic ( + Compare.eq (| + M.get_name (| globals, "new_value" |), + Constant.int 0 + |) + )) + |) + )) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "refund_counter" |), + M.call (| + M.get_name (| globals, "int" |), + make_list [ + M.get_name (| globals, "GAS_STORAGE_CLEAR_REFUND" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + BoolOp.and (| + Compare.not_eq (| + M.get_name (| globals, "original_value" |), + Constant.int 0 + |), + ltac:(M.monadic ( + Compare.eq (| + M.get_name (| globals, "current_value" |), + Constant.int 0 + |) + )) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_op (| + BinOp.sub, + M.get_field (| M.get_name (| globals, "evm" |), "refund_counter" |), + M.call (| + M.get_name (| globals, "int" |), + make_list [ + M.get_name (| globals, "GAS_STORAGE_CLEAR_REFUND" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, "original_value" |), + M.get_name (| globals, "new_value" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, "original_value" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "refund_counter" |), + M.call (| + M.get_name (| globals, "int" |), + make_list [ + BinOp.sub (| + M.get_name (| globals, "GAS_STORAGE_SET" |), + M.get_name (| globals, "GAS_SLOAD" |) + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "refund_counter" |), + M.call (| + M.get_name (| globals, "int" |), + make_list [ + BinOp.sub (| + M.get_name (| globals, "GAS_STORAGE_UPDATE" |), + M.get_name (| globals, "GAS_SLOAD" |) + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "gas_cost" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + UnOp.not (| M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "is_static" |) |); + M.get_name (| globals, "WriteInStaticContext" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "set_storage" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "env" |), "state" |); + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "current_target" |); + M.get_name (| globals, "key" |); + M.get_name (| globals, "new_value" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). diff --git a/CoqOfPython/ethereum/muir_glacier/vm/instructions/system.v b/CoqOfPython/ethereum/muir_glacier/vm/instructions/system.v new file mode 100644 index 0000000..087a683 --- /dev/null +++ b/CoqOfPython/ethereum/muir_glacier/vm/instructions/system.v @@ -0,0 +1,2117 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.muir_glacier.vm.instructions.system". + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) System Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM system related instructions. +". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_Bytes0 : + IsImported globals "ethereum.base_types" "Bytes0". +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". + +Axiom ethereum_utils_ensure_imports_ensure : + IsImported globals "ethereum.utils.ensure" "ensure". + +Axiom ethereum_utils_numeric_imports_ceil32 : + IsImported globals "ethereum.utils.numeric" "ceil32". + +Axiom ethereum_muir_glacier_fork_types_imports_Address : + IsImported globals "ethereum.muir_glacier.fork_types" "Address". + +Axiom ethereum_muir_glacier_state_imports_account_exists_and_is_empty : + IsImported globals "ethereum.muir_glacier.state" "account_exists_and_is_empty". +Axiom ethereum_muir_glacier_state_imports_account_has_code_or_nonce : + IsImported globals "ethereum.muir_glacier.state" "account_has_code_or_nonce". +Axiom ethereum_muir_glacier_state_imports_get_account : + IsImported globals "ethereum.muir_glacier.state" "get_account". +Axiom ethereum_muir_glacier_state_imports_increment_nonce : + IsImported globals "ethereum.muir_glacier.state" "increment_nonce". +Axiom ethereum_muir_glacier_state_imports_is_account_alive : + IsImported globals "ethereum.muir_glacier.state" "is_account_alive". +Axiom ethereum_muir_glacier_state_imports_set_account_balance : + IsImported globals "ethereum.muir_glacier.state" "set_account_balance". + +Axiom ethereum_muir_glacier_utils_address_imports_compute_contract_address : + IsImported globals "ethereum.muir_glacier.utils.address" "compute_contract_address". +Axiom ethereum_muir_glacier_utils_address_imports_compute_create2_contract_address : + IsImported globals "ethereum.muir_glacier.utils.address" "compute_create2_contract_address". +Axiom ethereum_muir_glacier_utils_address_imports_to_address : + IsImported globals "ethereum.muir_glacier.utils.address" "to_address". + +Axiom ethereum_muir_glacier_vm_imports_Evm : + IsImported globals "ethereum.muir_glacier.vm" "Evm". +Axiom ethereum_muir_glacier_vm_imports_Message : + IsImported globals "ethereum.muir_glacier.vm" "Message". +Axiom ethereum_muir_glacier_vm_imports_incorporate_child_on_error : + IsImported globals "ethereum.muir_glacier.vm" "incorporate_child_on_error". +Axiom ethereum_muir_glacier_vm_imports_incorporate_child_on_success : + IsImported globals "ethereum.muir_glacier.vm" "incorporate_child_on_success". + +Axiom ethereum_muir_glacier_vm_exceptions_imports_Revert : + IsImported globals "ethereum.muir_glacier.vm.exceptions" "Revert". +Axiom ethereum_muir_glacier_vm_exceptions_imports_WriteInStaticContext : + IsImported globals "ethereum.muir_glacier.vm.exceptions" "WriteInStaticContext". + +Axiom ethereum_muir_glacier_vm_gas_imports_GAS_CALL : + IsImported globals "ethereum.muir_glacier.vm.gas" "GAS_CALL". +Axiom ethereum_muir_glacier_vm_gas_imports_GAS_CALL_VALUE : + IsImported globals "ethereum.muir_glacier.vm.gas" "GAS_CALL_VALUE". +Axiom ethereum_muir_glacier_vm_gas_imports_GAS_CREATE : + IsImported globals "ethereum.muir_glacier.vm.gas" "GAS_CREATE". +Axiom ethereum_muir_glacier_vm_gas_imports_GAS_KECCAK256_WORD : + IsImported globals "ethereum.muir_glacier.vm.gas" "GAS_KECCAK256_WORD". +Axiom ethereum_muir_glacier_vm_gas_imports_GAS_NEW_ACCOUNT : + IsImported globals "ethereum.muir_glacier.vm.gas" "GAS_NEW_ACCOUNT". +Axiom ethereum_muir_glacier_vm_gas_imports_GAS_SELF_DESTRUCT : + IsImported globals "ethereum.muir_glacier.vm.gas" "GAS_SELF_DESTRUCT". +Axiom ethereum_muir_glacier_vm_gas_imports_GAS_SELF_DESTRUCT_NEW_ACCOUNT : + IsImported globals "ethereum.muir_glacier.vm.gas" "GAS_SELF_DESTRUCT_NEW_ACCOUNT". +Axiom ethereum_muir_glacier_vm_gas_imports_GAS_ZERO : + IsImported globals "ethereum.muir_glacier.vm.gas" "GAS_ZERO". +Axiom ethereum_muir_glacier_vm_gas_imports_REFUND_SELF_DESTRUCT : + IsImported globals "ethereum.muir_glacier.vm.gas" "REFUND_SELF_DESTRUCT". +Axiom ethereum_muir_glacier_vm_gas_imports_calculate_gas_extend_memory : + IsImported globals "ethereum.muir_glacier.vm.gas" "calculate_gas_extend_memory". +Axiom ethereum_muir_glacier_vm_gas_imports_calculate_message_call_gas : + IsImported globals "ethereum.muir_glacier.vm.gas" "calculate_message_call_gas". +Axiom ethereum_muir_glacier_vm_gas_imports_charge_gas : + IsImported globals "ethereum.muir_glacier.vm.gas" "charge_gas". +Axiom ethereum_muir_glacier_vm_gas_imports_max_message_call_gas : + IsImported globals "ethereum.muir_glacier.vm.gas" "max_message_call_gas". + +Axiom ethereum_muir_glacier_vm_memory_imports_memory_read_bytes : + IsImported globals "ethereum.muir_glacier.vm.memory" "memory_read_bytes". +Axiom ethereum_muir_glacier_vm_memory_imports_memory_write : + IsImported globals "ethereum.muir_glacier.vm.memory" "memory_write". + +Axiom ethereum_muir_glacier_vm_stack_imports_pop : + IsImported globals "ethereum.muir_glacier.vm.stack" "pop". +Axiom ethereum_muir_glacier_vm_stack_imports_push : + IsImported globals "ethereum.muir_glacier.vm.stack" "push". + +Definition generic_create : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm"; "endowment"; "contract_address"; "memory_start_position"; "memory_size" ] |) in + let _ := Constant.str " + Core logic used by the `CREATE*` family of opcodes. + " in +(* At stmt: unsupported node type: ImportFrom *) + let _ := M.assign_local (| + "create_message_gas" , + M.call (| + M.get_name (| globals, "max_message_call_gas" |), + make_list [ + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "gas_left" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_op (| + BinOp.sub, + M.get_field (| M.get_name (| globals, "evm" |), "gas_left" |), + M.get_name (| globals, "create_message_gas" |) + |) in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + UnOp.not (| M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "is_static" |) |); + M.get_name (| globals, "WriteInStaticContext" |) + ], + make_dict [] + |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, "evm" |), "return_data" |), + Constant.bytes "" + |) in + let _ := M.assign_local (| + "sender_address" , + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "current_target" |) + |) in + let _ := M.assign_local (| + "sender" , + M.call (| + M.get_name (| globals, "get_account" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "env" |), "state" |); + M.get_name (| globals, "sender_address" |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + BoolOp.or (| + Compare.lt (| + M.get_field (| M.get_name (| globals, "sender" |), "balance" |), + M.get_name (| globals, "endowment" |) + |), + ltac:(M.monadic ( + BoolOp.or (| + Compare.eq (| + M.get_field (| M.get_name (| globals, "sender" |), "nonce" |), + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + BinOp.sub (| + BinOp.pow (| + Constant.int 2, + Constant.int 64 + |), + Constant.int 1 + |) + ], + make_dict [] + |) + |), + ltac:(M.monadic ( + Compare.gt (| + BinOp.add (| + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "depth" |), + Constant.int 1 + |), + M.get_name (| globals, "STACK_DEPTH_LIMIT" |) + |) + )) + |) + )) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "gas_left" |), + M.get_name (| globals, "create_message_gas" |) + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.return_ (| + Constant.None_ + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, "account_has_code_or_nonce" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "env" |), "state" |); + M.get_name (| globals, "contract_address" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, "increment_nonce" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "env" |), "state" |); + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "current_target" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.return_ (| + Constant.None_ + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "call_data" , + M.call (| + M.get_name (| globals, "memory_read_bytes" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "memory" |); + M.get_name (| globals, "memory_start_position" |); + M.get_name (| globals, "memory_size" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "increment_nonce" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "env" |), "state" |); + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "current_target" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "child_message" , + M.call (| + M.get_name (| globals, "Message" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "child_evm" , + M.call (| + M.get_name (| globals, "process_create_message" |), + make_list [ + M.get_name (| globals, "child_message" |); + M.get_field (| M.get_name (| globals, "evm" |), "env" |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + M.get_field (| M.get_name (| globals, "child_evm" |), "error" |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, "incorporate_child_on_error" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "child_evm" |) + ], + make_dict [] + |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, "evm" |), "return_data" |), + M.get_field (| M.get_name (| globals, "child_evm" |), "output" |) + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + ], + make_dict [] + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, "incorporate_child_on_success" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "child_evm" |) + ], + make_dict [] + |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, "evm" |), "return_data" |), + Constant.bytes "" + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.call (| + M.get_field (| M.get_name (| globals, "U256" |), "from_be_bytes" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "child_evm" |), "message" |), "current_target" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_)). + +Definition create : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Creates a new account with associated code. + + Parameters + ---------- + evm : + The current EVM frame. + " in + let _ := M.assign_local (| + "endowment" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_start_position" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_size" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "extend_memory" , + M.call (| + M.get_name (| globals, "calculate_gas_extend_memory" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "memory" |); + make_list [ + make_tuple [ M.get_name (| globals, "memory_start_position" |); M.get_name (| globals, "memory_size" |) ] + ] + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + BinOp.add (| + M.get_name (| globals, "GAS_CREATE" |), + M.get_field (| M.get_name (| globals, "extend_memory" |), "cost" |) + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "memory" |), + BinOp.mult (| + Constant.bytes "00", + M.get_field (| M.get_name (| globals, "extend_memory" |), "expand_by" |) + |) + |) in + let _ := M.assign_local (| + "contract_address" , + M.call (| + M.get_name (| globals, "compute_contract_address" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "current_target" |); + M.get_field (| M.call (| + M.get_name (| globals, "get_account" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "env" |), "state" |); + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "current_target" |) + ], + make_dict [] + |), "nonce" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "generic_create" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "endowment" |); + M.get_name (| globals, "contract_address" |); + M.get_name (| globals, "memory_start_position" |); + M.get_name (| globals, "memory_size" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition create2 : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Creates a new account with associated code. + + It's similar to CREATE opcode except that the address of new account + depends on the init_code instead of the nonce of sender. + + Parameters + ---------- + evm : + The current EVM frame. + " in + let _ := M.assign_local (| + "endowment" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_start_position" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_size" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "salt" , + M.call (| + M.get_field (| M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |), "to_be_bytes32" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "extend_memory" , + M.call (| + M.get_name (| globals, "calculate_gas_extend_memory" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "memory" |); + make_list [ + make_tuple [ M.get_name (| globals, "memory_start_position" |); M.get_name (| globals, "memory_size" |) ] + ] + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "call_data_words" , + BinOp.floor_div (| + M.call (| + M.get_name (| globals, "ceil32" |), + make_list [ + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.get_name (| globals, "memory_size" |) + ], + make_dict [] + |) + ], + make_dict [] + |), + Constant.int 32 + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + BinOp.add (| + BinOp.add (| + M.get_name (| globals, "GAS_CREATE" |), + BinOp.mult (| + M.get_name (| globals, "GAS_KECCAK256_WORD" |), + M.get_name (| globals, "call_data_words" |) + |) + |), + M.get_field (| M.get_name (| globals, "extend_memory" |), "cost" |) + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "memory" |), + BinOp.mult (| + Constant.bytes "00", + M.get_field (| M.get_name (| globals, "extend_memory" |), "expand_by" |) + |) + |) in + let _ := M.assign_local (| + "contract_address" , + M.call (| + M.get_name (| globals, "compute_create2_contract_address" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "current_target" |); + M.get_name (| globals, "salt" |); + M.call (| + M.get_name (| globals, "memory_read_bytes" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "memory" |); + M.get_name (| globals, "memory_start_position" |); + M.get_name (| globals, "memory_size" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "generic_create" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "endowment" |); + M.get_name (| globals, "contract_address" |); + M.get_name (| globals, "memory_start_position" |); + M.get_name (| globals, "memory_size" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition return_ : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Halts execution returning output data. + + Parameters + ---------- + evm : + The current EVM frame. + " in + let _ := M.assign_local (| + "memory_start_position" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_size" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "extend_memory" , + M.call (| + M.get_name (| globals, "calculate_gas_extend_memory" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "memory" |); + make_list [ + make_tuple [ M.get_name (| globals, "memory_start_position" |); M.get_name (| globals, "memory_size" |) ] + ] + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + BinOp.add (| + M.get_name (| globals, "GAS_ZERO" |), + M.get_field (| M.get_name (| globals, "extend_memory" |), "cost" |) + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "memory" |), + BinOp.mult (| + Constant.bytes "00", + M.get_field (| M.get_name (| globals, "extend_memory" |), "expand_by" |) + |) + |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, "evm" |), "output" |), + M.call (| + M.get_name (| globals, "memory_read_bytes" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "memory" |); + M.get_name (| globals, "memory_start_position" |); + M.get_name (| globals, "memory_size" |) + ], + make_dict [] + |) + |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, "evm" |), "running" |), + Constant.bool false + |) in + let _ := M.pass (| |) in + M.pure Constant.None_)). + +Definition generic_call : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm"; "gas"; "value"; "caller"; "to"; "code_address"; "should_transfer_value"; "is_staticcall"; "memory_input_start_position"; "memory_input_size"; "memory_output_start_position"; "memory_output_size" ] |) in + let _ := Constant.str " + Perform the core logic of the `CALL*` family of opcodes. + " in +(* At stmt: unsupported node type: ImportFrom *) + let _ := M.assign (| + M.get_field (| M.get_name (| globals, "evm" |), "return_data" |), + Constant.bytes "" + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.gt (| + BinOp.add (| + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "depth" |), + Constant.int 1 + |), + M.get_name (| globals, "STACK_DEPTH_LIMIT" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "gas_left" |), + M.get_name (| globals, "gas" |) + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.return_ (| + Constant.None_ + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "call_data" , + M.call (| + M.get_name (| globals, "memory_read_bytes" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "memory" |); + M.get_name (| globals, "memory_input_start_position" |); + M.get_name (| globals, "memory_input_size" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "code" , + M.get_field (| M.call (| + M.get_name (| globals, "get_account" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "env" |), "state" |); + M.get_name (| globals, "code_address" |) + ], + make_dict [] + |), "code" |) + |) in + let _ := M.assign_local (| + "child_message" , + M.call (| + M.get_name (| globals, "Message" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "child_evm" , + M.call (| + M.get_name (| globals, "process_message" |), + make_list [ + M.get_name (| globals, "child_message" |); + M.get_field (| M.get_name (| globals, "evm" |), "env" |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + M.get_field (| M.get_name (| globals, "child_evm" |), "error" |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, "incorporate_child_on_error" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "child_evm" |) + ], + make_dict [] + |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, "evm" |), "return_data" |), + M.get_field (| M.get_name (| globals, "child_evm" |), "output" |) + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + ], + make_dict [] + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, "incorporate_child_on_success" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "child_evm" |) + ], + make_dict [] + |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, "evm" |), "return_data" |), + M.get_field (| M.get_name (| globals, "child_evm" |), "output" |) + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 1 + ], + make_dict [] + |) + ], + make_dict [] + |) in + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "actual_output_size" , + M.call (| + M.get_name (| globals, "min" |), + make_list [ + M.get_name (| globals, "memory_output_size" |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_field (| M.get_name (| globals, "child_evm" |), "output" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "memory_write" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "memory" |); + M.get_name (| globals, "memory_output_start_position" |); + M.slice (| + M.get_field (| M.get_name (| globals, "child_evm" |), "output" |), + Constant.None_, + M.get_name (| globals, "actual_output_size" |), + Constant.None_ + |) + ], + make_dict [] + |) in + M.pure Constant.None_)). + +Definition call : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Message-call into an account. + + Parameters + ---------- + evm : + The current EVM frame. + " in + let _ := M.assign_local (| + "gas" , + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "to" , + M.call (| + M.get_name (| globals, "to_address" |), + make_list [ + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "value" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_input_start_position" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_input_size" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_output_start_position" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_output_size" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "extend_memory" , + M.call (| + M.get_name (| globals, "calculate_gas_extend_memory" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "memory" |); + make_list [ + make_tuple [ M.get_name (| globals, "memory_input_start_position" |); M.get_name (| globals, "memory_input_size" |) ]; + make_tuple [ M.get_name (| globals, "memory_output_start_position" |); M.get_name (| globals, "memory_output_size" |) ] + ] + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "create_gas_cost" , + (* if *) + M.if_then_else (| + BoolOp.or (| + Compare.eq (| + M.get_name (| globals, "value" |), + Constant.int 0 + |), + ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "is_account_alive" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "env" |), "state" |); + M.get_name (| globals, "to" |) + ], + make_dict [] + |) + )) + |), + (* then *) + ltac:(M.monadic ( +M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + (* else *) + )), ltac:(M.monadic ( +M.get_name (| globals, "GAS_NEW_ACCOUNT" |) + )) |) + |) in + let _ := M.assign_local (| + "transfer_gas_cost" , + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, "value" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( +M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + (* else *) + )), ltac:(M.monadic ( +M.get_name (| globals, "GAS_CALL_VALUE" |) + )) |) + |) in + let _ := M.assign_local (| + "message_call_gas" , + M.call (| + M.get_name (| globals, "calculate_message_call_gas" |), + make_list [ + M.get_name (| globals, "value" |); + M.get_name (| globals, "gas" |); + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "gas_left" |) + ], + make_dict [] + |); + M.get_field (| M.get_name (| globals, "extend_memory" |), "cost" |); + BinOp.add (| + BinOp.add (| + M.get_name (| globals, "GAS_CALL" |), + M.get_name (| globals, "create_gas_cost" |) + |), + M.get_name (| globals, "transfer_gas_cost" |) + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + BinOp.add (| + M.get_field (| M.get_name (| globals, "message_call_gas" |), "cost" |), + M.get_field (| M.get_name (| globals, "extend_memory" |), "cost" |) + |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + BoolOp.or (| + UnOp.not (| M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "is_static" |) |), + ltac:(M.monadic ( + Compare.eq (| + M.get_name (| globals, "value" |), + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + |) + )) + |); + M.get_name (| globals, "WriteInStaticContext" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "memory" |), + BinOp.mult (| + Constant.bytes "00", + M.get_field (| M.get_name (| globals, "extend_memory" |), "expand_by" |) + |) + |) in + let _ := M.assign_local (| + "sender_balance" , + M.get_field (| M.call (| + M.get_name (| globals, "get_account" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "env" |), "state" |); + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "current_target" |) + ], + make_dict [] + |), "balance" |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.lt (| + M.get_name (| globals, "sender_balance" |), + M.get_name (| globals, "value" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, "evm" |), "return_data" |), + Constant.bytes "" + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "gas_left" |), + M.get_field (| M.get_name (| globals, "message_call_gas" |), "stipend" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, "generic_call" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_field (| M.get_name (| globals, "message_call_gas" |), "stipend" |); + M.get_name (| globals, "value" |); + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "current_target" |); + M.get_name (| globals, "to" |); + M.get_name (| globals, "to" |); + Constant.bool true; + Constant.bool false; + M.get_name (| globals, "memory_input_start_position" |); + M.get_name (| globals, "memory_input_size" |); + M.get_name (| globals, "memory_output_start_position" |); + M.get_name (| globals, "memory_output_size" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + )) |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition callcode : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Message-call into this account with alternative account’s code. + + Parameters + ---------- + evm : + The current EVM frame. + " in + let _ := M.assign_local (| + "gas" , + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "code_address" , + M.call (| + M.get_name (| globals, "to_address" |), + make_list [ + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "value" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_input_start_position" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_input_size" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_output_start_position" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_output_size" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "to" , + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "current_target" |) + |) in + let _ := M.assign_local (| + "extend_memory" , + M.call (| + M.get_name (| globals, "calculate_gas_extend_memory" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "memory" |); + make_list [ + make_tuple [ M.get_name (| globals, "memory_input_start_position" |); M.get_name (| globals, "memory_input_size" |) ]; + make_tuple [ M.get_name (| globals, "memory_output_start_position" |); M.get_name (| globals, "memory_output_size" |) ] + ] + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "transfer_gas_cost" , + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, "value" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( +M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + (* else *) + )), ltac:(M.monadic ( +M.get_name (| globals, "GAS_CALL_VALUE" |) + )) |) + |) in + let _ := M.assign_local (| + "message_call_gas" , + M.call (| + M.get_name (| globals, "calculate_message_call_gas" |), + make_list [ + M.get_name (| globals, "value" |); + M.get_name (| globals, "gas" |); + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "gas_left" |) + ], + make_dict [] + |); + M.get_field (| M.get_name (| globals, "extend_memory" |), "cost" |); + BinOp.add (| + M.get_name (| globals, "GAS_CALL" |), + M.get_name (| globals, "transfer_gas_cost" |) + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + BinOp.add (| + M.get_field (| M.get_name (| globals, "message_call_gas" |), "cost" |), + M.get_field (| M.get_name (| globals, "extend_memory" |), "cost" |) + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "memory" |), + BinOp.mult (| + Constant.bytes "00", + M.get_field (| M.get_name (| globals, "extend_memory" |), "expand_by" |) + |) + |) in + let _ := M.assign_local (| + "sender_balance" , + M.get_field (| M.call (| + M.get_name (| globals, "get_account" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "env" |), "state" |); + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "current_target" |) + ], + make_dict [] + |), "balance" |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.lt (| + M.get_name (| globals, "sender_balance" |), + M.get_name (| globals, "value" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, "evm" |), "return_data" |), + Constant.bytes "" + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "gas_left" |), + M.get_field (| M.get_name (| globals, "message_call_gas" |), "stipend" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, "generic_call" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_field (| M.get_name (| globals, "message_call_gas" |), "stipend" |); + M.get_name (| globals, "value" |); + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "current_target" |); + M.get_name (| globals, "to" |); + M.get_name (| globals, "code_address" |); + Constant.bool true; + Constant.bool false; + M.get_name (| globals, "memory_input_start_position" |); + M.get_name (| globals, "memory_input_size" |); + M.get_name (| globals, "memory_output_start_position" |); + M.get_name (| globals, "memory_output_size" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + )) |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition selfdestruct : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Halt execution and register account for later deletion. + + Parameters + ---------- + evm : + The current EVM frame. + " in + let _ := M.assign_local (| + "beneficiary" , + M.call (| + M.get_name (| globals, "to_address" |), + make_list [ + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "gas_cost" , + M.get_name (| globals, "GAS_SELF_DESTRUCT" |) + |) in + let _ := + (* if *) + M.if_then_else (| + BoolOp.and (| + UnOp.not (| M.call (| + M.get_name (| globals, "is_account_alive" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "env" |), "state" |); + M.get_name (| globals, "beneficiary" |) + ], + make_dict [] + |) |), + ltac:(M.monadic ( + Compare.not_eq (| + M.get_field (| M.call (| + M.get_name (| globals, "get_account" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "env" |), "state" |); + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "current_target" |) + ], + make_dict [] + |), "balance" |), + Constant.int 0 + |) + )) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_op_local (| + BinOp.add, + "gas_cost", + M.get_name (| globals, "GAS_SELF_DESTRUCT_NEW_ACCOUNT" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "originator" , + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "current_target" |) + |) in + let _ := M.assign_local (| + "refunded_accounts" , + M.get_field (| M.get_name (| globals, "evm" |), "accounts_to_delete" |) + |) in + let _ := M.assign_local (| + "parent_evm" , + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "parent_evm" |) + |) in + let _ := + M.while (| + Compare.is_not (| + M.get_name (| globals, "parent_evm" |), + Constant.None_ + |), + ltac:(M.monadic ( + let _ := M.call (| + M.get_field (| M.get_name (| globals, "refunded_accounts" |), "update" |), + make_list [ + M.get_field (| M.get_name (| globals, "parent_evm" |), "accounts_to_delete" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "parent_evm" , + M.get_field (| M.get_field (| M.get_name (| globals, "parent_evm" |), "message" |), "parent_evm" |) + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.not_in (| + M.get_name (| globals, "originator" |), + M.get_name (| globals, "refunded_accounts" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "refund_counter" |), + M.get_name (| globals, "REFUND_SELF_DESTRUCT" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "gas_cost" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + UnOp.not (| M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "is_static" |) |); + M.get_name (| globals, "WriteInStaticContext" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "beneficiary_balance" , + M.get_field (| M.call (| + M.get_name (| globals, "get_account" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "env" |), "state" |); + M.get_name (| globals, "beneficiary" |) + ], + make_dict [] + |), "balance" |) + |) in + let _ := M.assign_local (| + "originator_balance" , + M.get_field (| M.call (| + M.get_name (| globals, "get_account" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "env" |), "state" |); + M.get_name (| globals, "originator" |) + ], + make_dict [] + |), "balance" |) + |) in + let _ := M.call (| + M.get_name (| globals, "set_account_balance" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "env" |), "state" |); + M.get_name (| globals, "beneficiary" |); + BinOp.add (| + M.get_name (| globals, "beneficiary_balance" |), + M.get_name (| globals, "originator_balance" |) + |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "set_account_balance" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "env" |), "state" |); + M.get_name (| globals, "originator" |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "accounts_to_delete" |), "add" |), + make_list [ + M.get_name (| globals, "originator" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, "account_exists_and_is_empty" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "env" |), "state" |); + M.get_name (| globals, "beneficiary" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "touched_accounts" |), "add" |), + make_list [ + M.get_name (| globals, "beneficiary" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, "evm" |), "running" |), + Constant.bool false + |) in + let _ := M.pass (| |) in + M.pure Constant.None_)). + +Definition delegatecall : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Message-call into an account. + + Parameters + ---------- + evm : + The current EVM frame. + " in + let _ := M.assign_local (| + "gas" , + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "code_address" , + M.call (| + M.get_name (| globals, "to_address" |), + make_list [ + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_input_start_position" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_input_size" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_output_start_position" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_output_size" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "extend_memory" , + M.call (| + M.get_name (| globals, "calculate_gas_extend_memory" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "memory" |); + make_list [ + make_tuple [ M.get_name (| globals, "memory_input_start_position" |); M.get_name (| globals, "memory_input_size" |) ]; + make_tuple [ M.get_name (| globals, "memory_output_start_position" |); M.get_name (| globals, "memory_output_size" |) ] + ] + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "message_call_gas" , + M.call (| + M.get_name (| globals, "calculate_message_call_gas" |), + make_list [ + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |); + M.get_name (| globals, "gas" |); + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "gas_left" |) + ], + make_dict [] + |); + M.get_field (| M.get_name (| globals, "extend_memory" |), "cost" |); + M.get_name (| globals, "GAS_CALL" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + BinOp.add (| + M.get_field (| M.get_name (| globals, "message_call_gas" |), "cost" |), + M.get_field (| M.get_name (| globals, "extend_memory" |), "cost" |) + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "memory" |), + BinOp.mult (| + Constant.bytes "00", + M.get_field (| M.get_name (| globals, "extend_memory" |), "expand_by" |) + |) + |) in + let _ := M.call (| + M.get_name (| globals, "generic_call" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_field (| M.get_name (| globals, "message_call_gas" |), "stipend" |); + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "value" |); + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "caller" |); + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "current_target" |); + M.get_name (| globals, "code_address" |); + Constant.bool false; + Constant.bool false; + M.get_name (| globals, "memory_input_start_position" |); + M.get_name (| globals, "memory_input_size" |); + M.get_name (| globals, "memory_output_start_position" |); + M.get_name (| globals, "memory_output_size" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition staticcall : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Message-call into an account. + + Parameters + ---------- + evm : + The current EVM frame. + " in + let _ := M.assign_local (| + "gas" , + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "to" , + M.call (| + M.get_name (| globals, "to_address" |), + make_list [ + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_input_start_position" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_input_size" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_output_start_position" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_output_size" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "extend_memory" , + M.call (| + M.get_name (| globals, "calculate_gas_extend_memory" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "memory" |); + make_list [ + make_tuple [ M.get_name (| globals, "memory_input_start_position" |); M.get_name (| globals, "memory_input_size" |) ]; + make_tuple [ M.get_name (| globals, "memory_output_start_position" |); M.get_name (| globals, "memory_output_size" |) ] + ] + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "message_call_gas" , + M.call (| + M.get_name (| globals, "calculate_message_call_gas" |), + make_list [ + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |); + M.get_name (| globals, "gas" |); + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "gas_left" |) + ], + make_dict [] + |); + M.get_field (| M.get_name (| globals, "extend_memory" |), "cost" |); + M.get_name (| globals, "GAS_CALL" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + BinOp.add (| + M.get_field (| M.get_name (| globals, "message_call_gas" |), "cost" |), + M.get_field (| M.get_name (| globals, "extend_memory" |), "cost" |) + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "memory" |), + BinOp.mult (| + Constant.bytes "00", + M.get_field (| M.get_name (| globals, "extend_memory" |), "expand_by" |) + |) + |) in + let _ := M.call (| + M.get_name (| globals, "generic_call" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_field (| M.get_name (| globals, "message_call_gas" |), "stipend" |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |); + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "current_target" |); + M.get_name (| globals, "to" |); + M.get_name (| globals, "to" |); + Constant.bool true; + Constant.bool true; + M.get_name (| globals, "memory_input_start_position" |); + M.get_name (| globals, "memory_input_size" |); + M.get_name (| globals, "memory_output_start_position" |); + M.get_name (| globals, "memory_output_size" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition revert : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Stop execution and revert state changes, without consuming all provided gas + and also has the ability to return a reason + Parameters + ---------- + evm : + The current EVM frame. + " in + let _ := M.assign_local (| + "memory_start_index" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "size" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "extend_memory" , + M.call (| + M.get_name (| globals, "calculate_gas_extend_memory" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "memory" |); + make_list [ + make_tuple [ M.get_name (| globals, "memory_start_index" |); M.get_name (| globals, "size" |) ] + ] + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_field (| M.get_name (| globals, "extend_memory" |), "cost" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "memory" |), + BinOp.mult (| + Constant.bytes "00", + M.get_field (| M.get_name (| globals, "extend_memory" |), "expand_by" |) + |) + |) in + let _ := M.assign_local (| + "output" , + M.call (| + M.get_name (| globals, "memory_read_bytes" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "memory" |); + M.get_name (| globals, "memory_start_index" |); + M.get_name (| globals, "size" |) + ], + make_dict [] + |) + |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, "evm" |), "output" |), + M.call (| + M.get_name (| globals, "bytes" |), + make_list [ + M.get_name (| globals, "output" |) + ], + make_dict [] + |) + |) in + let _ := M.raise (| Some (M.get_name (| globals, "Revert" |)) |) in + let _ := M.pass (| |) in + M.pure Constant.None_)). diff --git a/CoqOfPython/ethereum/muir_glacier/vm/interpreter.v b/CoqOfPython/ethereum/muir_glacier/vm/interpreter.v new file mode 100644 index 0000000..03f7f66 --- /dev/null +++ b/CoqOfPython/ethereum/muir_glacier/vm/interpreter.v @@ -0,0 +1,673 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.muir_glacier.vm.interpreter". + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) Interpreter +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +A straightforward interpreter that executes EVM code. +". + +Axiom dataclasses_imports_dataclass : + IsImported globals "dataclasses" "dataclass". + +Axiom typing_imports_Iterable : + IsImported globals "typing" "Iterable". +Axiom typing_imports_Optional : + IsImported globals "typing" "Optional". +Axiom typing_imports_Set : + IsImported globals "typing" "Set". +Axiom typing_imports_Tuple : + IsImported globals "typing" "Tuple". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_Bytes0 : + IsImported globals "ethereum.base_types" "Bytes0". +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". + +Axiom ethereum_trace_imports_EvmStop : + IsImported globals "ethereum.trace" "EvmStop". +Axiom ethereum_trace_imports_OpEnd : + IsImported globals "ethereum.trace" "OpEnd". +Axiom ethereum_trace_imports_OpException : + IsImported globals "ethereum.trace" "OpException". +Axiom ethereum_trace_imports_OpStart : + IsImported globals "ethereum.trace" "OpStart". +Axiom ethereum_trace_imports_PrecompileEnd : + IsImported globals "ethereum.trace" "PrecompileEnd". +Axiom ethereum_trace_imports_PrecompileStart : + IsImported globals "ethereum.trace" "PrecompileStart". +Axiom ethereum_trace_imports_TransactionEnd : + IsImported globals "ethereum.trace" "TransactionEnd". +Axiom ethereum_trace_imports_evm_trace : + IsImported globals "ethereum.trace" "evm_trace". + +Axiom ethereum_utils_ensure_imports_ensure : + IsImported globals "ethereum.utils.ensure" "ensure". + +Axiom ethereum_muir_glacier_blocks_imports_Log : + IsImported globals "ethereum.muir_glacier.blocks" "Log". + +Axiom ethereum_muir_glacier_fork_types_imports_Address : + IsImported globals "ethereum.muir_glacier.fork_types" "Address". + +Axiom ethereum_muir_glacier_state_imports_account_exists_and_is_empty : + IsImported globals "ethereum.muir_glacier.state" "account_exists_and_is_empty". +Axiom ethereum_muir_glacier_state_imports_account_has_code_or_nonce : + IsImported globals "ethereum.muir_glacier.state" "account_has_code_or_nonce". +Axiom ethereum_muir_glacier_state_imports_begin_transaction : + IsImported globals "ethereum.muir_glacier.state" "begin_transaction". +Axiom ethereum_muir_glacier_state_imports_commit_transaction : + IsImported globals "ethereum.muir_glacier.state" "commit_transaction". +Axiom ethereum_muir_glacier_state_imports_destroy_storage : + IsImported globals "ethereum.muir_glacier.state" "destroy_storage". +Axiom ethereum_muir_glacier_state_imports_increment_nonce : + IsImported globals "ethereum.muir_glacier.state" "increment_nonce". +Axiom ethereum_muir_glacier_state_imports_mark_account_created : + IsImported globals "ethereum.muir_glacier.state" "mark_account_created". +Axiom ethereum_muir_glacier_state_imports_move_ether : + IsImported globals "ethereum.muir_glacier.state" "move_ether". +Axiom ethereum_muir_glacier_state_imports_rollback_transaction : + IsImported globals "ethereum.muir_glacier.state" "rollback_transaction". +Axiom ethereum_muir_glacier_state_imports_set_code : + IsImported globals "ethereum.muir_glacier.state" "set_code". +Axiom ethereum_muir_glacier_state_imports_touch_account : + IsImported globals "ethereum.muir_glacier.state" "touch_account". + +Axiom ethereum_muir_glacier_vm_imports_Message : + IsImported globals "ethereum.muir_glacier.vm" "Message". + +Axiom ethereum_muir_glacier_vm_gas_imports_GAS_CODE_DEPOSIT : + IsImported globals "ethereum.muir_glacier.vm.gas" "GAS_CODE_DEPOSIT". +Axiom ethereum_muir_glacier_vm_gas_imports_charge_gas : + IsImported globals "ethereum.muir_glacier.vm.gas" "charge_gas". + +Axiom ethereum_muir_glacier_vm_precompiled_contracts_mapping_imports_PRE_COMPILED_CONTRACTS : + IsImported globals "ethereum.muir_glacier.vm.precompiled_contracts.mapping" "PRE_COMPILED_CONTRACTS". + +Axiom ethereum_muir_glacier_vm_imports_Environment : + IsImported globals "ethereum.muir_glacier.vm" "Environment". +Axiom ethereum_muir_glacier_vm_imports_Evm : + IsImported globals "ethereum.muir_glacier.vm" "Evm". + +Axiom ethereum_muir_glacier_vm_exceptions_imports_AddressCollision : + IsImported globals "ethereum.muir_glacier.vm.exceptions" "AddressCollision". +Axiom ethereum_muir_glacier_vm_exceptions_imports_ExceptionalHalt : + IsImported globals "ethereum.muir_glacier.vm.exceptions" "ExceptionalHalt". +Axiom ethereum_muir_glacier_vm_exceptions_imports_InvalidOpcode : + IsImported globals "ethereum.muir_glacier.vm.exceptions" "InvalidOpcode". +Axiom ethereum_muir_glacier_vm_exceptions_imports_OutOfGasError : + IsImported globals "ethereum.muir_glacier.vm.exceptions" "OutOfGasError". +Axiom ethereum_muir_glacier_vm_exceptions_imports_Revert : + IsImported globals "ethereum.muir_glacier.vm.exceptions" "Revert". +Axiom ethereum_muir_glacier_vm_exceptions_imports_StackDepthLimitError : + IsImported globals "ethereum.muir_glacier.vm.exceptions" "StackDepthLimitError". + +Axiom ethereum_muir_glacier_vm_instructions_imports_Ops : + IsImported globals "ethereum.muir_glacier.vm.instructions" "Ops". +Axiom ethereum_muir_glacier_vm_instructions_imports_op_implementation : + IsImported globals "ethereum.muir_glacier.vm.instructions" "op_implementation". + +Axiom ethereum_muir_glacier_vm_runtime_imports_get_valid_jump_destinations : + IsImported globals "ethereum.muir_glacier.vm.runtime" "get_valid_jump_destinations". + +Definition STACK_DEPTH_LIMIT : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 1024 + ], + make_dict [] + |) +)). + +Definition MAX_CODE_SIZE : Value.t := M.run ltac:(M.monadic ( + Constant.int 24576 +)). + +Definition MessageCallOutput : Value.t := + builtins.make_klass + [] + [ + + ] + [ + + ]. + +Definition process_message_call : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "message"; "env" ] |) in + let _ := Constant.str " + If `message.current` is empty then it creates a smart contract + else it executes a call from the `message.caller` to the `message.target`. + + Parameters + ---------- + message : + Transaction specific items. + + env : + External items required for EVM execution. + + Returns + ------- + output : `MessageCallOutput` + Output of the message call + " in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_field (| M.get_name (| globals, "message" |), "target" |), + M.call (| + M.get_name (| globals, "Bytes0" |), + make_list [ + Constant.bytes "" + ], + make_dict [] + |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "is_collision" , + M.call (| + M.get_name (| globals, "account_has_code_or_nonce" |), + make_list [ + M.get_field (| M.get_name (| globals, "env" |), "state" |); + M.get_field (| M.get_name (| globals, "message" |), "current_target" |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + M.get_name (| globals, "is_collision" |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + M.call (| + M.get_name (| globals, "MessageCallOutput" |), + make_list [ + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |); + M.call (| + M.get_name (| globals, "tuple" |), + make_list [], + make_dict [] + |); + M.call (| + M.get_name (| globals, "set" |), + make_list [], + make_dict [] + |); + M.call (| + M.get_name (| globals, "set" |), + make_list [], + make_dict [] + |); + M.call (| + M.get_name (| globals, "AddressCollision" |), + make_list [], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "evm" , + M.call (| + M.get_name (| globals, "process_create_message" |), + make_list [ + M.get_name (| globals, "message" |); + M.get_name (| globals, "env" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "evm" , + M.call (| + M.get_name (| globals, "process_message" |), + make_list [ + M.get_name (| globals, "message" |); + M.get_name (| globals, "env" |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, "account_exists_and_is_empty" |), + make_list [ + M.get_field (| M.get_name (| globals, "env" |), "state" |); + M.call (| + M.get_name (| globals, "Address" |), + make_list [ + M.get_field (| M.get_name (| globals, "message" |), "target" |) + ], + make_dict [] + |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "touched_accounts" |), "add" |), + make_list [ + M.call (| + M.get_name (| globals, "Address" |), + make_list [ + M.get_field (| M.get_name (| globals, "message" |), "target" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + M.get_field (| M.get_name (| globals, "evm" |), "error" |), + (* then *) + ltac:(M.monadic ( +(* At stmt: unsupported node type: AnnAssign *) + let _ := M.assign_local (| + "accounts_to_delete" , + M.call (| + M.get_name (| globals, "set" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "touched_accounts" , + M.call (| + M.get_name (| globals, "set" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "refund_counter" , + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "logs" , + M.get_field (| M.get_name (| globals, "evm" |), "logs" |) + |) in + let _ := M.assign_local (| + "accounts_to_delete" , + M.get_field (| M.get_name (| globals, "evm" |), "accounts_to_delete" |) + |) in + let _ := M.assign_local (| + "touched_accounts" , + M.get_field (| M.get_name (| globals, "evm" |), "touched_accounts" |) + |) in + let _ := M.assign_local (| + "refund_counter" , + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "refund_counter" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "tx_end" , + M.call (| + M.get_name (| globals, "TransactionEnd" |), + make_list [ + BinOp.sub (| + M.get_field (| M.get_name (| globals, "message" |), "gas" |), + M.get_field (| M.get_name (| globals, "evm" |), "gas_left" |) + |); + M.get_field (| M.get_name (| globals, "evm" |), "output" |); + M.get_field (| M.get_name (| globals, "evm" |), "error" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "evm_trace" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "tx_end" |) + ], + make_dict [] + |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, "MessageCallOutput" |), + make_list [], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Definition process_create_message : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "message"; "env" ] |) in + let _ := Constant.str " + Executes a call to create a smart contract. + + Parameters + ---------- + message : + Transaction specific items. + env : + External items required for EVM execution. + + Returns + ------- + evm: :py:class:`~ethereum.muir_glacier.vm.Evm` + Items containing execution specific objects. + " in + let _ := M.call (| + M.get_name (| globals, "begin_transaction" |), + make_list [ + M.get_field (| M.get_name (| globals, "env" |), "state" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "destroy_storage" |), + make_list [ + M.get_field (| M.get_name (| globals, "env" |), "state" |); + M.get_field (| M.get_name (| globals, "message" |), "current_target" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "mark_account_created" |), + make_list [ + M.get_field (| M.get_name (| globals, "env" |), "state" |); + M.get_field (| M.get_name (| globals, "message" |), "current_target" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "increment_nonce" |), + make_list [ + M.get_field (| M.get_name (| globals, "env" |), "state" |); + M.get_field (| M.get_name (| globals, "message" |), "current_target" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "evm" , + M.call (| + M.get_name (| globals, "process_message" |), + make_list [ + M.get_name (| globals, "message" |); + M.get_name (| globals, "env" |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + UnOp.not (| M.get_field (| M.get_name (| globals, "evm" |), "error" |) |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "contract_code" , + M.get_field (| M.get_name (| globals, "evm" |), "output" |) + |) in + let _ := M.assign_local (| + "contract_code_gas" , + BinOp.mult (| + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_name (| globals, "contract_code" |) + ], + make_dict [] + |), + M.get_name (| globals, "GAS_CODE_DEPOSIT" |) + |) + |) in +(* At stmt: unsupported node type: Try *) + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, "rollback_transaction" |), + make_list [ + M.get_field (| M.get_name (| globals, "env" |), "state" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + )) |) in + let _ := M.return_ (| + M.get_name (| globals, "evm" |) + |) in + M.pure Constant.None_)). + +Definition process_message : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "message"; "env" ] |) in + let _ := Constant.str " + Executes a call to create a smart contract. + + Parameters + ---------- + message : + Transaction specific items. + env : + External items required for EVM execution. + + Returns + ------- + evm: :py:class:`~ethereum.muir_glacier.vm.Evm` + Items containing execution specific objects + " in + let _ := + (* if *) + M.if_then_else (| + Compare.gt (| + M.get_field (| M.get_name (| globals, "message" |), "depth" |), + M.get_name (| globals, "STACK_DEPTH_LIMIT" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.call (| + M.get_name (| globals, "StackDepthLimitError" |), + make_list [ + Constant.str "Stack depth limit reached" + ], + make_dict [] + |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.call (| + M.get_name (| globals, "begin_transaction" |), + make_list [ + M.get_field (| M.get_name (| globals, "env" |), "state" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "touch_account" |), + make_list [ + M.get_field (| M.get_name (| globals, "env" |), "state" |); + M.get_field (| M.get_name (| globals, "message" |), "current_target" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + BoolOp.and (| + M.get_field (| M.get_name (| globals, "message" |), "should_transfer_value" |), + ltac:(M.monadic ( + Compare.not_eq (| + M.get_field (| M.get_name (| globals, "message" |), "value" |), + Constant.int 0 + |) + )) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, "move_ether" |), + make_list [ + M.get_field (| M.get_name (| globals, "env" |), "state" |); + M.get_field (| M.get_name (| globals, "message" |), "caller" |); + M.get_field (| M.get_name (| globals, "message" |), "current_target" |); + M.get_field (| M.get_name (| globals, "message" |), "value" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "evm" , + M.call (| + M.get_name (| globals, "execute_code" |), + make_list [ + M.get_name (| globals, "message" |); + M.get_name (| globals, "env" |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + M.get_field (| M.get_name (| globals, "evm" |), "error" |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, "rollback_transaction" |), + make_list [ + M.get_field (| M.get_name (| globals, "env" |), "state" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, "commit_transaction" |), + make_list [ + M.get_field (| M.get_name (| globals, "env" |), "state" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + )) |) in + let _ := M.return_ (| + M.get_name (| globals, "evm" |) + |) in + M.pure Constant.None_)). + +Definition execute_code : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "message"; "env" ] |) in + let _ := Constant.str " + Executes bytecode present in the `message`. + + Parameters + ---------- + message : + Transaction specific items. + env : + External items required for EVM execution. + + Returns + ------- + evm: `ethereum.vm.EVM` + Items containing execution specific objects + " in + let _ := M.assign_local (| + "code" , + M.get_field (| M.get_name (| globals, "message" |), "code" |) + |) in + let _ := M.assign_local (| + "valid_jump_destinations" , + M.call (| + M.get_name (| globals, "get_valid_jump_destinations" |), + make_list [ + M.get_name (| globals, "code" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "evm" , + M.call (| + M.get_name (| globals, "Evm" |), + make_list [], + make_dict [] + |) + |) in +(* At stmt: unsupported node type: Try *) + let _ := M.return_ (| + M.get_name (| globals, "evm" |) + |) in + M.pure Constant.None_)). diff --git a/CoqOfPython/ethereum/muir_glacier/vm/memory.v b/CoqOfPython/ethereum/muir_glacier/vm/memory.v new file mode 100644 index 0000000..2bdcef4 --- /dev/null +++ b/CoqOfPython/ethereum/muir_glacier/vm/memory.v @@ -0,0 +1,166 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.muir_glacier.vm.memory". + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) Memory +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +EVM memory operations. +". + +Axiom ethereum_utils_byte_imports_right_pad_zero_bytes : + IsImported globals "ethereum.utils.byte" "right_pad_zero_bytes". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_Bytes : + IsImported globals "ethereum.base_types" "Bytes". +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". + +Definition memory_write : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "memory"; "start_position"; "value" ] |) in + let _ := Constant.str " + Writes to memory. + + Parameters + ---------- + memory : + Memory contents of the EVM. + start_position : + Starting pointer to the memory. + value : + Data to write to memory. + " in + let _ := M.assign (| + M.slice (| + M.get_name (| globals, "memory" |), + M.get_name (| globals, "start_position" |), + BinOp.add (| + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.get_name (| globals, "start_position" |) + ], + make_dict [] + |), + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_name (| globals, "value" |) + ], + make_dict [] + |) + |), + Constant.None_ + |), + M.get_name (| globals, "value" |) + |) in + M.pure Constant.None_)). + +Definition memory_read_bytes : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "memory"; "start_position"; "size" ] |) in + let _ := Constant.str " + Read bytes from memory. + + Parameters + ---------- + memory : + Memory contents of the EVM. + start_position : + Starting pointer to the memory. + size : + Size of the data that needs to be read from `start_position`. + + Returns + ------- + data_bytes : + Data read from memory. + " in + let _ := M.return_ (| + M.slice (| + M.get_name (| globals, "memory" |), + M.get_name (| globals, "start_position" |), + BinOp.add (| + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.get_name (| globals, "start_position" |) + ], + make_dict [] + |), + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.get_name (| globals, "size" |) + ], + make_dict [] + |) + |), + Constant.None_ + |) + |) in + M.pure Constant.None_)). + +Definition buffer_read : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "buffer"; "start_position"; "size" ] |) in + let _ := Constant.str " + Read bytes from a buffer. Padding with zeros if necessary. + + Parameters + ---------- + buffer : + Memory contents of the EVM. + start_position : + Starting pointer to the memory. + size : + Size of the data that needs to be read from `start_position`. + + Returns + ------- + data_bytes : + Data read from memory. + " in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, "right_pad_zero_bytes" |), + make_list [ + M.slice (| + M.get_name (| globals, "buffer" |), + M.get_name (| globals, "start_position" |), + BinOp.add (| + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.get_name (| globals, "start_position" |) + ], + make_dict [] + |), + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.get_name (| globals, "size" |) + ], + make_dict [] + |) + |), + Constant.None_ + |); + M.get_name (| globals, "size" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). diff --git a/CoqOfPython/ethereum/muir_glacier/vm/precompiled_contracts/__init__.v b/CoqOfPython/ethereum/muir_glacier/vm/precompiled_contracts/__init__.v new file mode 100644 index 0000000..714a0bb --- /dev/null +++ b/CoqOfPython/ethereum/muir_glacier/vm/precompiled_contracts/__init__.v @@ -0,0 +1,116 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.muir_glacier.vm.precompiled_contracts.__init__". + +Definition expr_1 : Value.t := + Constant.str " +Precompiled Contract Addresses +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Addresses of precompiled contracts and mappings to their +implementations. +". + +Axiom ethereum_muir_glacier_utils_hexadecimal_imports_hex_to_address : + IsImported globals "ethereum.muir_glacier.utils.hexadecimal" "hex_to_address". + +Definition __all__ : Value.t := M.run ltac:(M.monadic ( + make_tuple [ Constant.str "ECRECOVER_ADDRESS"; Constant.str "SHA256_ADDRESS"; Constant.str "RIPEMD160_ADDRESS"; Constant.str "IDENTITY_ADDRESS"; Constant.str "MODEXP_ADDRESS"; Constant.str "ALT_BN128_ADD_ADDRESS"; Constant.str "ALT_BN128_MUL_ADDRESS"; Constant.str "ALT_BN128_PAIRING_CHECK_ADDRESS"; Constant.str "BLAKE2F_ADDRESS" ] +)). + +Definition ECRECOVER_ADDRESS : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "hex_to_address" |), + make_list [ + Constant.str "0x01" + ], + make_dict [] + |) +)). + +Definition SHA256_ADDRESS : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "hex_to_address" |), + make_list [ + Constant.str "0x02" + ], + make_dict [] + |) +)). + +Definition RIPEMD160_ADDRESS : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "hex_to_address" |), + make_list [ + Constant.str "0x03" + ], + make_dict [] + |) +)). + +Definition IDENTITY_ADDRESS : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "hex_to_address" |), + make_list [ + Constant.str "0x04" + ], + make_dict [] + |) +)). + +Definition MODEXP_ADDRESS : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "hex_to_address" |), + make_list [ + Constant.str "0x05" + ], + make_dict [] + |) +)). + +Definition ALT_BN128_ADD_ADDRESS : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "hex_to_address" |), + make_list [ + Constant.str "0x06" + ], + make_dict [] + |) +)). + +Definition ALT_BN128_MUL_ADDRESS : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "hex_to_address" |), + make_list [ + Constant.str "0x07" + ], + make_dict [] + |) +)). + +Definition ALT_BN128_PAIRING_CHECK_ADDRESS : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "hex_to_address" |), + make_list [ + Constant.str "0x08" + ], + make_dict [] + |) +)). + +Definition BLAKE2F_ADDRESS : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "hex_to_address" |), + make_list [ + Constant.str "0x09" + ], + make_dict [] + |) +)). diff --git a/CoqOfPython/ethereum/muir_glacier/vm/precompiled_contracts/alt_bn128.v b/CoqOfPython/ethereum/muir_glacier/vm/precompiled_contracts/alt_bn128.v new file mode 100644 index 0000000..e709832 --- /dev/null +++ b/CoqOfPython/ethereum/muir_glacier/vm/precompiled_contracts/alt_bn128.v @@ -0,0 +1,778 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.muir_glacier.vm.precompiled_contracts.alt_bn128". + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) ALT_BN128 CONTRACTS +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementation of the ALT_BN128 precompiled contracts. +". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". + +Axiom ethereum_crypto_alt_bn128_imports_ALT_BN128_CURVE_ORDER : + IsImported globals "ethereum.crypto.alt_bn128" "ALT_BN128_CURVE_ORDER". +Axiom ethereum_crypto_alt_bn128_imports_ALT_BN128_PRIME : + IsImported globals "ethereum.crypto.alt_bn128" "ALT_BN128_PRIME". +Axiom ethereum_crypto_alt_bn128_imports_BNF : + IsImported globals "ethereum.crypto.alt_bn128" "BNF". +Axiom ethereum_crypto_alt_bn128_imports_BNF2 : + IsImported globals "ethereum.crypto.alt_bn128" "BNF2". +Axiom ethereum_crypto_alt_bn128_imports_BNF12 : + IsImported globals "ethereum.crypto.alt_bn128" "BNF12". +Axiom ethereum_crypto_alt_bn128_imports_BNP : + IsImported globals "ethereum.crypto.alt_bn128" "BNP". +Axiom ethereum_crypto_alt_bn128_imports_BNP2 : + IsImported globals "ethereum.crypto.alt_bn128" "BNP2". +Axiom ethereum_crypto_alt_bn128_imports_pairing : + IsImported globals "ethereum.crypto.alt_bn128" "pairing". + +Axiom ethereum_utils_ensure_imports_ensure : + IsImported globals "ethereum.utils.ensure" "ensure". + +Axiom ethereum_muir_glacier_vm_imports_Evm : + IsImported globals "ethereum.muir_glacier.vm" "Evm". + +Axiom ethereum_muir_glacier_vm_gas_imports_charge_gas : + IsImported globals "ethereum.muir_glacier.vm.gas" "charge_gas". + +Axiom ethereum_muir_glacier_vm_memory_imports_buffer_read : + IsImported globals "ethereum.muir_glacier.vm.memory" "buffer_read". + +Axiom ethereum_muir_glacier_vm_exceptions_imports_OutOfGasError : + IsImported globals "ethereum.muir_glacier.vm.exceptions" "OutOfGasError". + +Definition alt_bn128_add : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + The ALT_BN128 addition precompiled contract. + + Parameters + ---------- + evm : + The current EVM frame. + " in + let _ := M.assign_local (| + "data" , + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "data" |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 150 + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "x0_bytes" , + M.call (| + M.get_name (| globals, "buffer_read" |), + make_list [ + M.get_name (| globals, "data" |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 32 + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "x0_value" , + M.call (| + M.get_field (| M.get_name (| globals, "U256" |), "from_be_bytes" |), + make_list [ + M.get_name (| globals, "x0_bytes" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "y0_bytes" , + M.call (| + M.get_name (| globals, "buffer_read" |), + make_list [ + M.get_name (| globals, "data" |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 32 + ], + make_dict [] + |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 32 + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "y0_value" , + M.call (| + M.get_field (| M.get_name (| globals, "U256" |), "from_be_bytes" |), + make_list [ + M.get_name (| globals, "y0_bytes" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "x1_bytes" , + M.call (| + M.get_name (| globals, "buffer_read" |), + make_list [ + M.get_name (| globals, "data" |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 64 + ], + make_dict [] + |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 32 + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "x1_value" , + M.call (| + M.get_field (| M.get_name (| globals, "U256" |), "from_be_bytes" |), + make_list [ + M.get_name (| globals, "x1_bytes" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "y1_bytes" , + M.call (| + M.get_name (| globals, "buffer_read" |), + make_list [ + M.get_name (| globals, "data" |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 96 + ], + make_dict [] + |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 32 + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "y1_value" , + M.call (| + M.get_field (| M.get_name (| globals, "U256" |), "from_be_bytes" |), + make_list [ + M.get_name (| globals, "y1_bytes" |) + ], + make_dict [] + |) + |) in + let _ := + M.for_ (| + M.get_name (| globals, "i" |), + make_tuple [ M.get_name (| globals, "x0_value" |); M.get_name (| globals, "y0_value" |); M.get_name (| globals, "x1_value" |); M.get_name (| globals, "y1_value" |) ], + ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + Compare.gt_e (| + M.get_name (| globals, "i" |), + M.get_name (| globals, "ALT_BN128_PRIME" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, "OutOfGasError" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in +(* At stmt: unsupported node type: Try *) + let _ := M.assign_local (| + "p" , + BinOp.add (| + M.get_name (| globals, "p0" |), + M.get_name (| globals, "p1" |) + |) + |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, "evm" |), "output" |), + BinOp.add (| + M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, "p" |), "x" |), "to_be_bytes32" |), + make_list [], + make_dict [] + |), + M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, "p" |), "y" |), "to_be_bytes32" |), + make_list [], + make_dict [] + |) + |) + |) in + M.pure Constant.None_)). + +Definition alt_bn128_mul : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + The ALT_BN128 multiplication precompiled contract. + + Parameters + ---------- + evm : + The current EVM frame. + " in + let _ := M.assign_local (| + "data" , + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "data" |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 6000 + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "x0_bytes" , + M.call (| + M.get_name (| globals, "buffer_read" |), + make_list [ + M.get_name (| globals, "data" |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 32 + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "x0_value" , + M.call (| + M.get_field (| M.get_name (| globals, "U256" |), "from_be_bytes" |), + make_list [ + M.get_name (| globals, "x0_bytes" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "y0_bytes" , + M.call (| + M.get_name (| globals, "buffer_read" |), + make_list [ + M.get_name (| globals, "data" |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 32 + ], + make_dict [] + |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 32 + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "y0_value" , + M.call (| + M.get_field (| M.get_name (| globals, "U256" |), "from_be_bytes" |), + make_list [ + M.get_name (| globals, "y0_bytes" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "n" , + M.call (| + M.get_field (| M.get_name (| globals, "U256" |), "from_be_bytes" |), + make_list [ + M.call (| + M.get_name (| globals, "buffer_read" |), + make_list [ + M.get_name (| globals, "data" |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 64 + ], + make_dict [] + |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 32 + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := + M.for_ (| + M.get_name (| globals, "i" |), + make_tuple [ M.get_name (| globals, "x0_value" |); M.get_name (| globals, "y0_value" |) ], + ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + Compare.gt_e (| + M.get_name (| globals, "i" |), + M.get_name (| globals, "ALT_BN128_PRIME" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, "OutOfGasError" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in +(* At stmt: unsupported node type: Try *) + let _ := M.assign_local (| + "p" , + M.call (| + M.get_field (| M.get_name (| globals, "p0" |), "mul_by" |), + make_list [ + M.get_name (| globals, "n" |) + ], + make_dict [] + |) + |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, "evm" |), "output" |), + BinOp.add (| + M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, "p" |), "x" |), "to_be_bytes32" |), + make_list [], + make_dict [] + |), + M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, "p" |), "y" |), "to_be_bytes32" |), + make_list [], + make_dict [] + |) + |) + |) in + M.pure Constant.None_)). + +Definition alt_bn128_pairing_check : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + The ALT_BN128 pairing check precompiled contract. + + Parameters + ---------- + evm : + The current EVM frame. + " in + let _ := M.assign_local (| + "data" , + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "data" |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + BinOp.add (| + BinOp.mult (| + Constant.int 34000, + BinOp.floor_div (| + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_name (| globals, "data" |) + ], + make_dict [] + |), + Constant.int 192 + |) + |), + Constant.int 45000 + |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.not_eq (| + BinOp.mod_ (| + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_name (| globals, "data" |) + ], + make_dict [] + |), + Constant.int 192 + |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, "OutOfGasError" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "result" , + M.call (| + M.get_field (| M.get_name (| globals, "BNF12" |), "from_int" |), + make_list [ + Constant.int 1 + ], + make_dict [] + |) + |) in + let _ := + M.for_ (| + M.get_name (| globals, "i" |), + M.call (| + M.get_name (| globals, "range" |), + make_list [ + BinOp.floor_div (| + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_name (| globals, "data" |) + ], + make_dict [] + |), + Constant.int 192 + |) + ], + make_dict [] + |), + ltac:(M.monadic ( + let _ := M.assign_local (| + "values" , + make_list [] + |) in + let _ := + M.for_ (| + M.get_name (| globals, "j" |), + M.call (| + M.get_name (| globals, "range" |), + make_list [ + Constant.int 6 + ], + make_dict [] + |), + ltac:(M.monadic ( + let _ := M.assign_local (| + "value" , + M.call (| + M.get_field (| M.get_name (| globals, "U256" |), "from_be_bytes" |), + make_list [ + M.slice (| + M.get_name (| globals, "data" |), + BinOp.add (| + BinOp.mult (| + M.get_name (| globals, "i" |), + Constant.int 192 + |), + BinOp.mult (| + Constant.int 32, + M.get_name (| globals, "j" |) + |) + |), + BinOp.add (| + BinOp.mult (| + M.get_name (| globals, "i" |), + Constant.int 192 + |), + BinOp.mult (| + Constant.int 32, + BinOp.add (| + M.get_name (| globals, "j" |), + Constant.int 1 + |) + |) + |), + Constant.None_ + |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.gt_e (| + M.get_name (| globals, "value" |), + M.get_name (| globals, "ALT_BN128_PRIME" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, "OutOfGasError" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.call (| + M.get_field (| M.get_name (| globals, "values" |), "append" |), + make_list [ + M.call (| + M.get_name (| globals, "int" |), + make_list [ + M.get_name (| globals, "value" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in +(* At stmt: unsupported node type: Try *) + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + Compare.eq (| + M.call (| + M.get_field (| M.get_name (| globals, "p" |), "mul_by" |), + make_list [ + M.get_name (| globals, "ALT_BN128_CURVE_ORDER" |) + ], + make_dict [] + |), + M.call (| + M.get_field (| M.get_name (| globals, "BNP" |), "point_at_infinity" |), + make_list [], + make_dict [] + |) + |); + M.get_name (| globals, "OutOfGasError" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + Compare.eq (| + M.call (| + M.get_field (| M.get_name (| globals, "q" |), "mul_by" |), + make_list [ + M.get_name (| globals, "ALT_BN128_CURVE_ORDER" |) + ], + make_dict [] + |), + M.call (| + M.get_field (| M.get_name (| globals, "BNP2" |), "point_at_infinity" |), + make_list [], + make_dict [] + |) + |); + M.get_name (| globals, "OutOfGasError" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + BoolOp.and (| + Compare.not_eq (| + M.get_name (| globals, "p" |), + M.call (| + M.get_field (| M.get_name (| globals, "BNP" |), "point_at_infinity" |), + make_list [], + make_dict [] + |) + |), + ltac:(M.monadic ( + Compare.not_eq (| + M.get_name (| globals, "q" |), + M.call (| + M.get_field (| M.get_name (| globals, "BNP2" |), "point_at_infinity" |), + make_list [], + make_dict [] + |) + |) + )) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "result" , + BinOp.mult (| + M.get_name (| globals, "result" |), + M.call (| + M.get_name (| globals, "pairing" |), + make_list [ + M.get_name (| globals, "q" |); + M.get_name (| globals, "p" |) + ], + make_dict [] + |) + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, "result" |), + M.call (| + M.get_field (| M.get_name (| globals, "BNF12" |), "from_int" |), + make_list [ + Constant.int 1 + ], + make_dict [] + |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign (| + M.get_field (| M.get_name (| globals, "evm" |), "output" |), + M.call (| + M.get_field (| M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 1 + ], + make_dict [] + |), "to_be_bytes32" |), + make_list [], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign (| + M.get_field (| M.get_name (| globals, "evm" |), "output" |), + M.call (| + M.get_field (| M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |), "to_be_bytes32" |), + make_list [], + make_dict [] + |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_)). diff --git a/CoqOfPython/ethereum/muir_glacier/vm/precompiled_contracts/blake2f.v b/CoqOfPython/ethereum/muir_glacier/vm/precompiled_contracts/blake2f.v new file mode 100644 index 0000000..4a75fc0 --- /dev/null +++ b/CoqOfPython/ethereum/muir_glacier/vm/precompiled_contracts/blake2f.v @@ -0,0 +1,127 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.muir_glacier.vm.precompiled_contracts.blake2f". + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) Blake2 PRECOMPILED CONTRACT +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementation of the `Blake2` precompiled contract. +". + +Axiom ethereum_crypto_blake2_imports_Blake2b : + IsImported globals "ethereum.crypto.blake2" "Blake2b". + +Axiom ethereum_utils_ensure_imports_ensure : + IsImported globals "ethereum.utils.ensure" "ensure". + +Axiom ethereum_muir_glacier_vm_imports_Evm : + IsImported globals "ethereum.muir_glacier.vm" "Evm". + +Axiom ethereum_muir_glacier_vm_gas_imports_GAS_BLAKE2_PER_ROUND : + IsImported globals "ethereum.muir_glacier.vm.gas" "GAS_BLAKE2_PER_ROUND". +Axiom ethereum_muir_glacier_vm_gas_imports_charge_gas : + IsImported globals "ethereum.muir_glacier.vm.gas" "charge_gas". + +Axiom ethereum_muir_glacier_vm_exceptions_imports_InvalidParameter : + IsImported globals "ethereum.muir_glacier.vm.exceptions" "InvalidParameter". + +Definition blake2f : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Writes the Blake2 hash to output. + + Parameters + ---------- + evm : + The current EVM frame. + " in + let _ := M.assign_local (| + "data" , + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "data" |) + |) in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + Compare.eq (| + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_name (| globals, "data" |) + ], + make_dict [] + |), + Constant.int 213 + |); + M.get_name (| globals, "InvalidParameter" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "blake2b" , + M.call (| + M.get_name (| globals, "Blake2b" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.assign (| + make_tuple [ M.get_name (| globals, "rounds" |); M.get_name (| globals, "h" |); M.get_name (| globals, "m" |); M.get_name (| globals, "t_0" |); M.get_name (| globals, "t_1" |); M.get_name (| globals, "f" |) ], + M.call (| + M.get_field (| M.get_name (| globals, "blake2b" |), "get_blake2_parameters" |), + make_list [ + M.get_name (| globals, "data" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + BinOp.mult (| + M.get_name (| globals, "GAS_BLAKE2_PER_ROUND" |), + M.get_name (| globals, "rounds" |) + |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + Compare.in_ (| + M.get_name (| globals, "f" |), + make_list [ + Constant.int 0; + Constant.int 1 + ] + |); + M.get_name (| globals, "InvalidParameter" |) + ], + make_dict [] + |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, "evm" |), "output" |), + M.call (| + M.get_field (| M.get_name (| globals, "blake2b" |), "compress" |), + make_list [ + M.get_name (| globals, "rounds" |); + M.get_name (| globals, "h" |); + M.get_name (| globals, "m" |); + M.get_name (| globals, "t_0" |); + M.get_name (| globals, "t_1" |); + M.get_name (| globals, "f" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). diff --git a/CoqOfPython/ethereum/muir_glacier/vm/precompiled_contracts/ecrecover.v b/CoqOfPython/ethereum/muir_glacier/vm/precompiled_contracts/ecrecover.v new file mode 100644 index 0000000..8312694 --- /dev/null +++ b/CoqOfPython/ethereum/muir_glacier/vm/precompiled_contracts/ecrecover.v @@ -0,0 +1,301 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.muir_glacier.vm.precompiled_contracts.ecrecover". + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) ECRECOVER PRECOMPILED CONTRACT +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementation of the ECRECOVER precompiled contract. +". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". + +Axiom ethereum_crypto_elliptic_curve_imports_SECP256K1N : + IsImported globals "ethereum.crypto.elliptic_curve" "SECP256K1N". +Axiom ethereum_crypto_elliptic_curve_imports_secp256k1_recover : + IsImported globals "ethereum.crypto.elliptic_curve" "secp256k1_recover". + +Axiom ethereum_crypto_hash_imports_Hash32 : + IsImported globals "ethereum.crypto.hash" "Hash32". +Axiom ethereum_crypto_hash_imports_keccak256 : + IsImported globals "ethereum.crypto.hash" "keccak256". + +Axiom ethereum_utils_byte_imports_left_pad_zero_bytes : + IsImported globals "ethereum.utils.byte" "left_pad_zero_bytes". + +Axiom ethereum_muir_glacier_vm_imports_Evm : + IsImported globals "ethereum.muir_glacier.vm" "Evm". + +Axiom ethereum_muir_glacier_vm_gas_imports_GAS_ECRECOVER : + IsImported globals "ethereum.muir_glacier.vm.gas" "GAS_ECRECOVER". +Axiom ethereum_muir_glacier_vm_gas_imports_charge_gas : + IsImported globals "ethereum.muir_glacier.vm.gas" "charge_gas". + +Axiom ethereum_muir_glacier_vm_memory_imports_buffer_read : + IsImported globals "ethereum.muir_glacier.vm.memory" "buffer_read". + +Definition ecrecover : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Decrypts the address using elliptic curve DSA recovery mechanism and writes + the address to output. + + Parameters + ---------- + evm : + The current EVM frame. + " in + let _ := M.assign_local (| + "data" , + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "data" |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_ECRECOVER" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "message_hash_bytes" , + M.call (| + M.get_name (| globals, "buffer_read" |), + make_list [ + M.get_name (| globals, "data" |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 32 + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "message_hash" , + M.call (| + M.get_name (| globals, "Hash32" |), + make_list [ + M.get_name (| globals, "message_hash_bytes" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "v" , + M.call (| + M.get_field (| M.get_name (| globals, "U256" |), "from_be_bytes" |), + make_list [ + M.call (| + M.get_name (| globals, "buffer_read" |), + make_list [ + M.get_name (| globals, "data" |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 32 + ], + make_dict [] + |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 32 + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "r" , + M.call (| + M.get_field (| M.get_name (| globals, "U256" |), "from_be_bytes" |), + make_list [ + M.call (| + M.get_name (| globals, "buffer_read" |), + make_list [ + M.get_name (| globals, "data" |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 64 + ], + make_dict [] + |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 32 + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "s" , + M.call (| + M.get_field (| M.get_name (| globals, "U256" |), "from_be_bytes" |), + make_list [ + M.call (| + M.get_name (| globals, "buffer_read" |), + make_list [ + M.get_name (| globals, "data" |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 96 + ], + make_dict [] + |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 32 + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + BoolOp.and (| + Compare.not_eq (| + M.get_name (| globals, "v" |), + Constant.int 27 + |), + ltac:(M.monadic ( + Compare.not_eq (| + M.get_name (| globals, "v" |), + Constant.int 28 + |) + )) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + Constant.None_ + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + BoolOp.or (| + Compare.gt_e (| + Constant.int 0, + M.get_name (| globals, "r" |) + |), + ltac:(M.monadic ( + Compare.gt_e (| + M.get_name (| globals, "r" |), + M.get_name (| globals, "SECP256K1N" |) + |) + )) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + Constant.None_ + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + BoolOp.or (| + Compare.gt_e (| + Constant.int 0, + M.get_name (| globals, "s" |) + |), + ltac:(M.monadic ( + Compare.gt_e (| + M.get_name (| globals, "s" |), + M.get_name (| globals, "SECP256K1N" |) + |) + )) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + Constant.None_ + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in +(* At stmt: unsupported node type: Try *) + let _ := M.assign_local (| + "address" , + M.slice (| + M.call (| + M.get_name (| globals, "keccak256" |), + make_list [ + M.get_name (| globals, "public_key" |) + ], + make_dict [] + |), + Constant.int 12, + Constant.int 32, + Constant.None_ + |) + |) in + let _ := M.assign_local (| + "padded_address" , + M.call (| + M.get_name (| globals, "left_pad_zero_bytes" |), + make_list [ + M.get_name (| globals, "address" |); + Constant.int 32 + ], + make_dict [] + |) + |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, "evm" |), "output" |), + M.get_name (| globals, "padded_address" |) + |) in + M.pure Constant.None_)). diff --git a/CoqOfPython/ethereum/muir_glacier/vm/precompiled_contracts/identity.v b/CoqOfPython/ethereum/muir_glacier/vm/precompiled_contracts/identity.v new file mode 100644 index 0000000..f2eb008 --- /dev/null +++ b/CoqOfPython/ethereum/muir_glacier/vm/precompiled_contracts/identity.v @@ -0,0 +1,94 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.muir_glacier.vm.precompiled_contracts.identity". + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) IDENTITY PRECOMPILED CONTRACT +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementation of the `IDENTITY` precompiled contract. +". + +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". + +Axiom ethereum_utils_numeric_imports_ceil32 : + IsImported globals "ethereum.utils.numeric" "ceil32". + +Axiom ethereum_muir_glacier_vm_imports_Evm : + IsImported globals "ethereum.muir_glacier.vm" "Evm". + +Axiom ethereum_muir_glacier_vm_gas_imports_GAS_IDENTITY : + IsImported globals "ethereum.muir_glacier.vm.gas" "GAS_IDENTITY". +Axiom ethereum_muir_glacier_vm_gas_imports_GAS_IDENTITY_WORD : + IsImported globals "ethereum.muir_glacier.vm.gas" "GAS_IDENTITY_WORD". +Axiom ethereum_muir_glacier_vm_gas_imports_charge_gas : + IsImported globals "ethereum.muir_glacier.vm.gas" "charge_gas". + +Definition identity : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Writes the message data to output. + + Parameters + ---------- + evm : + The current EVM frame. + " in + let _ := M.assign_local (| + "data" , + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "data" |) + |) in + let _ := M.assign_local (| + "word_count" , + BinOp.floor_div (| + M.call (| + M.get_name (| globals, "ceil32" |), + make_list [ + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_name (| globals, "data" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |), + Constant.int 32 + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + BinOp.add (| + M.get_name (| globals, "GAS_IDENTITY" |), + BinOp.mult (| + M.get_name (| globals, "GAS_IDENTITY_WORD" |), + M.get_name (| globals, "word_count" |) + |) + |) + ], + make_dict [] + |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, "evm" |), "output" |), + M.get_name (| globals, "data" |) + |) in + M.pure Constant.None_)). diff --git a/CoqOfPython/ethereum/muir_glacier/vm/precompiled_contracts/mapping.v b/CoqOfPython/ethereum/muir_glacier/vm/precompiled_contracts/mapping.v new file mode 100644 index 0000000..e59e8d5 --- /dev/null +++ b/CoqOfPython/ethereum/muir_glacier/vm/precompiled_contracts/mapping.v @@ -0,0 +1,72 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.muir_glacier.vm.precompiled_contracts.mapping". + +Definition expr_1 : Value.t := + Constant.str " +Precompiled Contract Addresses +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Mapping of precompiled contracts their implementations. +". + +Axiom typing_imports_Callable : + IsImported globals "typing" "Callable". +Axiom typing_imports_Dict : + IsImported globals "typing" "Dict". + +Axiom ethereum_muir_glacier_fork_types_imports_Address : + IsImported globals "ethereum.muir_glacier.fork_types" "Address". + +Axiom ethereum_muir_glacier_vm_precompiled_contracts_imports_ALT_BN128_ADD_ADDRESS : + IsImported globals "ethereum.muir_glacier.vm.precompiled_contracts" "ALT_BN128_ADD_ADDRESS". +Axiom ethereum_muir_glacier_vm_precompiled_contracts_imports_ALT_BN128_MUL_ADDRESS : + IsImported globals "ethereum.muir_glacier.vm.precompiled_contracts" "ALT_BN128_MUL_ADDRESS". +Axiom ethereum_muir_glacier_vm_precompiled_contracts_imports_ALT_BN128_PAIRING_CHECK_ADDRESS : + IsImported globals "ethereum.muir_glacier.vm.precompiled_contracts" "ALT_BN128_PAIRING_CHECK_ADDRESS". +Axiom ethereum_muir_glacier_vm_precompiled_contracts_imports_BLAKE2F_ADDRESS : + IsImported globals "ethereum.muir_glacier.vm.precompiled_contracts" "BLAKE2F_ADDRESS". +Axiom ethereum_muir_glacier_vm_precompiled_contracts_imports_ECRECOVER_ADDRESS : + IsImported globals "ethereum.muir_glacier.vm.precompiled_contracts" "ECRECOVER_ADDRESS". +Axiom ethereum_muir_glacier_vm_precompiled_contracts_imports_IDENTITY_ADDRESS : + IsImported globals "ethereum.muir_glacier.vm.precompiled_contracts" "IDENTITY_ADDRESS". +Axiom ethereum_muir_glacier_vm_precompiled_contracts_imports_MODEXP_ADDRESS : + IsImported globals "ethereum.muir_glacier.vm.precompiled_contracts" "MODEXP_ADDRESS". +Axiom ethereum_muir_glacier_vm_precompiled_contracts_imports_RIPEMD160_ADDRESS : + IsImported globals "ethereum.muir_glacier.vm.precompiled_contracts" "RIPEMD160_ADDRESS". +Axiom ethereum_muir_glacier_vm_precompiled_contracts_imports_SHA256_ADDRESS : + IsImported globals "ethereum.muir_glacier.vm.precompiled_contracts" "SHA256_ADDRESS". + +Axiom ethereum_muir_glacier_vm_precompiled_contracts_alt_bn128_imports_alt_bn128_add : + IsImported globals "ethereum.muir_glacier.vm.precompiled_contracts.alt_bn128" "alt_bn128_add". +Axiom ethereum_muir_glacier_vm_precompiled_contracts_alt_bn128_imports_alt_bn128_mul : + IsImported globals "ethereum.muir_glacier.vm.precompiled_contracts.alt_bn128" "alt_bn128_mul". +Axiom ethereum_muir_glacier_vm_precompiled_contracts_alt_bn128_imports_alt_bn128_pairing_check : + IsImported globals "ethereum.muir_glacier.vm.precompiled_contracts.alt_bn128" "alt_bn128_pairing_check". + +Axiom ethereum_muir_glacier_vm_precompiled_contracts_blake2f_imports_blake2f : + IsImported globals "ethereum.muir_glacier.vm.precompiled_contracts.blake2f" "blake2f". + +Axiom ethereum_muir_glacier_vm_precompiled_contracts_ecrecover_imports_ecrecover : + IsImported globals "ethereum.muir_glacier.vm.precompiled_contracts.ecrecover" "ecrecover". + +Axiom ethereum_muir_glacier_vm_precompiled_contracts_identity_imports_identity : + IsImported globals "ethereum.muir_glacier.vm.precompiled_contracts.identity" "identity". + +Axiom ethereum_muir_glacier_vm_precompiled_contracts_modexp_imports_modexp : + IsImported globals "ethereum.muir_glacier.vm.precompiled_contracts.modexp" "modexp". + +Axiom ethereum_muir_glacier_vm_precompiled_contracts_ripemd160_imports_ripemd160 : + IsImported globals "ethereum.muir_glacier.vm.precompiled_contracts.ripemd160" "ripemd160". + +Axiom ethereum_muir_glacier_vm_precompiled_contracts_sha256_imports_sha256 : + IsImported globals "ethereum.muir_glacier.vm.precompiled_contracts.sha256" "sha256". + +(* At top_level_stmt: unsupported node type: AnnAssign *) diff --git a/CoqOfPython/ethereum/muir_glacier/vm/precompiled_contracts/modexp.v b/CoqOfPython/ethereum/muir_glacier/vm/precompiled_contracts/modexp.v new file mode 100644 index 0000000..adf5841 --- /dev/null +++ b/CoqOfPython/ethereum/muir_glacier/vm/precompiled_contracts/modexp.v @@ -0,0 +1,544 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.muir_glacier.vm.precompiled_contracts.modexp". + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) MODEXP PRECOMPILED CONTRACT +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementation of the `MODEXP` precompiled contract. +". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_Bytes : + IsImported globals "ethereum.base_types" "Bytes". +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". + +Axiom ethereum_muir_glacier_vm_imports_Evm : + IsImported globals "ethereum.muir_glacier.vm" "Evm". + +Axiom ethereum_muir_glacier_vm_gas_imports_charge_gas : + IsImported globals "ethereum.muir_glacier.vm.gas" "charge_gas". + +Axiom ethereum_muir_glacier_vm_memory_imports_buffer_read : + IsImported globals "ethereum.muir_glacier.vm.memory" "buffer_read". + +Definition GQUADDIVISOR : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 20 + ], + make_dict [] + |) +)). + +Definition modexp : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Calculates `(base**exp) % modulus` for arbitrary sized `base`, `exp` and. + `modulus`. The return value is the same length as the modulus. + " in + let _ := M.assign_local (| + "data" , + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "data" |) + |) in + let _ := M.assign_local (| + "base_length" , + M.call (| + M.get_field (| M.get_name (| globals, "U256" |), "from_be_bytes" |), + make_list [ + M.call (| + M.get_name (| globals, "buffer_read" |), + make_list [ + M.get_name (| globals, "data" |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 32 + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "exp_length" , + M.call (| + M.get_field (| M.get_name (| globals, "U256" |), "from_be_bytes" |), + make_list [ + M.call (| + M.get_name (| globals, "buffer_read" |), + make_list [ + M.get_name (| globals, "data" |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 32 + ], + make_dict [] + |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 32 + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "modulus_length" , + M.call (| + M.get_field (| M.get_name (| globals, "U256" |), "from_be_bytes" |), + make_list [ + M.call (| + M.get_name (| globals, "buffer_read" |), + make_list [ + M.get_name (| globals, "data" |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 64 + ], + make_dict [] + |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 32 + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "exp_start" , + BinOp.add (| + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 96 + ], + make_dict [] + |), + M.get_name (| globals, "base_length" |) + |) + |) in + let _ := M.assign_local (| + "exp_head" , + M.call (| + M.get_field (| M.get_name (| globals, "U256" |), "from_be_bytes" |), + make_list [ + M.call (| + M.get_name (| globals, "buffer_read" |), + make_list [ + M.get_name (| globals, "data" |); + M.get_name (| globals, "exp_start" |); + M.call (| + M.get_name (| globals, "min" |), + make_list [ + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 32 + ], + make_dict [] + |); + M.get_name (| globals, "exp_length" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.lt (| + M.get_name (| globals, "exp_length" |), + Constant.int 32 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "adjusted_exp_length" , + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, "max" |), + make_list [ + Constant.int 0; + BinOp.sub (| + M.call (| + M.get_field (| M.get_name (| globals, "exp_head" |), "bit_length" |), + make_list [], + make_dict [] + |), + Constant.int 1 + |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "adjusted_exp_length" , + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + BinOp.add (| + BinOp.mult (| + Constant.int 8, + BinOp.sub (| + M.call (| + M.get_name (| globals, "int" |), + make_list [ + M.get_name (| globals, "exp_length" |) + ], + make_dict [] + |), + Constant.int 32 + |) + |), + M.call (| + M.get_name (| globals, "max" |), + make_list [ + Constant.int 0; + BinOp.sub (| + M.call (| + M.get_field (| M.get_name (| globals, "exp_head" |), "bit_length" |), + make_list [], + make_dict [] + |), + Constant.int 1 + |) + ], + make_dict [] + |) + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + )) |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + BinOp.floor_div (| + BinOp.mult (| + M.call (| + M.get_name (| globals, "get_mult_complexity" |), + make_list [ + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, "max" |), + make_list [ + M.get_name (| globals, "base_length" |); + M.get_name (| globals, "modulus_length" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |), + M.call (| + M.get_name (| globals, "max" |), + make_list [ + M.get_name (| globals, "adjusted_exp_length" |); + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 1 + ], + make_dict [] + |) + ], + make_dict [] + |) + |), + M.get_name (| globals, "GQUADDIVISOR" |) + |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + BoolOp.and (| + Compare.eq (| + M.get_name (| globals, "base_length" |), + Constant.int 0 + |), + ltac:(M.monadic ( + Compare.eq (| + M.get_name (| globals, "modulus_length" |), + Constant.int 0 + |) + )) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign (| + M.get_field (| M.get_name (| globals, "evm" |), "output" |), + M.call (| + M.get_name (| globals, "Bytes" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.return_ (| + Constant.None_ + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "base" , + M.call (| + M.get_field (| M.get_name (| globals, "Uint" |), "from_be_bytes" |), + make_list [ + M.call (| + M.get_name (| globals, "buffer_read" |), + make_list [ + M.get_name (| globals, "data" |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 96 + ], + make_dict [] + |); + M.get_name (| globals, "base_length" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "exp" , + M.call (| + M.get_field (| M.get_name (| globals, "Uint" |), "from_be_bytes" |), + make_list [ + M.call (| + M.get_name (| globals, "buffer_read" |), + make_list [ + M.get_name (| globals, "data" |); + M.get_name (| globals, "exp_start" |); + M.get_name (| globals, "exp_length" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "modulus_start" , + BinOp.add (| + M.get_name (| globals, "exp_start" |), + M.get_name (| globals, "exp_length" |) + |) + |) in + let _ := M.assign_local (| + "modulus" , + M.call (| + M.get_field (| M.get_name (| globals, "Uint" |), "from_be_bytes" |), + make_list [ + M.call (| + M.get_name (| globals, "buffer_read" |), + make_list [ + M.get_name (| globals, "data" |); + M.get_name (| globals, "modulus_start" |); + M.get_name (| globals, "modulus_length" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, "modulus" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign (| + M.get_field (| M.get_name (| globals, "evm" |), "output" |), + BinOp.mult (| + M.call (| + M.get_name (| globals, "Bytes" |), + make_list [ + Constant.bytes "00" + ], + make_dict [] + |), + M.get_name (| globals, "modulus_length" |) + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign (| + M.get_field (| M.get_name (| globals, "evm" |), "output" |), + M.call (| + M.get_field (| M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, "pow" |), + make_list [ + M.get_name (| globals, "base" |); + M.get_name (| globals, "exp" |); + M.get_name (| globals, "modulus" |) + ], + make_dict [] + |) + ], + make_dict [] + |), "to_bytes" |), + make_list [ + M.get_name (| globals, "modulus_length" |); + Constant.str "big" + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_)). + +Definition get_mult_complexity : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "x" ] |) in + let _ := Constant.str " + Estimate the complexity of performing Karatsuba multiplication. + " in + let _ := + (* if *) + M.if_then_else (| + Compare.lt_e (| + M.get_name (| globals, "x" |), + Constant.int 64 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + BinOp.pow (| + M.get_name (| globals, "x" |), + Constant.int 2 + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + Compare.lt_e (| + M.get_name (| globals, "x" |), + Constant.int 1024 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + BinOp.sub (| + BinOp.add (| + BinOp.floor_div (| + BinOp.pow (| + M.get_name (| globals, "x" |), + Constant.int 2 + |), + Constant.int 4 + |), + BinOp.mult (| + Constant.int 96, + M.get_name (| globals, "x" |) + |) + |), + Constant.int 3072 + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.return_ (| + BinOp.sub (| + BinOp.add (| + BinOp.floor_div (| + BinOp.pow (| + M.get_name (| globals, "x" |), + Constant.int 2 + |), + Constant.int 16 + |), + BinOp.mult (| + Constant.int 480, + M.get_name (| globals, "x" |) + |) + |), + Constant.int 199680 + |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_)). diff --git a/CoqOfPython/ethereum/muir_glacier/vm/precompiled_contracts/ripemd160.v b/CoqOfPython/ethereum/muir_glacier/vm/precompiled_contracts/ripemd160.v new file mode 100644 index 0000000..d68f6cf --- /dev/null +++ b/CoqOfPython/ethereum/muir_glacier/vm/precompiled_contracts/ripemd160.v @@ -0,0 +1,125 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.muir_glacier.vm.precompiled_contracts.ripemd160". + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) RIPEMD160 PRECOMPILED CONTRACT +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementation of the `RIPEMD160` precompiled contract. +". + +(* At top_level_stmt: unsupported node type: Import *) + +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". + +Axiom ethereum_utils_byte_imports_left_pad_zero_bytes : + IsImported globals "ethereum.utils.byte" "left_pad_zero_bytes". + +Axiom ethereum_utils_numeric_imports_ceil32 : + IsImported globals "ethereum.utils.numeric" "ceil32". + +Axiom ethereum_muir_glacier_vm_imports_Evm : + IsImported globals "ethereum.muir_glacier.vm" "Evm". + +Axiom ethereum_muir_glacier_vm_gas_imports_GAS_RIPEMD160 : + IsImported globals "ethereum.muir_glacier.vm.gas" "GAS_RIPEMD160". +Axiom ethereum_muir_glacier_vm_gas_imports_GAS_RIPEMD160_WORD : + IsImported globals "ethereum.muir_glacier.vm.gas" "GAS_RIPEMD160_WORD". +Axiom ethereum_muir_glacier_vm_gas_imports_charge_gas : + IsImported globals "ethereum.muir_glacier.vm.gas" "charge_gas". + +Definition ripemd160 : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Writes the ripemd160 hash to output. + + Parameters + ---------- + evm : + The current EVM frame. + " in + let _ := M.assign_local (| + "data" , + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "data" |) + |) in + let _ := M.assign_local (| + "word_count" , + BinOp.floor_div (| + M.call (| + M.get_name (| globals, "ceil32" |), + make_list [ + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_name (| globals, "data" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |), + Constant.int 32 + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + BinOp.add (| + M.get_name (| globals, "GAS_RIPEMD160" |), + BinOp.mult (| + M.get_name (| globals, "GAS_RIPEMD160_WORD" |), + M.get_name (| globals, "word_count" |) + |) + |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "hash_bytes" , + M.call (| + M.get_field (| M.call (| + M.get_field (| M.get_name (| globals, "hashlib" |), "new" |), + make_list [ + Constant.str "ripemd160"; + M.get_name (| globals, "data" |) + ], + make_dict [] + |), "digest" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "padded_hash" , + M.call (| + M.get_name (| globals, "left_pad_zero_bytes" |), + make_list [ + M.get_name (| globals, "hash_bytes" |); + Constant.int 32 + ], + make_dict [] + |) + |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, "evm" |), "output" |), + M.get_name (| globals, "padded_hash" |) + |) in + M.pure Constant.None_)). diff --git a/CoqOfPython/ethereum/muir_glacier/vm/precompiled_contracts/sha256.v b/CoqOfPython/ethereum/muir_glacier/vm/precompiled_contracts/sha256.v new file mode 100644 index 0000000..778e74c --- /dev/null +++ b/CoqOfPython/ethereum/muir_glacier/vm/precompiled_contracts/sha256.v @@ -0,0 +1,106 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.muir_glacier.vm.precompiled_contracts.sha256". + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) SHA256 PRECOMPILED CONTRACT +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementation of the `SHA256` precompiled contract. +". + +(* At top_level_stmt: unsupported node type: Import *) + +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". + +Axiom ethereum_utils_numeric_imports_ceil32 : + IsImported globals "ethereum.utils.numeric" "ceil32". + +Axiom ethereum_muir_glacier_vm_imports_Evm : + IsImported globals "ethereum.muir_glacier.vm" "Evm". + +Axiom ethereum_muir_glacier_vm_gas_imports_GAS_SHA256 : + IsImported globals "ethereum.muir_glacier.vm.gas" "GAS_SHA256". +Axiom ethereum_muir_glacier_vm_gas_imports_GAS_SHA256_WORD : + IsImported globals "ethereum.muir_glacier.vm.gas" "GAS_SHA256_WORD". +Axiom ethereum_muir_glacier_vm_gas_imports_charge_gas : + IsImported globals "ethereum.muir_glacier.vm.gas" "charge_gas". + +Definition sha256 : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Writes the sha256 hash to output. + + Parameters + ---------- + evm : + The current EVM frame. + " in + let _ := M.assign_local (| + "data" , + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "data" |) + |) in + let _ := M.assign_local (| + "word_count" , + BinOp.floor_div (| + M.call (| + M.get_name (| globals, "ceil32" |), + make_list [ + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_name (| globals, "data" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |), + Constant.int 32 + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + BinOp.add (| + M.get_name (| globals, "GAS_SHA256" |), + BinOp.mult (| + M.get_name (| globals, "GAS_SHA256_WORD" |), + M.get_name (| globals, "word_count" |) + |) + |) + ], + make_dict [] + |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, "evm" |), "output" |), + M.call (| + M.get_field (| M.call (| + M.get_field (| M.get_name (| globals, "hashlib" |), "sha256" |), + make_list [ + M.get_name (| globals, "data" |) + ], + make_dict [] + |), "digest" |), + make_list [], + make_dict [] + |) + |) in + M.pure Constant.None_)). diff --git a/CoqOfPython/ethereum/muir_glacier/vm/runtime.v b/CoqOfPython/ethereum/muir_glacier/vm/runtime.v new file mode 100644 index 0000000..b541b08 --- /dev/null +++ b/CoqOfPython/ethereum/muir_glacier/vm/runtime.v @@ -0,0 +1,157 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.muir_glacier.vm.runtime". + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) Runtime Operations +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Runtime related operations used while executing EVM code. +". + +Axiom typing_imports_Set : + IsImported globals "typing" "Set". + +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". + +Axiom ethereum_muir_glacier_vm_instructions_imports_Ops : + IsImported globals "ethereum.muir_glacier.vm.instructions" "Ops". + +Definition get_valid_jump_destinations : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "code" ] |) in + let _ := Constant.str " + Analyze the evm code to obtain the set of valid jump destinations. + + Valid jump destinations are defined as follows: + * The jump destination is less than the length of the code. + * The jump destination should have the `JUMPDEST` opcode (0x5B). + * The jump destination shouldn't be part of the data corresponding to + `PUSH-N` opcodes. + + Note - Jump destinations are 0-indexed. + + Parameters + ---------- + code : + The EVM code which is to be executed. + + Returns + ------- + valid_jump_destinations: `Set[Uint]` + The set of valid jump destinations in the code. + " in + let _ := M.assign_local (| + "valid_jump_destinations" , + M.call (| + M.get_name (| globals, "set" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "pc" , + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + |) in + let _ := + M.while (| + Compare.lt (| + M.get_name (| globals, "pc" |), + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_name (| globals, "code" |) + ], + make_dict [] + |) + |), + ltac:(M.monadic ( +(* At stmt: unsupported node type: Try *) + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, "current_opcode" |), + M.get_field (| M.get_name (| globals, "Ops" |), "JUMPDEST" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_field (| M.get_name (| globals, "valid_jump_destinations" |), "add" |), + make_list [ + M.get_name (| globals, "pc" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + BoolOp.and (| + Compare.lt_e (| + M.get_field (| M.get_field (| M.get_name (| globals, "Ops" |), "PUSH1" |), "value" |), + M.get_field (| M.get_name (| globals, "current_opcode" |), "value" |) + |), + ltac:(M.monadic ( + Compare.lt_e (| + M.get_field (| M.get_name (| globals, "current_opcode" |), "value" |), + M.get_field (| M.get_field (| M.get_name (| globals, "Ops" |), "PUSH32" |), "value" |) + |) + )) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "push_data_size" , + BinOp.add (| + BinOp.sub (| + M.get_field (| M.get_name (| globals, "current_opcode" |), "value" |), + M.get_field (| M.get_field (| M.get_name (| globals, "Ops" |), "PUSH1" |), "value" |) + |), + Constant.int 1 + |) + |) in + let _ := M.assign_op_local (| + BinOp.add, + "pc", + M.get_name (| globals, "push_data_size" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )) |) in + let _ := M.assign_op_local (| + BinOp.add, + "pc", + Constant.int 1 + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := M.return_ (| + M.get_name (| globals, "valid_jump_destinations" |) + |) in + M.pure Constant.None_)). diff --git a/CoqOfPython/ethereum/muir_glacier/vm/stack.v b/CoqOfPython/ethereum/muir_glacier/vm/stack.v new file mode 100644 index 0000000..41a8707 --- /dev/null +++ b/CoqOfPython/ethereum/muir_glacier/vm/stack.v @@ -0,0 +1,123 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.muir_glacier.vm.stack". + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) Stack +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementation of the stack operators for the EVM. +". + +Axiom typing_imports_List : + IsImported globals "typing" "List". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". + +Axiom ethereum_muir_glacier_vm_exceptions_imports_StackOverflowError : + IsImported globals "ethereum.muir_glacier.vm.exceptions" "StackOverflowError". +Axiom ethereum_muir_glacier_vm_exceptions_imports_StackUnderflowError : + IsImported globals "ethereum.muir_glacier.vm.exceptions" "StackUnderflowError". + +Definition pop : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "stack" ] |) in + let _ := Constant.str " + Pops the top item off of `stack`. + + Parameters + ---------- + stack : + EVM stack. + + Returns + ------- + value : `U256` + The top element on the stack. + + " in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_name (| globals, "stack" |) + ], + make_dict [] + |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, "StackUnderflowError" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.return_ (| + M.call (| + M.get_field (| M.get_name (| globals, "stack" |), "pop" |), + make_list [], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Definition push : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "stack"; "value" ] |) in + let _ := Constant.str " + Pushes `value` onto `stack`. + + Parameters + ---------- + stack : + EVM stack. + + value : + Item to be pushed onto `stack`. + + " in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_name (| globals, "stack" |) + ], + make_dict [] + |), + Constant.int 1024 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, "StackOverflowError" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.return_ (| + M.call (| + M.get_field (| M.get_name (| globals, "stack" |), "append" |), + make_list [ + M.get_name (| globals, "value" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). diff --git a/CoqOfPython/ethereum/paris/__init__.v b/CoqOfPython/ethereum/paris/__init__.v new file mode 100644 index 0000000..fa10075 --- /dev/null +++ b/CoqOfPython/ethereum/paris/__init__.v @@ -0,0 +1,26 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.paris.__init__". + +Definition expr_1 : Value.t := + Constant.str " +The Paris fork transitions Ethereum from a proof-of-work consensus model to a +proof-of-stake one. This fork is often referred to as ""The Merge"" because it +marks the integration of the [consensus layer] with the execution layer +(defined in this project.) + +[consensus layer]: https://github.com/ethereum/consensus-specs +". + +Axiom ethereum_fork_criteria_imports_ByBlockNumber : + IsImported globals "ethereum.fork_criteria" "ByBlockNumber". + +Definition FORK_CRITERIA : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "ByBlockNumber" |), + make_list [ + Constant.int 15537394 + ], + make_dict [] + |) +)). diff --git a/CoqOfPython/ethereum/paris/blocks.v b/CoqOfPython/ethereum/paris/blocks.v new file mode 100644 index 0000000..2aa7600 --- /dev/null +++ b/CoqOfPython/ethereum/paris/blocks.v @@ -0,0 +1,89 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.paris.blocks". + +Definition expr_1 : Value.t := + Constant.str " +A `Block` is a single link in the chain that is Ethereum. Each `Block` contains +a `Header` and zero or more transactions. Each `Header` contains associated +metadata like the block number, parent block hash, and how much gas was +consumed by its transactions. + +Together, these blocks form a cryptographically secure journal recording the +history of all state transitions that have happened since the genesis of the +chain. +". + +Axiom dataclasses_imports_dataclass : + IsImported globals "dataclasses" "dataclass". + +Axiom typing_imports_Tuple : + IsImported globals "typing" "Tuple". +Axiom typing_imports_Union : + IsImported globals "typing" "Union". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_Bytes : + IsImported globals "ethereum.base_types" "Bytes". +Axiom ethereum_base_types_imports_Bytes8 : + IsImported globals "ethereum.base_types" "Bytes8". +Axiom ethereum_base_types_imports_Bytes32 : + IsImported globals "ethereum.base_types" "Bytes32". +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". +Axiom ethereum_base_types_imports_slotted_freezable : + IsImported globals "ethereum.base_types" "slotted_freezable". + +Axiom ethereum_crypto_hash_imports_Hash32 : + IsImported globals "ethereum.crypto.hash" "Hash32". + +Axiom ethereum_paris_fork_types_imports_Address : + IsImported globals "ethereum.paris.fork_types" "Address". +Axiom ethereum_paris_fork_types_imports_Bloom : + IsImported globals "ethereum.paris.fork_types" "Bloom". +Axiom ethereum_paris_fork_types_imports_Root : + IsImported globals "ethereum.paris.fork_types" "Root". + +Axiom ethereum_paris_transactions_imports_LegacyTransaction : + IsImported globals "ethereum.paris.transactions" "LegacyTransaction". + +Definition Header : Value.t := + builtins.make_klass + [] + [ + + ] + [ + + ]. + +Definition Block : Value.t := + builtins.make_klass + [] + [ + + ] + [ + + ]. + +Definition Log : Value.t := + builtins.make_klass + [] + [ + + ] + [ + + ]. + +Definition Receipt : Value.t := + builtins.make_klass + [] + [ + + ] + [ + + ]. diff --git a/CoqOfPython/ethereum/paris/bloom.v b/CoqOfPython/ethereum/paris/bloom.v new file mode 100644 index 0000000..6f6cc6b --- /dev/null +++ b/CoqOfPython/ethereum/paris/bloom.v @@ -0,0 +1,207 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.paris.bloom". + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Logs Bloom +^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +This modules defines functions for calculating bloom filters of logs. For the +general theory of bloom filters see e.g. `Wikipedia +`_. Bloom filters are used to allow +for efficient searching of logs by address and/or topic, by rapidly +eliminating blocks and receipts from their search. +". + +Axiom typing_imports_Tuple : + IsImported globals "typing" "Tuple". + +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". + +Axiom ethereum_crypto_hash_imports_keccak256 : + IsImported globals "ethereum.crypto.hash" "keccak256". + +Axiom ethereum_paris_blocks_imports_Log : + IsImported globals "ethereum.paris.blocks" "Log". + +Axiom ethereum_paris_fork_types_imports_Bloom : + IsImported globals "ethereum.paris.fork_types" "Bloom". + +Definition add_to_bloom : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "bloom"; "bloom_entry" ] |) in + let _ := Constant.str " + Add a bloom entry to the bloom filter (`bloom`). + + The number of hash functions used is 3. They are calculated by taking the + least significant 11 bits from the first 3 16-bit words of the + `keccak_256()` hash of `bloom_entry`. + + Parameters + ---------- + bloom : + The bloom filter. + bloom_entry : + An entry which is to be added to bloom filter. + " in + let _ := M.assign_local (| + "hash" , + M.call (| + M.get_name (| globals, "keccak256" |), + make_list [ + M.get_name (| globals, "bloom_entry" |) + ], + make_dict [] + |) + |) in + let _ := + M.for_ (| + M.get_name (| globals, "idx" |), + make_tuple [ Constant.int 0; Constant.int 2; Constant.int 4 ], + ltac:(M.monadic ( + let _ := M.assign_local (| + "bit_to_set" , + BinOp.bit_and (| + M.call (| + M.get_field (| M.get_name (| globals, "Uint" |), "from_be_bytes" |), + make_list [ + M.slice (| + M.get_name (| globals, "hash" |), + M.get_name (| globals, "idx" |), + BinOp.add (| + M.get_name (| globals, "idx" |), + Constant.int 2 + |), + Constant.None_ + |) + ], + make_dict [] + |), + Constant.int 2047 + |) + |) in + let _ := M.assign_local (| + "bit_index" , + BinOp.sub (| + Constant.int 2047, + M.get_name (| globals, "bit_to_set" |) + |) + |) in + let _ := M.assign_local (| + "byte_index" , + BinOp.floor_div (| + M.get_name (| globals, "bit_index" |), + Constant.int 8 + |) + |) in + let _ := M.assign_local (| + "bit_value" , + BinOp.l_shift (| + Constant.int 1, + BinOp.sub (| + Constant.int 7, + BinOp.mod_ (| + M.get_name (| globals, "bit_index" |), + Constant.int 8 + |) + |) + |) + |) in + let _ := M.assign (| + M.get_subscript (| + M.get_name (| globals, "bloom" |), + M.get_name (| globals, "byte_index" |) + |), + BinOp.bit_or (| + M.get_subscript (| + M.get_name (| globals, "bloom" |), + M.get_name (| globals, "byte_index" |) + |), + M.get_name (| globals, "bit_value" |) + |) + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + M.pure Constant.None_)). + +Definition logs_bloom : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "logs" ] |) in + let _ := Constant.str " + Obtain the logs bloom from a list of log entries. + + The address and each topic of a log are added to the bloom filter. + + Parameters + ---------- + logs : + List of logs for which the logs bloom is to be obtained. + + Returns + ------- + logs_bloom : `Bloom` + The logs bloom obtained which is 256 bytes with some bits set as per + the caller address and the log topics. + " in +(* At stmt: unsupported node type: AnnAssign *) + let _ := + M.for_ (| + M.get_name (| globals, "log" |), + M.get_name (| globals, "logs" |), + ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, "add_to_bloom" |), + make_list [ + M.get_name (| globals, "bloom" |); + M.get_field (| M.get_name (| globals, "log" |), "address" |) + ], + make_dict [] + |) in + let _ := + M.for_ (| + M.get_name (| globals, "topic" |), + M.get_field (| M.get_name (| globals, "log" |), "topics" |), + ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, "add_to_bloom" |), + make_list [ + M.get_name (| globals, "bloom" |); + M.get_name (| globals, "topic" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, "Bloom" |), + make_list [ + M.get_name (| globals, "bloom" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). diff --git a/CoqOfPython/ethereum/paris/fork.v b/CoqOfPython/ethereum/paris/fork.v new file mode 100644 index 0000000..442ce2d --- /dev/null +++ b/CoqOfPython/ethereum/paris/fork.v @@ -0,0 +1,2565 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.paris.fork". + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Specification +^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Entry point for the Ethereum specification. +". + +Axiom dataclasses_imports_dataclass : + IsImported globals "dataclasses" "dataclass". + +Axiom typing_imports_List : + IsImported globals "typing" "List". +Axiom typing_imports_Optional : + IsImported globals "typing" "Optional". +Axiom typing_imports_Tuple : + IsImported globals "typing" "Tuple". +Axiom typing_imports_Union : + IsImported globals "typing" "Union". + +Axiom ethereum_base_types_imports_Bytes0 : + IsImported globals "ethereum.base_types" "Bytes0". +Axiom ethereum_base_types_imports_Bytes32 : + IsImported globals "ethereum.base_types" "Bytes32". + +Axiom ethereum_crypto_elliptic_curve_imports_SECP256K1N : + IsImported globals "ethereum.crypto.elliptic_curve" "SECP256K1N". +Axiom ethereum_crypto_elliptic_curve_imports_secp256k1_recover : + IsImported globals "ethereum.crypto.elliptic_curve" "secp256k1_recover". + +Axiom ethereum_crypto_hash_imports_Hash32 : + IsImported globals "ethereum.crypto.hash" "Hash32". +Axiom ethereum_crypto_hash_imports_keccak256 : + IsImported globals "ethereum.crypto.hash" "keccak256". + +Axiom ethereum_exceptions_imports_InvalidBlock : + IsImported globals "ethereum.exceptions" "InvalidBlock". + +Axiom ethereum_utils_ensure_imports_ensure : + IsImported globals "ethereum.utils.ensure" "ensure". + +Axiom ethereum_imports_rlp : + IsImported globals "ethereum" "rlp". + +Axiom ethereum_base_types_imports_U64 : + IsImported globals "ethereum.base_types" "U64". +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_Bytes : + IsImported globals "ethereum.base_types" "Bytes". +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". + +Axiom ethereum_paris_imports_vm : + IsImported globals "ethereum.paris" "vm". + +Axiom ethereum_paris_blocks_imports_Block : + IsImported globals "ethereum.paris.blocks" "Block". +Axiom ethereum_paris_blocks_imports_Header : + IsImported globals "ethereum.paris.blocks" "Header". +Axiom ethereum_paris_blocks_imports_Log : + IsImported globals "ethereum.paris.blocks" "Log". +Axiom ethereum_paris_blocks_imports_Receipt : + IsImported globals "ethereum.paris.blocks" "Receipt". + +Axiom ethereum_paris_bloom_imports_logs_bloom : + IsImported globals "ethereum.paris.bloom" "logs_bloom". + +Axiom ethereum_paris_fork_types_imports_Address : + IsImported globals "ethereum.paris.fork_types" "Address". +Axiom ethereum_paris_fork_types_imports_Bloom : + IsImported globals "ethereum.paris.fork_types" "Bloom". +Axiom ethereum_paris_fork_types_imports_Root : + IsImported globals "ethereum.paris.fork_types" "Root". + +Axiom ethereum_paris_state_imports_State : + IsImported globals "ethereum.paris.state" "State". +Axiom ethereum_paris_state_imports_account_exists_and_is_empty : + IsImported globals "ethereum.paris.state" "account_exists_and_is_empty". +Axiom ethereum_paris_state_imports_destroy_account : + IsImported globals "ethereum.paris.state" "destroy_account". +Axiom ethereum_paris_state_imports_get_account : + IsImported globals "ethereum.paris.state" "get_account". +Axiom ethereum_paris_state_imports_increment_nonce : + IsImported globals "ethereum.paris.state" "increment_nonce". +Axiom ethereum_paris_state_imports_set_account_balance : + IsImported globals "ethereum.paris.state" "set_account_balance". +Axiom ethereum_paris_state_imports_state_root : + IsImported globals "ethereum.paris.state" "state_root". + +Axiom ethereum_paris_transactions_imports_TX_ACCESS_LIST_ADDRESS_COST : + IsImported globals "ethereum.paris.transactions" "TX_ACCESS_LIST_ADDRESS_COST". +Axiom ethereum_paris_transactions_imports_TX_ACCESS_LIST_STORAGE_KEY_COST : + IsImported globals "ethereum.paris.transactions" "TX_ACCESS_LIST_STORAGE_KEY_COST". +Axiom ethereum_paris_transactions_imports_TX_BASE_COST : + IsImported globals "ethereum.paris.transactions" "TX_BASE_COST". +Axiom ethereum_paris_transactions_imports_TX_CREATE_COST : + IsImported globals "ethereum.paris.transactions" "TX_CREATE_COST". +Axiom ethereum_paris_transactions_imports_TX_DATA_COST_PER_NON_ZERO : + IsImported globals "ethereum.paris.transactions" "TX_DATA_COST_PER_NON_ZERO". +Axiom ethereum_paris_transactions_imports_TX_DATA_COST_PER_ZERO : + IsImported globals "ethereum.paris.transactions" "TX_DATA_COST_PER_ZERO". +Axiom ethereum_paris_transactions_imports_AccessListTransaction : + IsImported globals "ethereum.paris.transactions" "AccessListTransaction". +Axiom ethereum_paris_transactions_imports_FeeMarketTransaction : + IsImported globals "ethereum.paris.transactions" "FeeMarketTransaction". +Axiom ethereum_paris_transactions_imports_LegacyTransaction : + IsImported globals "ethereum.paris.transactions" "LegacyTransaction". +Axiom ethereum_paris_transactions_imports_Transaction : + IsImported globals "ethereum.paris.transactions" "Transaction". +Axiom ethereum_paris_transactions_imports_decode_transaction : + IsImported globals "ethereum.paris.transactions" "decode_transaction". +Axiom ethereum_paris_transactions_imports_encode_transaction : + IsImported globals "ethereum.paris.transactions" "encode_transaction". + +Axiom ethereum_paris_trie_imports_Trie : + IsImported globals "ethereum.paris.trie" "Trie". +Axiom ethereum_paris_trie_imports_root : + IsImported globals "ethereum.paris.trie" "root". +Axiom ethereum_paris_trie_imports_trie_set : + IsImported globals "ethereum.paris.trie" "trie_set". + +Axiom ethereum_paris_utils_message_imports_prepare_message : + IsImported globals "ethereum.paris.utils.message" "prepare_message". + +Axiom ethereum_paris_vm_interpreter_imports_process_message_call : + IsImported globals "ethereum.paris.vm.interpreter" "process_message_call". + +Definition BASE_FEE_MAX_CHANGE_DENOMINATOR : Value.t := M.run ltac:(M.monadic ( + Constant.int 8 +)). + +Definition ELASTICITY_MULTIPLIER : Value.t := M.run ltac:(M.monadic ( + Constant.int 2 +)). + +Definition GAS_LIMIT_ADJUSTMENT_FACTOR : Value.t := M.run ltac:(M.monadic ( + Constant.int 1024 +)). + +Definition GAS_LIMIT_MINIMUM : Value.t := M.run ltac:(M.monadic ( + Constant.int 5000 +)). + +Definition EMPTY_OMMER_HASH : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "keccak256" |), + make_list [ + M.call (| + M.get_field (| M.get_name (| globals, "rlp" |), "encode" |), + make_list [ + make_list [] + ], + make_dict [] + |) + ], + make_dict [] + |) +)). + +Definition BlockChain : Value.t := + builtins.make_klass + [] + [ + + ] + [ + + ]. + +Definition apply_fork : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "old" ] |) in + let _ := Constant.str " + Transforms the state from the previous hard fork (`old`) into the block + chain object for this hard fork and returns it. + + When forks need to implement an irregular state transition, this function + is used to handle the irregularity. See the :ref:`DAO Fork ` for + an example. + + Parameters + ---------- + old : + Previous block chain object. + + Returns + ------- + new : `BlockChain` + Upgraded block chain object for this hard fork. + " in + let _ := M.return_ (| + M.get_name (| globals, "old" |) + |) in + M.pure Constant.None_)). + +Definition get_last_256_block_hashes : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "chain" ] |) in + let _ := Constant.str " + Obtain the list of hashes of the previous 256 blocks in order of + increasing block number. + + This function will return less hashes for the first 256 blocks. + + The ``BLOCKHASH`` opcode needs to access the latest hashes on the chain, + therefore this function retrieves them. + + Parameters + ---------- + chain : + History and current state. + + Returns + ------- + recent_block_hashes : `List[Hash32]` + Hashes of the recent 256 blocks in order of increasing block number. + " in + let _ := M.assign_local (| + "recent_blocks" , + M.slice (| + M.get_field (| M.get_name (| globals, "chain" |), "blocks" |), + UnOp.sub (| Constant.int 255 |), + Constant.None_, + Constant.None_ + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_name (| globals, "recent_blocks" |) + ], + make_dict [] + |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + make_list [] + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "recent_block_hashes" , + make_list [] + |) in + let _ := + M.for_ (| + M.get_name (| globals, "block" |), + M.get_name (| globals, "recent_blocks" |), + ltac:(M.monadic ( + let _ := M.assign_local (| + "prev_block_hash" , + M.get_field (| M.get_field (| M.get_name (| globals, "block" |), "header" |), "parent_hash" |) + |) in + let _ := M.call (| + M.get_field (| M.get_name (| globals, "recent_block_hashes" |), "append" |), + make_list [ + M.get_name (| globals, "prev_block_hash" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := M.assign_local (| + "most_recent_block_hash" , + M.call (| + M.get_name (| globals, "keccak256" |), + make_list [ + M.call (| + M.get_field (| M.get_name (| globals, "rlp" |), "encode" |), + make_list [ + M.get_field (| M.get_subscript (| + M.get_name (| globals, "recent_blocks" |), + UnOp.sub (| Constant.int 1 |) + |), "header" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_field (| M.get_name (| globals, "recent_block_hashes" |), "append" |), + make_list [ + M.get_name (| globals, "most_recent_block_hash" |) + ], + make_dict [] + |) in + let _ := M.return_ (| + M.get_name (| globals, "recent_block_hashes" |) + |) in + M.pure Constant.None_)). + +Definition state_transition : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "chain"; "block" ] |) in + let _ := Constant.str " + Attempts to apply a block to an existing block chain. + + All parts of the block's contents need to be verified before being added + to the chain. Blocks are verified by ensuring that the contents of the + block make logical sense with the contents of the parent block. The + information in the block's header must also match the corresponding + information in the block. + + To implement Ethereum, in theory clients are only required to store the + most recent 255 blocks of the chain since as far as execution is + concerned, only those blocks are accessed. Practically, however, clients + should store more blocks to handle reorgs. + + Parameters + ---------- + chain : + History and current state. + block : + Block to apply to `chain`. + " in + let _ := M.assign_local (| + "parent_header" , + M.get_field (| M.get_subscript (| + M.get_field (| M.get_name (| globals, "chain" |), "blocks" |), + UnOp.sub (| Constant.int 1 |) + |), "header" |) + |) in + let _ := M.call (| + M.get_name (| globals, "validate_header" |), + make_list [ + M.get_field (| M.get_name (| globals, "block" |), "header" |); + M.get_name (| globals, "parent_header" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + Compare.eq (| + M.get_field (| M.get_name (| globals, "block" |), "ommers" |), + make_tuple [ ] + |); + M.get_name (| globals, "InvalidBlock" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "apply_body_output" , + M.call (| + M.get_name (| globals, "apply_body" |), + make_list [ + M.get_field (| M.get_name (| globals, "chain" |), "state" |); + M.call (| + M.get_name (| globals, "get_last_256_block_hashes" |), + make_list [ + M.get_name (| globals, "chain" |) + ], + make_dict [] + |); + M.get_field (| M.get_field (| M.get_name (| globals, "block" |), "header" |), "coinbase" |); + M.get_field (| M.get_field (| M.get_name (| globals, "block" |), "header" |), "number" |); + M.get_field (| M.get_field (| M.get_name (| globals, "block" |), "header" |), "base_fee_per_gas" |); + M.get_field (| M.get_field (| M.get_name (| globals, "block" |), "header" |), "gas_limit" |); + M.get_field (| M.get_field (| M.get_name (| globals, "block" |), "header" |), "timestamp" |); + M.get_field (| M.get_field (| M.get_name (| globals, "block" |), "header" |), "prev_randao" |); + M.get_field (| M.get_name (| globals, "block" |), "transactions" |); + M.get_field (| M.get_name (| globals, "chain" |), "chain_id" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + Compare.eq (| + M.get_field (| M.get_name (| globals, "apply_body_output" |), "block_gas_used" |), + M.get_field (| M.get_field (| M.get_name (| globals, "block" |), "header" |), "gas_used" |) + |); + M.get_name (| globals, "InvalidBlock" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + Compare.eq (| + M.get_field (| M.get_name (| globals, "apply_body_output" |), "transactions_root" |), + M.get_field (| M.get_field (| M.get_name (| globals, "block" |), "header" |), "transactions_root" |) + |); + M.get_name (| globals, "InvalidBlock" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + Compare.eq (| + M.get_field (| M.get_name (| globals, "apply_body_output" |), "state_root" |), + M.get_field (| M.get_field (| M.get_name (| globals, "block" |), "header" |), "state_root" |) + |); + M.get_name (| globals, "InvalidBlock" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + Compare.eq (| + M.get_field (| M.get_name (| globals, "apply_body_output" |), "receipt_root" |), + M.get_field (| M.get_field (| M.get_name (| globals, "block" |), "header" |), "receipt_root" |) + |); + M.get_name (| globals, "InvalidBlock" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + Compare.eq (| + M.get_field (| M.get_name (| globals, "apply_body_output" |), "block_logs_bloom" |), + M.get_field (| M.get_field (| M.get_name (| globals, "block" |), "header" |), "bloom" |) + |); + M.get_name (| globals, "InvalidBlock" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, "chain" |), "blocks" |), "append" |), + make_list [ + M.get_name (| globals, "block" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.gt (| + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_field (| M.get_name (| globals, "chain" |), "blocks" |) + ], + make_dict [] + |), + Constant.int 255 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign (| + M.get_field (| M.get_name (| globals, "chain" |), "blocks" |), + M.slice (| + M.get_field (| M.get_name (| globals, "chain" |), "blocks" |), + UnOp.sub (| Constant.int 255 |), + Constant.None_, + Constant.None_ + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + M.pure Constant.None_)). + +Definition calculate_base_fee_per_gas : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "block_gas_limit"; "parent_gas_limit"; "parent_gas_used"; "parent_base_fee_per_gas" ] |) in + let _ := Constant.str " + Calculates the base fee per gas for the block. + + Parameters + ---------- + block_gas_limit : + Gas limit of the block for which the base fee is being calculated. + parent_gas_limit : + Gas limit of the parent block. + parent_gas_used : + Gas used in the parent block. + parent_base_fee_per_gas : + Base fee per gas of the parent block. + + Returns + ------- + base_fee_per_gas : `Uint` + Base fee per gas for the block. + " in + let _ := M.assign_local (| + "parent_gas_target" , + BinOp.floor_div (| + M.get_name (| globals, "parent_gas_limit" |), + M.get_name (| globals, "ELASTICITY_MULTIPLIER" |) + |) + |) in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + M.call (| + M.get_name (| globals, "check_gas_limit" |), + make_list [ + M.get_name (| globals, "block_gas_limit" |); + M.get_name (| globals, "parent_gas_limit" |) + ], + make_dict [] + |); + M.get_name (| globals, "InvalidBlock" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, "parent_gas_used" |), + M.get_name (| globals, "parent_gas_target" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "expected_base_fee_per_gas" , + M.get_name (| globals, "parent_base_fee_per_gas" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + Compare.gt (| + M.get_name (| globals, "parent_gas_used" |), + M.get_name (| globals, "parent_gas_target" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "gas_used_delta" , + BinOp.sub (| + M.get_name (| globals, "parent_gas_used" |), + M.get_name (| globals, "parent_gas_target" |) + |) + |) in + let _ := M.assign_local (| + "parent_fee_gas_delta" , + BinOp.mult (| + M.get_name (| globals, "parent_base_fee_per_gas" |), + M.get_name (| globals, "gas_used_delta" |) + |) + |) in + let _ := M.assign_local (| + "target_fee_gas_delta" , + BinOp.floor_div (| + M.get_name (| globals, "parent_fee_gas_delta" |), + M.get_name (| globals, "parent_gas_target" |) + |) + |) in + let _ := M.assign_local (| + "base_fee_per_gas_delta" , + M.call (| + M.get_name (| globals, "max" |), + make_list [ + BinOp.floor_div (| + M.get_name (| globals, "target_fee_gas_delta" |), + M.get_name (| globals, "BASE_FEE_MAX_CHANGE_DENOMINATOR" |) + |); + Constant.int 1 + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "expected_base_fee_per_gas" , + BinOp.add (| + M.get_name (| globals, "parent_base_fee_per_gas" |), + M.get_name (| globals, "base_fee_per_gas_delta" |) + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "gas_used_delta" , + BinOp.sub (| + M.get_name (| globals, "parent_gas_target" |), + M.get_name (| globals, "parent_gas_used" |) + |) + |) in + let _ := M.assign_local (| + "parent_fee_gas_delta" , + BinOp.mult (| + M.get_name (| globals, "parent_base_fee_per_gas" |), + M.get_name (| globals, "gas_used_delta" |) + |) + |) in + let _ := M.assign_local (| + "target_fee_gas_delta" , + BinOp.floor_div (| + M.get_name (| globals, "parent_fee_gas_delta" |), + M.get_name (| globals, "parent_gas_target" |) + |) + |) in + let _ := M.assign_local (| + "base_fee_per_gas_delta" , + BinOp.floor_div (| + M.get_name (| globals, "target_fee_gas_delta" |), + M.get_name (| globals, "BASE_FEE_MAX_CHANGE_DENOMINATOR" |) + |) + |) in + let _ := M.assign_local (| + "expected_base_fee_per_gas" , + BinOp.sub (| + M.get_name (| globals, "parent_base_fee_per_gas" |), + M.get_name (| globals, "base_fee_per_gas_delta" |) + |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )) |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.get_name (| globals, "expected_base_fee_per_gas" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Definition validate_header : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "header"; "parent_header" ] |) in + let _ := Constant.str " + Verifies a block header. + + In order to consider a block's header valid, the logic for the + quantities in the header should match the logic for the block itself. + For example the header timestamp should be greater than the block's parent + timestamp because the block was created *after* the parent block. + Additionally, the block's number should be directly following the parent + block's number since it is the next block in the sequence. + + Parameters + ---------- + header : + Header to check for correctness. + parent_header : + Parent Header of the header to check for correctness + " in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + Compare.lt_e (| + M.get_field (| M.get_name (| globals, "header" |), "gas_used" |), + M.get_field (| M.get_name (| globals, "header" |), "gas_limit" |) + |); + M.get_name (| globals, "InvalidBlock" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "expected_base_fee_per_gas" , + M.call (| + M.get_name (| globals, "calculate_base_fee_per_gas" |), + make_list [ + M.get_field (| M.get_name (| globals, "header" |), "gas_limit" |); + M.get_field (| M.get_name (| globals, "parent_header" |), "gas_limit" |); + M.get_field (| M.get_name (| globals, "parent_header" |), "gas_used" |); + M.get_field (| M.get_name (| globals, "parent_header" |), "base_fee_per_gas" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + Compare.eq (| + M.get_name (| globals, "expected_base_fee_per_gas" |), + M.get_field (| M.get_name (| globals, "header" |), "base_fee_per_gas" |) + |); + M.get_name (| globals, "InvalidBlock" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + Compare.gt (| + M.get_field (| M.get_name (| globals, "header" |), "timestamp" |), + M.get_field (| M.get_name (| globals, "parent_header" |), "timestamp" |) + |); + M.get_name (| globals, "InvalidBlock" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + Compare.eq (| + M.get_field (| M.get_name (| globals, "header" |), "number" |), + BinOp.add (| + M.get_field (| M.get_name (| globals, "parent_header" |), "number" |), + Constant.int 1 + |) + |); + M.get_name (| globals, "InvalidBlock" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + Compare.lt_e (| + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_field (| M.get_name (| globals, "header" |), "extra_data" |) + ], + make_dict [] + |), + Constant.int 32 + |); + M.get_name (| globals, "InvalidBlock" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + Compare.eq (| + M.get_field (| M.get_name (| globals, "header" |), "difficulty" |), + Constant.int 0 + |); + M.get_name (| globals, "InvalidBlock" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + Compare.eq (| + M.get_field (| M.get_name (| globals, "header" |), "nonce" |), + Constant.bytes "0000000000000000" + |); + M.get_name (| globals, "InvalidBlock" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + Compare.eq (| + M.get_field (| M.get_name (| globals, "header" |), "ommers_hash" |), + M.get_name (| globals, "EMPTY_OMMER_HASH" |) + |); + M.get_name (| globals, "InvalidBlock" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "block_parent_hash" , + M.call (| + M.get_name (| globals, "keccak256" |), + make_list [ + M.call (| + M.get_field (| M.get_name (| globals, "rlp" |), "encode" |), + make_list [ + M.get_name (| globals, "parent_header" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + Compare.eq (| + M.get_field (| M.get_name (| globals, "header" |), "parent_hash" |), + M.get_name (| globals, "block_parent_hash" |) + |); + M.get_name (| globals, "InvalidBlock" |) + ], + make_dict [] + |) in + M.pure Constant.None_)). + +Definition check_transaction : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "tx"; "base_fee_per_gas"; "gas_available"; "chain_id" ] |) in + let _ := Constant.str " + Check if the transaction is includable in the block. + + Parameters + ---------- + tx : + The transaction. + base_fee_per_gas : + The block base fee. + gas_available : + The gas remaining in the block. + chain_id : + The ID of the current chain. + + Returns + ------- + sender_address : + The sender of the transaction. + effective_gas_price : + The price to charge for gas when the transaction is executed. + + Raises + ------ + InvalidBlock : + If the transaction is not includable. + " in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + Compare.lt_e (| + M.get_field (| M.get_name (| globals, "tx" |), "gas" |), + M.get_name (| globals, "gas_available" |) + |); + M.get_name (| globals, "InvalidBlock" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "sender_address" , + M.call (| + M.get_name (| globals, "recover_sender" |), + make_list [ + M.get_name (| globals, "chain_id" |); + M.get_name (| globals, "tx" |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, "isinstance" |), + make_list [ + M.get_name (| globals, "tx" |); + M.get_name (| globals, "FeeMarketTransaction" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + Compare.gt_e (| + M.get_field (| M.get_name (| globals, "tx" |), "max_fee_per_gas" |), + M.get_field (| M.get_name (| globals, "tx" |), "max_priority_fee_per_gas" |) + |); + M.get_name (| globals, "InvalidBlock" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + Compare.gt_e (| + M.get_field (| M.get_name (| globals, "tx" |), "max_fee_per_gas" |), + M.get_name (| globals, "base_fee_per_gas" |) + |); + M.get_name (| globals, "InvalidBlock" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "priority_fee_per_gas" , + M.call (| + M.get_name (| globals, "min" |), + make_list [ + M.get_field (| M.get_name (| globals, "tx" |), "max_priority_fee_per_gas" |); + BinOp.sub (| + M.get_field (| M.get_name (| globals, "tx" |), "max_fee_per_gas" |), + M.get_name (| globals, "base_fee_per_gas" |) + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "effective_gas_price" , + BinOp.add (| + M.get_name (| globals, "priority_fee_per_gas" |), + M.get_name (| globals, "base_fee_per_gas" |) + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + Compare.gt_e (| + M.get_field (| M.get_name (| globals, "tx" |), "gas_price" |), + M.get_name (| globals, "base_fee_per_gas" |) + |); + M.get_name (| globals, "InvalidBlock" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "effective_gas_price" , + M.get_field (| M.get_name (| globals, "tx" |), "gas_price" |) + |) in + M.pure Constant.None_ + )) |) in + let _ := M.return_ (| + make_tuple [ M.get_name (| globals, "sender_address" |); M.get_name (| globals, "effective_gas_price" |) ] + |) in + M.pure Constant.None_)). + +Definition make_receipt : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "tx"; "error"; "cumulative_gas_used"; "logs" ] |) in + let _ := Constant.str " + Make the receipt for a transaction that was executed. + + Parameters + ---------- + tx : + The executed transaction. + error : + The error from the execution if any. + cumulative_gas_used : + The total gas used so far in the block after the transaction was + executed. + logs : + The logs produced by the transaction. + + Returns + ------- + receipt : + The receipt for the transaction. + " in + let _ := M.assign_local (| + "receipt" , + M.call (| + M.get_name (| globals, "Receipt" |), + make_list [], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, "isinstance" |), + make_list [ + M.get_name (| globals, "tx" |); + M.get_name (| globals, "AccessListTransaction" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + BinOp.add (| + Constant.bytes "01", + M.call (| + M.get_field (| M.get_name (| globals, "rlp" |), "encode" |), + make_list [ + M.get_name (| globals, "receipt" |) + ], + make_dict [] + |) + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, "isinstance" |), + make_list [ + M.get_name (| globals, "tx" |); + M.get_name (| globals, "FeeMarketTransaction" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + BinOp.add (| + Constant.bytes "02", + M.call (| + M.get_field (| M.get_name (| globals, "rlp" |), "encode" |), + make_list [ + M.get_name (| globals, "receipt" |) + ], + make_dict [] + |) + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.return_ (| + M.get_name (| globals, "receipt" |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_)). + +Definition ApplyBodyOutput : Value.t := + builtins.make_klass + [] + [ + + ] + [ + + ]. + +Definition apply_body : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "state"; "block_hashes"; "coinbase"; "block_number"; "base_fee_per_gas"; "block_gas_limit"; "block_time"; "prev_randao"; "transactions"; "chain_id" ] |) in + let _ := Constant.str " + Executes a block. + + Many of the contents of a block are stored in data structures called + tries. There is a transactions trie which is similar to a ledger of the + transactions stored in the current block. There is also a receipts trie + which stores the results of executing a transaction, like the post state + and gas used. This function creates and executes the block that is to be + added to the chain. + + Parameters + ---------- + state : + Current account state. + block_hashes : + List of hashes of the previous 256 blocks in the order of + increasing block number. + coinbase : + Address of account which receives block reward and transaction fees. + block_number : + Position of the block within the chain. + base_fee_per_gas : + Base fee per gas of within the block. + block_gas_limit : + Initial amount of gas available for execution in this block. + block_time : + Time the block was produced, measured in seconds since the epoch. + prev_randao : + The previous randao from the beacon chain. + transactions : + Transactions included in the block. + ommers : + Headers of ancestor blocks which are not direct parents (formerly + uncles.) + chain_id : + ID of the executing chain. + + Returns + ------- + apply_body_output : `ApplyBodyOutput` + Output of applying the block body to the state. + " in + let _ := M.assign_local (| + "gas_available" , + M.get_name (| globals, "block_gas_limit" |) + |) in +(* At stmt: unsupported node type: AnnAssign *) +(* At stmt: unsupported node type: AnnAssign *) +(* At stmt: unsupported node type: AnnAssign *) + let _ := + M.for_ (| + make_tuple [ M.get_name (| globals, "i" |); M.get_name (| globals, "tx" |) ], + M.call (| + M.get_name (| globals, "enumerate" |), + make_list [ + M.call (| + M.get_name (| globals, "map" |), + make_list [ + M.get_name (| globals, "decode_transaction" |); + M.get_name (| globals, "transactions" |) + ], + make_dict [] + |) + ], + make_dict [] + |), + ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, "trie_set" |), + make_list [ + M.get_name (| globals, "transactions_trie" |); + M.call (| + M.get_field (| M.get_name (| globals, "rlp" |), "encode" |), + make_list [ + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.get_name (| globals, "i" |) + ], + make_dict [] + |) + ], + make_dict [] + |); + M.call (| + M.get_name (| globals, "encode_transaction" |), + make_list [ + M.get_name (| globals, "tx" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign (| + make_tuple [ M.get_name (| globals, "sender_address" |); M.get_name (| globals, "effective_gas_price" |) ], + M.call (| + M.get_name (| globals, "check_transaction" |), + make_list [ + M.get_name (| globals, "tx" |); + M.get_name (| globals, "base_fee_per_gas" |); + M.get_name (| globals, "gas_available" |); + M.get_name (| globals, "chain_id" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "env" , + M.call (| + M.get_field (| M.get_name (| globals, "vm" |), "Environment" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.assign (| + make_tuple [ M.get_name (| globals, "gas_used" |); M.get_name (| globals, "logs" |); M.get_name (| globals, "error" |) ], + M.call (| + M.get_name (| globals, "process_transaction" |), + make_list [ + M.get_name (| globals, "env" |); + M.get_name (| globals, "tx" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_op_local (| + BinOp.sub, + "gas_available", + M.get_name (| globals, "gas_used" |) + |) in + let _ := M.assign_local (| + "receipt" , + M.call (| + M.get_name (| globals, "make_receipt" |), + make_list [ + M.get_name (| globals, "tx" |); + M.get_name (| globals, "error" |); + BinOp.sub (| + M.get_name (| globals, "block_gas_limit" |), + M.get_name (| globals, "gas_available" |) + |); + M.get_name (| globals, "logs" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "trie_set" |), + make_list [ + M.get_name (| globals, "receipts_trie" |); + M.call (| + M.get_field (| M.get_name (| globals, "rlp" |), "encode" |), + make_list [ + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.get_name (| globals, "i" |) + ], + make_dict [] + |) + ], + make_dict [] + |); + M.get_name (| globals, "receipt" |) + ], + make_dict [] + |) in + let _ := M.assign_op_local (| + BinOp.add, + "block_logs", + M.get_name (| globals, "logs" |) + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := M.assign_local (| + "block_gas_used" , + BinOp.sub (| + M.get_name (| globals, "block_gas_limit" |), + M.get_name (| globals, "gas_available" |) + |) + |) in + let _ := M.assign_local (| + "block_logs_bloom" , + M.call (| + M.get_name (| globals, "logs_bloom" |), + make_list [ + M.get_name (| globals, "block_logs" |) + ], + make_dict [] + |) + |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, "ApplyBodyOutput" |), + make_list [ + M.get_name (| globals, "block_gas_used" |); + M.call (| + M.get_name (| globals, "root" |), + make_list [ + M.get_name (| globals, "transactions_trie" |) + ], + make_dict [] + |); + M.call (| + M.get_name (| globals, "root" |), + make_list [ + M.get_name (| globals, "receipts_trie" |) + ], + make_dict [] + |); + M.get_name (| globals, "block_logs_bloom" |); + M.call (| + M.get_name (| globals, "state_root" |), + make_list [ + M.get_name (| globals, "state" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Definition process_transaction : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "env"; "tx" ] |) in + let _ := Constant.str " + Execute a transaction against the provided environment. + + This function processes the actions needed to execute a transaction. + It decrements the sender's account after calculating the gas fee and + refunds them the proper amount after execution. Calling contracts, + deploying code, and incrementing nonces are all examples of actions that + happen within this function or from a call made within this function. + + Accounts that are marked for deletion are processed and destroyed after + execution. + + Parameters + ---------- + env : + Environment for the Ethereum Virtual Machine. + tx : + Transaction to execute. + + Returns + ------- + gas_left : `ethereum.base_types.U256` + Remaining gas after execution. + logs : `Tuple[ethereum.blocks.Log, ...]` + Logs generated during execution. + " in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + M.call (| + M.get_name (| globals, "validate_transaction" |), + make_list [ + M.get_name (| globals, "tx" |) + ], + make_dict [] + |); + M.get_name (| globals, "InvalidBlock" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "sender" , + M.get_field (| M.get_name (| globals, "env" |), "origin" |) + |) in + let _ := M.assign_local (| + "sender_account" , + M.call (| + M.get_name (| globals, "get_account" |), + make_list [ + M.get_field (| M.get_name (| globals, "env" |), "state" |); + M.get_name (| globals, "sender" |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, "isinstance" |), + make_list [ + M.get_name (| globals, "tx" |); + M.get_name (| globals, "FeeMarketTransaction" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "max_gas_fee" , + BinOp.mult (| + M.get_field (| M.get_name (| globals, "tx" |), "gas" |), + M.get_field (| M.get_name (| globals, "tx" |), "max_fee_per_gas" |) + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "max_gas_fee" , + BinOp.mult (| + M.get_field (| M.get_name (| globals, "tx" |), "gas" |), + M.get_field (| M.get_name (| globals, "tx" |), "gas_price" |) + |) + |) in + M.pure Constant.None_ + )) |) in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + Compare.eq (| + M.get_field (| M.get_name (| globals, "sender_account" |), "nonce" |), + M.get_field (| M.get_name (| globals, "tx" |), "nonce" |) + |); + M.get_name (| globals, "InvalidBlock" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + Compare.gt_e (| + M.get_field (| M.get_name (| globals, "sender_account" |), "balance" |), + BinOp.add (| + M.get_name (| globals, "max_gas_fee" |), + M.get_field (| M.get_name (| globals, "tx" |), "value" |) + |) + |); + M.get_name (| globals, "InvalidBlock" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + Compare.eq (| + M.get_field (| M.get_name (| globals, "sender_account" |), "code" |), + M.call (| + M.get_name (| globals, "bytearray" |), + make_list [], + make_dict [] + |) + |); + M.get_name (| globals, "InvalidBlock" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "effective_gas_fee" , + BinOp.mult (| + M.get_field (| M.get_name (| globals, "tx" |), "gas" |), + M.get_field (| M.get_name (| globals, "env" |), "gas_price" |) + |) + |) in + let _ := M.assign_local (| + "gas" , + BinOp.sub (| + M.get_field (| M.get_name (| globals, "tx" |), "gas" |), + M.call (| + M.get_name (| globals, "calculate_intrinsic_cost" |), + make_list [ + M.get_name (| globals, "tx" |) + ], + make_dict [] + |) + |) + |) in + let _ := M.call (| + M.get_name (| globals, "increment_nonce" |), + make_list [ + M.get_field (| M.get_name (| globals, "env" |), "state" |); + M.get_name (| globals, "sender" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "sender_balance_after_gas_fee" , + BinOp.sub (| + M.get_field (| M.get_name (| globals, "sender_account" |), "balance" |), + M.get_name (| globals, "effective_gas_fee" |) + |) + |) in + let _ := M.call (| + M.get_name (| globals, "set_account_balance" |), + make_list [ + M.get_field (| M.get_name (| globals, "env" |), "state" |); + M.get_name (| globals, "sender" |); + M.get_name (| globals, "sender_balance_after_gas_fee" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "preaccessed_addresses" , + M.call (| + M.get_name (| globals, "set" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "preaccessed_storage_keys" , + M.call (| + M.get_name (| globals, "set" |), + make_list [], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, "isinstance" |), + make_list [ + M.get_name (| globals, "tx" |); + make_tuple [ M.get_name (| globals, "AccessListTransaction" |); M.get_name (| globals, "FeeMarketTransaction" |) ] + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := + M.for_ (| + make_tuple [ M.get_name (| globals, "address" |); M.get_name (| globals, "keys" |) ], + M.get_field (| M.get_name (| globals, "tx" |), "access_list" |), + ltac:(M.monadic ( + let _ := M.call (| + M.get_field (| M.get_name (| globals, "preaccessed_addresses" |), "add" |), + make_list [ + M.get_name (| globals, "address" |) + ], + make_dict [] + |) in + let _ := + M.for_ (| + M.get_name (| globals, "key" |), + M.get_name (| globals, "keys" |), + ltac:(M.monadic ( + let _ := M.call (| + M.get_field (| M.get_name (| globals, "preaccessed_storage_keys" |), "add" |), + make_list [ + make_tuple [ M.get_name (| globals, "address" |); M.get_name (| globals, "key" |) ] + ], + make_dict [] + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "message" , + M.call (| + M.get_name (| globals, "prepare_message" |), + make_list [ + M.get_name (| globals, "sender" |); + M.get_field (| M.get_name (| globals, "tx" |), "to" |); + M.get_field (| M.get_name (| globals, "tx" |), "value" |); + M.get_field (| M.get_name (| globals, "tx" |), "data" |); + M.get_name (| globals, "gas" |); + M.get_name (| globals, "env" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "output" , + M.call (| + M.get_name (| globals, "process_message_call" |), + make_list [ + M.get_name (| globals, "message" |); + M.get_name (| globals, "env" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "gas_used" , + BinOp.sub (| + M.get_field (| M.get_name (| globals, "tx" |), "gas" |), + M.get_field (| M.get_name (| globals, "output" |), "gas_left" |) + |) + |) in + let _ := M.assign_local (| + "gas_refund" , + M.call (| + M.get_name (| globals, "min" |), + make_list [ + BinOp.floor_div (| + M.get_name (| globals, "gas_used" |), + Constant.int 5 + |); + M.get_field (| M.get_name (| globals, "output" |), "refund_counter" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "gas_refund_amount" , + BinOp.mult (| + BinOp.add (| + M.get_field (| M.get_name (| globals, "output" |), "gas_left" |), + M.get_name (| globals, "gas_refund" |) + |), + M.get_field (| M.get_name (| globals, "env" |), "gas_price" |) + |) + |) in + let _ := M.assign_local (| + "priority_fee_per_gas" , + BinOp.sub (| + M.get_field (| M.get_name (| globals, "env" |), "gas_price" |), + M.get_field (| M.get_name (| globals, "env" |), "base_fee_per_gas" |) + |) + |) in + let _ := M.assign_local (| + "transaction_fee" , + BinOp.mult (| + BinOp.sub (| + BinOp.sub (| + M.get_field (| M.get_name (| globals, "tx" |), "gas" |), + M.get_field (| M.get_name (| globals, "output" |), "gas_left" |) + |), + M.get_name (| globals, "gas_refund" |) + |), + M.get_name (| globals, "priority_fee_per_gas" |) + |) + |) in + let _ := M.assign_local (| + "total_gas_used" , + BinOp.sub (| + M.get_name (| globals, "gas_used" |), + M.get_name (| globals, "gas_refund" |) + |) + |) in + let _ := M.assign_local (| + "sender_balance_after_refund" , + BinOp.add (| + M.get_field (| M.call (| + M.get_name (| globals, "get_account" |), + make_list [ + M.get_field (| M.get_name (| globals, "env" |), "state" |); + M.get_name (| globals, "sender" |) + ], + make_dict [] + |), "balance" |), + M.get_name (| globals, "gas_refund_amount" |) + |) + |) in + let _ := M.call (| + M.get_name (| globals, "set_account_balance" |), + make_list [ + M.get_field (| M.get_name (| globals, "env" |), "state" |); + M.get_name (| globals, "sender" |); + M.get_name (| globals, "sender_balance_after_refund" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "coinbase_balance_after_mining_fee" , + BinOp.add (| + M.get_field (| M.call (| + M.get_name (| globals, "get_account" |), + make_list [ + M.get_field (| M.get_name (| globals, "env" |), "state" |); + M.get_field (| M.get_name (| globals, "env" |), "coinbase" |) + ], + make_dict [] + |), "balance" |), + M.get_name (| globals, "transaction_fee" |) + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.not_eq (| + M.get_name (| globals, "coinbase_balance_after_mining_fee" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, "set_account_balance" |), + make_list [ + M.get_field (| M.get_name (| globals, "env" |), "state" |); + M.get_field (| M.get_name (| globals, "env" |), "coinbase" |); + M.get_name (| globals, "coinbase_balance_after_mining_fee" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, "account_exists_and_is_empty" |), + make_list [ + M.get_field (| M.get_name (| globals, "env" |), "state" |); + M.get_field (| M.get_name (| globals, "env" |), "coinbase" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, "destroy_account" |), + make_list [ + M.get_field (| M.get_name (| globals, "env" |), "state" |); + M.get_field (| M.get_name (| globals, "env" |), "coinbase" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )) |) in + let _ := + M.for_ (| + M.get_name (| globals, "address" |), + M.get_field (| M.get_name (| globals, "output" |), "accounts_to_delete" |), + ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, "destroy_account" |), + make_list [ + M.get_field (| M.get_name (| globals, "env" |), "state" |); + M.get_name (| globals, "address" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := + M.for_ (| + M.get_name (| globals, "address" |), + M.get_field (| M.get_name (| globals, "output" |), "touched_accounts" |), + ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, "account_exists_and_is_empty" |), + make_list [ + M.get_field (| M.get_name (| globals, "env" |), "state" |); + M.get_name (| globals, "address" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, "destroy_account" |), + make_list [ + M.get_field (| M.get_name (| globals, "env" |), "state" |); + M.get_name (| globals, "address" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := M.return_ (| + make_tuple [ M.get_name (| globals, "total_gas_used" |); M.get_field (| M.get_name (| globals, "output" |), "logs" |); M.get_field (| M.get_name (| globals, "output" |), "error" |) ] + |) in + M.pure Constant.None_)). + +Definition validate_transaction : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "tx" ] |) in + let _ := Constant.str " + Verifies a transaction. + + The gas in a transaction gets used to pay for the intrinsic cost of + operations, therefore if there is insufficient gas then it would not + be possible to execute a transaction and it will be declared invalid. + + Additionally, the nonce of a transaction must not equal or exceed the + limit defined in `EIP-2681 `_. + In practice, defining the limit as ``2**64-1`` has no impact because + sending ``2**64-1`` transactions is improbable. It's not strictly + impossible though, ``2**64-1`` transactions is the entire capacity of the + Ethereum blockchain at 2022 gas limits for a little over 22 years. + + Parameters + ---------- + tx : + Transaction to validate. + + Returns + ------- + verified : `bool` + True if the transaction can be executed, or False otherwise. + " in + let _ := M.return_ (| + BoolOp.and (| + Compare.lt_e (| + M.call (| + M.get_name (| globals, "calculate_intrinsic_cost" |), + make_list [ + M.get_name (| globals, "tx" |) + ], + make_dict [] + |), + M.get_field (| M.get_name (| globals, "tx" |), "gas" |) + |), + ltac:(M.monadic ( + Compare.lt (| + M.get_field (| M.get_name (| globals, "tx" |), "nonce" |), + BinOp.sub (| + BinOp.pow (| + Constant.int 2, + Constant.int 64 + |), + Constant.int 1 + |) + |) + )) + |) + |) in + M.pure Constant.None_)). + +Definition calculate_intrinsic_cost : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "tx" ] |) in + let _ := Constant.str " + Calculates the gas that is charged before execution is started. + + The intrinsic cost of the transaction is charged before execution has + begun. Functions/operations in the EVM cost money to execute so this + intrinsic cost is for the operations that need to be paid for as part of + the transaction. Data transfer, for example, is part of this intrinsic + cost. It costs ether to send data over the wire and that ether is + accounted for in the intrinsic cost calculated in this function. This + intrinsic cost must be calculated and paid for before execution in order + for all operations to be implemented. + + Parameters + ---------- + tx : + Transaction to compute the intrinsic cost of. + + Returns + ------- + verified : `ethereum.base_types.Uint` + The intrinsic cost of the transaction. + " in + let _ := M.assign_local (| + "data_cost" , + Constant.int 0 + |) in + let _ := + M.for_ (| + M.get_name (| globals, "byte" |), + M.get_field (| M.get_name (| globals, "tx" |), "data" |), + ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, "byte" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_op_local (| + BinOp.add, + "data_cost", + M.get_name (| globals, "TX_DATA_COST_PER_ZERO" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_op_local (| + BinOp.add, + "data_cost", + M.get_name (| globals, "TX_DATA_COST_PER_NON_ZERO" |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_field (| M.get_name (| globals, "tx" |), "to" |), + M.call (| + M.get_name (| globals, "Bytes0" |), + make_list [ + Constant.bytes "" + ], + make_dict [] + |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "create_cost" , + M.get_name (| globals, "TX_CREATE_COST" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "create_cost" , + Constant.int 0 + |) in + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "access_list_cost" , + Constant.int 0 + |) in + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, "isinstance" |), + make_list [ + M.get_name (| globals, "tx" |); + make_tuple [ M.get_name (| globals, "AccessListTransaction" |); M.get_name (| globals, "FeeMarketTransaction" |) ] + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := + M.for_ (| + make_tuple [ M.get_name (| globals, "_address" |); M.get_name (| globals, "keys" |) ], + M.get_field (| M.get_name (| globals, "tx" |), "access_list" |), + ltac:(M.monadic ( + let _ := M.assign_op_local (| + BinOp.add, + "access_list_cost", + M.get_name (| globals, "TX_ACCESS_LIST_ADDRESS_COST" |) + |) in + let _ := M.assign_op_local (| + BinOp.add, + "access_list_cost", + BinOp.mult (| + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_name (| globals, "keys" |) + ], + make_dict [] + |), + M.get_name (| globals, "TX_ACCESS_LIST_STORAGE_KEY_COST" |) + |) + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + BinOp.add (| + BinOp.add (| + BinOp.add (| + M.get_name (| globals, "TX_BASE_COST" |), + M.get_name (| globals, "data_cost" |) + |), + M.get_name (| globals, "create_cost" |) + |), + M.get_name (| globals, "access_list_cost" |) + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Definition recover_sender : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "chain_id"; "tx" ] |) in + let _ := Constant.str " + Extracts the sender address from a transaction. + + The v, r, and s values are the three parts that make up the signature + of a transaction. In order to recover the sender of a transaction the two + components needed are the signature (``v``, ``r``, and ``s``) and the + signing hash of the transaction. The sender's public key can be obtained + with these two values and therefore the sender address can be retrieved. + + Parameters + ---------- + tx : + Transaction of interest. + chain_id : + ID of the executing chain. + + Returns + ------- + sender : `ethereum.fork_types.Address` + The address of the account that signed the transaction. + " in + let _ := M.assign (| + make_tuple [ M.get_name (| globals, "r" |); M.get_name (| globals, "s" |) ], + make_tuple [ M.get_field (| M.get_name (| globals, "tx" |), "r" |); M.get_field (| M.get_name (| globals, "tx" |), "s" |) ] + |) in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + BoolOp.and (| + Compare.lt (| + Constant.int 0, + M.get_name (| globals, "r" |) + |), + ltac:(M.monadic ( + Compare.lt (| + M.get_name (| globals, "r" |), + M.get_name (| globals, "SECP256K1N" |) + |) + )) + |); + M.get_name (| globals, "InvalidBlock" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + BoolOp.and (| + Compare.lt (| + Constant.int 0, + M.get_name (| globals, "s" |) + |), + ltac:(M.monadic ( + Compare.lt_e (| + M.get_name (| globals, "s" |), + BinOp.floor_div (| + M.get_name (| globals, "SECP256K1N" |), + Constant.int 2 + |) + |) + )) + |); + M.get_name (| globals, "InvalidBlock" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, "isinstance" |), + make_list [ + M.get_name (| globals, "tx" |); + M.get_name (| globals, "LegacyTransaction" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "v" , + M.get_field (| M.get_name (| globals, "tx" |), "v" |) + |) in + let _ := + (* if *) + M.if_then_else (| + BoolOp.or (| + Compare.eq (| + M.get_name (| globals, "v" |), + Constant.int 27 + |), + ltac:(M.monadic ( + Compare.eq (| + M.get_name (| globals, "v" |), + Constant.int 28 + |) + )) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "public_key" , + M.call (| + M.get_name (| globals, "secp256k1_recover" |), + make_list [ + M.get_name (| globals, "r" |); + M.get_name (| globals, "s" |); + BinOp.sub (| + M.get_name (| globals, "v" |), + Constant.int 27 + |); + M.call (| + M.get_name (| globals, "signing_hash_pre155" |), + make_list [ + M.get_name (| globals, "tx" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + BoolOp.or (| + Compare.eq (| + M.get_name (| globals, "v" |), + BinOp.add (| + Constant.int 35, + BinOp.mult (| + M.get_name (| globals, "chain_id" |), + Constant.int 2 + |) + |) + |), + ltac:(M.monadic ( + Compare.eq (| + M.get_name (| globals, "v" |), + BinOp.add (| + Constant.int 36, + BinOp.mult (| + M.get_name (| globals, "chain_id" |), + Constant.int 2 + |) + |) + |) + )) + |); + M.get_name (| globals, "InvalidBlock" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "public_key" , + M.call (| + M.get_name (| globals, "secp256k1_recover" |), + make_list [ + M.get_name (| globals, "r" |); + M.get_name (| globals, "s" |); + BinOp.sub (| + BinOp.sub (| + M.get_name (| globals, "v" |), + Constant.int 35 + |), + BinOp.mult (| + M.get_name (| globals, "chain_id" |), + Constant.int 2 + |) + |); + M.call (| + M.get_name (| globals, "signing_hash_155" |), + make_list [ + M.get_name (| globals, "tx" |); + M.get_name (| globals, "chain_id" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, "isinstance" |), + make_list [ + M.get_name (| globals, "tx" |); + M.get_name (| globals, "AccessListTransaction" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "public_key" , + M.call (| + M.get_name (| globals, "secp256k1_recover" |), + make_list [ + M.get_name (| globals, "r" |); + M.get_name (| globals, "s" |); + M.get_field (| M.get_name (| globals, "tx" |), "y_parity" |); + M.call (| + M.get_name (| globals, "signing_hash_2930" |), + make_list [ + M.get_name (| globals, "tx" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, "isinstance" |), + make_list [ + M.get_name (| globals, "tx" |); + M.get_name (| globals, "FeeMarketTransaction" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "public_key" , + M.call (| + M.get_name (| globals, "secp256k1_recover" |), + make_list [ + M.get_name (| globals, "r" |); + M.get_name (| globals, "s" |); + M.get_field (| M.get_name (| globals, "tx" |), "y_parity" |); + M.call (| + M.get_name (| globals, "signing_hash_1559" |), + make_list [ + M.get_name (| globals, "tx" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )) |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, "Address" |), + make_list [ + M.slice (| + M.call (| + M.get_name (| globals, "keccak256" |), + make_list [ + M.get_name (| globals, "public_key" |) + ], + make_dict [] + |), + Constant.int 12, + Constant.int 32, + Constant.None_ + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Definition signing_hash_pre155 : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "tx" ] |) in + let _ := Constant.str " + Compute the hash of a transaction used in a legacy (pre EIP 155) signature. + + Parameters + ---------- + tx : + Transaction of interest. + + Returns + ------- + hash : `ethereum.crypto.hash.Hash32` + Hash of the transaction. + " in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, "keccak256" |), + make_list [ + M.call (| + M.get_field (| M.get_name (| globals, "rlp" |), "encode" |), + make_list [ + make_tuple [ M.get_field (| M.get_name (| globals, "tx" |), "nonce" |); M.get_field (| M.get_name (| globals, "tx" |), "gas_price" |); M.get_field (| M.get_name (| globals, "tx" |), "gas" |); M.get_field (| M.get_name (| globals, "tx" |), "to" |); M.get_field (| M.get_name (| globals, "tx" |), "value" |); M.get_field (| M.get_name (| globals, "tx" |), "data" |) ] + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Definition signing_hash_155 : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "tx"; "chain_id" ] |) in + let _ := Constant.str " + Compute the hash of a transaction used in a EIP 155 signature. + + Parameters + ---------- + tx : + Transaction of interest. + chain_id : + The id of the current chain. + + Returns + ------- + hash : `ethereum.crypto.hash.Hash32` + Hash of the transaction. + " in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, "keccak256" |), + make_list [ + M.call (| + M.get_field (| M.get_name (| globals, "rlp" |), "encode" |), + make_list [ + make_tuple [ M.get_field (| M.get_name (| globals, "tx" |), "nonce" |); M.get_field (| M.get_name (| globals, "tx" |), "gas_price" |); M.get_field (| M.get_name (| globals, "tx" |), "gas" |); M.get_field (| M.get_name (| globals, "tx" |), "to" |); M.get_field (| M.get_name (| globals, "tx" |), "value" |); M.get_field (| M.get_name (| globals, "tx" |), "data" |); M.get_name (| globals, "chain_id" |); M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |); M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) ] + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Definition signing_hash_2930 : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "tx" ] |) in + let _ := Constant.str " + Compute the hash of a transaction used in a EIP 2930 signature. + + Parameters + ---------- + tx : + Transaction of interest. + + Returns + ------- + hash : `ethereum.crypto.hash.Hash32` + Hash of the transaction. + " in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, "keccak256" |), + make_list [ + BinOp.add (| + Constant.bytes "01", + M.call (| + M.get_field (| M.get_name (| globals, "rlp" |), "encode" |), + make_list [ + make_tuple [ M.get_field (| M.get_name (| globals, "tx" |), "chain_id" |); M.get_field (| M.get_name (| globals, "tx" |), "nonce" |); M.get_field (| M.get_name (| globals, "tx" |), "gas_price" |); M.get_field (| M.get_name (| globals, "tx" |), "gas" |); M.get_field (| M.get_name (| globals, "tx" |), "to" |); M.get_field (| M.get_name (| globals, "tx" |), "value" |); M.get_field (| M.get_name (| globals, "tx" |), "data" |); M.get_field (| M.get_name (| globals, "tx" |), "access_list" |) ] + ], + make_dict [] + |) + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Definition signing_hash_1559 : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "tx" ] |) in + let _ := Constant.str " + Compute the hash of a transaction used in a EIP 1559 signature. + + Parameters + ---------- + tx : + Transaction of interest. + + Returns + ------- + hash : `ethereum.crypto.hash.Hash32` + Hash of the transaction. + " in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, "keccak256" |), + make_list [ + BinOp.add (| + Constant.bytes "02", + M.call (| + M.get_field (| M.get_name (| globals, "rlp" |), "encode" |), + make_list [ + make_tuple [ M.get_field (| M.get_name (| globals, "tx" |), "chain_id" |); M.get_field (| M.get_name (| globals, "tx" |), "nonce" |); M.get_field (| M.get_name (| globals, "tx" |), "max_priority_fee_per_gas" |); M.get_field (| M.get_name (| globals, "tx" |), "max_fee_per_gas" |); M.get_field (| M.get_name (| globals, "tx" |), "gas" |); M.get_field (| M.get_name (| globals, "tx" |), "to" |); M.get_field (| M.get_name (| globals, "tx" |), "value" |); M.get_field (| M.get_name (| globals, "tx" |), "data" |); M.get_field (| M.get_name (| globals, "tx" |), "access_list" |) ] + ], + make_dict [] + |) + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Definition compute_header_hash : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "header" ] |) in + let _ := Constant.str " + Computes the hash of a block header. + + The header hash of a block is the canonical hash that is used to refer + to a specific block and completely distinguishes a block from another. + + ``keccak256`` is a function that produces a 256 bit hash of any input. + It also takes in any number of bytes as an input and produces a single + hash for them. A hash is a completely unique output for a single input. + So an input corresponds to one unique hash that can be used to identify + the input exactly. + + Prior to using the ``keccak256`` hash function, the header must be + encoded using the Recursive-Length Prefix. See :ref:`rlp`. + RLP encoding the header converts it into a space-efficient format that + allows for easy transfer of data between nodes. The purpose of RLP is to + encode arbitrarily nested arrays of binary data, and RLP is the primary + encoding method used to serialize objects in Ethereum's execution layer. + The only purpose of RLP is to encode structure; encoding specific data + types (e.g. strings, floats) is left up to higher-order protocols. + + Parameters + ---------- + header : + Header of interest. + + Returns + ------- + hash : `ethereum.crypto.hash.Hash32` + Hash of the header. + " in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, "keccak256" |), + make_list [ + M.call (| + M.get_field (| M.get_name (| globals, "rlp" |), "encode" |), + make_list [ + M.get_name (| globals, "header" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Definition check_gas_limit : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "gas_limit"; "parent_gas_limit" ] |) in + let _ := Constant.str " + Validates the gas limit for a block. + + The bounds of the gas limit, ``max_adjustment_delta``, is set as the + quotient of the parent block's gas limit and the + ``GAS_LIMIT_ADJUSTMENT_FACTOR``. Therefore, if the gas limit that is + passed through as a parameter is greater than or equal to the *sum* of + the parent's gas and the adjustment delta then the limit for gas is too + high and fails this function's check. Similarly, if the limit is less + than or equal to the *difference* of the parent's gas and the adjustment + delta *or* the predefined ``GAS_LIMIT_MINIMUM`` then this function's + check fails because the gas limit doesn't allow for a sufficient or + reasonable amount of gas to be used on a block. + + Parameters + ---------- + gas_limit : + Gas limit to validate. + + parent_gas_limit : + Gas limit of the parent block. + + Returns + ------- + check : `bool` + True if gas limit constraints are satisfied, False otherwise. + " in + let _ := M.assign_local (| + "max_adjustment_delta" , + BinOp.floor_div (| + M.get_name (| globals, "parent_gas_limit" |), + M.get_name (| globals, "GAS_LIMIT_ADJUSTMENT_FACTOR" |) + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.gt_e (| + M.get_name (| globals, "gas_limit" |), + BinOp.add (| + M.get_name (| globals, "parent_gas_limit" |), + M.get_name (| globals, "max_adjustment_delta" |) + |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + Constant.bool false + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + Compare.lt_e (| + M.get_name (| globals, "gas_limit" |), + BinOp.sub (| + M.get_name (| globals, "parent_gas_limit" |), + M.get_name (| globals, "max_adjustment_delta" |) + |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + Constant.bool false + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + Compare.lt (| + M.get_name (| globals, "gas_limit" |), + M.get_name (| globals, "GAS_LIMIT_MINIMUM" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + Constant.bool false + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.return_ (| + Constant.bool true + |) in + M.pure Constant.None_)). diff --git a/CoqOfPython/ethereum/paris/fork_types.v b/CoqOfPython/ethereum/paris/fork_types.v new file mode 100644 index 0000000..a4242a8 --- /dev/null +++ b/CoqOfPython/ethereum/paris/fork_types.v @@ -0,0 +1,98 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.paris.fork_types". + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Types +^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Types re-used throughout the specification, which are specific to Ethereum. +". + +Axiom dataclasses_imports_dataclass : + IsImported globals "dataclasses" "dataclass". + +Axiom ethereum_imports_rlp : + IsImported globals "ethereum" "rlp". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_Bytes : + IsImported globals "ethereum.base_types" "Bytes". +Axiom ethereum_base_types_imports_Bytes20 : + IsImported globals "ethereum.base_types" "Bytes20". +Axiom ethereum_base_types_imports_Bytes256 : + IsImported globals "ethereum.base_types" "Bytes256". +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". +Axiom ethereum_base_types_imports_slotted_freezable : + IsImported globals "ethereum.base_types" "slotted_freezable". + +Axiom ethereum_crypto_hash_imports_Hash32 : + IsImported globals "ethereum.crypto.hash" "Hash32". +Axiom ethereum_crypto_hash_imports_keccak256 : + IsImported globals "ethereum.crypto.hash" "keccak256". + +Definition Address : Value.t := M.run ltac:(M.monadic ( + M.get_name (| globals, "Bytes20" |) +)). + +Definition Root : Value.t := M.run ltac:(M.monadic ( + M.get_name (| globals, "Hash32" |) +)). + +Definition Bloom : Value.t := M.run ltac:(M.monadic ( + M.get_name (| globals, "Bytes256" |) +)). + +Definition Account : Value.t := + builtins.make_klass + [] + [ + + ] + [ + + ]. + +Definition EMPTY_ACCOUNT : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Account" |), + make_list [], + make_dict [] + |) +)). + +Definition encode_account : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "raw_account_data"; "storage_root" ] |) in + let _ := Constant.str " + Encode `Account` dataclass. + + Storage is not stored in the `Account` dataclass, so `Accounts` cannot be + encoded with providing a storage root. + " in + let _ := M.return_ (| + M.call (| + M.get_field (| M.get_name (| globals, "rlp" |), "encode" |), + make_list [ + make_tuple [ M.get_field (| M.get_name (| globals, "raw_account_data" |), "nonce" |); M.get_field (| M.get_name (| globals, "raw_account_data" |), "balance" |); M.get_name (| globals, "storage_root" |); M.call (| + M.get_name (| globals, "keccak256" |), + make_list [ + M.get_field (| M.get_name (| globals, "raw_account_data" |), "code" |) + ], + make_dict [] + |) ] + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). diff --git a/CoqOfPython/ethereum/paris/state.v b/CoqOfPython/ethereum/paris/state.v new file mode 100644 index 0000000..a1eda52 --- /dev/null +++ b/CoqOfPython/ethereum/paris/state.v @@ -0,0 +1,1252 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.paris.state". + +Definition expr_1 : Value.t := + Constant.str " +State +^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +The state contains all information that is preserved between transactions. + +It consists of a main account trie and storage tries for each contract. + +There is a distinction between an account that does not exist and +`EMPTY_ACCOUNT`. +". + +Axiom dataclasses_imports_dataclass : + IsImported globals "dataclasses" "dataclass". +Axiom dataclasses_imports_field : + IsImported globals "dataclasses" "field". + +Axiom typing_imports_Callable : + IsImported globals "typing" "Callable". +Axiom typing_imports_Dict : + IsImported globals "typing" "Dict". +Axiom typing_imports_List : + IsImported globals "typing" "List". +Axiom typing_imports_Optional : + IsImported globals "typing" "Optional". +Axiom typing_imports_Set : + IsImported globals "typing" "Set". +Axiom typing_imports_Tuple : + IsImported globals "typing" "Tuple". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_Bytes : + IsImported globals "ethereum.base_types" "Bytes". +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". +Axiom ethereum_base_types_imports_modify : + IsImported globals "ethereum.base_types" "modify". + +Axiom ethereum_utils_ensure_imports_ensure : + IsImported globals "ethereum.utils.ensure" "ensure". + +Axiom ethereum_paris_fork_types_imports_EMPTY_ACCOUNT : + IsImported globals "ethereum.paris.fork_types" "EMPTY_ACCOUNT". +Axiom ethereum_paris_fork_types_imports_Account : + IsImported globals "ethereum.paris.fork_types" "Account". +Axiom ethereum_paris_fork_types_imports_Address : + IsImported globals "ethereum.paris.fork_types" "Address". +Axiom ethereum_paris_fork_types_imports_Root : + IsImported globals "ethereum.paris.fork_types" "Root". + +Axiom ethereum_paris_trie_imports_EMPTY_TRIE_ROOT : + IsImported globals "ethereum.paris.trie" "EMPTY_TRIE_ROOT". +Axiom ethereum_paris_trie_imports_Trie : + IsImported globals "ethereum.paris.trie" "Trie". +Axiom ethereum_paris_trie_imports_copy_trie : + IsImported globals "ethereum.paris.trie" "copy_trie". +Axiom ethereum_paris_trie_imports_root : + IsImported globals "ethereum.paris.trie" "root". +Axiom ethereum_paris_trie_imports_trie_get : + IsImported globals "ethereum.paris.trie" "trie_get". +Axiom ethereum_paris_trie_imports_trie_set : + IsImported globals "ethereum.paris.trie" "trie_set". + +Definition State : Value.t := + builtins.make_klass + [] + [ + + ] + [ + + ]. + +Definition close_state : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "state" ] |) in + let _ := Constant.str " + Free resources held by the state. Used by optimized implementations to + release file descriptors. + " in + let _ := M.delete (| M.get_field (| M.get_name (| globals, "state" |), "_main_trie" |) |) in + let _ := M.delete (| M.get_field (| M.get_name (| globals, "state" |), "_storage_tries" |) |) in + let _ := M.delete (| M.get_field (| M.get_name (| globals, "state" |), "_snapshots" |) |) in + let _ := M.delete (| M.get_field (| M.get_name (| globals, "state" |), "_created_accounts" |) |) in + M.pure Constant.None_)). + +Definition begin_transaction : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "state" ] |) in + let _ := Constant.str " + Start a state transaction. + + Transactions are entirely implicit and can be nested. It is not possible to + calculate the state root during a transaction. + + Parameters + ---------- + state : State + The state. + " in + let _ := M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, "state" |), "_snapshots" |), "append" |), + make_list [ + make_tuple [ M.call (| + M.get_name (| globals, "copy_trie" |), + make_list [ + M.get_field (| M.get_name (| globals, "state" |), "_main_trie" |) + ], + make_dict [] + |); Constant.str "(* At expr: unsupported node type: DictComp *)" ] + ], + make_dict [] + |) in + M.pure Constant.None_)). + +Definition commit_transaction : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "state" ] |) in + let _ := Constant.str " + Commit a state transaction. + + Parameters + ---------- + state : State + The state. + " in + let _ := M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, "state" |), "_snapshots" |), "pop" |), + make_list [], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + UnOp.not (| M.get_field (| M.get_name (| globals, "state" |), "_snapshots" |) |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, "state" |), "_created_accounts" |), "clear" |), + make_list [], + make_dict [] + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + M.pure Constant.None_)). + +Definition rollback_transaction : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "state" ] |) in + let _ := Constant.str " + Rollback a state transaction, resetting the state to the point when the + corresponding `start_transaction()` call was made. + + Parameters + ---------- + state : State + The state. + " in + let _ := M.assign (| + make_tuple [ M.get_field (| M.get_name (| globals, "state" |), "_main_trie" |); M.get_field (| M.get_name (| globals, "state" |), "_storage_tries" |) ], + M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, "state" |), "_snapshots" |), "pop" |), + make_list [], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + UnOp.not (| M.get_field (| M.get_name (| globals, "state" |), "_snapshots" |) |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, "state" |), "_created_accounts" |), "clear" |), + make_list [], + make_dict [] + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + M.pure Constant.None_)). + +Definition get_account : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "state"; "address" ] |) in + let _ := Constant.str " + Get the `Account` object at an address. Returns `EMPTY_ACCOUNT` if there + is no account at the address. + + Use `get_account_optional()` if you care about the difference between a + non-existent account and `EMPTY_ACCOUNT`. + + Parameters + ---------- + state: `State` + The state + address : `Address` + Address to lookup. + + Returns + ------- + account : `Account` + Account at address. + " in + let _ := M.assign_local (| + "account" , + M.call (| + M.get_name (| globals, "get_account_optional" |), + make_list [ + M.get_name (| globals, "state" |); + M.get_name (| globals, "address" |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, "isinstance" |), + make_list [ + M.get_name (| globals, "account" |); + M.get_name (| globals, "Account" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + M.get_name (| globals, "account" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.return_ (| + M.get_name (| globals, "EMPTY_ACCOUNT" |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_)). + +Definition get_account_optional : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "state"; "address" ] |) in + let _ := Constant.str " + Get the `Account` object at an address. Returns `None` (rather than + `EMPTY_ACCOUNT`) if there is no account at the address. + + Parameters + ---------- + state: `State` + The state + address : `Address` + Address to lookup. + + Returns + ------- + account : `Account` + Account at address. + " in + let _ := M.assign_local (| + "account" , + M.call (| + M.get_name (| globals, "trie_get" |), + make_list [ + M.get_field (| M.get_name (| globals, "state" |), "_main_trie" |); + M.get_name (| globals, "address" |) + ], + make_dict [] + |) + |) in + let _ := M.return_ (| + M.get_name (| globals, "account" |) + |) in + M.pure Constant.None_)). + +Definition set_account : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "state"; "address"; "account" ] |) in + let _ := Constant.str " + Set the `Account` object at an address. Setting to `None` deletes + the account (but not its storage, see `destroy_account()`). + + Parameters + ---------- + state: `State` + The state + address : `Address` + Address to set. + account : `Account` + Account to set at address. + " in + let _ := M.call (| + M.get_name (| globals, "trie_set" |), + make_list [ + M.get_field (| M.get_name (| globals, "state" |), "_main_trie" |); + M.get_name (| globals, "address" |); + M.get_name (| globals, "account" |) + ], + make_dict [] + |) in + M.pure Constant.None_)). + +Definition destroy_account : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "state"; "address" ] |) in + let _ := Constant.str " + Completely remove the account at `address` and all of its storage. + + This function is made available exclusively for the `SELFDESTRUCT` + opcode. It is expected that `SELFDESTRUCT` will be disabled in a future + hardfork and this function will be removed. + + Parameters + ---------- + state: `State` + The state + address : `Address` + Address of account to destroy. + " in + let _ := M.call (| + M.get_name (| globals, "destroy_storage" |), + make_list [ + M.get_name (| globals, "state" |); + M.get_name (| globals, "address" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "set_account" |), + make_list [ + M.get_name (| globals, "state" |); + M.get_name (| globals, "address" |); + Constant.None_ + ], + make_dict [] + |) in + M.pure Constant.None_)). + +Definition destroy_storage : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "state"; "address" ] |) in + let _ := Constant.str " + Completely remove the storage at `address`. + + Parameters + ---------- + state: `State` + The state + address : `Address` + Address of account whose storage is to be deleted. + " in + let _ := + (* if *) + M.if_then_else (| + Compare.in_ (| + M.get_name (| globals, "address" |), + M.get_field (| M.get_name (| globals, "state" |), "_storage_tries" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.delete (| M.get_subscript (| + M.get_field (| M.get_name (| globals, "state" |), "_storage_tries" |), + M.get_name (| globals, "address" |) + |) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + M.pure Constant.None_)). + +Definition mark_account_created : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "state"; "address" ] |) in + let _ := Constant.str " + Mark an account as having been created in the current transaction. + This information is used by `get_storage_original()` to handle an obscure + edgecase. + + The marker is not removed even if the account creation reverts. Since the + account cannot have had code prior to its creation and can't call + `get_storage_original()`, this is harmless. + + Parameters + ---------- + state: `State` + The state + address : `Address` + Address of the account that has been created. + " in + let _ := M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, "state" |), "_created_accounts" |), "add" |), + make_list [ + M.get_name (| globals, "address" |) + ], + make_dict [] + |) in + M.pure Constant.None_)). + +Definition get_storage : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "state"; "address"; "key" ] |) in + let _ := Constant.str " + Get a value at a storage key on an account. Returns `U256(0)` if the + storage key has not been set previously. + + Parameters + ---------- + state: `State` + The state + address : `Address` + Address of the account. + key : `Bytes` + Key to lookup. + + Returns + ------- + value : `U256` + Value at the key. + " in + let _ := M.assign_local (| + "trie" , + M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, "state" |), "_storage_tries" |), "get" |), + make_list [ + M.get_name (| globals, "address" |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.is (| + M.get_name (| globals, "trie" |), + Constant.None_ + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "value" , + M.call (| + M.get_name (| globals, "trie_get" |), + make_list [ + M.get_name (| globals, "trie" |); + M.get_name (| globals, "key" |) + ], + make_dict [] + |) + |) in + let _ := M.assert (| M.call (| + M.get_name (| globals, "isinstance" |), + make_list [ + M.get_name (| globals, "value" |); + M.get_name (| globals, "U256" |) + ], + make_dict [] + |) |) in + let _ := M.return_ (| + M.get_name (| globals, "value" |) + |) in + M.pure Constant.None_)). + +Definition set_storage : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "state"; "address"; "key"; "value" ] |) in + let _ := Constant.str " + Set a value at a storage key on an account. Setting to `U256(0)` deletes + the key. + + Parameters + ---------- + state: `State` + The state + address : `Address` + Address of the account. + key : `Bytes` + Key to set. + value : `U256` + Value to set at the key. + " in + let _ := M.assert (| Compare.is_not (| + M.call (| + M.get_name (| globals, "trie_get" |), + make_list [ + M.get_field (| M.get_name (| globals, "state" |), "_main_trie" |); + M.get_name (| globals, "address" |) + ], + make_dict [] + |), + Constant.None_ + |) |) in + let _ := M.assign_local (| + "trie" , + M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, "state" |), "_storage_tries" |), "get" |), + make_list [ + M.get_name (| globals, "address" |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.is (| + M.get_name (| globals, "trie" |), + Constant.None_ + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "trie" , + M.call (| + M.get_name (| globals, "Trie" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.assign (| + M.get_subscript (| + M.get_field (| M.get_name (| globals, "state" |), "_storage_tries" |), + M.get_name (| globals, "address" |) + |), + M.get_name (| globals, "trie" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.call (| + M.get_name (| globals, "trie_set" |), + make_list [ + M.get_name (| globals, "trie" |); + M.get_name (| globals, "key" |); + M.get_name (| globals, "value" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_field (| M.get_name (| globals, "trie" |), "_data" |), + Constant.str "(* At expr: unsupported node type: Dict *)" + |), + (* then *) + ltac:(M.monadic ( + let _ := M.delete (| M.get_subscript (| + M.get_field (| M.get_name (| globals, "state" |), "_storage_tries" |), + M.get_name (| globals, "address" |) + |) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + M.pure Constant.None_)). + +Definition storage_root : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "state"; "address" ] |) in + let _ := Constant.str " + Calculate the storage root of an account. + + Parameters + ---------- + state: + The state + address : + Address of the account. + + Returns + ------- + root : `Root` + Storage root of the account. + " in + let _ := M.assert (| UnOp.not (| M.get_field (| M.get_name (| globals, "state" |), "_snapshots" |) |) |) in + let _ := + (* if *) + M.if_then_else (| + Compare.in_ (| + M.get_name (| globals, "address" |), + M.get_field (| M.get_name (| globals, "state" |), "_storage_tries" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + M.call (| + M.get_name (| globals, "root" |), + make_list [ + M.get_subscript (| + M.get_field (| M.get_name (| globals, "state" |), "_storage_tries" |), + M.get_name (| globals, "address" |) + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.return_ (| + M.get_name (| globals, "EMPTY_TRIE_ROOT" |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_)). + +Definition state_root : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "state" ] |) in + let _ := Constant.str " + Calculate the state root. + + Parameters + ---------- + state: + The current state. + + Returns + ------- + root : `Root` + The state root. + " in + let _ := M.assert (| UnOp.not (| M.get_field (| M.get_name (| globals, "state" |), "_snapshots" |) |) |) in +(* At stmt: unsupported node type: FunctionDef *) + let _ := M.return_ (| + M.call (| + M.get_name (| globals, "root" |), + make_list [ + M.get_field (| M.get_name (| globals, "state" |), "_main_trie" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Definition account_exists : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "state"; "address" ] |) in + let _ := Constant.str " + Checks if an account exists in the state trie + + Parameters + ---------- + state: + The state + address: + Address of the account that needs to be checked. + + Returns + ------- + account_exists : `bool` + True if account exists in the state trie, False otherwise + " in + let _ := M.return_ (| + Compare.is_not (| + M.call (| + M.get_name (| globals, "get_account_optional" |), + make_list [ + M.get_name (| globals, "state" |); + M.get_name (| globals, "address" |) + ], + make_dict [] + |), + Constant.None_ + |) + |) in + M.pure Constant.None_)). + +Definition account_has_code_or_nonce : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "state"; "address" ] |) in + let _ := Constant.str " + Checks if an account has non zero nonce or non empty code + + Parameters + ---------- + state: + The state + address: + Address of the account that needs to be checked. + + Returns + ------- + has_code_or_nonce : `bool` + True if if an account has non zero nonce or non empty code, + False otherwise. + " in + let _ := M.assign_local (| + "account" , + M.call (| + M.get_name (| globals, "get_account" |), + make_list [ + M.get_name (| globals, "state" |); + M.get_name (| globals, "address" |) + ], + make_dict [] + |) + |) in + let _ := M.return_ (| + BoolOp.or (| + Compare.not_eq (| + M.get_field (| M.get_name (| globals, "account" |), "nonce" |), + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + |), + ltac:(M.monadic ( + Compare.not_eq (| + M.get_field (| M.get_name (| globals, "account" |), "code" |), + Constant.bytes "" + |) + )) + |) + |) in + M.pure Constant.None_)). + +Definition is_account_empty : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "state"; "address" ] |) in + let _ := Constant.str " + Checks if an account has zero nonce, empty code and zero balance. + + Parameters + ---------- + state: + The state + address: + Address of the account that needs to be checked. + + Returns + ------- + is_empty : `bool` + True if if an account has zero nonce, empty code and zero balance, + False otherwise. + " in + let _ := M.assign_local (| + "account" , + M.call (| + M.get_name (| globals, "get_account" |), + make_list [ + M.get_name (| globals, "state" |); + M.get_name (| globals, "address" |) + ], + make_dict [] + |) + |) in + let _ := M.return_ (| + BoolOp.and (| + Compare.eq (| + M.get_field (| M.get_name (| globals, "account" |), "nonce" |), + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + |), + ltac:(M.monadic ( + BoolOp.and (| + Compare.eq (| + M.get_field (| M.get_name (| globals, "account" |), "code" |), + Constant.bytes "" + |), + ltac:(M.monadic ( + Compare.eq (| + M.get_field (| M.get_name (| globals, "account" |), "balance" |), + Constant.int 0 + |) + )) + |) + )) + |) + |) in + M.pure Constant.None_)). + +Definition account_exists_and_is_empty : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "state"; "address" ] |) in + let _ := Constant.str " + Checks if an account exists and has zero nonce, empty code and zero + balance. + + Parameters + ---------- + state: + The state + address: + Address of the account that needs to be checked. + + Returns + ------- + exists_and_is_empty : `bool` + True if an account exists and has zero nonce, empty code and zero + balance, False otherwise. + " in + let _ := M.assign_local (| + "account" , + M.call (| + M.get_name (| globals, "get_account_optional" |), + make_list [ + M.get_name (| globals, "state" |); + M.get_name (| globals, "address" |) + ], + make_dict [] + |) + |) in + let _ := M.return_ (| + BoolOp.and (| + Compare.is_not (| + M.get_name (| globals, "account" |), + Constant.None_ + |), + ltac:(M.monadic ( + BoolOp.and (| + Compare.eq (| + M.get_field (| M.get_name (| globals, "account" |), "nonce" |), + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + |), + ltac:(M.monadic ( + BoolOp.and (| + Compare.eq (| + M.get_field (| M.get_name (| globals, "account" |), "code" |), + Constant.bytes "" + |), + ltac:(M.monadic ( + Compare.eq (| + M.get_field (| M.get_name (| globals, "account" |), "balance" |), + Constant.int 0 + |) + )) + |) + )) + |) + )) + |) + |) in + M.pure Constant.None_)). + +Definition is_account_alive : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "state"; "address" ] |) in + let _ := Constant.str " + Check whether is an account is both in the state and non empty. + + Parameters + ---------- + state: + The state + address: + Address of the account that needs to be checked. + + Returns + ------- + is_alive : `bool` + True if the account is alive. + " in + let _ := M.assign_local (| + "account" , + M.call (| + M.get_name (| globals, "get_account_optional" |), + make_list [ + M.get_name (| globals, "state" |); + M.get_name (| globals, "address" |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.is (| + M.get_name (| globals, "account" |), + Constant.None_ + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + Constant.bool false + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.return_ (| + UnOp.not (| BoolOp.and (| + Compare.eq (| + M.get_field (| M.get_name (| globals, "account" |), "nonce" |), + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + |), + ltac:(M.monadic ( + BoolOp.and (| + Compare.eq (| + M.get_field (| M.get_name (| globals, "account" |), "code" |), + Constant.bytes "" + |), + ltac:(M.monadic ( + Compare.eq (| + M.get_field (| M.get_name (| globals, "account" |), "balance" |), + Constant.int 0 + |) + )) + |) + )) + |) |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_)). + +Definition modify_state : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "state"; "address"; "f" ] |) in + let _ := Constant.str " + Modify an `Account` in the `State`. + " in + let _ := M.call (| + M.get_name (| globals, "set_account" |), + make_list [ + M.get_name (| globals, "state" |); + M.get_name (| globals, "address" |); + M.call (| + M.get_name (| globals, "modify" |), + make_list [ + M.call (| + M.get_name (| globals, "get_account" |), + make_list [ + M.get_name (| globals, "state" |); + M.get_name (| globals, "address" |) + ], + make_dict [] + |); + M.get_name (| globals, "f" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + M.pure Constant.None_)). + +Definition move_ether : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "state"; "sender_address"; "recipient_address"; "amount" ] |) in + let _ := Constant.str " + Move funds between accounts. + " in +(* At stmt: unsupported node type: FunctionDef *) +(* At stmt: unsupported node type: FunctionDef *) + let _ := M.call (| + M.get_name (| globals, "modify_state" |), + make_list [ + M.get_name (| globals, "state" |); + M.get_name (| globals, "sender_address" |); + M.get_name (| globals, "reduce_sender_balance" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "modify_state" |), + make_list [ + M.get_name (| globals, "state" |); + M.get_name (| globals, "recipient_address" |); + M.get_name (| globals, "increase_recipient_balance" |) + ], + make_dict [] + |) in + M.pure Constant.None_)). + +Definition set_account_balance : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "state"; "address"; "amount" ] |) in + let _ := Constant.str " + Sets the balance of an account. + + Parameters + ---------- + state: + The current state. + + address: + Address of the account whose nonce needs to be incremented. + + amount: + The amount that needs to set in balance. + " in +(* At stmt: unsupported node type: FunctionDef *) + let _ := M.call (| + M.get_name (| globals, "modify_state" |), + make_list [ + M.get_name (| globals, "state" |); + M.get_name (| globals, "address" |); + M.get_name (| globals, "set_balance" |) + ], + make_dict [] + |) in + M.pure Constant.None_)). + +Definition touch_account : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "state"; "address" ] |) in + let _ := Constant.str " + Initializes an account to state. + + Parameters + ---------- + state: + The current state. + + address: + The address of the account that need to initialised. + " in + let _ := + (* if *) + M.if_then_else (| + UnOp.not (| M.call (| + M.get_name (| globals, "account_exists" |), + make_list [ + M.get_name (| globals, "state" |); + M.get_name (| globals, "address" |) + ], + make_dict [] + |) |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, "set_account" |), + make_list [ + M.get_name (| globals, "state" |); + M.get_name (| globals, "address" |); + M.get_name (| globals, "EMPTY_ACCOUNT" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + M.pure Constant.None_)). + +Definition increment_nonce : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "state"; "address" ] |) in + let _ := Constant.str " + Increments the nonce of an account. + + Parameters + ---------- + state: + The current state. + + address: + Address of the account whose nonce needs to be incremented. + " in +(* At stmt: unsupported node type: FunctionDef *) + let _ := M.call (| + M.get_name (| globals, "modify_state" |), + make_list [ + M.get_name (| globals, "state" |); + M.get_name (| globals, "address" |); + M.get_name (| globals, "increase_nonce" |) + ], + make_dict [] + |) in + M.pure Constant.None_)). + +Definition set_code : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "state"; "address"; "code" ] |) in + let _ := Constant.str " + Sets Account code. + + Parameters + ---------- + state: + The current state. + + address: + Address of the account whose code needs to be update. + + code: + The bytecode that needs to be set. + " in +(* At stmt: unsupported node type: FunctionDef *) + let _ := M.call (| + M.get_name (| globals, "modify_state" |), + make_list [ + M.get_name (| globals, "state" |); + M.get_name (| globals, "address" |); + M.get_name (| globals, "write_code" |) + ], + make_dict [] + |) in + M.pure Constant.None_)). + +Definition get_storage_original : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "state"; "address"; "key" ] |) in + let _ := Constant.str " + Get the original value in a storage slot i.e. the value before the current + transaction began. This function reads the value from the snapshots taken + before executing the transaction. + + Parameters + ---------- + state: + The current state. + address: + Address of the account to read the value from. + key: + Key of the storage slot. + " in + let _ := + (* if *) + M.if_then_else (| + Compare.in_ (| + M.get_name (| globals, "address" |), + M.get_field (| M.get_name (| globals, "state" |), "_created_accounts" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign (| + make_tuple [ M.get_name (| globals, "_" |); M.get_name (| globals, "original_trie" |) ], + M.get_subscript (| + M.get_field (| M.get_name (| globals, "state" |), "_snapshots" |), + Constant.int 0 + |) + |) in + let _ := M.assign_local (| + "original_account_trie" , + M.call (| + M.get_field (| M.get_name (| globals, "original_trie" |), "get" |), + make_list [ + M.get_name (| globals, "address" |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.is (| + M.get_name (| globals, "original_account_trie" |), + Constant.None_ + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "original_value" , + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "original_value" , + M.call (| + M.get_name (| globals, "trie_get" |), + make_list [ + M.get_name (| globals, "original_account_trie" |); + M.get_name (| globals, "key" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + )) |) in + let _ := M.assert (| M.call (| + M.get_name (| globals, "isinstance" |), + make_list [ + M.get_name (| globals, "original_value" |); + M.get_name (| globals, "U256" |) + ], + make_dict [] + |) |) in + let _ := M.return_ (| + M.get_name (| globals, "original_value" |) + |) in + M.pure Constant.None_)). diff --git a/CoqOfPython/ethereum/paris/transactions.v b/CoqOfPython/ethereum/paris/transactions.v new file mode 100644 index 0000000..c466978 --- /dev/null +++ b/CoqOfPython/ethereum/paris/transactions.v @@ -0,0 +1,293 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.paris.transactions". + +Definition expr_1 : Value.t := + Constant.str " +Transactions are atomic units of work created externally to Ethereum and +submitted to be executed. If Ethereum is viewed as a state machine, +transactions are the events that move between states. +". + +Axiom dataclasses_imports_dataclass : + IsImported globals "dataclasses" "dataclass". + +Axiom typing_imports_Tuple : + IsImported globals "typing" "Tuple". +Axiom typing_imports_Union : + IsImported globals "typing" "Union". + +Axiom ethereum_imports_rlp : + IsImported globals "ethereum" "rlp". + +Axiom ethereum_base_types_imports_U64 : + IsImported globals "ethereum.base_types" "U64". +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_Bytes : + IsImported globals "ethereum.base_types" "Bytes". +Axiom ethereum_base_types_imports_Bytes0 : + IsImported globals "ethereum.base_types" "Bytes0". +Axiom ethereum_base_types_imports_Bytes32 : + IsImported globals "ethereum.base_types" "Bytes32". +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". +Axiom ethereum_base_types_imports_slotted_freezable : + IsImported globals "ethereum.base_types" "slotted_freezable". + +Axiom ethereum_exceptions_imports_InvalidBlock : + IsImported globals "ethereum.exceptions" "InvalidBlock". + +Axiom ethereum_paris_fork_types_imports_Address : + IsImported globals "ethereum.paris.fork_types" "Address". + +Definition TX_BASE_COST : Value.t := M.run ltac:(M.monadic ( + Constant.int 21000 +)). + +Definition TX_DATA_COST_PER_NON_ZERO : Value.t := M.run ltac:(M.monadic ( + Constant.int 16 +)). + +Definition TX_DATA_COST_PER_ZERO : Value.t := M.run ltac:(M.monadic ( + Constant.int 4 +)). + +Definition TX_CREATE_COST : Value.t := M.run ltac:(M.monadic ( + Constant.int 32000 +)). + +Definition TX_ACCESS_LIST_ADDRESS_COST : Value.t := M.run ltac:(M.monadic ( + Constant.int 2400 +)). + +Definition TX_ACCESS_LIST_STORAGE_KEY_COST : Value.t := M.run ltac:(M.monadic ( + Constant.int 1900 +)). + +Definition LegacyTransaction : Value.t := + builtins.make_klass + [] + [ + + ] + [ + + ]. + +Definition AccessListTransaction : Value.t := + builtins.make_klass + [] + [ + + ] + [ + + ]. + +Definition FeeMarketTransaction : Value.t := + builtins.make_klass + [] + [ + + ] + [ + + ]. + +Definition Transaction : Value.t := M.run ltac:(M.monadic ( + M.get_subscript (| + M.get_name (| globals, "Union" |), + make_tuple [ M.get_name (| globals, "LegacyTransaction" |); M.get_name (| globals, "AccessListTransaction" |); M.get_name (| globals, "FeeMarketTransaction" |) ] + |) +)). + +Definition encode_transaction : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "tx" ] |) in + let _ := Constant.str " + Encode a transaction. Needed because non-legacy transactions aren't RLP. + " in + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, "isinstance" |), + make_list [ + M.get_name (| globals, "tx" |); + M.get_name (| globals, "LegacyTransaction" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + M.get_name (| globals, "tx" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, "isinstance" |), + make_list [ + M.get_name (| globals, "tx" |); + M.get_name (| globals, "AccessListTransaction" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + BinOp.add (| + Constant.bytes "01", + M.call (| + M.get_field (| M.get_name (| globals, "rlp" |), "encode" |), + make_list [ + M.get_name (| globals, "tx" |) + ], + make_dict [] + |) + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, "isinstance" |), + make_list [ + M.get_name (| globals, "tx" |); + M.get_name (| globals, "FeeMarketTransaction" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + BinOp.add (| + Constant.bytes "02", + M.call (| + M.get_field (| M.get_name (| globals, "rlp" |), "encode" |), + make_list [ + M.get_name (| globals, "tx" |) + ], + make_dict [] + |) + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.raise (| Some (M.call (| + M.get_name (| globals, "Exception" |), + make_list [ + Constant.str "(* At expr: unsupported node type: JoinedStr *)" + ], + make_dict [] + |)) |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_)). + +Definition decode_transaction : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "tx" ] |) in + let _ := Constant.str " + Decode a transaction. Needed because non-legacy transactions aren't RLP. + " in + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, "isinstance" |), + make_list [ + M.get_name (| globals, "tx" |); + M.get_name (| globals, "Bytes" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_subscript (| + M.get_name (| globals, "tx" |), + Constant.int 0 + |), + Constant.int 1 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + M.call (| + M.get_field (| M.get_name (| globals, "rlp" |), "decode_to" |), + make_list [ + M.get_name (| globals, "AccessListTransaction" |); + M.slice (| + M.get_name (| globals, "tx" |), + Constant.int 1, + Constant.None_, + Constant.None_ + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_subscript (| + M.get_name (| globals, "tx" |), + Constant.int 0 + |), + Constant.int 2 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + M.call (| + M.get_field (| M.get_name (| globals, "rlp" |), "decode_to" |), + make_list [ + M.get_name (| globals, "FeeMarketTransaction" |); + M.slice (| + M.get_name (| globals, "tx" |), + Constant.int 1, + Constant.None_, + Constant.None_ + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, "InvalidBlock" |)) |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.return_ (| + M.get_name (| globals, "tx" |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_)). diff --git a/CoqOfPython/ethereum/paris/trie.v b/CoqOfPython/ethereum/paris/trie.v new file mode 100644 index 0000000..90b1e2c --- /dev/null +++ b/CoqOfPython/ethereum/paris/trie.v @@ -0,0 +1,1595 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.paris.trie". + +Definition expr_1 : Value.t := + Constant.str " +State Trie +^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +The state trie is the structure responsible for storing +`.fork_types.Account` objects. +". + +(* At top_level_stmt: unsupported node type: Import *) + +Axiom dataclasses_imports_dataclass : + IsImported globals "dataclasses" "dataclass". +Axiom dataclasses_imports_field : + IsImported globals "dataclasses" "field". + +Axiom typing_imports_Callable : + IsImported globals "typing" "Callable". +Axiom typing_imports_Dict : + IsImported globals "typing" "Dict". +Axiom typing_imports_Generic : + IsImported globals "typing" "Generic". +Axiom typing_imports_List : + IsImported globals "typing" "List". +Axiom typing_imports_Mapping : + IsImported globals "typing" "Mapping". +Axiom typing_imports_MutableMapping : + IsImported globals "typing" "MutableMapping". +Axiom typing_imports_Optional : + IsImported globals "typing" "Optional". +Axiom typing_imports_Sequence : + IsImported globals "typing" "Sequence". +Axiom typing_imports_TypeVar : + IsImported globals "typing" "TypeVar". +Axiom typing_imports_Union : + IsImported globals "typing" "Union". +Axiom typing_imports_cast : + IsImported globals "typing" "cast". + +Axiom ethereum_crypto_hash_imports_keccak256 : + IsImported globals "ethereum.crypto.hash" "keccak256". + +Axiom ethereum_gray_glacier_imports_trie : + IsImported globals "ethereum.gray_glacier" "trie". + +Axiom ethereum_utils_ensure_imports_ensure : + IsImported globals "ethereum.utils.ensure" "ensure". + +Axiom ethereum_utils_hexadecimal_imports_hex_to_bytes : + IsImported globals "ethereum.utils.hexadecimal" "hex_to_bytes". + +Axiom ethereum_imports_rlp : + IsImported globals "ethereum" "rlp". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_Bytes : + IsImported globals "ethereum.base_types" "Bytes". +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". +Axiom ethereum_base_types_imports_slotted_freezable : + IsImported globals "ethereum.base_types" "slotted_freezable". + +Axiom ethereum_paris_blocks_imports_Receipt : + IsImported globals "ethereum.paris.blocks" "Receipt". + +Axiom ethereum_paris_fork_types_imports_Account : + IsImported globals "ethereum.paris.fork_types" "Account". +Axiom ethereum_paris_fork_types_imports_Address : + IsImported globals "ethereum.paris.fork_types" "Address". +Axiom ethereum_paris_fork_types_imports_Root : + IsImported globals "ethereum.paris.fork_types" "Root". +Axiom ethereum_paris_fork_types_imports_encode_account : + IsImported globals "ethereum.paris.fork_types" "encode_account". + +Axiom ethereum_paris_transactions_imports_LegacyTransaction : + IsImported globals "ethereum.paris.transactions" "LegacyTransaction". + +Definition EMPTY_TRIE_ROOT : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Root" |), + make_list [ + M.call (| + M.get_name (| globals, "hex_to_bytes" |), + make_list [ + Constant.str "56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421" + ], + make_dict [] + |) + ], + make_dict [] + |) +)). + +Definition Node : Value.t := M.run ltac:(M.monadic ( + M.get_subscript (| + M.get_name (| globals, "Union" |), + make_tuple [ M.get_name (| globals, "Account" |); M.get_name (| globals, "Bytes" |); M.get_name (| globals, "LegacyTransaction" |); M.get_name (| globals, "Receipt" |); M.get_name (| globals, "Uint" |); M.get_name (| globals, "U256" |); Constant.None_ ] + |) +)). + +Definition K : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "TypeVar" |), + make_list [ + Constant.str "K" + ], + make_dict [] + |) +)). + +Definition V : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "TypeVar" |), + make_list [ + Constant.str "V"; + M.get_subscript (| + M.get_name (| globals, "Optional" |), + M.get_name (| globals, "Account" |) + |); + M.get_subscript (| + M.get_name (| globals, "Optional" |), + M.get_name (| globals, "Bytes" |) + |); + M.get_name (| globals, "Bytes" |); + M.get_subscript (| + M.get_name (| globals, "Optional" |), + M.get_subscript (| + M.get_name (| globals, "Union" |), + make_tuple [ M.get_name (| globals, "LegacyTransaction" |); M.get_name (| globals, "Bytes" |) ] + |) + |); + M.get_subscript (| + M.get_name (| globals, "Optional" |), + M.get_subscript (| + M.get_name (| globals, "Union" |), + make_tuple [ M.get_name (| globals, "Receipt" |); M.get_name (| globals, "Bytes" |) ] + |) + |); + M.get_name (| globals, "Uint" |); + M.get_name (| globals, "U256" |) + ], + make_dict [] + |) +)). + +Definition LeafNode : Value.t := + builtins.make_klass + [] + [ + + ] + [ + + ]. + +Definition ExtensionNode : Value.t := + builtins.make_klass + [] + [ + + ] + [ + + ]. + +Definition BranchNode : Value.t := + builtins.make_klass + [] + [ + + ] + [ + + ]. + +Definition InternalNode : Value.t := M.run ltac:(M.monadic ( + M.get_subscript (| + M.get_name (| globals, "Union" |), + make_tuple [ M.get_name (| globals, "LeafNode" |); M.get_name (| globals, "ExtensionNode" |); M.get_name (| globals, "BranchNode" |) ] + |) +)). + +Definition encode_internal_node : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "node" ] |) in + let _ := Constant.str " + Encodes a Merkle Trie node into its RLP form. The RLP will then be + serialized into a `Bytes` and hashed unless it is less that 32 bytes + when serialized. + + This function also accepts `None`, representing the absence of a node, + which is encoded to `b""""`. + + Parameters + ---------- + node : Optional[InternalNode] + The node to encode. + + Returns + ------- + encoded : `rlp.RLP` + The node encoded as RLP. + " in +(* At stmt: unsupported node type: AnnAssign *) + let _ := + (* if *) + M.if_then_else (| + Compare.is (| + M.get_name (| globals, "node" |), + Constant.None_ + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "unencoded" , + Constant.bytes "" + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, "isinstance" |), + make_list [ + M.get_name (| globals, "node" |); + M.get_name (| globals, "LeafNode" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "unencoded" , + make_tuple [ M.call (| + M.get_name (| globals, "nibble_list_to_compact" |), + make_list [ + M.get_field (| M.get_name (| globals, "node" |), "rest_of_key" |); + Constant.bool true + ], + make_dict [] + |); M.get_field (| M.get_name (| globals, "node" |), "value" |) ] + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, "isinstance" |), + make_list [ + M.get_name (| globals, "node" |); + M.get_name (| globals, "ExtensionNode" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "unencoded" , + make_tuple [ M.call (| + M.get_name (| globals, "nibble_list_to_compact" |), + make_list [ + M.get_field (| M.get_name (| globals, "node" |), "key_segment" |); + Constant.bool false + ], + make_dict [] + |); M.get_field (| M.get_name (| globals, "node" |), "subnode" |) ] + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, "isinstance" |), + make_list [ + M.get_name (| globals, "node" |); + M.get_name (| globals, "BranchNode" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "unencoded" , + BinOp.add (| + M.get_field (| M.get_name (| globals, "node" |), "subnodes" |), + make_list [ + M.get_field (| M.get_name (| globals, "node" |), "value" |) + ] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.raise (| Some (M.call (| + M.get_name (| globals, "AssertionError" |), + make_list [ + Constant.str "(* At expr: unsupported node type: JoinedStr *)" + ], + make_dict [] + |)) |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "encoded" , + M.call (| + M.get_field (| M.get_name (| globals, "rlp" |), "encode" |), + make_list [ + M.get_name (| globals, "unencoded" |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.lt (| + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_name (| globals, "encoded" |) + ], + make_dict [] + |), + Constant.int 32 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + M.get_name (| globals, "unencoded" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.return_ (| + M.call (| + M.get_name (| globals, "keccak256" |), + make_list [ + M.get_name (| globals, "encoded" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_)). + +Definition encode_node : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "node"; "storage_root" ] |) in + let _ := Constant.str " + Encode a Node for storage in the Merkle Trie. + + Currently mostly an unimplemented stub. + " in + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, "isinstance" |), + make_list [ + M.get_name (| globals, "node" |); + M.get_name (| globals, "Account" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assert (| Compare.is_not (| + M.get_name (| globals, "storage_root" |), + Constant.None_ + |) |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, "encode_account" |), + make_list [ + M.get_name (| globals, "node" |); + M.get_name (| globals, "storage_root" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, "isinstance" |), + make_list [ + M.get_name (| globals, "node" |); + make_tuple [ M.get_name (| globals, "LegacyTransaction" |); M.get_name (| globals, "Receipt" |); M.get_name (| globals, "U256" |) ] + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + M.call (| + M.get_field (| M.get_name (| globals, "rlp" |), "encode" |), + make_list [ + M.call (| + M.get_name (| globals, "cast" |), + make_list [ + M.get_field (| M.get_name (| globals, "rlp" |), "RLP" |); + M.get_name (| globals, "node" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, "isinstance" |), + make_list [ + M.get_name (| globals, "node" |); + M.get_name (| globals, "Bytes" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + M.get_name (| globals, "node" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.return_ (| + M.call (| + M.get_field (| M.get_name (| globals, "previous_trie" |), "encode_node" |), + make_list [ + M.get_name (| globals, "node" |); + M.get_name (| globals, "storage_root" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_)). + +Definition Trie : Value.t := + builtins.make_klass + [(* At base: unsupported node type: Subscript *)] + [ + + ] + [ + + ]. + +Definition copy_trie : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "trie" ] |) in + let _ := Constant.str " + Create a copy of `trie`. Since only frozen objects may be stored in tries, + the contents are reused. + + Parameters + ---------- + trie: `Trie` + Trie to copy. + + Returns + ------- + new_trie : `Trie[K, V]` + A copy of the trie. + " in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, "Trie" |), + make_list [ + M.get_field (| M.get_name (| globals, "trie" |), "secured" |); + M.get_field (| M.get_name (| globals, "trie" |), "default" |); + M.call (| + M.get_field (| M.get_name (| globals, "copy" |), "copy" |), + make_list [ + M.get_field (| M.get_name (| globals, "trie" |), "_data" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Definition trie_set : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "trie"; "key"; "value" ] |) in + let _ := Constant.str " + Stores an item in a Merkle Trie. + + This method deletes the key if `value == trie.default`, because the Merkle + Trie represents the default value by omitting it from the trie. + + Parameters + ---------- + trie: `Trie` + Trie to store in. + key : `Bytes` + Key to lookup. + value : `V` + Node to insert at `key`. + " in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, "value" |), + M.get_field (| M.get_name (| globals, "trie" |), "default" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + Compare.in_ (| + M.get_name (| globals, "key" |), + M.get_field (| M.get_name (| globals, "trie" |), "_data" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.delete (| M.get_subscript (| + M.get_field (| M.get_name (| globals, "trie" |), "_data" |), + M.get_name (| globals, "key" |) + |) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign (| + M.get_subscript (| + M.get_field (| M.get_name (| globals, "trie" |), "_data" |), + M.get_name (| globals, "key" |) + |), + M.get_name (| globals, "value" |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_)). + +Definition trie_get : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "trie"; "key" ] |) in + let _ := Constant.str " + Gets an item from the Merkle Trie. + + This method returns `trie.default` if the key is missing. + + Parameters + ---------- + trie: + Trie to lookup in. + key : + Key to lookup. + + Returns + ------- + node : `V` + Node at `key` in the trie. + " in + let _ := M.return_ (| + M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, "trie" |), "_data" |), "get" |), + make_list [ + M.get_name (| globals, "key" |); + M.get_field (| M.get_name (| globals, "trie" |), "default" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Definition common_prefix_length : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "a"; "b" ] |) in + let _ := Constant.str " + Find the longest common prefix of two sequences. + " in + let _ := + M.for_ (| + M.get_name (| globals, "i" |), + M.call (| + M.get_name (| globals, "range" |), + make_list [ + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_name (| globals, "a" |) + ], + make_dict [] + |) + ], + make_dict [] + |), + ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + BoolOp.or (| + Compare.gt_e (| + M.get_name (| globals, "i" |), + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_name (| globals, "b" |) + ], + make_dict [] + |) + |), + ltac:(M.monadic ( + Compare.not_eq (| + M.get_subscript (| + M.get_name (| globals, "a" |), + M.get_name (| globals, "i" |) + |), + M.get_subscript (| + M.get_name (| globals, "b" |), + M.get_name (| globals, "i" |) + |) + |) + )) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + M.get_name (| globals, "i" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_name (| globals, "a" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Definition nibble_list_to_compact : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "x"; "is_leaf" ] |) in + let _ := Constant.str " + Compresses nibble-list into a standard byte array with a flag. + + A nibble-list is a list of byte values no greater than `15`. The flag is + encoded in high nibble of the highest byte. The flag nibble can be broken + down into two two-bit flags. + + Highest nibble:: + + +---+---+----------+--------+ + | _ | _ | is_leaf | parity | + +---+---+----------+--------+ + 3 2 1 0 + + + The lowest bit of the nibble encodes the parity of the length of the + remaining nibbles -- `0` when even and `1` when odd. The second lowest bit + is used to distinguish leaf and extension nodes. The other two bits are not + used. + + Parameters + ---------- + x : + Array of nibbles. + is_leaf : + True if this is part of a leaf node, or false if it is an extension + node. + + Returns + ------- + compressed : `bytearray` + Compact byte array. + " in + let _ := M.assign_local (| + "compact" , + M.call (| + M.get_name (| globals, "bytearray" |), + make_list [], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + BinOp.mod_ (| + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_name (| globals, "x" |) + ], + make_dict [] + |), + Constant.int 2 + |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_field (| M.get_name (| globals, "compact" |), "append" |), + make_list [ + BinOp.mult (| + Constant.int 16, + BinOp.mult (| + Constant.int 2, + M.get_name (| globals, "is_leaf" |) + |) + |) + ], + make_dict [] + |) in + let _ := + M.for_ (| + M.get_name (| globals, "i" |), + M.call (| + M.get_name (| globals, "range" |), + make_list [ + Constant.int 0; + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_name (| globals, "x" |) + ], + make_dict [] + |); + Constant.int 2 + ], + make_dict [] + |), + ltac:(M.monadic ( + let _ := M.call (| + M.get_field (| M.get_name (| globals, "compact" |), "append" |), + make_list [ + BinOp.add (| + BinOp.mult (| + Constant.int 16, + M.get_subscript (| + M.get_name (| globals, "x" |), + M.get_name (| globals, "i" |) + |) + |), + M.get_subscript (| + M.get_name (| globals, "x" |), + BinOp.add (| + M.get_name (| globals, "i" |), + Constant.int 1 + |) + |) + |) + ], + make_dict [] + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.call (| + M.get_field (| M.get_name (| globals, "compact" |), "append" |), + make_list [ + BinOp.add (| + BinOp.mult (| + Constant.int 16, + BinOp.add (| + BinOp.mult (| + Constant.int 2, + M.get_name (| globals, "is_leaf" |) + |), + Constant.int 1 + |) + |), + M.get_subscript (| + M.get_name (| globals, "x" |), + Constant.int 0 + |) + |) + ], + make_dict [] + |) in + let _ := + M.for_ (| + M.get_name (| globals, "i" |), + M.call (| + M.get_name (| globals, "range" |), + make_list [ + Constant.int 1; + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_name (| globals, "x" |) + ], + make_dict [] + |); + Constant.int 2 + ], + make_dict [] + |), + ltac:(M.monadic ( + let _ := M.call (| + M.get_field (| M.get_name (| globals, "compact" |), "append" |), + make_list [ + BinOp.add (| + BinOp.mult (| + Constant.int 16, + M.get_subscript (| + M.get_name (| globals, "x" |), + M.get_name (| globals, "i" |) + |) + |), + M.get_subscript (| + M.get_name (| globals, "x" |), + BinOp.add (| + M.get_name (| globals, "i" |), + Constant.int 1 + |) + |) + |) + ], + make_dict [] + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + M.pure Constant.None_ + )) |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, "Bytes" |), + make_list [ + M.get_name (| globals, "compact" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Definition bytes_to_nibble_list : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "bytes_" ] |) in + let _ := Constant.str " + Converts a `Bytes` into to a sequence of nibbles (bytes with value < 16). + + Parameters + ---------- + bytes_: + The `Bytes` to convert. + + Returns + ------- + nibble_list : `Bytes` + The `Bytes` in nibble-list format. + " in + let _ := M.assign_local (| + "nibble_list" , + M.call (| + M.get_name (| globals, "bytearray" |), + make_list [ + BinOp.mult (| + Constant.int 2, + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_name (| globals, "bytes_" |) + ], + make_dict [] + |) + |) + ], + make_dict [] + |) + |) in + let _ := + M.for_ (| + make_tuple [ M.get_name (| globals, "byte_index" |); M.get_name (| globals, "byte" |) ], + M.call (| + M.get_name (| globals, "enumerate" |), + make_list [ + M.get_name (| globals, "bytes_" |) + ], + make_dict [] + |), + ltac:(M.monadic ( + let _ := M.assign (| + M.get_subscript (| + M.get_name (| globals, "nibble_list" |), + BinOp.mult (| + M.get_name (| globals, "byte_index" |), + Constant.int 2 + |) + |), + BinOp.r_shift (| + BinOp.bit_and (| + M.get_name (| globals, "byte" |), + Constant.int 240 + |), + Constant.int 4 + |) + |) in + let _ := M.assign (| + M.get_subscript (| + M.get_name (| globals, "nibble_list" |), + BinOp.add (| + BinOp.mult (| + M.get_name (| globals, "byte_index" |), + Constant.int 2 + |), + Constant.int 1 + |) + |), + BinOp.bit_and (| + M.get_name (| globals, "byte" |), + Constant.int 15 + |) + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, "Bytes" |), + make_list [ + M.get_name (| globals, "nibble_list" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Definition _prepare_trie : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "trie"; "get_storage_root" ] |) in + let _ := Constant.str " + Prepares the trie for root calculation. Removes values that are empty, + hashes the keys (if `secured == True`) and encodes all the nodes. + + Parameters + ---------- + trie : + The `Trie` to prepare. + get_storage_root : + Function to get the storage root of an account. Needed to encode + `Account` objects. + + Returns + ------- + out : `Mapping[ethereum.base_types.Bytes, Node]` + Object with keys mapped to nibble-byte form. + " in +(* At stmt: unsupported node type: AnnAssign *) + let _ := + M.for_ (| + make_tuple [ M.get_name (| globals, "preimage" |); M.get_name (| globals, "value" |) ], + M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, "trie" |), "_data" |), "items" |), + make_list [], + make_dict [] + |), + ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, "isinstance" |), + make_list [ + M.get_name (| globals, "value" |); + M.get_name (| globals, "Account" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assert (| Compare.is_not (| + M.get_name (| globals, "get_storage_root" |), + Constant.None_ + |) |) in + let _ := M.assign_local (| + "address" , + M.call (| + M.get_name (| globals, "Address" |), + make_list [ + M.get_name (| globals, "preimage" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "encoded_value" , + M.call (| + M.get_name (| globals, "encode_node" |), + make_list [ + M.get_name (| globals, "value" |); + M.call (| + M.get_name (| globals, "get_storage_root" |), + make_list [ + M.get_name (| globals, "address" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "encoded_value" , + M.call (| + M.get_name (| globals, "encode_node" |), + make_list [ + M.get_name (| globals, "value" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + )) |) in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + Compare.not_eq (| + M.get_name (| globals, "encoded_value" |), + Constant.bytes "" + |); + M.get_name (| globals, "AssertionError" |) + ], + make_dict [] + |) in +(* At stmt: unsupported node type: AnnAssign *) + let _ := + (* if *) + M.if_then_else (| + M.get_field (| M.get_name (| globals, "trie" |), "secured" |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "key" , + M.call (| + M.get_name (| globals, "keccak256" |), + make_list [ + M.get_name (| globals, "preimage" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "key" , + M.get_name (| globals, "preimage" |) + |) in + M.pure Constant.None_ + )) |) in + let _ := M.assign (| + M.get_subscript (| + M.get_name (| globals, "mapped" |), + M.call (| + M.get_name (| globals, "bytes_to_nibble_list" |), + make_list [ + M.get_name (| globals, "key" |) + ], + make_dict [] + |) + |), + M.get_name (| globals, "encoded_value" |) + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := M.return_ (| + M.get_name (| globals, "mapped" |) + |) in + M.pure Constant.None_)). + +Definition root : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "trie"; "get_storage_root" ] |) in + let _ := Constant.str " + Computes the root of a modified merkle patricia trie (MPT). + + Parameters + ---------- + trie : + `Trie` to get the root of. + get_storage_root : + Function to get the storage root of an account. Needed to encode + `Account` objects. + + + Returns + ------- + root : `.fork_types.Root` + MPT root of the underlying key-value pairs. + " in + let _ := M.assign_local (| + "obj" , + M.call (| + M.get_name (| globals, "_prepare_trie" |), + make_list [ + M.get_name (| globals, "trie" |); + M.get_name (| globals, "get_storage_root" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "root_node" , + M.call (| + M.get_name (| globals, "encode_internal_node" |), + make_list [ + M.call (| + M.get_name (| globals, "patricialize" |), + make_list [ + M.get_name (| globals, "obj" |); + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.lt (| + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.call (| + M.get_field (| M.get_name (| globals, "rlp" |), "encode" |), + make_list [ + M.get_name (| globals, "root_node" |) + ], + make_dict [] + |) + ], + make_dict [] + |), + Constant.int 32 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + M.call (| + M.get_name (| globals, "keccak256" |), + make_list [ + M.call (| + M.get_field (| M.get_name (| globals, "rlp" |), "encode" |), + make_list [ + M.get_name (| globals, "root_node" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assert (| M.call (| + M.get_name (| globals, "isinstance" |), + make_list [ + M.get_name (| globals, "root_node" |); + M.get_name (| globals, "Bytes" |) + ], + make_dict [] + |) |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, "Root" |), + make_list [ + M.get_name (| globals, "root_node" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_)). + +Definition patricialize : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "obj"; "level" ] |) in + let _ := Constant.str " + Structural composition function. + + Used to recursively patricialize and merkleize a dictionary. Includes + memoization of the tree structure and hashes. + + Parameters + ---------- + obj : + Underlying trie key-value pairs, with keys in nibble-list format. + level : + Current trie level. + + Returns + ------- + node : `ethereum.base_types.Bytes` + Root node of `obj`. + " in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_name (| globals, "obj" |) + ], + make_dict [] + |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + Constant.None_ + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "arbitrary_key" , + M.call (| + M.get_name (| globals, "next" |), + make_list [ + M.call (| + M.get_name (| globals, "iter" |), + make_list [ + M.get_name (| globals, "obj" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_name (| globals, "obj" |) + ], + make_dict [] + |), + Constant.int 1 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "leaf" , + M.call (| + M.get_name (| globals, "LeafNode" |), + make_list [ + M.slice (| + M.get_name (| globals, "arbitrary_key" |), + M.get_name (| globals, "level" |), + Constant.None_, + Constant.None_ + |); + M.get_subscript (| + M.get_name (| globals, "obj" |), + M.get_name (| globals, "arbitrary_key" |) + |) + ], + make_dict [] + |) + |) in + let _ := M.return_ (| + M.get_name (| globals, "leaf" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "substring" , + M.slice (| + M.get_name (| globals, "arbitrary_key" |), + M.get_name (| globals, "level" |), + Constant.None_, + Constant.None_ + |) + |) in + let _ := M.assign_local (| + "prefix_length" , + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_name (| globals, "substring" |) + ], + make_dict [] + |) + |) in + let _ := + M.for_ (| + M.get_name (| globals, "key" |), + M.get_name (| globals, "obj" |), + ltac:(M.monadic ( + let _ := M.assign_local (| + "prefix_length" , + M.call (| + M.get_name (| globals, "min" |), + make_list [ + M.get_name (| globals, "prefix_length" |); + M.call (| + M.get_name (| globals, "common_prefix_length" |), + make_list [ + M.get_name (| globals, "substring" |); + M.slice (| + M.get_name (| globals, "key" |), + M.get_name (| globals, "level" |), + Constant.None_, + Constant.None_ + |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, "prefix_length" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.break (| |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.gt (| + M.get_name (| globals, "prefix_length" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "prefix" , + M.slice (| + M.get_name (| globals, "arbitrary_key" |), + M.get_name (| globals, "level" |), + BinOp.add (| + M.get_name (| globals, "level" |), + M.get_name (| globals, "prefix_length" |) + |), + Constant.None_ + |) + |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, "ExtensionNode" |), + make_list [ + M.get_name (| globals, "prefix" |); + M.call (| + M.get_name (| globals, "encode_internal_node" |), + make_list [ + M.call (| + M.get_name (| globals, "patricialize" |), + make_list [ + M.get_name (| globals, "obj" |); + BinOp.add (| + M.get_name (| globals, "level" |), + M.get_name (| globals, "prefix_length" |) + |) + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in +(* At stmt: unsupported node type: AnnAssign *) + let _ := + M.for_ (| + M.get_name (| globals, "_" |), + M.call (| + M.get_name (| globals, "range" |), + make_list [ + Constant.int 16 + ], + make_dict [] + |), + ltac:(M.monadic ( + let _ := M.call (| + M.get_field (| M.get_name (| globals, "branches" |), "append" |), + make_list [ + Constant.str "(* At expr: unsupported node type: Dict *)" + ], + make_dict [] + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := M.assign_local (| + "value" , + Constant.bytes "" + |) in + let _ := + M.for_ (| + M.get_name (| globals, "key" |), + M.get_name (| globals, "obj" |), + ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_name (| globals, "key" |) + ], + make_dict [] + |), + M.get_name (| globals, "level" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, "isinstance" |), + make_list [ + M.get_subscript (| + M.get_name (| globals, "obj" |), + M.get_name (| globals, "key" |) + |); + make_tuple [ M.get_name (| globals, "Account" |); M.get_name (| globals, "Receipt" |); M.get_name (| globals, "Uint" |) ] + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, "AssertionError" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "value" , + M.get_subscript (| + M.get_name (| globals, "obj" |), + M.get_name (| globals, "key" |) + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign (| + M.get_subscript (| + M.get_subscript (| + M.get_name (| globals, "branches" |), + M.get_subscript (| + M.get_name (| globals, "key" |), + M.get_name (| globals, "level" |) + |) + |), + M.get_name (| globals, "key" |) + |), + M.get_subscript (| + M.get_name (| globals, "obj" |), + M.get_name (| globals, "key" |) + |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, "BranchNode" |), + make_list [ + Constant.str "(* At expr: unsupported node type: ListComp *)"; + M.get_name (| globals, "value" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). diff --git a/CoqOfPython/ethereum/paris/utils/__init__.v b/CoqOfPython/ethereum/paris/utils/__init__.v new file mode 100644 index 0000000..afb5c35 --- /dev/null +++ b/CoqOfPython/ethereum/paris/utils/__init__.v @@ -0,0 +1,8 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.paris.utils.__init__". + +Definition expr_1 : Value.t := + Constant.str " +Utility functions unique to this particular fork. +". diff --git a/CoqOfPython/ethereum/paris/utils/address.v b/CoqOfPython/ethereum/paris/utils/address.v new file mode 100644 index 0000000..bd0c332 --- /dev/null +++ b/CoqOfPython/ethereum/paris/utils/address.v @@ -0,0 +1,227 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.paris.utils.address". + +Definition expr_1 : Value.t := + Constant.str " +Hardfork Utility Functions For Addresses +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Address specific functions used in this paris version of +specification. +". + +Axiom typing_imports_Union : + IsImported globals "typing" "Union". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_Bytes32 : + IsImported globals "ethereum.base_types" "Bytes32". +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". + +Axiom ethereum_crypto_hash_imports_keccak256 : + IsImported globals "ethereum.crypto.hash" "keccak256". + +Axiom ethereum_utils_byte_imports_left_pad_zero_bytes : + IsImported globals "ethereum.utils.byte" "left_pad_zero_bytes". + +Axiom ethereum_imports_rlp : + IsImported globals "ethereum" "rlp". + +Axiom ethereum_paris_fork_types_imports_Address : + IsImported globals "ethereum.paris.fork_types" "Address". + +Definition to_address : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "data" ] |) in + let _ := Constant.str " + Convert a Uint or U256 value to a valid address (20 bytes). + + Parameters + ---------- + data : + The string to be converted to bytes. + + Returns + ------- + address : `Address` + The obtained address. + " in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, "Address" |), + make_list [ + M.slice (| + M.call (| + M.get_field (| M.get_name (| globals, "data" |), "to_be_bytes32" |), + make_list [], + make_dict [] + |), + UnOp.sub (| Constant.int 20 |), + Constant.None_, + Constant.None_ + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Definition compute_contract_address : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "address"; "nonce" ] |) in + let _ := Constant.str " + Computes address of the new account that needs to be created. + + Parameters + ---------- + address : + The address of the account that wants to create the new account. + nonce : + The transaction count of the account that wants to create the new + account. + + Returns + ------- + address: `Address` + The computed address of the new account. + " in + let _ := M.assign_local (| + "computed_address" , + M.call (| + M.get_name (| globals, "keccak256" |), + make_list [ + M.call (| + M.get_field (| M.get_name (| globals, "rlp" |), "encode" |), + make_list [ + make_list [ + M.get_name (| globals, "address" |); + M.get_name (| globals, "nonce" |) + ] + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "canonical_address" , + M.slice (| + M.get_name (| globals, "computed_address" |), + UnOp.sub (| Constant.int 20 |), + Constant.None_, + Constant.None_ + |) + |) in + let _ := M.assign_local (| + "padded_address" , + M.call (| + M.get_name (| globals, "left_pad_zero_bytes" |), + make_list [ + M.get_name (| globals, "canonical_address" |); + Constant.int 20 + ], + make_dict [] + |) + |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, "Address" |), + make_list [ + M.get_name (| globals, "padded_address" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Definition compute_create2_contract_address : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "address"; "salt"; "call_data" ] |) in + let _ := Constant.str " + Computes address of the new account that needs to be created, which is + based on the sender address, salt and the call data as well. + + Parameters + ---------- + address : + The address of the account that wants to create the new account. + salt : + Address generation salt. + call_data : + The code of the new account which is to be created. + + Returns + ------- + address: `ethereum.paris.fork_types.Address` + The computed address of the new account. + " in + let _ := M.assign_local (| + "preimage" , + BinOp.add (| + BinOp.add (| + BinOp.add (| + Constant.bytes "ff", + M.get_name (| globals, "address" |) + |), + M.get_name (| globals, "salt" |) + |), + M.call (| + M.get_name (| globals, "keccak256" |), + make_list [ + M.get_name (| globals, "call_data" |) + ], + make_dict [] + |) + |) + |) in + let _ := M.assign_local (| + "computed_address" , + M.call (| + M.get_name (| globals, "keccak256" |), + make_list [ + M.get_name (| globals, "preimage" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "canonical_address" , + M.slice (| + M.get_name (| globals, "computed_address" |), + UnOp.sub (| Constant.int 20 |), + Constant.None_, + Constant.None_ + |) + |) in + let _ := M.assign_local (| + "padded_address" , + M.call (| + M.get_name (| globals, "left_pad_zero_bytes" |), + make_list [ + M.get_name (| globals, "canonical_address" |); + Constant.int 20 + ], + make_dict [] + |) + |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, "Address" |), + make_list [ + M.get_name (| globals, "padded_address" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). diff --git a/CoqOfPython/ethereum/paris/utils/hexadecimal.v b/CoqOfPython/ethereum/paris/utils/hexadecimal.v new file mode 100644 index 0000000..62e084d --- /dev/null +++ b/CoqOfPython/ethereum/paris/utils/hexadecimal.v @@ -0,0 +1,153 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.paris.utils.hexadecimal". + +Definition expr_1 : Value.t := + Constant.str " +Utility Functions For Hexadecimal Strings +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Hexadecimal utility functions used in this specification, specific to +Paris types. +". + +Axiom ethereum_utils_hexadecimal_imports_remove_hex_prefix : + IsImported globals "ethereum.utils.hexadecimal" "remove_hex_prefix". + +Axiom ethereum_paris_fork_types_imports_Address : + IsImported globals "ethereum.paris.fork_types" "Address". +Axiom ethereum_paris_fork_types_imports_Bloom : + IsImported globals "ethereum.paris.fork_types" "Bloom". +Axiom ethereum_paris_fork_types_imports_Root : + IsImported globals "ethereum.paris.fork_types" "Root". + +Definition hex_to_root : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "hex_string" ] |) in + let _ := Constant.str " + Convert hex string to trie root. + + Parameters + ---------- + hex_string : + The hexadecimal string to be converted to trie root. + + Returns + ------- + root : `Root` + Trie root obtained from the given hexadecimal string. + " in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, "Root" |), + make_list [ + M.call (| + M.get_field (| M.get_name (| globals, "bytes" |), "fromhex" |), + make_list [ + M.call (| + M.get_name (| globals, "remove_hex_prefix" |), + make_list [ + M.get_name (| globals, "hex_string" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Definition hex_to_bloom : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "hex_string" ] |) in + let _ := Constant.str " + Convert hex string to bloom. + + Parameters + ---------- + hex_string : + The hexadecimal string to be converted to bloom. + + Returns + ------- + bloom : `Bloom` + Bloom obtained from the given hexadecimal string. + " in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, "Bloom" |), + make_list [ + M.call (| + M.get_field (| M.get_name (| globals, "bytes" |), "fromhex" |), + make_list [ + M.call (| + M.get_name (| globals, "remove_hex_prefix" |), + make_list [ + M.get_name (| globals, "hex_string" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Definition hex_to_address : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "hex_string" ] |) in + let _ := Constant.str " + Convert hex string to Address (20 bytes). + + Parameters + ---------- + hex_string : + The hexadecimal string to be converted to Address. + + Returns + ------- + address : `Address` + The address obtained from the given hexadecimal string. + " in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, "Address" |), + make_list [ + M.call (| + M.get_field (| M.get_name (| globals, "bytes" |), "fromhex" |), + make_list [ + M.call (| + M.get_field (| M.call (| + M.get_name (| globals, "remove_hex_prefix" |), + make_list [ + M.get_name (| globals, "hex_string" |) + ], + make_dict [] + |), "rjust" |), + make_list [ + Constant.int 40; + Constant.str "0" + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). diff --git a/CoqOfPython/ethereum/paris/utils/message.v b/CoqOfPython/ethereum/paris/utils/message.v new file mode 100644 index 0000000..9e2da6d --- /dev/null +++ b/CoqOfPython/ethereum/paris/utils/message.v @@ -0,0 +1,266 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.paris.utils.message". + +Definition expr_1 : Value.t := + Constant.str " +Hardfork Utility Functions For The Message Data-structure +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Message specific functions used in this paris version of +specification. +". + +Axiom typing_imports_FrozenSet : + IsImported globals "typing" "FrozenSet". +Axiom typing_imports_Optional : + IsImported globals "typing" "Optional". +Axiom typing_imports_Tuple : + IsImported globals "typing" "Tuple". +Axiom typing_imports_Union : + IsImported globals "typing" "Union". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_Bytes : + IsImported globals "ethereum.base_types" "Bytes". +Axiom ethereum_base_types_imports_Bytes0 : + IsImported globals "ethereum.base_types" "Bytes0". +Axiom ethereum_base_types_imports_Bytes32 : + IsImported globals "ethereum.base_types" "Bytes32". +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". + +Axiom ethereum_paris_fork_types_imports_Address : + IsImported globals "ethereum.paris.fork_types" "Address". + +Axiom ethereum_paris_state_imports_get_account : + IsImported globals "ethereum.paris.state" "get_account". + +Axiom ethereum_paris_vm_imports_Environment : + IsImported globals "ethereum.paris.vm" "Environment". +Axiom ethereum_paris_vm_imports_Message : + IsImported globals "ethereum.paris.vm" "Message". + +Axiom ethereum_paris_vm_precompiled_contracts_mapping_imports_PRE_COMPILED_CONTRACTS : + IsImported globals "ethereum.paris.vm.precompiled_contracts.mapping" "PRE_COMPILED_CONTRACTS". + +Axiom ethereum_paris_utils_address_imports_compute_contract_address : + IsImported globals "ethereum.paris.utils.address" "compute_contract_address". + +Definition prepare_message : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "caller"; "target"; "value"; "data"; "gas"; "env"; "code_address"; "should_transfer_value"; "is_static"; "preaccessed_addresses"; "preaccessed_storage_keys" ] |) in + let _ := Constant.str " + Execute a transaction against the provided environment. + + Parameters + ---------- + caller : + Address which initiated the transaction + target : + Address whose code will be executed + value : + Value to be transferred. + data : + Array of bytes provided to the code in `target`. + gas : + Gas provided for the code in `target`. + env : + Environment for the Ethereum Virtual Machine. + code_address : + This is usually same as the `target` address except when an alternative + accounts code needs to be executed. + eg. `CALLCODE` calling a precompile. + should_transfer_value : + if True ETH should be transferred while executing a message call. + is_static: + if True then it prevents all state-changing operations from being + executed. + preaccessed_addresses: + Addresses that should be marked as accessed prior to the message call + preaccessed_storage_keys: + Storage keys that should be marked as accessed prior to the message + call + + Returns + ------- + message: `ethereum.paris.vm.Message` + Items containing contract creation or message call specific data. + " in + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, "isinstance" |), + make_list [ + M.get_name (| globals, "target" |); + M.get_name (| globals, "Bytes0" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "current_target" , + M.call (| + M.get_name (| globals, "compute_contract_address" |), + make_list [ + M.get_name (| globals, "caller" |); + BinOp.sub (| + M.get_field (| M.call (| + M.get_name (| globals, "get_account" |), + make_list [ + M.get_field (| M.get_name (| globals, "env" |), "state" |); + M.get_name (| globals, "caller" |) + ], + make_dict [] + |), "nonce" |), + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 1 + ], + make_dict [] + |) + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "msg_data" , + M.call (| + M.get_name (| globals, "Bytes" |), + make_list [ + Constant.bytes "" + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "code" , + M.get_name (| globals, "data" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, "isinstance" |), + make_list [ + M.get_name (| globals, "target" |); + M.get_name (| globals, "Address" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "current_target" , + M.get_name (| globals, "target" |) + |) in + let _ := M.assign_local (| + "msg_data" , + M.get_name (| globals, "data" |) + |) in + let _ := M.assign_local (| + "code" , + M.get_field (| M.call (| + M.get_name (| globals, "get_account" |), + make_list [ + M.get_field (| M.get_name (| globals, "env" |), "state" |); + M.get_name (| globals, "target" |) + ], + make_dict [] + |), "code" |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.is (| + M.get_name (| globals, "code_address" |), + Constant.None_ + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "code_address" , + M.get_name (| globals, "target" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.raise (| Some (M.call (| + M.get_name (| globals, "AssertionError" |), + make_list [ + Constant.str "Target must be address or empty bytes" + ], + make_dict [] + |)) |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "accessed_addresses" , + M.call (| + M.get_name (| globals, "set" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_field (| M.get_name (| globals, "accessed_addresses" |), "add" |), + make_list [ + M.get_name (| globals, "current_target" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_field (| M.get_name (| globals, "accessed_addresses" |), "add" |), + make_list [ + M.get_name (| globals, "caller" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_field (| M.get_name (| globals, "accessed_addresses" |), "update" |), + make_list [ + M.call (| + M.get_field (| M.get_name (| globals, "PRE_COMPILED_CONTRACTS" |), "keys" |), + make_list [], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_field (| M.get_name (| globals, "accessed_addresses" |), "update" |), + make_list [ + M.get_name (| globals, "preaccessed_addresses" |) + ], + make_dict [] + |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, "Message" |), + make_list [], + make_dict [] + |) + |) in + M.pure Constant.None_)). diff --git a/CoqOfPython/ethereum/paris/vm/__init__.v b/CoqOfPython/ethereum/paris/vm/__init__.v new file mode 100644 index 0000000..472ccd5 --- /dev/null +++ b/CoqOfPython/ethereum/paris/vm/__init__.v @@ -0,0 +1,260 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.paris.vm.__init__". + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +The abstract computer which runs the code stored in an +`.fork_types.Account`. +". + +Axiom dataclasses_imports_dataclass : + IsImported globals "dataclasses" "dataclass". + +Axiom typing_imports_List : + IsImported globals "typing" "List". +Axiom typing_imports_Optional : + IsImported globals "typing" "Optional". +Axiom typing_imports_Set : + IsImported globals "typing" "Set". +Axiom typing_imports_Tuple : + IsImported globals "typing" "Tuple". +Axiom typing_imports_Union : + IsImported globals "typing" "Union". + +Axiom ethereum_base_types_imports_U64 : + IsImported globals "ethereum.base_types" "U64". +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_Bytes : + IsImported globals "ethereum.base_types" "Bytes". +Axiom ethereum_base_types_imports_Bytes0 : + IsImported globals "ethereum.base_types" "Bytes0". +Axiom ethereum_base_types_imports_Bytes32 : + IsImported globals "ethereum.base_types" "Bytes32". +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". + +Axiom ethereum_crypto_hash_imports_Hash32 : + IsImported globals "ethereum.crypto.hash" "Hash32". + +Axiom ethereum_paris_blocks_imports_Log : + IsImported globals "ethereum.paris.blocks" "Log". + +Axiom ethereum_paris_fork_types_imports_Address : + IsImported globals "ethereum.paris.fork_types" "Address". + +Axiom ethereum_paris_state_imports_State : + IsImported globals "ethereum.paris.state" "State". +Axiom ethereum_paris_state_imports_account_exists_and_is_empty : + IsImported globals "ethereum.paris.state" "account_exists_and_is_empty". + +Axiom ethereum_paris_vm_precompiled_contracts_imports_RIPEMD160_ADDRESS : + IsImported globals "ethereum.paris.vm.precompiled_contracts" "RIPEMD160_ADDRESS". + +Definition __all__ : Value.t := M.run ltac:(M.monadic ( + make_tuple [ Constant.str "Environment"; Constant.str "Evm"; Constant.str "Message" ] +)). + +Definition Environment : Value.t := + builtins.make_klass + [] + [ + + ] + [ + + ]. + +Definition Message : Value.t := + builtins.make_klass + [] + [ + + ] + [ + + ]. + +Definition Evm : Value.t := + builtins.make_klass + [] + [ + + ] + [ + + ]. + +Definition incorporate_child_on_success : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm"; "child_evm" ] |) in + let _ := Constant.str " + Incorporate the state of a successful `child_evm` into the parent `evm`. + + Parameters + ---------- + evm : + The parent `EVM`. + child_evm : + The child evm to incorporate. + " in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "gas_left" |), + M.get_field (| M.get_name (| globals, "child_evm" |), "gas_left" |) + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "logs" |), + M.get_field (| M.get_name (| globals, "child_evm" |), "logs" |) + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "refund_counter" |), + M.get_field (| M.get_name (| globals, "child_evm" |), "refund_counter" |) + |) in + let _ := M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "accounts_to_delete" |), "update" |), + make_list [ + M.get_field (| M.get_name (| globals, "child_evm" |), "accounts_to_delete" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "touched_accounts" |), "update" |), + make_list [ + M.get_field (| M.get_name (| globals, "child_evm" |), "touched_accounts" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, "account_exists_and_is_empty" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "env" |), "state" |); + M.get_field (| M.get_field (| M.get_name (| globals, "child_evm" |), "message" |), "current_target" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "touched_accounts" |), "add" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "child_evm" |), "message" |), "current_target" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "accessed_addresses" |), "update" |), + make_list [ + M.get_field (| M.get_name (| globals, "child_evm" |), "accessed_addresses" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "accessed_storage_keys" |), "update" |), + make_list [ + M.get_field (| M.get_name (| globals, "child_evm" |), "accessed_storage_keys" |) + ], + make_dict [] + |) in + M.pure Constant.None_)). + +Definition incorporate_child_on_error : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm"; "child_evm" ] |) in + let _ := Constant.str " + Incorporate the state of an unsuccessful `child_evm` into the parent `evm`. + + Parameters + ---------- + evm : + The parent `EVM`. + child_evm : + The child evm to incorporate. + " in + let _ := + (* if *) + M.if_then_else (| + Compare.in_ (| + M.get_name (| globals, "RIPEMD160_ADDRESS" |), + M.get_field (| M.get_name (| globals, "child_evm" |), "touched_accounts" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "touched_accounts" |), "add" |), + make_list [ + M.get_name (| globals, "RIPEMD160_ADDRESS" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_field (| M.get_field (| M.get_name (| globals, "child_evm" |), "message" |), "current_target" |), + M.get_name (| globals, "RIPEMD160_ADDRESS" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, "account_exists_and_is_empty" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "env" |), "state" |); + M.get_field (| M.get_field (| M.get_name (| globals, "child_evm" |), "message" |), "current_target" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "touched_accounts" |), "add" |), + make_list [ + M.get_name (| globals, "RIPEMD160_ADDRESS" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "gas_left" |), + M.get_field (| M.get_name (| globals, "child_evm" |), "gas_left" |) + |) in + M.pure Constant.None_)). diff --git a/CoqOfPython/ethereum/paris/vm/exceptions.v b/CoqOfPython/ethereum/paris/vm/exceptions.v new file mode 100644 index 0000000..95b6cd9 --- /dev/null +++ b/CoqOfPython/ethereum/paris/vm/exceptions.v @@ -0,0 +1,171 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.paris.vm.exceptions". + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) Exceptions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Exceptions which cause the EVM to halt exceptionally. +". + +Axiom ethereum_exceptions_imports_EthereumException : + IsImported globals "ethereum.exceptions" "EthereumException". + +Definition ExceptionalHalt : Value.t := + builtins.make_klass + [(globals, "EthereumException")] + [ + + ] + [ + + ]. + +Definition Revert : Value.t := + builtins.make_klass + [(globals, "EthereumException")] + [ + + ] + [ + + ]. + +Definition StackUnderflowError : Value.t := + builtins.make_klass + [(globals, "ExceptionalHalt")] + [ + + ] + [ + + ]. + +Definition StackOverflowError : Value.t := + builtins.make_klass + [(globals, "ExceptionalHalt")] + [ + + ] + [ + + ]. + +Definition OutOfGasError : Value.t := + builtins.make_klass + [(globals, "ExceptionalHalt")] + [ + + ] + [ + + ]. + +Definition InvalidOpcode : Value.t := + builtins.make_klass + [(globals, "ExceptionalHalt")] + [ + + ] + [ + ( + "__init__", + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "self"; "code" ] |) in + let _ := M.call (| + M.get_field (| M.call (| + M.get_name (| globals, "super" |), + make_list [], + make_dict [] + |), "__init__" |), + make_list [ + M.get_name (| globals, "code" |) + ], + make_dict [] + |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, "self" |), "code" |), + M.get_name (| globals, "code" |) + |) in + M.pure Constant.None_)) + ) + ]. + +Definition InvalidJumpDestError : Value.t := + builtins.make_klass + [(globals, "ExceptionalHalt")] + [ + + ] + [ + + ]. + +Definition StackDepthLimitError : Value.t := + builtins.make_klass + [(globals, "ExceptionalHalt")] + [ + + ] + [ + + ]. + +Definition WriteInStaticContext : Value.t := + builtins.make_klass + [(globals, "ExceptionalHalt")] + [ + + ] + [ + + ]. + +Definition OutOfBoundsRead : Value.t := + builtins.make_klass + [(globals, "ExceptionalHalt")] + [ + + ] + [ + + ]. + +Definition InvalidParameter : Value.t := + builtins.make_klass + [(globals, "ExceptionalHalt")] + [ + + ] + [ + + ]. + +Definition InvalidContractPrefix : Value.t := + builtins.make_klass + [(globals, "ExceptionalHalt")] + [ + + ] + [ + + ]. + +Definition AddressCollision : Value.t := + builtins.make_klass + [(globals, "ExceptionalHalt")] + [ + + ] + [ + + ]. diff --git a/CoqOfPython/ethereum/paris/vm/gas.v b/CoqOfPython/ethereum/paris/vm/gas.v new file mode 100644 index 0000000..7b37d78 --- /dev/null +++ b/CoqOfPython/ethereum/paris/vm/gas.v @@ -0,0 +1,912 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.paris.vm.gas". + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) Gas +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +EVM gas constants and calculators. +". + +Axiom dataclasses_imports_dataclass : + IsImported globals "dataclasses" "dataclass". + +Axiom typing_imports_List : + IsImported globals "typing" "List". +Axiom typing_imports_Tuple : + IsImported globals "typing" "Tuple". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". + +Axiom ethereum_trace_imports_GasAndRefund : + IsImported globals "ethereum.trace" "GasAndRefund". +Axiom ethereum_trace_imports_evm_trace : + IsImported globals "ethereum.trace" "evm_trace". + +Axiom ethereum_utils_numeric_imports_ceil32 : + IsImported globals "ethereum.utils.numeric" "ceil32". + +Axiom ethereum_paris_vm_imports_Evm : + IsImported globals "ethereum.paris.vm" "Evm". + +Axiom ethereum_paris_vm_exceptions_imports_OutOfGasError : + IsImported globals "ethereum.paris.vm.exceptions" "OutOfGasError". + +Definition GAS_JUMPDEST : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 1 + ], + make_dict [] + |) +)). + +Definition GAS_BASE : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 2 + ], + make_dict [] + |) +)). + +Definition GAS_VERY_LOW : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 3 + ], + make_dict [] + |) +)). + +Definition GAS_STORAGE_SET : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 20000 + ], + make_dict [] + |) +)). + +Definition GAS_STORAGE_UPDATE : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 5000 + ], + make_dict [] + |) +)). + +Definition GAS_STORAGE_CLEAR_REFUND : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 4800 + ], + make_dict [] + |) +)). + +Definition GAS_LOW : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 5 + ], + make_dict [] + |) +)). + +Definition GAS_MID : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 8 + ], + make_dict [] + |) +)). + +Definition GAS_HIGH : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 10 + ], + make_dict [] + |) +)). + +Definition GAS_EXPONENTIATION : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 10 + ], + make_dict [] + |) +)). + +Definition GAS_EXPONENTIATION_PER_BYTE : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 50 + ], + make_dict [] + |) +)). + +Definition GAS_MEMORY : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 3 + ], + make_dict [] + |) +)). + +Definition GAS_KECCAK256 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 30 + ], + make_dict [] + |) +)). + +Definition GAS_KECCAK256_WORD : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 6 + ], + make_dict [] + |) +)). + +Definition GAS_COPY : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 3 + ], + make_dict [] + |) +)). + +Definition GAS_BLOCK_HASH : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 20 + ], + make_dict [] + |) +)). + +Definition GAS_LOG : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 375 + ], + make_dict [] + |) +)). + +Definition GAS_LOG_DATA : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 8 + ], + make_dict [] + |) +)). + +Definition GAS_LOG_TOPIC : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 375 + ], + make_dict [] + |) +)). + +Definition GAS_CREATE : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 32000 + ], + make_dict [] + |) +)). + +Definition GAS_CODE_DEPOSIT : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 200 + ], + make_dict [] + |) +)). + +Definition GAS_ZERO : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) +)). + +Definition GAS_NEW_ACCOUNT : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 25000 + ], + make_dict [] + |) +)). + +Definition GAS_CALL_VALUE : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 9000 + ], + make_dict [] + |) +)). + +Definition GAS_CALL_STIPEND : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 2300 + ], + make_dict [] + |) +)). + +Definition GAS_SELF_DESTRUCT : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 5000 + ], + make_dict [] + |) +)). + +Definition GAS_SELF_DESTRUCT_NEW_ACCOUNT : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 25000 + ], + make_dict [] + |) +)). + +Definition GAS_ECRECOVER : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 3000 + ], + make_dict [] + |) +)). + +Definition GAS_SHA256 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 60 + ], + make_dict [] + |) +)). + +Definition GAS_SHA256_WORD : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 12 + ], + make_dict [] + |) +)). + +Definition GAS_RIPEMD160 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 600 + ], + make_dict [] + |) +)). + +Definition GAS_RIPEMD160_WORD : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 120 + ], + make_dict [] + |) +)). + +Definition GAS_IDENTITY : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 15 + ], + make_dict [] + |) +)). + +Definition GAS_IDENTITY_WORD : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 3 + ], + make_dict [] + |) +)). + +Definition GAS_RETURN_DATA_COPY : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 3 + ], + make_dict [] + |) +)). + +Definition GAS_FAST_STEP : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 5 + ], + make_dict [] + |) +)). + +Definition GAS_BLAKE2_PER_ROUND : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 1 + ], + make_dict [] + |) +)). + +Definition GAS_COLD_SLOAD : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 2100 + ], + make_dict [] + |) +)). + +Definition GAS_COLD_ACCOUNT_ACCESS : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 2600 + ], + make_dict [] + |) +)). + +Definition GAS_WARM_ACCESS : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 100 + ], + make_dict [] + |) +)). + +Definition ExtendMemory : Value.t := + builtins.make_klass + [] + [ + + ] + [ + + ]. + +Definition MessageCallGas : Value.t := + builtins.make_klass + [] + [ + + ] + [ + + ]. + +Definition charge_gas : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm"; "amount" ] |) in + let _ := Constant.str " + Subtracts `amount` from `evm.gas_left`. + + Parameters + ---------- + evm : + The current EVM. + amount : + The amount of gas the current operation requires. + + " in + let _ := M.call (| + M.get_name (| globals, "evm_trace" |), + make_list [ + M.get_name (| globals, "evm" |); + M.call (| + M.get_name (| globals, "GasAndRefund" |), + make_list [ + M.get_name (| globals, "amount" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.lt (| + M.get_field (| M.get_name (| globals, "evm" |), "gas_left" |), + M.get_name (| globals, "amount" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, "OutOfGasError" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_op (| + BinOp.sub, + M.get_field (| M.get_name (| globals, "evm" |), "gas_left" |), + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + M.get_name (| globals, "amount" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_)). + +Definition calculate_memory_gas_cost : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "size_in_bytes" ] |) in + let _ := Constant.str " + Calculates the gas cost for allocating memory + to the smallest multiple of 32 bytes, + such that the allocated size is at least as big as the given size. + + Parameters + ---------- + size_in_bytes : + The size of the data in bytes. + + Returns + ------- + total_gas_cost : `ethereum.base_types.Uint` + The gas cost for storing data in memory. + " in + let _ := M.assign_local (| + "size_in_words" , + BinOp.floor_div (| + M.call (| + M.get_name (| globals, "ceil32" |), + make_list [ + M.get_name (| globals, "size_in_bytes" |) + ], + make_dict [] + |), + Constant.int 32 + |) + |) in + let _ := M.assign_local (| + "linear_cost" , + BinOp.mult (| + M.get_name (| globals, "size_in_words" |), + M.get_name (| globals, "GAS_MEMORY" |) + |) + |) in + let _ := M.assign_local (| + "quadratic_cost" , + BinOp.floor_div (| + BinOp.pow (| + M.get_name (| globals, "size_in_words" |), + Constant.int 2 + |), + Constant.int 512 + |) + |) in + let _ := M.assign_local (| + "total_gas_cost" , + BinOp.add (| + M.get_name (| globals, "linear_cost" |), + M.get_name (| globals, "quadratic_cost" |) + |) + |) in +(* At stmt: unsupported node type: Try *) + M.pure Constant.None_)). + +Definition calculate_gas_extend_memory : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "memory"; "extensions" ] |) in + let _ := Constant.str " + Calculates the gas amount to extend memory + + Parameters + ---------- + memory : + Memory contents of the EVM. + extensions: + List of extensions to be made to the memory. + Consists of a tuple of start position and size. + + Returns + ------- + extend_memory: `ExtendMemory` + " in + let _ := M.assign_local (| + "size_to_extend" , + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "to_be_paid" , + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "current_size" , + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_name (| globals, "memory" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := + M.for_ (| + make_tuple [ M.get_name (| globals, "start_position" |); M.get_name (| globals, "size" |) ], + M.get_name (| globals, "extensions" |), + ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, "size" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.continue (| |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "before_size" , + M.call (| + M.get_name (| globals, "ceil32" |), + make_list [ + M.get_name (| globals, "current_size" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "after_size" , + M.call (| + M.get_name (| globals, "ceil32" |), + make_list [ + BinOp.add (| + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.get_name (| globals, "start_position" |) + ], + make_dict [] + |), + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.get_name (| globals, "size" |) + ], + make_dict [] + |) + |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.lt_e (| + M.get_name (| globals, "after_size" |), + M.get_name (| globals, "before_size" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.continue (| |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_op_local (| + BinOp.add, + "size_to_extend", + BinOp.sub (| + M.get_name (| globals, "after_size" |), + M.get_name (| globals, "before_size" |) + |) + |) in + let _ := M.assign_local (| + "already_paid" , + M.call (| + M.get_name (| globals, "calculate_memory_gas_cost" |), + make_list [ + M.get_name (| globals, "before_size" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "total_cost" , + M.call (| + M.get_name (| globals, "calculate_memory_gas_cost" |), + make_list [ + M.get_name (| globals, "after_size" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_op_local (| + BinOp.add, + "to_be_paid", + BinOp.sub (| + M.get_name (| globals, "total_cost" |), + M.get_name (| globals, "already_paid" |) + |) + |) in + let _ := M.assign_local (| + "current_size" , + M.get_name (| globals, "after_size" |) + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, "ExtendMemory" |), + make_list [ + M.get_name (| globals, "to_be_paid" |); + M.get_name (| globals, "size_to_extend" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Definition calculate_message_call_gas : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "value"; "gas"; "gas_left"; "memory_cost"; "extra_gas"; "call_stipend" ] |) in + let _ := Constant.str " + Calculates the MessageCallGas (cost and stipend) for + executing call Opcodes. + + Parameters + ---------- + value: + The amount of `ETH` that needs to be transferred. + gas : + The amount of gas provided to the message-call. + gas_left : + The amount of gas left in the current frame. + memory_cost : + The amount needed to extend the memory in the current frame. + extra_gas : + The amount of gas needed for transferring value + creating a new + account inside a message call. + call_stipend : + The amount of stipend provided to a message call to execute code while + transferring value(ETH). + + Returns + ------- + message_call_gas: `MessageCallGas` + " in + let _ := M.assign_local (| + "call_stipend" , + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, "value" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( +M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + (* else *) + )), ltac:(M.monadic ( +M.get_name (| globals, "call_stipend" |) + )) |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.lt (| + M.get_name (| globals, "gas_left" |), + BinOp.add (| + M.get_name (| globals, "extra_gas" |), + M.get_name (| globals, "memory_cost" |) + |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + M.call (| + M.get_name (| globals, "MessageCallGas" |), + make_list [ + BinOp.add (| + M.get_name (| globals, "gas" |), + M.get_name (| globals, "extra_gas" |) + |); + BinOp.add (| + M.get_name (| globals, "gas" |), + M.get_name (| globals, "call_stipend" |) + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "gas" , + M.call (| + M.get_name (| globals, "min" |), + make_list [ + M.get_name (| globals, "gas" |); + M.call (| + M.get_name (| globals, "max_message_call_gas" |), + make_list [ + BinOp.sub (| + BinOp.sub (| + M.get_name (| globals, "gas_left" |), + M.get_name (| globals, "memory_cost" |) + |), + M.get_name (| globals, "extra_gas" |) + |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, "MessageCallGas" |), + make_list [ + BinOp.add (| + M.get_name (| globals, "gas" |), + M.get_name (| globals, "extra_gas" |) + |); + BinOp.add (| + M.get_name (| globals, "gas" |), + M.get_name (| globals, "call_stipend" |) + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Definition max_message_call_gas : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "gas" ] |) in + let _ := Constant.str " + Calculates the maximum gas that is allowed for making a message call + + Parameters + ---------- + gas : + The amount of gas provided to the message-call. + + Returns + ------- + max_allowed_message_call_gas: `ethereum.base_types.Uint` + The maximum gas allowed for making the message-call. + " in + let _ := M.return_ (| + BinOp.sub (| + M.get_name (| globals, "gas" |), + BinOp.floor_div (| + M.get_name (| globals, "gas" |), + Constant.int 64 + |) + |) + |) in + M.pure Constant.None_)). diff --git a/CoqOfPython/ethereum/paris/vm/instructions/__init__.v b/CoqOfPython/ethereum/paris/vm/instructions/__init__.v new file mode 100644 index 0000000..8cfce01 --- /dev/null +++ b/CoqOfPython/ethereum/paris/vm/instructions/__init__.v @@ -0,0 +1,74 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.paris.vm.instructions.__init__". + +Definition expr_1 : Value.t := + Constant.str " +EVM Instruction Encoding (Opcodes) +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Machine readable representations of EVM instructions, and a mapping to their +implementations. +". + +(* At top_level_stmt: unsupported node type: Import *) + +Axiom typing_imports_Callable : + IsImported globals "typing" "Callable". +Axiom typing_imports_Dict : + IsImported globals "typing" "Dict". + +Axiom ethereum_paris_vm_instructions_imports_arithmetic : + IsImported globals "ethereum.paris.vm.instructions" "arithmetic". + +Axiom ethereum_paris_vm_instructions_imports_bitwise : + IsImported globals "ethereum.paris.vm.instructions" "bitwise". + +Axiom ethereum_paris_vm_instructions_imports_block : + IsImported globals "ethereum.paris.vm.instructions" "block". + +Axiom ethereum_paris_vm_instructions_imports_comparison : + IsImported globals "ethereum.paris.vm.instructions" "comparison". + +Axiom ethereum_paris_vm_instructions_imports_control_flow : + IsImported globals "ethereum.paris.vm.instructions" "control_flow". + +Axiom ethereum_paris_vm_instructions_imports_environment : + IsImported globals "ethereum.paris.vm.instructions" "environment". + +Axiom ethereum_paris_vm_instructions_imports_keccak : + IsImported globals "ethereum.paris.vm.instructions" "keccak". + +Axiom ethereum_paris_vm_instructions_imports_log : + IsImported globals "ethereum.paris.vm.instructions" "log". + +Axiom ethereum_paris_vm_instructions_imports_memory : + IsImported globals "ethereum.paris.vm.instructions" "memory". + +Axiom ethereum_paris_vm_instructions_imports_stack : + IsImported globals "ethereum.paris.vm.instructions" "stack". + +Axiom ethereum_paris_vm_instructions_imports_storage : + IsImported globals "ethereum.paris.vm.instructions" "storage". + +Axiom ethereum_paris_vm_instructions_imports_system : + IsImported globals "ethereum.paris.vm.instructions" "system". + +Definition Ops : Value.t := + builtins.make_klass + [(* At base: unsupported node type: Attribute *)] + [ + + ] + [ + + ]. + +(* At top_level_stmt: unsupported node type: AnnAssign *) diff --git a/CoqOfPython/ethereum/paris/vm/instructions/arithmetic.v b/CoqOfPython/ethereum/paris/vm/instructions/arithmetic.v index 9020f6d..3996ed7 100644 --- a/CoqOfPython/ethereum/paris/vm/instructions/arithmetic.v +++ b/CoqOfPython/ethereum/paris/vm/instructions/arithmetic.v @@ -1,7 +1,9 @@ Require Import CoqOfPython.CoqOfPython. +Definition globals : string := "ethereum.paris.vm.instructions.arithmetic". + Definition expr_1 : Value.t := - (Value.String " + Constant.str " Ethereum Virtual Machine (EVM) Arithmetic Instructions ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -13,36 +15,45 @@ Introduction ------------ Implementations of the EVM Arithmetic instructions. -"). - -Require ethereum.base_types. -Definition U255_CEIL_VALUE := U255_CEIL_VALUE. -Definition U256 := U256. -Definition U256_CEIL_VALUE := U256_CEIL_VALUE. -Definition Uint := Uint. - -Require ethereum.utils.numeric. -Definition get_sign := get_sign. - -Require __init__. -Definition Evm := Evm. - -Require gas. -Definition GAS_EXPONENTIATION := GAS_EXPONENTIATION. -Definition GAS_EXPONENTIATION_PER_BYTE := GAS_EXPONENTIATION_PER_BYTE. -Definition GAS_LOW := GAS_LOW. -Definition GAS_MID := GAS_MID. -Definition GAS_VERY_LOW := GAS_VERY_LOW. -Definition charge_gas := charge_gas. - -Require stack. -Definition pop := pop. -Definition push := push. - -Definition add (args : list Value.t) : M := - match args with - | [evm] => ltac:(M.monadic ( - let _ := (Value.String " +". + +Axiom ethereum_base_types_imports_U255_CEIL_VALUE : + IsImported globals "ethereum.base_types" "U255_CEIL_VALUE". +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_U256_CEIL_VALUE : + IsImported globals "ethereum.base_types" "U256_CEIL_VALUE". +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". + +Axiom ethereum_utils_numeric_imports_get_sign : + IsImported globals "ethereum.utils.numeric" "get_sign". + +Axiom ethereum_paris_vm_imports_Evm : + IsImported globals "ethereum.paris.vm" "Evm". + +Axiom ethereum_paris_vm_gas_imports_GAS_EXPONENTIATION : + IsImported globals "ethereum.paris.vm.gas" "GAS_EXPONENTIATION". +Axiom ethereum_paris_vm_gas_imports_GAS_EXPONENTIATION_PER_BYTE : + IsImported globals "ethereum.paris.vm.gas" "GAS_EXPONENTIATION_PER_BYTE". +Axiom ethereum_paris_vm_gas_imports_GAS_LOW : + IsImported globals "ethereum.paris.vm.gas" "GAS_LOW". +Axiom ethereum_paris_vm_gas_imports_GAS_MID : + IsImported globals "ethereum.paris.vm.gas" "GAS_MID". +Axiom ethereum_paris_vm_gas_imports_GAS_VERY_LOW : + IsImported globals "ethereum.paris.vm.gas" "GAS_VERY_LOW". +Axiom ethereum_paris_vm_gas_imports_charge_gas : + IsImported globals "ethereum.paris.vm.gas" "charge_gas". + +Axiom ethereum_paris_vm_stack_imports_pop : + IsImported globals "ethereum.paris.vm.stack" "pop". +Axiom ethereum_paris_vm_stack_imports_push : + IsImported globals "ethereum.paris.vm.stack" "push". + +Definition add : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " Adds the top two elements of the stack together, and pushes the result back on the stack. @@ -51,24 +62,64 @@ Definition add (args : list Value.t) : M := evm : The current EVM frame. - ") in - let x := (M.call (| pop, [evm.stack] |)) in - let y := (M.call (| pop, [evm.stack] |)) in - let _ := (M.call (| charge_gas, [evm; GAS_VERY_LOW] |)) in - let result := (M.call (| x.wrapping_add, [y] |)) in - let _ := (M.call (| push, [evm.stack; result] |)) in - let _ := M.assign_op (| - BinOp.add, - evm.pc, - (Value.Integer 1) - |) in)) - | _ => M.impossible - end. - -Definition sub (args : list Value.t) : M := - match args with - | [evm] => ltac:(M.monadic ( - let _ := (Value.String " + " in + let _ := M.assign_local (| + "x" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "y" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_VERY_LOW" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "result" , + M.call (| + M.get_field (| M.get_name (| globals, "x" |), "wrapping_add" |), + make_list [ + M.get_name (| globals, "y" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.get_name (| globals, "result" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition sub : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " Subtracts the top two elements of the stack, and pushes the result back on the stack. @@ -77,24 +128,64 @@ Definition sub (args : list Value.t) : M := evm : The current EVM frame. - ") in - let x := (M.call (| pop, [evm.stack] |)) in - let y := (M.call (| pop, [evm.stack] |)) in - let _ := (M.call (| charge_gas, [evm; GAS_VERY_LOW] |)) in - let result := (M.call (| x.wrapping_sub, [y] |)) in - let _ := (M.call (| push, [evm.stack; result] |)) in - let _ := M.assign_op (| - BinOp.add, - evm.pc, - (Value.Integer 1) - |) in)) - | _ => M.impossible - end. - -Definition mul (args : list Value.t) : M := - match args with - | [evm] => ltac:(M.monadic ( - let _ := (Value.String " + " in + let _ := M.assign_local (| + "x" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "y" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_VERY_LOW" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "result" , + M.call (| + M.get_field (| M.get_name (| globals, "x" |), "wrapping_sub" |), + make_list [ + M.get_name (| globals, "y" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.get_name (| globals, "result" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition mul : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " Multiply the top two elements of the stack, and pushes the result back on the stack. @@ -103,24 +194,64 @@ Definition mul (args : list Value.t) : M := evm : The current EVM frame. - ") in - let x := (M.call (| pop, [evm.stack] |)) in - let y := (M.call (| pop, [evm.stack] |)) in - let _ := (M.call (| charge_gas, [evm; GAS_LOW] |)) in - let result := (M.call (| x.wrapping_mul, [y] |)) in - let _ := (M.call (| push, [evm.stack; result] |)) in - let _ := M.assign_op (| - BinOp.add, - evm.pc, - (Value.Integer 1) - |) in)) - | _ => M.impossible - end. - -Definition div (args : list Value.t) : M := - match args with - | [evm] => ltac:(M.monadic ( - let _ := (Value.String " + " in + let _ := M.assign_local (| + "x" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "y" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_LOW" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "result" , + M.call (| + M.get_field (| M.get_name (| globals, "x" |), "wrapping_mul" |), + make_list [ + M.get_name (| globals, "y" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.get_name (| globals, "result" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition div : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " Integer division of the top two elements of the stack. Pushes the result back on the stack. @@ -129,28 +260,85 @@ Definition div (args : list Value.t) : M := evm : The current EVM frame. - ") in - let dividend := (M.call (| pop, [evm.stack] |)) in - let divisor := (M.call (| pop, [evm.stack] |)) in - let _ := (M.call (| charge_gas, [evm; GAS_LOW] |)) in - let _ := - if M.is_true (Compare.eq (| divisor, (Value.Integer 0) |)) then - let quotient := (M.call (| U256, [(Value.Integer 0)] |)) in - else - let quotient := BinOp.floor_div (| dividend, divisor |) in in - let _ := (M.call (| push, [evm.stack; quotient] |)) in - let _ := M.assign_op (| - BinOp.add, - evm.pc, - (Value.Integer 1) - |) in)) - | _ => M.impossible - end. - -Definition sdiv (args : list Value.t) : M := - match args with - | [evm] => ltac:(M.monadic ( - let _ := (Value.String " + " in + let _ := M.assign_local (| + "dividend" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "divisor" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_LOW" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, "divisor" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "quotient" , + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "quotient" , + BinOp.floor_div (| + M.get_name (| globals, "dividend" |), + M.get_name (| globals, "divisor" |) + |) + |) in + M.pure Constant.None_ + )) |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.get_name (| globals, "quotient" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition sdiv : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " Signed integer division of the top two elements of the stack. Pushes the result back on the stack. @@ -159,33 +347,147 @@ Definition sdiv (args : list Value.t) : M := evm : The current EVM frame. - ") in - let dividend := (M.call (| (M.call (| pop, [evm.stack] |)).to_signed, [] |)) in - let divisor := (M.call (| (M.call (| pop, [evm.stack] |)).to_signed, [] |)) in - let _ := (M.call (| charge_gas, [evm; GAS_LOW] |)) in - let _ := - if M.is_true (Compare.eq (| divisor, (Value.Integer 0) |)) then - let quotient := (Value.Integer 0) in - else - let _ := - if M.is_true (BoolOp.and(Compare.eq (| dividend, (UnOp.subU255_CEIL_VALUE) |)) (Compare.eq (| divisor, (UnOp.sub(Value.Integer 1)) |))) then - let quotient := (UnOp.subU255_CEIL_VALUE) in - else - let sign := (M.call (| get_sign, [BinOp.mult (| dividend, divisor |)] |)) in - let quotient := BinOp.mult (| sign, BinOp.floor_div (| (M.call (| abs, [dividend] |)), (M.call (| abs, [divisor] |)) |) |) in in in - let _ := (M.call (| push, [evm.stack; (M.call (| U256.from_signed, [quotient] |))] |)) in - let _ := M.assign_op (| - BinOp.add, - evm.pc, - (Value.Integer 1) - |) in)) - | _ => M.impossible - end. - -Definition mod (args : list Value.t) : M := - match args with - | [evm] => ltac:(M.monadic ( - let _ := (Value.String " + " in + let _ := M.assign_local (| + "dividend" , + M.call (| + M.get_field (| M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |), "to_signed" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "divisor" , + M.call (| + M.get_field (| M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |), "to_signed" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_LOW" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, "divisor" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "quotient" , + Constant.int 0 + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + BoolOp.and (| + Compare.eq (| + M.get_name (| globals, "dividend" |), + UnOp.sub (| M.get_name (| globals, "U255_CEIL_VALUE" |) |) + |), + ltac:(M.monadic ( + Compare.eq (| + M.get_name (| globals, "divisor" |), + UnOp.sub (| Constant.int 1 |) + |) + )) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "quotient" , + UnOp.sub (| M.get_name (| globals, "U255_CEIL_VALUE" |) |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "sign" , + M.call (| + M.get_name (| globals, "get_sign" |), + make_list [ + BinOp.mult (| + M.get_name (| globals, "dividend" |), + M.get_name (| globals, "divisor" |) + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "quotient" , + BinOp.mult (| + M.get_name (| globals, "sign" |), + BinOp.floor_div (| + M.call (| + M.get_name (| globals, "abs" |), + make_list [ + M.get_name (| globals, "dividend" |) + ], + make_dict [] + |), + M.call (| + M.get_name (| globals, "abs" |), + make_list [ + M.get_name (| globals, "divisor" |) + ], + make_dict [] + |) + |) + |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )) |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.call (| + M.get_field (| M.get_name (| globals, "U256" |), "from_signed" |), + make_list [ + M.get_name (| globals, "quotient" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition mod_ : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " Modulo remainder of the top two elements of the stack. Pushes the result back on the stack. @@ -194,28 +496,85 @@ Definition mod (args : list Value.t) : M := evm : The current EVM frame. - ") in - let x := (M.call (| pop, [evm.stack] |)) in - let y := (M.call (| pop, [evm.stack] |)) in - let _ := (M.call (| charge_gas, [evm; GAS_LOW] |)) in - let _ := - if M.is_true (Compare.eq (| y, (Value.Integer 0) |)) then - let remainder := (M.call (| U256, [(Value.Integer 0)] |)) in - else - let remainder := BinOp.mod_ (| x, y |) in in - let _ := (M.call (| push, [evm.stack; remainder] |)) in - let _ := M.assign_op (| - BinOp.add, - evm.pc, - (Value.Integer 1) - |) in)) - | _ => M.impossible - end. - -Definition smod (args : list Value.t) : M := - match args with - | [evm] => ltac:(M.monadic ( - let _ := (Value.String " + " in + let _ := M.assign_local (| + "x" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "y" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_LOW" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, "y" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "remainder" , + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "remainder" , + BinOp.mod_ (| + M.get_name (| globals, "x" |), + M.get_name (| globals, "y" |) + |) + |) in + M.pure Constant.None_ + )) |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.get_name (| globals, "remainder" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition smod : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " Signed modulo remainder of the top two elements of the stack. Pushes the result back on the stack. @@ -224,28 +583,114 @@ Definition smod (args : list Value.t) : M := evm : The current EVM frame. - ") in - let x := (M.call (| (M.call (| pop, [evm.stack] |)).to_signed, [] |)) in - let y := (M.call (| (M.call (| pop, [evm.stack] |)).to_signed, [] |)) in - let _ := (M.call (| charge_gas, [evm; GAS_LOW] |)) in - let _ := - if M.is_true (Compare.eq (| y, (Value.Integer 0) |)) then - let remainder := (Value.Integer 0) in - else - let remainder := BinOp.mult (| (M.call (| get_sign, [x] |)), BinOp.mod_ (| (M.call (| abs, [x] |)), (M.call (| abs, [y] |)) |) |) in in - let _ := (M.call (| push, [evm.stack; (M.call (| U256.from_signed, [remainder] |))] |)) in - let _ := M.assign_op (| - BinOp.add, - evm.pc, - (Value.Integer 1) - |) in)) - | _ => M.impossible - end. - -Definition addmod (args : list Value.t) : M := - match args with - | [evm] => ltac:(M.monadic ( - let _ := (Value.String " + " in + let _ := M.assign_local (| + "x" , + M.call (| + M.get_field (| M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |), "to_signed" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "y" , + M.call (| + M.get_field (| M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |), "to_signed" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_LOW" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, "y" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "remainder" , + Constant.int 0 + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "remainder" , + BinOp.mult (| + M.call (| + M.get_name (| globals, "get_sign" |), + make_list [ + M.get_name (| globals, "x" |) + ], + make_dict [] + |), + BinOp.mod_ (| + M.call (| + M.get_name (| globals, "abs" |), + make_list [ + M.get_name (| globals, "x" |) + ], + make_dict [] + |), + M.call (| + M.get_name (| globals, "abs" |), + make_list [ + M.get_name (| globals, "y" |) + ], + make_dict [] + |) + |) + |) + |) in + M.pure Constant.None_ + )) |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.call (| + M.get_field (| M.get_name (| globals, "U256" |), "from_signed" |), + make_list [ + M.get_name (| globals, "remainder" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition addmod : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " Modulo addition of the top 2 elements with the 3rd element. Pushes the result back on the stack. @@ -254,29 +699,122 @@ Definition addmod (args : list Value.t) : M := evm : The current EVM frame. - ") in - let x := (M.call (| Uint, [(M.call (| pop, [evm.stack] |))] |)) in - let y := (M.call (| Uint, [(M.call (| pop, [evm.stack] |))] |)) in - let z := (M.call (| Uint, [(M.call (| pop, [evm.stack] |))] |)) in - let _ := (M.call (| charge_gas, [evm; GAS_MID] |)) in - let _ := - if M.is_true (Compare.eq (| z, (Value.Integer 0) |)) then - let result := (M.call (| U256, [(Value.Integer 0)] |)) in - else - let result := (M.call (| U256, [BinOp.mod_ (| BinOp.add (| x, y |), z |)] |)) in in - let _ := (M.call (| push, [evm.stack; result] |)) in - let _ := M.assign_op (| - BinOp.add, - evm.pc, - (Value.Integer 1) - |) in)) - | _ => M.impossible - end. - -Definition mulmod (args : list Value.t) : M := - match args with - | [evm] => ltac:(M.monadic ( - let _ := (Value.String " + " in + let _ := M.assign_local (| + "x" , + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "y" , + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "z" , + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_MID" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, "z" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "result" , + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "result" , + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + BinOp.mod_ (| + BinOp.add (| + M.get_name (| globals, "x" |), + M.get_name (| globals, "y" |) + |), + M.get_name (| globals, "z" |) + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + )) |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.get_name (| globals, "result" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition mulmod : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " Modulo multiplication of the top 2 elements with the 3rd element. Pushes the result back on the stack. @@ -285,29 +823,122 @@ Definition mulmod (args : list Value.t) : M := evm : The current EVM frame. - ") in - let x := (M.call (| Uint, [(M.call (| pop, [evm.stack] |))] |)) in - let y := (M.call (| Uint, [(M.call (| pop, [evm.stack] |))] |)) in - let z := (M.call (| Uint, [(M.call (| pop, [evm.stack] |))] |)) in - let _ := (M.call (| charge_gas, [evm; GAS_MID] |)) in - let _ := - if M.is_true (Compare.eq (| z, (Value.Integer 0) |)) then - let result := (M.call (| U256, [(Value.Integer 0)] |)) in - else - let result := (M.call (| U256, [BinOp.mod_ (| BinOp.mult (| x, y |), z |)] |)) in in - let _ := (M.call (| push, [evm.stack; result] |)) in - let _ := M.assign_op (| - BinOp.add, - evm.pc, - (Value.Integer 1) - |) in)) - | _ => M.impossible - end. - -Definition exp (args : list Value.t) : M := - match args with - | [evm] => ltac:(M.monadic ( - let _ := (Value.String " + " in + let _ := M.assign_local (| + "x" , + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "y" , + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "z" , + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_MID" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, "z" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "result" , + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "result" , + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + BinOp.mod_ (| + BinOp.mult (| + M.get_name (| globals, "x" |), + M.get_name (| globals, "y" |) + |), + M.get_name (| globals, "z" |) + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + )) |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.get_name (| globals, "result" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition exp : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " Exponential operation of the top 2 elements. Pushes the result back on the stack. @@ -316,26 +947,108 @@ Definition exp (args : list Value.t) : M := evm : The current EVM frame. - ") in - let base := (M.call (| Uint, [(M.call (| pop, [evm.stack] |))] |)) in - let exponent := (M.call (| Uint, [(M.call (| pop, [evm.stack] |))] |)) in - let exponent_bits := (M.call (| exponent.bit_length, [] |)) in - let exponent_bytes := BinOp.floor_div (| BinOp.add (| exponent_bits, (Value.Integer 7) |), (Value.Integer 8) |) in - let _ := (M.call (| charge_gas, [evm; BinOp.add (| GAS_EXPONENTIATION, BinOp.mult (| GAS_EXPONENTIATION_PER_BYTE, exponent_bytes |) |)] |)) in - let result := (M.call (| U256, [(M.call (| pow, [base; exponent; U256_CEIL_VALUE] |))] |)) in - let _ := (M.call (| push, [evm.stack; result] |)) in - let _ := M.assign_op (| - BinOp.add, - evm.pc, - (Value.Integer 1) - |) in)) - | _ => M.impossible - end. - -Definition signextend (args : list Value.t) : M := - match args with - | [evm] => ltac:(M.monadic ( - let _ := (Value.String " + " in + let _ := M.assign_local (| + "base" , + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "exponent" , + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "exponent_bits" , + M.call (| + M.get_field (| M.get_name (| globals, "exponent" |), "bit_length" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "exponent_bytes" , + BinOp.floor_div (| + BinOp.add (| + M.get_name (| globals, "exponent_bits" |), + Constant.int 7 + |), + Constant.int 8 + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + BinOp.add (| + M.get_name (| globals, "GAS_EXPONENTIATION" |), + BinOp.mult (| + M.get_name (| globals, "GAS_EXPONENTIATION_PER_BYTE" |), + M.get_name (| globals, "exponent_bytes" |) + |) + |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "result" , + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + M.call (| + M.get_name (| globals, "pow" |), + make_list [ + M.get_name (| globals, "base" |); + M.get_name (| globals, "exponent" |); + M.get_name (| globals, "U256_CEIL_VALUE" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.get_name (| globals, "result" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition signextend : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " Sign extend operation. In other words, extend a signed number which fits in N bytes to 32 bytes. @@ -344,28 +1057,164 @@ Definition signextend (args : list Value.t) : M := evm : The current EVM frame. - ") in - let byte_num := (M.call (| pop, [evm.stack] |)) in - let value := (M.call (| pop, [evm.stack] |)) in - let _ := (M.call (| charge_gas, [evm; GAS_LOW] |)) in - let _ := - if M.is_true (Compare.gt (| byte_num, (Value.Integer 31) |)) then - let result := value in - else - let value_bytes := (M.call (| bytes, [(M.call (| value.to_be_bytes32, [] |))] |)) in - let value_bytes := value_bytes[BinOp.sub (| (Value.Integer 31), (M.call (| int, [byte_num] |)) |):(* At stmt: unsupported node type: NoneType *)] in - let sign_bit := BinOp.r_shift (| value_bytes[(Value.Integer 0)], (Value.Integer 7) |) in - let _ := - if M.is_true (Compare.eq (| sign_bit, (Value.Integer 0) |)) then - let result := (M.call (| U256.from_be_bytes, [value_bytes] |)) in - else - let num_bytes_prepend := BinOp.sub (| (Value.Integer 32), BinOp.add (| byte_num, (Value.Integer 1) |) |) in - let result := (M.call (| U256.from_be_bytes, [BinOp.add (| (M.call (| bytearray, [BinOp.mult (| [(Value.Integer 255)], num_bytes_prepend |)] |)), value_bytes |)] |)) in in in - let _ := (M.call (| push, [evm.stack; result] |)) in - let _ := M.assign_op (| - BinOp.add, - evm.pc, - (Value.Integer 1) - |) in)) - | _ => M.impossible - end. + " in + let _ := M.assign_local (| + "byte_num" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "value" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_LOW" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.gt (| + M.get_name (| globals, "byte_num" |), + Constant.int 31 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "result" , + M.get_name (| globals, "value" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "value_bytes" , + M.call (| + M.get_name (| globals, "bytes" |), + make_list [ + M.call (| + M.get_field (| M.get_name (| globals, "value" |), "to_be_bytes32" |), + make_list [], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "value_bytes" , + M.slice (| + M.get_name (| globals, "value_bytes" |), + BinOp.sub (| + Constant.int 31, + M.call (| + M.get_name (| globals, "int" |), + make_list [ + M.get_name (| globals, "byte_num" |) + ], + make_dict [] + |) + |), + Constant.None_, + Constant.None_ + |) + |) in + let _ := M.assign_local (| + "sign_bit" , + BinOp.r_shift (| + M.get_subscript (| + M.get_name (| globals, "value_bytes" |), + Constant.int 0 + |), + Constant.int 7 + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, "sign_bit" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "result" , + M.call (| + M.get_field (| M.get_name (| globals, "U256" |), "from_be_bytes" |), + make_list [ + M.get_name (| globals, "value_bytes" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "num_bytes_prepend" , + BinOp.sub (| + Constant.int 32, + BinOp.add (| + M.get_name (| globals, "byte_num" |), + Constant.int 1 + |) + |) + |) in + let _ := M.assign_local (| + "result" , + M.call (| + M.get_field (| M.get_name (| globals, "U256" |), "from_be_bytes" |), + make_list [ + BinOp.add (| + M.call (| + M.get_name (| globals, "bytearray" |), + make_list [ + BinOp.mult (| + make_list [ + Constant.int 255 + ], + M.get_name (| globals, "num_bytes_prepend" |) + |) + ], + make_dict [] + |), + M.get_name (| globals, "value_bytes" |) + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )) |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.get_name (| globals, "result" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). diff --git a/CoqOfPython/ethereum/paris/vm/instructions/bitwise.v b/CoqOfPython/ethereum/paris/vm/instructions/bitwise.v new file mode 100644 index 0000000..68e07c4 --- /dev/null +++ b/CoqOfPython/ethereum/paris/vm/instructions/bitwise.v @@ -0,0 +1,666 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.paris.vm.instructions.bitwise". + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) Bitwise Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM bitwise instructions. +". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_U256_CEIL_VALUE : + IsImported globals "ethereum.base_types" "U256_CEIL_VALUE". + +Axiom ethereum_paris_vm_imports_Evm : + IsImported globals "ethereum.paris.vm" "Evm". + +Axiom ethereum_paris_vm_gas_imports_GAS_VERY_LOW : + IsImported globals "ethereum.paris.vm.gas" "GAS_VERY_LOW". +Axiom ethereum_paris_vm_gas_imports_charge_gas : + IsImported globals "ethereum.paris.vm.gas" "charge_gas". + +Axiom ethereum_paris_vm_stack_imports_pop : + IsImported globals "ethereum.paris.vm.stack" "pop". +Axiom ethereum_paris_vm_stack_imports_push : + IsImported globals "ethereum.paris.vm.stack" "push". + +Definition bitwise_and : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Bitwise AND operation of the top 2 elements of the stack. Pushes the + result back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "x" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "y" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_VERY_LOW" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + BinOp.bit_and (| + M.get_name (| globals, "x" |), + M.get_name (| globals, "y" |) + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition bitwise_or : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Bitwise OR operation of the top 2 elements of the stack. Pushes the + result back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "x" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "y" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_VERY_LOW" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + BinOp.bit_or (| + M.get_name (| globals, "x" |), + M.get_name (| globals, "y" |) + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition bitwise_xor : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Bitwise XOR operation of the top 2 elements of the stack. Pushes the + result back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "x" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "y" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_VERY_LOW" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + BinOp.bit_xor (| + M.get_name (| globals, "x" |), + M.get_name (| globals, "y" |) + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition bitwise_not : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Bitwise NOT operation of the top element of the stack. Pushes the + result back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "x" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_VERY_LOW" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + UnOp.invert (| M.get_name (| globals, "x" |) |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition get_byte : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + For a word (defined by next top element of the stack), retrieve the + Nth byte (0-indexed and defined by top element of stack) from the + left (most significant) to right (least significant). + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "byte_index" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "word" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_VERY_LOW" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.gt_e (| + M.get_name (| globals, "byte_index" |), + Constant.int 32 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "result" , + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "extra_bytes_to_right" , + BinOp.sub (| + Constant.int 31, + M.get_name (| globals, "byte_index" |) + |) + |) in + let _ := M.assign_local (| + "word" , + BinOp.r_shift (| + M.get_name (| globals, "word" |), + BinOp.mult (| + M.get_name (| globals, "extra_bytes_to_right" |), + Constant.int 8 + |) + |) + |) in + let _ := M.assign_local (| + "word" , + BinOp.bit_and (| + M.get_name (| globals, "word" |), + Constant.int 255 + |) + |) in + let _ := M.assign_local (| + "result" , + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + M.get_name (| globals, "word" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + )) |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.get_name (| globals, "result" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition bitwise_shl : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Logical shift left (SHL) operation of the top 2 elements of the stack. + Pushes the result back on the stack. + Parameters + ---------- + evm : + The current EVM frame. + " in + let _ := M.assign_local (| + "shift" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "value" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_VERY_LOW" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.lt (| + M.get_name (| globals, "shift" |), + Constant.int 256 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "result" , + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + BinOp.mod_ (| + BinOp.l_shift (| + M.get_name (| globals, "value" |), + M.get_name (| globals, "shift" |) + |), + M.get_name (| globals, "U256_CEIL_VALUE" |) + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "result" , + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + )) |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.get_name (| globals, "result" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition bitwise_shr : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Logical shift right (SHR) operation of the top 2 elements of the stack. + Pushes the result back on the stack. + Parameters + ---------- + evm : + The current EVM frame. + " in + let _ := M.assign_local (| + "shift" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "value" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_VERY_LOW" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.lt (| + M.get_name (| globals, "shift" |), + Constant.int 256 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "result" , + BinOp.r_shift (| + M.get_name (| globals, "value" |), + M.get_name (| globals, "shift" |) + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "result" , + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + )) |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.get_name (| globals, "result" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition bitwise_sar : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Arithmetic shift right (SAR) operation of the top 2 elements of the stack. + Pushes the result back on the stack. + Parameters + ---------- + evm : + The current EVM frame. + " in + let _ := M.assign_local (| + "shift" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "signed_value" , + M.call (| + M.get_field (| M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |), "to_signed" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_VERY_LOW" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.lt (| + M.get_name (| globals, "shift" |), + Constant.int 256 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "result" , + M.call (| + M.get_field (| M.get_name (| globals, "U256" |), "from_signed" |), + make_list [ + BinOp.r_shift (| + M.get_name (| globals, "signed_value" |), + M.get_name (| globals, "shift" |) + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + Compare.gt_e (| + M.get_name (| globals, "signed_value" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "result" , + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "result" , + M.get_field (| M.get_name (| globals, "U256" |), "MAX_VALUE" |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )) |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.get_name (| globals, "result" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). diff --git a/CoqOfPython/ethereum/paris/vm/instructions/block.v b/CoqOfPython/ethereum/paris/vm/instructions/block.v new file mode 100644 index 0000000..5869617 --- /dev/null +++ b/CoqOfPython/ethereum/paris/vm/instructions/block.v @@ -0,0 +1,432 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.paris.vm.instructions.block". + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) Block Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM block instructions. +". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". + +Axiom ethereum_paris_vm_imports_Evm : + IsImported globals "ethereum.paris.vm" "Evm". + +Axiom ethereum_paris_vm_gas_imports_GAS_BASE : + IsImported globals "ethereum.paris.vm.gas" "GAS_BASE". +Axiom ethereum_paris_vm_gas_imports_GAS_BLOCK_HASH : + IsImported globals "ethereum.paris.vm.gas" "GAS_BLOCK_HASH". +Axiom ethereum_paris_vm_gas_imports_charge_gas : + IsImported globals "ethereum.paris.vm.gas" "charge_gas". + +Axiom ethereum_paris_vm_stack_imports_pop : + IsImported globals "ethereum.paris.vm.stack" "pop". +Axiom ethereum_paris_vm_stack_imports_push : + IsImported globals "ethereum.paris.vm.stack" "push". + +Definition block_hash : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Push the hash of one of the 256 most recent complete blocks onto the + stack. The block number to hash is present at the top of the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + Raises + ------ + :py:class:`~ethereum.paris.vm.exceptions.StackUnderflowError` + If `len(stack)` is less than `1`. + :py:class:`~ethereum.paris.vm.exceptions.OutOfGasError` + If `evm.gas_left` is less than `20`. + " in + let _ := M.assign_local (| + "block_number" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_BLOCK_HASH" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + BoolOp.or (| + Compare.lt_e (| + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "env" |), "number" |), + M.get_name (| globals, "block_number" |) + |), + ltac:(M.monadic ( + Compare.gt (| + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "env" |), "number" |), + BinOp.add (| + M.get_name (| globals, "block_number" |), + Constant.int 256 + |) + |) + )) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "hash" , + Constant.bytes "00" + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "hash" , + M.get_subscript (| + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "env" |), "block_hashes" |), + UnOp.sub (| BinOp.sub (| + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "env" |), "number" |), + M.get_name (| globals, "block_number" |) + |) |) + |) + |) in + M.pure Constant.None_ + )) |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.call (| + M.get_field (| M.get_name (| globals, "U256" |), "from_be_bytes" |), + make_list [ + M.get_name (| globals, "hash" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition coinbase : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Push the current block's beneficiary address (address of the block miner) + onto the stack. + + Here the current block refers to the block in which the currently + executing transaction/call resides. + + Parameters + ---------- + evm : + The current EVM frame. + + Raises + ------ + :py:class:`~ethereum.paris.vm.exceptions.StackOverflowError` + If `len(stack)` is equal to `1024`. + :py:class:`~ethereum.paris.vm.exceptions.OutOfGasError` + If `evm.gas_left` is less than `2`. + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_BASE" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.call (| + M.get_field (| M.get_name (| globals, "U256" |), "from_be_bytes" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "env" |), "coinbase" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition timestamp : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Push the current block's timestamp onto the stack. Here the timestamp + being referred is actually the unix timestamp in seconds. + + Here the current block refers to the block in which the currently + executing transaction/call resides. + + Parameters + ---------- + evm : + The current EVM frame. + + Raises + ------ + :py:class:`~ethereum.paris.vm.exceptions.StackOverflowError` + If `len(stack)` is equal to `1024`. + :py:class:`~ethereum.paris.vm.exceptions.OutOfGasError` + If `evm.gas_left` is less than `2`. + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_BASE" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "env" |), "time" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition number : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Push the current block's number onto the stack. + + Here the current block refers to the block in which the currently + executing transaction/call resides. + + Parameters + ---------- + evm : + The current EVM frame. + + Raises + ------ + :py:class:`~ethereum.paris.vm.exceptions.StackOverflowError` + If `len(stack)` is equal to `1024`. + :py:class:`~ethereum.paris.vm.exceptions.OutOfGasError` + If `evm.gas_left` is less than `2`. + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_BASE" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "env" |), "number" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition prev_randao : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Push the `prev_randao` value onto the stack. + + The `prev_randao` value is the random output of the beacon chain's + randomness oracle for the previous block. + + Parameters + ---------- + evm : + The current EVM frame. + + Raises + ------ + :py:class:`~ethereum.paris.vm.exceptions.StackOverflowError` + If `len(stack)` is equal to `1024`. + :py:class:`~ethereum.paris.vm.exceptions.OutOfGasError` + If `evm.gas_left` is less than `2`. + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_BASE" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.call (| + M.get_field (| M.get_name (| globals, "U256" |), "from_be_bytes" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "env" |), "prev_randao" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition gas_limit : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Push the current block's gas limit onto the stack. + + Here the current block refers to the block in which the currently + executing transaction/call resides. + + Parameters + ---------- + evm : + The current EVM frame. + + Raises + ------ + :py:class:`~ethereum.paris.vm.exceptions.StackOverflowError` + If `len(stack)` is equal to `1024`. + :py:class:`~ethereum.paris.vm.exceptions.OutOfGasError` + If `evm.gas_left` is less than `2`. + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_BASE" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "env" |), "gas_limit" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition chain_id : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Push the chain id onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + Raises + ------ + :py:class:`~ethereum.paris.vm.exceptions.StackOverflowError` + If `len(stack)` is equal to `1024`. + :py:class:`~ethereum.paris.vm.exceptions.OutOfGasError` + If `evm.gas_left` is less than `2`. + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_BASE" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "env" |), "chain_id" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). diff --git a/CoqOfPython/ethereum/paris/vm/instructions/comparison.v b/CoqOfPython/ethereum/paris/vm/instructions/comparison.v new file mode 100644 index 0000000..f0bbc4a --- /dev/null +++ b/CoqOfPython/ethereum/paris/vm/instructions/comparison.v @@ -0,0 +1,452 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.paris.vm.instructions.comparison". + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) Comparison Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM Comparison instructions. +". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". + +Axiom ethereum_paris_vm_imports_Evm : + IsImported globals "ethereum.paris.vm" "Evm". + +Axiom ethereum_paris_vm_gas_imports_GAS_VERY_LOW : + IsImported globals "ethereum.paris.vm.gas" "GAS_VERY_LOW". +Axiom ethereum_paris_vm_gas_imports_charge_gas : + IsImported globals "ethereum.paris.vm.gas" "charge_gas". + +Axiom ethereum_paris_vm_stack_imports_pop : + IsImported globals "ethereum.paris.vm.stack" "pop". +Axiom ethereum_paris_vm_stack_imports_push : + IsImported globals "ethereum.paris.vm.stack" "push". + +Definition less_than : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Checks if the top element is less than the next top element. Pushes the + result back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "left" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "right" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_VERY_LOW" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "result" , + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Compare.lt (| + M.get_name (| globals, "left" |), + M.get_name (| globals, "right" |) + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.get_name (| globals, "result" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition signed_less_than : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Signed less-than comparison. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "left" , + M.call (| + M.get_field (| M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |), "to_signed" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "right" , + M.call (| + M.get_field (| M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |), "to_signed" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_VERY_LOW" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "result" , + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Compare.lt (| + M.get_name (| globals, "left" |), + M.get_name (| globals, "right" |) + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.get_name (| globals, "result" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition greater_than : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Checks if the top element is greater than the next top element. Pushes + the result back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "left" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "right" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_VERY_LOW" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "result" , + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Compare.gt (| + M.get_name (| globals, "left" |), + M.get_name (| globals, "right" |) + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.get_name (| globals, "result" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition signed_greater_than : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Signed greater-than comparison. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "left" , + M.call (| + M.get_field (| M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |), "to_signed" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "right" , + M.call (| + M.get_field (| M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |), "to_signed" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_VERY_LOW" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "result" , + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Compare.gt (| + M.get_name (| globals, "left" |), + M.get_name (| globals, "right" |) + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.get_name (| globals, "result" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition equal : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Checks if the top element is equal to the next top element. Pushes + the result back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "left" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "right" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_VERY_LOW" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "result" , + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Compare.eq (| + M.get_name (| globals, "left" |), + M.get_name (| globals, "right" |) + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.get_name (| globals, "result" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition is_zero : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Checks if the top element is equal to 0. Pushes the result back on the + stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "x" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_VERY_LOW" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "result" , + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Compare.eq (| + M.get_name (| globals, "x" |), + Constant.int 0 + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.get_name (| globals, "result" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). diff --git a/CoqOfPython/ethereum/paris/vm/instructions/control_flow.v b/CoqOfPython/ethereum/paris/vm/instructions/control_flow.v new file mode 100644 index 0000000..077810e --- /dev/null +++ b/CoqOfPython/ethereum/paris/vm/instructions/control_flow.v @@ -0,0 +1,350 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.paris.vm.instructions.control_flow". + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) Control Flow Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM control flow instructions. +". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". + +Axiom ethereum_paris_vm_gas_imports_GAS_BASE : + IsImported globals "ethereum.paris.vm.gas" "GAS_BASE". +Axiom ethereum_paris_vm_gas_imports_GAS_HIGH : + IsImported globals "ethereum.paris.vm.gas" "GAS_HIGH". +Axiom ethereum_paris_vm_gas_imports_GAS_JUMPDEST : + IsImported globals "ethereum.paris.vm.gas" "GAS_JUMPDEST". +Axiom ethereum_paris_vm_gas_imports_GAS_MID : + IsImported globals "ethereum.paris.vm.gas" "GAS_MID". +Axiom ethereum_paris_vm_gas_imports_charge_gas : + IsImported globals "ethereum.paris.vm.gas" "charge_gas". + +Axiom ethereum_paris_vm_imports_Evm : + IsImported globals "ethereum.paris.vm" "Evm". + +Axiom ethereum_paris_vm_exceptions_imports_InvalidJumpDestError : + IsImported globals "ethereum.paris.vm.exceptions" "InvalidJumpDestError". + +Axiom ethereum_paris_vm_stack_imports_pop : + IsImported globals "ethereum.paris.vm.stack" "pop". +Axiom ethereum_paris_vm_stack_imports_push : + IsImported globals "ethereum.paris.vm.stack" "push". + +Definition stop : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Stop further execution of EVM code. + + Parameters + ---------- + evm : + The current EVM frame. + " in + let _ := M.pass (| |) in + let _ := M.pass (| |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, "evm" |), "running" |), + Constant.bool false + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition jump : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Alter the program counter to the location specified by the top of the + stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "jump_dest" , + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_MID" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.not_in (| + M.get_name (| globals, "jump_dest" |), + M.get_field (| M.get_name (| globals, "evm" |), "valid_jump_destinations" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, "InvalidJumpDestError" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.get_name (| globals, "jump_dest" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Definition jumpi : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Alter the program counter to the specified location if and only if a + condition is true. If the condition is not true, then the program counter + would increase only by 1. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "jump_dest" , + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "conditional_value" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_HIGH" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, "conditional_value" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "destination" , + BinOp.add (| + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + Compare.not_in (| + M.get_name (| globals, "jump_dest" |), + M.get_field (| M.get_name (| globals, "evm" |), "valid_jump_destinations" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, "InvalidJumpDestError" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "destination" , + M.get_name (| globals, "jump_dest" |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )) |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.get_name (| globals, "destination" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Definition pc : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Push onto the stack the value of the program counter after reaching the + current instruction and without increasing it for the next instruction. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_BASE" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "pc" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition gas_left : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Push the amount of available gas (including the corresponding reduction + for the cost of this instruction) onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_BASE" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "gas_left" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition jumpdest : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Mark a valid destination for jumps. This is a noop, present only + to be used by `JUMP` and `JUMPI` opcodes to verify that their jump is + valid. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_JUMPDEST" |) + ], + make_dict [] + |) in + let _ := M.pass (| |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). diff --git a/CoqOfPython/ethereum/paris/vm/instructions/environment.v b/CoqOfPython/ethereum/paris/vm/instructions/environment.v new file mode 100644 index 0000000..44987c3 --- /dev/null +++ b/CoqOfPython/ethereum/paris/vm/instructions/environment.v @@ -0,0 +1,1529 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.paris.vm.instructions.environment". + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) Environmental Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM environment related instructions. +". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". + +Axiom ethereum_crypto_hash_imports_keccak256 : + IsImported globals "ethereum.crypto.hash" "keccak256". + +Axiom ethereum_utils_ensure_imports_ensure : + IsImported globals "ethereum.utils.ensure" "ensure". + +Axiom ethereum_utils_numeric_imports_ceil32 : + IsImported globals "ethereum.utils.numeric" "ceil32". + +Axiom ethereum_paris_fork_types_imports_EMPTY_ACCOUNT : + IsImported globals "ethereum.paris.fork_types" "EMPTY_ACCOUNT". + +Axiom ethereum_paris_state_imports_get_account : + IsImported globals "ethereum.paris.state" "get_account". + +Axiom ethereum_paris_utils_address_imports_to_address : + IsImported globals "ethereum.paris.utils.address" "to_address". + +Axiom ethereum_paris_vm_memory_imports_buffer_read : + IsImported globals "ethereum.paris.vm.memory" "buffer_read". +Axiom ethereum_paris_vm_memory_imports_memory_write : + IsImported globals "ethereum.paris.vm.memory" "memory_write". + +Axiom ethereum_paris_vm_imports_Evm : + IsImported globals "ethereum.paris.vm" "Evm". + +Axiom ethereum_paris_vm_exceptions_imports_OutOfBoundsRead : + IsImported globals "ethereum.paris.vm.exceptions" "OutOfBoundsRead". + +Axiom ethereum_paris_vm_gas_imports_GAS_BASE : + IsImported globals "ethereum.paris.vm.gas" "GAS_BASE". +Axiom ethereum_paris_vm_gas_imports_GAS_COLD_ACCOUNT_ACCESS : + IsImported globals "ethereum.paris.vm.gas" "GAS_COLD_ACCOUNT_ACCESS". +Axiom ethereum_paris_vm_gas_imports_GAS_COPY : + IsImported globals "ethereum.paris.vm.gas" "GAS_COPY". +Axiom ethereum_paris_vm_gas_imports_GAS_FAST_STEP : + IsImported globals "ethereum.paris.vm.gas" "GAS_FAST_STEP". +Axiom ethereum_paris_vm_gas_imports_GAS_RETURN_DATA_COPY : + IsImported globals "ethereum.paris.vm.gas" "GAS_RETURN_DATA_COPY". +Axiom ethereum_paris_vm_gas_imports_GAS_VERY_LOW : + IsImported globals "ethereum.paris.vm.gas" "GAS_VERY_LOW". +Axiom ethereum_paris_vm_gas_imports_GAS_WARM_ACCESS : + IsImported globals "ethereum.paris.vm.gas" "GAS_WARM_ACCESS". +Axiom ethereum_paris_vm_gas_imports_calculate_gas_extend_memory : + IsImported globals "ethereum.paris.vm.gas" "calculate_gas_extend_memory". +Axiom ethereum_paris_vm_gas_imports_charge_gas : + IsImported globals "ethereum.paris.vm.gas" "charge_gas". + +Axiom ethereum_paris_vm_stack_imports_pop : + IsImported globals "ethereum.paris.vm.stack" "pop". +Axiom ethereum_paris_vm_stack_imports_push : + IsImported globals "ethereum.paris.vm.stack" "push". + +Definition address : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Pushes the address of the current executing account to the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_BASE" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.call (| + M.get_field (| M.get_name (| globals, "U256" |), "from_be_bytes" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "current_target" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition balance : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Pushes the balance of the given account onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "address" , + M.call (| + M.get_name (| globals, "to_address" |), + make_list [ + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.in_ (| + M.get_name (| globals, "address" |), + M.get_field (| M.get_name (| globals, "evm" |), "accessed_addresses" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_WARM_ACCESS" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "accessed_addresses" |), "add" |), + make_list [ + M.get_name (| globals, "address" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_COLD_ACCOUNT_ACCESS" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "balance" , + M.get_field (| M.call (| + M.get_name (| globals, "get_account" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "env" |), "state" |); + M.get_name (| globals, "address" |) + ], + make_dict [] + |), "balance" |) + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.get_name (| globals, "balance" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition origin : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Pushes the address of the original transaction sender to the stack. + The origin address can only be an EOA. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_BASE" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.call (| + M.get_field (| M.get_name (| globals, "U256" |), "from_be_bytes" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "env" |), "origin" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition caller : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Pushes the address of the caller onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_BASE" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.call (| + M.get_field (| M.get_name (| globals, "U256" |), "from_be_bytes" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "caller" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition callvalue : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Push the value (in wei) sent with the call onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_BASE" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "value" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition calldataload : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Push a word (32 bytes) of the input data belonging to the current + environment onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "start_index" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_VERY_LOW" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "value" , + M.call (| + M.get_name (| globals, "buffer_read" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "data" |); + M.get_name (| globals, "start_index" |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 32 + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.call (| + M.get_field (| M.get_name (| globals, "U256" |), "from_be_bytes" |), + make_list [ + M.get_name (| globals, "value" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition calldatasize : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Push the size of input data in current environment onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_BASE" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "data" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition calldatacopy : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Copy a portion of the input data in current environment to memory. + + This will also expand the memory, in case that the memory is insufficient + to store the data. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "memory_start_index" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "data_start_index" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "size" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "words" , + BinOp.floor_div (| + M.call (| + M.get_name (| globals, "ceil32" |), + make_list [ + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.get_name (| globals, "size" |) + ], + make_dict [] + |) + ], + make_dict [] + |), + Constant.int 32 + |) + |) in + let _ := M.assign_local (| + "copy_gas_cost" , + BinOp.mult (| + M.get_name (| globals, "GAS_COPY" |), + M.get_name (| globals, "words" |) + |) + |) in + let _ := M.assign_local (| + "extend_memory" , + M.call (| + M.get_name (| globals, "calculate_gas_extend_memory" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "memory" |); + make_list [ + make_tuple [ M.get_name (| globals, "memory_start_index" |); M.get_name (| globals, "size" |) ] + ] + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + BinOp.add (| + BinOp.add (| + M.get_name (| globals, "GAS_VERY_LOW" |), + M.get_name (| globals, "copy_gas_cost" |) + |), + M.get_field (| M.get_name (| globals, "extend_memory" |), "cost" |) + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "memory" |), + BinOp.mult (| + Constant.bytes "00", + M.get_field (| M.get_name (| globals, "extend_memory" |), "expand_by" |) + |) + |) in + let _ := M.assign_local (| + "value" , + M.call (| + M.get_name (| globals, "buffer_read" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "data" |); + M.get_name (| globals, "data_start_index" |); + M.get_name (| globals, "size" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "memory_write" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "memory" |); + M.get_name (| globals, "memory_start_index" |); + M.get_name (| globals, "value" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition codesize : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Push the size of code running in current environment onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_BASE" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "code" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition codecopy : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Copy a portion of the code in current environment to memory. + + This will also expand the memory, in case that the memory is insufficient + to store the data. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "memory_start_index" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "code_start_index" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "size" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "words" , + BinOp.floor_div (| + M.call (| + M.get_name (| globals, "ceil32" |), + make_list [ + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.get_name (| globals, "size" |) + ], + make_dict [] + |) + ], + make_dict [] + |), + Constant.int 32 + |) + |) in + let _ := M.assign_local (| + "copy_gas_cost" , + BinOp.mult (| + M.get_name (| globals, "GAS_COPY" |), + M.get_name (| globals, "words" |) + |) + |) in + let _ := M.assign_local (| + "extend_memory" , + M.call (| + M.get_name (| globals, "calculate_gas_extend_memory" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "memory" |); + make_list [ + make_tuple [ M.get_name (| globals, "memory_start_index" |); M.get_name (| globals, "size" |) ] + ] + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + BinOp.add (| + BinOp.add (| + M.get_name (| globals, "GAS_VERY_LOW" |), + M.get_name (| globals, "copy_gas_cost" |) + |), + M.get_field (| M.get_name (| globals, "extend_memory" |), "cost" |) + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "memory" |), + BinOp.mult (| + Constant.bytes "00", + M.get_field (| M.get_name (| globals, "extend_memory" |), "expand_by" |) + |) + |) in + let _ := M.assign_local (| + "value" , + M.call (| + M.get_name (| globals, "buffer_read" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "code" |); + M.get_name (| globals, "code_start_index" |); + M.get_name (| globals, "size" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "memory_write" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "memory" |); + M.get_name (| globals, "memory_start_index" |); + M.get_name (| globals, "value" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition gasprice : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Push the gas price used in current environment onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_BASE" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "env" |), "gas_price" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition extcodesize : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Push the code size of a given account onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "address" , + M.call (| + M.get_name (| globals, "to_address" |), + make_list [ + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.in_ (| + M.get_name (| globals, "address" |), + M.get_field (| M.get_name (| globals, "evm" |), "accessed_addresses" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_WARM_ACCESS" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "accessed_addresses" |), "add" |), + make_list [ + M.get_name (| globals, "address" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_COLD_ACCOUNT_ACCESS" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "codesize" , + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_field (| M.call (| + M.get_name (| globals, "get_account" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "env" |), "state" |); + M.get_name (| globals, "address" |) + ], + make_dict [] + |), "code" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.get_name (| globals, "codesize" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition extcodecopy : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Copy a portion of an account's code to memory. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "address" , + M.call (| + M.get_name (| globals, "to_address" |), + make_list [ + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_start_index" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "code_start_index" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "size" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "words" , + BinOp.floor_div (| + M.call (| + M.get_name (| globals, "ceil32" |), + make_list [ + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.get_name (| globals, "size" |) + ], + make_dict [] + |) + ], + make_dict [] + |), + Constant.int 32 + |) + |) in + let _ := M.assign_local (| + "copy_gas_cost" , + BinOp.mult (| + M.get_name (| globals, "GAS_COPY" |), + M.get_name (| globals, "words" |) + |) + |) in + let _ := M.assign_local (| + "extend_memory" , + M.call (| + M.get_name (| globals, "calculate_gas_extend_memory" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "memory" |); + make_list [ + make_tuple [ M.get_name (| globals, "memory_start_index" |); M.get_name (| globals, "size" |) ] + ] + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.in_ (| + M.get_name (| globals, "address" |), + M.get_field (| M.get_name (| globals, "evm" |), "accessed_addresses" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + BinOp.add (| + BinOp.add (| + M.get_name (| globals, "GAS_WARM_ACCESS" |), + M.get_name (| globals, "copy_gas_cost" |) + |), + M.get_field (| M.get_name (| globals, "extend_memory" |), "cost" |) + |) + ], + make_dict [] + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "accessed_addresses" |), "add" |), + make_list [ + M.get_name (| globals, "address" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + BinOp.add (| + BinOp.add (| + M.get_name (| globals, "GAS_COLD_ACCOUNT_ACCESS" |), + M.get_name (| globals, "copy_gas_cost" |) + |), + M.get_field (| M.get_name (| globals, "extend_memory" |), "cost" |) + |) + ], + make_dict [] + |) in + M.pure Constant.None_ + )) |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "memory" |), + BinOp.mult (| + Constant.bytes "00", + M.get_field (| M.get_name (| globals, "extend_memory" |), "expand_by" |) + |) + |) in + let _ := M.assign_local (| + "code" , + M.get_field (| M.call (| + M.get_name (| globals, "get_account" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "env" |), "state" |); + M.get_name (| globals, "address" |) + ], + make_dict [] + |), "code" |) + |) in + let _ := M.assign_local (| + "value" , + M.call (| + M.get_name (| globals, "buffer_read" |), + make_list [ + M.get_name (| globals, "code" |); + M.get_name (| globals, "code_start_index" |); + M.get_name (| globals, "size" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "memory_write" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "memory" |); + M.get_name (| globals, "memory_start_index" |); + M.get_name (| globals, "value" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition returndatasize : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Pushes the size of the return data buffer onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_BASE" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "return_data" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition returndatacopy : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Copies data from the return data buffer code to memory + + Parameters + ---------- + evm : + The current EVM frame. + " in + let _ := M.assign_local (| + "memory_start_index" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "return_data_start_position" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "size" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "words" , + BinOp.floor_div (| + M.call (| + M.get_name (| globals, "ceil32" |), + make_list [ + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.get_name (| globals, "size" |) + ], + make_dict [] + |) + ], + make_dict [] + |), + Constant.int 32 + |) + |) in + let _ := M.assign_local (| + "copy_gas_cost" , + BinOp.mult (| + M.get_name (| globals, "GAS_RETURN_DATA_COPY" |), + M.get_name (| globals, "words" |) + |) + |) in + let _ := M.assign_local (| + "extend_memory" , + M.call (| + M.get_name (| globals, "calculate_gas_extend_memory" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "memory" |); + make_list [ + make_tuple [ M.get_name (| globals, "memory_start_index" |); M.get_name (| globals, "size" |) ] + ] + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + BinOp.add (| + BinOp.add (| + M.get_name (| globals, "GAS_VERY_LOW" |), + M.get_name (| globals, "copy_gas_cost" |) + |), + M.get_field (| M.get_name (| globals, "extend_memory" |), "cost" |) + |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + Compare.lt_e (| + BinOp.add (| + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.get_name (| globals, "return_data_start_position" |) + ], + make_dict [] + |), + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.get_name (| globals, "size" |) + ], + make_dict [] + |) + |), + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "return_data" |) + ], + make_dict [] + |) + |); + M.get_name (| globals, "OutOfBoundsRead" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "memory" |), + BinOp.mult (| + Constant.bytes "00", + M.get_field (| M.get_name (| globals, "extend_memory" |), "expand_by" |) + |) + |) in + let _ := M.assign_local (| + "value" , + M.slice (| + M.get_field (| M.get_name (| globals, "evm" |), "return_data" |), + M.get_name (| globals, "return_data_start_position" |), + BinOp.add (| + M.get_name (| globals, "return_data_start_position" |), + M.get_name (| globals, "size" |) + |), + Constant.None_ + |) + |) in + let _ := M.call (| + M.get_name (| globals, "memory_write" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "memory" |); + M.get_name (| globals, "memory_start_index" |); + M.get_name (| globals, "value" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition extcodehash : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Returns the keccak256 hash of a contract’s bytecode + Parameters + ---------- + evm : + The current EVM frame. + " in + let _ := M.assign_local (| + "address" , + M.call (| + M.get_name (| globals, "to_address" |), + make_list [ + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.in_ (| + M.get_name (| globals, "address" |), + M.get_field (| M.get_name (| globals, "evm" |), "accessed_addresses" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_WARM_ACCESS" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "accessed_addresses" |), "add" |), + make_list [ + M.get_name (| globals, "address" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_COLD_ACCOUNT_ACCESS" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "account" , + M.call (| + M.get_name (| globals, "get_account" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "env" |), "state" |); + M.get_name (| globals, "address" |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, "account" |), + M.get_name (| globals, "EMPTY_ACCOUNT" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "codehash" , + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "codehash" , + M.call (| + M.get_field (| M.get_name (| globals, "U256" |), "from_be_bytes" |), + make_list [ + M.call (| + M.get_name (| globals, "keccak256" |), + make_list [ + M.get_field (| M.get_name (| globals, "account" |), "code" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + )) |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.get_name (| globals, "codehash" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition self_balance : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Pushes the balance of the current address to the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_FAST_STEP" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "balance" , + M.get_field (| M.call (| + M.get_name (| globals, "get_account" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "env" |), "state" |); + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "current_target" |) + ], + make_dict [] + |), "balance" |) + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.get_name (| globals, "balance" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition base_fee : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Pushes the base fee of the current block on to the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_BASE" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "env" |), "base_fee_per_gas" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). diff --git a/CoqOfPython/ethereum/paris/vm/instructions/keccak.v b/CoqOfPython/ethereum/paris/vm/instructions/keccak.v new file mode 100644 index 0000000..e935544 --- /dev/null +++ b/CoqOfPython/ethereum/paris/vm/instructions/keccak.v @@ -0,0 +1,188 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.paris.vm.instructions.keccak". + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) Keccak Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM keccak instructions. +". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". + +Axiom ethereum_crypto_hash_imports_keccak256 : + IsImported globals "ethereum.crypto.hash" "keccak256". + +Axiom ethereum_utils_numeric_imports_ceil32 : + IsImported globals "ethereum.utils.numeric" "ceil32". + +Axiom ethereum_paris_vm_imports_Evm : + IsImported globals "ethereum.paris.vm" "Evm". + +Axiom ethereum_paris_vm_gas_imports_GAS_KECCAK256 : + IsImported globals "ethereum.paris.vm.gas" "GAS_KECCAK256". +Axiom ethereum_paris_vm_gas_imports_GAS_KECCAK256_WORD : + IsImported globals "ethereum.paris.vm.gas" "GAS_KECCAK256_WORD". +Axiom ethereum_paris_vm_gas_imports_calculate_gas_extend_memory : + IsImported globals "ethereum.paris.vm.gas" "calculate_gas_extend_memory". +Axiom ethereum_paris_vm_gas_imports_charge_gas : + IsImported globals "ethereum.paris.vm.gas" "charge_gas". + +Axiom ethereum_paris_vm_memory_imports_memory_read_bytes : + IsImported globals "ethereum.paris.vm.memory" "memory_read_bytes". + +Axiom ethereum_paris_vm_stack_imports_pop : + IsImported globals "ethereum.paris.vm.stack" "pop". +Axiom ethereum_paris_vm_stack_imports_push : + IsImported globals "ethereum.paris.vm.stack" "push". + +Definition keccak : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Pushes to the stack the Keccak-256 hash of a region of memory. + + This also expands the memory, in case the memory is insufficient to + access the data's memory location. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "memory_start_index" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "size" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "words" , + BinOp.floor_div (| + M.call (| + M.get_name (| globals, "ceil32" |), + make_list [ + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.get_name (| globals, "size" |) + ], + make_dict [] + |) + ], + make_dict [] + |), + Constant.int 32 + |) + |) in + let _ := M.assign_local (| + "word_gas_cost" , + BinOp.mult (| + M.get_name (| globals, "GAS_KECCAK256_WORD" |), + M.get_name (| globals, "words" |) + |) + |) in + let _ := M.assign_local (| + "extend_memory" , + M.call (| + M.get_name (| globals, "calculate_gas_extend_memory" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "memory" |); + make_list [ + make_tuple [ M.get_name (| globals, "memory_start_index" |); M.get_name (| globals, "size" |) ] + ] + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + BinOp.add (| + BinOp.add (| + M.get_name (| globals, "GAS_KECCAK256" |), + M.get_name (| globals, "word_gas_cost" |) + |), + M.get_field (| M.get_name (| globals, "extend_memory" |), "cost" |) + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "memory" |), + BinOp.mult (| + Constant.bytes "00", + M.get_field (| M.get_name (| globals, "extend_memory" |), "expand_by" |) + |) + |) in + let _ := M.assign_local (| + "data" , + M.call (| + M.get_name (| globals, "memory_read_bytes" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "memory" |); + M.get_name (| globals, "memory_start_index" |); + M.get_name (| globals, "size" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "hash" , + M.call (| + M.get_name (| globals, "keccak256" |), + make_list [ + M.get_name (| globals, "data" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.call (| + M.get_field (| M.get_name (| globals, "U256" |), "from_be_bytes" |), + make_list [ + M.get_name (| globals, "hash" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). diff --git a/CoqOfPython/ethereum/paris/vm/instructions/log.v b/CoqOfPython/ethereum/paris/vm/instructions/log.v new file mode 100644 index 0000000..e38fab2 --- /dev/null +++ b/CoqOfPython/ethereum/paris/vm/instructions/log.v @@ -0,0 +1,256 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.paris.vm.instructions.log". + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) Logging Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM logging instructions. +". + +Axiom functools_imports_partial : + IsImported globals "functools" "partial". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". + +Axiom ethereum_utils_ensure_imports_ensure : + IsImported globals "ethereum.utils.ensure" "ensure". + +Axiom ethereum_paris_blocks_imports_Log : + IsImported globals "ethereum.paris.blocks" "Log". + +Axiom ethereum_paris_vm_imports_Evm : + IsImported globals "ethereum.paris.vm" "Evm". + +Axiom ethereum_paris_vm_exceptions_imports_WriteInStaticContext : + IsImported globals "ethereum.paris.vm.exceptions" "WriteInStaticContext". + +Axiom ethereum_paris_vm_gas_imports_GAS_LOG : + IsImported globals "ethereum.paris.vm.gas" "GAS_LOG". +Axiom ethereum_paris_vm_gas_imports_GAS_LOG_DATA : + IsImported globals "ethereum.paris.vm.gas" "GAS_LOG_DATA". +Axiom ethereum_paris_vm_gas_imports_GAS_LOG_TOPIC : + IsImported globals "ethereum.paris.vm.gas" "GAS_LOG_TOPIC". +Axiom ethereum_paris_vm_gas_imports_calculate_gas_extend_memory : + IsImported globals "ethereum.paris.vm.gas" "calculate_gas_extend_memory". +Axiom ethereum_paris_vm_gas_imports_charge_gas : + IsImported globals "ethereum.paris.vm.gas" "charge_gas". + +Axiom ethereum_paris_vm_memory_imports_memory_read_bytes : + IsImported globals "ethereum.paris.vm.memory" "memory_read_bytes". + +Axiom ethereum_paris_vm_stack_imports_pop : + IsImported globals "ethereum.paris.vm.stack" "pop". + +Definition log_n : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm"; "num_topics" ] |) in + let _ := Constant.str " + Appends a log entry, having `num_topics` topics, to the evm logs. + + This will also expand the memory if the data (required by the log entry) + corresponding to the memory is not accessible. + + Parameters + ---------- + evm : + The current EVM frame. + num_topics : + The number of topics to be included in the log entry. + + " in + let _ := M.assign_local (| + "memory_start_index" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "size" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "topics" , + make_list [] + |) in + let _ := + M.for_ (| + M.get_name (| globals, "_" |), + M.call (| + M.get_name (| globals, "range" |), + make_list [ + M.get_name (| globals, "num_topics" |) + ], + make_dict [] + |), + ltac:(M.monadic ( + let _ := M.assign_local (| + "topic" , + M.call (| + M.get_field (| M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |), "to_be_bytes32" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_field (| M.get_name (| globals, "topics" |), "append" |), + make_list [ + M.get_name (| globals, "topic" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := M.assign_local (| + "extend_memory" , + M.call (| + M.get_name (| globals, "calculate_gas_extend_memory" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "memory" |); + make_list [ + make_tuple [ M.get_name (| globals, "memory_start_index" |); M.get_name (| globals, "size" |) ] + ] + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + BinOp.add (| + BinOp.add (| + BinOp.add (| + M.get_name (| globals, "GAS_LOG" |), + BinOp.mult (| + M.get_name (| globals, "GAS_LOG_DATA" |), + M.get_name (| globals, "size" |) + |) + |), + BinOp.mult (| + M.get_name (| globals, "GAS_LOG_TOPIC" |), + M.get_name (| globals, "num_topics" |) + |) + |), + M.get_field (| M.get_name (| globals, "extend_memory" |), "cost" |) + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "memory" |), + BinOp.mult (| + Constant.bytes "00", + M.get_field (| M.get_name (| globals, "extend_memory" |), "expand_by" |) + |) + |) in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + UnOp.not (| M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "is_static" |) |); + M.get_name (| globals, "WriteInStaticContext" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "log_entry" , + M.call (| + M.get_name (| globals, "Log" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, "evm" |), "logs" |), + BinOp.add (| + M.get_field (| M.get_name (| globals, "evm" |), "logs" |), + make_tuple [ M.get_name (| globals, "log_entry" |) ] + |) + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition log0 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "log_n" |) + ], + make_dict [] + |) +)). + +Definition log1 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "log_n" |) + ], + make_dict [] + |) +)). + +Definition log2 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "log_n" |) + ], + make_dict [] + |) +)). + +Definition log3 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "log_n" |) + ], + make_dict [] + |) +)). + +Definition log4 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "log_n" |) + ], + make_dict [] + |) +)). diff --git a/CoqOfPython/ethereum/paris/vm/instructions/memory.v b/CoqOfPython/ethereum/paris/vm/instructions/memory.v new file mode 100644 index 0000000..211fafb --- /dev/null +++ b/CoqOfPython/ethereum/paris/vm/instructions/memory.v @@ -0,0 +1,393 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.paris.vm.instructions.memory". + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) Memory Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM Memory instructions. +". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_Bytes : + IsImported globals "ethereum.base_types" "Bytes". + +Axiom ethereum_paris_vm_imports_Evm : + IsImported globals "ethereum.paris.vm" "Evm". + +Axiom ethereum_paris_vm_gas_imports_GAS_BASE : + IsImported globals "ethereum.paris.vm.gas" "GAS_BASE". +Axiom ethereum_paris_vm_gas_imports_GAS_VERY_LOW : + IsImported globals "ethereum.paris.vm.gas" "GAS_VERY_LOW". +Axiom ethereum_paris_vm_gas_imports_calculate_gas_extend_memory : + IsImported globals "ethereum.paris.vm.gas" "calculate_gas_extend_memory". +Axiom ethereum_paris_vm_gas_imports_charge_gas : + IsImported globals "ethereum.paris.vm.gas" "charge_gas". + +Axiom ethereum_paris_vm_memory_imports_memory_read_bytes : + IsImported globals "ethereum.paris.vm.memory" "memory_read_bytes". +Axiom ethereum_paris_vm_memory_imports_memory_write : + IsImported globals "ethereum.paris.vm.memory" "memory_write". + +Axiom ethereum_paris_vm_stack_imports_pop : + IsImported globals "ethereum.paris.vm.stack" "pop". +Axiom ethereum_paris_vm_stack_imports_push : + IsImported globals "ethereum.paris.vm.stack" "push". + +Definition mstore : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Stores a word to memory. + This also expands the memory, if the memory is + insufficient to store the word. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "start_position" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "value" , + M.call (| + M.get_field (| M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |), "to_be_bytes32" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "extend_memory" , + M.call (| + M.get_name (| globals, "calculate_gas_extend_memory" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "memory" |); + make_list [ + make_tuple [ M.get_name (| globals, "start_position" |); M.call (| + M.get_name (| globals, "U256" |), + make_list [ + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_name (| globals, "value" |) + ], + make_dict [] + |) + ], + make_dict [] + |) ] + ] + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + BinOp.add (| + M.get_name (| globals, "GAS_VERY_LOW" |), + M.get_field (| M.get_name (| globals, "extend_memory" |), "cost" |) + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "memory" |), + BinOp.mult (| + Constant.bytes "00", + M.get_field (| M.get_name (| globals, "extend_memory" |), "expand_by" |) + |) + |) in + let _ := M.call (| + M.get_name (| globals, "memory_write" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "memory" |); + M.get_name (| globals, "start_position" |); + M.get_name (| globals, "value" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition mstore8 : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Stores a byte to memory. + This also expands the memory, if the memory is + insufficient to store the word. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "start_position" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "value" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "extend_memory" , + M.call (| + M.get_name (| globals, "calculate_gas_extend_memory" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "memory" |); + make_list [ + make_tuple [ M.get_name (| globals, "start_position" |); M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 1 + ], + make_dict [] + |) ] + ] + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + BinOp.add (| + M.get_name (| globals, "GAS_VERY_LOW" |), + M.get_field (| M.get_name (| globals, "extend_memory" |), "cost" |) + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "memory" |), + BinOp.mult (| + Constant.bytes "00", + M.get_field (| M.get_name (| globals, "extend_memory" |), "expand_by" |) + |) + |) in + let _ := M.assign_local (| + "normalized_bytes_value" , + M.call (| + M.get_name (| globals, "Bytes" |), + make_list [ + make_list [ + BinOp.bit_and (| + M.get_name (| globals, "value" |), + Constant.int 255 + |) + ] + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "memory_write" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "memory" |); + M.get_name (| globals, "start_position" |); + M.get_name (| globals, "normalized_bytes_value" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition mload : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Load word from memory. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "start_position" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "extend_memory" , + M.call (| + M.get_name (| globals, "calculate_gas_extend_memory" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "memory" |); + make_list [ + make_tuple [ M.get_name (| globals, "start_position" |); M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 32 + ], + make_dict [] + |) ] + ] + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + BinOp.add (| + M.get_name (| globals, "GAS_VERY_LOW" |), + M.get_field (| M.get_name (| globals, "extend_memory" |), "cost" |) + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "memory" |), + BinOp.mult (| + Constant.bytes "00", + M.get_field (| M.get_name (| globals, "extend_memory" |), "expand_by" |) + |) + |) in + let _ := M.assign_local (| + "value" , + M.call (| + M.get_field (| M.get_name (| globals, "U256" |), "from_be_bytes" |), + make_list [ + M.call (| + M.get_name (| globals, "memory_read_bytes" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "memory" |); + M.get_name (| globals, "start_position" |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 32 + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.get_name (| globals, "value" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition msize : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Push the size of active memory in bytes onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_BASE" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "memory" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). diff --git a/CoqOfPython/ethereum/paris/vm/instructions/stack.v b/CoqOfPython/ethereum/paris/vm/instructions/stack.v new file mode 100644 index 0000000..7c6a4bf --- /dev/null +++ b/CoqOfPython/ethereum/paris/vm/instructions/stack.v @@ -0,0 +1,947 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.paris.vm.instructions.stack". + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) Stack Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM stack related instructions. +". + +Axiom functools_imports_partial : + IsImported globals "functools" "partial". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". + +Axiom ethereum_utils_ensure_imports_ensure : + IsImported globals "ethereum.utils.ensure" "ensure". + +Axiom ethereum_paris_vm_imports_Evm : + IsImported globals "ethereum.paris.vm" "Evm". +Axiom ethereum_paris_vm_imports_stack : + IsImported globals "ethereum.paris.vm" "stack". + +Axiom ethereum_paris_vm_exceptions_imports_StackUnderflowError : + IsImported globals "ethereum.paris.vm.exceptions" "StackUnderflowError". + +Axiom ethereum_paris_vm_gas_imports_GAS_BASE : + IsImported globals "ethereum.paris.vm.gas" "GAS_BASE". +Axiom ethereum_paris_vm_gas_imports_GAS_VERY_LOW : + IsImported globals "ethereum.paris.vm.gas" "GAS_VERY_LOW". +Axiom ethereum_paris_vm_gas_imports_charge_gas : + IsImported globals "ethereum.paris.vm.gas" "charge_gas". + +Axiom ethereum_paris_vm_memory_imports_buffer_read : + IsImported globals "ethereum.paris.vm.memory" "buffer_read". + +Definition pop : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Remove item from stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.call (| + M.get_field (| M.get_name (| globals, "stack" |), "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_BASE" |) + ], + make_dict [] + |) in + let _ := M.pass (| |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition push_n : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm"; "num_bytes" ] |) in + let _ := Constant.str " + Pushes a N-byte immediate onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + num_bytes : + The number of immediate bytes to be read from the code and pushed to + the stack. + + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_VERY_LOW" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "data_to_push" , + M.call (| + M.get_field (| M.get_name (| globals, "U256" |), "from_be_bytes" |), + make_list [ + M.call (| + M.get_name (| globals, "buffer_read" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "code" |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + BinOp.add (| + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) + ], + make_dict [] + |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + M.get_name (| globals, "num_bytes" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_field (| M.get_name (| globals, "stack" |), "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.get_name (| globals, "data_to_push" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + BinOp.add (| + Constant.int 1, + M.get_name (| globals, "num_bytes" |) + |) + |) in + M.pure Constant.None_)). + +Definition dup_n : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm"; "item_number" ] |) in + let _ := Constant.str " + Duplicate the Nth stack item (from top of the stack) to the top of stack. + + Parameters + ---------- + evm : + The current EVM frame. + + item_number : + The stack item number (0-indexed from top of stack) to be duplicated + to the top of stack. + + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_VERY_LOW" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + Compare.lt (| + M.get_name (| globals, "item_number" |), + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |); + M.get_name (| globals, "StackUnderflowError" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "data_to_duplicate" , + M.get_subscript (| + M.get_field (| M.get_name (| globals, "evm" |), "stack" |), + BinOp.sub (| + BinOp.sub (| + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |), + Constant.int 1 + |), + M.get_name (| globals, "item_number" |) + |) + |) + |) in + let _ := M.call (| + M.get_field (| M.get_name (| globals, "stack" |), "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.get_name (| globals, "data_to_duplicate" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition swap_n : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm"; "item_number" ] |) in + let _ := Constant.str " + Swap the top and the `item_number` element of the stack, where + the top of the stack is position zero. + + If `item_number` is zero, this function does nothing (which should not be + possible, since there is no `SWAP0` instruction). + + Parameters + ---------- + evm : + The current EVM frame. + + item_number : + The stack item number (0-indexed from top of stack) to be swapped + with the top of stack element. + + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_VERY_LOW" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + Compare.lt (| + M.get_name (| globals, "item_number" |), + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |); + M.get_name (| globals, "StackUnderflowError" |) + ], + make_dict [] + |) in + let _ := M.assign (| + make_tuple [ M.get_subscript (| + M.get_field (| M.get_name (| globals, "evm" |), "stack" |), + UnOp.sub (| Constant.int 1 |) + |); M.get_subscript (| + M.get_field (| M.get_name (| globals, "evm" |), "stack" |), + BinOp.sub (| + UnOp.sub (| Constant.int 1 |), + M.get_name (| globals, "item_number" |) + |) + |) ], + make_tuple [ M.get_subscript (| + M.get_field (| M.get_name (| globals, "evm" |), "stack" |), + BinOp.sub (| + UnOp.sub (| Constant.int 1 |), + M.get_name (| globals, "item_number" |) + |) + |); M.get_subscript (| + M.get_field (| M.get_name (| globals, "evm" |), "stack" |), + UnOp.sub (| Constant.int 1 |) + |) ] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition push1 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push2 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push3 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push4 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push5 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push6 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push7 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push8 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push9 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push10 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push11 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push12 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push13 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push14 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push15 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push16 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push17 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push18 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push19 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push20 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push21 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push22 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push23 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push24 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push25 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push26 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push27 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push28 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push29 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push30 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push31 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push32 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "push_n" |) + ], + make_dict [] + |) +)). + +Definition dup1 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "dup_n" |) + ], + make_dict [] + |) +)). + +Definition dup2 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "dup_n" |) + ], + make_dict [] + |) +)). + +Definition dup3 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "dup_n" |) + ], + make_dict [] + |) +)). + +Definition dup4 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "dup_n" |) + ], + make_dict [] + |) +)). + +Definition dup5 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "dup_n" |) + ], + make_dict [] + |) +)). + +Definition dup6 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "dup_n" |) + ], + make_dict [] + |) +)). + +Definition dup7 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "dup_n" |) + ], + make_dict [] + |) +)). + +Definition dup8 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "dup_n" |) + ], + make_dict [] + |) +)). + +Definition dup9 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "dup_n" |) + ], + make_dict [] + |) +)). + +Definition dup10 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "dup_n" |) + ], + make_dict [] + |) +)). + +Definition dup11 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "dup_n" |) + ], + make_dict [] + |) +)). + +Definition dup12 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "dup_n" |) + ], + make_dict [] + |) +)). + +Definition dup13 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "dup_n" |) + ], + make_dict [] + |) +)). + +Definition dup14 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "dup_n" |) + ], + make_dict [] + |) +)). + +Definition dup15 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "dup_n" |) + ], + make_dict [] + |) +)). + +Definition dup16 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "dup_n" |) + ], + make_dict [] + |) +)). + +Definition swap1 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "swap_n" |) + ], + make_dict [] + |) +)). + +Definition swap2 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "swap_n" |) + ], + make_dict [] + |) +)). + +Definition swap3 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "swap_n" |) + ], + make_dict [] + |) +)). + +Definition swap4 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "swap_n" |) + ], + make_dict [] + |) +)). + +Definition swap5 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "swap_n" |) + ], + make_dict [] + |) +)). + +Definition swap6 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "swap_n" |) + ], + make_dict [] + |) +)). + +Definition swap7 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "swap_n" |) + ], + make_dict [] + |) +)). + +Definition swap8 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "swap_n" |) + ], + make_dict [] + |) +)). + +Definition swap9 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "swap_n" |) + ], + make_dict [] + |) +)). + +Definition swap10 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "swap_n" |) + ], + make_dict [] + |) +)). + +Definition swap11 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "swap_n" |) + ], + make_dict [] + |) +)). + +Definition swap12 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "swap_n" |) + ], + make_dict [] + |) +)). + +Definition swap13 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "swap_n" |) + ], + make_dict [] + |) +)). + +Definition swap14 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "swap_n" |) + ], + make_dict [] + |) +)). + +Definition swap15 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "swap_n" |) + ], + make_dict [] + |) +)). + +Definition swap16 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "swap_n" |) + ], + make_dict [] + |) +)). diff --git a/CoqOfPython/ethereum/paris/vm/instructions/storage.v b/CoqOfPython/ethereum/paris/vm/instructions/storage.v new file mode 100644 index 0000000..760b3c6 --- /dev/null +++ b/CoqOfPython/ethereum/paris/vm/instructions/storage.v @@ -0,0 +1,491 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.paris.vm.instructions.storage". + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) Storage Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM storage related instructions. +". + +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". + +Axiom ethereum_utils_ensure_imports_ensure : + IsImported globals "ethereum.utils.ensure" "ensure". + +Axiom ethereum_paris_state_imports_get_storage : + IsImported globals "ethereum.paris.state" "get_storage". +Axiom ethereum_paris_state_imports_get_storage_original : + IsImported globals "ethereum.paris.state" "get_storage_original". +Axiom ethereum_paris_state_imports_set_storage : + IsImported globals "ethereum.paris.state" "set_storage". + +Axiom ethereum_paris_vm_imports_Evm : + IsImported globals "ethereum.paris.vm" "Evm". + +Axiom ethereum_paris_vm_exceptions_imports_OutOfGasError : + IsImported globals "ethereum.paris.vm.exceptions" "OutOfGasError". +Axiom ethereum_paris_vm_exceptions_imports_WriteInStaticContext : + IsImported globals "ethereum.paris.vm.exceptions" "WriteInStaticContext". + +Axiom ethereum_paris_vm_gas_imports_GAS_CALL_STIPEND : + IsImported globals "ethereum.paris.vm.gas" "GAS_CALL_STIPEND". +Axiom ethereum_paris_vm_gas_imports_GAS_COLD_SLOAD : + IsImported globals "ethereum.paris.vm.gas" "GAS_COLD_SLOAD". +Axiom ethereum_paris_vm_gas_imports_GAS_STORAGE_CLEAR_REFUND : + IsImported globals "ethereum.paris.vm.gas" "GAS_STORAGE_CLEAR_REFUND". +Axiom ethereum_paris_vm_gas_imports_GAS_STORAGE_SET : + IsImported globals "ethereum.paris.vm.gas" "GAS_STORAGE_SET". +Axiom ethereum_paris_vm_gas_imports_GAS_STORAGE_UPDATE : + IsImported globals "ethereum.paris.vm.gas" "GAS_STORAGE_UPDATE". +Axiom ethereum_paris_vm_gas_imports_GAS_WARM_ACCESS : + IsImported globals "ethereum.paris.vm.gas" "GAS_WARM_ACCESS". +Axiom ethereum_paris_vm_gas_imports_charge_gas : + IsImported globals "ethereum.paris.vm.gas" "charge_gas". + +Axiom ethereum_paris_vm_stack_imports_pop : + IsImported globals "ethereum.paris.vm.stack" "pop". +Axiom ethereum_paris_vm_stack_imports_push : + IsImported globals "ethereum.paris.vm.stack" "push". + +Definition sload : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Loads to the stack, the value corresponding to a certain key from the + storage of the current account. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "key" , + M.call (| + M.get_field (| M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |), "to_be_bytes32" |), + make_list [], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.in_ (| + make_tuple [ M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "current_target" |); M.get_name (| globals, "key" |) ], + M.get_field (| M.get_name (| globals, "evm" |), "accessed_storage_keys" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_WARM_ACCESS" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "accessed_storage_keys" |), "add" |), + make_list [ + make_tuple [ M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "current_target" |); M.get_name (| globals, "key" |) ] + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_COLD_SLOAD" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "value" , + M.call (| + M.get_name (| globals, "get_storage" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "env" |), "state" |); + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "current_target" |); + M.get_name (| globals, "key" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.get_name (| globals, "value" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition sstore : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Stores a value at a certain key in the current context's storage. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "key" , + M.call (| + M.get_field (| M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |), "to_be_bytes32" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "new_value" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + Compare.gt (| + M.get_field (| M.get_name (| globals, "evm" |), "gas_left" |), + M.get_name (| globals, "GAS_CALL_STIPEND" |) + |); + M.get_name (| globals, "OutOfGasError" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "original_value" , + M.call (| + M.get_name (| globals, "get_storage_original" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "env" |), "state" |); + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "current_target" |); + M.get_name (| globals, "key" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "current_value" , + M.call (| + M.get_name (| globals, "get_storage" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "env" |), "state" |); + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "current_target" |); + M.get_name (| globals, "key" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "gas_cost" , + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.not_in (| + make_tuple [ M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "current_target" |); M.get_name (| globals, "key" |) ], + M.get_field (| M.get_name (| globals, "evm" |), "accessed_storage_keys" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "accessed_storage_keys" |), "add" |), + make_list [ + make_tuple [ M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "current_target" |); M.get_name (| globals, "key" |) ] + ], + make_dict [] + |) in + let _ := M.assign_op_local (| + BinOp.add, + "gas_cost", + M.get_name (| globals, "GAS_COLD_SLOAD" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + BoolOp.and (| + Compare.eq (| + M.get_name (| globals, "original_value" |), + M.get_name (| globals, "current_value" |) + |), + ltac:(M.monadic ( + Compare.not_eq (| + M.get_name (| globals, "current_value" |), + M.get_name (| globals, "new_value" |) + |) + )) + |), + (* then *) + ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, "original_value" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_op_local (| + BinOp.add, + "gas_cost", + M.get_name (| globals, "GAS_STORAGE_SET" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_op_local (| + BinOp.add, + "gas_cost", + BinOp.sub (| + M.get_name (| globals, "GAS_STORAGE_UPDATE" |), + M.get_name (| globals, "GAS_COLD_SLOAD" |) + |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_op_local (| + BinOp.add, + "gas_cost", + M.get_name (| globals, "GAS_WARM_ACCESS" |) + |) in + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + Compare.not_eq (| + M.get_name (| globals, "current_value" |), + M.get_name (| globals, "new_value" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + BoolOp.and (| + Compare.not_eq (| + M.get_name (| globals, "original_value" |), + Constant.int 0 + |), + ltac:(M.monadic ( + BoolOp.and (| + Compare.not_eq (| + M.get_name (| globals, "current_value" |), + Constant.int 0 + |), + ltac:(M.monadic ( + Compare.eq (| + M.get_name (| globals, "new_value" |), + Constant.int 0 + |) + )) + |) + )) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "refund_counter" |), + M.call (| + M.get_name (| globals, "int" |), + make_list [ + M.get_name (| globals, "GAS_STORAGE_CLEAR_REFUND" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + BoolOp.and (| + Compare.not_eq (| + M.get_name (| globals, "original_value" |), + Constant.int 0 + |), + ltac:(M.monadic ( + Compare.eq (| + M.get_name (| globals, "current_value" |), + Constant.int 0 + |) + )) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_op (| + BinOp.sub, + M.get_field (| M.get_name (| globals, "evm" |), "refund_counter" |), + M.call (| + M.get_name (| globals, "int" |), + make_list [ + M.get_name (| globals, "GAS_STORAGE_CLEAR_REFUND" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, "original_value" |), + M.get_name (| globals, "new_value" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, "original_value" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "refund_counter" |), + M.call (| + M.get_name (| globals, "int" |), + make_list [ + BinOp.sub (| + M.get_name (| globals, "GAS_STORAGE_SET" |), + M.get_name (| globals, "GAS_WARM_ACCESS" |) + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "refund_counter" |), + M.call (| + M.get_name (| globals, "int" |), + make_list [ + BinOp.sub (| + BinOp.sub (| + M.get_name (| globals, "GAS_STORAGE_UPDATE" |), + M.get_name (| globals, "GAS_COLD_SLOAD" |) + |), + M.get_name (| globals, "GAS_WARM_ACCESS" |) + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "gas_cost" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + UnOp.not (| M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "is_static" |) |); + M.get_name (| globals, "WriteInStaticContext" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "set_storage" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "env" |), "state" |); + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "current_target" |); + M.get_name (| globals, "key" |); + M.get_name (| globals, "new_value" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). diff --git a/CoqOfPython/ethereum/paris/vm/instructions/system.v b/CoqOfPython/ethereum/paris/vm/instructions/system.v new file mode 100644 index 0000000..2ed4520 --- /dev/null +++ b/CoqOfPython/ethereum/paris/vm/instructions/system.v @@ -0,0 +1,2215 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.paris.vm.instructions.system". + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) System Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM system related instructions. +". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_Bytes0 : + IsImported globals "ethereum.base_types" "Bytes0". +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". + +Axiom ethereum_utils_ensure_imports_ensure : + IsImported globals "ethereum.utils.ensure" "ensure". + +Axiom ethereum_utils_numeric_imports_ceil32 : + IsImported globals "ethereum.utils.numeric" "ceil32". + +Axiom ethereum_paris_fork_types_imports_Address : + IsImported globals "ethereum.paris.fork_types" "Address". + +Axiom ethereum_paris_state_imports_account_exists_and_is_empty : + IsImported globals "ethereum.paris.state" "account_exists_and_is_empty". +Axiom ethereum_paris_state_imports_account_has_code_or_nonce : + IsImported globals "ethereum.paris.state" "account_has_code_or_nonce". +Axiom ethereum_paris_state_imports_get_account : + IsImported globals "ethereum.paris.state" "get_account". +Axiom ethereum_paris_state_imports_increment_nonce : + IsImported globals "ethereum.paris.state" "increment_nonce". +Axiom ethereum_paris_state_imports_is_account_alive : + IsImported globals "ethereum.paris.state" "is_account_alive". +Axiom ethereum_paris_state_imports_set_account_balance : + IsImported globals "ethereum.paris.state" "set_account_balance". + +Axiom ethereum_paris_utils_address_imports_compute_contract_address : + IsImported globals "ethereum.paris.utils.address" "compute_contract_address". +Axiom ethereum_paris_utils_address_imports_compute_create2_contract_address : + IsImported globals "ethereum.paris.utils.address" "compute_create2_contract_address". +Axiom ethereum_paris_utils_address_imports_to_address : + IsImported globals "ethereum.paris.utils.address" "to_address". + +Axiom ethereum_paris_vm_imports_Evm : + IsImported globals "ethereum.paris.vm" "Evm". +Axiom ethereum_paris_vm_imports_Message : + IsImported globals "ethereum.paris.vm" "Message". +Axiom ethereum_paris_vm_imports_incorporate_child_on_error : + IsImported globals "ethereum.paris.vm" "incorporate_child_on_error". +Axiom ethereum_paris_vm_imports_incorporate_child_on_success : + IsImported globals "ethereum.paris.vm" "incorporate_child_on_success". + +Axiom ethereum_paris_vm_exceptions_imports_Revert : + IsImported globals "ethereum.paris.vm.exceptions" "Revert". +Axiom ethereum_paris_vm_exceptions_imports_WriteInStaticContext : + IsImported globals "ethereum.paris.vm.exceptions" "WriteInStaticContext". + +Axiom ethereum_paris_vm_gas_imports_GAS_CALL_VALUE : + IsImported globals "ethereum.paris.vm.gas" "GAS_CALL_VALUE". +Axiom ethereum_paris_vm_gas_imports_GAS_COLD_ACCOUNT_ACCESS : + IsImported globals "ethereum.paris.vm.gas" "GAS_COLD_ACCOUNT_ACCESS". +Axiom ethereum_paris_vm_gas_imports_GAS_CREATE : + IsImported globals "ethereum.paris.vm.gas" "GAS_CREATE". +Axiom ethereum_paris_vm_gas_imports_GAS_KECCAK256_WORD : + IsImported globals "ethereum.paris.vm.gas" "GAS_KECCAK256_WORD". +Axiom ethereum_paris_vm_gas_imports_GAS_NEW_ACCOUNT : + IsImported globals "ethereum.paris.vm.gas" "GAS_NEW_ACCOUNT". +Axiom ethereum_paris_vm_gas_imports_GAS_SELF_DESTRUCT : + IsImported globals "ethereum.paris.vm.gas" "GAS_SELF_DESTRUCT". +Axiom ethereum_paris_vm_gas_imports_GAS_SELF_DESTRUCT_NEW_ACCOUNT : + IsImported globals "ethereum.paris.vm.gas" "GAS_SELF_DESTRUCT_NEW_ACCOUNT". +Axiom ethereum_paris_vm_gas_imports_GAS_WARM_ACCESS : + IsImported globals "ethereum.paris.vm.gas" "GAS_WARM_ACCESS". +Axiom ethereum_paris_vm_gas_imports_GAS_ZERO : + IsImported globals "ethereum.paris.vm.gas" "GAS_ZERO". +Axiom ethereum_paris_vm_gas_imports_calculate_gas_extend_memory : + IsImported globals "ethereum.paris.vm.gas" "calculate_gas_extend_memory". +Axiom ethereum_paris_vm_gas_imports_calculate_message_call_gas : + IsImported globals "ethereum.paris.vm.gas" "calculate_message_call_gas". +Axiom ethereum_paris_vm_gas_imports_charge_gas : + IsImported globals "ethereum.paris.vm.gas" "charge_gas". +Axiom ethereum_paris_vm_gas_imports_max_message_call_gas : + IsImported globals "ethereum.paris.vm.gas" "max_message_call_gas". + +Axiom ethereum_paris_vm_memory_imports_memory_read_bytes : + IsImported globals "ethereum.paris.vm.memory" "memory_read_bytes". +Axiom ethereum_paris_vm_memory_imports_memory_write : + IsImported globals "ethereum.paris.vm.memory" "memory_write". + +Axiom ethereum_paris_vm_stack_imports_pop : + IsImported globals "ethereum.paris.vm.stack" "pop". +Axiom ethereum_paris_vm_stack_imports_push : + IsImported globals "ethereum.paris.vm.stack" "push". + +Definition generic_create : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm"; "endowment"; "contract_address"; "memory_start_position"; "memory_size" ] |) in + let _ := Constant.str " + Core logic used by the `CREATE*` family of opcodes. + " in +(* At stmt: unsupported node type: ImportFrom *) + let _ := M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "accessed_addresses" |), "add" |), + make_list [ + M.get_name (| globals, "contract_address" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "create_message_gas" , + M.call (| + M.get_name (| globals, "max_message_call_gas" |), + make_list [ + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "gas_left" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_op (| + BinOp.sub, + M.get_field (| M.get_name (| globals, "evm" |), "gas_left" |), + M.get_name (| globals, "create_message_gas" |) + |) in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + UnOp.not (| M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "is_static" |) |); + M.get_name (| globals, "WriteInStaticContext" |) + ], + make_dict [] + |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, "evm" |), "return_data" |), + Constant.bytes "" + |) in + let _ := M.assign_local (| + "sender_address" , + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "current_target" |) + |) in + let _ := M.assign_local (| + "sender" , + M.call (| + M.get_name (| globals, "get_account" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "env" |), "state" |); + M.get_name (| globals, "sender_address" |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + BoolOp.or (| + Compare.lt (| + M.get_field (| M.get_name (| globals, "sender" |), "balance" |), + M.get_name (| globals, "endowment" |) + |), + ltac:(M.monadic ( + BoolOp.or (| + Compare.eq (| + M.get_field (| M.get_name (| globals, "sender" |), "nonce" |), + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + BinOp.sub (| + BinOp.pow (| + Constant.int 2, + Constant.int 64 + |), + Constant.int 1 + |) + ], + make_dict [] + |) + |), + ltac:(M.monadic ( + Compare.gt (| + BinOp.add (| + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "depth" |), + Constant.int 1 + |), + M.get_name (| globals, "STACK_DEPTH_LIMIT" |) + |) + )) + |) + )) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "gas_left" |), + M.get_name (| globals, "create_message_gas" |) + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.return_ (| + Constant.None_ + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, "account_has_code_or_nonce" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "env" |), "state" |); + M.get_name (| globals, "contract_address" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, "increment_nonce" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "env" |), "state" |); + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "current_target" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.return_ (| + Constant.None_ + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "call_data" , + M.call (| + M.get_name (| globals, "memory_read_bytes" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "memory" |); + M.get_name (| globals, "memory_start_position" |); + M.get_name (| globals, "memory_size" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "increment_nonce" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "env" |), "state" |); + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "current_target" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "child_message" , + M.call (| + M.get_name (| globals, "Message" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "child_evm" , + M.call (| + M.get_name (| globals, "process_create_message" |), + make_list [ + M.get_name (| globals, "child_message" |); + M.get_field (| M.get_name (| globals, "evm" |), "env" |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + M.get_field (| M.get_name (| globals, "child_evm" |), "error" |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, "incorporate_child_on_error" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "child_evm" |) + ], + make_dict [] + |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, "evm" |), "return_data" |), + M.get_field (| M.get_name (| globals, "child_evm" |), "output" |) + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + ], + make_dict [] + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, "incorporate_child_on_success" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "child_evm" |) + ], + make_dict [] + |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, "evm" |), "return_data" |), + Constant.bytes "" + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.call (| + M.get_field (| M.get_name (| globals, "U256" |), "from_be_bytes" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "child_evm" |), "message" |), "current_target" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_)). + +Definition create : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Creates a new account with associated code. + + Parameters + ---------- + evm : + The current EVM frame. + " in + let _ := M.assign_local (| + "endowment" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_start_position" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_size" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "extend_memory" , + M.call (| + M.get_name (| globals, "calculate_gas_extend_memory" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "memory" |); + make_list [ + make_tuple [ M.get_name (| globals, "memory_start_position" |); M.get_name (| globals, "memory_size" |) ] + ] + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + BinOp.add (| + M.get_name (| globals, "GAS_CREATE" |), + M.get_field (| M.get_name (| globals, "extend_memory" |), "cost" |) + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "memory" |), + BinOp.mult (| + Constant.bytes "00", + M.get_field (| M.get_name (| globals, "extend_memory" |), "expand_by" |) + |) + |) in + let _ := M.assign_local (| + "contract_address" , + M.call (| + M.get_name (| globals, "compute_contract_address" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "current_target" |); + M.get_field (| M.call (| + M.get_name (| globals, "get_account" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "env" |), "state" |); + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "current_target" |) + ], + make_dict [] + |), "nonce" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "generic_create" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "endowment" |); + M.get_name (| globals, "contract_address" |); + M.get_name (| globals, "memory_start_position" |); + M.get_name (| globals, "memory_size" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition create2 : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Creates a new account with associated code. + + It's similar to CREATE opcode except that the address of new account + depends on the init_code instead of the nonce of sender. + + Parameters + ---------- + evm : + The current EVM frame. + " in + let _ := M.assign_local (| + "endowment" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_start_position" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_size" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "salt" , + M.call (| + M.get_field (| M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |), "to_be_bytes32" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "extend_memory" , + M.call (| + M.get_name (| globals, "calculate_gas_extend_memory" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "memory" |); + make_list [ + make_tuple [ M.get_name (| globals, "memory_start_position" |); M.get_name (| globals, "memory_size" |) ] + ] + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "call_data_words" , + BinOp.floor_div (| + M.call (| + M.get_name (| globals, "ceil32" |), + make_list [ + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.get_name (| globals, "memory_size" |) + ], + make_dict [] + |) + ], + make_dict [] + |), + Constant.int 32 + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + BinOp.add (| + BinOp.add (| + M.get_name (| globals, "GAS_CREATE" |), + BinOp.mult (| + M.get_name (| globals, "GAS_KECCAK256_WORD" |), + M.get_name (| globals, "call_data_words" |) + |) + |), + M.get_field (| M.get_name (| globals, "extend_memory" |), "cost" |) + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "memory" |), + BinOp.mult (| + Constant.bytes "00", + M.get_field (| M.get_name (| globals, "extend_memory" |), "expand_by" |) + |) + |) in + let _ := M.assign_local (| + "contract_address" , + M.call (| + M.get_name (| globals, "compute_create2_contract_address" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "current_target" |); + M.get_name (| globals, "salt" |); + M.call (| + M.get_name (| globals, "memory_read_bytes" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "memory" |); + M.get_name (| globals, "memory_start_position" |); + M.get_name (| globals, "memory_size" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "generic_create" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "endowment" |); + M.get_name (| globals, "contract_address" |); + M.get_name (| globals, "memory_start_position" |); + M.get_name (| globals, "memory_size" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition return_ : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Halts execution returning output data. + + Parameters + ---------- + evm : + The current EVM frame. + " in + let _ := M.assign_local (| + "memory_start_position" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_size" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "extend_memory" , + M.call (| + M.get_name (| globals, "calculate_gas_extend_memory" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "memory" |); + make_list [ + make_tuple [ M.get_name (| globals, "memory_start_position" |); M.get_name (| globals, "memory_size" |) ] + ] + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + BinOp.add (| + M.get_name (| globals, "GAS_ZERO" |), + M.get_field (| M.get_name (| globals, "extend_memory" |), "cost" |) + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "memory" |), + BinOp.mult (| + Constant.bytes "00", + M.get_field (| M.get_name (| globals, "extend_memory" |), "expand_by" |) + |) + |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, "evm" |), "output" |), + M.call (| + M.get_name (| globals, "memory_read_bytes" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "memory" |); + M.get_name (| globals, "memory_start_position" |); + M.get_name (| globals, "memory_size" |) + ], + make_dict [] + |) + |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, "evm" |), "running" |), + Constant.bool false + |) in + let _ := M.pass (| |) in + M.pure Constant.None_)). + +Definition generic_call : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm"; "gas"; "value"; "caller"; "to"; "code_address"; "should_transfer_value"; "is_staticcall"; "memory_input_start_position"; "memory_input_size"; "memory_output_start_position"; "memory_output_size" ] |) in + let _ := Constant.str " + Perform the core logic of the `CALL*` family of opcodes. + " in +(* At stmt: unsupported node type: ImportFrom *) + let _ := M.assign (| + M.get_field (| M.get_name (| globals, "evm" |), "return_data" |), + Constant.bytes "" + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.gt (| + BinOp.add (| + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "depth" |), + Constant.int 1 + |), + M.get_name (| globals, "STACK_DEPTH_LIMIT" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "gas_left" |), + M.get_name (| globals, "gas" |) + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.return_ (| + Constant.None_ + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "call_data" , + M.call (| + M.get_name (| globals, "memory_read_bytes" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "memory" |); + M.get_name (| globals, "memory_input_start_position" |); + M.get_name (| globals, "memory_input_size" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "code" , + M.get_field (| M.call (| + M.get_name (| globals, "get_account" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "env" |), "state" |); + M.get_name (| globals, "code_address" |) + ], + make_dict [] + |), "code" |) + |) in + let _ := M.assign_local (| + "child_message" , + M.call (| + M.get_name (| globals, "Message" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "child_evm" , + M.call (| + M.get_name (| globals, "process_message" |), + make_list [ + M.get_name (| globals, "child_message" |); + M.get_field (| M.get_name (| globals, "evm" |), "env" |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + M.get_field (| M.get_name (| globals, "child_evm" |), "error" |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, "incorporate_child_on_error" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "child_evm" |) + ], + make_dict [] + |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, "evm" |), "return_data" |), + M.get_field (| M.get_name (| globals, "child_evm" |), "output" |) + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + ], + make_dict [] + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, "incorporate_child_on_success" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "child_evm" |) + ], + make_dict [] + |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, "evm" |), "return_data" |), + M.get_field (| M.get_name (| globals, "child_evm" |), "output" |) + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 1 + ], + make_dict [] + |) + ], + make_dict [] + |) in + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "actual_output_size" , + M.call (| + M.get_name (| globals, "min" |), + make_list [ + M.get_name (| globals, "memory_output_size" |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_field (| M.get_name (| globals, "child_evm" |), "output" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "memory_write" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "memory" |); + M.get_name (| globals, "memory_output_start_position" |); + M.slice (| + M.get_field (| M.get_name (| globals, "child_evm" |), "output" |), + Constant.None_, + M.get_name (| globals, "actual_output_size" |), + Constant.None_ + |) + ], + make_dict [] + |) in + M.pure Constant.None_)). + +Definition call : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Message-call into an account. + + Parameters + ---------- + evm : + The current EVM frame. + " in + let _ := M.assign_local (| + "gas" , + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "to" , + M.call (| + M.get_name (| globals, "to_address" |), + make_list [ + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "value" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_input_start_position" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_input_size" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_output_start_position" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_output_size" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "extend_memory" , + M.call (| + M.get_name (| globals, "calculate_gas_extend_memory" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "memory" |); + make_list [ + make_tuple [ M.get_name (| globals, "memory_input_start_position" |); M.get_name (| globals, "memory_input_size" |) ]; + make_tuple [ M.get_name (| globals, "memory_output_start_position" |); M.get_name (| globals, "memory_output_size" |) ] + ] + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.in_ (| + M.get_name (| globals, "to" |), + M.get_field (| M.get_name (| globals, "evm" |), "accessed_addresses" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "access_gas_cost" , + M.get_name (| globals, "GAS_WARM_ACCESS" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "accessed_addresses" |), "add" |), + make_list [ + M.get_name (| globals, "to" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "access_gas_cost" , + M.get_name (| globals, "GAS_COLD_ACCOUNT_ACCESS" |) + |) in + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "create_gas_cost" , + (* if *) + M.if_then_else (| + BoolOp.or (| + M.call (| + M.get_name (| globals, "is_account_alive" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "env" |), "state" |); + M.get_name (| globals, "to" |) + ], + make_dict [] + |), + ltac:(M.monadic ( + Compare.eq (| + M.get_name (| globals, "value" |), + Constant.int 0 + |) + )) + |), + (* then *) + ltac:(M.monadic ( +M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + (* else *) + )), ltac:(M.monadic ( +M.get_name (| globals, "GAS_NEW_ACCOUNT" |) + )) |) + |) in + let _ := M.assign_local (| + "transfer_gas_cost" , + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, "value" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( +M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + (* else *) + )), ltac:(M.monadic ( +M.get_name (| globals, "GAS_CALL_VALUE" |) + )) |) + |) in + let _ := M.assign_local (| + "message_call_gas" , + M.call (| + M.get_name (| globals, "calculate_message_call_gas" |), + make_list [ + M.get_name (| globals, "value" |); + M.get_name (| globals, "gas" |); + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "gas_left" |) + ], + make_dict [] + |); + M.get_field (| M.get_name (| globals, "extend_memory" |), "cost" |); + BinOp.add (| + BinOp.add (| + M.get_name (| globals, "access_gas_cost" |), + M.get_name (| globals, "create_gas_cost" |) + |), + M.get_name (| globals, "transfer_gas_cost" |) + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + BinOp.add (| + M.get_field (| M.get_name (| globals, "message_call_gas" |), "cost" |), + M.get_field (| M.get_name (| globals, "extend_memory" |), "cost" |) + |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + BoolOp.or (| + UnOp.not (| M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "is_static" |) |), + ltac:(M.monadic ( + Compare.eq (| + M.get_name (| globals, "value" |), + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + |) + )) + |); + M.get_name (| globals, "WriteInStaticContext" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "memory" |), + BinOp.mult (| + Constant.bytes "00", + M.get_field (| M.get_name (| globals, "extend_memory" |), "expand_by" |) + |) + |) in + let _ := M.assign_local (| + "sender_balance" , + M.get_field (| M.call (| + M.get_name (| globals, "get_account" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "env" |), "state" |); + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "current_target" |) + ], + make_dict [] + |), "balance" |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.lt (| + M.get_name (| globals, "sender_balance" |), + M.get_name (| globals, "value" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, "evm" |), "return_data" |), + Constant.bytes "" + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "gas_left" |), + M.get_field (| M.get_name (| globals, "message_call_gas" |), "stipend" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, "generic_call" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_field (| M.get_name (| globals, "message_call_gas" |), "stipend" |); + M.get_name (| globals, "value" |); + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "current_target" |); + M.get_name (| globals, "to" |); + M.get_name (| globals, "to" |); + Constant.bool true; + Constant.bool false; + M.get_name (| globals, "memory_input_start_position" |); + M.get_name (| globals, "memory_input_size" |); + M.get_name (| globals, "memory_output_start_position" |); + M.get_name (| globals, "memory_output_size" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + )) |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition callcode : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Message-call into this account with alternative account’s code. + + Parameters + ---------- + evm : + The current EVM frame. + " in + let _ := M.assign_local (| + "gas" , + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "code_address" , + M.call (| + M.get_name (| globals, "to_address" |), + make_list [ + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "value" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_input_start_position" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_input_size" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_output_start_position" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_output_size" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "to" , + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "current_target" |) + |) in + let _ := M.assign_local (| + "extend_memory" , + M.call (| + M.get_name (| globals, "calculate_gas_extend_memory" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "memory" |); + make_list [ + make_tuple [ M.get_name (| globals, "memory_input_start_position" |); M.get_name (| globals, "memory_input_size" |) ]; + make_tuple [ M.get_name (| globals, "memory_output_start_position" |); M.get_name (| globals, "memory_output_size" |) ] + ] + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.in_ (| + M.get_name (| globals, "code_address" |), + M.get_field (| M.get_name (| globals, "evm" |), "accessed_addresses" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "access_gas_cost" , + M.get_name (| globals, "GAS_WARM_ACCESS" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "accessed_addresses" |), "add" |), + make_list [ + M.get_name (| globals, "code_address" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "access_gas_cost" , + M.get_name (| globals, "GAS_COLD_ACCOUNT_ACCESS" |) + |) in + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "transfer_gas_cost" , + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, "value" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( +M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + (* else *) + )), ltac:(M.monadic ( +M.get_name (| globals, "GAS_CALL_VALUE" |) + )) |) + |) in + let _ := M.assign_local (| + "message_call_gas" , + M.call (| + M.get_name (| globals, "calculate_message_call_gas" |), + make_list [ + M.get_name (| globals, "value" |); + M.get_name (| globals, "gas" |); + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "gas_left" |) + ], + make_dict [] + |); + M.get_field (| M.get_name (| globals, "extend_memory" |), "cost" |); + BinOp.add (| + M.get_name (| globals, "access_gas_cost" |), + M.get_name (| globals, "transfer_gas_cost" |) + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + BinOp.add (| + M.get_field (| M.get_name (| globals, "message_call_gas" |), "cost" |), + M.get_field (| M.get_name (| globals, "extend_memory" |), "cost" |) + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "memory" |), + BinOp.mult (| + Constant.bytes "00", + M.get_field (| M.get_name (| globals, "extend_memory" |), "expand_by" |) + |) + |) in + let _ := M.assign_local (| + "sender_balance" , + M.get_field (| M.call (| + M.get_name (| globals, "get_account" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "env" |), "state" |); + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "current_target" |) + ], + make_dict [] + |), "balance" |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.lt (| + M.get_name (| globals, "sender_balance" |), + M.get_name (| globals, "value" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, "evm" |), "return_data" |), + Constant.bytes "" + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "gas_left" |), + M.get_field (| M.get_name (| globals, "message_call_gas" |), "stipend" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, "generic_call" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_field (| M.get_name (| globals, "message_call_gas" |), "stipend" |); + M.get_name (| globals, "value" |); + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "current_target" |); + M.get_name (| globals, "to" |); + M.get_name (| globals, "code_address" |); + Constant.bool true; + Constant.bool false; + M.get_name (| globals, "memory_input_start_position" |); + M.get_name (| globals, "memory_input_size" |); + M.get_name (| globals, "memory_output_start_position" |); + M.get_name (| globals, "memory_output_size" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + )) |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition selfdestruct : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Halt execution and register account for later deletion. + + Parameters + ---------- + evm : + The current EVM frame. + " in + let _ := M.assign_local (| + "beneficiary" , + M.call (| + M.get_name (| globals, "to_address" |), + make_list [ + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "gas_cost" , + M.get_name (| globals, "GAS_SELF_DESTRUCT" |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.not_in (| + M.get_name (| globals, "beneficiary" |), + M.get_field (| M.get_name (| globals, "evm" |), "accessed_addresses" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "accessed_addresses" |), "add" |), + make_list [ + M.get_name (| globals, "beneficiary" |) + ], + make_dict [] + |) in + let _ := M.assign_op_local (| + BinOp.add, + "gas_cost", + M.get_name (| globals, "GAS_COLD_ACCOUNT_ACCESS" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + BoolOp.and (| + UnOp.not (| M.call (| + M.get_name (| globals, "is_account_alive" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "env" |), "state" |); + M.get_name (| globals, "beneficiary" |) + ], + make_dict [] + |) |), + ltac:(M.monadic ( + Compare.not_eq (| + M.get_field (| M.call (| + M.get_name (| globals, "get_account" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "env" |), "state" |); + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "current_target" |) + ], + make_dict [] + |), "balance" |), + Constant.int 0 + |) + )) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_op_local (| + BinOp.add, + "gas_cost", + M.get_name (| globals, "GAS_SELF_DESTRUCT_NEW_ACCOUNT" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "gas_cost" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + UnOp.not (| M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "is_static" |) |); + M.get_name (| globals, "WriteInStaticContext" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "originator" , + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "current_target" |) + |) in + let _ := M.assign_local (| + "beneficiary_balance" , + M.get_field (| M.call (| + M.get_name (| globals, "get_account" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "env" |), "state" |); + M.get_name (| globals, "beneficiary" |) + ], + make_dict [] + |), "balance" |) + |) in + let _ := M.assign_local (| + "originator_balance" , + M.get_field (| M.call (| + M.get_name (| globals, "get_account" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "env" |), "state" |); + M.get_name (| globals, "originator" |) + ], + make_dict [] + |), "balance" |) + |) in + let _ := M.call (| + M.get_name (| globals, "set_account_balance" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "env" |), "state" |); + M.get_name (| globals, "beneficiary" |); + BinOp.add (| + M.get_name (| globals, "beneficiary_balance" |), + M.get_name (| globals, "originator_balance" |) + |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "set_account_balance" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "env" |), "state" |); + M.get_name (| globals, "originator" |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "accounts_to_delete" |), "add" |), + make_list [ + M.get_name (| globals, "originator" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, "account_exists_and_is_empty" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "env" |), "state" |); + M.get_name (| globals, "beneficiary" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "touched_accounts" |), "add" |), + make_list [ + M.get_name (| globals, "beneficiary" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, "evm" |), "running" |), + Constant.bool false + |) in + let _ := M.pass (| |) in + M.pure Constant.None_)). + +Definition delegatecall : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Message-call into an account. + + Parameters + ---------- + evm : + The current EVM frame. + " in + let _ := M.assign_local (| + "gas" , + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "code_address" , + M.call (| + M.get_name (| globals, "to_address" |), + make_list [ + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_input_start_position" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_input_size" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_output_start_position" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_output_size" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "extend_memory" , + M.call (| + M.get_name (| globals, "calculate_gas_extend_memory" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "memory" |); + make_list [ + make_tuple [ M.get_name (| globals, "memory_input_start_position" |); M.get_name (| globals, "memory_input_size" |) ]; + make_tuple [ M.get_name (| globals, "memory_output_start_position" |); M.get_name (| globals, "memory_output_size" |) ] + ] + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.in_ (| + M.get_name (| globals, "code_address" |), + M.get_field (| M.get_name (| globals, "evm" |), "accessed_addresses" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "access_gas_cost" , + M.get_name (| globals, "GAS_WARM_ACCESS" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "accessed_addresses" |), "add" |), + make_list [ + M.get_name (| globals, "code_address" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "access_gas_cost" , + M.get_name (| globals, "GAS_COLD_ACCOUNT_ACCESS" |) + |) in + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "message_call_gas" , + M.call (| + M.get_name (| globals, "calculate_message_call_gas" |), + make_list [ + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |); + M.get_name (| globals, "gas" |); + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "gas_left" |) + ], + make_dict [] + |); + M.get_field (| M.get_name (| globals, "extend_memory" |), "cost" |); + M.get_name (| globals, "access_gas_cost" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + BinOp.add (| + M.get_field (| M.get_name (| globals, "message_call_gas" |), "cost" |), + M.get_field (| M.get_name (| globals, "extend_memory" |), "cost" |) + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "memory" |), + BinOp.mult (| + Constant.bytes "00", + M.get_field (| M.get_name (| globals, "extend_memory" |), "expand_by" |) + |) + |) in + let _ := M.call (| + M.get_name (| globals, "generic_call" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_field (| M.get_name (| globals, "message_call_gas" |), "stipend" |); + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "value" |); + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "caller" |); + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "current_target" |); + M.get_name (| globals, "code_address" |); + Constant.bool false; + Constant.bool false; + M.get_name (| globals, "memory_input_start_position" |); + M.get_name (| globals, "memory_input_size" |); + M.get_name (| globals, "memory_output_start_position" |); + M.get_name (| globals, "memory_output_size" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition staticcall : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Message-call into an account. + + Parameters + ---------- + evm : + The current EVM frame. + " in + let _ := M.assign_local (| + "gas" , + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "to" , + M.call (| + M.get_name (| globals, "to_address" |), + make_list [ + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_input_start_position" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_input_size" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_output_start_position" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_output_size" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "extend_memory" , + M.call (| + M.get_name (| globals, "calculate_gas_extend_memory" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "memory" |); + make_list [ + make_tuple [ M.get_name (| globals, "memory_input_start_position" |); M.get_name (| globals, "memory_input_size" |) ]; + make_tuple [ M.get_name (| globals, "memory_output_start_position" |); M.get_name (| globals, "memory_output_size" |) ] + ] + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.in_ (| + M.get_name (| globals, "to" |), + M.get_field (| M.get_name (| globals, "evm" |), "accessed_addresses" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "access_gas_cost" , + M.get_name (| globals, "GAS_WARM_ACCESS" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "accessed_addresses" |), "add" |), + make_list [ + M.get_name (| globals, "to" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "access_gas_cost" , + M.get_name (| globals, "GAS_COLD_ACCOUNT_ACCESS" |) + |) in + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "message_call_gas" , + M.call (| + M.get_name (| globals, "calculate_message_call_gas" |), + make_list [ + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |); + M.get_name (| globals, "gas" |); + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "gas_left" |) + ], + make_dict [] + |); + M.get_field (| M.get_name (| globals, "extend_memory" |), "cost" |); + M.get_name (| globals, "access_gas_cost" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + BinOp.add (| + M.get_field (| M.get_name (| globals, "message_call_gas" |), "cost" |), + M.get_field (| M.get_name (| globals, "extend_memory" |), "cost" |) + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "memory" |), + BinOp.mult (| + Constant.bytes "00", + M.get_field (| M.get_name (| globals, "extend_memory" |), "expand_by" |) + |) + |) in + let _ := M.call (| + M.get_name (| globals, "generic_call" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_field (| M.get_name (| globals, "message_call_gas" |), "stipend" |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |); + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "current_target" |); + M.get_name (| globals, "to" |); + M.get_name (| globals, "to" |); + Constant.bool true; + Constant.bool true; + M.get_name (| globals, "memory_input_start_position" |); + M.get_name (| globals, "memory_input_size" |); + M.get_name (| globals, "memory_output_start_position" |); + M.get_name (| globals, "memory_output_size" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition revert : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Stop execution and revert state changes, without consuming all provided gas + and also has the ability to return a reason + Parameters + ---------- + evm : + The current EVM frame. + " in + let _ := M.assign_local (| + "memory_start_index" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "size" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "extend_memory" , + M.call (| + M.get_name (| globals, "calculate_gas_extend_memory" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "memory" |); + make_list [ + make_tuple [ M.get_name (| globals, "memory_start_index" |); M.get_name (| globals, "size" |) ] + ] + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_field (| M.get_name (| globals, "extend_memory" |), "cost" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "memory" |), + BinOp.mult (| + Constant.bytes "00", + M.get_field (| M.get_name (| globals, "extend_memory" |), "expand_by" |) + |) + |) in + let _ := M.assign_local (| + "output" , + M.call (| + M.get_name (| globals, "memory_read_bytes" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "memory" |); + M.get_name (| globals, "memory_start_index" |); + M.get_name (| globals, "size" |) + ], + make_dict [] + |) + |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, "evm" |), "output" |), + M.call (| + M.get_name (| globals, "bytes" |), + make_list [ + M.get_name (| globals, "output" |) + ], + make_dict [] + |) + |) in + let _ := M.raise (| Some (M.get_name (| globals, "Revert" |)) |) in + let _ := M.pass (| |) in + M.pure Constant.None_)). diff --git a/CoqOfPython/ethereum/paris/vm/interpreter.v b/CoqOfPython/ethereum/paris/vm/interpreter.v new file mode 100644 index 0000000..ddfc003 --- /dev/null +++ b/CoqOfPython/ethereum/paris/vm/interpreter.v @@ -0,0 +1,677 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.paris.vm.interpreter". + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) Interpreter +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +A straightforward interpreter that executes EVM code. +". + +Axiom dataclasses_imports_dataclass : + IsImported globals "dataclasses" "dataclass". + +Axiom typing_imports_Iterable : + IsImported globals "typing" "Iterable". +Axiom typing_imports_Optional : + IsImported globals "typing" "Optional". +Axiom typing_imports_Set : + IsImported globals "typing" "Set". +Axiom typing_imports_Tuple : + IsImported globals "typing" "Tuple". +Axiom typing_imports_Union : + IsImported globals "typing" "Union". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_Bytes0 : + IsImported globals "ethereum.base_types" "Bytes0". +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". + +Axiom ethereum_trace_imports_EvmStop : + IsImported globals "ethereum.trace" "EvmStop". +Axiom ethereum_trace_imports_OpEnd : + IsImported globals "ethereum.trace" "OpEnd". +Axiom ethereum_trace_imports_OpException : + IsImported globals "ethereum.trace" "OpException". +Axiom ethereum_trace_imports_OpStart : + IsImported globals "ethereum.trace" "OpStart". +Axiom ethereum_trace_imports_PrecompileEnd : + IsImported globals "ethereum.trace" "PrecompileEnd". +Axiom ethereum_trace_imports_PrecompileStart : + IsImported globals "ethereum.trace" "PrecompileStart". +Axiom ethereum_trace_imports_TransactionEnd : + IsImported globals "ethereum.trace" "TransactionEnd". +Axiom ethereum_trace_imports_evm_trace : + IsImported globals "ethereum.trace" "evm_trace". + +Axiom ethereum_utils_ensure_imports_ensure : + IsImported globals "ethereum.utils.ensure" "ensure". + +Axiom ethereum_paris_blocks_imports_Log : + IsImported globals "ethereum.paris.blocks" "Log". + +Axiom ethereum_paris_fork_types_imports_Address : + IsImported globals "ethereum.paris.fork_types" "Address". + +Axiom ethereum_paris_state_imports_account_exists_and_is_empty : + IsImported globals "ethereum.paris.state" "account_exists_and_is_empty". +Axiom ethereum_paris_state_imports_account_has_code_or_nonce : + IsImported globals "ethereum.paris.state" "account_has_code_or_nonce". +Axiom ethereum_paris_state_imports_begin_transaction : + IsImported globals "ethereum.paris.state" "begin_transaction". +Axiom ethereum_paris_state_imports_commit_transaction : + IsImported globals "ethereum.paris.state" "commit_transaction". +Axiom ethereum_paris_state_imports_destroy_storage : + IsImported globals "ethereum.paris.state" "destroy_storage". +Axiom ethereum_paris_state_imports_increment_nonce : + IsImported globals "ethereum.paris.state" "increment_nonce". +Axiom ethereum_paris_state_imports_mark_account_created : + IsImported globals "ethereum.paris.state" "mark_account_created". +Axiom ethereum_paris_state_imports_move_ether : + IsImported globals "ethereum.paris.state" "move_ether". +Axiom ethereum_paris_state_imports_rollback_transaction : + IsImported globals "ethereum.paris.state" "rollback_transaction". +Axiom ethereum_paris_state_imports_set_code : + IsImported globals "ethereum.paris.state" "set_code". +Axiom ethereum_paris_state_imports_touch_account : + IsImported globals "ethereum.paris.state" "touch_account". + +Axiom ethereum_paris_vm_imports_Message : + IsImported globals "ethereum.paris.vm" "Message". + +Axiom ethereum_paris_vm_gas_imports_GAS_CODE_DEPOSIT : + IsImported globals "ethereum.paris.vm.gas" "GAS_CODE_DEPOSIT". +Axiom ethereum_paris_vm_gas_imports_charge_gas : + IsImported globals "ethereum.paris.vm.gas" "charge_gas". + +Axiom ethereum_paris_vm_precompiled_contracts_mapping_imports_PRE_COMPILED_CONTRACTS : + IsImported globals "ethereum.paris.vm.precompiled_contracts.mapping" "PRE_COMPILED_CONTRACTS". + +Axiom ethereum_paris_vm_imports_Environment : + IsImported globals "ethereum.paris.vm" "Environment". +Axiom ethereum_paris_vm_imports_Evm : + IsImported globals "ethereum.paris.vm" "Evm". + +Axiom ethereum_paris_vm_exceptions_imports_AddressCollision : + IsImported globals "ethereum.paris.vm.exceptions" "AddressCollision". +Axiom ethereum_paris_vm_exceptions_imports_ExceptionalHalt : + IsImported globals "ethereum.paris.vm.exceptions" "ExceptionalHalt". +Axiom ethereum_paris_vm_exceptions_imports_InvalidContractPrefix : + IsImported globals "ethereum.paris.vm.exceptions" "InvalidContractPrefix". +Axiom ethereum_paris_vm_exceptions_imports_InvalidOpcode : + IsImported globals "ethereum.paris.vm.exceptions" "InvalidOpcode". +Axiom ethereum_paris_vm_exceptions_imports_OutOfGasError : + IsImported globals "ethereum.paris.vm.exceptions" "OutOfGasError". +Axiom ethereum_paris_vm_exceptions_imports_Revert : + IsImported globals "ethereum.paris.vm.exceptions" "Revert". +Axiom ethereum_paris_vm_exceptions_imports_StackDepthLimitError : + IsImported globals "ethereum.paris.vm.exceptions" "StackDepthLimitError". + +Axiom ethereum_paris_vm_instructions_imports_Ops : + IsImported globals "ethereum.paris.vm.instructions" "Ops". +Axiom ethereum_paris_vm_instructions_imports_op_implementation : + IsImported globals "ethereum.paris.vm.instructions" "op_implementation". + +Axiom ethereum_paris_vm_runtime_imports_get_valid_jump_destinations : + IsImported globals "ethereum.paris.vm.runtime" "get_valid_jump_destinations". + +Definition STACK_DEPTH_LIMIT : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 1024 + ], + make_dict [] + |) +)). + +Definition MAX_CODE_SIZE : Value.t := M.run ltac:(M.monadic ( + Constant.int 24576 +)). + +Definition MessageCallOutput : Value.t := + builtins.make_klass + [] + [ + + ] + [ + + ]. + +Definition process_message_call : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "message"; "env" ] |) in + let _ := Constant.str " + If `message.current` is empty then it creates a smart contract + else it executes a call from the `message.caller` to the `message.target`. + + Parameters + ---------- + message : + Transaction specific items. + + env : + External items required for EVM execution. + + Returns + ------- + output : `MessageCallOutput` + Output of the message call + " in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_field (| M.get_name (| globals, "message" |), "target" |), + M.call (| + M.get_name (| globals, "Bytes0" |), + make_list [ + Constant.bytes "" + ], + make_dict [] + |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "is_collision" , + M.call (| + M.get_name (| globals, "account_has_code_or_nonce" |), + make_list [ + M.get_field (| M.get_name (| globals, "env" |), "state" |); + M.get_field (| M.get_name (| globals, "message" |), "current_target" |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + M.get_name (| globals, "is_collision" |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + M.call (| + M.get_name (| globals, "MessageCallOutput" |), + make_list [ + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |); + M.call (| + M.get_name (| globals, "tuple" |), + make_list [], + make_dict [] + |); + M.call (| + M.get_name (| globals, "set" |), + make_list [], + make_dict [] + |); + M.call (| + M.get_name (| globals, "set" |), + make_list [], + make_dict [] + |); + M.call (| + M.get_name (| globals, "AddressCollision" |), + make_list [], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "evm" , + M.call (| + M.get_name (| globals, "process_create_message" |), + make_list [ + M.get_name (| globals, "message" |); + M.get_name (| globals, "env" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "evm" , + M.call (| + M.get_name (| globals, "process_message" |), + make_list [ + M.get_name (| globals, "message" |); + M.get_name (| globals, "env" |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, "account_exists_and_is_empty" |), + make_list [ + M.get_field (| M.get_name (| globals, "env" |), "state" |); + M.call (| + M.get_name (| globals, "Address" |), + make_list [ + M.get_field (| M.get_name (| globals, "message" |), "target" |) + ], + make_dict [] + |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "touched_accounts" |), "add" |), + make_list [ + M.call (| + M.get_name (| globals, "Address" |), + make_list [ + M.get_field (| M.get_name (| globals, "message" |), "target" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + M.get_field (| M.get_name (| globals, "evm" |), "error" |), + (* then *) + ltac:(M.monadic ( +(* At stmt: unsupported node type: AnnAssign *) + let _ := M.assign_local (| + "accounts_to_delete" , + M.call (| + M.get_name (| globals, "set" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "touched_accounts" , + M.call (| + M.get_name (| globals, "set" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "refund_counter" , + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "logs" , + M.get_field (| M.get_name (| globals, "evm" |), "logs" |) + |) in + let _ := M.assign_local (| + "accounts_to_delete" , + M.get_field (| M.get_name (| globals, "evm" |), "accounts_to_delete" |) + |) in + let _ := M.assign_local (| + "touched_accounts" , + M.get_field (| M.get_name (| globals, "evm" |), "touched_accounts" |) + |) in + let _ := M.assign_local (| + "refund_counter" , + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "refund_counter" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "tx_end" , + M.call (| + M.get_name (| globals, "TransactionEnd" |), + make_list [ + BinOp.sub (| + M.get_field (| M.get_name (| globals, "message" |), "gas" |), + M.get_field (| M.get_name (| globals, "evm" |), "gas_left" |) + |); + M.get_field (| M.get_name (| globals, "evm" |), "output" |); + M.get_field (| M.get_name (| globals, "evm" |), "error" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "evm_trace" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "tx_end" |) + ], + make_dict [] + |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, "MessageCallOutput" |), + make_list [], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Definition process_create_message : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "message"; "env" ] |) in + let _ := Constant.str " + Executes a call to create a smart contract. + + Parameters + ---------- + message : + Transaction specific items. + env : + External items required for EVM execution. + + Returns + ------- + evm: :py:class:`~ethereum.paris.vm.Evm` + Items containing execution specific objects. + " in + let _ := M.call (| + M.get_name (| globals, "begin_transaction" |), + make_list [ + M.get_field (| M.get_name (| globals, "env" |), "state" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "destroy_storage" |), + make_list [ + M.get_field (| M.get_name (| globals, "env" |), "state" |); + M.get_field (| M.get_name (| globals, "message" |), "current_target" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "mark_account_created" |), + make_list [ + M.get_field (| M.get_name (| globals, "env" |), "state" |); + M.get_field (| M.get_name (| globals, "message" |), "current_target" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "increment_nonce" |), + make_list [ + M.get_field (| M.get_name (| globals, "env" |), "state" |); + M.get_field (| M.get_name (| globals, "message" |), "current_target" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "evm" , + M.call (| + M.get_name (| globals, "process_message" |), + make_list [ + M.get_name (| globals, "message" |); + M.get_name (| globals, "env" |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + UnOp.not (| M.get_field (| M.get_name (| globals, "evm" |), "error" |) |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "contract_code" , + M.get_field (| M.get_name (| globals, "evm" |), "output" |) + |) in + let _ := M.assign_local (| + "contract_code_gas" , + BinOp.mult (| + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_name (| globals, "contract_code" |) + ], + make_dict [] + |), + M.get_name (| globals, "GAS_CODE_DEPOSIT" |) + |) + |) in +(* At stmt: unsupported node type: Try *) + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, "rollback_transaction" |), + make_list [ + M.get_field (| M.get_name (| globals, "env" |), "state" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + )) |) in + let _ := M.return_ (| + M.get_name (| globals, "evm" |) + |) in + M.pure Constant.None_)). + +Definition process_message : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "message"; "env" ] |) in + let _ := Constant.str " + Executes a call to create a smart contract. + + Parameters + ---------- + message : + Transaction specific items. + env : + External items required for EVM execution. + + Returns + ------- + evm: :py:class:`~ethereum.paris.vm.Evm` + Items containing execution specific objects + " in + let _ := + (* if *) + M.if_then_else (| + Compare.gt (| + M.get_field (| M.get_name (| globals, "message" |), "depth" |), + M.get_name (| globals, "STACK_DEPTH_LIMIT" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.call (| + M.get_name (| globals, "StackDepthLimitError" |), + make_list [ + Constant.str "Stack depth limit reached" + ], + make_dict [] + |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.call (| + M.get_name (| globals, "begin_transaction" |), + make_list [ + M.get_field (| M.get_name (| globals, "env" |), "state" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "touch_account" |), + make_list [ + M.get_field (| M.get_name (| globals, "env" |), "state" |); + M.get_field (| M.get_name (| globals, "message" |), "current_target" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + BoolOp.and (| + M.get_field (| M.get_name (| globals, "message" |), "should_transfer_value" |), + ltac:(M.monadic ( + Compare.not_eq (| + M.get_field (| M.get_name (| globals, "message" |), "value" |), + Constant.int 0 + |) + )) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, "move_ether" |), + make_list [ + M.get_field (| M.get_name (| globals, "env" |), "state" |); + M.get_field (| M.get_name (| globals, "message" |), "caller" |); + M.get_field (| M.get_name (| globals, "message" |), "current_target" |); + M.get_field (| M.get_name (| globals, "message" |), "value" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "evm" , + M.call (| + M.get_name (| globals, "execute_code" |), + make_list [ + M.get_name (| globals, "message" |); + M.get_name (| globals, "env" |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + M.get_field (| M.get_name (| globals, "evm" |), "error" |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, "rollback_transaction" |), + make_list [ + M.get_field (| M.get_name (| globals, "env" |), "state" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, "commit_transaction" |), + make_list [ + M.get_field (| M.get_name (| globals, "env" |), "state" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + )) |) in + let _ := M.return_ (| + M.get_name (| globals, "evm" |) + |) in + M.pure Constant.None_)). + +Definition execute_code : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "message"; "env" ] |) in + let _ := Constant.str " + Executes bytecode present in the `message`. + + Parameters + ---------- + message : + Transaction specific items. + env : + External items required for EVM execution. + + Returns + ------- + evm: `ethereum.vm.EVM` + Items containing execution specific objects + " in + let _ := M.assign_local (| + "code" , + M.get_field (| M.get_name (| globals, "message" |), "code" |) + |) in + let _ := M.assign_local (| + "valid_jump_destinations" , + M.call (| + M.get_name (| globals, "get_valid_jump_destinations" |), + make_list [ + M.get_name (| globals, "code" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "evm" , + M.call (| + M.get_name (| globals, "Evm" |), + make_list [], + make_dict [] + |) + |) in +(* At stmt: unsupported node type: Try *) + let _ := M.return_ (| + M.get_name (| globals, "evm" |) + |) in + M.pure Constant.None_)). diff --git a/CoqOfPython/ethereum/paris/vm/memory.v b/CoqOfPython/ethereum/paris/vm/memory.v new file mode 100644 index 0000000..0a1308d --- /dev/null +++ b/CoqOfPython/ethereum/paris/vm/memory.v @@ -0,0 +1,166 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.paris.vm.memory". + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) Memory +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +EVM memory operations. +". + +Axiom ethereum_utils_byte_imports_right_pad_zero_bytes : + IsImported globals "ethereum.utils.byte" "right_pad_zero_bytes". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_Bytes : + IsImported globals "ethereum.base_types" "Bytes". +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". + +Definition memory_write : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "memory"; "start_position"; "value" ] |) in + let _ := Constant.str " + Writes to memory. + + Parameters + ---------- + memory : + Memory contents of the EVM. + start_position : + Starting pointer to the memory. + value : + Data to write to memory. + " in + let _ := M.assign (| + M.slice (| + M.get_name (| globals, "memory" |), + M.get_name (| globals, "start_position" |), + BinOp.add (| + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.get_name (| globals, "start_position" |) + ], + make_dict [] + |), + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_name (| globals, "value" |) + ], + make_dict [] + |) + |), + Constant.None_ + |), + M.get_name (| globals, "value" |) + |) in + M.pure Constant.None_)). + +Definition memory_read_bytes : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "memory"; "start_position"; "size" ] |) in + let _ := Constant.str " + Read bytes from memory. + + Parameters + ---------- + memory : + Memory contents of the EVM. + start_position : + Starting pointer to the memory. + size : + Size of the data that needs to be read from `start_position`. + + Returns + ------- + data_bytes : + Data read from memory. + " in + let _ := M.return_ (| + M.slice (| + M.get_name (| globals, "memory" |), + M.get_name (| globals, "start_position" |), + BinOp.add (| + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.get_name (| globals, "start_position" |) + ], + make_dict [] + |), + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.get_name (| globals, "size" |) + ], + make_dict [] + |) + |), + Constant.None_ + |) + |) in + M.pure Constant.None_)). + +Definition buffer_read : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "buffer"; "start_position"; "size" ] |) in + let _ := Constant.str " + Read bytes from a buffer. Padding with zeros if necessary. + + Parameters + ---------- + buffer : + Memory contents of the EVM. + start_position : + Starting pointer to the memory. + size : + Size of the data that needs to be read from `start_position`. + + Returns + ------- + data_bytes : + Data read from memory. + " in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, "right_pad_zero_bytes" |), + make_list [ + M.slice (| + M.get_name (| globals, "buffer" |), + M.get_name (| globals, "start_position" |), + BinOp.add (| + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.get_name (| globals, "start_position" |) + ], + make_dict [] + |), + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.get_name (| globals, "size" |) + ], + make_dict [] + |) + |), + Constant.None_ + |); + M.get_name (| globals, "size" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). diff --git a/CoqOfPython/ethereum/paris/vm/precompiled_contracts/__init__.v b/CoqOfPython/ethereum/paris/vm/precompiled_contracts/__init__.v new file mode 100644 index 0000000..0726d50 --- /dev/null +++ b/CoqOfPython/ethereum/paris/vm/precompiled_contracts/__init__.v @@ -0,0 +1,116 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.paris.vm.precompiled_contracts.__init__". + +Definition expr_1 : Value.t := + Constant.str " +Precompiled Contract Addresses +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Addresses of precompiled contracts and mappings to their +implementations. +". + +Axiom ethereum_paris_utils_hexadecimal_imports_hex_to_address : + IsImported globals "ethereum.paris.utils.hexadecimal" "hex_to_address". + +Definition __all__ : Value.t := M.run ltac:(M.monadic ( + make_tuple [ Constant.str "ECRECOVER_ADDRESS"; Constant.str "SHA256_ADDRESS"; Constant.str "RIPEMD160_ADDRESS"; Constant.str "IDENTITY_ADDRESS"; Constant.str "MODEXP_ADDRESS"; Constant.str "ALT_BN128_ADD_ADDRESS"; Constant.str "ALT_BN128_MUL_ADDRESS"; Constant.str "ALT_BN128_PAIRING_CHECK_ADDRESS"; Constant.str "BLAKE2F_ADDRESS" ] +)). + +Definition ECRECOVER_ADDRESS : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "hex_to_address" |), + make_list [ + Constant.str "0x01" + ], + make_dict [] + |) +)). + +Definition SHA256_ADDRESS : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "hex_to_address" |), + make_list [ + Constant.str "0x02" + ], + make_dict [] + |) +)). + +Definition RIPEMD160_ADDRESS : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "hex_to_address" |), + make_list [ + Constant.str "0x03" + ], + make_dict [] + |) +)). + +Definition IDENTITY_ADDRESS : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "hex_to_address" |), + make_list [ + Constant.str "0x04" + ], + make_dict [] + |) +)). + +Definition MODEXP_ADDRESS : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "hex_to_address" |), + make_list [ + Constant.str "0x05" + ], + make_dict [] + |) +)). + +Definition ALT_BN128_ADD_ADDRESS : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "hex_to_address" |), + make_list [ + Constant.str "0x06" + ], + make_dict [] + |) +)). + +Definition ALT_BN128_MUL_ADDRESS : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "hex_to_address" |), + make_list [ + Constant.str "0x07" + ], + make_dict [] + |) +)). + +Definition ALT_BN128_PAIRING_CHECK_ADDRESS : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "hex_to_address" |), + make_list [ + Constant.str "0x08" + ], + make_dict [] + |) +)). + +Definition BLAKE2F_ADDRESS : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "hex_to_address" |), + make_list [ + Constant.str "0x09" + ], + make_dict [] + |) +)). diff --git a/CoqOfPython/ethereum/paris/vm/precompiled_contracts/alt_bn128.v b/CoqOfPython/ethereum/paris/vm/precompiled_contracts/alt_bn128.v new file mode 100644 index 0000000..21ebabe --- /dev/null +++ b/CoqOfPython/ethereum/paris/vm/precompiled_contracts/alt_bn128.v @@ -0,0 +1,778 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.paris.vm.precompiled_contracts.alt_bn128". + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) ALT_BN128 CONTRACTS +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementation of the ALT_BN128 precompiled contracts. +". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". + +Axiom ethereum_crypto_alt_bn128_imports_ALT_BN128_CURVE_ORDER : + IsImported globals "ethereum.crypto.alt_bn128" "ALT_BN128_CURVE_ORDER". +Axiom ethereum_crypto_alt_bn128_imports_ALT_BN128_PRIME : + IsImported globals "ethereum.crypto.alt_bn128" "ALT_BN128_PRIME". +Axiom ethereum_crypto_alt_bn128_imports_BNF : + IsImported globals "ethereum.crypto.alt_bn128" "BNF". +Axiom ethereum_crypto_alt_bn128_imports_BNF2 : + IsImported globals "ethereum.crypto.alt_bn128" "BNF2". +Axiom ethereum_crypto_alt_bn128_imports_BNF12 : + IsImported globals "ethereum.crypto.alt_bn128" "BNF12". +Axiom ethereum_crypto_alt_bn128_imports_BNP : + IsImported globals "ethereum.crypto.alt_bn128" "BNP". +Axiom ethereum_crypto_alt_bn128_imports_BNP2 : + IsImported globals "ethereum.crypto.alt_bn128" "BNP2". +Axiom ethereum_crypto_alt_bn128_imports_pairing : + IsImported globals "ethereum.crypto.alt_bn128" "pairing". + +Axiom ethereum_utils_ensure_imports_ensure : + IsImported globals "ethereum.utils.ensure" "ensure". + +Axiom ethereum_paris_vm_imports_Evm : + IsImported globals "ethereum.paris.vm" "Evm". + +Axiom ethereum_paris_vm_gas_imports_charge_gas : + IsImported globals "ethereum.paris.vm.gas" "charge_gas". + +Axiom ethereum_paris_vm_memory_imports_buffer_read : + IsImported globals "ethereum.paris.vm.memory" "buffer_read". + +Axiom ethereum_paris_vm_exceptions_imports_OutOfGasError : + IsImported globals "ethereum.paris.vm.exceptions" "OutOfGasError". + +Definition alt_bn128_add : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + The ALT_BN128 addition precompiled contract. + + Parameters + ---------- + evm : + The current EVM frame. + " in + let _ := M.assign_local (| + "data" , + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "data" |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 150 + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "x0_bytes" , + M.call (| + M.get_name (| globals, "buffer_read" |), + make_list [ + M.get_name (| globals, "data" |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 32 + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "x0_value" , + M.call (| + M.get_field (| M.get_name (| globals, "U256" |), "from_be_bytes" |), + make_list [ + M.get_name (| globals, "x0_bytes" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "y0_bytes" , + M.call (| + M.get_name (| globals, "buffer_read" |), + make_list [ + M.get_name (| globals, "data" |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 32 + ], + make_dict [] + |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 32 + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "y0_value" , + M.call (| + M.get_field (| M.get_name (| globals, "U256" |), "from_be_bytes" |), + make_list [ + M.get_name (| globals, "y0_bytes" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "x1_bytes" , + M.call (| + M.get_name (| globals, "buffer_read" |), + make_list [ + M.get_name (| globals, "data" |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 64 + ], + make_dict [] + |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 32 + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "x1_value" , + M.call (| + M.get_field (| M.get_name (| globals, "U256" |), "from_be_bytes" |), + make_list [ + M.get_name (| globals, "x1_bytes" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "y1_bytes" , + M.call (| + M.get_name (| globals, "buffer_read" |), + make_list [ + M.get_name (| globals, "data" |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 96 + ], + make_dict [] + |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 32 + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "y1_value" , + M.call (| + M.get_field (| M.get_name (| globals, "U256" |), "from_be_bytes" |), + make_list [ + M.get_name (| globals, "y1_bytes" |) + ], + make_dict [] + |) + |) in + let _ := + M.for_ (| + M.get_name (| globals, "i" |), + make_tuple [ M.get_name (| globals, "x0_value" |); M.get_name (| globals, "y0_value" |); M.get_name (| globals, "x1_value" |); M.get_name (| globals, "y1_value" |) ], + ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + Compare.gt_e (| + M.get_name (| globals, "i" |), + M.get_name (| globals, "ALT_BN128_PRIME" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, "OutOfGasError" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in +(* At stmt: unsupported node type: Try *) + let _ := M.assign_local (| + "p" , + BinOp.add (| + M.get_name (| globals, "p0" |), + M.get_name (| globals, "p1" |) + |) + |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, "evm" |), "output" |), + BinOp.add (| + M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, "p" |), "x" |), "to_be_bytes32" |), + make_list [], + make_dict [] + |), + M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, "p" |), "y" |), "to_be_bytes32" |), + make_list [], + make_dict [] + |) + |) + |) in + M.pure Constant.None_)). + +Definition alt_bn128_mul : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + The ALT_BN128 multiplication precompiled contract. + + Parameters + ---------- + evm : + The current EVM frame. + " in + let _ := M.assign_local (| + "data" , + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "data" |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 6000 + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "x0_bytes" , + M.call (| + M.get_name (| globals, "buffer_read" |), + make_list [ + M.get_name (| globals, "data" |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 32 + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "x0_value" , + M.call (| + M.get_field (| M.get_name (| globals, "U256" |), "from_be_bytes" |), + make_list [ + M.get_name (| globals, "x0_bytes" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "y0_bytes" , + M.call (| + M.get_name (| globals, "buffer_read" |), + make_list [ + M.get_name (| globals, "data" |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 32 + ], + make_dict [] + |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 32 + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "y0_value" , + M.call (| + M.get_field (| M.get_name (| globals, "U256" |), "from_be_bytes" |), + make_list [ + M.get_name (| globals, "y0_bytes" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "n" , + M.call (| + M.get_field (| M.get_name (| globals, "U256" |), "from_be_bytes" |), + make_list [ + M.call (| + M.get_name (| globals, "buffer_read" |), + make_list [ + M.get_name (| globals, "data" |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 64 + ], + make_dict [] + |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 32 + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := + M.for_ (| + M.get_name (| globals, "i" |), + make_tuple [ M.get_name (| globals, "x0_value" |); M.get_name (| globals, "y0_value" |) ], + ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + Compare.gt_e (| + M.get_name (| globals, "i" |), + M.get_name (| globals, "ALT_BN128_PRIME" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, "OutOfGasError" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in +(* At stmt: unsupported node type: Try *) + let _ := M.assign_local (| + "p" , + M.call (| + M.get_field (| M.get_name (| globals, "p0" |), "mul_by" |), + make_list [ + M.get_name (| globals, "n" |) + ], + make_dict [] + |) + |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, "evm" |), "output" |), + BinOp.add (| + M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, "p" |), "x" |), "to_be_bytes32" |), + make_list [], + make_dict [] + |), + M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, "p" |), "y" |), "to_be_bytes32" |), + make_list [], + make_dict [] + |) + |) + |) in + M.pure Constant.None_)). + +Definition alt_bn128_pairing_check : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + The ALT_BN128 pairing check precompiled contract. + + Parameters + ---------- + evm : + The current EVM frame. + " in + let _ := M.assign_local (| + "data" , + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "data" |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + BinOp.add (| + BinOp.mult (| + Constant.int 34000, + BinOp.floor_div (| + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_name (| globals, "data" |) + ], + make_dict [] + |), + Constant.int 192 + |) + |), + Constant.int 45000 + |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.not_eq (| + BinOp.mod_ (| + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_name (| globals, "data" |) + ], + make_dict [] + |), + Constant.int 192 + |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, "OutOfGasError" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "result" , + M.call (| + M.get_field (| M.get_name (| globals, "BNF12" |), "from_int" |), + make_list [ + Constant.int 1 + ], + make_dict [] + |) + |) in + let _ := + M.for_ (| + M.get_name (| globals, "i" |), + M.call (| + M.get_name (| globals, "range" |), + make_list [ + BinOp.floor_div (| + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_name (| globals, "data" |) + ], + make_dict [] + |), + Constant.int 192 + |) + ], + make_dict [] + |), + ltac:(M.monadic ( + let _ := M.assign_local (| + "values" , + make_list [] + |) in + let _ := + M.for_ (| + M.get_name (| globals, "j" |), + M.call (| + M.get_name (| globals, "range" |), + make_list [ + Constant.int 6 + ], + make_dict [] + |), + ltac:(M.monadic ( + let _ := M.assign_local (| + "value" , + M.call (| + M.get_field (| M.get_name (| globals, "U256" |), "from_be_bytes" |), + make_list [ + M.slice (| + M.get_name (| globals, "data" |), + BinOp.add (| + BinOp.mult (| + M.get_name (| globals, "i" |), + Constant.int 192 + |), + BinOp.mult (| + Constant.int 32, + M.get_name (| globals, "j" |) + |) + |), + BinOp.add (| + BinOp.mult (| + M.get_name (| globals, "i" |), + Constant.int 192 + |), + BinOp.mult (| + Constant.int 32, + BinOp.add (| + M.get_name (| globals, "j" |), + Constant.int 1 + |) + |) + |), + Constant.None_ + |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.gt_e (| + M.get_name (| globals, "value" |), + M.get_name (| globals, "ALT_BN128_PRIME" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, "OutOfGasError" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.call (| + M.get_field (| M.get_name (| globals, "values" |), "append" |), + make_list [ + M.call (| + M.get_name (| globals, "int" |), + make_list [ + M.get_name (| globals, "value" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in +(* At stmt: unsupported node type: Try *) + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + Compare.eq (| + M.call (| + M.get_field (| M.get_name (| globals, "p" |), "mul_by" |), + make_list [ + M.get_name (| globals, "ALT_BN128_CURVE_ORDER" |) + ], + make_dict [] + |), + M.call (| + M.get_field (| M.get_name (| globals, "BNP" |), "point_at_infinity" |), + make_list [], + make_dict [] + |) + |); + M.get_name (| globals, "OutOfGasError" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + Compare.eq (| + M.call (| + M.get_field (| M.get_name (| globals, "q" |), "mul_by" |), + make_list [ + M.get_name (| globals, "ALT_BN128_CURVE_ORDER" |) + ], + make_dict [] + |), + M.call (| + M.get_field (| M.get_name (| globals, "BNP2" |), "point_at_infinity" |), + make_list [], + make_dict [] + |) + |); + M.get_name (| globals, "OutOfGasError" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + BoolOp.and (| + Compare.not_eq (| + M.get_name (| globals, "p" |), + M.call (| + M.get_field (| M.get_name (| globals, "BNP" |), "point_at_infinity" |), + make_list [], + make_dict [] + |) + |), + ltac:(M.monadic ( + Compare.not_eq (| + M.get_name (| globals, "q" |), + M.call (| + M.get_field (| M.get_name (| globals, "BNP2" |), "point_at_infinity" |), + make_list [], + make_dict [] + |) + |) + )) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "result" , + BinOp.mult (| + M.get_name (| globals, "result" |), + M.call (| + M.get_name (| globals, "pairing" |), + make_list [ + M.get_name (| globals, "q" |); + M.get_name (| globals, "p" |) + ], + make_dict [] + |) + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, "result" |), + M.call (| + M.get_field (| M.get_name (| globals, "BNF12" |), "from_int" |), + make_list [ + Constant.int 1 + ], + make_dict [] + |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign (| + M.get_field (| M.get_name (| globals, "evm" |), "output" |), + M.call (| + M.get_field (| M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 1 + ], + make_dict [] + |), "to_be_bytes32" |), + make_list [], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign (| + M.get_field (| M.get_name (| globals, "evm" |), "output" |), + M.call (| + M.get_field (| M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |), "to_be_bytes32" |), + make_list [], + make_dict [] + |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_)). diff --git a/CoqOfPython/ethereum/paris/vm/precompiled_contracts/blake2f.v b/CoqOfPython/ethereum/paris/vm/precompiled_contracts/blake2f.v new file mode 100644 index 0000000..e4c8b13 --- /dev/null +++ b/CoqOfPython/ethereum/paris/vm/precompiled_contracts/blake2f.v @@ -0,0 +1,127 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.paris.vm.precompiled_contracts.blake2f". + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) Blake2 PRECOMPILED CONTRACT +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementation of the `Blake2` precompiled contract. +". + +Axiom ethereum_crypto_blake2_imports_Blake2b : + IsImported globals "ethereum.crypto.blake2" "Blake2b". + +Axiom ethereum_utils_ensure_imports_ensure : + IsImported globals "ethereum.utils.ensure" "ensure". + +Axiom ethereum_paris_vm_imports_Evm : + IsImported globals "ethereum.paris.vm" "Evm". + +Axiom ethereum_paris_vm_gas_imports_GAS_BLAKE2_PER_ROUND : + IsImported globals "ethereum.paris.vm.gas" "GAS_BLAKE2_PER_ROUND". +Axiom ethereum_paris_vm_gas_imports_charge_gas : + IsImported globals "ethereum.paris.vm.gas" "charge_gas". + +Axiom ethereum_paris_vm_exceptions_imports_InvalidParameter : + IsImported globals "ethereum.paris.vm.exceptions" "InvalidParameter". + +Definition blake2f : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Writes the Blake2 hash to output. + + Parameters + ---------- + evm : + The current EVM frame. + " in + let _ := M.assign_local (| + "data" , + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "data" |) + |) in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + Compare.eq (| + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_name (| globals, "data" |) + ], + make_dict [] + |), + Constant.int 213 + |); + M.get_name (| globals, "InvalidParameter" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "blake2b" , + M.call (| + M.get_name (| globals, "Blake2b" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.assign (| + make_tuple [ M.get_name (| globals, "rounds" |); M.get_name (| globals, "h" |); M.get_name (| globals, "m" |); M.get_name (| globals, "t_0" |); M.get_name (| globals, "t_1" |); M.get_name (| globals, "f" |) ], + M.call (| + M.get_field (| M.get_name (| globals, "blake2b" |), "get_blake2_parameters" |), + make_list [ + M.get_name (| globals, "data" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + BinOp.mult (| + M.get_name (| globals, "GAS_BLAKE2_PER_ROUND" |), + M.get_name (| globals, "rounds" |) + |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + Compare.in_ (| + M.get_name (| globals, "f" |), + make_list [ + Constant.int 0; + Constant.int 1 + ] + |); + M.get_name (| globals, "InvalidParameter" |) + ], + make_dict [] + |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, "evm" |), "output" |), + M.call (| + M.get_field (| M.get_name (| globals, "blake2b" |), "compress" |), + make_list [ + M.get_name (| globals, "rounds" |); + M.get_name (| globals, "h" |); + M.get_name (| globals, "m" |); + M.get_name (| globals, "t_0" |); + M.get_name (| globals, "t_1" |); + M.get_name (| globals, "f" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). diff --git a/CoqOfPython/ethereum/paris/vm/precompiled_contracts/ecrecover.v b/CoqOfPython/ethereum/paris/vm/precompiled_contracts/ecrecover.v new file mode 100644 index 0000000..62c83c2 --- /dev/null +++ b/CoqOfPython/ethereum/paris/vm/precompiled_contracts/ecrecover.v @@ -0,0 +1,301 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.paris.vm.precompiled_contracts.ecrecover". + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) ECRECOVER PRECOMPILED CONTRACT +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementation of the ECRECOVER precompiled contract. +". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". + +Axiom ethereum_crypto_elliptic_curve_imports_SECP256K1N : + IsImported globals "ethereum.crypto.elliptic_curve" "SECP256K1N". +Axiom ethereum_crypto_elliptic_curve_imports_secp256k1_recover : + IsImported globals "ethereum.crypto.elliptic_curve" "secp256k1_recover". + +Axiom ethereum_crypto_hash_imports_Hash32 : + IsImported globals "ethereum.crypto.hash" "Hash32". +Axiom ethereum_crypto_hash_imports_keccak256 : + IsImported globals "ethereum.crypto.hash" "keccak256". + +Axiom ethereum_utils_byte_imports_left_pad_zero_bytes : + IsImported globals "ethereum.utils.byte" "left_pad_zero_bytes". + +Axiom ethereum_paris_vm_imports_Evm : + IsImported globals "ethereum.paris.vm" "Evm". + +Axiom ethereum_paris_vm_gas_imports_GAS_ECRECOVER : + IsImported globals "ethereum.paris.vm.gas" "GAS_ECRECOVER". +Axiom ethereum_paris_vm_gas_imports_charge_gas : + IsImported globals "ethereum.paris.vm.gas" "charge_gas". + +Axiom ethereum_paris_vm_memory_imports_buffer_read : + IsImported globals "ethereum.paris.vm.memory" "buffer_read". + +Definition ecrecover : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Decrypts the address using elliptic curve DSA recovery mechanism and writes + the address to output. + + Parameters + ---------- + evm : + The current EVM frame. + " in + let _ := M.assign_local (| + "data" , + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "data" |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_ECRECOVER" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "message_hash_bytes" , + M.call (| + M.get_name (| globals, "buffer_read" |), + make_list [ + M.get_name (| globals, "data" |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 32 + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "message_hash" , + M.call (| + M.get_name (| globals, "Hash32" |), + make_list [ + M.get_name (| globals, "message_hash_bytes" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "v" , + M.call (| + M.get_field (| M.get_name (| globals, "U256" |), "from_be_bytes" |), + make_list [ + M.call (| + M.get_name (| globals, "buffer_read" |), + make_list [ + M.get_name (| globals, "data" |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 32 + ], + make_dict [] + |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 32 + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "r" , + M.call (| + M.get_field (| M.get_name (| globals, "U256" |), "from_be_bytes" |), + make_list [ + M.call (| + M.get_name (| globals, "buffer_read" |), + make_list [ + M.get_name (| globals, "data" |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 64 + ], + make_dict [] + |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 32 + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "s" , + M.call (| + M.get_field (| M.get_name (| globals, "U256" |), "from_be_bytes" |), + make_list [ + M.call (| + M.get_name (| globals, "buffer_read" |), + make_list [ + M.get_name (| globals, "data" |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 96 + ], + make_dict [] + |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 32 + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + BoolOp.and (| + Compare.not_eq (| + M.get_name (| globals, "v" |), + Constant.int 27 + |), + ltac:(M.monadic ( + Compare.not_eq (| + M.get_name (| globals, "v" |), + Constant.int 28 + |) + )) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + Constant.None_ + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + BoolOp.or (| + Compare.gt_e (| + Constant.int 0, + M.get_name (| globals, "r" |) + |), + ltac:(M.monadic ( + Compare.gt_e (| + M.get_name (| globals, "r" |), + M.get_name (| globals, "SECP256K1N" |) + |) + )) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + Constant.None_ + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + BoolOp.or (| + Compare.gt_e (| + Constant.int 0, + M.get_name (| globals, "s" |) + |), + ltac:(M.monadic ( + Compare.gt_e (| + M.get_name (| globals, "s" |), + M.get_name (| globals, "SECP256K1N" |) + |) + )) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + Constant.None_ + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in +(* At stmt: unsupported node type: Try *) + let _ := M.assign_local (| + "address" , + M.slice (| + M.call (| + M.get_name (| globals, "keccak256" |), + make_list [ + M.get_name (| globals, "public_key" |) + ], + make_dict [] + |), + Constant.int 12, + Constant.int 32, + Constant.None_ + |) + |) in + let _ := M.assign_local (| + "padded_address" , + M.call (| + M.get_name (| globals, "left_pad_zero_bytes" |), + make_list [ + M.get_name (| globals, "address" |); + Constant.int 32 + ], + make_dict [] + |) + |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, "evm" |), "output" |), + M.get_name (| globals, "padded_address" |) + |) in + M.pure Constant.None_)). diff --git a/CoqOfPython/ethereum/paris/vm/precompiled_contracts/identity.v b/CoqOfPython/ethereum/paris/vm/precompiled_contracts/identity.v new file mode 100644 index 0000000..1936c37 --- /dev/null +++ b/CoqOfPython/ethereum/paris/vm/precompiled_contracts/identity.v @@ -0,0 +1,94 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.paris.vm.precompiled_contracts.identity". + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) IDENTITY PRECOMPILED CONTRACT +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementation of the `IDENTITY` precompiled contract. +". + +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". + +Axiom ethereum_utils_numeric_imports_ceil32 : + IsImported globals "ethereum.utils.numeric" "ceil32". + +Axiom ethereum_paris_vm_imports_Evm : + IsImported globals "ethereum.paris.vm" "Evm". + +Axiom ethereum_paris_vm_gas_imports_GAS_IDENTITY : + IsImported globals "ethereum.paris.vm.gas" "GAS_IDENTITY". +Axiom ethereum_paris_vm_gas_imports_GAS_IDENTITY_WORD : + IsImported globals "ethereum.paris.vm.gas" "GAS_IDENTITY_WORD". +Axiom ethereum_paris_vm_gas_imports_charge_gas : + IsImported globals "ethereum.paris.vm.gas" "charge_gas". + +Definition identity : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Writes the message data to output. + + Parameters + ---------- + evm : + The current EVM frame. + " in + let _ := M.assign_local (| + "data" , + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "data" |) + |) in + let _ := M.assign_local (| + "word_count" , + BinOp.floor_div (| + M.call (| + M.get_name (| globals, "ceil32" |), + make_list [ + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_name (| globals, "data" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |), + Constant.int 32 + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + BinOp.add (| + M.get_name (| globals, "GAS_IDENTITY" |), + BinOp.mult (| + M.get_name (| globals, "GAS_IDENTITY_WORD" |), + M.get_name (| globals, "word_count" |) + |) + |) + ], + make_dict [] + |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, "evm" |), "output" |), + M.get_name (| globals, "data" |) + |) in + M.pure Constant.None_)). diff --git a/CoqOfPython/ethereum/paris/vm/precompiled_contracts/mapping.v b/CoqOfPython/ethereum/paris/vm/precompiled_contracts/mapping.v new file mode 100644 index 0000000..eb81d35 --- /dev/null +++ b/CoqOfPython/ethereum/paris/vm/precompiled_contracts/mapping.v @@ -0,0 +1,72 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.paris.vm.precompiled_contracts.mapping". + +Definition expr_1 : Value.t := + Constant.str " +Precompiled Contract Addresses +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Mapping of precompiled contracts their implementations. +". + +Axiom typing_imports_Callable : + IsImported globals "typing" "Callable". +Axiom typing_imports_Dict : + IsImported globals "typing" "Dict". + +Axiom ethereum_paris_fork_types_imports_Address : + IsImported globals "ethereum.paris.fork_types" "Address". + +Axiom ethereum_paris_vm_precompiled_contracts_imports_ALT_BN128_ADD_ADDRESS : + IsImported globals "ethereum.paris.vm.precompiled_contracts" "ALT_BN128_ADD_ADDRESS". +Axiom ethereum_paris_vm_precompiled_contracts_imports_ALT_BN128_MUL_ADDRESS : + IsImported globals "ethereum.paris.vm.precompiled_contracts" "ALT_BN128_MUL_ADDRESS". +Axiom ethereum_paris_vm_precompiled_contracts_imports_ALT_BN128_PAIRING_CHECK_ADDRESS : + IsImported globals "ethereum.paris.vm.precompiled_contracts" "ALT_BN128_PAIRING_CHECK_ADDRESS". +Axiom ethereum_paris_vm_precompiled_contracts_imports_BLAKE2F_ADDRESS : + IsImported globals "ethereum.paris.vm.precompiled_contracts" "BLAKE2F_ADDRESS". +Axiom ethereum_paris_vm_precompiled_contracts_imports_ECRECOVER_ADDRESS : + IsImported globals "ethereum.paris.vm.precompiled_contracts" "ECRECOVER_ADDRESS". +Axiom ethereum_paris_vm_precompiled_contracts_imports_IDENTITY_ADDRESS : + IsImported globals "ethereum.paris.vm.precompiled_contracts" "IDENTITY_ADDRESS". +Axiom ethereum_paris_vm_precompiled_contracts_imports_MODEXP_ADDRESS : + IsImported globals "ethereum.paris.vm.precompiled_contracts" "MODEXP_ADDRESS". +Axiom ethereum_paris_vm_precompiled_contracts_imports_RIPEMD160_ADDRESS : + IsImported globals "ethereum.paris.vm.precompiled_contracts" "RIPEMD160_ADDRESS". +Axiom ethereum_paris_vm_precompiled_contracts_imports_SHA256_ADDRESS : + IsImported globals "ethereum.paris.vm.precompiled_contracts" "SHA256_ADDRESS". + +Axiom ethereum_paris_vm_precompiled_contracts_alt_bn128_imports_alt_bn128_add : + IsImported globals "ethereum.paris.vm.precompiled_contracts.alt_bn128" "alt_bn128_add". +Axiom ethereum_paris_vm_precompiled_contracts_alt_bn128_imports_alt_bn128_mul : + IsImported globals "ethereum.paris.vm.precompiled_contracts.alt_bn128" "alt_bn128_mul". +Axiom ethereum_paris_vm_precompiled_contracts_alt_bn128_imports_alt_bn128_pairing_check : + IsImported globals "ethereum.paris.vm.precompiled_contracts.alt_bn128" "alt_bn128_pairing_check". + +Axiom ethereum_paris_vm_precompiled_contracts_blake2f_imports_blake2f : + IsImported globals "ethereum.paris.vm.precompiled_contracts.blake2f" "blake2f". + +Axiom ethereum_paris_vm_precompiled_contracts_ecrecover_imports_ecrecover : + IsImported globals "ethereum.paris.vm.precompiled_contracts.ecrecover" "ecrecover". + +Axiom ethereum_paris_vm_precompiled_contracts_identity_imports_identity : + IsImported globals "ethereum.paris.vm.precompiled_contracts.identity" "identity". + +Axiom ethereum_paris_vm_precompiled_contracts_modexp_imports_modexp : + IsImported globals "ethereum.paris.vm.precompiled_contracts.modexp" "modexp". + +Axiom ethereum_paris_vm_precompiled_contracts_ripemd160_imports_ripemd160 : + IsImported globals "ethereum.paris.vm.precompiled_contracts.ripemd160" "ripemd160". + +Axiom ethereum_paris_vm_precompiled_contracts_sha256_imports_sha256 : + IsImported globals "ethereum.paris.vm.precompiled_contracts.sha256" "sha256". + +(* At top_level_stmt: unsupported node type: AnnAssign *) diff --git a/CoqOfPython/ethereum/paris/vm/precompiled_contracts/modexp.v b/CoqOfPython/ethereum/paris/vm/precompiled_contracts/modexp.v new file mode 100644 index 0000000..6904c05 --- /dev/null +++ b/CoqOfPython/ethereum/paris/vm/precompiled_contracts/modexp.v @@ -0,0 +1,676 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.paris.vm.precompiled_contracts.modexp". + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) MODEXP PRECOMPILED CONTRACT +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementation of the `MODEXP` precompiled contract. +". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_Bytes : + IsImported globals "ethereum.base_types" "Bytes". +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". + +Axiom ethereum_paris_vm_imports_Evm : + IsImported globals "ethereum.paris.vm" "Evm". + +Axiom ethereum_paris_vm_gas_imports_charge_gas : + IsImported globals "ethereum.paris.vm.gas" "charge_gas". + +Axiom ethereum_paris_vm_memory_imports_buffer_read : + IsImported globals "ethereum.paris.vm.memory" "buffer_read". + +Definition GQUADDIVISOR : Value.t := M.run ltac:(M.monadic ( + Constant.int 3 +)). + +Definition modexp : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Calculates `(base**exp) % modulus` for arbitrary sized `base`, `exp` and. + `modulus`. The return value is the same length as the modulus. + " in + let _ := M.assign_local (| + "data" , + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "data" |) + |) in + let _ := M.assign_local (| + "base_length" , + M.call (| + M.get_field (| M.get_name (| globals, "U256" |), "from_be_bytes" |), + make_list [ + M.call (| + M.get_name (| globals, "buffer_read" |), + make_list [ + M.get_name (| globals, "data" |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 32 + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "exp_length" , + M.call (| + M.get_field (| M.get_name (| globals, "U256" |), "from_be_bytes" |), + make_list [ + M.call (| + M.get_name (| globals, "buffer_read" |), + make_list [ + M.get_name (| globals, "data" |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 32 + ], + make_dict [] + |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 32 + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "modulus_length" , + M.call (| + M.get_field (| M.get_name (| globals, "U256" |), "from_be_bytes" |), + make_list [ + M.call (| + M.get_name (| globals, "buffer_read" |), + make_list [ + M.get_name (| globals, "data" |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 64 + ], + make_dict [] + |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 32 + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "exp_start" , + BinOp.add (| + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 96 + ], + make_dict [] + |), + M.get_name (| globals, "base_length" |) + |) + |) in + let _ := M.assign_local (| + "exp_head" , + M.call (| + M.get_field (| M.get_name (| globals, "Uint" |), "from_be_bytes" |), + make_list [ + M.call (| + M.get_name (| globals, "buffer_read" |), + make_list [ + M.get_name (| globals, "data" |); + M.get_name (| globals, "exp_start" |); + M.call (| + M.get_name (| globals, "min" |), + make_list [ + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 32 + ], + make_dict [] + |); + M.get_name (| globals, "exp_length" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.call (| + M.get_name (| globals, "gas_cost" |), + make_list [ + M.get_name (| globals, "base_length" |); + M.get_name (| globals, "modulus_length" |); + M.get_name (| globals, "exp_length" |); + M.get_name (| globals, "exp_head" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + BoolOp.and (| + Compare.eq (| + M.get_name (| globals, "base_length" |), + Constant.int 0 + |), + ltac:(M.monadic ( + Compare.eq (| + M.get_name (| globals, "modulus_length" |), + Constant.int 0 + |) + )) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign (| + M.get_field (| M.get_name (| globals, "evm" |), "output" |), + M.call (| + M.get_name (| globals, "Bytes" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.return_ (| + Constant.None_ + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "base" , + M.call (| + M.get_field (| M.get_name (| globals, "Uint" |), "from_be_bytes" |), + make_list [ + M.call (| + M.get_name (| globals, "buffer_read" |), + make_list [ + M.get_name (| globals, "data" |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 96 + ], + make_dict [] + |); + M.get_name (| globals, "base_length" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "exp" , + M.call (| + M.get_field (| M.get_name (| globals, "Uint" |), "from_be_bytes" |), + make_list [ + M.call (| + M.get_name (| globals, "buffer_read" |), + make_list [ + M.get_name (| globals, "data" |); + M.get_name (| globals, "exp_start" |); + M.get_name (| globals, "exp_length" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "modulus_start" , + BinOp.add (| + M.get_name (| globals, "exp_start" |), + M.get_name (| globals, "exp_length" |) + |) + |) in + let _ := M.assign_local (| + "modulus" , + M.call (| + M.get_field (| M.get_name (| globals, "Uint" |), "from_be_bytes" |), + make_list [ + M.call (| + M.get_name (| globals, "buffer_read" |), + make_list [ + M.get_name (| globals, "data" |); + M.get_name (| globals, "modulus_start" |); + M.get_name (| globals, "modulus_length" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, "modulus" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign (| + M.get_field (| M.get_name (| globals, "evm" |), "output" |), + BinOp.mult (| + M.call (| + M.get_name (| globals, "Bytes" |), + make_list [ + Constant.bytes "00" + ], + make_dict [] + |), + M.get_name (| globals, "modulus_length" |) + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign (| + M.get_field (| M.get_name (| globals, "evm" |), "output" |), + M.call (| + M.get_field (| M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, "pow" |), + make_list [ + M.get_name (| globals, "base" |); + M.get_name (| globals, "exp" |); + M.get_name (| globals, "modulus" |) + ], + make_dict [] + |) + ], + make_dict [] + |), "to_bytes" |), + make_list [ + M.get_name (| globals, "modulus_length" |); + Constant.str "big" + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_)). + +Definition complexity : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "base_length"; "modulus_length" ] |) in + let _ := Constant.str " + Estimate the complexity of performing a modular exponentiation. + + Parameters + ---------- + + base_length : + Length of the array representing the base integer. + + modulus_length : + Length of the array representing the modulus integer. + + Returns + ------- + + complexity : `Uint` + Complexity of performing the operation. + " in + let _ := M.assign_local (| + "max_length" , + M.call (| + M.get_name (| globals, "max" |), + make_list [ + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.get_name (| globals, "base_length" |) + ], + make_dict [] + |); + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.get_name (| globals, "modulus_length" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "words" , + BinOp.floor_div (| + BinOp.add (| + M.get_name (| globals, "max_length" |), + Constant.int 7 + |), + Constant.int 8 + |) + |) in + let _ := M.return_ (| + BinOp.pow (| + M.get_name (| globals, "words" |), + Constant.int 2 + |) + |) in + M.pure Constant.None_)). + +Definition iterations : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "exponent_length"; "exponent_head" ] |) in + let _ := Constant.str " + Calculate the number of iterations required to perform a modular + exponentiation. + + Parameters + ---------- + + exponent_length : + Length of the array representing the exponent integer. + + exponent_head : + First 32 bytes of the exponent (with leading zero padding if it is + shorter than 32 bytes), as an unsigned integer. + + Returns + ------- + + iterations : `Uint` + Number of iterations. + " in + let _ := + (* if *) + M.if_then_else (| + BoolOp.and (| + Compare.lt_e (| + M.get_name (| globals, "exponent_length" |), + Constant.int 32 + |), + ltac:(M.monadic ( + Compare.eq (| + M.get_name (| globals, "exponent_head" |), + Constant.int 0 + |) + )) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "count" , + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + Compare.lt_e (| + M.get_name (| globals, "exponent_length" |), + Constant.int 32 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "bit_length" , + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.call (| + M.get_field (| M.get_name (| globals, "exponent_head" |), "bit_length" |), + make_list [], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.gt (| + M.get_name (| globals, "bit_length" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_op_local (| + BinOp.sub, + "bit_length", + Constant.int 1 + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "count" , + M.get_name (| globals, "bit_length" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "length_part" , + BinOp.mult (| + Constant.int 8, + BinOp.sub (| + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.get_name (| globals, "exponent_length" |) + ], + make_dict [] + |), + Constant.int 32 + |) + |) + |) in + let _ := M.assign_local (| + "bits_part" , + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.call (| + M.get_field (| M.get_name (| globals, "exponent_head" |), "bit_length" |), + make_list [], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.gt (| + M.get_name (| globals, "bits_part" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_op_local (| + BinOp.sub, + "bits_part", + Constant.int 1 + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "count" , + BinOp.add (| + M.get_name (| globals, "length_part" |), + M.get_name (| globals, "bits_part" |) + |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )) |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, "max" |), + make_list [ + M.get_name (| globals, "count" |); + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 1 + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Definition gas_cost : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "base_length"; "modulus_length"; "exponent_length"; "exponent_head" ] |) in + let _ := Constant.str " + Calculate the gas cost of performing a modular exponentiation. + + Parameters + ---------- + + base_length : + Length of the array representing the base integer. + + modulus_length : + Length of the array representing the modulus integer. + + exponent_length : + Length of the array representing the exponent integer. + + exponent_head : + First 32 bytes of the exponent (with leading zero padding if it is + shorter than 32 bytes), as an unsigned integer. + + Returns + ------- + + gas_cost : `Uint` + Gas required for performing the operation. + " in + let _ := M.assign_local (| + "multiplication_complexity" , + M.call (| + M.get_name (| globals, "complexity" |), + make_list [ + M.get_name (| globals, "base_length" |); + M.get_name (| globals, "modulus_length" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "iteration_count" , + M.call (| + M.get_name (| globals, "iterations" |), + make_list [ + M.get_name (| globals, "exponent_length" |); + M.get_name (| globals, "exponent_head" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "cost" , + BinOp.mult (| + M.get_name (| globals, "multiplication_complexity" |), + M.get_name (| globals, "iteration_count" |) + |) + |) in + let _ := M.assign_op_local (| + BinOp.floor_div, + "cost", + M.get_name (| globals, "GQUADDIVISOR" |) + |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, "max" |), + make_list [ + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 200 + ], + make_dict [] + |); + M.get_name (| globals, "cost" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). diff --git a/CoqOfPython/ethereum/paris/vm/precompiled_contracts/ripemd160.v b/CoqOfPython/ethereum/paris/vm/precompiled_contracts/ripemd160.v new file mode 100644 index 0000000..5a9416e --- /dev/null +++ b/CoqOfPython/ethereum/paris/vm/precompiled_contracts/ripemd160.v @@ -0,0 +1,125 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.paris.vm.precompiled_contracts.ripemd160". + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) RIPEMD160 PRECOMPILED CONTRACT +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementation of the `RIPEMD160` precompiled contract. +". + +(* At top_level_stmt: unsupported node type: Import *) + +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". + +Axiom ethereum_utils_byte_imports_left_pad_zero_bytes : + IsImported globals "ethereum.utils.byte" "left_pad_zero_bytes". + +Axiom ethereum_utils_numeric_imports_ceil32 : + IsImported globals "ethereum.utils.numeric" "ceil32". + +Axiom ethereum_paris_vm_imports_Evm : + IsImported globals "ethereum.paris.vm" "Evm". + +Axiom ethereum_paris_vm_gas_imports_GAS_RIPEMD160 : + IsImported globals "ethereum.paris.vm.gas" "GAS_RIPEMD160". +Axiom ethereum_paris_vm_gas_imports_GAS_RIPEMD160_WORD : + IsImported globals "ethereum.paris.vm.gas" "GAS_RIPEMD160_WORD". +Axiom ethereum_paris_vm_gas_imports_charge_gas : + IsImported globals "ethereum.paris.vm.gas" "charge_gas". + +Definition ripemd160 : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Writes the ripemd160 hash to output. + + Parameters + ---------- + evm : + The current EVM frame. + " in + let _ := M.assign_local (| + "data" , + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "data" |) + |) in + let _ := M.assign_local (| + "word_count" , + BinOp.floor_div (| + M.call (| + M.get_name (| globals, "ceil32" |), + make_list [ + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_name (| globals, "data" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |), + Constant.int 32 + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + BinOp.add (| + M.get_name (| globals, "GAS_RIPEMD160" |), + BinOp.mult (| + M.get_name (| globals, "GAS_RIPEMD160_WORD" |), + M.get_name (| globals, "word_count" |) + |) + |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "hash_bytes" , + M.call (| + M.get_field (| M.call (| + M.get_field (| M.get_name (| globals, "hashlib" |), "new" |), + make_list [ + Constant.str "ripemd160"; + M.get_name (| globals, "data" |) + ], + make_dict [] + |), "digest" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "padded_hash" , + M.call (| + M.get_name (| globals, "left_pad_zero_bytes" |), + make_list [ + M.get_name (| globals, "hash_bytes" |); + Constant.int 32 + ], + make_dict [] + |) + |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, "evm" |), "output" |), + M.get_name (| globals, "padded_hash" |) + |) in + M.pure Constant.None_)). diff --git a/CoqOfPython/ethereum/paris/vm/precompiled_contracts/sha256.v b/CoqOfPython/ethereum/paris/vm/precompiled_contracts/sha256.v new file mode 100644 index 0000000..882cecd --- /dev/null +++ b/CoqOfPython/ethereum/paris/vm/precompiled_contracts/sha256.v @@ -0,0 +1,106 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.paris.vm.precompiled_contracts.sha256". + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) SHA256 PRECOMPILED CONTRACT +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementation of the `SHA256` precompiled contract. +". + +(* At top_level_stmt: unsupported node type: Import *) + +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". + +Axiom ethereum_utils_numeric_imports_ceil32 : + IsImported globals "ethereum.utils.numeric" "ceil32". + +Axiom ethereum_paris_vm_imports_Evm : + IsImported globals "ethereum.paris.vm" "Evm". + +Axiom ethereum_paris_vm_gas_imports_GAS_SHA256 : + IsImported globals "ethereum.paris.vm.gas" "GAS_SHA256". +Axiom ethereum_paris_vm_gas_imports_GAS_SHA256_WORD : + IsImported globals "ethereum.paris.vm.gas" "GAS_SHA256_WORD". +Axiom ethereum_paris_vm_gas_imports_charge_gas : + IsImported globals "ethereum.paris.vm.gas" "charge_gas". + +Definition sha256 : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Writes the sha256 hash to output. + + Parameters + ---------- + evm : + The current EVM frame. + " in + let _ := M.assign_local (| + "data" , + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "data" |) + |) in + let _ := M.assign_local (| + "word_count" , + BinOp.floor_div (| + M.call (| + M.get_name (| globals, "ceil32" |), + make_list [ + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_name (| globals, "data" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |), + Constant.int 32 + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + BinOp.add (| + M.get_name (| globals, "GAS_SHA256" |), + BinOp.mult (| + M.get_name (| globals, "GAS_SHA256_WORD" |), + M.get_name (| globals, "word_count" |) + |) + |) + ], + make_dict [] + |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, "evm" |), "output" |), + M.call (| + M.get_field (| M.call (| + M.get_field (| M.get_name (| globals, "hashlib" |), "sha256" |), + make_list [ + M.get_name (| globals, "data" |) + ], + make_dict [] + |), "digest" |), + make_list [], + make_dict [] + |) + |) in + M.pure Constant.None_)). diff --git a/CoqOfPython/ethereum/paris/vm/runtime.v b/CoqOfPython/ethereum/paris/vm/runtime.v new file mode 100644 index 0000000..4733e48 --- /dev/null +++ b/CoqOfPython/ethereum/paris/vm/runtime.v @@ -0,0 +1,157 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.paris.vm.runtime". + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) Runtime Operations +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Runtime related operations used while executing EVM code. +". + +Axiom typing_imports_Set : + IsImported globals "typing" "Set". + +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". + +Axiom ethereum_paris_vm_instructions_imports_Ops : + IsImported globals "ethereum.paris.vm.instructions" "Ops". + +Definition get_valid_jump_destinations : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "code" ] |) in + let _ := Constant.str " + Analyze the evm code to obtain the set of valid jump destinations. + + Valid jump destinations are defined as follows: + * The jump destination is less than the length of the code. + * The jump destination should have the `JUMPDEST` opcode (0x5B). + * The jump destination shouldn't be part of the data corresponding to + `PUSH-N` opcodes. + + Note - Jump destinations are 0-indexed. + + Parameters + ---------- + code : + The EVM code which is to be executed. + + Returns + ------- + valid_jump_destinations: `Set[Uint]` + The set of valid jump destinations in the code. + " in + let _ := M.assign_local (| + "valid_jump_destinations" , + M.call (| + M.get_name (| globals, "set" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "pc" , + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + |) in + let _ := + M.while (| + Compare.lt (| + M.get_name (| globals, "pc" |), + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_name (| globals, "code" |) + ], + make_dict [] + |) + |), + ltac:(M.monadic ( +(* At stmt: unsupported node type: Try *) + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, "current_opcode" |), + M.get_field (| M.get_name (| globals, "Ops" |), "JUMPDEST" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_field (| M.get_name (| globals, "valid_jump_destinations" |), "add" |), + make_list [ + M.get_name (| globals, "pc" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + BoolOp.and (| + Compare.lt_e (| + M.get_field (| M.get_field (| M.get_name (| globals, "Ops" |), "PUSH1" |), "value" |), + M.get_field (| M.get_name (| globals, "current_opcode" |), "value" |) + |), + ltac:(M.monadic ( + Compare.lt_e (| + M.get_field (| M.get_name (| globals, "current_opcode" |), "value" |), + M.get_field (| M.get_field (| M.get_name (| globals, "Ops" |), "PUSH32" |), "value" |) + |) + )) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "push_data_size" , + BinOp.add (| + BinOp.sub (| + M.get_field (| M.get_name (| globals, "current_opcode" |), "value" |), + M.get_field (| M.get_field (| M.get_name (| globals, "Ops" |), "PUSH1" |), "value" |) + |), + Constant.int 1 + |) + |) in + let _ := M.assign_op_local (| + BinOp.add, + "pc", + M.get_name (| globals, "push_data_size" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )) |) in + let _ := M.assign_op_local (| + BinOp.add, + "pc", + Constant.int 1 + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := M.return_ (| + M.get_name (| globals, "valid_jump_destinations" |) + |) in + M.pure Constant.None_)). diff --git a/CoqOfPython/ethereum/paris/vm/stack.v b/CoqOfPython/ethereum/paris/vm/stack.v new file mode 100644 index 0000000..026c5b4 --- /dev/null +++ b/CoqOfPython/ethereum/paris/vm/stack.v @@ -0,0 +1,123 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.paris.vm.stack". + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) Stack +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementation of the stack operators for the EVM. +". + +Axiom typing_imports_List : + IsImported globals "typing" "List". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". + +Axiom ethereum_paris_vm_exceptions_imports_StackOverflowError : + IsImported globals "ethereum.paris.vm.exceptions" "StackOverflowError". +Axiom ethereum_paris_vm_exceptions_imports_StackUnderflowError : + IsImported globals "ethereum.paris.vm.exceptions" "StackUnderflowError". + +Definition pop : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "stack" ] |) in + let _ := Constant.str " + Pops the top item off of `stack`. + + Parameters + ---------- + stack : + EVM stack. + + Returns + ------- + value : `U256` + The top element on the stack. + + " in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_name (| globals, "stack" |) + ], + make_dict [] + |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, "StackUnderflowError" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.return_ (| + M.call (| + M.get_field (| M.get_name (| globals, "stack" |), "pop" |), + make_list [], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Definition push : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "stack"; "value" ] |) in + let _ := Constant.str " + Pushes `value` onto `stack`. + + Parameters + ---------- + stack : + EVM stack. + + value : + Item to be pushed onto `stack`. + + " in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_name (| globals, "stack" |) + ], + make_dict [] + |), + Constant.int 1024 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, "StackOverflowError" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.return_ (| + M.call (| + M.get_field (| M.get_name (| globals, "stack" |), "append" |), + make_list [ + M.get_name (| globals, "value" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). diff --git a/CoqOfPython/ethereum/rlp.v b/CoqOfPython/ethereum/rlp.v new file mode 100644 index 0000000..d513852 --- /dev/null +++ b/CoqOfPython/ethereum/rlp.v @@ -0,0 +1,2435 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.rlp". + +Definition expr_1 : Value.t := + Constant.str " +.. _rlp: + +Recursive Length Prefix (RLP) Encoding +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Defines the serialization and deserialization format used throughout Ethereum. +". + +Axiom dataclasses_imports_astuple : + IsImported globals "dataclasses" "astuple". +Axiom dataclasses_imports_fields : + IsImported globals "dataclasses" "fields". +Axiom dataclasses_imports_is_dataclass : + IsImported globals "dataclasses" "is_dataclass". + +Axiom typing_imports_Any : + IsImported globals "typing" "Any". +Axiom typing_imports_List : + IsImported globals "typing" "List". +Axiom typing_imports_Sequence : + IsImported globals "typing" "Sequence". +Axiom typing_imports_Tuple : + IsImported globals "typing" "Tuple". +Axiom typing_imports_Type : + IsImported globals "typing" "Type". +Axiom typing_imports_TypeVar : + IsImported globals "typing" "TypeVar". +Axiom typing_imports_Union : + IsImported globals "typing" "Union". +Axiom typing_imports_cast : + IsImported globals "typing" "cast". + +Axiom ethereum_crypto_hash_imports_Hash32 : + IsImported globals "ethereum.crypto.hash" "Hash32". +Axiom ethereum_crypto_hash_imports_keccak256 : + IsImported globals "ethereum.crypto.hash" "keccak256". + +Axiom ethereum_exceptions_imports_RLPDecodingError : + IsImported globals "ethereum.exceptions" "RLPDecodingError". +Axiom ethereum_exceptions_imports_RLPEncodingError : + IsImported globals "ethereum.exceptions" "RLPEncodingError". + +Axiom ethereum_utils_ensure_imports_ensure : + IsImported globals "ethereum.utils.ensure" "ensure". + +Axiom ethereum_base_types_imports_Bytes : + IsImported globals "ethereum.base_types" "Bytes". +Axiom ethereum_base_types_imports_Bytes0 : + IsImported globals "ethereum.base_types" "Bytes0". +Axiom ethereum_base_types_imports_Bytes20 : + IsImported globals "ethereum.base_types" "Bytes20". +Axiom ethereum_base_types_imports_FixedBytes : + IsImported globals "ethereum.base_types" "FixedBytes". +Axiom ethereum_base_types_imports_FixedUint : + IsImported globals "ethereum.base_types" "FixedUint". +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". + +Definition RLP : Value.t := M.run ltac:(M.monadic ( + M.get_name (| globals, "Any" |) +)). + +Definition encode : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "raw_data" ] |) in + let _ := Constant.str " + Encodes `raw_data` into a sequence of bytes using RLP. + + Parameters + ---------- + raw_data : + A `Bytes`, `Uint`, `Uint256` or sequence of `RLP` encodable + objects. + + Returns + ------- + encoded : `ethereum.base_types.Bytes` + The RLP encoded bytes representing `raw_data`. + " in + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, "isinstance" |), + make_list [ + M.get_name (| globals, "raw_data" |); + make_tuple [ M.get_name (| globals, "bytearray" |); M.get_name (| globals, "bytes" |) ] + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + M.call (| + M.get_name (| globals, "encode_bytes" |), + make_list [ + M.get_name (| globals, "raw_data" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, "isinstance" |), + make_list [ + M.get_name (| globals, "raw_data" |); + make_tuple [ M.get_name (| globals, "Uint" |); M.get_name (| globals, "FixedUint" |) ] + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + M.call (| + M.get_name (| globals, "encode" |), + make_list [ + M.call (| + M.get_field (| M.get_name (| globals, "raw_data" |), "to_be_bytes" |), + make_list [], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, "isinstance" |), + make_list [ + M.get_name (| globals, "raw_data" |); + M.get_name (| globals, "str" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + M.call (| + M.get_name (| globals, "encode_bytes" |), + make_list [ + M.call (| + M.get_field (| M.get_name (| globals, "raw_data" |), "encode" |), + make_list [], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, "isinstance" |), + make_list [ + M.get_name (| globals, "raw_data" |); + M.get_name (| globals, "bool" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + M.get_name (| globals, "raw_data" |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + M.call (| + M.get_name (| globals, "encode_bytes" |), + make_list [ + Constant.bytes "01" + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.return_ (| + M.call (| + M.get_name (| globals, "encode_bytes" |), + make_list [ + Constant.bytes "" + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, "isinstance" |), + make_list [ + M.get_name (| globals, "raw_data" |); + M.get_name (| globals, "Sequence" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + M.call (| + M.get_name (| globals, "encode_sequence" |), + make_list [ + M.get_name (| globals, "raw_data" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, "is_dataclass" |), + make_list [ + M.get_name (| globals, "raw_data" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + M.call (| + M.get_name (| globals, "encode" |), + make_list [ + M.call (| + M.get_name (| globals, "astuple" |), + make_list [ + M.get_name (| globals, "raw_data" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.raise (| Some (M.call (| + M.get_name (| globals, "RLPEncodingError" |), + make_list [ + M.call (| + M.get_field (| Constant.str "RLP Encoding of type {} is not supported", "format" |), + make_list [ + M.call (| + M.get_name (| globals, "type" |), + make_list [ + M.get_name (| globals, "raw_data" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |)) |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_)). + +Definition encode_bytes : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "raw_bytes" ] |) in + let _ := Constant.str " + Encodes `raw_bytes`, a sequence of bytes, using RLP. + + Parameters + ---------- + raw_bytes : + Bytes to encode with RLP. + + Returns + ------- + encoded : `ethereum.base_types.Bytes` + The RLP encoded bytes representing `raw_bytes`. + " in + let _ := M.assign_local (| + "len_raw_data" , + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_name (| globals, "raw_bytes" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + BoolOp.and (| + Compare.eq (| + M.get_name (| globals, "len_raw_data" |), + Constant.int 1 + |), + ltac:(M.monadic ( + Compare.lt (| + M.get_subscript (| + M.get_name (| globals, "raw_bytes" |), + Constant.int 0 + |), + Constant.int 128 + |) + )) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + M.get_name (| globals, "raw_bytes" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + Compare.lt (| + M.get_name (| globals, "len_raw_data" |), + Constant.int 56 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + BinOp.add (| + M.call (| + M.get_name (| globals, "bytes" |), + make_list [ + make_list [ + BinOp.add (| + Constant.int 128, + M.get_name (| globals, "len_raw_data" |) + |) + ] + ], + make_dict [] + |), + M.get_name (| globals, "raw_bytes" |) + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "len_raw_data_as_be" , + M.call (| + M.get_field (| M.get_name (| globals, "len_raw_data" |), "to_be_bytes" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.return_ (| + BinOp.add (| + BinOp.add (| + M.call (| + M.get_name (| globals, "bytes" |), + make_list [ + make_list [ + BinOp.add (| + Constant.int 183, + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_name (| globals, "len_raw_data_as_be" |) + ], + make_dict [] + |) + |) + ] + ], + make_dict [] + |), + M.get_name (| globals, "len_raw_data_as_be" |) + |), + M.get_name (| globals, "raw_bytes" |) + |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_)). + +Definition encode_sequence : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "raw_sequence" ] |) in + let _ := Constant.str " + Encodes a list of RLP encodable objects (`raw_sequence`) using RLP. + + Parameters + ---------- + raw_sequence : + Sequence of RLP encodable objects. + + Returns + ------- + encoded : `ethereum.base_types.Bytes` + The RLP encoded bytes representing `raw_sequence`. + " in + let _ := M.assign_local (| + "joined_encodings" , + M.call (| + M.get_name (| globals, "get_joined_encodings" |), + make_list [ + M.get_name (| globals, "raw_sequence" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "len_joined_encodings" , + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_name (| globals, "joined_encodings" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.lt (| + M.get_name (| globals, "len_joined_encodings" |), + Constant.int 56 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + BinOp.add (| + M.call (| + M.get_name (| globals, "Bytes" |), + make_list [ + make_list [ + BinOp.add (| + Constant.int 192, + M.get_name (| globals, "len_joined_encodings" |) + |) + ] + ], + make_dict [] + |), + M.get_name (| globals, "joined_encodings" |) + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "len_joined_encodings_as_be" , + M.call (| + M.get_field (| M.get_name (| globals, "len_joined_encodings" |), "to_be_bytes" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.return_ (| + BinOp.add (| + BinOp.add (| + M.call (| + M.get_name (| globals, "Bytes" |), + make_list [ + make_list [ + BinOp.add (| + Constant.int 247, + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_name (| globals, "len_joined_encodings_as_be" |) + ], + make_dict [] + |) + |) + ] + ], + make_dict [] + |), + M.get_name (| globals, "len_joined_encodings_as_be" |) + |), + M.get_name (| globals, "joined_encodings" |) + |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_)). + +Definition get_joined_encodings : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "raw_sequence" ] |) in + let _ := Constant.str " + Obtain concatenation of rlp encoding for each item in the sequence + raw_sequence. + + Parameters + ---------- + raw_sequence : + Sequence to encode with RLP. + + Returns + ------- + joined_encodings : `ethereum.base_types.Bytes` + The concatenated RLP encoded bytes for each item in sequence + raw_sequence. + " in + let _ := M.return_ (| + M.call (| + M.get_field (| Constant.bytes "", "join" |), + make_list [ + Constant.str "(* At expr: unsupported node type: GeneratorExp *)" + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Definition decode : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "encoded_data" ] |) in + let _ := Constant.str " + Decodes an integer, byte sequence, or list of RLP encodable objects + from the byte sequence `encoded_data`, using RLP. + + Parameters + ---------- + encoded_data : + A sequence of bytes, in RLP form. + + Returns + ------- + decoded_data : `RLP` + Object decoded from `encoded_data`. + " in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + Compare.gt (| + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_name (| globals, "encoded_data" |) + ], + make_dict [] + |), + Constant.int 0 + |); + M.call (| + M.get_name (| globals, "RLPDecodingError" |), + make_list [ + Constant.str "Cannot decode empty bytestring" + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.lt_e (| + M.get_subscript (| + M.get_name (| globals, "encoded_data" |), + Constant.int 0 + |), + Constant.int 191 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + M.call (| + M.get_name (| globals, "decode_to_bytes" |), + make_list [ + M.get_name (| globals, "encoded_data" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.return_ (| + M.call (| + M.get_name (| globals, "decode_to_sequence" |), + make_list [ + M.get_name (| globals, "encoded_data" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_)). + +Definition T : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "TypeVar" |), + make_list [ + Constant.str "T" + ], + make_dict [] + |) +)). + +Definition decode_to : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "cls"; "encoded_data" ] |) in + let _ := Constant.str " + Decode the bytes in `encoded_data` to an object of type `cls`. `cls` can be + a `Bytes` subclass, a dataclass, `Uint`, `U256` or `Tuple[cls]`. + + Parameters + ---------- + cls: `Type[T]` + The type to decode to. + encoded_data : + A sequence of bytes, in RLP form. + + Returns + ------- + decoded_data : `T` + Object decoded from `encoded_data`. + " in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, "_decode_to" |), + make_list [ + M.get_name (| globals, "cls" |); + M.call (| + M.get_name (| globals, "decode" |), + make_list [ + M.get_name (| globals, "encoded_data" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Definition _decode_to : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "cls"; "raw_rlp" ] |) in + let _ := Constant.str " + Decode the rlp structure in `encoded_data` to an object of type `cls`. + `cls` can be a `Bytes` subclass, a dataclass, `Uint`, `U256`, + `Tuple[cls, ...]`, `Tuple[cls1, cls2]` or `Union[Bytes, cls]`. + + Parameters + ---------- + cls: `Type[T]` + The type to decode to. + raw_rlp : + A decoded rlp structure. + + Returns + ------- + decoded_data : `T` + Object decoded from `encoded_data`. + " in + let _ := + (* if *) + M.if_then_else (| + BoolOp.and (| + M.call (| + M.get_name (| globals, "isinstance" |), + make_list [ + M.get_name (| globals, "cls" |); + M.call (| + M.get_name (| globals, "type" |), + make_list [ + M.get_subscript (| + M.get_name (| globals, "Tuple" |), + make_tuple [ M.get_name (| globals, "Uint" |); Constant.ellipsis ] + |) + ], + make_dict [] + |) + ], + make_dict [] + |), + ltac:(M.monadic ( + Compare.eq (| + M.get_field (| M.get_name (| globals, "cls" |), "_name" |), + Constant.str "Tuple" + |) + )) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + M.call (| + M.get_name (| globals, "isinstance" |), + make_list [ + M.get_name (| globals, "raw_rlp" |); + M.get_name (| globals, "list" |) + ], + make_dict [] + |); + M.get_name (| globals, "RLPDecodingError" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_subscript (| + M.get_field (| M.get_name (| globals, "cls" |), "__args__" |), + Constant.int 1 + |), + Constant.ellipsis + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "args" , + make_list [] + |) in + let _ := + M.for_ (| + M.get_name (| globals, "raw_item" |), + M.get_name (| globals, "raw_rlp" |), + ltac:(M.monadic ( + let _ := M.call (| + M.get_field (| M.get_name (| globals, "args" |), "append" |), + make_list [ + M.call (| + M.get_name (| globals, "_decode_to" |), + make_list [ + M.get_subscript (| + M.get_field (| M.get_name (| globals, "cls" |), "__args__" |), + Constant.int 0 + |); + M.get_name (| globals, "raw_item" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, "tuple" |), + make_list [ + M.get_name (| globals, "args" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "args" , + make_list [] + |) in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + Compare.eq (| + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_name (| globals, "raw_rlp" |) + ], + make_dict [] + |), + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_field (| M.get_name (| globals, "cls" |), "__args__" |) + ], + make_dict [] + |) + |); + M.get_name (| globals, "RLPDecodingError" |) + ], + make_dict [] + |) in + let _ := + M.for_ (| + make_tuple [ M.get_name (| globals, "t" |); M.get_name (| globals, "raw_item" |) ], + M.call (| + M.get_name (| globals, "zip" |), + make_list [ + M.get_field (| M.get_name (| globals, "cls" |), "__args__" |); + M.get_name (| globals, "raw_rlp" |) + ], + make_dict [] + |), + ltac:(M.monadic ( + let _ := M.call (| + M.get_field (| M.get_name (| globals, "args" |), "append" |), + make_list [ + M.call (| + M.get_name (| globals, "_decode_to" |), + make_list [ + M.get_name (| globals, "t" |); + M.get_name (| globals, "raw_item" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, "tuple" |), + make_list [ + M.get_name (| globals, "args" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, "cls" |), + M.get_subscript (| + M.get_name (| globals, "Union" |), + make_tuple [ M.get_name (| globals, "Bytes0" |); M.get_name (| globals, "Bytes20" |) ] + |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + M.call (| + M.get_name (| globals, "isinstance" |), + make_list [ + M.get_name (| globals, "raw_rlp" |); + M.get_name (| globals, "Bytes" |) + ], + make_dict [] + |); + M.get_name (| globals, "RLPDecodingError" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_name (| globals, "raw_rlp" |) + ], + make_dict [] + |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + M.call (| + M.get_name (| globals, "Bytes0" |), + make_list [], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_name (| globals, "raw_rlp" |) + ], + make_dict [] + |), + Constant.int 20 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + M.call (| + M.get_name (| globals, "Bytes20" |), + make_list [ + M.get_name (| globals, "raw_rlp" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.raise (| Some (M.call (| + M.get_name (| globals, "RLPDecodingError" |), + make_list [ + M.call (| + M.get_field (| Constant.str "Bytes has length {}, expected 0 or 20", "format" |), + make_list [ + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_name (| globals, "raw_rlp" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |)) |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + BoolOp.and (| + M.call (| + M.get_name (| globals, "isinstance" |), + make_list [ + M.get_name (| globals, "cls" |); + M.call (| + M.get_name (| globals, "type" |), + make_list [ + M.get_subscript (| + M.get_name (| globals, "List" |), + M.get_name (| globals, "Bytes" |) + |) + ], + make_dict [] + |) + ], + make_dict [] + |), + ltac:(M.monadic ( + Compare.eq (| + M.get_field (| M.get_name (| globals, "cls" |), "_name" |), + Constant.str "List" + |) + )) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + M.call (| + M.get_name (| globals, "isinstance" |), + make_list [ + M.get_name (| globals, "raw_rlp" |); + M.get_name (| globals, "list" |) + ], + make_dict [] + |); + M.get_name (| globals, "RLPDecodingError" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "items" , + make_list [] + |) in + let _ := + M.for_ (| + M.get_name (| globals, "raw_item" |), + M.get_name (| globals, "raw_rlp" |), + ltac:(M.monadic ( + let _ := M.call (| + M.get_field (| M.get_name (| globals, "items" |), "append" |), + make_list [ + M.call (| + M.get_name (| globals, "_decode_to" |), + make_list [ + M.get_subscript (| + M.get_field (| M.get_name (| globals, "cls" |), "__args__" |), + Constant.int 0 + |); + M.get_name (| globals, "raw_item" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := M.return_ (| + M.get_name (| globals, "items" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + BoolOp.and (| + M.call (| + M.get_name (| globals, "isinstance" |), + make_list [ + M.get_name (| globals, "cls" |); + M.call (| + M.get_name (| globals, "type" |), + make_list [ + M.get_subscript (| + M.get_name (| globals, "Union" |), + make_tuple [ M.get_name (| globals, "Bytes" |); M.get_subscript (| + M.get_name (| globals, "List" |), + M.get_name (| globals, "Bytes" |) + |) ] + |) + ], + make_dict [] + |) + ], + make_dict [] + |), + ltac:(M.monadic ( + Compare.eq (| + M.get_field (| M.get_name (| globals, "cls" |), "__origin__" |), + M.get_name (| globals, "Union" |) + |) + )) + |), + (* then *) + ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + BoolOp.or (| + Compare.not_eq (| + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_field (| M.get_name (| globals, "cls" |), "__args__" |) + ], + make_dict [] + |), + Constant.int 2 + |), + ltac:(M.monadic ( + Compare.not_in (| + M.get_name (| globals, "Bytes" |), + M.get_field (| M.get_name (| globals, "cls" |), "__args__" |) + |) + )) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.call (| + M.get_name (| globals, "RLPDecodingError" |), + make_list [ + M.call (| + M.get_field (| Constant.str "RLP Decoding to type {} is not supported", "format" |), + make_list [ + M.get_name (| globals, "cls" |) + ], + make_dict [] + |) + ], + make_dict [] + |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, "isinstance" |), + make_list [ + M.get_name (| globals, "raw_rlp" |); + M.get_name (| globals, "Bytes" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + M.get_name (| globals, "raw_rlp" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_subscript (| + M.get_field (| M.get_name (| globals, "cls" |), "__args__" |), + Constant.int 0 + |), + M.get_name (| globals, "Bytes" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + M.call (| + M.get_name (| globals, "_decode_to" |), + make_list [ + M.get_subscript (| + M.get_field (| M.get_name (| globals, "cls" |), "__args__" |), + Constant.int 1 + |); + M.get_name (| globals, "raw_rlp" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.return_ (| + M.call (| + M.get_name (| globals, "_decode_to" |), + make_list [ + M.get_subscript (| + M.get_field (| M.get_name (| globals, "cls" |), "__args__" |), + Constant.int 0 + |); + M.get_name (| globals, "raw_rlp" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, "issubclass" |), + make_list [ + M.get_name (| globals, "cls" |); + M.get_name (| globals, "bool" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, "raw_rlp" |), + Constant.bytes "01" + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + M.call (| + M.get_name (| globals, "cls" |), + make_list [ + Constant.bool true + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, "raw_rlp" |), + Constant.bytes "" + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + M.call (| + M.get_name (| globals, "cls" |), + make_list [ + Constant.bool false + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.raise (| Some (M.call (| + M.get_name (| globals, "TypeError" |), + make_list [ + M.call (| + M.get_field (| Constant.str "Cannot decode {} as {}", "format" |), + make_list [ + M.get_name (| globals, "raw_rlp" |); + M.get_name (| globals, "cls" |) + ], + make_dict [] + |) + ], + make_dict [] + |)) |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, "issubclass" |), + make_list [ + M.get_name (| globals, "cls" |); + M.get_name (| globals, "FixedBytes" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + M.call (| + M.get_name (| globals, "isinstance" |), + make_list [ + M.get_name (| globals, "raw_rlp" |); + M.get_name (| globals, "Bytes" |) + ], + make_dict [] + |); + M.get_name (| globals, "RLPDecodingError" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + Compare.eq (| + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_name (| globals, "raw_rlp" |) + ], + make_dict [] + |), + M.get_field (| M.get_name (| globals, "cls" |), "LENGTH" |) + |); + M.get_name (| globals, "RLPDecodingError" |) + ], + make_dict [] + |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, "cls" |), + make_list [ + M.get_name (| globals, "raw_rlp" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, "issubclass" |), + make_list [ + M.get_name (| globals, "cls" |); + M.get_name (| globals, "Bytes" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + M.call (| + M.get_name (| globals, "isinstance" |), + make_list [ + M.get_name (| globals, "raw_rlp" |); + M.get_name (| globals, "Bytes" |) + ], + make_dict [] + |); + M.get_name (| globals, "RLPDecodingError" |) + ], + make_dict [] + |) in + let _ := M.return_ (| + M.get_name (| globals, "raw_rlp" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, "issubclass" |), + make_list [ + M.get_name (| globals, "cls" |); + make_tuple [ M.get_name (| globals, "Uint" |); M.get_name (| globals, "FixedUint" |) ] + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + M.call (| + M.get_name (| globals, "isinstance" |), + make_list [ + M.get_name (| globals, "raw_rlp" |); + M.get_name (| globals, "Bytes" |) + ], + make_dict [] + |); + M.get_name (| globals, "RLPDecodingError" |) + ], + make_dict [] + |) in +(* At stmt: unsupported node type: Try *) + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, "is_dataclass" |), + make_list [ + M.get_name (| globals, "cls" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + M.call (| + M.get_name (| globals, "isinstance" |), + make_list [ + M.get_name (| globals, "raw_rlp" |); + M.get_name (| globals, "list" |) + ], + make_dict [] + |); + M.get_name (| globals, "RLPDecodingError" |) + ], + make_dict [] + |) in + let _ := M.assert (| M.call (| + M.get_name (| globals, "isinstance" |), + make_list [ + M.get_name (| globals, "raw_rlp" |); + M.get_name (| globals, "list" |) + ], + make_dict [] + |) |) in + let _ := M.assign_local (| + "args" , + make_list [] + |) in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + Compare.eq (| + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.call (| + M.get_name (| globals, "fields" |), + make_list [ + M.get_name (| globals, "cls" |) + ], + make_dict [] + |) + ], + make_dict [] + |), + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_name (| globals, "raw_rlp" |) + ], + make_dict [] + |) + |); + M.get_name (| globals, "RLPDecodingError" |) + ], + make_dict [] + |) in + let _ := + M.for_ (| + make_tuple [ M.get_name (| globals, "field" |); M.get_name (| globals, "rlp_item" |) ], + M.call (| + M.get_name (| globals, "zip" |), + make_list [ + M.call (| + M.get_name (| globals, "fields" |), + make_list [ + M.get_name (| globals, "cls" |) + ], + make_dict [] + |); + M.get_name (| globals, "raw_rlp" |) + ], + make_dict [] + |), + ltac:(M.monadic ( + let _ := M.call (| + M.get_field (| M.get_name (| globals, "args" |), "append" |), + make_list [ + M.call (| + M.get_name (| globals, "_decode_to" |), + make_list [ + M.get_field (| M.get_name (| globals, "field" |), "type" |); + M.get_name (| globals, "rlp_item" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, "cast" |), + make_list [ + M.get_name (| globals, "T" |); + M.call (| + M.get_name (| globals, "cls" |), + M.get_name (| globals, "args" |), + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.raise (| Some (M.call (| + M.get_name (| globals, "RLPDecodingError" |), + make_list [ + M.call (| + M.get_field (| Constant.str "RLP Decoding to type {} is not supported", "format" |), + make_list [ + M.get_name (| globals, "cls" |) + ], + make_dict [] + |) + ], + make_dict [] + |)) |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_)). + +Definition decode_to_bytes : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "encoded_bytes" ] |) in + let _ := Constant.str " + Decodes a rlp encoded byte stream assuming that the decoded data + should be of type `bytes`. + + Parameters + ---------- + encoded_bytes : + RLP encoded byte stream. + + Returns + ------- + decoded : `ethereum.base_types.Bytes` + RLP decoded Bytes data + " in + let _ := + (* if *) + M.if_then_else (| + BoolOp.and (| + Compare.eq (| + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_name (| globals, "encoded_bytes" |) + ], + make_dict [] + |), + Constant.int 1 + |), + ltac:(M.monadic ( + Compare.lt (| + M.get_subscript (| + M.get_name (| globals, "encoded_bytes" |), + Constant.int 0 + |), + Constant.int 128 + |) + )) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + M.get_name (| globals, "encoded_bytes" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + Compare.lt_e (| + M.get_subscript (| + M.get_name (| globals, "encoded_bytes" |), + Constant.int 0 + |), + Constant.int 183 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "len_raw_data" , + BinOp.sub (| + M.get_subscript (| + M.get_name (| globals, "encoded_bytes" |), + Constant.int 0 + |), + Constant.int 128 + |) + |) in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + Compare.lt (| + M.get_name (| globals, "len_raw_data" |), + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_name (| globals, "encoded_bytes" |) + ], + make_dict [] + |) + |); + M.get_name (| globals, "RLPDecodingError" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "raw_data" , + M.slice (| + M.get_name (| globals, "encoded_bytes" |), + Constant.int 1, + BinOp.add (| + Constant.int 1, + M.get_name (| globals, "len_raw_data" |) + |), + Constant.None_ + |) + |) in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + UnOp.not (| BoolOp.and (| + Compare.eq (| + M.get_name (| globals, "len_raw_data" |), + Constant.int 1 + |), + ltac:(M.monadic ( + Compare.lt (| + M.get_subscript (| + M.get_name (| globals, "raw_data" |), + Constant.int 0 + |), + Constant.int 128 + |) + )) + |) |); + M.get_name (| globals, "RLPDecodingError" |) + ], + make_dict [] + |) in + let _ := M.return_ (| + M.get_name (| globals, "raw_data" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "decoded_data_start_idx" , + BinOp.sub (| + BinOp.add (| + Constant.int 1, + M.get_subscript (| + M.get_name (| globals, "encoded_bytes" |), + Constant.int 0 + |) + |), + Constant.int 183 + |) + |) in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + Compare.lt (| + BinOp.sub (| + M.get_name (| globals, "decoded_data_start_idx" |), + Constant.int 1 + |), + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_name (| globals, "encoded_bytes" |) + ], + make_dict [] + |) + |); + M.get_name (| globals, "RLPDecodingError" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + Compare.not_eq (| + M.get_subscript (| + M.get_name (| globals, "encoded_bytes" |), + Constant.int 1 + |), + Constant.int 0 + |); + M.get_name (| globals, "RLPDecodingError" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "len_decoded_data" , + M.call (| + M.get_field (| M.get_name (| globals, "Uint" |), "from_be_bytes" |), + make_list [ + M.slice (| + M.get_name (| globals, "encoded_bytes" |), + Constant.int 1, + M.get_name (| globals, "decoded_data_start_idx" |), + Constant.None_ + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + Compare.gt_e (| + M.get_name (| globals, "len_decoded_data" |), + Constant.int 56 + |); + M.get_name (| globals, "RLPDecodingError" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "decoded_data_end_idx" , + BinOp.add (| + M.get_name (| globals, "decoded_data_start_idx" |), + M.get_name (| globals, "len_decoded_data" |) + |) + |) in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + Compare.lt (| + BinOp.sub (| + M.get_name (| globals, "decoded_data_end_idx" |), + Constant.int 1 + |), + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_name (| globals, "encoded_bytes" |) + ], + make_dict [] + |) + |); + M.get_name (| globals, "RLPDecodingError" |) + ], + make_dict [] + |) in + let _ := M.return_ (| + M.slice (| + M.get_name (| globals, "encoded_bytes" |), + M.get_name (| globals, "decoded_data_start_idx" |), + M.get_name (| globals, "decoded_data_end_idx" |), + Constant.None_ + |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_)). + +Definition decode_to_sequence : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "encoded_sequence" ] |) in + let _ := Constant.str " + Decodes a rlp encoded byte stream assuming that the decoded data + should be of type `Sequence` of objects. + + Parameters + ---------- + encoded_sequence : + An RLP encoded Sequence. + + Returns + ------- + decoded : `Sequence[RLP]` + Sequence of objects decoded from `encoded_sequence`. + " in + let _ := + (* if *) + M.if_then_else (| + Compare.lt_e (| + M.get_subscript (| + M.get_name (| globals, "encoded_sequence" |), + Constant.int 0 + |), + Constant.int 247 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "len_joined_encodings" , + BinOp.sub (| + M.get_subscript (| + M.get_name (| globals, "encoded_sequence" |), + Constant.int 0 + |), + Constant.int 192 + |) + |) in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + Compare.lt (| + M.get_name (| globals, "len_joined_encodings" |), + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_name (| globals, "encoded_sequence" |) + ], + make_dict [] + |) + |); + M.get_name (| globals, "RLPDecodingError" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "joined_encodings" , + M.slice (| + M.get_name (| globals, "encoded_sequence" |), + Constant.int 1, + BinOp.add (| + Constant.int 1, + M.get_name (| globals, "len_joined_encodings" |) + |), + Constant.None_ + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "joined_encodings_start_idx" , + BinOp.sub (| + BinOp.add (| + Constant.int 1, + M.get_subscript (| + M.get_name (| globals, "encoded_sequence" |), + Constant.int 0 + |) + |), + Constant.int 247 + |) + |) in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + Compare.lt (| + BinOp.sub (| + M.get_name (| globals, "joined_encodings_start_idx" |), + Constant.int 1 + |), + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_name (| globals, "encoded_sequence" |) + ], + make_dict [] + |) + |); + M.get_name (| globals, "RLPDecodingError" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + Compare.not_eq (| + M.get_subscript (| + M.get_name (| globals, "encoded_sequence" |), + Constant.int 1 + |), + Constant.int 0 + |); + M.get_name (| globals, "RLPDecodingError" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "len_joined_encodings" , + M.call (| + M.get_field (| M.get_name (| globals, "Uint" |), "from_be_bytes" |), + make_list [ + M.slice (| + M.get_name (| globals, "encoded_sequence" |), + Constant.int 1, + M.get_name (| globals, "joined_encodings_start_idx" |), + Constant.None_ + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + Compare.gt_e (| + M.get_name (| globals, "len_joined_encodings" |), + Constant.int 56 + |); + M.get_name (| globals, "RLPDecodingError" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "joined_encodings_end_idx" , + BinOp.add (| + M.get_name (| globals, "joined_encodings_start_idx" |), + M.get_name (| globals, "len_joined_encodings" |) + |) + |) in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + Compare.lt (| + BinOp.sub (| + M.get_name (| globals, "joined_encodings_end_idx" |), + Constant.int 1 + |), + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_name (| globals, "encoded_sequence" |) + ], + make_dict [] + |) + |); + M.get_name (| globals, "RLPDecodingError" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "joined_encodings" , + M.slice (| + M.get_name (| globals, "encoded_sequence" |), + M.get_name (| globals, "joined_encodings_start_idx" |), + M.get_name (| globals, "joined_encodings_end_idx" |), + Constant.None_ + |) + |) in + M.pure Constant.None_ + )) |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, "decode_joined_encodings" |), + make_list [ + M.get_name (| globals, "joined_encodings" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Definition decode_joined_encodings : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "joined_encodings" ] |) in + let _ := Constant.str " + Decodes `joined_encodings`, which is a concatenation of RLP encoded + objects. + + Parameters + ---------- + joined_encodings : + concatenation of RLP encoded objects + + Returns + ------- + decoded : `List[RLP]` + A list of objects decoded from `joined_encodings`. + " in + let _ := M.assign_local (| + "decoded_sequence" , + make_list [] + |) in + let _ := M.assign_local (| + "item_start_idx" , + Constant.int 0 + |) in + let _ := + M.while (| + Compare.lt (| + M.get_name (| globals, "item_start_idx" |), + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_name (| globals, "joined_encodings" |) + ], + make_dict [] + |) + |), + ltac:(M.monadic ( + let _ := M.assign_local (| + "encoded_item_length" , + M.call (| + M.get_name (| globals, "decode_item_length" |), + make_list [ + M.slice (| + M.get_name (| globals, "joined_encodings" |), + M.get_name (| globals, "item_start_idx" |), + Constant.None_, + Constant.None_ + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + Compare.lt (| + BinOp.sub (| + BinOp.add (| + M.get_name (| globals, "item_start_idx" |), + M.get_name (| globals, "encoded_item_length" |) + |), + Constant.int 1 + |), + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_name (| globals, "joined_encodings" |) + ], + make_dict [] + |) + |); + M.get_name (| globals, "RLPDecodingError" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "encoded_item" , + M.slice (| + M.get_name (| globals, "joined_encodings" |), + M.get_name (| globals, "item_start_idx" |), + BinOp.add (| + M.get_name (| globals, "item_start_idx" |), + M.get_name (| globals, "encoded_item_length" |) + |), + Constant.None_ + |) + |) in + let _ := M.call (| + M.get_field (| M.get_name (| globals, "decoded_sequence" |), "append" |), + make_list [ + M.call (| + M.get_name (| globals, "decode" |), + make_list [ + M.get_name (| globals, "encoded_item" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op_local (| + BinOp.add, + "item_start_idx", + M.get_name (| globals, "encoded_item_length" |) + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := M.return_ (| + M.get_name (| globals, "decoded_sequence" |) + |) in + M.pure Constant.None_)). + +Definition decode_item_length : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "encoded_data" ] |) in + let _ := Constant.str " + Find the length of the rlp encoding for the first object in the + encoded sequence. + Here `encoded_data` refers to concatenation of rlp encoding for each + item in a sequence. + + NOTE - This is a helper function not described in the spec. It was + introduced as the spec doesn't discuss about decoding the RLP encoded + data. + + Parameters + ---------- + encoded_data : + RLP encoded data for a sequence of objects. + + Returns + ------- + rlp_length : `int` + " in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + Compare.gt (| + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_name (| globals, "encoded_data" |) + ], + make_dict [] + |), + Constant.int 0 + |); + M.get_name (| globals, "RLPDecodingError" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "first_rlp_byte" , + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.get_subscript (| + M.get_name (| globals, "encoded_data" |), + Constant.int 0 + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "length_length" , + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "decoded_data_length" , + Constant.int 0 + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.lt (| + M.get_name (| globals, "first_rlp_byte" |), + Constant.int 128 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + Constant.int 1 + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + Compare.lt_e (| + M.get_name (| globals, "first_rlp_byte" |), + Constant.int 183 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "decoded_data_length" , + BinOp.sub (| + M.get_name (| globals, "first_rlp_byte" |), + Constant.int 128 + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + Compare.lt_e (| + M.get_name (| globals, "first_rlp_byte" |), + Constant.int 191 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "length_length" , + BinOp.sub (| + M.get_name (| globals, "first_rlp_byte" |), + Constant.int 183 + |) + |) in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + Compare.lt (| + M.get_name (| globals, "length_length" |), + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_name (| globals, "encoded_data" |) + ], + make_dict [] + |) + |); + M.get_name (| globals, "RLPDecodingError" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + Compare.not_eq (| + M.get_subscript (| + M.get_name (| globals, "encoded_data" |), + Constant.int 1 + |), + Constant.int 0 + |); + M.get_name (| globals, "RLPDecodingError" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "decoded_data_length" , + M.call (| + M.get_field (| M.get_name (| globals, "Uint" |), "from_be_bytes" |), + make_list [ + M.slice (| + M.get_name (| globals, "encoded_data" |), + Constant.int 1, + BinOp.add (| + Constant.int 1, + M.get_name (| globals, "length_length" |) + |), + Constant.None_ + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + Compare.lt_e (| + M.get_name (| globals, "first_rlp_byte" |), + Constant.int 247 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "decoded_data_length" , + BinOp.sub (| + M.get_name (| globals, "first_rlp_byte" |), + Constant.int 192 + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + Compare.lt_e (| + M.get_name (| globals, "first_rlp_byte" |), + Constant.int 255 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "length_length" , + BinOp.sub (| + M.get_name (| globals, "first_rlp_byte" |), + Constant.int 247 + |) + |) in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + Compare.lt (| + M.get_name (| globals, "length_length" |), + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_name (| globals, "encoded_data" |) + ], + make_dict [] + |) + |); + M.get_name (| globals, "RLPDecodingError" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + Compare.not_eq (| + M.get_subscript (| + M.get_name (| globals, "encoded_data" |), + Constant.int 1 + |), + Constant.int 0 + |); + M.get_name (| globals, "RLPDecodingError" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "decoded_data_length" , + M.call (| + M.get_field (| M.get_name (| globals, "Uint" |), "from_be_bytes" |), + make_list [ + M.slice (| + M.get_name (| globals, "encoded_data" |), + Constant.int 1, + BinOp.add (| + Constant.int 1, + M.get_name (| globals, "length_length" |) + |), + Constant.None_ + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )) |) in + let _ := M.return_ (| + BinOp.add (| + BinOp.add (| + Constant.int 1, + M.get_name (| globals, "length_length" |) + |), + M.get_name (| globals, "decoded_data_length" |) + |) + |) in + M.pure Constant.None_)). + +Definition rlp_hash : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "data" ] |) in + let _ := Constant.str " + Obtain the keccak-256 hash of the rlp encoding of the passed in data. + + Parameters + ---------- + data : + The data for which we need the rlp hash. + + Returns + ------- + hash : `Hash32` + The rlp hash of the passed in data. + " in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, "keccak256" |), + make_list [ + M.call (| + M.get_name (| globals, "encode" |), + make_list [ + M.get_name (| globals, "data" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). diff --git a/CoqOfPython/ethereum/shanghai/__init__.v b/CoqOfPython/ethereum/shanghai/__init__.v new file mode 100644 index 0000000..c452ed3 --- /dev/null +++ b/CoqOfPython/ethereum/shanghai/__init__.v @@ -0,0 +1,23 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.shanghai.__init__". + +Definition expr_1 : Value.t := + Constant.str " +The Shanghai fork brings staking withdrawals to the execution layer, adds a +push-zero EVM instruction, limits the maximum size of initialization +bytecode, and deprecates the self-destruct EVM instruction. +". + +Axiom ethereum_fork_criteria_imports_ByTimestamp : + IsImported globals "ethereum.fork_criteria" "ByTimestamp". + +Definition FORK_CRITERIA : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "ByTimestamp" |), + make_list [ + Constant.int 1681338455 + ], + make_dict [] + |) +)). diff --git a/CoqOfPython/ethereum/shanghai/blocks.v b/CoqOfPython/ethereum/shanghai/blocks.v new file mode 100644 index 0000000..3dccfcd --- /dev/null +++ b/CoqOfPython/ethereum/shanghai/blocks.v @@ -0,0 +1,101 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.shanghai.blocks". + +Definition expr_1 : Value.t := + Constant.str " +A `Block` is a single link in the chain that is Ethereum. Each `Block` contains +a `Header` and zero or more transactions. Each `Header` contains associated +metadata like the block number, parent block hash, and how much gas was +consumed by its transactions. + +Together, these blocks form a cryptographically secure journal recording the +history of all state transitions that have happened since the genesis of the +chain. +". + +Axiom dataclasses_imports_dataclass : + IsImported globals "dataclasses" "dataclass". + +Axiom typing_imports_Tuple : + IsImported globals "typing" "Tuple". +Axiom typing_imports_Union : + IsImported globals "typing" "Union". + +Axiom ethereum_base_types_imports_U64 : + IsImported globals "ethereum.base_types" "U64". +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_Bytes : + IsImported globals "ethereum.base_types" "Bytes". +Axiom ethereum_base_types_imports_Bytes8 : + IsImported globals "ethereum.base_types" "Bytes8". +Axiom ethereum_base_types_imports_Bytes32 : + IsImported globals "ethereum.base_types" "Bytes32". +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". +Axiom ethereum_base_types_imports_slotted_freezable : + IsImported globals "ethereum.base_types" "slotted_freezable". + +Axiom ethereum_crypto_hash_imports_Hash32 : + IsImported globals "ethereum.crypto.hash" "Hash32". + +Axiom ethereum_shanghai_fork_types_imports_Address : + IsImported globals "ethereum.shanghai.fork_types" "Address". +Axiom ethereum_shanghai_fork_types_imports_Bloom : + IsImported globals "ethereum.shanghai.fork_types" "Bloom". +Axiom ethereum_shanghai_fork_types_imports_Root : + IsImported globals "ethereum.shanghai.fork_types" "Root". + +Axiom ethereum_shanghai_transactions_imports_LegacyTransaction : + IsImported globals "ethereum.shanghai.transactions" "LegacyTransaction". + +Definition Withdrawal : Value.t := + builtins.make_klass + [] + [ + + ] + [ + + ]. + +Definition Header : Value.t := + builtins.make_klass + [] + [ + + ] + [ + + ]. + +Definition Block : Value.t := + builtins.make_klass + [] + [ + + ] + [ + + ]. + +Definition Log : Value.t := + builtins.make_klass + [] + [ + + ] + [ + + ]. + +Definition Receipt : Value.t := + builtins.make_klass + [] + [ + + ] + [ + + ]. diff --git a/CoqOfPython/ethereum/shanghai/bloom.v b/CoqOfPython/ethereum/shanghai/bloom.v new file mode 100644 index 0000000..f6a336d --- /dev/null +++ b/CoqOfPython/ethereum/shanghai/bloom.v @@ -0,0 +1,207 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.shanghai.bloom". + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Logs Bloom +^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +This modules defines functions for calculating bloom filters of logs. For the +general theory of bloom filters see e.g. `Wikipedia +`_. Bloom filters are used to allow +for efficient searching of logs by address and/or topic, by rapidly +eliminating blocks and receipts from their search. +". + +Axiom typing_imports_Tuple : + IsImported globals "typing" "Tuple". + +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". + +Axiom ethereum_crypto_hash_imports_keccak256 : + IsImported globals "ethereum.crypto.hash" "keccak256". + +Axiom ethereum_shanghai_blocks_imports_Log : + IsImported globals "ethereum.shanghai.blocks" "Log". + +Axiom ethereum_shanghai_fork_types_imports_Bloom : + IsImported globals "ethereum.shanghai.fork_types" "Bloom". + +Definition add_to_bloom : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "bloom"; "bloom_entry" ] |) in + let _ := Constant.str " + Add a bloom entry to the bloom filter (`bloom`). + + The number of hash functions used is 3. They are calculated by taking the + least significant 11 bits from the first 3 16-bit words of the + `keccak_256()` hash of `bloom_entry`. + + Parameters + ---------- + bloom : + The bloom filter. + bloom_entry : + An entry which is to be added to bloom filter. + " in + let _ := M.assign_local (| + "hash" , + M.call (| + M.get_name (| globals, "keccak256" |), + make_list [ + M.get_name (| globals, "bloom_entry" |) + ], + make_dict [] + |) + |) in + let _ := + M.for_ (| + M.get_name (| globals, "idx" |), + make_tuple [ Constant.int 0; Constant.int 2; Constant.int 4 ], + ltac:(M.monadic ( + let _ := M.assign_local (| + "bit_to_set" , + BinOp.bit_and (| + M.call (| + M.get_field (| M.get_name (| globals, "Uint" |), "from_be_bytes" |), + make_list [ + M.slice (| + M.get_name (| globals, "hash" |), + M.get_name (| globals, "idx" |), + BinOp.add (| + M.get_name (| globals, "idx" |), + Constant.int 2 + |), + Constant.None_ + |) + ], + make_dict [] + |), + Constant.int 2047 + |) + |) in + let _ := M.assign_local (| + "bit_index" , + BinOp.sub (| + Constant.int 2047, + M.get_name (| globals, "bit_to_set" |) + |) + |) in + let _ := M.assign_local (| + "byte_index" , + BinOp.floor_div (| + M.get_name (| globals, "bit_index" |), + Constant.int 8 + |) + |) in + let _ := M.assign_local (| + "bit_value" , + BinOp.l_shift (| + Constant.int 1, + BinOp.sub (| + Constant.int 7, + BinOp.mod_ (| + M.get_name (| globals, "bit_index" |), + Constant.int 8 + |) + |) + |) + |) in + let _ := M.assign (| + M.get_subscript (| + M.get_name (| globals, "bloom" |), + M.get_name (| globals, "byte_index" |) + |), + BinOp.bit_or (| + M.get_subscript (| + M.get_name (| globals, "bloom" |), + M.get_name (| globals, "byte_index" |) + |), + M.get_name (| globals, "bit_value" |) + |) + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + M.pure Constant.None_)). + +Definition logs_bloom : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "logs" ] |) in + let _ := Constant.str " + Obtain the logs bloom from a list of log entries. + + The address and each topic of a log are added to the bloom filter. + + Parameters + ---------- + logs : + List of logs for which the logs bloom is to be obtained. + + Returns + ------- + logs_bloom : `Bloom` + The logs bloom obtained which is 256 bytes with some bits set as per + the caller address and the log topics. + " in +(* At stmt: unsupported node type: AnnAssign *) + let _ := + M.for_ (| + M.get_name (| globals, "log" |), + M.get_name (| globals, "logs" |), + ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, "add_to_bloom" |), + make_list [ + M.get_name (| globals, "bloom" |); + M.get_field (| M.get_name (| globals, "log" |), "address" |) + ], + make_dict [] + |) in + let _ := + M.for_ (| + M.get_name (| globals, "topic" |), + M.get_field (| M.get_name (| globals, "log" |), "topics" |), + ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, "add_to_bloom" |), + make_list [ + M.get_name (| globals, "bloom" |); + M.get_name (| globals, "topic" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, "Bloom" |), + make_list [ + M.get_name (| globals, "bloom" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). diff --git a/CoqOfPython/ethereum/shanghai/fork.v b/CoqOfPython/ethereum/shanghai/fork.v new file mode 100644 index 0000000..1ec1953 --- /dev/null +++ b/CoqOfPython/ethereum/shanghai/fork.v @@ -0,0 +1,2771 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.shanghai.fork". + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Specification +^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Entry point for the Ethereum specification. +". + +Axiom dataclasses_imports_dataclass : + IsImported globals "dataclasses" "dataclass". + +Axiom typing_imports_List : + IsImported globals "typing" "List". +Axiom typing_imports_Optional : + IsImported globals "typing" "Optional". +Axiom typing_imports_Tuple : + IsImported globals "typing" "Tuple". +Axiom typing_imports_Union : + IsImported globals "typing" "Union". + +Axiom ethereum_base_types_imports_Bytes0 : + IsImported globals "ethereum.base_types" "Bytes0". +Axiom ethereum_base_types_imports_Bytes32 : + IsImported globals "ethereum.base_types" "Bytes32". + +Axiom ethereum_crypto_elliptic_curve_imports_SECP256K1N : + IsImported globals "ethereum.crypto.elliptic_curve" "SECP256K1N". +Axiom ethereum_crypto_elliptic_curve_imports_secp256k1_recover : + IsImported globals "ethereum.crypto.elliptic_curve" "secp256k1_recover". + +Axiom ethereum_crypto_hash_imports_Hash32 : + IsImported globals "ethereum.crypto.hash" "Hash32". +Axiom ethereum_crypto_hash_imports_keccak256 : + IsImported globals "ethereum.crypto.hash" "keccak256". + +Axiom ethereum_exceptions_imports_InvalidBlock : + IsImported globals "ethereum.exceptions" "InvalidBlock". + +Axiom ethereum_utils_ensure_imports_ensure : + IsImported globals "ethereum.utils.ensure" "ensure". + +Axiom ethereum_imports_rlp : + IsImported globals "ethereum" "rlp". + +Axiom ethereum_base_types_imports_U64 : + IsImported globals "ethereum.base_types" "U64". +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_Bytes : + IsImported globals "ethereum.base_types" "Bytes". +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". + +Axiom ethereum_shanghai_imports_vm : + IsImported globals "ethereum.shanghai" "vm". + +Axiom ethereum_shanghai_blocks_imports_Block : + IsImported globals "ethereum.shanghai.blocks" "Block". +Axiom ethereum_shanghai_blocks_imports_Header : + IsImported globals "ethereum.shanghai.blocks" "Header". +Axiom ethereum_shanghai_blocks_imports_Log : + IsImported globals "ethereum.shanghai.blocks" "Log". +Axiom ethereum_shanghai_blocks_imports_Receipt : + IsImported globals "ethereum.shanghai.blocks" "Receipt". +Axiom ethereum_shanghai_blocks_imports_Withdrawal : + IsImported globals "ethereum.shanghai.blocks" "Withdrawal". + +Axiom ethereum_shanghai_bloom_imports_logs_bloom : + IsImported globals "ethereum.shanghai.bloom" "logs_bloom". + +Axiom ethereum_shanghai_fork_types_imports_Address : + IsImported globals "ethereum.shanghai.fork_types" "Address". +Axiom ethereum_shanghai_fork_types_imports_Bloom : + IsImported globals "ethereum.shanghai.fork_types" "Bloom". +Axiom ethereum_shanghai_fork_types_imports_Root : + IsImported globals "ethereum.shanghai.fork_types" "Root". + +Axiom ethereum_shanghai_state_imports_State : + IsImported globals "ethereum.shanghai.state" "State". +Axiom ethereum_shanghai_state_imports_account_exists_and_is_empty : + IsImported globals "ethereum.shanghai.state" "account_exists_and_is_empty". +Axiom ethereum_shanghai_state_imports_destroy_account : + IsImported globals "ethereum.shanghai.state" "destroy_account". +Axiom ethereum_shanghai_state_imports_get_account : + IsImported globals "ethereum.shanghai.state" "get_account". +Axiom ethereum_shanghai_state_imports_increment_nonce : + IsImported globals "ethereum.shanghai.state" "increment_nonce". +Axiom ethereum_shanghai_state_imports_process_withdrawal : + IsImported globals "ethereum.shanghai.state" "process_withdrawal". +Axiom ethereum_shanghai_state_imports_set_account_balance : + IsImported globals "ethereum.shanghai.state" "set_account_balance". +Axiom ethereum_shanghai_state_imports_state_root : + IsImported globals "ethereum.shanghai.state" "state_root". + +Axiom ethereum_shanghai_transactions_imports_TX_ACCESS_LIST_ADDRESS_COST : + IsImported globals "ethereum.shanghai.transactions" "TX_ACCESS_LIST_ADDRESS_COST". +Axiom ethereum_shanghai_transactions_imports_TX_ACCESS_LIST_STORAGE_KEY_COST : + IsImported globals "ethereum.shanghai.transactions" "TX_ACCESS_LIST_STORAGE_KEY_COST". +Axiom ethereum_shanghai_transactions_imports_TX_BASE_COST : + IsImported globals "ethereum.shanghai.transactions" "TX_BASE_COST". +Axiom ethereum_shanghai_transactions_imports_TX_CREATE_COST : + IsImported globals "ethereum.shanghai.transactions" "TX_CREATE_COST". +Axiom ethereum_shanghai_transactions_imports_TX_DATA_COST_PER_NON_ZERO : + IsImported globals "ethereum.shanghai.transactions" "TX_DATA_COST_PER_NON_ZERO". +Axiom ethereum_shanghai_transactions_imports_TX_DATA_COST_PER_ZERO : + IsImported globals "ethereum.shanghai.transactions" "TX_DATA_COST_PER_ZERO". +Axiom ethereum_shanghai_transactions_imports_AccessListTransaction : + IsImported globals "ethereum.shanghai.transactions" "AccessListTransaction". +Axiom ethereum_shanghai_transactions_imports_FeeMarketTransaction : + IsImported globals "ethereum.shanghai.transactions" "FeeMarketTransaction". +Axiom ethereum_shanghai_transactions_imports_LegacyTransaction : + IsImported globals "ethereum.shanghai.transactions" "LegacyTransaction". +Axiom ethereum_shanghai_transactions_imports_Transaction : + IsImported globals "ethereum.shanghai.transactions" "Transaction". +Axiom ethereum_shanghai_transactions_imports_decode_transaction : + IsImported globals "ethereum.shanghai.transactions" "decode_transaction". +Axiom ethereum_shanghai_transactions_imports_encode_transaction : + IsImported globals "ethereum.shanghai.transactions" "encode_transaction". + +Axiom ethereum_shanghai_trie_imports_Trie : + IsImported globals "ethereum.shanghai.trie" "Trie". +Axiom ethereum_shanghai_trie_imports_root : + IsImported globals "ethereum.shanghai.trie" "root". +Axiom ethereum_shanghai_trie_imports_trie_set : + IsImported globals "ethereum.shanghai.trie" "trie_set". + +Axiom ethereum_shanghai_utils_message_imports_prepare_message : + IsImported globals "ethereum.shanghai.utils.message" "prepare_message". + +Axiom ethereum_shanghai_vm_gas_imports_init_code_cost : + IsImported globals "ethereum.shanghai.vm.gas" "init_code_cost". + +Axiom ethereum_shanghai_vm_interpreter_imports_MAX_CODE_SIZE : + IsImported globals "ethereum.shanghai.vm.interpreter" "MAX_CODE_SIZE". +Axiom ethereum_shanghai_vm_interpreter_imports_process_message_call : + IsImported globals "ethereum.shanghai.vm.interpreter" "process_message_call". + +Definition BASE_FEE_MAX_CHANGE_DENOMINATOR : Value.t := M.run ltac:(M.monadic ( + Constant.int 8 +)). + +Definition ELASTICITY_MULTIPLIER : Value.t := M.run ltac:(M.monadic ( + Constant.int 2 +)). + +Definition GAS_LIMIT_ADJUSTMENT_FACTOR : Value.t := M.run ltac:(M.monadic ( + Constant.int 1024 +)). + +Definition GAS_LIMIT_MINIMUM : Value.t := M.run ltac:(M.monadic ( + Constant.int 5000 +)). + +Definition EMPTY_OMMER_HASH : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "keccak256" |), + make_list [ + M.call (| + M.get_field (| M.get_name (| globals, "rlp" |), "encode" |), + make_list [ + make_list [] + ], + make_dict [] + |) + ], + make_dict [] + |) +)). + +Definition BlockChain : Value.t := + builtins.make_klass + [] + [ + + ] + [ + + ]. + +Definition apply_fork : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "old" ] |) in + let _ := Constant.str " + Transforms the state from the previous hard fork (`old`) into the block + chain object for this hard fork and returns it. + + When forks need to implement an irregular state transition, this function + is used to handle the irregularity. See the :ref:`DAO Fork ` for + an example. + + Parameters + ---------- + old : + Previous block chain object. + + Returns + ------- + new : `BlockChain` + Upgraded block chain object for this hard fork. + " in + let _ := M.return_ (| + M.get_name (| globals, "old" |) + |) in + M.pure Constant.None_)). + +Definition get_last_256_block_hashes : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "chain" ] |) in + let _ := Constant.str " + Obtain the list of hashes of the previous 256 blocks in order of + increasing block number. + + This function will return less hashes for the first 256 blocks. + + The ``BLOCKHASH`` opcode needs to access the latest hashes on the chain, + therefore this function retrieves them. + + Parameters + ---------- + chain : + History and current state. + + Returns + ------- + recent_block_hashes : `List[Hash32]` + Hashes of the recent 256 blocks in order of increasing block number. + " in + let _ := M.assign_local (| + "recent_blocks" , + M.slice (| + M.get_field (| M.get_name (| globals, "chain" |), "blocks" |), + UnOp.sub (| Constant.int 255 |), + Constant.None_, + Constant.None_ + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_name (| globals, "recent_blocks" |) + ], + make_dict [] + |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + make_list [] + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "recent_block_hashes" , + make_list [] + |) in + let _ := + M.for_ (| + M.get_name (| globals, "block" |), + M.get_name (| globals, "recent_blocks" |), + ltac:(M.monadic ( + let _ := M.assign_local (| + "prev_block_hash" , + M.get_field (| M.get_field (| M.get_name (| globals, "block" |), "header" |), "parent_hash" |) + |) in + let _ := M.call (| + M.get_field (| M.get_name (| globals, "recent_block_hashes" |), "append" |), + make_list [ + M.get_name (| globals, "prev_block_hash" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := M.assign_local (| + "most_recent_block_hash" , + M.call (| + M.get_name (| globals, "keccak256" |), + make_list [ + M.call (| + M.get_field (| M.get_name (| globals, "rlp" |), "encode" |), + make_list [ + M.get_field (| M.get_subscript (| + M.get_name (| globals, "recent_blocks" |), + UnOp.sub (| Constant.int 1 |) + |), "header" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_field (| M.get_name (| globals, "recent_block_hashes" |), "append" |), + make_list [ + M.get_name (| globals, "most_recent_block_hash" |) + ], + make_dict [] + |) in + let _ := M.return_ (| + M.get_name (| globals, "recent_block_hashes" |) + |) in + M.pure Constant.None_)). + +Definition state_transition : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "chain"; "block" ] |) in + let _ := Constant.str " + Attempts to apply a block to an existing block chain. + + All parts of the block's contents need to be verified before being added + to the chain. Blocks are verified by ensuring that the contents of the + block make logical sense with the contents of the parent block. The + information in the block's header must also match the corresponding + information in the block. + + To implement Ethereum, in theory clients are only required to store the + most recent 255 blocks of the chain since as far as execution is + concerned, only those blocks are accessed. Practically, however, clients + should store more blocks to handle reorgs. + + Parameters + ---------- + chain : + History and current state. + block : + Block to apply to `chain`. + " in + let _ := M.assign_local (| + "parent_header" , + M.get_field (| M.get_subscript (| + M.get_field (| M.get_name (| globals, "chain" |), "blocks" |), + UnOp.sub (| Constant.int 1 |) + |), "header" |) + |) in + let _ := M.call (| + M.get_name (| globals, "validate_header" |), + make_list [ + M.get_field (| M.get_name (| globals, "block" |), "header" |); + M.get_name (| globals, "parent_header" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + Compare.eq (| + M.get_field (| M.get_name (| globals, "block" |), "ommers" |), + make_tuple [ ] + |); + M.get_name (| globals, "InvalidBlock" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "apply_body_output" , + M.call (| + M.get_name (| globals, "apply_body" |), + make_list [ + M.get_field (| M.get_name (| globals, "chain" |), "state" |); + M.call (| + M.get_name (| globals, "get_last_256_block_hashes" |), + make_list [ + M.get_name (| globals, "chain" |) + ], + make_dict [] + |); + M.get_field (| M.get_field (| M.get_name (| globals, "block" |), "header" |), "coinbase" |); + M.get_field (| M.get_field (| M.get_name (| globals, "block" |), "header" |), "number" |); + M.get_field (| M.get_field (| M.get_name (| globals, "block" |), "header" |), "base_fee_per_gas" |); + M.get_field (| M.get_field (| M.get_name (| globals, "block" |), "header" |), "gas_limit" |); + M.get_field (| M.get_field (| M.get_name (| globals, "block" |), "header" |), "timestamp" |); + M.get_field (| M.get_field (| M.get_name (| globals, "block" |), "header" |), "prev_randao" |); + M.get_field (| M.get_name (| globals, "block" |), "transactions" |); + M.get_field (| M.get_name (| globals, "chain" |), "chain_id" |); + M.get_field (| M.get_name (| globals, "block" |), "withdrawals" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + Compare.eq (| + M.get_field (| M.get_name (| globals, "apply_body_output" |), "block_gas_used" |), + M.get_field (| M.get_field (| M.get_name (| globals, "block" |), "header" |), "gas_used" |) + |); + M.get_name (| globals, "InvalidBlock" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + Compare.eq (| + M.get_field (| M.get_name (| globals, "apply_body_output" |), "transactions_root" |), + M.get_field (| M.get_field (| M.get_name (| globals, "block" |), "header" |), "transactions_root" |) + |); + M.get_name (| globals, "InvalidBlock" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + Compare.eq (| + M.get_field (| M.get_name (| globals, "apply_body_output" |), "state_root" |), + M.get_field (| M.get_field (| M.get_name (| globals, "block" |), "header" |), "state_root" |) + |); + M.get_name (| globals, "InvalidBlock" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + Compare.eq (| + M.get_field (| M.get_name (| globals, "apply_body_output" |), "receipt_root" |), + M.get_field (| M.get_field (| M.get_name (| globals, "block" |), "header" |), "receipt_root" |) + |); + M.get_name (| globals, "InvalidBlock" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + Compare.eq (| + M.get_field (| M.get_name (| globals, "apply_body_output" |), "block_logs_bloom" |), + M.get_field (| M.get_field (| M.get_name (| globals, "block" |), "header" |), "bloom" |) + |); + M.get_name (| globals, "InvalidBlock" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + Compare.eq (| + M.get_field (| M.get_name (| globals, "apply_body_output" |), "withdrawals_root" |), + M.get_field (| M.get_field (| M.get_name (| globals, "block" |), "header" |), "withdrawals_root" |) + |); + M.get_name (| globals, "InvalidBlock" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, "chain" |), "blocks" |), "append" |), + make_list [ + M.get_name (| globals, "block" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.gt (| + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_field (| M.get_name (| globals, "chain" |), "blocks" |) + ], + make_dict [] + |), + Constant.int 255 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign (| + M.get_field (| M.get_name (| globals, "chain" |), "blocks" |), + M.slice (| + M.get_field (| M.get_name (| globals, "chain" |), "blocks" |), + UnOp.sub (| Constant.int 255 |), + Constant.None_, + Constant.None_ + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + M.pure Constant.None_)). + +Definition calculate_base_fee_per_gas : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "block_gas_limit"; "parent_gas_limit"; "parent_gas_used"; "parent_base_fee_per_gas" ] |) in + let _ := Constant.str " + Calculates the base fee per gas for the block. + + Parameters + ---------- + block_gas_limit : + Gas limit of the block for which the base fee is being calculated. + parent_gas_limit : + Gas limit of the parent block. + parent_gas_used : + Gas used in the parent block. + parent_base_fee_per_gas : + Base fee per gas of the parent block. + + Returns + ------- + base_fee_per_gas : `Uint` + Base fee per gas for the block. + " in + let _ := M.assign_local (| + "parent_gas_target" , + BinOp.floor_div (| + M.get_name (| globals, "parent_gas_limit" |), + M.get_name (| globals, "ELASTICITY_MULTIPLIER" |) + |) + |) in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + M.call (| + M.get_name (| globals, "check_gas_limit" |), + make_list [ + M.get_name (| globals, "block_gas_limit" |); + M.get_name (| globals, "parent_gas_limit" |) + ], + make_dict [] + |); + M.get_name (| globals, "InvalidBlock" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, "parent_gas_used" |), + M.get_name (| globals, "parent_gas_target" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "expected_base_fee_per_gas" , + M.get_name (| globals, "parent_base_fee_per_gas" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + Compare.gt (| + M.get_name (| globals, "parent_gas_used" |), + M.get_name (| globals, "parent_gas_target" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "gas_used_delta" , + BinOp.sub (| + M.get_name (| globals, "parent_gas_used" |), + M.get_name (| globals, "parent_gas_target" |) + |) + |) in + let _ := M.assign_local (| + "parent_fee_gas_delta" , + BinOp.mult (| + M.get_name (| globals, "parent_base_fee_per_gas" |), + M.get_name (| globals, "gas_used_delta" |) + |) + |) in + let _ := M.assign_local (| + "target_fee_gas_delta" , + BinOp.floor_div (| + M.get_name (| globals, "parent_fee_gas_delta" |), + M.get_name (| globals, "parent_gas_target" |) + |) + |) in + let _ := M.assign_local (| + "base_fee_per_gas_delta" , + M.call (| + M.get_name (| globals, "max" |), + make_list [ + BinOp.floor_div (| + M.get_name (| globals, "target_fee_gas_delta" |), + M.get_name (| globals, "BASE_FEE_MAX_CHANGE_DENOMINATOR" |) + |); + Constant.int 1 + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "expected_base_fee_per_gas" , + BinOp.add (| + M.get_name (| globals, "parent_base_fee_per_gas" |), + M.get_name (| globals, "base_fee_per_gas_delta" |) + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "gas_used_delta" , + BinOp.sub (| + M.get_name (| globals, "parent_gas_target" |), + M.get_name (| globals, "parent_gas_used" |) + |) + |) in + let _ := M.assign_local (| + "parent_fee_gas_delta" , + BinOp.mult (| + M.get_name (| globals, "parent_base_fee_per_gas" |), + M.get_name (| globals, "gas_used_delta" |) + |) + |) in + let _ := M.assign_local (| + "target_fee_gas_delta" , + BinOp.floor_div (| + M.get_name (| globals, "parent_fee_gas_delta" |), + M.get_name (| globals, "parent_gas_target" |) + |) + |) in + let _ := M.assign_local (| + "base_fee_per_gas_delta" , + BinOp.floor_div (| + M.get_name (| globals, "target_fee_gas_delta" |), + M.get_name (| globals, "BASE_FEE_MAX_CHANGE_DENOMINATOR" |) + |) + |) in + let _ := M.assign_local (| + "expected_base_fee_per_gas" , + BinOp.sub (| + M.get_name (| globals, "parent_base_fee_per_gas" |), + M.get_name (| globals, "base_fee_per_gas_delta" |) + |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )) |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.get_name (| globals, "expected_base_fee_per_gas" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Definition validate_header : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "header"; "parent_header" ] |) in + let _ := Constant.str " + Verifies a block header. + + In order to consider a block's header valid, the logic for the + quantities in the header should match the logic for the block itself. + For example the header timestamp should be greater than the block's parent + timestamp because the block was created *after* the parent block. + Additionally, the block's number should be directly following the parent + block's number since it is the next block in the sequence. + + Parameters + ---------- + header : + Header to check for correctness. + parent_header : + Parent Header of the header to check for correctness + " in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + Compare.lt_e (| + M.get_field (| M.get_name (| globals, "header" |), "gas_used" |), + M.get_field (| M.get_name (| globals, "header" |), "gas_limit" |) + |); + M.get_name (| globals, "InvalidBlock" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "expected_base_fee_per_gas" , + M.call (| + M.get_name (| globals, "calculate_base_fee_per_gas" |), + make_list [ + M.get_field (| M.get_name (| globals, "header" |), "gas_limit" |); + M.get_field (| M.get_name (| globals, "parent_header" |), "gas_limit" |); + M.get_field (| M.get_name (| globals, "parent_header" |), "gas_used" |); + M.get_field (| M.get_name (| globals, "parent_header" |), "base_fee_per_gas" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + Compare.eq (| + M.get_name (| globals, "expected_base_fee_per_gas" |), + M.get_field (| M.get_name (| globals, "header" |), "base_fee_per_gas" |) + |); + M.get_name (| globals, "InvalidBlock" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + Compare.gt (| + M.get_field (| M.get_name (| globals, "header" |), "timestamp" |), + M.get_field (| M.get_name (| globals, "parent_header" |), "timestamp" |) + |); + M.get_name (| globals, "InvalidBlock" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + Compare.eq (| + M.get_field (| M.get_name (| globals, "header" |), "number" |), + BinOp.add (| + M.get_field (| M.get_name (| globals, "parent_header" |), "number" |), + Constant.int 1 + |) + |); + M.get_name (| globals, "InvalidBlock" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + Compare.lt_e (| + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_field (| M.get_name (| globals, "header" |), "extra_data" |) + ], + make_dict [] + |), + Constant.int 32 + |); + M.get_name (| globals, "InvalidBlock" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + Compare.eq (| + M.get_field (| M.get_name (| globals, "header" |), "difficulty" |), + Constant.int 0 + |); + M.get_name (| globals, "InvalidBlock" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + Compare.eq (| + M.get_field (| M.get_name (| globals, "header" |), "nonce" |), + Constant.bytes "0000000000000000" + |); + M.get_name (| globals, "InvalidBlock" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + Compare.eq (| + M.get_field (| M.get_name (| globals, "header" |), "ommers_hash" |), + M.get_name (| globals, "EMPTY_OMMER_HASH" |) + |); + M.get_name (| globals, "InvalidBlock" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "block_parent_hash" , + M.call (| + M.get_name (| globals, "keccak256" |), + make_list [ + M.call (| + M.get_field (| M.get_name (| globals, "rlp" |), "encode" |), + make_list [ + M.get_name (| globals, "parent_header" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + Compare.eq (| + M.get_field (| M.get_name (| globals, "header" |), "parent_hash" |), + M.get_name (| globals, "block_parent_hash" |) + |); + M.get_name (| globals, "InvalidBlock" |) + ], + make_dict [] + |) in + M.pure Constant.None_)). + +Definition check_transaction : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "tx"; "base_fee_per_gas"; "gas_available"; "chain_id" ] |) in + let _ := Constant.str " + Check if the transaction is includable in the block. + + Parameters + ---------- + tx : + The transaction. + base_fee_per_gas : + The block base fee. + gas_available : + The gas remaining in the block. + chain_id : + The ID of the current chain. + + Returns + ------- + sender_address : + The sender of the transaction. + effective_gas_price : + The price to charge for gas when the transaction is executed. + + Raises + ------ + InvalidBlock : + If the transaction is not includable. + " in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + Compare.lt_e (| + M.get_field (| M.get_name (| globals, "tx" |), "gas" |), + M.get_name (| globals, "gas_available" |) + |); + M.get_name (| globals, "InvalidBlock" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "sender_address" , + M.call (| + M.get_name (| globals, "recover_sender" |), + make_list [ + M.get_name (| globals, "chain_id" |); + M.get_name (| globals, "tx" |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, "isinstance" |), + make_list [ + M.get_name (| globals, "tx" |); + M.get_name (| globals, "FeeMarketTransaction" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + Compare.gt_e (| + M.get_field (| M.get_name (| globals, "tx" |), "max_fee_per_gas" |), + M.get_field (| M.get_name (| globals, "tx" |), "max_priority_fee_per_gas" |) + |); + M.get_name (| globals, "InvalidBlock" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + Compare.gt_e (| + M.get_field (| M.get_name (| globals, "tx" |), "max_fee_per_gas" |), + M.get_name (| globals, "base_fee_per_gas" |) + |); + M.get_name (| globals, "InvalidBlock" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "priority_fee_per_gas" , + M.call (| + M.get_name (| globals, "min" |), + make_list [ + M.get_field (| M.get_name (| globals, "tx" |), "max_priority_fee_per_gas" |); + BinOp.sub (| + M.get_field (| M.get_name (| globals, "tx" |), "max_fee_per_gas" |), + M.get_name (| globals, "base_fee_per_gas" |) + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "effective_gas_price" , + BinOp.add (| + M.get_name (| globals, "priority_fee_per_gas" |), + M.get_name (| globals, "base_fee_per_gas" |) + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + Compare.gt_e (| + M.get_field (| M.get_name (| globals, "tx" |), "gas_price" |), + M.get_name (| globals, "base_fee_per_gas" |) + |); + M.get_name (| globals, "InvalidBlock" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "effective_gas_price" , + M.get_field (| M.get_name (| globals, "tx" |), "gas_price" |) + |) in + M.pure Constant.None_ + )) |) in + let _ := M.return_ (| + make_tuple [ M.get_name (| globals, "sender_address" |); M.get_name (| globals, "effective_gas_price" |) ] + |) in + M.pure Constant.None_)). + +Definition make_receipt : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "tx"; "error"; "cumulative_gas_used"; "logs" ] |) in + let _ := Constant.str " + Make the receipt for a transaction that was executed. + + Parameters + ---------- + tx : + The executed transaction. + error : + Error in the top level frame of the transaction, if any. + cumulative_gas_used : + The total gas used so far in the block after the transaction was + executed. + logs : + The logs produced by the transaction. + + Returns + ------- + receipt : + The receipt for the transaction. + " in + let _ := M.assign_local (| + "receipt" , + M.call (| + M.get_name (| globals, "Receipt" |), + make_list [], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, "isinstance" |), + make_list [ + M.get_name (| globals, "tx" |); + M.get_name (| globals, "AccessListTransaction" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + BinOp.add (| + Constant.bytes "01", + M.call (| + M.get_field (| M.get_name (| globals, "rlp" |), "encode" |), + make_list [ + M.get_name (| globals, "receipt" |) + ], + make_dict [] + |) + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, "isinstance" |), + make_list [ + M.get_name (| globals, "tx" |); + M.get_name (| globals, "FeeMarketTransaction" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + BinOp.add (| + Constant.bytes "02", + M.call (| + M.get_field (| M.get_name (| globals, "rlp" |), "encode" |), + make_list [ + M.get_name (| globals, "receipt" |) + ], + make_dict [] + |) + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.return_ (| + M.get_name (| globals, "receipt" |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_)). + +Definition ApplyBodyOutput : Value.t := + builtins.make_klass + [] + [ + + ] + [ + + ]. + +Definition apply_body : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "state"; "block_hashes"; "coinbase"; "block_number"; "base_fee_per_gas"; "block_gas_limit"; "block_time"; "prev_randao"; "transactions"; "chain_id"; "withdrawals" ] |) in + let _ := Constant.str " + Executes a block. + + Many of the contents of a block are stored in data structures called + tries. There is a transactions trie which is similar to a ledger of the + transactions stored in the current block. There is also a receipts trie + which stores the results of executing a transaction, like the post state + and gas used. This function creates and executes the block that is to be + added to the chain. + + Parameters + ---------- + state : + Current account state. + block_hashes : + List of hashes of the previous 256 blocks in the order of + increasing block number. + coinbase : + Address of account which receives block reward and transaction fees. + block_number : + Position of the block within the chain. + base_fee_per_gas : + Base fee per gas of within the block. + block_gas_limit : + Initial amount of gas available for execution in this block. + block_time : + Time the block was produced, measured in seconds since the epoch. + prev_randao : + The previous randao from the beacon chain. + transactions : + Transactions included in the block. + ommers : + Headers of ancestor blocks which are not direct parents (formerly + uncles.) + chain_id : + ID of the executing chain. + withdrawals : + Withdrawals to be processed in the current block. + + Returns + ------- + apply_body_output : `ApplyBodyOutput` + Output of applying the block body to the state. + " in + let _ := M.assign_local (| + "gas_available" , + M.get_name (| globals, "block_gas_limit" |) + |) in +(* At stmt: unsupported node type: AnnAssign *) +(* At stmt: unsupported node type: AnnAssign *) +(* At stmt: unsupported node type: AnnAssign *) +(* At stmt: unsupported node type: AnnAssign *) + let _ := + M.for_ (| + make_tuple [ M.get_name (| globals, "i" |); M.get_name (| globals, "tx" |) ], + M.call (| + M.get_name (| globals, "enumerate" |), + make_list [ + M.call (| + M.get_name (| globals, "map" |), + make_list [ + M.get_name (| globals, "decode_transaction" |); + M.get_name (| globals, "transactions" |) + ], + make_dict [] + |) + ], + make_dict [] + |), + ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, "trie_set" |), + make_list [ + M.get_name (| globals, "transactions_trie" |); + M.call (| + M.get_field (| M.get_name (| globals, "rlp" |), "encode" |), + make_list [ + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.get_name (| globals, "i" |) + ], + make_dict [] + |) + ], + make_dict [] + |); + M.call (| + M.get_name (| globals, "encode_transaction" |), + make_list [ + M.get_name (| globals, "tx" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign (| + make_tuple [ M.get_name (| globals, "sender_address" |); M.get_name (| globals, "effective_gas_price" |) ], + M.call (| + M.get_name (| globals, "check_transaction" |), + make_list [ + M.get_name (| globals, "tx" |); + M.get_name (| globals, "base_fee_per_gas" |); + M.get_name (| globals, "gas_available" |); + M.get_name (| globals, "chain_id" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "env" , + M.call (| + M.get_field (| M.get_name (| globals, "vm" |), "Environment" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.assign (| + make_tuple [ M.get_name (| globals, "gas_used" |); M.get_name (| globals, "logs" |); M.get_name (| globals, "error" |) ], + M.call (| + M.get_name (| globals, "process_transaction" |), + make_list [ + M.get_name (| globals, "env" |); + M.get_name (| globals, "tx" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_op_local (| + BinOp.sub, + "gas_available", + M.get_name (| globals, "gas_used" |) + |) in + let _ := M.assign_local (| + "receipt" , + M.call (| + M.get_name (| globals, "make_receipt" |), + make_list [ + M.get_name (| globals, "tx" |); + M.get_name (| globals, "error" |); + BinOp.sub (| + M.get_name (| globals, "block_gas_limit" |), + M.get_name (| globals, "gas_available" |) + |); + M.get_name (| globals, "logs" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "trie_set" |), + make_list [ + M.get_name (| globals, "receipts_trie" |); + M.call (| + M.get_field (| M.get_name (| globals, "rlp" |), "encode" |), + make_list [ + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.get_name (| globals, "i" |) + ], + make_dict [] + |) + ], + make_dict [] + |); + M.get_name (| globals, "receipt" |) + ], + make_dict [] + |) in + let _ := M.assign_op_local (| + BinOp.add, + "block_logs", + M.get_name (| globals, "logs" |) + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := M.assign_local (| + "block_gas_used" , + BinOp.sub (| + M.get_name (| globals, "block_gas_limit" |), + M.get_name (| globals, "gas_available" |) + |) + |) in + let _ := M.assign_local (| + "block_logs_bloom" , + M.call (| + M.get_name (| globals, "logs_bloom" |), + make_list [ + M.get_name (| globals, "block_logs" |) + ], + make_dict [] + |) + |) in + let _ := + M.for_ (| + make_tuple [ M.get_name (| globals, "i" |); M.get_name (| globals, "wd" |) ], + M.call (| + M.get_name (| globals, "enumerate" |), + make_list [ + M.get_name (| globals, "withdrawals" |) + ], + make_dict [] + |), + ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, "trie_set" |), + make_list [ + M.get_name (| globals, "withdrawals_trie" |); + M.call (| + M.get_field (| M.get_name (| globals, "rlp" |), "encode" |), + make_list [ + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.get_name (| globals, "i" |) + ], + make_dict [] + |) + ], + make_dict [] + |); + M.call (| + M.get_field (| M.get_name (| globals, "rlp" |), "encode" |), + make_list [ + M.get_name (| globals, "wd" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "process_withdrawal" |), + make_list [ + M.get_name (| globals, "state" |); + M.get_name (| globals, "wd" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, "account_exists_and_is_empty" |), + make_list [ + M.get_name (| globals, "state" |); + M.get_field (| M.get_name (| globals, "wd" |), "address" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, "destroy_account" |), + make_list [ + M.get_name (| globals, "state" |); + M.get_field (| M.get_name (| globals, "wd" |), "address" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, "ApplyBodyOutput" |), + make_list [ + M.get_name (| globals, "block_gas_used" |); + M.call (| + M.get_name (| globals, "root" |), + make_list [ + M.get_name (| globals, "transactions_trie" |) + ], + make_dict [] + |); + M.call (| + M.get_name (| globals, "root" |), + make_list [ + M.get_name (| globals, "receipts_trie" |) + ], + make_dict [] + |); + M.get_name (| globals, "block_logs_bloom" |); + M.call (| + M.get_name (| globals, "state_root" |), + make_list [ + M.get_name (| globals, "state" |) + ], + make_dict [] + |); + M.call (| + M.get_name (| globals, "root" |), + make_list [ + M.get_name (| globals, "withdrawals_trie" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Definition process_transaction : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "env"; "tx" ] |) in + let _ := Constant.str " + Execute a transaction against the provided environment. + + This function processes the actions needed to execute a transaction. + It decrements the sender's account after calculating the gas fee and + refunds them the proper amount after execution. Calling contracts, + deploying code, and incrementing nonces are all examples of actions that + happen within this function or from a call made within this function. + + Accounts that are marked for deletion are processed and destroyed after + execution. + + Parameters + ---------- + env : + Environment for the Ethereum Virtual Machine. + tx : + Transaction to execute. + + Returns + ------- + gas_left : `ethereum.base_types.U256` + Remaining gas after execution. + logs : `Tuple[ethereum.blocks.Log, ...]` + Logs generated during execution. + " in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + M.call (| + M.get_name (| globals, "validate_transaction" |), + make_list [ + M.get_name (| globals, "tx" |) + ], + make_dict [] + |); + M.get_name (| globals, "InvalidBlock" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "sender" , + M.get_field (| M.get_name (| globals, "env" |), "origin" |) + |) in + let _ := M.assign_local (| + "sender_account" , + M.call (| + M.get_name (| globals, "get_account" |), + make_list [ + M.get_field (| M.get_name (| globals, "env" |), "state" |); + M.get_name (| globals, "sender" |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, "isinstance" |), + make_list [ + M.get_name (| globals, "tx" |); + M.get_name (| globals, "FeeMarketTransaction" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "max_gas_fee" , + BinOp.mult (| + M.get_field (| M.get_name (| globals, "tx" |), "gas" |), + M.get_field (| M.get_name (| globals, "tx" |), "max_fee_per_gas" |) + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "max_gas_fee" , + BinOp.mult (| + M.get_field (| M.get_name (| globals, "tx" |), "gas" |), + M.get_field (| M.get_name (| globals, "tx" |), "gas_price" |) + |) + |) in + M.pure Constant.None_ + )) |) in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + Compare.eq (| + M.get_field (| M.get_name (| globals, "sender_account" |), "nonce" |), + M.get_field (| M.get_name (| globals, "tx" |), "nonce" |) + |); + M.get_name (| globals, "InvalidBlock" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + Compare.gt_e (| + M.get_field (| M.get_name (| globals, "sender_account" |), "balance" |), + BinOp.add (| + M.get_name (| globals, "max_gas_fee" |), + M.get_field (| M.get_name (| globals, "tx" |), "value" |) + |) + |); + M.get_name (| globals, "InvalidBlock" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + Compare.eq (| + M.get_field (| M.get_name (| globals, "sender_account" |), "code" |), + M.call (| + M.get_name (| globals, "bytearray" |), + make_list [], + make_dict [] + |) + |); + M.get_name (| globals, "InvalidBlock" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "effective_gas_fee" , + BinOp.mult (| + M.get_field (| M.get_name (| globals, "tx" |), "gas" |), + M.get_field (| M.get_name (| globals, "env" |), "gas_price" |) + |) + |) in + let _ := M.assign_local (| + "gas" , + BinOp.sub (| + M.get_field (| M.get_name (| globals, "tx" |), "gas" |), + M.call (| + M.get_name (| globals, "calculate_intrinsic_cost" |), + make_list [ + M.get_name (| globals, "tx" |) + ], + make_dict [] + |) + |) + |) in + let _ := M.call (| + M.get_name (| globals, "increment_nonce" |), + make_list [ + M.get_field (| M.get_name (| globals, "env" |), "state" |); + M.get_name (| globals, "sender" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "sender_balance_after_gas_fee" , + BinOp.sub (| + M.get_field (| M.get_name (| globals, "sender_account" |), "balance" |), + M.get_name (| globals, "effective_gas_fee" |) + |) + |) in + let _ := M.call (| + M.get_name (| globals, "set_account_balance" |), + make_list [ + M.get_field (| M.get_name (| globals, "env" |), "state" |); + M.get_name (| globals, "sender" |); + M.get_name (| globals, "sender_balance_after_gas_fee" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "preaccessed_addresses" , + M.call (| + M.get_name (| globals, "set" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "preaccessed_storage_keys" , + M.call (| + M.get_name (| globals, "set" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_field (| M.get_name (| globals, "preaccessed_addresses" |), "add" |), + make_list [ + M.get_field (| M.get_name (| globals, "env" |), "coinbase" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, "isinstance" |), + make_list [ + M.get_name (| globals, "tx" |); + make_tuple [ M.get_name (| globals, "AccessListTransaction" |); M.get_name (| globals, "FeeMarketTransaction" |) ] + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := + M.for_ (| + make_tuple [ M.get_name (| globals, "address" |); M.get_name (| globals, "keys" |) ], + M.get_field (| M.get_name (| globals, "tx" |), "access_list" |), + ltac:(M.monadic ( + let _ := M.call (| + M.get_field (| M.get_name (| globals, "preaccessed_addresses" |), "add" |), + make_list [ + M.get_name (| globals, "address" |) + ], + make_dict [] + |) in + let _ := + M.for_ (| + M.get_name (| globals, "key" |), + M.get_name (| globals, "keys" |), + ltac:(M.monadic ( + let _ := M.call (| + M.get_field (| M.get_name (| globals, "preaccessed_storage_keys" |), "add" |), + make_list [ + make_tuple [ M.get_name (| globals, "address" |); M.get_name (| globals, "key" |) ] + ], + make_dict [] + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "message" , + M.call (| + M.get_name (| globals, "prepare_message" |), + make_list [ + M.get_name (| globals, "sender" |); + M.get_field (| M.get_name (| globals, "tx" |), "to" |); + M.get_field (| M.get_name (| globals, "tx" |), "value" |); + M.get_field (| M.get_name (| globals, "tx" |), "data" |); + M.get_name (| globals, "gas" |); + M.get_name (| globals, "env" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "output" , + M.call (| + M.get_name (| globals, "process_message_call" |), + make_list [ + M.get_name (| globals, "message" |); + M.get_name (| globals, "env" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "gas_used" , + BinOp.sub (| + M.get_field (| M.get_name (| globals, "tx" |), "gas" |), + M.get_field (| M.get_name (| globals, "output" |), "gas_left" |) + |) + |) in + let _ := M.assign_local (| + "gas_refund" , + M.call (| + M.get_name (| globals, "min" |), + make_list [ + BinOp.floor_div (| + M.get_name (| globals, "gas_used" |), + Constant.int 5 + |); + M.get_field (| M.get_name (| globals, "output" |), "refund_counter" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "gas_refund_amount" , + BinOp.mult (| + BinOp.add (| + M.get_field (| M.get_name (| globals, "output" |), "gas_left" |), + M.get_name (| globals, "gas_refund" |) + |), + M.get_field (| M.get_name (| globals, "env" |), "gas_price" |) + |) + |) in + let _ := M.assign_local (| + "priority_fee_per_gas" , + BinOp.sub (| + M.get_field (| M.get_name (| globals, "env" |), "gas_price" |), + M.get_field (| M.get_name (| globals, "env" |), "base_fee_per_gas" |) + |) + |) in + let _ := M.assign_local (| + "transaction_fee" , + BinOp.mult (| + BinOp.sub (| + BinOp.sub (| + M.get_field (| M.get_name (| globals, "tx" |), "gas" |), + M.get_field (| M.get_name (| globals, "output" |), "gas_left" |) + |), + M.get_name (| globals, "gas_refund" |) + |), + M.get_name (| globals, "priority_fee_per_gas" |) + |) + |) in + let _ := M.assign_local (| + "total_gas_used" , + BinOp.sub (| + M.get_name (| globals, "gas_used" |), + M.get_name (| globals, "gas_refund" |) + |) + |) in + let _ := M.assign_local (| + "sender_balance_after_refund" , + BinOp.add (| + M.get_field (| M.call (| + M.get_name (| globals, "get_account" |), + make_list [ + M.get_field (| M.get_name (| globals, "env" |), "state" |); + M.get_name (| globals, "sender" |) + ], + make_dict [] + |), "balance" |), + M.get_name (| globals, "gas_refund_amount" |) + |) + |) in + let _ := M.call (| + M.get_name (| globals, "set_account_balance" |), + make_list [ + M.get_field (| M.get_name (| globals, "env" |), "state" |); + M.get_name (| globals, "sender" |); + M.get_name (| globals, "sender_balance_after_refund" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "coinbase_balance_after_mining_fee" , + BinOp.add (| + M.get_field (| M.call (| + M.get_name (| globals, "get_account" |), + make_list [ + M.get_field (| M.get_name (| globals, "env" |), "state" |); + M.get_field (| M.get_name (| globals, "env" |), "coinbase" |) + ], + make_dict [] + |), "balance" |), + M.get_name (| globals, "transaction_fee" |) + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.not_eq (| + M.get_name (| globals, "coinbase_balance_after_mining_fee" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, "set_account_balance" |), + make_list [ + M.get_field (| M.get_name (| globals, "env" |), "state" |); + M.get_field (| M.get_name (| globals, "env" |), "coinbase" |); + M.get_name (| globals, "coinbase_balance_after_mining_fee" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, "account_exists_and_is_empty" |), + make_list [ + M.get_field (| M.get_name (| globals, "env" |), "state" |); + M.get_field (| M.get_name (| globals, "env" |), "coinbase" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, "destroy_account" |), + make_list [ + M.get_field (| M.get_name (| globals, "env" |), "state" |); + M.get_field (| M.get_name (| globals, "env" |), "coinbase" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )) |) in + let _ := + M.for_ (| + M.get_name (| globals, "address" |), + M.get_field (| M.get_name (| globals, "output" |), "accounts_to_delete" |), + ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, "destroy_account" |), + make_list [ + M.get_field (| M.get_name (| globals, "env" |), "state" |); + M.get_name (| globals, "address" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := + M.for_ (| + M.get_name (| globals, "address" |), + M.get_field (| M.get_name (| globals, "output" |), "touched_accounts" |), + ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, "account_exists_and_is_empty" |), + make_list [ + M.get_field (| M.get_name (| globals, "env" |), "state" |); + M.get_name (| globals, "address" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, "destroy_account" |), + make_list [ + M.get_field (| M.get_name (| globals, "env" |), "state" |); + M.get_name (| globals, "address" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := M.return_ (| + make_tuple [ M.get_name (| globals, "total_gas_used" |); M.get_field (| M.get_name (| globals, "output" |), "logs" |); M.get_field (| M.get_name (| globals, "output" |), "error" |) ] + |) in + M.pure Constant.None_)). + +Definition validate_transaction : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "tx" ] |) in + let _ := Constant.str " + Verifies a transaction. + + The gas in a transaction gets used to pay for the intrinsic cost of + operations, therefore if there is insufficient gas then it would not + be possible to execute a transaction and it will be declared invalid. + + Additionally, the nonce of a transaction must not equal or exceed the + limit defined in `EIP-2681 `_. + In practice, defining the limit as ``2**64-1`` has no impact because + sending ``2**64-1`` transactions is improbable. It's not strictly + impossible though, ``2**64-1`` transactions is the entire capacity of the + Ethereum blockchain at 2022 gas limits for a little over 22 years. + + Parameters + ---------- + tx : + Transaction to validate. + + Returns + ------- + verified : `bool` + True if the transaction can be executed, or False otherwise. + " in + let _ := + (* if *) + M.if_then_else (| + Compare.gt (| + M.call (| + M.get_name (| globals, "calculate_intrinsic_cost" |), + make_list [ + M.get_name (| globals, "tx" |) + ], + make_dict [] + |), + M.get_field (| M.get_name (| globals, "tx" |), "gas" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + Constant.bool false + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + Compare.gt_e (| + M.get_field (| M.get_name (| globals, "tx" |), "nonce" |), + BinOp.sub (| + BinOp.pow (| + Constant.int 2, + Constant.int 64 + |), + Constant.int 1 + |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + Constant.bool false + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + BoolOp.and (| + Compare.eq (| + M.get_field (| M.get_name (| globals, "tx" |), "to" |), + M.call (| + M.get_name (| globals, "Bytes0" |), + make_list [ + Constant.bytes "" + ], + make_dict [] + |) + |), + ltac:(M.monadic ( + Compare.gt (| + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_field (| M.get_name (| globals, "tx" |), "data" |) + ], + make_dict [] + |), + BinOp.mult (| + Constant.int 2, + M.get_name (| globals, "MAX_CODE_SIZE" |) + |) + |) + )) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + Constant.bool false + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.return_ (| + Constant.bool true + |) in + M.pure Constant.None_)). + +Definition calculate_intrinsic_cost : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "tx" ] |) in + let _ := Constant.str " + Calculates the gas that is charged before execution is started. + + The intrinsic cost of the transaction is charged before execution has + begun. Functions/operations in the EVM cost money to execute so this + intrinsic cost is for the operations that need to be paid for as part of + the transaction. Data transfer, for example, is part of this intrinsic + cost. It costs ether to send data over the wire and that ether is + accounted for in the intrinsic cost calculated in this function. This + intrinsic cost must be calculated and paid for before execution in order + for all operations to be implemented. + + Parameters + ---------- + tx : + Transaction to compute the intrinsic cost of. + + Returns + ------- + verified : `ethereum.base_types.Uint` + The intrinsic cost of the transaction. + " in + let _ := M.assign_local (| + "data_cost" , + Constant.int 0 + |) in + let _ := + M.for_ (| + M.get_name (| globals, "byte" |), + M.get_field (| M.get_name (| globals, "tx" |), "data" |), + ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, "byte" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_op_local (| + BinOp.add, + "data_cost", + M.get_name (| globals, "TX_DATA_COST_PER_ZERO" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_op_local (| + BinOp.add, + "data_cost", + M.get_name (| globals, "TX_DATA_COST_PER_NON_ZERO" |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_field (| M.get_name (| globals, "tx" |), "to" |), + M.call (| + M.get_name (| globals, "Bytes0" |), + make_list [ + Constant.bytes "" + ], + make_dict [] + |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "create_cost" , + BinOp.add (| + M.get_name (| globals, "TX_CREATE_COST" |), + M.call (| + M.get_name (| globals, "int" |), + make_list [ + M.call (| + M.get_name (| globals, "init_code_cost" |), + make_list [ + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_field (| M.get_name (| globals, "tx" |), "data" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "create_cost" , + Constant.int 0 + |) in + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "access_list_cost" , + Constant.int 0 + |) in + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, "isinstance" |), + make_list [ + M.get_name (| globals, "tx" |); + make_tuple [ M.get_name (| globals, "AccessListTransaction" |); M.get_name (| globals, "FeeMarketTransaction" |) ] + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := + M.for_ (| + make_tuple [ M.get_name (| globals, "_address" |); M.get_name (| globals, "keys" |) ], + M.get_field (| M.get_name (| globals, "tx" |), "access_list" |), + ltac:(M.monadic ( + let _ := M.assign_op_local (| + BinOp.add, + "access_list_cost", + M.get_name (| globals, "TX_ACCESS_LIST_ADDRESS_COST" |) + |) in + let _ := M.assign_op_local (| + BinOp.add, + "access_list_cost", + BinOp.mult (| + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_name (| globals, "keys" |) + ], + make_dict [] + |), + M.get_name (| globals, "TX_ACCESS_LIST_STORAGE_KEY_COST" |) + |) + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + BinOp.add (| + BinOp.add (| + BinOp.add (| + M.get_name (| globals, "TX_BASE_COST" |), + M.get_name (| globals, "data_cost" |) + |), + M.get_name (| globals, "create_cost" |) + |), + M.get_name (| globals, "access_list_cost" |) + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Definition recover_sender : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "chain_id"; "tx" ] |) in + let _ := Constant.str " + Extracts the sender address from a transaction. + + The v, r, and s values are the three parts that make up the signature + of a transaction. In order to recover the sender of a transaction the two + components needed are the signature (``v``, ``r``, and ``s``) and the + signing hash of the transaction. The sender's public key can be obtained + with these two values and therefore the sender address can be retrieved. + + Parameters + ---------- + tx : + Transaction of interest. + chain_id : + ID of the executing chain. + + Returns + ------- + sender : `ethereum.fork_types.Address` + The address of the account that signed the transaction. + " in + let _ := M.assign (| + make_tuple [ M.get_name (| globals, "r" |); M.get_name (| globals, "s" |) ], + make_tuple [ M.get_field (| M.get_name (| globals, "tx" |), "r" |); M.get_field (| M.get_name (| globals, "tx" |), "s" |) ] + |) in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + BoolOp.and (| + Compare.lt (| + Constant.int 0, + M.get_name (| globals, "r" |) + |), + ltac:(M.monadic ( + Compare.lt (| + M.get_name (| globals, "r" |), + M.get_name (| globals, "SECP256K1N" |) + |) + )) + |); + M.get_name (| globals, "InvalidBlock" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + BoolOp.and (| + Compare.lt (| + Constant.int 0, + M.get_name (| globals, "s" |) + |), + ltac:(M.monadic ( + Compare.lt_e (| + M.get_name (| globals, "s" |), + BinOp.floor_div (| + M.get_name (| globals, "SECP256K1N" |), + Constant.int 2 + |) + |) + )) + |); + M.get_name (| globals, "InvalidBlock" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, "isinstance" |), + make_list [ + M.get_name (| globals, "tx" |); + M.get_name (| globals, "LegacyTransaction" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "v" , + M.get_field (| M.get_name (| globals, "tx" |), "v" |) + |) in + let _ := + (* if *) + M.if_then_else (| + BoolOp.or (| + Compare.eq (| + M.get_name (| globals, "v" |), + Constant.int 27 + |), + ltac:(M.monadic ( + Compare.eq (| + M.get_name (| globals, "v" |), + Constant.int 28 + |) + )) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "public_key" , + M.call (| + M.get_name (| globals, "secp256k1_recover" |), + make_list [ + M.get_name (| globals, "r" |); + M.get_name (| globals, "s" |); + BinOp.sub (| + M.get_name (| globals, "v" |), + Constant.int 27 + |); + M.call (| + M.get_name (| globals, "signing_hash_pre155" |), + make_list [ + M.get_name (| globals, "tx" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + BoolOp.or (| + Compare.eq (| + M.get_name (| globals, "v" |), + BinOp.add (| + Constant.int 35, + BinOp.mult (| + M.get_name (| globals, "chain_id" |), + Constant.int 2 + |) + |) + |), + ltac:(M.monadic ( + Compare.eq (| + M.get_name (| globals, "v" |), + BinOp.add (| + Constant.int 36, + BinOp.mult (| + M.get_name (| globals, "chain_id" |), + Constant.int 2 + |) + |) + |) + )) + |); + M.get_name (| globals, "InvalidBlock" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "public_key" , + M.call (| + M.get_name (| globals, "secp256k1_recover" |), + make_list [ + M.get_name (| globals, "r" |); + M.get_name (| globals, "s" |); + BinOp.sub (| + BinOp.sub (| + M.get_name (| globals, "v" |), + Constant.int 35 + |), + BinOp.mult (| + M.get_name (| globals, "chain_id" |), + Constant.int 2 + |) + |); + M.call (| + M.get_name (| globals, "signing_hash_155" |), + make_list [ + M.get_name (| globals, "tx" |); + M.get_name (| globals, "chain_id" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, "isinstance" |), + make_list [ + M.get_name (| globals, "tx" |); + M.get_name (| globals, "AccessListTransaction" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "public_key" , + M.call (| + M.get_name (| globals, "secp256k1_recover" |), + make_list [ + M.get_name (| globals, "r" |); + M.get_name (| globals, "s" |); + M.get_field (| M.get_name (| globals, "tx" |), "y_parity" |); + M.call (| + M.get_name (| globals, "signing_hash_2930" |), + make_list [ + M.get_name (| globals, "tx" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, "isinstance" |), + make_list [ + M.get_name (| globals, "tx" |); + M.get_name (| globals, "FeeMarketTransaction" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "public_key" , + M.call (| + M.get_name (| globals, "secp256k1_recover" |), + make_list [ + M.get_name (| globals, "r" |); + M.get_name (| globals, "s" |); + M.get_field (| M.get_name (| globals, "tx" |), "y_parity" |); + M.call (| + M.get_name (| globals, "signing_hash_1559" |), + make_list [ + M.get_name (| globals, "tx" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )) |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, "Address" |), + make_list [ + M.slice (| + M.call (| + M.get_name (| globals, "keccak256" |), + make_list [ + M.get_name (| globals, "public_key" |) + ], + make_dict [] + |), + Constant.int 12, + Constant.int 32, + Constant.None_ + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Definition signing_hash_pre155 : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "tx" ] |) in + let _ := Constant.str " + Compute the hash of a transaction used in a legacy (pre EIP 155) signature. + + Parameters + ---------- + tx : + Transaction of interest. + + Returns + ------- + hash : `ethereum.crypto.hash.Hash32` + Hash of the transaction. + " in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, "keccak256" |), + make_list [ + M.call (| + M.get_field (| M.get_name (| globals, "rlp" |), "encode" |), + make_list [ + make_tuple [ M.get_field (| M.get_name (| globals, "tx" |), "nonce" |); M.get_field (| M.get_name (| globals, "tx" |), "gas_price" |); M.get_field (| M.get_name (| globals, "tx" |), "gas" |); M.get_field (| M.get_name (| globals, "tx" |), "to" |); M.get_field (| M.get_name (| globals, "tx" |), "value" |); M.get_field (| M.get_name (| globals, "tx" |), "data" |) ] + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Definition signing_hash_155 : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "tx"; "chain_id" ] |) in + let _ := Constant.str " + Compute the hash of a transaction used in a EIP 155 signature. + + Parameters + ---------- + tx : + Transaction of interest. + chain_id : + The id of the current chain. + + Returns + ------- + hash : `ethereum.crypto.hash.Hash32` + Hash of the transaction. + " in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, "keccak256" |), + make_list [ + M.call (| + M.get_field (| M.get_name (| globals, "rlp" |), "encode" |), + make_list [ + make_tuple [ M.get_field (| M.get_name (| globals, "tx" |), "nonce" |); M.get_field (| M.get_name (| globals, "tx" |), "gas_price" |); M.get_field (| M.get_name (| globals, "tx" |), "gas" |); M.get_field (| M.get_name (| globals, "tx" |), "to" |); M.get_field (| M.get_name (| globals, "tx" |), "value" |); M.get_field (| M.get_name (| globals, "tx" |), "data" |); M.get_name (| globals, "chain_id" |); M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |); M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) ] + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Definition signing_hash_2930 : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "tx" ] |) in + let _ := Constant.str " + Compute the hash of a transaction used in a EIP 2930 signature. + + Parameters + ---------- + tx : + Transaction of interest. + + Returns + ------- + hash : `ethereum.crypto.hash.Hash32` + Hash of the transaction. + " in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, "keccak256" |), + make_list [ + BinOp.add (| + Constant.bytes "01", + M.call (| + M.get_field (| M.get_name (| globals, "rlp" |), "encode" |), + make_list [ + make_tuple [ M.get_field (| M.get_name (| globals, "tx" |), "chain_id" |); M.get_field (| M.get_name (| globals, "tx" |), "nonce" |); M.get_field (| M.get_name (| globals, "tx" |), "gas_price" |); M.get_field (| M.get_name (| globals, "tx" |), "gas" |); M.get_field (| M.get_name (| globals, "tx" |), "to" |); M.get_field (| M.get_name (| globals, "tx" |), "value" |); M.get_field (| M.get_name (| globals, "tx" |), "data" |); M.get_field (| M.get_name (| globals, "tx" |), "access_list" |) ] + ], + make_dict [] + |) + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Definition signing_hash_1559 : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "tx" ] |) in + let _ := Constant.str " + Compute the hash of a transaction used in a EIP 1559 signature. + + Parameters + ---------- + tx : + Transaction of interest. + + Returns + ------- + hash : `ethereum.crypto.hash.Hash32` + Hash of the transaction. + " in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, "keccak256" |), + make_list [ + BinOp.add (| + Constant.bytes "02", + M.call (| + M.get_field (| M.get_name (| globals, "rlp" |), "encode" |), + make_list [ + make_tuple [ M.get_field (| M.get_name (| globals, "tx" |), "chain_id" |); M.get_field (| M.get_name (| globals, "tx" |), "nonce" |); M.get_field (| M.get_name (| globals, "tx" |), "max_priority_fee_per_gas" |); M.get_field (| M.get_name (| globals, "tx" |), "max_fee_per_gas" |); M.get_field (| M.get_name (| globals, "tx" |), "gas" |); M.get_field (| M.get_name (| globals, "tx" |), "to" |); M.get_field (| M.get_name (| globals, "tx" |), "value" |); M.get_field (| M.get_name (| globals, "tx" |), "data" |); M.get_field (| M.get_name (| globals, "tx" |), "access_list" |) ] + ], + make_dict [] + |) + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Definition compute_header_hash : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "header" ] |) in + let _ := Constant.str " + Computes the hash of a block header. + + The header hash of a block is the canonical hash that is used to refer + to a specific block and completely distinguishes a block from another. + + ``keccak256`` is a function that produces a 256 bit hash of any input. + It also takes in any number of bytes as an input and produces a single + hash for them. A hash is a completely unique output for a single input. + So an input corresponds to one unique hash that can be used to identify + the input exactly. + + Prior to using the ``keccak256`` hash function, the header must be + encoded using the Recursive-Length Prefix. See :ref:`rlp`. + RLP encoding the header converts it into a space-efficient format that + allows for easy transfer of data between nodes. The purpose of RLP is to + encode arbitrarily nested arrays of binary data, and RLP is the primary + encoding method used to serialize objects in Ethereum's execution layer. + The only purpose of RLP is to encode structure; encoding specific data + types (e.g. strings, floats) is left up to higher-order protocols. + + Parameters + ---------- + header : + Header of interest. + + Returns + ------- + hash : `ethereum.crypto.hash.Hash32` + Hash of the header. + " in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, "keccak256" |), + make_list [ + M.call (| + M.get_field (| M.get_name (| globals, "rlp" |), "encode" |), + make_list [ + M.get_name (| globals, "header" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Definition check_gas_limit : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "gas_limit"; "parent_gas_limit" ] |) in + let _ := Constant.str " + Validates the gas limit for a block. + + The bounds of the gas limit, ``max_adjustment_delta``, is set as the + quotient of the parent block's gas limit and the + ``GAS_LIMIT_ADJUSTMENT_FACTOR``. Therefore, if the gas limit that is + passed through as a parameter is greater than or equal to the *sum* of + the parent's gas and the adjustment delta then the limit for gas is too + high and fails this function's check. Similarly, if the limit is less + than or equal to the *difference* of the parent's gas and the adjustment + delta *or* the predefined ``GAS_LIMIT_MINIMUM`` then this function's + check fails because the gas limit doesn't allow for a sufficient or + reasonable amount of gas to be used on a block. + + Parameters + ---------- + gas_limit : + Gas limit to validate. + + parent_gas_limit : + Gas limit of the parent block. + + Returns + ------- + check : `bool` + True if gas limit constraints are satisfied, False otherwise. + " in + let _ := M.assign_local (| + "max_adjustment_delta" , + BinOp.floor_div (| + M.get_name (| globals, "parent_gas_limit" |), + M.get_name (| globals, "GAS_LIMIT_ADJUSTMENT_FACTOR" |) + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.gt_e (| + M.get_name (| globals, "gas_limit" |), + BinOp.add (| + M.get_name (| globals, "parent_gas_limit" |), + M.get_name (| globals, "max_adjustment_delta" |) + |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + Constant.bool false + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + Compare.lt_e (| + M.get_name (| globals, "gas_limit" |), + BinOp.sub (| + M.get_name (| globals, "parent_gas_limit" |), + M.get_name (| globals, "max_adjustment_delta" |) + |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + Constant.bool false + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + Compare.lt (| + M.get_name (| globals, "gas_limit" |), + M.get_name (| globals, "GAS_LIMIT_MINIMUM" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + Constant.bool false + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.return_ (| + Constant.bool true + |) in + M.pure Constant.None_)). diff --git a/CoqOfPython/ethereum/shanghai/fork_types.v b/CoqOfPython/ethereum/shanghai/fork_types.v new file mode 100644 index 0000000..ce691e3 --- /dev/null +++ b/CoqOfPython/ethereum/shanghai/fork_types.v @@ -0,0 +1,98 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.shanghai.fork_types". + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Types +^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Types re-used throughout the specification, which are specific to Ethereum. +". + +Axiom dataclasses_imports_dataclass : + IsImported globals "dataclasses" "dataclass". + +Axiom ethereum_imports_rlp : + IsImported globals "ethereum" "rlp". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_Bytes : + IsImported globals "ethereum.base_types" "Bytes". +Axiom ethereum_base_types_imports_Bytes20 : + IsImported globals "ethereum.base_types" "Bytes20". +Axiom ethereum_base_types_imports_Bytes256 : + IsImported globals "ethereum.base_types" "Bytes256". +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". +Axiom ethereum_base_types_imports_slotted_freezable : + IsImported globals "ethereum.base_types" "slotted_freezable". + +Axiom ethereum_crypto_hash_imports_Hash32 : + IsImported globals "ethereum.crypto.hash" "Hash32". +Axiom ethereum_crypto_hash_imports_keccak256 : + IsImported globals "ethereum.crypto.hash" "keccak256". + +Definition Address : Value.t := M.run ltac:(M.monadic ( + M.get_name (| globals, "Bytes20" |) +)). + +Definition Root : Value.t := M.run ltac:(M.monadic ( + M.get_name (| globals, "Hash32" |) +)). + +Definition Bloom : Value.t := M.run ltac:(M.monadic ( + M.get_name (| globals, "Bytes256" |) +)). + +Definition Account : Value.t := + builtins.make_klass + [] + [ + + ] + [ + + ]. + +Definition EMPTY_ACCOUNT : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Account" |), + make_list [], + make_dict [] + |) +)). + +Definition encode_account : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "raw_account_data"; "storage_root" ] |) in + let _ := Constant.str " + Encode `Account` dataclass. + + Storage is not stored in the `Account` dataclass, so `Accounts` cannot be + encoded with providing a storage root. + " in + let _ := M.return_ (| + M.call (| + M.get_field (| M.get_name (| globals, "rlp" |), "encode" |), + make_list [ + make_tuple [ M.get_field (| M.get_name (| globals, "raw_account_data" |), "nonce" |); M.get_field (| M.get_name (| globals, "raw_account_data" |), "balance" |); M.get_name (| globals, "storage_root" |); M.call (| + M.get_name (| globals, "keccak256" |), + make_list [ + M.get_field (| M.get_name (| globals, "raw_account_data" |), "code" |) + ], + make_dict [] + |) ] + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). diff --git a/CoqOfPython/ethereum/shanghai/state.v b/CoqOfPython/ethereum/shanghai/state.v new file mode 100644 index 0000000..6c39384 --- /dev/null +++ b/CoqOfPython/ethereum/shanghai/state.v @@ -0,0 +1,1273 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.shanghai.state". + +Definition expr_1 : Value.t := + Constant.str " +State +^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +The state contains all information that is preserved between transactions. + +It consists of a main account trie and storage tries for each contract. + +There is a distinction between an account that does not exist and +`EMPTY_ACCOUNT`. +". + +Axiom dataclasses_imports_dataclass : + IsImported globals "dataclasses" "dataclass". +Axiom dataclasses_imports_field : + IsImported globals "dataclasses" "field". + +Axiom typing_imports_Callable : + IsImported globals "typing" "Callable". +Axiom typing_imports_Dict : + IsImported globals "typing" "Dict". +Axiom typing_imports_List : + IsImported globals "typing" "List". +Axiom typing_imports_Optional : + IsImported globals "typing" "Optional". +Axiom typing_imports_Set : + IsImported globals "typing" "Set". +Axiom typing_imports_Tuple : + IsImported globals "typing" "Tuple". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_Bytes : + IsImported globals "ethereum.base_types" "Bytes". +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". +Axiom ethereum_base_types_imports_modify : + IsImported globals "ethereum.base_types" "modify". + +Axiom ethereum_utils_ensure_imports_ensure : + IsImported globals "ethereum.utils.ensure" "ensure". + +Axiom ethereum_shanghai_blocks_imports_Withdrawal : + IsImported globals "ethereum.shanghai.blocks" "Withdrawal". + +Axiom ethereum_shanghai_fork_types_imports_EMPTY_ACCOUNT : + IsImported globals "ethereum.shanghai.fork_types" "EMPTY_ACCOUNT". +Axiom ethereum_shanghai_fork_types_imports_Account : + IsImported globals "ethereum.shanghai.fork_types" "Account". +Axiom ethereum_shanghai_fork_types_imports_Address : + IsImported globals "ethereum.shanghai.fork_types" "Address". +Axiom ethereum_shanghai_fork_types_imports_Root : + IsImported globals "ethereum.shanghai.fork_types" "Root". + +Axiom ethereum_shanghai_trie_imports_EMPTY_TRIE_ROOT : + IsImported globals "ethereum.shanghai.trie" "EMPTY_TRIE_ROOT". +Axiom ethereum_shanghai_trie_imports_Trie : + IsImported globals "ethereum.shanghai.trie" "Trie". +Axiom ethereum_shanghai_trie_imports_copy_trie : + IsImported globals "ethereum.shanghai.trie" "copy_trie". +Axiom ethereum_shanghai_trie_imports_root : + IsImported globals "ethereum.shanghai.trie" "root". +Axiom ethereum_shanghai_trie_imports_trie_get : + IsImported globals "ethereum.shanghai.trie" "trie_get". +Axiom ethereum_shanghai_trie_imports_trie_set : + IsImported globals "ethereum.shanghai.trie" "trie_set". + +Definition State : Value.t := + builtins.make_klass + [] + [ + + ] + [ + + ]. + +Definition close_state : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "state" ] |) in + let _ := Constant.str " + Free resources held by the state. Used by optimized implementations to + release file descriptors. + " in + let _ := M.delete (| M.get_field (| M.get_name (| globals, "state" |), "_main_trie" |) |) in + let _ := M.delete (| M.get_field (| M.get_name (| globals, "state" |), "_storage_tries" |) |) in + let _ := M.delete (| M.get_field (| M.get_name (| globals, "state" |), "_snapshots" |) |) in + let _ := M.delete (| M.get_field (| M.get_name (| globals, "state" |), "_created_accounts" |) |) in + M.pure Constant.None_)). + +Definition begin_transaction : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "state" ] |) in + let _ := Constant.str " + Start a state transaction. + + Transactions are entirely implicit and can be nested. It is not possible to + calculate the state root during a transaction. + + Parameters + ---------- + state : State + The state. + " in + let _ := M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, "state" |), "_snapshots" |), "append" |), + make_list [ + make_tuple [ M.call (| + M.get_name (| globals, "copy_trie" |), + make_list [ + M.get_field (| M.get_name (| globals, "state" |), "_main_trie" |) + ], + make_dict [] + |); Constant.str "(* At expr: unsupported node type: DictComp *)" ] + ], + make_dict [] + |) in + M.pure Constant.None_)). + +Definition commit_transaction : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "state" ] |) in + let _ := Constant.str " + Commit a state transaction. + + Parameters + ---------- + state : State + The state. + " in + let _ := M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, "state" |), "_snapshots" |), "pop" |), + make_list [], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + UnOp.not (| M.get_field (| M.get_name (| globals, "state" |), "_snapshots" |) |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, "state" |), "_created_accounts" |), "clear" |), + make_list [], + make_dict [] + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + M.pure Constant.None_)). + +Definition rollback_transaction : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "state" ] |) in + let _ := Constant.str " + Rollback a state transaction, resetting the state to the point when the + corresponding `start_transaction()` call was made. + + Parameters + ---------- + state : State + The state. + " in + let _ := M.assign (| + make_tuple [ M.get_field (| M.get_name (| globals, "state" |), "_main_trie" |); M.get_field (| M.get_name (| globals, "state" |), "_storage_tries" |) ], + M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, "state" |), "_snapshots" |), "pop" |), + make_list [], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + UnOp.not (| M.get_field (| M.get_name (| globals, "state" |), "_snapshots" |) |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, "state" |), "_created_accounts" |), "clear" |), + make_list [], + make_dict [] + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + M.pure Constant.None_)). + +Definition get_account : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "state"; "address" ] |) in + let _ := Constant.str " + Get the `Account` object at an address. Returns `EMPTY_ACCOUNT` if there + is no account at the address. + + Use `get_account_optional()` if you care about the difference between a + non-existent account and `EMPTY_ACCOUNT`. + + Parameters + ---------- + state: `State` + The state + address : `Address` + Address to lookup. + + Returns + ------- + account : `Account` + Account at address. + " in + let _ := M.assign_local (| + "account" , + M.call (| + M.get_name (| globals, "get_account_optional" |), + make_list [ + M.get_name (| globals, "state" |); + M.get_name (| globals, "address" |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, "isinstance" |), + make_list [ + M.get_name (| globals, "account" |); + M.get_name (| globals, "Account" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + M.get_name (| globals, "account" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.return_ (| + M.get_name (| globals, "EMPTY_ACCOUNT" |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_)). + +Definition get_account_optional : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "state"; "address" ] |) in + let _ := Constant.str " + Get the `Account` object at an address. Returns `None` (rather than + `EMPTY_ACCOUNT`) if there is no account at the address. + + Parameters + ---------- + state: `State` + The state + address : `Address` + Address to lookup. + + Returns + ------- + account : `Account` + Account at address. + " in + let _ := M.assign_local (| + "account" , + M.call (| + M.get_name (| globals, "trie_get" |), + make_list [ + M.get_field (| M.get_name (| globals, "state" |), "_main_trie" |); + M.get_name (| globals, "address" |) + ], + make_dict [] + |) + |) in + let _ := M.return_ (| + M.get_name (| globals, "account" |) + |) in + M.pure Constant.None_)). + +Definition set_account : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "state"; "address"; "account" ] |) in + let _ := Constant.str " + Set the `Account` object at an address. Setting to `None` deletes + the account (but not its storage, see `destroy_account()`). + + Parameters + ---------- + state: `State` + The state + address : `Address` + Address to set. + account : `Account` + Account to set at address. + " in + let _ := M.call (| + M.get_name (| globals, "trie_set" |), + make_list [ + M.get_field (| M.get_name (| globals, "state" |), "_main_trie" |); + M.get_name (| globals, "address" |); + M.get_name (| globals, "account" |) + ], + make_dict [] + |) in + M.pure Constant.None_)). + +Definition destroy_account : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "state"; "address" ] |) in + let _ := Constant.str " + Completely remove the account at `address` and all of its storage. + + This function is made available exclusively for the `SELFDESTRUCT` + opcode. It is expected that `SELFDESTRUCT` will be disabled in a future + hardfork and this function will be removed. + + Parameters + ---------- + state: `State` + The state + address : `Address` + Address of account to destroy. + " in + let _ := M.call (| + M.get_name (| globals, "destroy_storage" |), + make_list [ + M.get_name (| globals, "state" |); + M.get_name (| globals, "address" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "set_account" |), + make_list [ + M.get_name (| globals, "state" |); + M.get_name (| globals, "address" |); + Constant.None_ + ], + make_dict [] + |) in + M.pure Constant.None_)). + +Definition destroy_storage : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "state"; "address" ] |) in + let _ := Constant.str " + Completely remove the storage at `address`. + + Parameters + ---------- + state: `State` + The state + address : `Address` + Address of account whose storage is to be deleted. + " in + let _ := + (* if *) + M.if_then_else (| + Compare.in_ (| + M.get_name (| globals, "address" |), + M.get_field (| M.get_name (| globals, "state" |), "_storage_tries" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.delete (| M.get_subscript (| + M.get_field (| M.get_name (| globals, "state" |), "_storage_tries" |), + M.get_name (| globals, "address" |) + |) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + M.pure Constant.None_)). + +Definition mark_account_created : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "state"; "address" ] |) in + let _ := Constant.str " + Mark an account as having been created in the current transaction. + This information is used by `get_storage_original()` to handle an obscure + edgecase. + + The marker is not removed even if the account creation reverts. Since the + account cannot have had code prior to its creation and can't call + `get_storage_original()`, this is harmless. + + Parameters + ---------- + state: `State` + The state + address : `Address` + Address of the account that has been created. + " in + let _ := M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, "state" |), "_created_accounts" |), "add" |), + make_list [ + M.get_name (| globals, "address" |) + ], + make_dict [] + |) in + M.pure Constant.None_)). + +Definition get_storage : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "state"; "address"; "key" ] |) in + let _ := Constant.str " + Get a value at a storage key on an account. Returns `U256(0)` if the + storage key has not been set previously. + + Parameters + ---------- + state: `State` + The state + address : `Address` + Address of the account. + key : `Bytes` + Key to lookup. + + Returns + ------- + value : `U256` + Value at the key. + " in + let _ := M.assign_local (| + "trie" , + M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, "state" |), "_storage_tries" |), "get" |), + make_list [ + M.get_name (| globals, "address" |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.is (| + M.get_name (| globals, "trie" |), + Constant.None_ + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "value" , + M.call (| + M.get_name (| globals, "trie_get" |), + make_list [ + M.get_name (| globals, "trie" |); + M.get_name (| globals, "key" |) + ], + make_dict [] + |) + |) in + let _ := M.assert (| M.call (| + M.get_name (| globals, "isinstance" |), + make_list [ + M.get_name (| globals, "value" |); + M.get_name (| globals, "U256" |) + ], + make_dict [] + |) |) in + let _ := M.return_ (| + M.get_name (| globals, "value" |) + |) in + M.pure Constant.None_)). + +Definition set_storage : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "state"; "address"; "key"; "value" ] |) in + let _ := Constant.str " + Set a value at a storage key on an account. Setting to `U256(0)` deletes + the key. + + Parameters + ---------- + state: `State` + The state + address : `Address` + Address of the account. + key : `Bytes` + Key to set. + value : `U256` + Value to set at the key. + " in + let _ := M.assert (| Compare.is_not (| + M.call (| + M.get_name (| globals, "trie_get" |), + make_list [ + M.get_field (| M.get_name (| globals, "state" |), "_main_trie" |); + M.get_name (| globals, "address" |) + ], + make_dict [] + |), + Constant.None_ + |) |) in + let _ := M.assign_local (| + "trie" , + M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, "state" |), "_storage_tries" |), "get" |), + make_list [ + M.get_name (| globals, "address" |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.is (| + M.get_name (| globals, "trie" |), + Constant.None_ + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "trie" , + M.call (| + M.get_name (| globals, "Trie" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.assign (| + M.get_subscript (| + M.get_field (| M.get_name (| globals, "state" |), "_storage_tries" |), + M.get_name (| globals, "address" |) + |), + M.get_name (| globals, "trie" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.call (| + M.get_name (| globals, "trie_set" |), + make_list [ + M.get_name (| globals, "trie" |); + M.get_name (| globals, "key" |); + M.get_name (| globals, "value" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_field (| M.get_name (| globals, "trie" |), "_data" |), + Constant.str "(* At expr: unsupported node type: Dict *)" + |), + (* then *) + ltac:(M.monadic ( + let _ := M.delete (| M.get_subscript (| + M.get_field (| M.get_name (| globals, "state" |), "_storage_tries" |), + M.get_name (| globals, "address" |) + |) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + M.pure Constant.None_)). + +Definition storage_root : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "state"; "address" ] |) in + let _ := Constant.str " + Calculate the storage root of an account. + + Parameters + ---------- + state: + The state + address : + Address of the account. + + Returns + ------- + root : `Root` + Storage root of the account. + " in + let _ := M.assert (| UnOp.not (| M.get_field (| M.get_name (| globals, "state" |), "_snapshots" |) |) |) in + let _ := + (* if *) + M.if_then_else (| + Compare.in_ (| + M.get_name (| globals, "address" |), + M.get_field (| M.get_name (| globals, "state" |), "_storage_tries" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + M.call (| + M.get_name (| globals, "root" |), + make_list [ + M.get_subscript (| + M.get_field (| M.get_name (| globals, "state" |), "_storage_tries" |), + M.get_name (| globals, "address" |) + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.return_ (| + M.get_name (| globals, "EMPTY_TRIE_ROOT" |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_)). + +Definition state_root : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "state" ] |) in + let _ := Constant.str " + Calculate the state root. + + Parameters + ---------- + state: + The current state. + + Returns + ------- + root : `Root` + The state root. + " in + let _ := M.assert (| UnOp.not (| M.get_field (| M.get_name (| globals, "state" |), "_snapshots" |) |) |) in +(* At stmt: unsupported node type: FunctionDef *) + let _ := M.return_ (| + M.call (| + M.get_name (| globals, "root" |), + make_list [ + M.get_field (| M.get_name (| globals, "state" |), "_main_trie" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Definition account_exists : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "state"; "address" ] |) in + let _ := Constant.str " + Checks if an account exists in the state trie + + Parameters + ---------- + state: + The state + address: + Address of the account that needs to be checked. + + Returns + ------- + account_exists : `bool` + True if account exists in the state trie, False otherwise + " in + let _ := M.return_ (| + Compare.is_not (| + M.call (| + M.get_name (| globals, "get_account_optional" |), + make_list [ + M.get_name (| globals, "state" |); + M.get_name (| globals, "address" |) + ], + make_dict [] + |), + Constant.None_ + |) + |) in + M.pure Constant.None_)). + +Definition account_has_code_or_nonce : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "state"; "address" ] |) in + let _ := Constant.str " + Checks if an account has non zero nonce or non empty code + + Parameters + ---------- + state: + The state + address: + Address of the account that needs to be checked. + + Returns + ------- + has_code_or_nonce : `bool` + True if if an account has non zero nonce or non empty code, + False otherwise. + " in + let _ := M.assign_local (| + "account" , + M.call (| + M.get_name (| globals, "get_account" |), + make_list [ + M.get_name (| globals, "state" |); + M.get_name (| globals, "address" |) + ], + make_dict [] + |) + |) in + let _ := M.return_ (| + BoolOp.or (| + Compare.not_eq (| + M.get_field (| M.get_name (| globals, "account" |), "nonce" |), + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + |), + ltac:(M.monadic ( + Compare.not_eq (| + M.get_field (| M.get_name (| globals, "account" |), "code" |), + Constant.bytes "" + |) + )) + |) + |) in + M.pure Constant.None_)). + +Definition is_account_empty : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "state"; "address" ] |) in + let _ := Constant.str " + Checks if an account has zero nonce, empty code and zero balance. + + Parameters + ---------- + state: + The state + address: + Address of the account that needs to be checked. + + Returns + ------- + is_empty : `bool` + True if if an account has zero nonce, empty code and zero balance, + False otherwise. + " in + let _ := M.assign_local (| + "account" , + M.call (| + M.get_name (| globals, "get_account" |), + make_list [ + M.get_name (| globals, "state" |); + M.get_name (| globals, "address" |) + ], + make_dict [] + |) + |) in + let _ := M.return_ (| + BoolOp.and (| + Compare.eq (| + M.get_field (| M.get_name (| globals, "account" |), "nonce" |), + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + |), + ltac:(M.monadic ( + BoolOp.and (| + Compare.eq (| + M.get_field (| M.get_name (| globals, "account" |), "code" |), + Constant.bytes "" + |), + ltac:(M.monadic ( + Compare.eq (| + M.get_field (| M.get_name (| globals, "account" |), "balance" |), + Constant.int 0 + |) + )) + |) + )) + |) + |) in + M.pure Constant.None_)). + +Definition account_exists_and_is_empty : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "state"; "address" ] |) in + let _ := Constant.str " + Checks if an account exists and has zero nonce, empty code and zero + balance. + + Parameters + ---------- + state: + The state + address: + Address of the account that needs to be checked. + + Returns + ------- + exists_and_is_empty : `bool` + True if an account exists and has zero nonce, empty code and zero + balance, False otherwise. + " in + let _ := M.assign_local (| + "account" , + M.call (| + M.get_name (| globals, "get_account_optional" |), + make_list [ + M.get_name (| globals, "state" |); + M.get_name (| globals, "address" |) + ], + make_dict [] + |) + |) in + let _ := M.return_ (| + BoolOp.and (| + Compare.is_not (| + M.get_name (| globals, "account" |), + Constant.None_ + |), + ltac:(M.monadic ( + BoolOp.and (| + Compare.eq (| + M.get_field (| M.get_name (| globals, "account" |), "nonce" |), + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + |), + ltac:(M.monadic ( + BoolOp.and (| + Compare.eq (| + M.get_field (| M.get_name (| globals, "account" |), "code" |), + Constant.bytes "" + |), + ltac:(M.monadic ( + Compare.eq (| + M.get_field (| M.get_name (| globals, "account" |), "balance" |), + Constant.int 0 + |) + )) + |) + )) + |) + )) + |) + |) in + M.pure Constant.None_)). + +Definition is_account_alive : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "state"; "address" ] |) in + let _ := Constant.str " + Check whether is an account is both in the state and non empty. + + Parameters + ---------- + state: + The state + address: + Address of the account that needs to be checked. + + Returns + ------- + is_alive : `bool` + True if the account is alive. + " in + let _ := M.assign_local (| + "account" , + M.call (| + M.get_name (| globals, "get_account_optional" |), + make_list [ + M.get_name (| globals, "state" |); + M.get_name (| globals, "address" |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.is (| + M.get_name (| globals, "account" |), + Constant.None_ + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + Constant.bool false + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.return_ (| + UnOp.not (| BoolOp.and (| + Compare.eq (| + M.get_field (| M.get_name (| globals, "account" |), "nonce" |), + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + |), + ltac:(M.monadic ( + BoolOp.and (| + Compare.eq (| + M.get_field (| M.get_name (| globals, "account" |), "code" |), + Constant.bytes "" + |), + ltac:(M.monadic ( + Compare.eq (| + M.get_field (| M.get_name (| globals, "account" |), "balance" |), + Constant.int 0 + |) + )) + |) + )) + |) |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_)). + +Definition modify_state : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "state"; "address"; "f" ] |) in + let _ := Constant.str " + Modify an `Account` in the `State`. + " in + let _ := M.call (| + M.get_name (| globals, "set_account" |), + make_list [ + M.get_name (| globals, "state" |); + M.get_name (| globals, "address" |); + M.call (| + M.get_name (| globals, "modify" |), + make_list [ + M.call (| + M.get_name (| globals, "get_account" |), + make_list [ + M.get_name (| globals, "state" |); + M.get_name (| globals, "address" |) + ], + make_dict [] + |); + M.get_name (| globals, "f" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + M.pure Constant.None_)). + +Definition move_ether : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "state"; "sender_address"; "recipient_address"; "amount" ] |) in + let _ := Constant.str " + Move funds between accounts. + " in +(* At stmt: unsupported node type: FunctionDef *) +(* At stmt: unsupported node type: FunctionDef *) + let _ := M.call (| + M.get_name (| globals, "modify_state" |), + make_list [ + M.get_name (| globals, "state" |); + M.get_name (| globals, "sender_address" |); + M.get_name (| globals, "reduce_sender_balance" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "modify_state" |), + make_list [ + M.get_name (| globals, "state" |); + M.get_name (| globals, "recipient_address" |); + M.get_name (| globals, "increase_recipient_balance" |) + ], + make_dict [] + |) in + M.pure Constant.None_)). + +Definition process_withdrawal : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "state"; "wd" ] |) in + let _ := Constant.str " + Increase the balance of the withdrawing account. + " in +(* At stmt: unsupported node type: FunctionDef *) + let _ := M.call (| + M.get_name (| globals, "modify_state" |), + make_list [ + M.get_name (| globals, "state" |); + M.get_field (| M.get_name (| globals, "wd" |), "address" |); + M.get_name (| globals, "increase_recipient_balance" |) + ], + make_dict [] + |) in + M.pure Constant.None_)). + +Definition set_account_balance : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "state"; "address"; "amount" ] |) in + let _ := Constant.str " + Sets the balance of an account. + + Parameters + ---------- + state: + The current state. + + address: + Address of the account whose nonce needs to be incremented. + + amount: + The amount that needs to set in balance. + " in +(* At stmt: unsupported node type: FunctionDef *) + let _ := M.call (| + M.get_name (| globals, "modify_state" |), + make_list [ + M.get_name (| globals, "state" |); + M.get_name (| globals, "address" |); + M.get_name (| globals, "set_balance" |) + ], + make_dict [] + |) in + M.pure Constant.None_)). + +Definition touch_account : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "state"; "address" ] |) in + let _ := Constant.str " + Initializes an account to state. + + Parameters + ---------- + state: + The current state. + + address: + The address of the account that need to initialised. + " in + let _ := + (* if *) + M.if_then_else (| + UnOp.not (| M.call (| + M.get_name (| globals, "account_exists" |), + make_list [ + M.get_name (| globals, "state" |); + M.get_name (| globals, "address" |) + ], + make_dict [] + |) |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, "set_account" |), + make_list [ + M.get_name (| globals, "state" |); + M.get_name (| globals, "address" |); + M.get_name (| globals, "EMPTY_ACCOUNT" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + M.pure Constant.None_)). + +Definition increment_nonce : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "state"; "address" ] |) in + let _ := Constant.str " + Increments the nonce of an account. + + Parameters + ---------- + state: + The current state. + + address: + Address of the account whose nonce needs to be incremented. + " in +(* At stmt: unsupported node type: FunctionDef *) + let _ := M.call (| + M.get_name (| globals, "modify_state" |), + make_list [ + M.get_name (| globals, "state" |); + M.get_name (| globals, "address" |); + M.get_name (| globals, "increase_nonce" |) + ], + make_dict [] + |) in + M.pure Constant.None_)). + +Definition set_code : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "state"; "address"; "code" ] |) in + let _ := Constant.str " + Sets Account code. + + Parameters + ---------- + state: + The current state. + + address: + Address of the account whose code needs to be update. + + code: + The bytecode that needs to be set. + " in +(* At stmt: unsupported node type: FunctionDef *) + let _ := M.call (| + M.get_name (| globals, "modify_state" |), + make_list [ + M.get_name (| globals, "state" |); + M.get_name (| globals, "address" |); + M.get_name (| globals, "write_code" |) + ], + make_dict [] + |) in + M.pure Constant.None_)). + +Definition get_storage_original : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "state"; "address"; "key" ] |) in + let _ := Constant.str " + Get the original value in a storage slot i.e. the value before the current + transaction began. This function reads the value from the snapshots taken + before executing the transaction. + + Parameters + ---------- + state: + The current state. + address: + Address of the account to read the value from. + key: + Key of the storage slot. + " in + let _ := + (* if *) + M.if_then_else (| + Compare.in_ (| + M.get_name (| globals, "address" |), + M.get_field (| M.get_name (| globals, "state" |), "_created_accounts" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign (| + make_tuple [ M.get_name (| globals, "_" |); M.get_name (| globals, "original_trie" |) ], + M.get_subscript (| + M.get_field (| M.get_name (| globals, "state" |), "_snapshots" |), + Constant.int 0 + |) + |) in + let _ := M.assign_local (| + "original_account_trie" , + M.call (| + M.get_field (| M.get_name (| globals, "original_trie" |), "get" |), + make_list [ + M.get_name (| globals, "address" |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.is (| + M.get_name (| globals, "original_account_trie" |), + Constant.None_ + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "original_value" , + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "original_value" , + M.call (| + M.get_name (| globals, "trie_get" |), + make_list [ + M.get_name (| globals, "original_account_trie" |); + M.get_name (| globals, "key" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + )) |) in + let _ := M.assert (| M.call (| + M.get_name (| globals, "isinstance" |), + make_list [ + M.get_name (| globals, "original_value" |); + M.get_name (| globals, "U256" |) + ], + make_dict [] + |) |) in + let _ := M.return_ (| + M.get_name (| globals, "original_value" |) + |) in + M.pure Constant.None_)). diff --git a/CoqOfPython/ethereum/shanghai/transactions.v b/CoqOfPython/ethereum/shanghai/transactions.v new file mode 100644 index 0000000..76f69cd --- /dev/null +++ b/CoqOfPython/ethereum/shanghai/transactions.v @@ -0,0 +1,293 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.shanghai.transactions". + +Definition expr_1 : Value.t := + Constant.str " +Transactions are atomic units of work created externally to Ethereum and +submitted to be executed. If Ethereum is viewed as a state machine, +transactions are the events that move between states. +". + +Axiom dataclasses_imports_dataclass : + IsImported globals "dataclasses" "dataclass". + +Axiom typing_imports_Tuple : + IsImported globals "typing" "Tuple". +Axiom typing_imports_Union : + IsImported globals "typing" "Union". + +Axiom ethereum_imports_rlp : + IsImported globals "ethereum" "rlp". + +Axiom ethereum_base_types_imports_U64 : + IsImported globals "ethereum.base_types" "U64". +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_Bytes : + IsImported globals "ethereum.base_types" "Bytes". +Axiom ethereum_base_types_imports_Bytes0 : + IsImported globals "ethereum.base_types" "Bytes0". +Axiom ethereum_base_types_imports_Bytes32 : + IsImported globals "ethereum.base_types" "Bytes32". +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". +Axiom ethereum_base_types_imports_slotted_freezable : + IsImported globals "ethereum.base_types" "slotted_freezable". + +Axiom ethereum_exceptions_imports_InvalidBlock : + IsImported globals "ethereum.exceptions" "InvalidBlock". + +Axiom ethereum_shanghai_fork_types_imports_Address : + IsImported globals "ethereum.shanghai.fork_types" "Address". + +Definition TX_BASE_COST : Value.t := M.run ltac:(M.monadic ( + Constant.int 21000 +)). + +Definition TX_DATA_COST_PER_NON_ZERO : Value.t := M.run ltac:(M.monadic ( + Constant.int 16 +)). + +Definition TX_DATA_COST_PER_ZERO : Value.t := M.run ltac:(M.monadic ( + Constant.int 4 +)). + +Definition TX_CREATE_COST : Value.t := M.run ltac:(M.monadic ( + Constant.int 32000 +)). + +Definition TX_ACCESS_LIST_ADDRESS_COST : Value.t := M.run ltac:(M.monadic ( + Constant.int 2400 +)). + +Definition TX_ACCESS_LIST_STORAGE_KEY_COST : Value.t := M.run ltac:(M.monadic ( + Constant.int 1900 +)). + +Definition LegacyTransaction : Value.t := + builtins.make_klass + [] + [ + + ] + [ + + ]. + +Definition AccessListTransaction : Value.t := + builtins.make_klass + [] + [ + + ] + [ + + ]. + +Definition FeeMarketTransaction : Value.t := + builtins.make_klass + [] + [ + + ] + [ + + ]. + +Definition Transaction : Value.t := M.run ltac:(M.monadic ( + M.get_subscript (| + M.get_name (| globals, "Union" |), + make_tuple [ M.get_name (| globals, "LegacyTransaction" |); M.get_name (| globals, "AccessListTransaction" |); M.get_name (| globals, "FeeMarketTransaction" |) ] + |) +)). + +Definition encode_transaction : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "tx" ] |) in + let _ := Constant.str " + Encode a transaction. Needed because non-legacy transactions aren't RLP. + " in + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, "isinstance" |), + make_list [ + M.get_name (| globals, "tx" |); + M.get_name (| globals, "LegacyTransaction" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + M.get_name (| globals, "tx" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, "isinstance" |), + make_list [ + M.get_name (| globals, "tx" |); + M.get_name (| globals, "AccessListTransaction" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + BinOp.add (| + Constant.bytes "01", + M.call (| + M.get_field (| M.get_name (| globals, "rlp" |), "encode" |), + make_list [ + M.get_name (| globals, "tx" |) + ], + make_dict [] + |) + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, "isinstance" |), + make_list [ + M.get_name (| globals, "tx" |); + M.get_name (| globals, "FeeMarketTransaction" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + BinOp.add (| + Constant.bytes "02", + M.call (| + M.get_field (| M.get_name (| globals, "rlp" |), "encode" |), + make_list [ + M.get_name (| globals, "tx" |) + ], + make_dict [] + |) + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.raise (| Some (M.call (| + M.get_name (| globals, "Exception" |), + make_list [ + Constant.str "(* At expr: unsupported node type: JoinedStr *)" + ], + make_dict [] + |)) |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_)). + +Definition decode_transaction : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "tx" ] |) in + let _ := Constant.str " + Decode a transaction. Needed because non-legacy transactions aren't RLP. + " in + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, "isinstance" |), + make_list [ + M.get_name (| globals, "tx" |); + M.get_name (| globals, "Bytes" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_subscript (| + M.get_name (| globals, "tx" |), + Constant.int 0 + |), + Constant.int 1 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + M.call (| + M.get_field (| M.get_name (| globals, "rlp" |), "decode_to" |), + make_list [ + M.get_name (| globals, "AccessListTransaction" |); + M.slice (| + M.get_name (| globals, "tx" |), + Constant.int 1, + Constant.None_, + Constant.None_ + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_subscript (| + M.get_name (| globals, "tx" |), + Constant.int 0 + |), + Constant.int 2 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + M.call (| + M.get_field (| M.get_name (| globals, "rlp" |), "decode_to" |), + make_list [ + M.get_name (| globals, "FeeMarketTransaction" |); + M.slice (| + M.get_name (| globals, "tx" |), + Constant.int 1, + Constant.None_, + Constant.None_ + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, "InvalidBlock" |)) |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.return_ (| + M.get_name (| globals, "tx" |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_)). diff --git a/CoqOfPython/ethereum/shanghai/trie.v b/CoqOfPython/ethereum/shanghai/trie.v new file mode 100644 index 0000000..3192625 --- /dev/null +++ b/CoqOfPython/ethereum/shanghai/trie.v @@ -0,0 +1,1604 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.shanghai.trie". + +Definition expr_1 : Value.t := + Constant.str " +State Trie +^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +The state trie is the structure responsible for storing +`.fork_types.Account` objects. +". + +(* At top_level_stmt: unsupported node type: Import *) + +Axiom dataclasses_imports_dataclass : + IsImported globals "dataclasses" "dataclass". +Axiom dataclasses_imports_field : + IsImported globals "dataclasses" "field". + +Axiom typing_imports_Callable : + IsImported globals "typing" "Callable". +Axiom typing_imports_Dict : + IsImported globals "typing" "Dict". +Axiom typing_imports_Generic : + IsImported globals "typing" "Generic". +Axiom typing_imports_List : + IsImported globals "typing" "List". +Axiom typing_imports_Mapping : + IsImported globals "typing" "Mapping". +Axiom typing_imports_MutableMapping : + IsImported globals "typing" "MutableMapping". +Axiom typing_imports_Optional : + IsImported globals "typing" "Optional". +Axiom typing_imports_Sequence : + IsImported globals "typing" "Sequence". +Axiom typing_imports_TypeVar : + IsImported globals "typing" "TypeVar". +Axiom typing_imports_Union : + IsImported globals "typing" "Union". +Axiom typing_imports_cast : + IsImported globals "typing" "cast". + +Axiom ethereum_crypto_hash_imports_keccak256 : + IsImported globals "ethereum.crypto.hash" "keccak256". + +Axiom ethereum_paris_imports_trie : + IsImported globals "ethereum.paris" "trie". + +Axiom ethereum_utils_ensure_imports_ensure : + IsImported globals "ethereum.utils.ensure" "ensure". + +Axiom ethereum_utils_hexadecimal_imports_hex_to_bytes : + IsImported globals "ethereum.utils.hexadecimal" "hex_to_bytes". + +Axiom ethereum_imports_rlp : + IsImported globals "ethereum" "rlp". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_Bytes : + IsImported globals "ethereum.base_types" "Bytes". +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". +Axiom ethereum_base_types_imports_slotted_freezable : + IsImported globals "ethereum.base_types" "slotted_freezable". + +Axiom ethereum_shanghai_blocks_imports_Receipt : + IsImported globals "ethereum.shanghai.blocks" "Receipt". +Axiom ethereum_shanghai_blocks_imports_Withdrawal : + IsImported globals "ethereum.shanghai.blocks" "Withdrawal". + +Axiom ethereum_shanghai_fork_types_imports_Account : + IsImported globals "ethereum.shanghai.fork_types" "Account". +Axiom ethereum_shanghai_fork_types_imports_Address : + IsImported globals "ethereum.shanghai.fork_types" "Address". +Axiom ethereum_shanghai_fork_types_imports_Root : + IsImported globals "ethereum.shanghai.fork_types" "Root". +Axiom ethereum_shanghai_fork_types_imports_encode_account : + IsImported globals "ethereum.shanghai.fork_types" "encode_account". + +Axiom ethereum_shanghai_transactions_imports_LegacyTransaction : + IsImported globals "ethereum.shanghai.transactions" "LegacyTransaction". + +Definition EMPTY_TRIE_ROOT : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Root" |), + make_list [ + M.call (| + M.get_name (| globals, "hex_to_bytes" |), + make_list [ + Constant.str "56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421" + ], + make_dict [] + |) + ], + make_dict [] + |) +)). + +Definition Node : Value.t := M.run ltac:(M.monadic ( + M.get_subscript (| + M.get_name (| globals, "Union" |), + make_tuple [ M.get_name (| globals, "Account" |); M.get_name (| globals, "Bytes" |); M.get_name (| globals, "LegacyTransaction" |); M.get_name (| globals, "Receipt" |); M.get_name (| globals, "Uint" |); M.get_name (| globals, "U256" |); M.get_name (| globals, "Withdrawal" |); Constant.None_ ] + |) +)). + +Definition K : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "TypeVar" |), + make_list [ + Constant.str "K" + ], + make_dict [] + |) +)). + +Definition V : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "TypeVar" |), + make_list [ + Constant.str "V"; + M.get_subscript (| + M.get_name (| globals, "Optional" |), + M.get_name (| globals, "Account" |) + |); + M.get_subscript (| + M.get_name (| globals, "Optional" |), + M.get_name (| globals, "Bytes" |) + |); + M.get_name (| globals, "Bytes" |); + M.get_subscript (| + M.get_name (| globals, "Optional" |), + M.get_subscript (| + M.get_name (| globals, "Union" |), + make_tuple [ M.get_name (| globals, "LegacyTransaction" |); M.get_name (| globals, "Bytes" |) ] + |) + |); + M.get_subscript (| + M.get_name (| globals, "Optional" |), + M.get_subscript (| + M.get_name (| globals, "Union" |), + make_tuple [ M.get_name (| globals, "Receipt" |); M.get_name (| globals, "Bytes" |) ] + |) + |); + M.get_subscript (| + M.get_name (| globals, "Optional" |), + M.get_subscript (| + M.get_name (| globals, "Union" |), + make_tuple [ M.get_name (| globals, "Withdrawal" |); M.get_name (| globals, "Bytes" |) ] + |) + |); + M.get_name (| globals, "Uint" |); + M.get_name (| globals, "U256" |) + ], + make_dict [] + |) +)). + +Definition LeafNode : Value.t := + builtins.make_klass + [] + [ + + ] + [ + + ]. + +Definition ExtensionNode : Value.t := + builtins.make_klass + [] + [ + + ] + [ + + ]. + +Definition BranchNode : Value.t := + builtins.make_klass + [] + [ + + ] + [ + + ]. + +Definition InternalNode : Value.t := M.run ltac:(M.monadic ( + M.get_subscript (| + M.get_name (| globals, "Union" |), + make_tuple [ M.get_name (| globals, "LeafNode" |); M.get_name (| globals, "ExtensionNode" |); M.get_name (| globals, "BranchNode" |) ] + |) +)). + +Definition encode_internal_node : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "node" ] |) in + let _ := Constant.str " + Encodes a Merkle Trie node into its RLP form. The RLP will then be + serialized into a `Bytes` and hashed unless it is less that 32 bytes + when serialized. + + This function also accepts `None`, representing the absence of a node, + which is encoded to `b""""`. + + Parameters + ---------- + node : Optional[InternalNode] + The node to encode. + + Returns + ------- + encoded : `rlp.RLP` + The node encoded as RLP. + " in +(* At stmt: unsupported node type: AnnAssign *) + let _ := + (* if *) + M.if_then_else (| + Compare.is (| + M.get_name (| globals, "node" |), + Constant.None_ + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "unencoded" , + Constant.bytes "" + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, "isinstance" |), + make_list [ + M.get_name (| globals, "node" |); + M.get_name (| globals, "LeafNode" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "unencoded" , + make_tuple [ M.call (| + M.get_name (| globals, "nibble_list_to_compact" |), + make_list [ + M.get_field (| M.get_name (| globals, "node" |), "rest_of_key" |); + Constant.bool true + ], + make_dict [] + |); M.get_field (| M.get_name (| globals, "node" |), "value" |) ] + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, "isinstance" |), + make_list [ + M.get_name (| globals, "node" |); + M.get_name (| globals, "ExtensionNode" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "unencoded" , + make_tuple [ M.call (| + M.get_name (| globals, "nibble_list_to_compact" |), + make_list [ + M.get_field (| M.get_name (| globals, "node" |), "key_segment" |); + Constant.bool false + ], + make_dict [] + |); M.get_field (| M.get_name (| globals, "node" |), "subnode" |) ] + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, "isinstance" |), + make_list [ + M.get_name (| globals, "node" |); + M.get_name (| globals, "BranchNode" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "unencoded" , + BinOp.add (| + M.get_field (| M.get_name (| globals, "node" |), "subnodes" |), + make_list [ + M.get_field (| M.get_name (| globals, "node" |), "value" |) + ] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.raise (| Some (M.call (| + M.get_name (| globals, "AssertionError" |), + make_list [ + Constant.str "(* At expr: unsupported node type: JoinedStr *)" + ], + make_dict [] + |)) |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "encoded" , + M.call (| + M.get_field (| M.get_name (| globals, "rlp" |), "encode" |), + make_list [ + M.get_name (| globals, "unencoded" |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.lt (| + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_name (| globals, "encoded" |) + ], + make_dict [] + |), + Constant.int 32 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + M.get_name (| globals, "unencoded" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.return_ (| + M.call (| + M.get_name (| globals, "keccak256" |), + make_list [ + M.get_name (| globals, "encoded" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_)). + +Definition encode_node : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "node"; "storage_root" ] |) in + let _ := Constant.str " + Encode a Node for storage in the Merkle Trie. + + Currently mostly an unimplemented stub. + " in + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, "isinstance" |), + make_list [ + M.get_name (| globals, "node" |); + M.get_name (| globals, "Account" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assert (| Compare.is_not (| + M.get_name (| globals, "storage_root" |), + Constant.None_ + |) |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, "encode_account" |), + make_list [ + M.get_name (| globals, "node" |); + M.get_name (| globals, "storage_root" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, "isinstance" |), + make_list [ + M.get_name (| globals, "node" |); + make_tuple [ M.get_name (| globals, "LegacyTransaction" |); M.get_name (| globals, "Receipt" |); M.get_name (| globals, "Withdrawal" |); M.get_name (| globals, "U256" |) ] + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + M.call (| + M.get_field (| M.get_name (| globals, "rlp" |), "encode" |), + make_list [ + M.call (| + M.get_name (| globals, "cast" |), + make_list [ + M.get_field (| M.get_name (| globals, "rlp" |), "RLP" |); + M.get_name (| globals, "node" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, "isinstance" |), + make_list [ + M.get_name (| globals, "node" |); + M.get_name (| globals, "Bytes" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + M.get_name (| globals, "node" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.return_ (| + M.call (| + M.get_field (| M.get_name (| globals, "previous_trie" |), "encode_node" |), + make_list [ + M.get_name (| globals, "node" |); + M.get_name (| globals, "storage_root" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_)). + +Definition Trie : Value.t := + builtins.make_klass + [(* At base: unsupported node type: Subscript *)] + [ + + ] + [ + + ]. + +Definition copy_trie : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "trie" ] |) in + let _ := Constant.str " + Create a copy of `trie`. Since only frozen objects may be stored in tries, + the contents are reused. + + Parameters + ---------- + trie: `Trie` + Trie to copy. + + Returns + ------- + new_trie : `Trie[K, V]` + A copy of the trie. + " in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, "Trie" |), + make_list [ + M.get_field (| M.get_name (| globals, "trie" |), "secured" |); + M.get_field (| M.get_name (| globals, "trie" |), "default" |); + M.call (| + M.get_field (| M.get_name (| globals, "copy" |), "copy" |), + make_list [ + M.get_field (| M.get_name (| globals, "trie" |), "_data" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Definition trie_set : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "trie"; "key"; "value" ] |) in + let _ := Constant.str " + Stores an item in a Merkle Trie. + + This method deletes the key if `value == trie.default`, because the Merkle + Trie represents the default value by omitting it from the trie. + + Parameters + ---------- + trie: `Trie` + Trie to store in. + key : `Bytes` + Key to lookup. + value : `V` + Node to insert at `key`. + " in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, "value" |), + M.get_field (| M.get_name (| globals, "trie" |), "default" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + Compare.in_ (| + M.get_name (| globals, "key" |), + M.get_field (| M.get_name (| globals, "trie" |), "_data" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.delete (| M.get_subscript (| + M.get_field (| M.get_name (| globals, "trie" |), "_data" |), + M.get_name (| globals, "key" |) + |) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign (| + M.get_subscript (| + M.get_field (| M.get_name (| globals, "trie" |), "_data" |), + M.get_name (| globals, "key" |) + |), + M.get_name (| globals, "value" |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_)). + +Definition trie_get : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "trie"; "key" ] |) in + let _ := Constant.str " + Gets an item from the Merkle Trie. + + This method returns `trie.default` if the key is missing. + + Parameters + ---------- + trie: + Trie to lookup in. + key : + Key to lookup. + + Returns + ------- + node : `V` + Node at `key` in the trie. + " in + let _ := M.return_ (| + M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, "trie" |), "_data" |), "get" |), + make_list [ + M.get_name (| globals, "key" |); + M.get_field (| M.get_name (| globals, "trie" |), "default" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Definition common_prefix_length : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "a"; "b" ] |) in + let _ := Constant.str " + Find the longest common prefix of two sequences. + " in + let _ := + M.for_ (| + M.get_name (| globals, "i" |), + M.call (| + M.get_name (| globals, "range" |), + make_list [ + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_name (| globals, "a" |) + ], + make_dict [] + |) + ], + make_dict [] + |), + ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + BoolOp.or (| + Compare.gt_e (| + M.get_name (| globals, "i" |), + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_name (| globals, "b" |) + ], + make_dict [] + |) + |), + ltac:(M.monadic ( + Compare.not_eq (| + M.get_subscript (| + M.get_name (| globals, "a" |), + M.get_name (| globals, "i" |) + |), + M.get_subscript (| + M.get_name (| globals, "b" |), + M.get_name (| globals, "i" |) + |) + |) + )) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + M.get_name (| globals, "i" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_name (| globals, "a" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Definition nibble_list_to_compact : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "x"; "is_leaf" ] |) in + let _ := Constant.str " + Compresses nibble-list into a standard byte array with a flag. + + A nibble-list is a list of byte values no greater than `15`. The flag is + encoded in high nibble of the highest byte. The flag nibble can be broken + down into two two-bit flags. + + Highest nibble:: + + +---+---+----------+--------+ + | _ | _ | is_leaf | parity | + +---+---+----------+--------+ + 3 2 1 0 + + + The lowest bit of the nibble encodes the parity of the length of the + remaining nibbles -- `0` when even and `1` when odd. The second lowest bit + is used to distinguish leaf and extension nodes. The other two bits are not + used. + + Parameters + ---------- + x : + Array of nibbles. + is_leaf : + True if this is part of a leaf node, or false if it is an extension + node. + + Returns + ------- + compressed : `bytearray` + Compact byte array. + " in + let _ := M.assign_local (| + "compact" , + M.call (| + M.get_name (| globals, "bytearray" |), + make_list [], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + BinOp.mod_ (| + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_name (| globals, "x" |) + ], + make_dict [] + |), + Constant.int 2 + |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_field (| M.get_name (| globals, "compact" |), "append" |), + make_list [ + BinOp.mult (| + Constant.int 16, + BinOp.mult (| + Constant.int 2, + M.get_name (| globals, "is_leaf" |) + |) + |) + ], + make_dict [] + |) in + let _ := + M.for_ (| + M.get_name (| globals, "i" |), + M.call (| + M.get_name (| globals, "range" |), + make_list [ + Constant.int 0; + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_name (| globals, "x" |) + ], + make_dict [] + |); + Constant.int 2 + ], + make_dict [] + |), + ltac:(M.monadic ( + let _ := M.call (| + M.get_field (| M.get_name (| globals, "compact" |), "append" |), + make_list [ + BinOp.add (| + BinOp.mult (| + Constant.int 16, + M.get_subscript (| + M.get_name (| globals, "x" |), + M.get_name (| globals, "i" |) + |) + |), + M.get_subscript (| + M.get_name (| globals, "x" |), + BinOp.add (| + M.get_name (| globals, "i" |), + Constant.int 1 + |) + |) + |) + ], + make_dict [] + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.call (| + M.get_field (| M.get_name (| globals, "compact" |), "append" |), + make_list [ + BinOp.add (| + BinOp.mult (| + Constant.int 16, + BinOp.add (| + BinOp.mult (| + Constant.int 2, + M.get_name (| globals, "is_leaf" |) + |), + Constant.int 1 + |) + |), + M.get_subscript (| + M.get_name (| globals, "x" |), + Constant.int 0 + |) + |) + ], + make_dict [] + |) in + let _ := + M.for_ (| + M.get_name (| globals, "i" |), + M.call (| + M.get_name (| globals, "range" |), + make_list [ + Constant.int 1; + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_name (| globals, "x" |) + ], + make_dict [] + |); + Constant.int 2 + ], + make_dict [] + |), + ltac:(M.monadic ( + let _ := M.call (| + M.get_field (| M.get_name (| globals, "compact" |), "append" |), + make_list [ + BinOp.add (| + BinOp.mult (| + Constant.int 16, + M.get_subscript (| + M.get_name (| globals, "x" |), + M.get_name (| globals, "i" |) + |) + |), + M.get_subscript (| + M.get_name (| globals, "x" |), + BinOp.add (| + M.get_name (| globals, "i" |), + Constant.int 1 + |) + |) + |) + ], + make_dict [] + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + M.pure Constant.None_ + )) |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, "Bytes" |), + make_list [ + M.get_name (| globals, "compact" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Definition bytes_to_nibble_list : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "bytes_" ] |) in + let _ := Constant.str " + Converts a `Bytes` into to a sequence of nibbles (bytes with value < 16). + + Parameters + ---------- + bytes_: + The `Bytes` to convert. + + Returns + ------- + nibble_list : `Bytes` + The `Bytes` in nibble-list format. + " in + let _ := M.assign_local (| + "nibble_list" , + M.call (| + M.get_name (| globals, "bytearray" |), + make_list [ + BinOp.mult (| + Constant.int 2, + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_name (| globals, "bytes_" |) + ], + make_dict [] + |) + |) + ], + make_dict [] + |) + |) in + let _ := + M.for_ (| + make_tuple [ M.get_name (| globals, "byte_index" |); M.get_name (| globals, "byte" |) ], + M.call (| + M.get_name (| globals, "enumerate" |), + make_list [ + M.get_name (| globals, "bytes_" |) + ], + make_dict [] + |), + ltac:(M.monadic ( + let _ := M.assign (| + M.get_subscript (| + M.get_name (| globals, "nibble_list" |), + BinOp.mult (| + M.get_name (| globals, "byte_index" |), + Constant.int 2 + |) + |), + BinOp.r_shift (| + BinOp.bit_and (| + M.get_name (| globals, "byte" |), + Constant.int 240 + |), + Constant.int 4 + |) + |) in + let _ := M.assign (| + M.get_subscript (| + M.get_name (| globals, "nibble_list" |), + BinOp.add (| + BinOp.mult (| + M.get_name (| globals, "byte_index" |), + Constant.int 2 + |), + Constant.int 1 + |) + |), + BinOp.bit_and (| + M.get_name (| globals, "byte" |), + Constant.int 15 + |) + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, "Bytes" |), + make_list [ + M.get_name (| globals, "nibble_list" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Definition _prepare_trie : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "trie"; "get_storage_root" ] |) in + let _ := Constant.str " + Prepares the trie for root calculation. Removes values that are empty, + hashes the keys (if `secured == True`) and encodes all the nodes. + + Parameters + ---------- + trie : + The `Trie` to prepare. + get_storage_root : + Function to get the storage root of an account. Needed to encode + `Account` objects. + + Returns + ------- + out : `Mapping[ethereum.base_types.Bytes, Node]` + Object with keys mapped to nibble-byte form. + " in +(* At stmt: unsupported node type: AnnAssign *) + let _ := + M.for_ (| + make_tuple [ M.get_name (| globals, "preimage" |); M.get_name (| globals, "value" |) ], + M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, "trie" |), "_data" |), "items" |), + make_list [], + make_dict [] + |), + ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, "isinstance" |), + make_list [ + M.get_name (| globals, "value" |); + M.get_name (| globals, "Account" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assert (| Compare.is_not (| + M.get_name (| globals, "get_storage_root" |), + Constant.None_ + |) |) in + let _ := M.assign_local (| + "address" , + M.call (| + M.get_name (| globals, "Address" |), + make_list [ + M.get_name (| globals, "preimage" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "encoded_value" , + M.call (| + M.get_name (| globals, "encode_node" |), + make_list [ + M.get_name (| globals, "value" |); + M.call (| + M.get_name (| globals, "get_storage_root" |), + make_list [ + M.get_name (| globals, "address" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "encoded_value" , + M.call (| + M.get_name (| globals, "encode_node" |), + make_list [ + M.get_name (| globals, "value" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + )) |) in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + Compare.not_eq (| + M.get_name (| globals, "encoded_value" |), + Constant.bytes "" + |); + M.get_name (| globals, "AssertionError" |) + ], + make_dict [] + |) in +(* At stmt: unsupported node type: AnnAssign *) + let _ := + (* if *) + M.if_then_else (| + M.get_field (| M.get_name (| globals, "trie" |), "secured" |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "key" , + M.call (| + M.get_name (| globals, "keccak256" |), + make_list [ + M.get_name (| globals, "preimage" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "key" , + M.get_name (| globals, "preimage" |) + |) in + M.pure Constant.None_ + )) |) in + let _ := M.assign (| + M.get_subscript (| + M.get_name (| globals, "mapped" |), + M.call (| + M.get_name (| globals, "bytes_to_nibble_list" |), + make_list [ + M.get_name (| globals, "key" |) + ], + make_dict [] + |) + |), + M.get_name (| globals, "encoded_value" |) + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := M.return_ (| + M.get_name (| globals, "mapped" |) + |) in + M.pure Constant.None_)). + +Definition root : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "trie"; "get_storage_root" ] |) in + let _ := Constant.str " + Computes the root of a modified merkle patricia trie (MPT). + + Parameters + ---------- + trie : + `Trie` to get the root of. + get_storage_root : + Function to get the storage root of an account. Needed to encode + `Account` objects. + + + Returns + ------- + root : `.fork_types.Root` + MPT root of the underlying key-value pairs. + " in + let _ := M.assign_local (| + "obj" , + M.call (| + M.get_name (| globals, "_prepare_trie" |), + make_list [ + M.get_name (| globals, "trie" |); + M.get_name (| globals, "get_storage_root" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "root_node" , + M.call (| + M.get_name (| globals, "encode_internal_node" |), + make_list [ + M.call (| + M.get_name (| globals, "patricialize" |), + make_list [ + M.get_name (| globals, "obj" |); + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.lt (| + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.call (| + M.get_field (| M.get_name (| globals, "rlp" |), "encode" |), + make_list [ + M.get_name (| globals, "root_node" |) + ], + make_dict [] + |) + ], + make_dict [] + |), + Constant.int 32 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + M.call (| + M.get_name (| globals, "keccak256" |), + make_list [ + M.call (| + M.get_field (| M.get_name (| globals, "rlp" |), "encode" |), + make_list [ + M.get_name (| globals, "root_node" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assert (| M.call (| + M.get_name (| globals, "isinstance" |), + make_list [ + M.get_name (| globals, "root_node" |); + M.get_name (| globals, "Bytes" |) + ], + make_dict [] + |) |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, "Root" |), + make_list [ + M.get_name (| globals, "root_node" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_)). + +Definition patricialize : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "obj"; "level" ] |) in + let _ := Constant.str " + Structural composition function. + + Used to recursively patricialize and merkleize a dictionary. Includes + memoization of the tree structure and hashes. + + Parameters + ---------- + obj : + Underlying trie key-value pairs, with keys in nibble-list format. + level : + Current trie level. + + Returns + ------- + node : `ethereum.base_types.Bytes` + Root node of `obj`. + " in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_name (| globals, "obj" |) + ], + make_dict [] + |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + Constant.None_ + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "arbitrary_key" , + M.call (| + M.get_name (| globals, "next" |), + make_list [ + M.call (| + M.get_name (| globals, "iter" |), + make_list [ + M.get_name (| globals, "obj" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_name (| globals, "obj" |) + ], + make_dict [] + |), + Constant.int 1 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "leaf" , + M.call (| + M.get_name (| globals, "LeafNode" |), + make_list [ + M.slice (| + M.get_name (| globals, "arbitrary_key" |), + M.get_name (| globals, "level" |), + Constant.None_, + Constant.None_ + |); + M.get_subscript (| + M.get_name (| globals, "obj" |), + M.get_name (| globals, "arbitrary_key" |) + |) + ], + make_dict [] + |) + |) in + let _ := M.return_ (| + M.get_name (| globals, "leaf" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "substring" , + M.slice (| + M.get_name (| globals, "arbitrary_key" |), + M.get_name (| globals, "level" |), + Constant.None_, + Constant.None_ + |) + |) in + let _ := M.assign_local (| + "prefix_length" , + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_name (| globals, "substring" |) + ], + make_dict [] + |) + |) in + let _ := + M.for_ (| + M.get_name (| globals, "key" |), + M.get_name (| globals, "obj" |), + ltac:(M.monadic ( + let _ := M.assign_local (| + "prefix_length" , + M.call (| + M.get_name (| globals, "min" |), + make_list [ + M.get_name (| globals, "prefix_length" |); + M.call (| + M.get_name (| globals, "common_prefix_length" |), + make_list [ + M.get_name (| globals, "substring" |); + M.slice (| + M.get_name (| globals, "key" |), + M.get_name (| globals, "level" |), + Constant.None_, + Constant.None_ + |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, "prefix_length" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.break (| |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.gt (| + M.get_name (| globals, "prefix_length" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "prefix" , + M.slice (| + M.get_name (| globals, "arbitrary_key" |), + M.get_name (| globals, "level" |), + BinOp.add (| + M.get_name (| globals, "level" |), + M.get_name (| globals, "prefix_length" |) + |), + Constant.None_ + |) + |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, "ExtensionNode" |), + make_list [ + M.get_name (| globals, "prefix" |); + M.call (| + M.get_name (| globals, "encode_internal_node" |), + make_list [ + M.call (| + M.get_name (| globals, "patricialize" |), + make_list [ + M.get_name (| globals, "obj" |); + BinOp.add (| + M.get_name (| globals, "level" |), + M.get_name (| globals, "prefix_length" |) + |) + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in +(* At stmt: unsupported node type: AnnAssign *) + let _ := + M.for_ (| + M.get_name (| globals, "_" |), + M.call (| + M.get_name (| globals, "range" |), + make_list [ + Constant.int 16 + ], + make_dict [] + |), + ltac:(M.monadic ( + let _ := M.call (| + M.get_field (| M.get_name (| globals, "branches" |), "append" |), + make_list [ + Constant.str "(* At expr: unsupported node type: Dict *)" + ], + make_dict [] + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := M.assign_local (| + "value" , + Constant.bytes "" + |) in + let _ := + M.for_ (| + M.get_name (| globals, "key" |), + M.get_name (| globals, "obj" |), + ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_name (| globals, "key" |) + ], + make_dict [] + |), + M.get_name (| globals, "level" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, "isinstance" |), + make_list [ + M.get_subscript (| + M.get_name (| globals, "obj" |), + M.get_name (| globals, "key" |) + |); + make_tuple [ M.get_name (| globals, "Account" |); M.get_name (| globals, "Receipt" |); M.get_name (| globals, "Uint" |) ] + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, "AssertionError" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "value" , + M.get_subscript (| + M.get_name (| globals, "obj" |), + M.get_name (| globals, "key" |) + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign (| + M.get_subscript (| + M.get_subscript (| + M.get_name (| globals, "branches" |), + M.get_subscript (| + M.get_name (| globals, "key" |), + M.get_name (| globals, "level" |) + |) + |), + M.get_name (| globals, "key" |) + |), + M.get_subscript (| + M.get_name (| globals, "obj" |), + M.get_name (| globals, "key" |) + |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, "BranchNode" |), + make_list [ + Constant.str "(* At expr: unsupported node type: ListComp *)"; + M.get_name (| globals, "value" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). diff --git a/CoqOfPython/ethereum/shanghai/utils/__init__.v b/CoqOfPython/ethereum/shanghai/utils/__init__.v new file mode 100644 index 0000000..5a9b965 --- /dev/null +++ b/CoqOfPython/ethereum/shanghai/utils/__init__.v @@ -0,0 +1,8 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.shanghai.utils.__init__". + +Definition expr_1 : Value.t := + Constant.str " +Utility functions unique to this particular fork. +". diff --git a/CoqOfPython/ethereum/shanghai/utils/address.v b/CoqOfPython/ethereum/shanghai/utils/address.v new file mode 100644 index 0000000..309f4c7 --- /dev/null +++ b/CoqOfPython/ethereum/shanghai/utils/address.v @@ -0,0 +1,227 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.shanghai.utils.address". + +Definition expr_1 : Value.t := + Constant.str " +Hardfork Utility Functions For Addresses +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Address specific functions used in this shanghai version of +specification. +". + +Axiom typing_imports_Union : + IsImported globals "typing" "Union". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_Bytes32 : + IsImported globals "ethereum.base_types" "Bytes32". +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". + +Axiom ethereum_crypto_hash_imports_keccak256 : + IsImported globals "ethereum.crypto.hash" "keccak256". + +Axiom ethereum_utils_byte_imports_left_pad_zero_bytes : + IsImported globals "ethereum.utils.byte" "left_pad_zero_bytes". + +Axiom ethereum_imports_rlp : + IsImported globals "ethereum" "rlp". + +Axiom ethereum_shanghai_fork_types_imports_Address : + IsImported globals "ethereum.shanghai.fork_types" "Address". + +Definition to_address : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "data" ] |) in + let _ := Constant.str " + Convert a Uint or U256 value to a valid address (20 bytes). + + Parameters + ---------- + data : + The string to be converted to bytes. + + Returns + ------- + address : `Address` + The obtained address. + " in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, "Address" |), + make_list [ + M.slice (| + M.call (| + M.get_field (| M.get_name (| globals, "data" |), "to_be_bytes32" |), + make_list [], + make_dict [] + |), + UnOp.sub (| Constant.int 20 |), + Constant.None_, + Constant.None_ + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Definition compute_contract_address : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "address"; "nonce" ] |) in + let _ := Constant.str " + Computes address of the new account that needs to be created. + + Parameters + ---------- + address : + The address of the account that wants to create the new account. + nonce : + The transaction count of the account that wants to create the new + account. + + Returns + ------- + address: `Address` + The computed address of the new account. + " in + let _ := M.assign_local (| + "computed_address" , + M.call (| + M.get_name (| globals, "keccak256" |), + make_list [ + M.call (| + M.get_field (| M.get_name (| globals, "rlp" |), "encode" |), + make_list [ + make_list [ + M.get_name (| globals, "address" |); + M.get_name (| globals, "nonce" |) + ] + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "canonical_address" , + M.slice (| + M.get_name (| globals, "computed_address" |), + UnOp.sub (| Constant.int 20 |), + Constant.None_, + Constant.None_ + |) + |) in + let _ := M.assign_local (| + "padded_address" , + M.call (| + M.get_name (| globals, "left_pad_zero_bytes" |), + make_list [ + M.get_name (| globals, "canonical_address" |); + Constant.int 20 + ], + make_dict [] + |) + |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, "Address" |), + make_list [ + M.get_name (| globals, "padded_address" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Definition compute_create2_contract_address : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "address"; "salt"; "call_data" ] |) in + let _ := Constant.str " + Computes address of the new account that needs to be created, which is + based on the sender address, salt and the call data as well. + + Parameters + ---------- + address : + The address of the account that wants to create the new account. + salt : + Address generation salt. + call_data : + The code of the new account which is to be created. + + Returns + ------- + address: `ethereum.shanghai.fork_types.Address` + The computed address of the new account. + " in + let _ := M.assign_local (| + "preimage" , + BinOp.add (| + BinOp.add (| + BinOp.add (| + Constant.bytes "ff", + M.get_name (| globals, "address" |) + |), + M.get_name (| globals, "salt" |) + |), + M.call (| + M.get_name (| globals, "keccak256" |), + make_list [ + M.get_name (| globals, "call_data" |) + ], + make_dict [] + |) + |) + |) in + let _ := M.assign_local (| + "computed_address" , + M.call (| + M.get_name (| globals, "keccak256" |), + make_list [ + M.get_name (| globals, "preimage" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "canonical_address" , + M.slice (| + M.get_name (| globals, "computed_address" |), + UnOp.sub (| Constant.int 20 |), + Constant.None_, + Constant.None_ + |) + |) in + let _ := M.assign_local (| + "padded_address" , + M.call (| + M.get_name (| globals, "left_pad_zero_bytes" |), + make_list [ + M.get_name (| globals, "canonical_address" |); + Constant.int 20 + ], + make_dict [] + |) + |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, "Address" |), + make_list [ + M.get_name (| globals, "padded_address" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). diff --git a/CoqOfPython/ethereum/shanghai/utils/hexadecimal.v b/CoqOfPython/ethereum/shanghai/utils/hexadecimal.v new file mode 100644 index 0000000..d044fd0 --- /dev/null +++ b/CoqOfPython/ethereum/shanghai/utils/hexadecimal.v @@ -0,0 +1,153 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.shanghai.utils.hexadecimal". + +Definition expr_1 : Value.t := + Constant.str " +Utility Functions For Hexadecimal Strings +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Hexadecimal utility functions used in this specification, specific to +Shanghai types. +". + +Axiom ethereum_utils_hexadecimal_imports_remove_hex_prefix : + IsImported globals "ethereum.utils.hexadecimal" "remove_hex_prefix". + +Axiom ethereum_shanghai_fork_types_imports_Address : + IsImported globals "ethereum.shanghai.fork_types" "Address". +Axiom ethereum_shanghai_fork_types_imports_Bloom : + IsImported globals "ethereum.shanghai.fork_types" "Bloom". +Axiom ethereum_shanghai_fork_types_imports_Root : + IsImported globals "ethereum.shanghai.fork_types" "Root". + +Definition hex_to_root : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "hex_string" ] |) in + let _ := Constant.str " + Convert hex string to trie root. + + Parameters + ---------- + hex_string : + The hexadecimal string to be converted to trie root. + + Returns + ------- + root : `Root` + Trie root obtained from the given hexadecimal string. + " in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, "Root" |), + make_list [ + M.call (| + M.get_field (| M.get_name (| globals, "bytes" |), "fromhex" |), + make_list [ + M.call (| + M.get_name (| globals, "remove_hex_prefix" |), + make_list [ + M.get_name (| globals, "hex_string" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Definition hex_to_bloom : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "hex_string" ] |) in + let _ := Constant.str " + Convert hex string to bloom. + + Parameters + ---------- + hex_string : + The hexadecimal string to be converted to bloom. + + Returns + ------- + bloom : `Bloom` + Bloom obtained from the given hexadecimal string. + " in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, "Bloom" |), + make_list [ + M.call (| + M.get_field (| M.get_name (| globals, "bytes" |), "fromhex" |), + make_list [ + M.call (| + M.get_name (| globals, "remove_hex_prefix" |), + make_list [ + M.get_name (| globals, "hex_string" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Definition hex_to_address : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "hex_string" ] |) in + let _ := Constant.str " + Convert hex string to Address (20 bytes). + + Parameters + ---------- + hex_string : + The hexadecimal string to be converted to Address. + + Returns + ------- + address : `Address` + The address obtained from the given hexadecimal string. + " in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, "Address" |), + make_list [ + M.call (| + M.get_field (| M.get_name (| globals, "bytes" |), "fromhex" |), + make_list [ + M.call (| + M.get_field (| M.call (| + M.get_name (| globals, "remove_hex_prefix" |), + make_list [ + M.get_name (| globals, "hex_string" |) + ], + make_dict [] + |), "rjust" |), + make_list [ + Constant.int 40; + Constant.str "0" + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). diff --git a/CoqOfPython/ethereum/shanghai/utils/message.v b/CoqOfPython/ethereum/shanghai/utils/message.v new file mode 100644 index 0000000..d1e2dbc --- /dev/null +++ b/CoqOfPython/ethereum/shanghai/utils/message.v @@ -0,0 +1,266 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.shanghai.utils.message". + +Definition expr_1 : Value.t := + Constant.str " +Hardfork Utility Functions For The Message Data-structure +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Message specific functions used in this shanghai version of +specification. +". + +Axiom typing_imports_FrozenSet : + IsImported globals "typing" "FrozenSet". +Axiom typing_imports_Optional : + IsImported globals "typing" "Optional". +Axiom typing_imports_Tuple : + IsImported globals "typing" "Tuple". +Axiom typing_imports_Union : + IsImported globals "typing" "Union". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_Bytes : + IsImported globals "ethereum.base_types" "Bytes". +Axiom ethereum_base_types_imports_Bytes0 : + IsImported globals "ethereum.base_types" "Bytes0". +Axiom ethereum_base_types_imports_Bytes32 : + IsImported globals "ethereum.base_types" "Bytes32". +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". + +Axiom ethereum_shanghai_fork_types_imports_Address : + IsImported globals "ethereum.shanghai.fork_types" "Address". + +Axiom ethereum_shanghai_state_imports_get_account : + IsImported globals "ethereum.shanghai.state" "get_account". + +Axiom ethereum_shanghai_vm_imports_Environment : + IsImported globals "ethereum.shanghai.vm" "Environment". +Axiom ethereum_shanghai_vm_imports_Message : + IsImported globals "ethereum.shanghai.vm" "Message". + +Axiom ethereum_shanghai_vm_precompiled_contracts_mapping_imports_PRE_COMPILED_CONTRACTS : + IsImported globals "ethereum.shanghai.vm.precompiled_contracts.mapping" "PRE_COMPILED_CONTRACTS". + +Axiom ethereum_shanghai_utils_address_imports_compute_contract_address : + IsImported globals "ethereum.shanghai.utils.address" "compute_contract_address". + +Definition prepare_message : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "caller"; "target"; "value"; "data"; "gas"; "env"; "code_address"; "should_transfer_value"; "is_static"; "preaccessed_addresses"; "preaccessed_storage_keys" ] |) in + let _ := Constant.str " + Execute a transaction against the provided environment. + + Parameters + ---------- + caller : + Address which initiated the transaction + target : + Address whose code will be executed + value : + Value to be transferred. + data : + Array of bytes provided to the code in `target`. + gas : + Gas provided for the code in `target`. + env : + Environment for the Ethereum Virtual Machine. + code_address : + This is usually same as the `target` address except when an alternative + accounts code needs to be executed. + eg. `CALLCODE` calling a precompile. + should_transfer_value : + if True ETH should be transferred while executing a message call. + is_static: + if True then it prevents all state-changing operations from being + executed. + preaccessed_addresses: + Addresses that should be marked as accessed prior to the message call + preaccessed_storage_keys: + Storage keys that should be marked as accessed prior to the message + call + + Returns + ------- + message: `ethereum.shanghai.vm.Message` + Items containing contract creation or message call specific data. + " in + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, "isinstance" |), + make_list [ + M.get_name (| globals, "target" |); + M.get_name (| globals, "Bytes0" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "current_target" , + M.call (| + M.get_name (| globals, "compute_contract_address" |), + make_list [ + M.get_name (| globals, "caller" |); + BinOp.sub (| + M.get_field (| M.call (| + M.get_name (| globals, "get_account" |), + make_list [ + M.get_field (| M.get_name (| globals, "env" |), "state" |); + M.get_name (| globals, "caller" |) + ], + make_dict [] + |), "nonce" |), + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 1 + ], + make_dict [] + |) + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "msg_data" , + M.call (| + M.get_name (| globals, "Bytes" |), + make_list [ + Constant.bytes "" + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "code" , + M.get_name (| globals, "data" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, "isinstance" |), + make_list [ + M.get_name (| globals, "target" |); + M.get_name (| globals, "Address" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "current_target" , + M.get_name (| globals, "target" |) + |) in + let _ := M.assign_local (| + "msg_data" , + M.get_name (| globals, "data" |) + |) in + let _ := M.assign_local (| + "code" , + M.get_field (| M.call (| + M.get_name (| globals, "get_account" |), + make_list [ + M.get_field (| M.get_name (| globals, "env" |), "state" |); + M.get_name (| globals, "target" |) + ], + make_dict [] + |), "code" |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.is (| + M.get_name (| globals, "code_address" |), + Constant.None_ + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "code_address" , + M.get_name (| globals, "target" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.raise (| Some (M.call (| + M.get_name (| globals, "AssertionError" |), + make_list [ + Constant.str "Target must be address or empty bytes" + ], + make_dict [] + |)) |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "accessed_addresses" , + M.call (| + M.get_name (| globals, "set" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_field (| M.get_name (| globals, "accessed_addresses" |), "add" |), + make_list [ + M.get_name (| globals, "current_target" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_field (| M.get_name (| globals, "accessed_addresses" |), "add" |), + make_list [ + M.get_name (| globals, "caller" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_field (| M.get_name (| globals, "accessed_addresses" |), "update" |), + make_list [ + M.call (| + M.get_field (| M.get_name (| globals, "PRE_COMPILED_CONTRACTS" |), "keys" |), + make_list [], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_field (| M.get_name (| globals, "accessed_addresses" |), "update" |), + make_list [ + M.get_name (| globals, "preaccessed_addresses" |) + ], + make_dict [] + |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, "Message" |), + make_list [], + make_dict [] + |) + |) in + M.pure Constant.None_)). diff --git a/CoqOfPython/ethereum/shanghai/vm/__init__.v b/CoqOfPython/ethereum/shanghai/vm/__init__.v new file mode 100644 index 0000000..1cfebb9 --- /dev/null +++ b/CoqOfPython/ethereum/shanghai/vm/__init__.v @@ -0,0 +1,260 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.shanghai.vm.__init__". + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +The abstract computer which runs the code stored in an +`.fork_types.Account`. +". + +Axiom dataclasses_imports_dataclass : + IsImported globals "dataclasses" "dataclass". + +Axiom typing_imports_List : + IsImported globals "typing" "List". +Axiom typing_imports_Optional : + IsImported globals "typing" "Optional". +Axiom typing_imports_Set : + IsImported globals "typing" "Set". +Axiom typing_imports_Tuple : + IsImported globals "typing" "Tuple". +Axiom typing_imports_Union : + IsImported globals "typing" "Union". + +Axiom ethereum_base_types_imports_U64 : + IsImported globals "ethereum.base_types" "U64". +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_Bytes : + IsImported globals "ethereum.base_types" "Bytes". +Axiom ethereum_base_types_imports_Bytes0 : + IsImported globals "ethereum.base_types" "Bytes0". +Axiom ethereum_base_types_imports_Bytes32 : + IsImported globals "ethereum.base_types" "Bytes32". +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". + +Axiom ethereum_crypto_hash_imports_Hash32 : + IsImported globals "ethereum.crypto.hash" "Hash32". + +Axiom ethereum_shanghai_blocks_imports_Log : + IsImported globals "ethereum.shanghai.blocks" "Log". + +Axiom ethereum_shanghai_fork_types_imports_Address : + IsImported globals "ethereum.shanghai.fork_types" "Address". + +Axiom ethereum_shanghai_state_imports_State : + IsImported globals "ethereum.shanghai.state" "State". +Axiom ethereum_shanghai_state_imports_account_exists_and_is_empty : + IsImported globals "ethereum.shanghai.state" "account_exists_and_is_empty". + +Axiom ethereum_shanghai_vm_precompiled_contracts_imports_RIPEMD160_ADDRESS : + IsImported globals "ethereum.shanghai.vm.precompiled_contracts" "RIPEMD160_ADDRESS". + +Definition __all__ : Value.t := M.run ltac:(M.monadic ( + make_tuple [ Constant.str "Environment"; Constant.str "Evm"; Constant.str "Message" ] +)). + +Definition Environment : Value.t := + builtins.make_klass + [] + [ + + ] + [ + + ]. + +Definition Message : Value.t := + builtins.make_klass + [] + [ + + ] + [ + + ]. + +Definition Evm : Value.t := + builtins.make_klass + [] + [ + + ] + [ + + ]. + +Definition incorporate_child_on_success : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm"; "child_evm" ] |) in + let _ := Constant.str " + Incorporate the state of a successful `child_evm` into the parent `evm`. + + Parameters + ---------- + evm : + The parent `EVM`. + child_evm : + The child evm to incorporate. + " in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "gas_left" |), + M.get_field (| M.get_name (| globals, "child_evm" |), "gas_left" |) + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "logs" |), + M.get_field (| M.get_name (| globals, "child_evm" |), "logs" |) + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "refund_counter" |), + M.get_field (| M.get_name (| globals, "child_evm" |), "refund_counter" |) + |) in + let _ := M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "accounts_to_delete" |), "update" |), + make_list [ + M.get_field (| M.get_name (| globals, "child_evm" |), "accounts_to_delete" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "touched_accounts" |), "update" |), + make_list [ + M.get_field (| M.get_name (| globals, "child_evm" |), "touched_accounts" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, "account_exists_and_is_empty" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "env" |), "state" |); + M.get_field (| M.get_field (| M.get_name (| globals, "child_evm" |), "message" |), "current_target" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "touched_accounts" |), "add" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "child_evm" |), "message" |), "current_target" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "accessed_addresses" |), "update" |), + make_list [ + M.get_field (| M.get_name (| globals, "child_evm" |), "accessed_addresses" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "accessed_storage_keys" |), "update" |), + make_list [ + M.get_field (| M.get_name (| globals, "child_evm" |), "accessed_storage_keys" |) + ], + make_dict [] + |) in + M.pure Constant.None_)). + +Definition incorporate_child_on_error : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm"; "child_evm" ] |) in + let _ := Constant.str " + Incorporate the state of an unsuccessful `child_evm` into the parent `evm`. + + Parameters + ---------- + evm : + The parent `EVM`. + child_evm : + The child evm to incorporate. + " in + let _ := + (* if *) + M.if_then_else (| + Compare.in_ (| + M.get_name (| globals, "RIPEMD160_ADDRESS" |), + M.get_field (| M.get_name (| globals, "child_evm" |), "touched_accounts" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "touched_accounts" |), "add" |), + make_list [ + M.get_name (| globals, "RIPEMD160_ADDRESS" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_field (| M.get_field (| M.get_name (| globals, "child_evm" |), "message" |), "current_target" |), + M.get_name (| globals, "RIPEMD160_ADDRESS" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, "account_exists_and_is_empty" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "env" |), "state" |); + M.get_field (| M.get_field (| M.get_name (| globals, "child_evm" |), "message" |), "current_target" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "touched_accounts" |), "add" |), + make_list [ + M.get_name (| globals, "RIPEMD160_ADDRESS" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "gas_left" |), + M.get_field (| M.get_name (| globals, "child_evm" |), "gas_left" |) + |) in + M.pure Constant.None_)). diff --git a/CoqOfPython/ethereum/shanghai/vm/exceptions.v b/CoqOfPython/ethereum/shanghai/vm/exceptions.v new file mode 100644 index 0000000..b659bce --- /dev/null +++ b/CoqOfPython/ethereum/shanghai/vm/exceptions.v @@ -0,0 +1,171 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.shanghai.vm.exceptions". + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) Exceptions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Exceptions which cause the EVM to halt exceptionally. +". + +Axiom ethereum_exceptions_imports_EthereumException : + IsImported globals "ethereum.exceptions" "EthereumException". + +Definition ExceptionalHalt : Value.t := + builtins.make_klass + [(globals, "EthereumException")] + [ + + ] + [ + + ]. + +Definition Revert : Value.t := + builtins.make_klass + [(globals, "EthereumException")] + [ + + ] + [ + + ]. + +Definition StackUnderflowError : Value.t := + builtins.make_klass + [(globals, "ExceptionalHalt")] + [ + + ] + [ + + ]. + +Definition StackOverflowError : Value.t := + builtins.make_klass + [(globals, "ExceptionalHalt")] + [ + + ] + [ + + ]. + +Definition OutOfGasError : Value.t := + builtins.make_klass + [(globals, "ExceptionalHalt")] + [ + + ] + [ + + ]. + +Definition InvalidOpcode : Value.t := + builtins.make_klass + [(globals, "ExceptionalHalt")] + [ + + ] + [ + ( + "__init__", + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "self"; "code" ] |) in + let _ := M.call (| + M.get_field (| M.call (| + M.get_name (| globals, "super" |), + make_list [], + make_dict [] + |), "__init__" |), + make_list [ + M.get_name (| globals, "code" |) + ], + make_dict [] + |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, "self" |), "code" |), + M.get_name (| globals, "code" |) + |) in + M.pure Constant.None_)) + ) + ]. + +Definition InvalidJumpDestError : Value.t := + builtins.make_klass + [(globals, "ExceptionalHalt")] + [ + + ] + [ + + ]. + +Definition StackDepthLimitError : Value.t := + builtins.make_klass + [(globals, "ExceptionalHalt")] + [ + + ] + [ + + ]. + +Definition WriteInStaticContext : Value.t := + builtins.make_klass + [(globals, "ExceptionalHalt")] + [ + + ] + [ + + ]. + +Definition OutOfBoundsRead : Value.t := + builtins.make_klass + [(globals, "ExceptionalHalt")] + [ + + ] + [ + + ]. + +Definition InvalidParameter : Value.t := + builtins.make_klass + [(globals, "ExceptionalHalt")] + [ + + ] + [ + + ]. + +Definition InvalidContractPrefix : Value.t := + builtins.make_klass + [(globals, "ExceptionalHalt")] + [ + + ] + [ + + ]. + +Definition AddressCollision : Value.t := + builtins.make_klass + [(globals, "ExceptionalHalt")] + [ + + ] + [ + + ]. diff --git a/CoqOfPython/ethereum/shanghai/vm/gas.v b/CoqOfPython/ethereum/shanghai/vm/gas.v new file mode 100644 index 0000000..3604b0f --- /dev/null +++ b/CoqOfPython/ethereum/shanghai/vm/gas.v @@ -0,0 +1,951 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.shanghai.vm.gas". + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) Gas +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +EVM gas constants and calculators. +". + +Axiom dataclasses_imports_dataclass : + IsImported globals "dataclasses" "dataclass". + +Axiom typing_imports_List : + IsImported globals "typing" "List". +Axiom typing_imports_Tuple : + IsImported globals "typing" "Tuple". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". + +Axiom ethereum_trace_imports_GasAndRefund : + IsImported globals "ethereum.trace" "GasAndRefund". +Axiom ethereum_trace_imports_evm_trace : + IsImported globals "ethereum.trace" "evm_trace". + +Axiom ethereum_utils_numeric_imports_ceil32 : + IsImported globals "ethereum.utils.numeric" "ceil32". + +Axiom ethereum_shanghai_vm_imports_Evm : + IsImported globals "ethereum.shanghai.vm" "Evm". + +Axiom ethereum_shanghai_vm_exceptions_imports_OutOfGasError : + IsImported globals "ethereum.shanghai.vm.exceptions" "OutOfGasError". + +Definition GAS_JUMPDEST : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 1 + ], + make_dict [] + |) +)). + +Definition GAS_BASE : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 2 + ], + make_dict [] + |) +)). + +Definition GAS_VERY_LOW : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 3 + ], + make_dict [] + |) +)). + +Definition GAS_STORAGE_SET : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 20000 + ], + make_dict [] + |) +)). + +Definition GAS_STORAGE_UPDATE : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 5000 + ], + make_dict [] + |) +)). + +Definition GAS_STORAGE_CLEAR_REFUND : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 4800 + ], + make_dict [] + |) +)). + +Definition GAS_LOW : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 5 + ], + make_dict [] + |) +)). + +Definition GAS_MID : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 8 + ], + make_dict [] + |) +)). + +Definition GAS_HIGH : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 10 + ], + make_dict [] + |) +)). + +Definition GAS_EXPONENTIATION : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 10 + ], + make_dict [] + |) +)). + +Definition GAS_EXPONENTIATION_PER_BYTE : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 50 + ], + make_dict [] + |) +)). + +Definition GAS_MEMORY : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 3 + ], + make_dict [] + |) +)). + +Definition GAS_KECCAK256 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 30 + ], + make_dict [] + |) +)). + +Definition GAS_KECCAK256_WORD : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 6 + ], + make_dict [] + |) +)). + +Definition GAS_COPY : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 3 + ], + make_dict [] + |) +)). + +Definition GAS_BLOCK_HASH : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 20 + ], + make_dict [] + |) +)). + +Definition GAS_LOG : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 375 + ], + make_dict [] + |) +)). + +Definition GAS_LOG_DATA : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 8 + ], + make_dict [] + |) +)). + +Definition GAS_LOG_TOPIC : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 375 + ], + make_dict [] + |) +)). + +Definition GAS_CREATE : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 32000 + ], + make_dict [] + |) +)). + +Definition GAS_CODE_DEPOSIT : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 200 + ], + make_dict [] + |) +)). + +Definition GAS_ZERO : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) +)). + +Definition GAS_NEW_ACCOUNT : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 25000 + ], + make_dict [] + |) +)). + +Definition GAS_CALL_VALUE : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 9000 + ], + make_dict [] + |) +)). + +Definition GAS_CALL_STIPEND : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 2300 + ], + make_dict [] + |) +)). + +Definition GAS_SELF_DESTRUCT : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 5000 + ], + make_dict [] + |) +)). + +Definition GAS_SELF_DESTRUCT_NEW_ACCOUNT : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 25000 + ], + make_dict [] + |) +)). + +Definition GAS_ECRECOVER : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 3000 + ], + make_dict [] + |) +)). + +Definition GAS_SHA256 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 60 + ], + make_dict [] + |) +)). + +Definition GAS_SHA256_WORD : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 12 + ], + make_dict [] + |) +)). + +Definition GAS_RIPEMD160 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 600 + ], + make_dict [] + |) +)). + +Definition GAS_RIPEMD160_WORD : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 120 + ], + make_dict [] + |) +)). + +Definition GAS_IDENTITY : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 15 + ], + make_dict [] + |) +)). + +Definition GAS_IDENTITY_WORD : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 3 + ], + make_dict [] + |) +)). + +Definition GAS_RETURN_DATA_COPY : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 3 + ], + make_dict [] + |) +)). + +Definition GAS_FAST_STEP : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 5 + ], + make_dict [] + |) +)). + +Definition GAS_BLAKE2_PER_ROUND : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 1 + ], + make_dict [] + |) +)). + +Definition GAS_COLD_SLOAD : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 2100 + ], + make_dict [] + |) +)). + +Definition GAS_COLD_ACCOUNT_ACCESS : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 2600 + ], + make_dict [] + |) +)). + +Definition GAS_WARM_ACCESS : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 100 + ], + make_dict [] + |) +)). + +Definition GAS_INIT_CODE_WORD_COST : Value.t := M.run ltac:(M.monadic ( + Constant.int 2 +)). + +Definition ExtendMemory : Value.t := + builtins.make_klass + [] + [ + + ] + [ + + ]. + +Definition MessageCallGas : Value.t := + builtins.make_klass + [] + [ + + ] + [ + + ]. + +Definition charge_gas : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm"; "amount" ] |) in + let _ := Constant.str " + Subtracts `amount` from `evm.gas_left`. + + Parameters + ---------- + evm : + The current EVM. + amount : + The amount of gas the current operation requires. + + " in + let _ := M.call (| + M.get_name (| globals, "evm_trace" |), + make_list [ + M.get_name (| globals, "evm" |); + M.call (| + M.get_name (| globals, "GasAndRefund" |), + make_list [ + M.get_name (| globals, "amount" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.lt (| + M.get_field (| M.get_name (| globals, "evm" |), "gas_left" |), + M.get_name (| globals, "amount" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, "OutOfGasError" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_op (| + BinOp.sub, + M.get_field (| M.get_name (| globals, "evm" |), "gas_left" |), + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + M.get_name (| globals, "amount" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_)). + +Definition calculate_memory_gas_cost : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "size_in_bytes" ] |) in + let _ := Constant.str " + Calculates the gas cost for allocating memory + to the smallest multiple of 32 bytes, + such that the allocated size is at least as big as the given size. + + Parameters + ---------- + size_in_bytes : + The size of the data in bytes. + + Returns + ------- + total_gas_cost : `ethereum.base_types.Uint` + The gas cost for storing data in memory. + " in + let _ := M.assign_local (| + "size_in_words" , + BinOp.floor_div (| + M.call (| + M.get_name (| globals, "ceil32" |), + make_list [ + M.get_name (| globals, "size_in_bytes" |) + ], + make_dict [] + |), + Constant.int 32 + |) + |) in + let _ := M.assign_local (| + "linear_cost" , + BinOp.mult (| + M.get_name (| globals, "size_in_words" |), + M.get_name (| globals, "GAS_MEMORY" |) + |) + |) in + let _ := M.assign_local (| + "quadratic_cost" , + BinOp.floor_div (| + BinOp.pow (| + M.get_name (| globals, "size_in_words" |), + Constant.int 2 + |), + Constant.int 512 + |) + |) in + let _ := M.assign_local (| + "total_gas_cost" , + BinOp.add (| + M.get_name (| globals, "linear_cost" |), + M.get_name (| globals, "quadratic_cost" |) + |) + |) in +(* At stmt: unsupported node type: Try *) + M.pure Constant.None_)). + +Definition calculate_gas_extend_memory : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "memory"; "extensions" ] |) in + let _ := Constant.str " + Calculates the gas amount to extend memory + + Parameters + ---------- + memory : + Memory contents of the EVM. + extensions: + List of extensions to be made to the memory. + Consists of a tuple of start position and size. + + Returns + ------- + extend_memory: `ExtendMemory` + " in + let _ := M.assign_local (| + "size_to_extend" , + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "to_be_paid" , + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "current_size" , + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_name (| globals, "memory" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := + M.for_ (| + make_tuple [ M.get_name (| globals, "start_position" |); M.get_name (| globals, "size" |) ], + M.get_name (| globals, "extensions" |), + ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, "size" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.continue (| |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "before_size" , + M.call (| + M.get_name (| globals, "ceil32" |), + make_list [ + M.get_name (| globals, "current_size" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "after_size" , + M.call (| + M.get_name (| globals, "ceil32" |), + make_list [ + BinOp.add (| + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.get_name (| globals, "start_position" |) + ], + make_dict [] + |), + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.get_name (| globals, "size" |) + ], + make_dict [] + |) + |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.lt_e (| + M.get_name (| globals, "after_size" |), + M.get_name (| globals, "before_size" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.continue (| |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_op_local (| + BinOp.add, + "size_to_extend", + BinOp.sub (| + M.get_name (| globals, "after_size" |), + M.get_name (| globals, "before_size" |) + |) + |) in + let _ := M.assign_local (| + "already_paid" , + M.call (| + M.get_name (| globals, "calculate_memory_gas_cost" |), + make_list [ + M.get_name (| globals, "before_size" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "total_cost" , + M.call (| + M.get_name (| globals, "calculate_memory_gas_cost" |), + make_list [ + M.get_name (| globals, "after_size" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_op_local (| + BinOp.add, + "to_be_paid", + BinOp.sub (| + M.get_name (| globals, "total_cost" |), + M.get_name (| globals, "already_paid" |) + |) + |) in + let _ := M.assign_local (| + "current_size" , + M.get_name (| globals, "after_size" |) + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, "ExtendMemory" |), + make_list [ + M.get_name (| globals, "to_be_paid" |); + M.get_name (| globals, "size_to_extend" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Definition calculate_message_call_gas : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "value"; "gas"; "gas_left"; "memory_cost"; "extra_gas"; "call_stipend" ] |) in + let _ := Constant.str " + Calculates the MessageCallGas (cost and stipend) for + executing call Opcodes. + + Parameters + ---------- + value: + The amount of `ETH` that needs to be transferred. + gas : + The amount of gas provided to the message-call. + gas_left : + The amount of gas left in the current frame. + memory_cost : + The amount needed to extend the memory in the current frame. + extra_gas : + The amount of gas needed for transferring value + creating a new + account inside a message call. + call_stipend : + The amount of stipend provided to a message call to execute code while + transferring value(ETH). + + Returns + ------- + message_call_gas: `MessageCallGas` + " in + let _ := M.assign_local (| + "call_stipend" , + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, "value" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( +M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + (* else *) + )), ltac:(M.monadic ( +M.get_name (| globals, "call_stipend" |) + )) |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.lt (| + M.get_name (| globals, "gas_left" |), + BinOp.add (| + M.get_name (| globals, "extra_gas" |), + M.get_name (| globals, "memory_cost" |) + |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + M.call (| + M.get_name (| globals, "MessageCallGas" |), + make_list [ + BinOp.add (| + M.get_name (| globals, "gas" |), + M.get_name (| globals, "extra_gas" |) + |); + BinOp.add (| + M.get_name (| globals, "gas" |), + M.get_name (| globals, "call_stipend" |) + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "gas" , + M.call (| + M.get_name (| globals, "min" |), + make_list [ + M.get_name (| globals, "gas" |); + M.call (| + M.get_name (| globals, "max_message_call_gas" |), + make_list [ + BinOp.sub (| + BinOp.sub (| + M.get_name (| globals, "gas_left" |), + M.get_name (| globals, "memory_cost" |) + |), + M.get_name (| globals, "extra_gas" |) + |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, "MessageCallGas" |), + make_list [ + BinOp.add (| + M.get_name (| globals, "gas" |), + M.get_name (| globals, "extra_gas" |) + |); + BinOp.add (| + M.get_name (| globals, "gas" |), + M.get_name (| globals, "call_stipend" |) + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Definition max_message_call_gas : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "gas" ] |) in + let _ := Constant.str " + Calculates the maximum gas that is allowed for making a message call + + Parameters + ---------- + gas : + The amount of gas provided to the message-call. + + Returns + ------- + max_allowed_message_call_gas: `ethereum.base_types.Uint` + The maximum gas allowed for making the message-call. + " in + let _ := M.return_ (| + BinOp.sub (| + M.get_name (| globals, "gas" |), + BinOp.floor_div (| + M.get_name (| globals, "gas" |), + Constant.int 64 + |) + |) + |) in + M.pure Constant.None_)). + +Definition init_code_cost : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "init_code_length" ] |) in + let _ := Constant.str " + Calculates the gas to be charged for the init code in CREAT* + opcodes as well as create transactions. + + Parameters + ---------- + init_code_length : + The length of the init code provided to the opcode + or a create transaction + + Returns + ------- + init_code_gas: `ethereum.base_types.Uint` + The gas to be charged for the init code. + " in + let _ := M.return_ (| + BinOp.floor_div (| + BinOp.mult (| + M.get_name (| globals, "GAS_INIT_CODE_WORD_COST" |), + M.call (| + M.get_name (| globals, "ceil32" |), + make_list [ + M.get_name (| globals, "init_code_length" |) + ], + make_dict [] + |) + |), + Constant.int 32 + |) + |) in + M.pure Constant.None_)). diff --git a/CoqOfPython/ethereum/shanghai/vm/instructions/__init__.v b/CoqOfPython/ethereum/shanghai/vm/instructions/__init__.v new file mode 100644 index 0000000..bf085c7 --- /dev/null +++ b/CoqOfPython/ethereum/shanghai/vm/instructions/__init__.v @@ -0,0 +1,74 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.shanghai.vm.instructions.__init__". + +Definition expr_1 : Value.t := + Constant.str " +EVM Instruction Encoding (Opcodes) +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Machine readable representations of EVM instructions, and a mapping to their +implementations. +". + +(* At top_level_stmt: unsupported node type: Import *) + +Axiom typing_imports_Callable : + IsImported globals "typing" "Callable". +Axiom typing_imports_Dict : + IsImported globals "typing" "Dict". + +Axiom ethereum_shanghai_vm_instructions_imports_arithmetic : + IsImported globals "ethereum.shanghai.vm.instructions" "arithmetic". + +Axiom ethereum_shanghai_vm_instructions_imports_bitwise : + IsImported globals "ethereum.shanghai.vm.instructions" "bitwise". + +Axiom ethereum_shanghai_vm_instructions_imports_block : + IsImported globals "ethereum.shanghai.vm.instructions" "block". + +Axiom ethereum_shanghai_vm_instructions_imports_comparison : + IsImported globals "ethereum.shanghai.vm.instructions" "comparison". + +Axiom ethereum_shanghai_vm_instructions_imports_control_flow : + IsImported globals "ethereum.shanghai.vm.instructions" "control_flow". + +Axiom ethereum_shanghai_vm_instructions_imports_environment : + IsImported globals "ethereum.shanghai.vm.instructions" "environment". + +Axiom ethereum_shanghai_vm_instructions_imports_keccak : + IsImported globals "ethereum.shanghai.vm.instructions" "keccak". + +Axiom ethereum_shanghai_vm_instructions_imports_log : + IsImported globals "ethereum.shanghai.vm.instructions" "log". + +Axiom ethereum_shanghai_vm_instructions_imports_memory : + IsImported globals "ethereum.shanghai.vm.instructions" "memory". + +Axiom ethereum_shanghai_vm_instructions_imports_stack : + IsImported globals "ethereum.shanghai.vm.instructions" "stack". + +Axiom ethereum_shanghai_vm_instructions_imports_storage : + IsImported globals "ethereum.shanghai.vm.instructions" "storage". + +Axiom ethereum_shanghai_vm_instructions_imports_system : + IsImported globals "ethereum.shanghai.vm.instructions" "system". + +Definition Ops : Value.t := + builtins.make_klass + [(* At base: unsupported node type: Attribute *)] + [ + + ] + [ + + ]. + +(* At top_level_stmt: unsupported node type: AnnAssign *) diff --git a/CoqOfPython/ethereum/shanghai/vm/instructions/arithmetic.v b/CoqOfPython/ethereum/shanghai/vm/instructions/arithmetic.v new file mode 100644 index 0000000..d62c2ed --- /dev/null +++ b/CoqOfPython/ethereum/shanghai/vm/instructions/arithmetic.v @@ -0,0 +1,1220 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.shanghai.vm.instructions.arithmetic". + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) Arithmetic Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM Arithmetic instructions. +". + +Axiom ethereum_base_types_imports_U255_CEIL_VALUE : + IsImported globals "ethereum.base_types" "U255_CEIL_VALUE". +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_U256_CEIL_VALUE : + IsImported globals "ethereum.base_types" "U256_CEIL_VALUE". +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". + +Axiom ethereum_utils_numeric_imports_get_sign : + IsImported globals "ethereum.utils.numeric" "get_sign". + +Axiom ethereum_shanghai_vm_imports_Evm : + IsImported globals "ethereum.shanghai.vm" "Evm". + +Axiom ethereum_shanghai_vm_gas_imports_GAS_EXPONENTIATION : + IsImported globals "ethereum.shanghai.vm.gas" "GAS_EXPONENTIATION". +Axiom ethereum_shanghai_vm_gas_imports_GAS_EXPONENTIATION_PER_BYTE : + IsImported globals "ethereum.shanghai.vm.gas" "GAS_EXPONENTIATION_PER_BYTE". +Axiom ethereum_shanghai_vm_gas_imports_GAS_LOW : + IsImported globals "ethereum.shanghai.vm.gas" "GAS_LOW". +Axiom ethereum_shanghai_vm_gas_imports_GAS_MID : + IsImported globals "ethereum.shanghai.vm.gas" "GAS_MID". +Axiom ethereum_shanghai_vm_gas_imports_GAS_VERY_LOW : + IsImported globals "ethereum.shanghai.vm.gas" "GAS_VERY_LOW". +Axiom ethereum_shanghai_vm_gas_imports_charge_gas : + IsImported globals "ethereum.shanghai.vm.gas" "charge_gas". + +Axiom ethereum_shanghai_vm_stack_imports_pop : + IsImported globals "ethereum.shanghai.vm.stack" "pop". +Axiom ethereum_shanghai_vm_stack_imports_push : + IsImported globals "ethereum.shanghai.vm.stack" "push". + +Definition add : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Adds the top two elements of the stack together, and pushes the result back + on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "x" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "y" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_VERY_LOW" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "result" , + M.call (| + M.get_field (| M.get_name (| globals, "x" |), "wrapping_add" |), + make_list [ + M.get_name (| globals, "y" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.get_name (| globals, "result" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition sub : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Subtracts the top two elements of the stack, and pushes the result back + on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "x" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "y" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_VERY_LOW" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "result" , + M.call (| + M.get_field (| M.get_name (| globals, "x" |), "wrapping_sub" |), + make_list [ + M.get_name (| globals, "y" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.get_name (| globals, "result" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition mul : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Multiply the top two elements of the stack, and pushes the result back + on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "x" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "y" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_LOW" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "result" , + M.call (| + M.get_field (| M.get_name (| globals, "x" |), "wrapping_mul" |), + make_list [ + M.get_name (| globals, "y" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.get_name (| globals, "result" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition div : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Integer division of the top two elements of the stack. Pushes the result + back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "dividend" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "divisor" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_LOW" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, "divisor" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "quotient" , + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "quotient" , + BinOp.floor_div (| + M.get_name (| globals, "dividend" |), + M.get_name (| globals, "divisor" |) + |) + |) in + M.pure Constant.None_ + )) |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.get_name (| globals, "quotient" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition sdiv : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Signed integer division of the top two elements of the stack. Pushes the + result back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "dividend" , + M.call (| + M.get_field (| M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |), "to_signed" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "divisor" , + M.call (| + M.get_field (| M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |), "to_signed" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_LOW" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, "divisor" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "quotient" , + Constant.int 0 + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + BoolOp.and (| + Compare.eq (| + M.get_name (| globals, "dividend" |), + UnOp.sub (| M.get_name (| globals, "U255_CEIL_VALUE" |) |) + |), + ltac:(M.monadic ( + Compare.eq (| + M.get_name (| globals, "divisor" |), + UnOp.sub (| Constant.int 1 |) + |) + )) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "quotient" , + UnOp.sub (| M.get_name (| globals, "U255_CEIL_VALUE" |) |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "sign" , + M.call (| + M.get_name (| globals, "get_sign" |), + make_list [ + BinOp.mult (| + M.get_name (| globals, "dividend" |), + M.get_name (| globals, "divisor" |) + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "quotient" , + BinOp.mult (| + M.get_name (| globals, "sign" |), + BinOp.floor_div (| + M.call (| + M.get_name (| globals, "abs" |), + make_list [ + M.get_name (| globals, "dividend" |) + ], + make_dict [] + |), + M.call (| + M.get_name (| globals, "abs" |), + make_list [ + M.get_name (| globals, "divisor" |) + ], + make_dict [] + |) + |) + |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )) |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.call (| + M.get_field (| M.get_name (| globals, "U256" |), "from_signed" |), + make_list [ + M.get_name (| globals, "quotient" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition mod_ : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Modulo remainder of the top two elements of the stack. Pushes the result + back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "x" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "y" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_LOW" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, "y" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "remainder" , + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "remainder" , + BinOp.mod_ (| + M.get_name (| globals, "x" |), + M.get_name (| globals, "y" |) + |) + |) in + M.pure Constant.None_ + )) |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.get_name (| globals, "remainder" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition smod : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Signed modulo remainder of the top two elements of the stack. Pushes the + result back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "x" , + M.call (| + M.get_field (| M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |), "to_signed" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "y" , + M.call (| + M.get_field (| M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |), "to_signed" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_LOW" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, "y" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "remainder" , + Constant.int 0 + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "remainder" , + BinOp.mult (| + M.call (| + M.get_name (| globals, "get_sign" |), + make_list [ + M.get_name (| globals, "x" |) + ], + make_dict [] + |), + BinOp.mod_ (| + M.call (| + M.get_name (| globals, "abs" |), + make_list [ + M.get_name (| globals, "x" |) + ], + make_dict [] + |), + M.call (| + M.get_name (| globals, "abs" |), + make_list [ + M.get_name (| globals, "y" |) + ], + make_dict [] + |) + |) + |) + |) in + M.pure Constant.None_ + )) |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.call (| + M.get_field (| M.get_name (| globals, "U256" |), "from_signed" |), + make_list [ + M.get_name (| globals, "remainder" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition addmod : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Modulo addition of the top 2 elements with the 3rd element. Pushes the + result back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "x" , + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "y" , + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "z" , + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_MID" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, "z" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "result" , + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "result" , + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + BinOp.mod_ (| + BinOp.add (| + M.get_name (| globals, "x" |), + M.get_name (| globals, "y" |) + |), + M.get_name (| globals, "z" |) + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + )) |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.get_name (| globals, "result" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition mulmod : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Modulo multiplication of the top 2 elements with the 3rd element. Pushes + the result back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "x" , + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "y" , + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "z" , + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_MID" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, "z" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "result" , + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "result" , + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + BinOp.mod_ (| + BinOp.mult (| + M.get_name (| globals, "x" |), + M.get_name (| globals, "y" |) + |), + M.get_name (| globals, "z" |) + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + )) |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.get_name (| globals, "result" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition exp : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Exponential operation of the top 2 elements. Pushes the result back on + the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "base" , + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "exponent" , + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "exponent_bits" , + M.call (| + M.get_field (| M.get_name (| globals, "exponent" |), "bit_length" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "exponent_bytes" , + BinOp.floor_div (| + BinOp.add (| + M.get_name (| globals, "exponent_bits" |), + Constant.int 7 + |), + Constant.int 8 + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + BinOp.add (| + M.get_name (| globals, "GAS_EXPONENTIATION" |), + BinOp.mult (| + M.get_name (| globals, "GAS_EXPONENTIATION_PER_BYTE" |), + M.get_name (| globals, "exponent_bytes" |) + |) + |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "result" , + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + M.call (| + M.get_name (| globals, "pow" |), + make_list [ + M.get_name (| globals, "base" |); + M.get_name (| globals, "exponent" |); + M.get_name (| globals, "U256_CEIL_VALUE" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.get_name (| globals, "result" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition signextend : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Sign extend operation. In other words, extend a signed number which + fits in N bytes to 32 bytes. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "byte_num" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "value" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_LOW" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.gt (| + M.get_name (| globals, "byte_num" |), + Constant.int 31 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "result" , + M.get_name (| globals, "value" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "value_bytes" , + M.call (| + M.get_name (| globals, "bytes" |), + make_list [ + M.call (| + M.get_field (| M.get_name (| globals, "value" |), "to_be_bytes32" |), + make_list [], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "value_bytes" , + M.slice (| + M.get_name (| globals, "value_bytes" |), + BinOp.sub (| + Constant.int 31, + M.call (| + M.get_name (| globals, "int" |), + make_list [ + M.get_name (| globals, "byte_num" |) + ], + make_dict [] + |) + |), + Constant.None_, + Constant.None_ + |) + |) in + let _ := M.assign_local (| + "sign_bit" , + BinOp.r_shift (| + M.get_subscript (| + M.get_name (| globals, "value_bytes" |), + Constant.int 0 + |), + Constant.int 7 + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, "sign_bit" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "result" , + M.call (| + M.get_field (| M.get_name (| globals, "U256" |), "from_be_bytes" |), + make_list [ + M.get_name (| globals, "value_bytes" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "num_bytes_prepend" , + BinOp.sub (| + Constant.int 32, + BinOp.add (| + M.get_name (| globals, "byte_num" |), + Constant.int 1 + |) + |) + |) in + let _ := M.assign_local (| + "result" , + M.call (| + M.get_field (| M.get_name (| globals, "U256" |), "from_be_bytes" |), + make_list [ + BinOp.add (| + M.call (| + M.get_name (| globals, "bytearray" |), + make_list [ + BinOp.mult (| + make_list [ + Constant.int 255 + ], + M.get_name (| globals, "num_bytes_prepend" |) + |) + ], + make_dict [] + |), + M.get_name (| globals, "value_bytes" |) + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )) |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.get_name (| globals, "result" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). diff --git a/CoqOfPython/ethereum/shanghai/vm/instructions/bitwise.v b/CoqOfPython/ethereum/shanghai/vm/instructions/bitwise.v new file mode 100644 index 0000000..5e49a28 --- /dev/null +++ b/CoqOfPython/ethereum/shanghai/vm/instructions/bitwise.v @@ -0,0 +1,666 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.shanghai.vm.instructions.bitwise". + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) Bitwise Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM bitwise instructions. +". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_U256_CEIL_VALUE : + IsImported globals "ethereum.base_types" "U256_CEIL_VALUE". + +Axiom ethereum_shanghai_vm_imports_Evm : + IsImported globals "ethereum.shanghai.vm" "Evm". + +Axiom ethereum_shanghai_vm_gas_imports_GAS_VERY_LOW : + IsImported globals "ethereum.shanghai.vm.gas" "GAS_VERY_LOW". +Axiom ethereum_shanghai_vm_gas_imports_charge_gas : + IsImported globals "ethereum.shanghai.vm.gas" "charge_gas". + +Axiom ethereum_shanghai_vm_stack_imports_pop : + IsImported globals "ethereum.shanghai.vm.stack" "pop". +Axiom ethereum_shanghai_vm_stack_imports_push : + IsImported globals "ethereum.shanghai.vm.stack" "push". + +Definition bitwise_and : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Bitwise AND operation of the top 2 elements of the stack. Pushes the + result back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "x" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "y" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_VERY_LOW" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + BinOp.bit_and (| + M.get_name (| globals, "x" |), + M.get_name (| globals, "y" |) + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition bitwise_or : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Bitwise OR operation of the top 2 elements of the stack. Pushes the + result back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "x" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "y" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_VERY_LOW" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + BinOp.bit_or (| + M.get_name (| globals, "x" |), + M.get_name (| globals, "y" |) + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition bitwise_xor : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Bitwise XOR operation of the top 2 elements of the stack. Pushes the + result back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "x" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "y" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_VERY_LOW" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + BinOp.bit_xor (| + M.get_name (| globals, "x" |), + M.get_name (| globals, "y" |) + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition bitwise_not : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Bitwise NOT operation of the top element of the stack. Pushes the + result back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "x" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_VERY_LOW" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + UnOp.invert (| M.get_name (| globals, "x" |) |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition get_byte : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + For a word (defined by next top element of the stack), retrieve the + Nth byte (0-indexed and defined by top element of stack) from the + left (most significant) to right (least significant). + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "byte_index" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "word" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_VERY_LOW" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.gt_e (| + M.get_name (| globals, "byte_index" |), + Constant.int 32 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "result" , + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "extra_bytes_to_right" , + BinOp.sub (| + Constant.int 31, + M.get_name (| globals, "byte_index" |) + |) + |) in + let _ := M.assign_local (| + "word" , + BinOp.r_shift (| + M.get_name (| globals, "word" |), + BinOp.mult (| + M.get_name (| globals, "extra_bytes_to_right" |), + Constant.int 8 + |) + |) + |) in + let _ := M.assign_local (| + "word" , + BinOp.bit_and (| + M.get_name (| globals, "word" |), + Constant.int 255 + |) + |) in + let _ := M.assign_local (| + "result" , + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + M.get_name (| globals, "word" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + )) |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.get_name (| globals, "result" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition bitwise_shl : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Logical shift left (SHL) operation of the top 2 elements of the stack. + Pushes the result back on the stack. + Parameters + ---------- + evm : + The current EVM frame. + " in + let _ := M.assign_local (| + "shift" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "value" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_VERY_LOW" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.lt (| + M.get_name (| globals, "shift" |), + Constant.int 256 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "result" , + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + BinOp.mod_ (| + BinOp.l_shift (| + M.get_name (| globals, "value" |), + M.get_name (| globals, "shift" |) + |), + M.get_name (| globals, "U256_CEIL_VALUE" |) + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "result" , + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + )) |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.get_name (| globals, "result" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition bitwise_shr : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Logical shift right (SHR) operation of the top 2 elements of the stack. + Pushes the result back on the stack. + Parameters + ---------- + evm : + The current EVM frame. + " in + let _ := M.assign_local (| + "shift" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "value" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_VERY_LOW" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.lt (| + M.get_name (| globals, "shift" |), + Constant.int 256 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "result" , + BinOp.r_shift (| + M.get_name (| globals, "value" |), + M.get_name (| globals, "shift" |) + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "result" , + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + )) |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.get_name (| globals, "result" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition bitwise_sar : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Arithmetic shift right (SAR) operation of the top 2 elements of the stack. + Pushes the result back on the stack. + Parameters + ---------- + evm : + The current EVM frame. + " in + let _ := M.assign_local (| + "shift" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "signed_value" , + M.call (| + M.get_field (| M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |), "to_signed" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_VERY_LOW" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.lt (| + M.get_name (| globals, "shift" |), + Constant.int 256 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "result" , + M.call (| + M.get_field (| M.get_name (| globals, "U256" |), "from_signed" |), + make_list [ + BinOp.r_shift (| + M.get_name (| globals, "signed_value" |), + M.get_name (| globals, "shift" |) + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + Compare.gt_e (| + M.get_name (| globals, "signed_value" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "result" , + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "result" , + M.get_field (| M.get_name (| globals, "U256" |), "MAX_VALUE" |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )) |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.get_name (| globals, "result" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). diff --git a/CoqOfPython/ethereum/shanghai/vm/instructions/block.v b/CoqOfPython/ethereum/shanghai/vm/instructions/block.v new file mode 100644 index 0000000..72e72da --- /dev/null +++ b/CoqOfPython/ethereum/shanghai/vm/instructions/block.v @@ -0,0 +1,432 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.shanghai.vm.instructions.block". + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) Block Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM block instructions. +". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". + +Axiom ethereum_shanghai_vm_imports_Evm : + IsImported globals "ethereum.shanghai.vm" "Evm". + +Axiom ethereum_shanghai_vm_gas_imports_GAS_BASE : + IsImported globals "ethereum.shanghai.vm.gas" "GAS_BASE". +Axiom ethereum_shanghai_vm_gas_imports_GAS_BLOCK_HASH : + IsImported globals "ethereum.shanghai.vm.gas" "GAS_BLOCK_HASH". +Axiom ethereum_shanghai_vm_gas_imports_charge_gas : + IsImported globals "ethereum.shanghai.vm.gas" "charge_gas". + +Axiom ethereum_shanghai_vm_stack_imports_pop : + IsImported globals "ethereum.shanghai.vm.stack" "pop". +Axiom ethereum_shanghai_vm_stack_imports_push : + IsImported globals "ethereum.shanghai.vm.stack" "push". + +Definition block_hash : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Push the hash of one of the 256 most recent complete blocks onto the + stack. The block number to hash is present at the top of the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + Raises + ------ + :py:class:`~ethereum.shanghai.vm.exceptions.StackUnderflowError` + If `len(stack)` is less than `1`. + :py:class:`~ethereum.shanghai.vm.exceptions.OutOfGasError` + If `evm.gas_left` is less than `20`. + " in + let _ := M.assign_local (| + "block_number" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_BLOCK_HASH" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + BoolOp.or (| + Compare.lt_e (| + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "env" |), "number" |), + M.get_name (| globals, "block_number" |) + |), + ltac:(M.monadic ( + Compare.gt (| + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "env" |), "number" |), + BinOp.add (| + M.get_name (| globals, "block_number" |), + Constant.int 256 + |) + |) + )) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "hash" , + Constant.bytes "00" + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "hash" , + M.get_subscript (| + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "env" |), "block_hashes" |), + UnOp.sub (| BinOp.sub (| + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "env" |), "number" |), + M.get_name (| globals, "block_number" |) + |) |) + |) + |) in + M.pure Constant.None_ + )) |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.call (| + M.get_field (| M.get_name (| globals, "U256" |), "from_be_bytes" |), + make_list [ + M.get_name (| globals, "hash" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition coinbase : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Push the current block's beneficiary address (address of the block miner) + onto the stack. + + Here the current block refers to the block in which the currently + executing transaction/call resides. + + Parameters + ---------- + evm : + The current EVM frame. + + Raises + ------ + :py:class:`~ethereum.shanghai.vm.exceptions.StackOverflowError` + If `len(stack)` is equal to `1024`. + :py:class:`~ethereum.shanghai.vm.exceptions.OutOfGasError` + If `evm.gas_left` is less than `2`. + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_BASE" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.call (| + M.get_field (| M.get_name (| globals, "U256" |), "from_be_bytes" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "env" |), "coinbase" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition timestamp : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Push the current block's timestamp onto the stack. Here the timestamp + being referred is actually the unix timestamp in seconds. + + Here the current block refers to the block in which the currently + executing transaction/call resides. + + Parameters + ---------- + evm : + The current EVM frame. + + Raises + ------ + :py:class:`~ethereum.shanghai.vm.exceptions.StackOverflowError` + If `len(stack)` is equal to `1024`. + :py:class:`~ethereum.shanghai.vm.exceptions.OutOfGasError` + If `evm.gas_left` is less than `2`. + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_BASE" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "env" |), "time" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition number : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Push the current block's number onto the stack. + + Here the current block refers to the block in which the currently + executing transaction/call resides. + + Parameters + ---------- + evm : + The current EVM frame. + + Raises + ------ + :py:class:`~ethereum.shanghai.vm.exceptions.StackOverflowError` + If `len(stack)` is equal to `1024`. + :py:class:`~ethereum.shanghai.vm.exceptions.OutOfGasError` + If `evm.gas_left` is less than `2`. + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_BASE" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "env" |), "number" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition prev_randao : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Push the `prev_randao` value onto the stack. + + The `prev_randao` value is the random output of the beacon chain's + randomness oracle for the previous block. + + Parameters + ---------- + evm : + The current EVM frame. + + Raises + ------ + :py:class:`~ethereum.shanghai.vm.exceptions.StackOverflowError` + If `len(stack)` is equal to `1024`. + :py:class:`~ethereum.shanghai.vm.exceptions.OutOfGasError` + If `evm.gas_left` is less than `2`. + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_BASE" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.call (| + M.get_field (| M.get_name (| globals, "U256" |), "from_be_bytes" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "env" |), "prev_randao" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition gas_limit : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Push the current block's gas limit onto the stack. + + Here the current block refers to the block in which the currently + executing transaction/call resides. + + Parameters + ---------- + evm : + The current EVM frame. + + Raises + ------ + :py:class:`~ethereum.shanghai.vm.exceptions.StackOverflowError` + If `len(stack)` is equal to `1024`. + :py:class:`~ethereum.shanghai.vm.exceptions.OutOfGasError` + If `evm.gas_left` is less than `2`. + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_BASE" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "env" |), "gas_limit" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition chain_id : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Push the chain id onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + Raises + ------ + :py:class:`~ethereum.shanghai.vm.exceptions.StackOverflowError` + If `len(stack)` is equal to `1024`. + :py:class:`~ethereum.shanghai.vm.exceptions.OutOfGasError` + If `evm.gas_left` is less than `2`. + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_BASE" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "env" |), "chain_id" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). diff --git a/CoqOfPython/ethereum/shanghai/vm/instructions/comparison.v b/CoqOfPython/ethereum/shanghai/vm/instructions/comparison.v new file mode 100644 index 0000000..53c9557 --- /dev/null +++ b/CoqOfPython/ethereum/shanghai/vm/instructions/comparison.v @@ -0,0 +1,452 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.shanghai.vm.instructions.comparison". + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) Comparison Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM Comparison instructions. +". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". + +Axiom ethereum_shanghai_vm_imports_Evm : + IsImported globals "ethereum.shanghai.vm" "Evm". + +Axiom ethereum_shanghai_vm_gas_imports_GAS_VERY_LOW : + IsImported globals "ethereum.shanghai.vm.gas" "GAS_VERY_LOW". +Axiom ethereum_shanghai_vm_gas_imports_charge_gas : + IsImported globals "ethereum.shanghai.vm.gas" "charge_gas". + +Axiom ethereum_shanghai_vm_stack_imports_pop : + IsImported globals "ethereum.shanghai.vm.stack" "pop". +Axiom ethereum_shanghai_vm_stack_imports_push : + IsImported globals "ethereum.shanghai.vm.stack" "push". + +Definition less_than : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Checks if the top element is less than the next top element. Pushes the + result back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "left" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "right" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_VERY_LOW" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "result" , + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Compare.lt (| + M.get_name (| globals, "left" |), + M.get_name (| globals, "right" |) + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.get_name (| globals, "result" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition signed_less_than : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Signed less-than comparison. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "left" , + M.call (| + M.get_field (| M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |), "to_signed" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "right" , + M.call (| + M.get_field (| M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |), "to_signed" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_VERY_LOW" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "result" , + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Compare.lt (| + M.get_name (| globals, "left" |), + M.get_name (| globals, "right" |) + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.get_name (| globals, "result" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition greater_than : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Checks if the top element is greater than the next top element. Pushes + the result back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "left" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "right" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_VERY_LOW" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "result" , + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Compare.gt (| + M.get_name (| globals, "left" |), + M.get_name (| globals, "right" |) + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.get_name (| globals, "result" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition signed_greater_than : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Signed greater-than comparison. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "left" , + M.call (| + M.get_field (| M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |), "to_signed" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "right" , + M.call (| + M.get_field (| M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |), "to_signed" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_VERY_LOW" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "result" , + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Compare.gt (| + M.get_name (| globals, "left" |), + M.get_name (| globals, "right" |) + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.get_name (| globals, "result" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition equal : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Checks if the top element is equal to the next top element. Pushes + the result back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "left" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "right" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_VERY_LOW" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "result" , + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Compare.eq (| + M.get_name (| globals, "left" |), + M.get_name (| globals, "right" |) + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.get_name (| globals, "result" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition is_zero : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Checks if the top element is equal to 0. Pushes the result back on the + stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "x" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_VERY_LOW" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "result" , + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Compare.eq (| + M.get_name (| globals, "x" |), + Constant.int 0 + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.get_name (| globals, "result" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). diff --git a/CoqOfPython/ethereum/shanghai/vm/instructions/control_flow.v b/CoqOfPython/ethereum/shanghai/vm/instructions/control_flow.v new file mode 100644 index 0000000..e43ea45 --- /dev/null +++ b/CoqOfPython/ethereum/shanghai/vm/instructions/control_flow.v @@ -0,0 +1,350 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.shanghai.vm.instructions.control_flow". + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) Control Flow Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM control flow instructions. +". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". + +Axiom ethereum_shanghai_vm_gas_imports_GAS_BASE : + IsImported globals "ethereum.shanghai.vm.gas" "GAS_BASE". +Axiom ethereum_shanghai_vm_gas_imports_GAS_HIGH : + IsImported globals "ethereum.shanghai.vm.gas" "GAS_HIGH". +Axiom ethereum_shanghai_vm_gas_imports_GAS_JUMPDEST : + IsImported globals "ethereum.shanghai.vm.gas" "GAS_JUMPDEST". +Axiom ethereum_shanghai_vm_gas_imports_GAS_MID : + IsImported globals "ethereum.shanghai.vm.gas" "GAS_MID". +Axiom ethereum_shanghai_vm_gas_imports_charge_gas : + IsImported globals "ethereum.shanghai.vm.gas" "charge_gas". + +Axiom ethereum_shanghai_vm_imports_Evm : + IsImported globals "ethereum.shanghai.vm" "Evm". + +Axiom ethereum_shanghai_vm_exceptions_imports_InvalidJumpDestError : + IsImported globals "ethereum.shanghai.vm.exceptions" "InvalidJumpDestError". + +Axiom ethereum_shanghai_vm_stack_imports_pop : + IsImported globals "ethereum.shanghai.vm.stack" "pop". +Axiom ethereum_shanghai_vm_stack_imports_push : + IsImported globals "ethereum.shanghai.vm.stack" "push". + +Definition stop : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Stop further execution of EVM code. + + Parameters + ---------- + evm : + The current EVM frame. + " in + let _ := M.pass (| |) in + let _ := M.pass (| |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, "evm" |), "running" |), + Constant.bool false + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition jump : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Alter the program counter to the location specified by the top of the + stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "jump_dest" , + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_MID" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.not_in (| + M.get_name (| globals, "jump_dest" |), + M.get_field (| M.get_name (| globals, "evm" |), "valid_jump_destinations" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, "InvalidJumpDestError" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.get_name (| globals, "jump_dest" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Definition jumpi : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Alter the program counter to the specified location if and only if a + condition is true. If the condition is not true, then the program counter + would increase only by 1. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "jump_dest" , + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "conditional_value" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_HIGH" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, "conditional_value" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "destination" , + BinOp.add (| + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + Compare.not_in (| + M.get_name (| globals, "jump_dest" |), + M.get_field (| M.get_name (| globals, "evm" |), "valid_jump_destinations" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, "InvalidJumpDestError" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "destination" , + M.get_name (| globals, "jump_dest" |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )) |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.get_name (| globals, "destination" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Definition pc : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Push onto the stack the value of the program counter after reaching the + current instruction and without increasing it for the next instruction. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_BASE" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "pc" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition gas_left : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Push the amount of available gas (including the corresponding reduction + for the cost of this instruction) onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_BASE" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "gas_left" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition jumpdest : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Mark a valid destination for jumps. This is a noop, present only + to be used by `JUMP` and `JUMPI` opcodes to verify that their jump is + valid. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_JUMPDEST" |) + ], + make_dict [] + |) in + let _ := M.pass (| |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). diff --git a/CoqOfPython/ethereum/shanghai/vm/instructions/environment.v b/CoqOfPython/ethereum/shanghai/vm/instructions/environment.v new file mode 100644 index 0000000..17798fb --- /dev/null +++ b/CoqOfPython/ethereum/shanghai/vm/instructions/environment.v @@ -0,0 +1,1529 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.shanghai.vm.instructions.environment". + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) Environmental Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM environment related instructions. +". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". + +Axiom ethereum_crypto_hash_imports_keccak256 : + IsImported globals "ethereum.crypto.hash" "keccak256". + +Axiom ethereum_utils_ensure_imports_ensure : + IsImported globals "ethereum.utils.ensure" "ensure". + +Axiom ethereum_utils_numeric_imports_ceil32 : + IsImported globals "ethereum.utils.numeric" "ceil32". + +Axiom ethereum_shanghai_fork_types_imports_EMPTY_ACCOUNT : + IsImported globals "ethereum.shanghai.fork_types" "EMPTY_ACCOUNT". + +Axiom ethereum_shanghai_state_imports_get_account : + IsImported globals "ethereum.shanghai.state" "get_account". + +Axiom ethereum_shanghai_utils_address_imports_to_address : + IsImported globals "ethereum.shanghai.utils.address" "to_address". + +Axiom ethereum_shanghai_vm_memory_imports_buffer_read : + IsImported globals "ethereum.shanghai.vm.memory" "buffer_read". +Axiom ethereum_shanghai_vm_memory_imports_memory_write : + IsImported globals "ethereum.shanghai.vm.memory" "memory_write". + +Axiom ethereum_shanghai_vm_imports_Evm : + IsImported globals "ethereum.shanghai.vm" "Evm". + +Axiom ethereum_shanghai_vm_exceptions_imports_OutOfBoundsRead : + IsImported globals "ethereum.shanghai.vm.exceptions" "OutOfBoundsRead". + +Axiom ethereum_shanghai_vm_gas_imports_GAS_BASE : + IsImported globals "ethereum.shanghai.vm.gas" "GAS_BASE". +Axiom ethereum_shanghai_vm_gas_imports_GAS_COLD_ACCOUNT_ACCESS : + IsImported globals "ethereum.shanghai.vm.gas" "GAS_COLD_ACCOUNT_ACCESS". +Axiom ethereum_shanghai_vm_gas_imports_GAS_COPY : + IsImported globals "ethereum.shanghai.vm.gas" "GAS_COPY". +Axiom ethereum_shanghai_vm_gas_imports_GAS_FAST_STEP : + IsImported globals "ethereum.shanghai.vm.gas" "GAS_FAST_STEP". +Axiom ethereum_shanghai_vm_gas_imports_GAS_RETURN_DATA_COPY : + IsImported globals "ethereum.shanghai.vm.gas" "GAS_RETURN_DATA_COPY". +Axiom ethereum_shanghai_vm_gas_imports_GAS_VERY_LOW : + IsImported globals "ethereum.shanghai.vm.gas" "GAS_VERY_LOW". +Axiom ethereum_shanghai_vm_gas_imports_GAS_WARM_ACCESS : + IsImported globals "ethereum.shanghai.vm.gas" "GAS_WARM_ACCESS". +Axiom ethereum_shanghai_vm_gas_imports_calculate_gas_extend_memory : + IsImported globals "ethereum.shanghai.vm.gas" "calculate_gas_extend_memory". +Axiom ethereum_shanghai_vm_gas_imports_charge_gas : + IsImported globals "ethereum.shanghai.vm.gas" "charge_gas". + +Axiom ethereum_shanghai_vm_stack_imports_pop : + IsImported globals "ethereum.shanghai.vm.stack" "pop". +Axiom ethereum_shanghai_vm_stack_imports_push : + IsImported globals "ethereum.shanghai.vm.stack" "push". + +Definition address : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Pushes the address of the current executing account to the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_BASE" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.call (| + M.get_field (| M.get_name (| globals, "U256" |), "from_be_bytes" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "current_target" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition balance : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Pushes the balance of the given account onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "address" , + M.call (| + M.get_name (| globals, "to_address" |), + make_list [ + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.in_ (| + M.get_name (| globals, "address" |), + M.get_field (| M.get_name (| globals, "evm" |), "accessed_addresses" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_WARM_ACCESS" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "accessed_addresses" |), "add" |), + make_list [ + M.get_name (| globals, "address" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_COLD_ACCOUNT_ACCESS" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "balance" , + M.get_field (| M.call (| + M.get_name (| globals, "get_account" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "env" |), "state" |); + M.get_name (| globals, "address" |) + ], + make_dict [] + |), "balance" |) + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.get_name (| globals, "balance" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition origin : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Pushes the address of the original transaction sender to the stack. + The origin address can only be an EOA. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_BASE" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.call (| + M.get_field (| M.get_name (| globals, "U256" |), "from_be_bytes" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "env" |), "origin" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition caller : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Pushes the address of the caller onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_BASE" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.call (| + M.get_field (| M.get_name (| globals, "U256" |), "from_be_bytes" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "caller" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition callvalue : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Push the value (in wei) sent with the call onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_BASE" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "value" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition calldataload : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Push a word (32 bytes) of the input data belonging to the current + environment onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "start_index" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_VERY_LOW" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "value" , + M.call (| + M.get_name (| globals, "buffer_read" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "data" |); + M.get_name (| globals, "start_index" |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 32 + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.call (| + M.get_field (| M.get_name (| globals, "U256" |), "from_be_bytes" |), + make_list [ + M.get_name (| globals, "value" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition calldatasize : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Push the size of input data in current environment onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_BASE" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "data" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition calldatacopy : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Copy a portion of the input data in current environment to memory. + + This will also expand the memory, in case that the memory is insufficient + to store the data. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "memory_start_index" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "data_start_index" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "size" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "words" , + BinOp.floor_div (| + M.call (| + M.get_name (| globals, "ceil32" |), + make_list [ + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.get_name (| globals, "size" |) + ], + make_dict [] + |) + ], + make_dict [] + |), + Constant.int 32 + |) + |) in + let _ := M.assign_local (| + "copy_gas_cost" , + BinOp.mult (| + M.get_name (| globals, "GAS_COPY" |), + M.get_name (| globals, "words" |) + |) + |) in + let _ := M.assign_local (| + "extend_memory" , + M.call (| + M.get_name (| globals, "calculate_gas_extend_memory" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "memory" |); + make_list [ + make_tuple [ M.get_name (| globals, "memory_start_index" |); M.get_name (| globals, "size" |) ] + ] + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + BinOp.add (| + BinOp.add (| + M.get_name (| globals, "GAS_VERY_LOW" |), + M.get_name (| globals, "copy_gas_cost" |) + |), + M.get_field (| M.get_name (| globals, "extend_memory" |), "cost" |) + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "memory" |), + BinOp.mult (| + Constant.bytes "00", + M.get_field (| M.get_name (| globals, "extend_memory" |), "expand_by" |) + |) + |) in + let _ := M.assign_local (| + "value" , + M.call (| + M.get_name (| globals, "buffer_read" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "data" |); + M.get_name (| globals, "data_start_index" |); + M.get_name (| globals, "size" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "memory_write" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "memory" |); + M.get_name (| globals, "memory_start_index" |); + M.get_name (| globals, "value" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition codesize : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Push the size of code running in current environment onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_BASE" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "code" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition codecopy : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Copy a portion of the code in current environment to memory. + + This will also expand the memory, in case that the memory is insufficient + to store the data. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "memory_start_index" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "code_start_index" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "size" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "words" , + BinOp.floor_div (| + M.call (| + M.get_name (| globals, "ceil32" |), + make_list [ + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.get_name (| globals, "size" |) + ], + make_dict [] + |) + ], + make_dict [] + |), + Constant.int 32 + |) + |) in + let _ := M.assign_local (| + "copy_gas_cost" , + BinOp.mult (| + M.get_name (| globals, "GAS_COPY" |), + M.get_name (| globals, "words" |) + |) + |) in + let _ := M.assign_local (| + "extend_memory" , + M.call (| + M.get_name (| globals, "calculate_gas_extend_memory" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "memory" |); + make_list [ + make_tuple [ M.get_name (| globals, "memory_start_index" |); M.get_name (| globals, "size" |) ] + ] + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + BinOp.add (| + BinOp.add (| + M.get_name (| globals, "GAS_VERY_LOW" |), + M.get_name (| globals, "copy_gas_cost" |) + |), + M.get_field (| M.get_name (| globals, "extend_memory" |), "cost" |) + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "memory" |), + BinOp.mult (| + Constant.bytes "00", + M.get_field (| M.get_name (| globals, "extend_memory" |), "expand_by" |) + |) + |) in + let _ := M.assign_local (| + "value" , + M.call (| + M.get_name (| globals, "buffer_read" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "code" |); + M.get_name (| globals, "code_start_index" |); + M.get_name (| globals, "size" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "memory_write" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "memory" |); + M.get_name (| globals, "memory_start_index" |); + M.get_name (| globals, "value" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition gasprice : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Push the gas price used in current environment onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_BASE" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "env" |), "gas_price" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition extcodesize : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Push the code size of a given account onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "address" , + M.call (| + M.get_name (| globals, "to_address" |), + make_list [ + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.in_ (| + M.get_name (| globals, "address" |), + M.get_field (| M.get_name (| globals, "evm" |), "accessed_addresses" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_WARM_ACCESS" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "accessed_addresses" |), "add" |), + make_list [ + M.get_name (| globals, "address" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_COLD_ACCOUNT_ACCESS" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "codesize" , + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_field (| M.call (| + M.get_name (| globals, "get_account" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "env" |), "state" |); + M.get_name (| globals, "address" |) + ], + make_dict [] + |), "code" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.get_name (| globals, "codesize" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition extcodecopy : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Copy a portion of an account's code to memory. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "address" , + M.call (| + M.get_name (| globals, "to_address" |), + make_list [ + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_start_index" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "code_start_index" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "size" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "words" , + BinOp.floor_div (| + M.call (| + M.get_name (| globals, "ceil32" |), + make_list [ + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.get_name (| globals, "size" |) + ], + make_dict [] + |) + ], + make_dict [] + |), + Constant.int 32 + |) + |) in + let _ := M.assign_local (| + "copy_gas_cost" , + BinOp.mult (| + M.get_name (| globals, "GAS_COPY" |), + M.get_name (| globals, "words" |) + |) + |) in + let _ := M.assign_local (| + "extend_memory" , + M.call (| + M.get_name (| globals, "calculate_gas_extend_memory" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "memory" |); + make_list [ + make_tuple [ M.get_name (| globals, "memory_start_index" |); M.get_name (| globals, "size" |) ] + ] + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.in_ (| + M.get_name (| globals, "address" |), + M.get_field (| M.get_name (| globals, "evm" |), "accessed_addresses" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + BinOp.add (| + BinOp.add (| + M.get_name (| globals, "GAS_WARM_ACCESS" |), + M.get_name (| globals, "copy_gas_cost" |) + |), + M.get_field (| M.get_name (| globals, "extend_memory" |), "cost" |) + |) + ], + make_dict [] + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "accessed_addresses" |), "add" |), + make_list [ + M.get_name (| globals, "address" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + BinOp.add (| + BinOp.add (| + M.get_name (| globals, "GAS_COLD_ACCOUNT_ACCESS" |), + M.get_name (| globals, "copy_gas_cost" |) + |), + M.get_field (| M.get_name (| globals, "extend_memory" |), "cost" |) + |) + ], + make_dict [] + |) in + M.pure Constant.None_ + )) |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "memory" |), + BinOp.mult (| + Constant.bytes "00", + M.get_field (| M.get_name (| globals, "extend_memory" |), "expand_by" |) + |) + |) in + let _ := M.assign_local (| + "code" , + M.get_field (| M.call (| + M.get_name (| globals, "get_account" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "env" |), "state" |); + M.get_name (| globals, "address" |) + ], + make_dict [] + |), "code" |) + |) in + let _ := M.assign_local (| + "value" , + M.call (| + M.get_name (| globals, "buffer_read" |), + make_list [ + M.get_name (| globals, "code" |); + M.get_name (| globals, "code_start_index" |); + M.get_name (| globals, "size" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "memory_write" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "memory" |); + M.get_name (| globals, "memory_start_index" |); + M.get_name (| globals, "value" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition returndatasize : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Pushes the size of the return data buffer onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_BASE" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "return_data" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition returndatacopy : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Copies data from the return data buffer code to memory + + Parameters + ---------- + evm : + The current EVM frame. + " in + let _ := M.assign_local (| + "memory_start_index" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "return_data_start_position" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "size" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "words" , + BinOp.floor_div (| + M.call (| + M.get_name (| globals, "ceil32" |), + make_list [ + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.get_name (| globals, "size" |) + ], + make_dict [] + |) + ], + make_dict [] + |), + Constant.int 32 + |) + |) in + let _ := M.assign_local (| + "copy_gas_cost" , + BinOp.mult (| + M.get_name (| globals, "GAS_RETURN_DATA_COPY" |), + M.get_name (| globals, "words" |) + |) + |) in + let _ := M.assign_local (| + "extend_memory" , + M.call (| + M.get_name (| globals, "calculate_gas_extend_memory" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "memory" |); + make_list [ + make_tuple [ M.get_name (| globals, "memory_start_index" |); M.get_name (| globals, "size" |) ] + ] + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + BinOp.add (| + BinOp.add (| + M.get_name (| globals, "GAS_VERY_LOW" |), + M.get_name (| globals, "copy_gas_cost" |) + |), + M.get_field (| M.get_name (| globals, "extend_memory" |), "cost" |) + |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + Compare.lt_e (| + BinOp.add (| + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.get_name (| globals, "return_data_start_position" |) + ], + make_dict [] + |), + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.get_name (| globals, "size" |) + ], + make_dict [] + |) + |), + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "return_data" |) + ], + make_dict [] + |) + |); + M.get_name (| globals, "OutOfBoundsRead" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "memory" |), + BinOp.mult (| + Constant.bytes "00", + M.get_field (| M.get_name (| globals, "extend_memory" |), "expand_by" |) + |) + |) in + let _ := M.assign_local (| + "value" , + M.slice (| + M.get_field (| M.get_name (| globals, "evm" |), "return_data" |), + M.get_name (| globals, "return_data_start_position" |), + BinOp.add (| + M.get_name (| globals, "return_data_start_position" |), + M.get_name (| globals, "size" |) + |), + Constant.None_ + |) + |) in + let _ := M.call (| + M.get_name (| globals, "memory_write" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "memory" |); + M.get_name (| globals, "memory_start_index" |); + M.get_name (| globals, "value" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition extcodehash : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Returns the keccak256 hash of a contract’s bytecode + Parameters + ---------- + evm : + The current EVM frame. + " in + let _ := M.assign_local (| + "address" , + M.call (| + M.get_name (| globals, "to_address" |), + make_list [ + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.in_ (| + M.get_name (| globals, "address" |), + M.get_field (| M.get_name (| globals, "evm" |), "accessed_addresses" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_WARM_ACCESS" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "accessed_addresses" |), "add" |), + make_list [ + M.get_name (| globals, "address" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_COLD_ACCOUNT_ACCESS" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "account" , + M.call (| + M.get_name (| globals, "get_account" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "env" |), "state" |); + M.get_name (| globals, "address" |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, "account" |), + M.get_name (| globals, "EMPTY_ACCOUNT" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "codehash" , + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "codehash" , + M.call (| + M.get_field (| M.get_name (| globals, "U256" |), "from_be_bytes" |), + make_list [ + M.call (| + M.get_name (| globals, "keccak256" |), + make_list [ + M.get_field (| M.get_name (| globals, "account" |), "code" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + )) |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.get_name (| globals, "codehash" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition self_balance : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Pushes the balance of the current address to the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_FAST_STEP" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "balance" , + M.get_field (| M.call (| + M.get_name (| globals, "get_account" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "env" |), "state" |); + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "current_target" |) + ], + make_dict [] + |), "balance" |) + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.get_name (| globals, "balance" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition base_fee : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Pushes the base fee of the current block on to the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_BASE" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "env" |), "base_fee_per_gas" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). diff --git a/CoqOfPython/ethereum/shanghai/vm/instructions/keccak.v b/CoqOfPython/ethereum/shanghai/vm/instructions/keccak.v new file mode 100644 index 0000000..1565118 --- /dev/null +++ b/CoqOfPython/ethereum/shanghai/vm/instructions/keccak.v @@ -0,0 +1,188 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.shanghai.vm.instructions.keccak". + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) Keccak Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM keccak instructions. +". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". + +Axiom ethereum_crypto_hash_imports_keccak256 : + IsImported globals "ethereum.crypto.hash" "keccak256". + +Axiom ethereum_utils_numeric_imports_ceil32 : + IsImported globals "ethereum.utils.numeric" "ceil32". + +Axiom ethereum_shanghai_vm_imports_Evm : + IsImported globals "ethereum.shanghai.vm" "Evm". + +Axiom ethereum_shanghai_vm_gas_imports_GAS_KECCAK256 : + IsImported globals "ethereum.shanghai.vm.gas" "GAS_KECCAK256". +Axiom ethereum_shanghai_vm_gas_imports_GAS_KECCAK256_WORD : + IsImported globals "ethereum.shanghai.vm.gas" "GAS_KECCAK256_WORD". +Axiom ethereum_shanghai_vm_gas_imports_calculate_gas_extend_memory : + IsImported globals "ethereum.shanghai.vm.gas" "calculate_gas_extend_memory". +Axiom ethereum_shanghai_vm_gas_imports_charge_gas : + IsImported globals "ethereum.shanghai.vm.gas" "charge_gas". + +Axiom ethereum_shanghai_vm_memory_imports_memory_read_bytes : + IsImported globals "ethereum.shanghai.vm.memory" "memory_read_bytes". + +Axiom ethereum_shanghai_vm_stack_imports_pop : + IsImported globals "ethereum.shanghai.vm.stack" "pop". +Axiom ethereum_shanghai_vm_stack_imports_push : + IsImported globals "ethereum.shanghai.vm.stack" "push". + +Definition keccak : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Pushes to the stack the Keccak-256 hash of a region of memory. + + This also expands the memory, in case the memory is insufficient to + access the data's memory location. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "memory_start_index" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "size" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "words" , + BinOp.floor_div (| + M.call (| + M.get_name (| globals, "ceil32" |), + make_list [ + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.get_name (| globals, "size" |) + ], + make_dict [] + |) + ], + make_dict [] + |), + Constant.int 32 + |) + |) in + let _ := M.assign_local (| + "word_gas_cost" , + BinOp.mult (| + M.get_name (| globals, "GAS_KECCAK256_WORD" |), + M.get_name (| globals, "words" |) + |) + |) in + let _ := M.assign_local (| + "extend_memory" , + M.call (| + M.get_name (| globals, "calculate_gas_extend_memory" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "memory" |); + make_list [ + make_tuple [ M.get_name (| globals, "memory_start_index" |); M.get_name (| globals, "size" |) ] + ] + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + BinOp.add (| + BinOp.add (| + M.get_name (| globals, "GAS_KECCAK256" |), + M.get_name (| globals, "word_gas_cost" |) + |), + M.get_field (| M.get_name (| globals, "extend_memory" |), "cost" |) + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "memory" |), + BinOp.mult (| + Constant.bytes "00", + M.get_field (| M.get_name (| globals, "extend_memory" |), "expand_by" |) + |) + |) in + let _ := M.assign_local (| + "data" , + M.call (| + M.get_name (| globals, "memory_read_bytes" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "memory" |); + M.get_name (| globals, "memory_start_index" |); + M.get_name (| globals, "size" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "hash" , + M.call (| + M.get_name (| globals, "keccak256" |), + make_list [ + M.get_name (| globals, "data" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.call (| + M.get_field (| M.get_name (| globals, "U256" |), "from_be_bytes" |), + make_list [ + M.get_name (| globals, "hash" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). diff --git a/CoqOfPython/ethereum/shanghai/vm/instructions/log.v b/CoqOfPython/ethereum/shanghai/vm/instructions/log.v new file mode 100644 index 0000000..b7f272a --- /dev/null +++ b/CoqOfPython/ethereum/shanghai/vm/instructions/log.v @@ -0,0 +1,256 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.shanghai.vm.instructions.log". + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) Logging Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM logging instructions. +". + +Axiom functools_imports_partial : + IsImported globals "functools" "partial". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". + +Axiom ethereum_utils_ensure_imports_ensure : + IsImported globals "ethereum.utils.ensure" "ensure". + +Axiom ethereum_shanghai_blocks_imports_Log : + IsImported globals "ethereum.shanghai.blocks" "Log". + +Axiom ethereum_shanghai_vm_imports_Evm : + IsImported globals "ethereum.shanghai.vm" "Evm". + +Axiom ethereum_shanghai_vm_exceptions_imports_WriteInStaticContext : + IsImported globals "ethereum.shanghai.vm.exceptions" "WriteInStaticContext". + +Axiom ethereum_shanghai_vm_gas_imports_GAS_LOG : + IsImported globals "ethereum.shanghai.vm.gas" "GAS_LOG". +Axiom ethereum_shanghai_vm_gas_imports_GAS_LOG_DATA : + IsImported globals "ethereum.shanghai.vm.gas" "GAS_LOG_DATA". +Axiom ethereum_shanghai_vm_gas_imports_GAS_LOG_TOPIC : + IsImported globals "ethereum.shanghai.vm.gas" "GAS_LOG_TOPIC". +Axiom ethereum_shanghai_vm_gas_imports_calculate_gas_extend_memory : + IsImported globals "ethereum.shanghai.vm.gas" "calculate_gas_extend_memory". +Axiom ethereum_shanghai_vm_gas_imports_charge_gas : + IsImported globals "ethereum.shanghai.vm.gas" "charge_gas". + +Axiom ethereum_shanghai_vm_memory_imports_memory_read_bytes : + IsImported globals "ethereum.shanghai.vm.memory" "memory_read_bytes". + +Axiom ethereum_shanghai_vm_stack_imports_pop : + IsImported globals "ethereum.shanghai.vm.stack" "pop". + +Definition log_n : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm"; "num_topics" ] |) in + let _ := Constant.str " + Appends a log entry, having `num_topics` topics, to the evm logs. + + This will also expand the memory if the data (required by the log entry) + corresponding to the memory is not accessible. + + Parameters + ---------- + evm : + The current EVM frame. + num_topics : + The number of topics to be included in the log entry. + + " in + let _ := M.assign_local (| + "memory_start_index" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "size" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "topics" , + make_list [] + |) in + let _ := + M.for_ (| + M.get_name (| globals, "_" |), + M.call (| + M.get_name (| globals, "range" |), + make_list [ + M.get_name (| globals, "num_topics" |) + ], + make_dict [] + |), + ltac:(M.monadic ( + let _ := M.assign_local (| + "topic" , + M.call (| + M.get_field (| M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |), "to_be_bytes32" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_field (| M.get_name (| globals, "topics" |), "append" |), + make_list [ + M.get_name (| globals, "topic" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := M.assign_local (| + "extend_memory" , + M.call (| + M.get_name (| globals, "calculate_gas_extend_memory" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "memory" |); + make_list [ + make_tuple [ M.get_name (| globals, "memory_start_index" |); M.get_name (| globals, "size" |) ] + ] + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + BinOp.add (| + BinOp.add (| + BinOp.add (| + M.get_name (| globals, "GAS_LOG" |), + BinOp.mult (| + M.get_name (| globals, "GAS_LOG_DATA" |), + M.get_name (| globals, "size" |) + |) + |), + BinOp.mult (| + M.get_name (| globals, "GAS_LOG_TOPIC" |), + M.get_name (| globals, "num_topics" |) + |) + |), + M.get_field (| M.get_name (| globals, "extend_memory" |), "cost" |) + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "memory" |), + BinOp.mult (| + Constant.bytes "00", + M.get_field (| M.get_name (| globals, "extend_memory" |), "expand_by" |) + |) + |) in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + UnOp.not (| M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "is_static" |) |); + M.get_name (| globals, "WriteInStaticContext" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "log_entry" , + M.call (| + M.get_name (| globals, "Log" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, "evm" |), "logs" |), + BinOp.add (| + M.get_field (| M.get_name (| globals, "evm" |), "logs" |), + make_tuple [ M.get_name (| globals, "log_entry" |) ] + |) + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition log0 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "log_n" |) + ], + make_dict [] + |) +)). + +Definition log1 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "log_n" |) + ], + make_dict [] + |) +)). + +Definition log2 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "log_n" |) + ], + make_dict [] + |) +)). + +Definition log3 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "log_n" |) + ], + make_dict [] + |) +)). + +Definition log4 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "log_n" |) + ], + make_dict [] + |) +)). diff --git a/CoqOfPython/ethereum/shanghai/vm/instructions/memory.v b/CoqOfPython/ethereum/shanghai/vm/instructions/memory.v new file mode 100644 index 0000000..f71e369 --- /dev/null +++ b/CoqOfPython/ethereum/shanghai/vm/instructions/memory.v @@ -0,0 +1,393 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.shanghai.vm.instructions.memory". + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) Memory Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM Memory instructions. +". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_Bytes : + IsImported globals "ethereum.base_types" "Bytes". + +Axiom ethereum_shanghai_vm_imports_Evm : + IsImported globals "ethereum.shanghai.vm" "Evm". + +Axiom ethereum_shanghai_vm_gas_imports_GAS_BASE : + IsImported globals "ethereum.shanghai.vm.gas" "GAS_BASE". +Axiom ethereum_shanghai_vm_gas_imports_GAS_VERY_LOW : + IsImported globals "ethereum.shanghai.vm.gas" "GAS_VERY_LOW". +Axiom ethereum_shanghai_vm_gas_imports_calculate_gas_extend_memory : + IsImported globals "ethereum.shanghai.vm.gas" "calculate_gas_extend_memory". +Axiom ethereum_shanghai_vm_gas_imports_charge_gas : + IsImported globals "ethereum.shanghai.vm.gas" "charge_gas". + +Axiom ethereum_shanghai_vm_memory_imports_memory_read_bytes : + IsImported globals "ethereum.shanghai.vm.memory" "memory_read_bytes". +Axiom ethereum_shanghai_vm_memory_imports_memory_write : + IsImported globals "ethereum.shanghai.vm.memory" "memory_write". + +Axiom ethereum_shanghai_vm_stack_imports_pop : + IsImported globals "ethereum.shanghai.vm.stack" "pop". +Axiom ethereum_shanghai_vm_stack_imports_push : + IsImported globals "ethereum.shanghai.vm.stack" "push". + +Definition mstore : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Stores a word to memory. + This also expands the memory, if the memory is + insufficient to store the word. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "start_position" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "value" , + M.call (| + M.get_field (| M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |), "to_be_bytes32" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "extend_memory" , + M.call (| + M.get_name (| globals, "calculate_gas_extend_memory" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "memory" |); + make_list [ + make_tuple [ M.get_name (| globals, "start_position" |); M.call (| + M.get_name (| globals, "U256" |), + make_list [ + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_name (| globals, "value" |) + ], + make_dict [] + |) + ], + make_dict [] + |) ] + ] + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + BinOp.add (| + M.get_name (| globals, "GAS_VERY_LOW" |), + M.get_field (| M.get_name (| globals, "extend_memory" |), "cost" |) + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "memory" |), + BinOp.mult (| + Constant.bytes "00", + M.get_field (| M.get_name (| globals, "extend_memory" |), "expand_by" |) + |) + |) in + let _ := M.call (| + M.get_name (| globals, "memory_write" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "memory" |); + M.get_name (| globals, "start_position" |); + M.get_name (| globals, "value" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition mstore8 : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Stores a byte to memory. + This also expands the memory, if the memory is + insufficient to store the word. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "start_position" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "value" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "extend_memory" , + M.call (| + M.get_name (| globals, "calculate_gas_extend_memory" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "memory" |); + make_list [ + make_tuple [ M.get_name (| globals, "start_position" |); M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 1 + ], + make_dict [] + |) ] + ] + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + BinOp.add (| + M.get_name (| globals, "GAS_VERY_LOW" |), + M.get_field (| M.get_name (| globals, "extend_memory" |), "cost" |) + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "memory" |), + BinOp.mult (| + Constant.bytes "00", + M.get_field (| M.get_name (| globals, "extend_memory" |), "expand_by" |) + |) + |) in + let _ := M.assign_local (| + "normalized_bytes_value" , + M.call (| + M.get_name (| globals, "Bytes" |), + make_list [ + make_list [ + BinOp.bit_and (| + M.get_name (| globals, "value" |), + Constant.int 255 + |) + ] + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "memory_write" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "memory" |); + M.get_name (| globals, "start_position" |); + M.get_name (| globals, "normalized_bytes_value" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition mload : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Load word from memory. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "start_position" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "extend_memory" , + M.call (| + M.get_name (| globals, "calculate_gas_extend_memory" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "memory" |); + make_list [ + make_tuple [ M.get_name (| globals, "start_position" |); M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 32 + ], + make_dict [] + |) ] + ] + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + BinOp.add (| + M.get_name (| globals, "GAS_VERY_LOW" |), + M.get_field (| M.get_name (| globals, "extend_memory" |), "cost" |) + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "memory" |), + BinOp.mult (| + Constant.bytes "00", + M.get_field (| M.get_name (| globals, "extend_memory" |), "expand_by" |) + |) + |) in + let _ := M.assign_local (| + "value" , + M.call (| + M.get_field (| M.get_name (| globals, "U256" |), "from_be_bytes" |), + make_list [ + M.call (| + M.get_name (| globals, "memory_read_bytes" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "memory" |); + M.get_name (| globals, "start_position" |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 32 + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.get_name (| globals, "value" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition msize : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Push the size of active memory in bytes onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_BASE" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "memory" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). diff --git a/CoqOfPython/ethereum/shanghai/vm/instructions/stack.v b/CoqOfPython/ethereum/shanghai/vm/instructions/stack.v new file mode 100644 index 0000000..8c4b767 --- /dev/null +++ b/CoqOfPython/ethereum/shanghai/vm/instructions/stack.v @@ -0,0 +1,979 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.shanghai.vm.instructions.stack". + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) Stack Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM stack related instructions. +". + +Axiom functools_imports_partial : + IsImported globals "functools" "partial". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". + +Axiom ethereum_utils_ensure_imports_ensure : + IsImported globals "ethereum.utils.ensure" "ensure". + +Axiom ethereum_shanghai_vm_imports_Evm : + IsImported globals "ethereum.shanghai.vm" "Evm". +Axiom ethereum_shanghai_vm_imports_stack : + IsImported globals "ethereum.shanghai.vm" "stack". + +Axiom ethereum_shanghai_vm_exceptions_imports_StackUnderflowError : + IsImported globals "ethereum.shanghai.vm.exceptions" "StackUnderflowError". + +Axiom ethereum_shanghai_vm_gas_imports_GAS_BASE : + IsImported globals "ethereum.shanghai.vm.gas" "GAS_BASE". +Axiom ethereum_shanghai_vm_gas_imports_GAS_VERY_LOW : + IsImported globals "ethereum.shanghai.vm.gas" "GAS_VERY_LOW". +Axiom ethereum_shanghai_vm_gas_imports_charge_gas : + IsImported globals "ethereum.shanghai.vm.gas" "charge_gas". + +Axiom ethereum_shanghai_vm_memory_imports_buffer_read : + IsImported globals "ethereum.shanghai.vm.memory" "buffer_read". + +Definition pop : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Remove item from stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.call (| + M.get_field (| M.get_name (| globals, "stack" |), "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_BASE" |) + ], + make_dict [] + |) in + let _ := M.pass (| |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition push_n : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm"; "num_bytes" ] |) in + let _ := Constant.str " + Pushes a N-byte immediate onto the stack. Push zero if num_bytes is zero. + + Parameters + ---------- + evm : + The current EVM frame. + + num_bytes : + The number of immediate bytes to be read from the code and pushed to + the stack. Push zero if num_bytes is zero. + + " in + let _ := M.pass (| |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, "num_bytes" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_BASE" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_VERY_LOW" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "data_to_push" , + M.call (| + M.get_field (| M.get_name (| globals, "U256" |), "from_be_bytes" |), + make_list [ + M.call (| + M.get_name (| globals, "buffer_read" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "code" |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + BinOp.add (| + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) + ], + make_dict [] + |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + M.get_name (| globals, "num_bytes" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_field (| M.get_name (| globals, "stack" |), "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.get_name (| globals, "data_to_push" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + BinOp.add (| + Constant.int 1, + M.get_name (| globals, "num_bytes" |) + |) + |) in + M.pure Constant.None_)). + +Definition dup_n : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm"; "item_number" ] |) in + let _ := Constant.str " + Duplicate the Nth stack item (from top of the stack) to the top of stack. + + Parameters + ---------- + evm : + The current EVM frame. + + item_number : + The stack item number (0-indexed from top of stack) to be duplicated + to the top of stack. + + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_VERY_LOW" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + Compare.lt (| + M.get_name (| globals, "item_number" |), + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |); + M.get_name (| globals, "StackUnderflowError" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "data_to_duplicate" , + M.get_subscript (| + M.get_field (| M.get_name (| globals, "evm" |), "stack" |), + BinOp.sub (| + BinOp.sub (| + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |), + Constant.int 1 + |), + M.get_name (| globals, "item_number" |) + |) + |) + |) in + let _ := M.call (| + M.get_field (| M.get_name (| globals, "stack" |), "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.get_name (| globals, "data_to_duplicate" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition swap_n : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm"; "item_number" ] |) in + let _ := Constant.str " + Swap the top and the `item_number` element of the stack, where + the top of the stack is position zero. + + If `item_number` is zero, this function does nothing (which should not be + possible, since there is no `SWAP0` instruction). + + Parameters + ---------- + evm : + The current EVM frame. + + item_number : + The stack item number (0-indexed from top of stack) to be swapped + with the top of stack element. + + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_VERY_LOW" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + Compare.lt (| + M.get_name (| globals, "item_number" |), + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |); + M.get_name (| globals, "StackUnderflowError" |) + ], + make_dict [] + |) in + let _ := M.assign (| + make_tuple [ M.get_subscript (| + M.get_field (| M.get_name (| globals, "evm" |), "stack" |), + UnOp.sub (| Constant.int 1 |) + |); M.get_subscript (| + M.get_field (| M.get_name (| globals, "evm" |), "stack" |), + BinOp.sub (| + UnOp.sub (| Constant.int 1 |), + M.get_name (| globals, "item_number" |) + |) + |) ], + make_tuple [ M.get_subscript (| + M.get_field (| M.get_name (| globals, "evm" |), "stack" |), + BinOp.sub (| + UnOp.sub (| Constant.int 1 |), + M.get_name (| globals, "item_number" |) + |) + |); M.get_subscript (| + M.get_field (| M.get_name (| globals, "evm" |), "stack" |), + UnOp.sub (| Constant.int 1 |) + |) ] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition push0 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push1 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push2 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push3 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push4 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push5 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push6 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push7 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push8 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push9 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push10 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push11 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push12 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push13 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push14 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push15 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push16 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push17 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push18 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push19 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push20 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push21 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push22 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push23 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push24 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push25 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push26 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push27 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push28 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push29 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push30 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push31 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push32 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "push_n" |) + ], + make_dict [] + |) +)). + +Definition dup1 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "dup_n" |) + ], + make_dict [] + |) +)). + +Definition dup2 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "dup_n" |) + ], + make_dict [] + |) +)). + +Definition dup3 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "dup_n" |) + ], + make_dict [] + |) +)). + +Definition dup4 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "dup_n" |) + ], + make_dict [] + |) +)). + +Definition dup5 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "dup_n" |) + ], + make_dict [] + |) +)). + +Definition dup6 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "dup_n" |) + ], + make_dict [] + |) +)). + +Definition dup7 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "dup_n" |) + ], + make_dict [] + |) +)). + +Definition dup8 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "dup_n" |) + ], + make_dict [] + |) +)). + +Definition dup9 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "dup_n" |) + ], + make_dict [] + |) +)). + +Definition dup10 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "dup_n" |) + ], + make_dict [] + |) +)). + +Definition dup11 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "dup_n" |) + ], + make_dict [] + |) +)). + +Definition dup12 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "dup_n" |) + ], + make_dict [] + |) +)). + +Definition dup13 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "dup_n" |) + ], + make_dict [] + |) +)). + +Definition dup14 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "dup_n" |) + ], + make_dict [] + |) +)). + +Definition dup15 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "dup_n" |) + ], + make_dict [] + |) +)). + +Definition dup16 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "dup_n" |) + ], + make_dict [] + |) +)). + +Definition swap1 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "swap_n" |) + ], + make_dict [] + |) +)). + +Definition swap2 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "swap_n" |) + ], + make_dict [] + |) +)). + +Definition swap3 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "swap_n" |) + ], + make_dict [] + |) +)). + +Definition swap4 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "swap_n" |) + ], + make_dict [] + |) +)). + +Definition swap5 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "swap_n" |) + ], + make_dict [] + |) +)). + +Definition swap6 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "swap_n" |) + ], + make_dict [] + |) +)). + +Definition swap7 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "swap_n" |) + ], + make_dict [] + |) +)). + +Definition swap8 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "swap_n" |) + ], + make_dict [] + |) +)). + +Definition swap9 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "swap_n" |) + ], + make_dict [] + |) +)). + +Definition swap10 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "swap_n" |) + ], + make_dict [] + |) +)). + +Definition swap11 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "swap_n" |) + ], + make_dict [] + |) +)). + +Definition swap12 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "swap_n" |) + ], + make_dict [] + |) +)). + +Definition swap13 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "swap_n" |) + ], + make_dict [] + |) +)). + +Definition swap14 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "swap_n" |) + ], + make_dict [] + |) +)). + +Definition swap15 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "swap_n" |) + ], + make_dict [] + |) +)). + +Definition swap16 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "swap_n" |) + ], + make_dict [] + |) +)). diff --git a/CoqOfPython/ethereum/shanghai/vm/instructions/storage.v b/CoqOfPython/ethereum/shanghai/vm/instructions/storage.v new file mode 100644 index 0000000..a05890f --- /dev/null +++ b/CoqOfPython/ethereum/shanghai/vm/instructions/storage.v @@ -0,0 +1,491 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.shanghai.vm.instructions.storage". + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) Storage Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM storage related instructions. +". + +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". + +Axiom ethereum_utils_ensure_imports_ensure : + IsImported globals "ethereum.utils.ensure" "ensure". + +Axiom ethereum_shanghai_state_imports_get_storage : + IsImported globals "ethereum.shanghai.state" "get_storage". +Axiom ethereum_shanghai_state_imports_get_storage_original : + IsImported globals "ethereum.shanghai.state" "get_storage_original". +Axiom ethereum_shanghai_state_imports_set_storage : + IsImported globals "ethereum.shanghai.state" "set_storage". + +Axiom ethereum_shanghai_vm_imports_Evm : + IsImported globals "ethereum.shanghai.vm" "Evm". + +Axiom ethereum_shanghai_vm_exceptions_imports_OutOfGasError : + IsImported globals "ethereum.shanghai.vm.exceptions" "OutOfGasError". +Axiom ethereum_shanghai_vm_exceptions_imports_WriteInStaticContext : + IsImported globals "ethereum.shanghai.vm.exceptions" "WriteInStaticContext". + +Axiom ethereum_shanghai_vm_gas_imports_GAS_CALL_STIPEND : + IsImported globals "ethereum.shanghai.vm.gas" "GAS_CALL_STIPEND". +Axiom ethereum_shanghai_vm_gas_imports_GAS_COLD_SLOAD : + IsImported globals "ethereum.shanghai.vm.gas" "GAS_COLD_SLOAD". +Axiom ethereum_shanghai_vm_gas_imports_GAS_STORAGE_CLEAR_REFUND : + IsImported globals "ethereum.shanghai.vm.gas" "GAS_STORAGE_CLEAR_REFUND". +Axiom ethereum_shanghai_vm_gas_imports_GAS_STORAGE_SET : + IsImported globals "ethereum.shanghai.vm.gas" "GAS_STORAGE_SET". +Axiom ethereum_shanghai_vm_gas_imports_GAS_STORAGE_UPDATE : + IsImported globals "ethereum.shanghai.vm.gas" "GAS_STORAGE_UPDATE". +Axiom ethereum_shanghai_vm_gas_imports_GAS_WARM_ACCESS : + IsImported globals "ethereum.shanghai.vm.gas" "GAS_WARM_ACCESS". +Axiom ethereum_shanghai_vm_gas_imports_charge_gas : + IsImported globals "ethereum.shanghai.vm.gas" "charge_gas". + +Axiom ethereum_shanghai_vm_stack_imports_pop : + IsImported globals "ethereum.shanghai.vm.stack" "pop". +Axiom ethereum_shanghai_vm_stack_imports_push : + IsImported globals "ethereum.shanghai.vm.stack" "push". + +Definition sload : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Loads to the stack, the value corresponding to a certain key from the + storage of the current account. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "key" , + M.call (| + M.get_field (| M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |), "to_be_bytes32" |), + make_list [], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.in_ (| + make_tuple [ M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "current_target" |); M.get_name (| globals, "key" |) ], + M.get_field (| M.get_name (| globals, "evm" |), "accessed_storage_keys" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_WARM_ACCESS" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "accessed_storage_keys" |), "add" |), + make_list [ + make_tuple [ M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "current_target" |); M.get_name (| globals, "key" |) ] + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_COLD_SLOAD" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "value" , + M.call (| + M.get_name (| globals, "get_storage" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "env" |), "state" |); + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "current_target" |); + M.get_name (| globals, "key" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.get_name (| globals, "value" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition sstore : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Stores a value at a certain key in the current context's storage. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "key" , + M.call (| + M.get_field (| M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |), "to_be_bytes32" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "new_value" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + Compare.gt (| + M.get_field (| M.get_name (| globals, "evm" |), "gas_left" |), + M.get_name (| globals, "GAS_CALL_STIPEND" |) + |); + M.get_name (| globals, "OutOfGasError" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "original_value" , + M.call (| + M.get_name (| globals, "get_storage_original" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "env" |), "state" |); + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "current_target" |); + M.get_name (| globals, "key" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "current_value" , + M.call (| + M.get_name (| globals, "get_storage" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "env" |), "state" |); + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "current_target" |); + M.get_name (| globals, "key" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "gas_cost" , + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.not_in (| + make_tuple [ M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "current_target" |); M.get_name (| globals, "key" |) ], + M.get_field (| M.get_name (| globals, "evm" |), "accessed_storage_keys" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "accessed_storage_keys" |), "add" |), + make_list [ + make_tuple [ M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "current_target" |); M.get_name (| globals, "key" |) ] + ], + make_dict [] + |) in + let _ := M.assign_op_local (| + BinOp.add, + "gas_cost", + M.get_name (| globals, "GAS_COLD_SLOAD" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + BoolOp.and (| + Compare.eq (| + M.get_name (| globals, "original_value" |), + M.get_name (| globals, "current_value" |) + |), + ltac:(M.monadic ( + Compare.not_eq (| + M.get_name (| globals, "current_value" |), + M.get_name (| globals, "new_value" |) + |) + )) + |), + (* then *) + ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, "original_value" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_op_local (| + BinOp.add, + "gas_cost", + M.get_name (| globals, "GAS_STORAGE_SET" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_op_local (| + BinOp.add, + "gas_cost", + BinOp.sub (| + M.get_name (| globals, "GAS_STORAGE_UPDATE" |), + M.get_name (| globals, "GAS_COLD_SLOAD" |) + |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_op_local (| + BinOp.add, + "gas_cost", + M.get_name (| globals, "GAS_WARM_ACCESS" |) + |) in + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + Compare.not_eq (| + M.get_name (| globals, "current_value" |), + M.get_name (| globals, "new_value" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + BoolOp.and (| + Compare.not_eq (| + M.get_name (| globals, "original_value" |), + Constant.int 0 + |), + ltac:(M.monadic ( + BoolOp.and (| + Compare.not_eq (| + M.get_name (| globals, "current_value" |), + Constant.int 0 + |), + ltac:(M.monadic ( + Compare.eq (| + M.get_name (| globals, "new_value" |), + Constant.int 0 + |) + )) + |) + )) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "refund_counter" |), + M.call (| + M.get_name (| globals, "int" |), + make_list [ + M.get_name (| globals, "GAS_STORAGE_CLEAR_REFUND" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + BoolOp.and (| + Compare.not_eq (| + M.get_name (| globals, "original_value" |), + Constant.int 0 + |), + ltac:(M.monadic ( + Compare.eq (| + M.get_name (| globals, "current_value" |), + Constant.int 0 + |) + )) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_op (| + BinOp.sub, + M.get_field (| M.get_name (| globals, "evm" |), "refund_counter" |), + M.call (| + M.get_name (| globals, "int" |), + make_list [ + M.get_name (| globals, "GAS_STORAGE_CLEAR_REFUND" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, "original_value" |), + M.get_name (| globals, "new_value" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, "original_value" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "refund_counter" |), + M.call (| + M.get_name (| globals, "int" |), + make_list [ + BinOp.sub (| + M.get_name (| globals, "GAS_STORAGE_SET" |), + M.get_name (| globals, "GAS_WARM_ACCESS" |) + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "refund_counter" |), + M.call (| + M.get_name (| globals, "int" |), + make_list [ + BinOp.sub (| + BinOp.sub (| + M.get_name (| globals, "GAS_STORAGE_UPDATE" |), + M.get_name (| globals, "GAS_COLD_SLOAD" |) + |), + M.get_name (| globals, "GAS_WARM_ACCESS" |) + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "gas_cost" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + UnOp.not (| M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "is_static" |) |); + M.get_name (| globals, "WriteInStaticContext" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "set_storage" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "env" |), "state" |); + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "current_target" |); + M.get_name (| globals, "key" |); + M.get_name (| globals, "new_value" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). diff --git a/CoqOfPython/ethereum/shanghai/vm/instructions/system.v b/CoqOfPython/ethereum/shanghai/vm/instructions/system.v new file mode 100644 index 0000000..4fc7b71 --- /dev/null +++ b/CoqOfPython/ethereum/shanghai/vm/instructions/system.v @@ -0,0 +1,2279 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.shanghai.vm.instructions.system". + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) System Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM system related instructions. +". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_Bytes0 : + IsImported globals "ethereum.base_types" "Bytes0". +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". + +Axiom ethereum_utils_ensure_imports_ensure : + IsImported globals "ethereum.utils.ensure" "ensure". + +Axiom ethereum_utils_numeric_imports_ceil32 : + IsImported globals "ethereum.utils.numeric" "ceil32". + +Axiom ethereum_shanghai_fork_types_imports_Address : + IsImported globals "ethereum.shanghai.fork_types" "Address". + +Axiom ethereum_shanghai_state_imports_account_exists_and_is_empty : + IsImported globals "ethereum.shanghai.state" "account_exists_and_is_empty". +Axiom ethereum_shanghai_state_imports_account_has_code_or_nonce : + IsImported globals "ethereum.shanghai.state" "account_has_code_or_nonce". +Axiom ethereum_shanghai_state_imports_get_account : + IsImported globals "ethereum.shanghai.state" "get_account". +Axiom ethereum_shanghai_state_imports_increment_nonce : + IsImported globals "ethereum.shanghai.state" "increment_nonce". +Axiom ethereum_shanghai_state_imports_is_account_alive : + IsImported globals "ethereum.shanghai.state" "is_account_alive". +Axiom ethereum_shanghai_state_imports_set_account_balance : + IsImported globals "ethereum.shanghai.state" "set_account_balance". + +Axiom ethereum_shanghai_utils_address_imports_compute_contract_address : + IsImported globals "ethereum.shanghai.utils.address" "compute_contract_address". +Axiom ethereum_shanghai_utils_address_imports_compute_create2_contract_address : + IsImported globals "ethereum.shanghai.utils.address" "compute_create2_contract_address". +Axiom ethereum_shanghai_utils_address_imports_to_address : + IsImported globals "ethereum.shanghai.utils.address" "to_address". + +Axiom ethereum_shanghai_vm_imports_Evm : + IsImported globals "ethereum.shanghai.vm" "Evm". +Axiom ethereum_shanghai_vm_imports_Message : + IsImported globals "ethereum.shanghai.vm" "Message". +Axiom ethereum_shanghai_vm_imports_incorporate_child_on_error : + IsImported globals "ethereum.shanghai.vm" "incorporate_child_on_error". +Axiom ethereum_shanghai_vm_imports_incorporate_child_on_success : + IsImported globals "ethereum.shanghai.vm" "incorporate_child_on_success". + +Axiom ethereum_shanghai_vm_exceptions_imports_OutOfGasError : + IsImported globals "ethereum.shanghai.vm.exceptions" "OutOfGasError". +Axiom ethereum_shanghai_vm_exceptions_imports_Revert : + IsImported globals "ethereum.shanghai.vm.exceptions" "Revert". +Axiom ethereum_shanghai_vm_exceptions_imports_WriteInStaticContext : + IsImported globals "ethereum.shanghai.vm.exceptions" "WriteInStaticContext". + +Axiom ethereum_shanghai_vm_gas_imports_GAS_CALL_VALUE : + IsImported globals "ethereum.shanghai.vm.gas" "GAS_CALL_VALUE". +Axiom ethereum_shanghai_vm_gas_imports_GAS_COLD_ACCOUNT_ACCESS : + IsImported globals "ethereum.shanghai.vm.gas" "GAS_COLD_ACCOUNT_ACCESS". +Axiom ethereum_shanghai_vm_gas_imports_GAS_CREATE : + IsImported globals "ethereum.shanghai.vm.gas" "GAS_CREATE". +Axiom ethereum_shanghai_vm_gas_imports_GAS_KECCAK256_WORD : + IsImported globals "ethereum.shanghai.vm.gas" "GAS_KECCAK256_WORD". +Axiom ethereum_shanghai_vm_gas_imports_GAS_NEW_ACCOUNT : + IsImported globals "ethereum.shanghai.vm.gas" "GAS_NEW_ACCOUNT". +Axiom ethereum_shanghai_vm_gas_imports_GAS_SELF_DESTRUCT : + IsImported globals "ethereum.shanghai.vm.gas" "GAS_SELF_DESTRUCT". +Axiom ethereum_shanghai_vm_gas_imports_GAS_SELF_DESTRUCT_NEW_ACCOUNT : + IsImported globals "ethereum.shanghai.vm.gas" "GAS_SELF_DESTRUCT_NEW_ACCOUNT". +Axiom ethereum_shanghai_vm_gas_imports_GAS_WARM_ACCESS : + IsImported globals "ethereum.shanghai.vm.gas" "GAS_WARM_ACCESS". +Axiom ethereum_shanghai_vm_gas_imports_GAS_ZERO : + IsImported globals "ethereum.shanghai.vm.gas" "GAS_ZERO". +Axiom ethereum_shanghai_vm_gas_imports_calculate_gas_extend_memory : + IsImported globals "ethereum.shanghai.vm.gas" "calculate_gas_extend_memory". +Axiom ethereum_shanghai_vm_gas_imports_calculate_message_call_gas : + IsImported globals "ethereum.shanghai.vm.gas" "calculate_message_call_gas". +Axiom ethereum_shanghai_vm_gas_imports_charge_gas : + IsImported globals "ethereum.shanghai.vm.gas" "charge_gas". +Axiom ethereum_shanghai_vm_gas_imports_init_code_cost : + IsImported globals "ethereum.shanghai.vm.gas" "init_code_cost". +Axiom ethereum_shanghai_vm_gas_imports_max_message_call_gas : + IsImported globals "ethereum.shanghai.vm.gas" "max_message_call_gas". + +Axiom ethereum_shanghai_vm_memory_imports_memory_read_bytes : + IsImported globals "ethereum.shanghai.vm.memory" "memory_read_bytes". +Axiom ethereum_shanghai_vm_memory_imports_memory_write : + IsImported globals "ethereum.shanghai.vm.memory" "memory_write". + +Axiom ethereum_shanghai_vm_stack_imports_pop : + IsImported globals "ethereum.shanghai.vm.stack" "pop". +Axiom ethereum_shanghai_vm_stack_imports_push : + IsImported globals "ethereum.shanghai.vm.stack" "push". + +Definition generic_create : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm"; "endowment"; "contract_address"; "memory_start_position"; "memory_size"; "init_code_gas" ] |) in + let _ := Constant.str " + Core logic used by the `CREATE*` family of opcodes. + " in +(* At stmt: unsupported node type: ImportFrom *) + let _ := M.assign_local (| + "call_data" , + M.call (| + M.get_name (| globals, "memory_read_bytes" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "memory" |); + M.get_name (| globals, "memory_start_position" |); + M.get_name (| globals, "memory_size" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + Compare.lt_e (| + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_name (| globals, "call_data" |) + ], + make_dict [] + |), + BinOp.mult (| + Constant.int 2, + M.get_name (| globals, "MAX_CODE_SIZE" |) + |) + |); + M.get_name (| globals, "OutOfGasError" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "accessed_addresses" |), "add" |), + make_list [ + M.get_name (| globals, "contract_address" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "create_message_gas" , + M.call (| + M.get_name (| globals, "max_message_call_gas" |), + make_list [ + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "gas_left" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_op (| + BinOp.sub, + M.get_field (| M.get_name (| globals, "evm" |), "gas_left" |), + M.get_name (| globals, "create_message_gas" |) + |) in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + UnOp.not (| M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "is_static" |) |); + M.get_name (| globals, "WriteInStaticContext" |) + ], + make_dict [] + |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, "evm" |), "return_data" |), + Constant.bytes "" + |) in + let _ := M.assign_local (| + "sender_address" , + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "current_target" |) + |) in + let _ := M.assign_local (| + "sender" , + M.call (| + M.get_name (| globals, "get_account" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "env" |), "state" |); + M.get_name (| globals, "sender_address" |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + BoolOp.or (| + Compare.lt (| + M.get_field (| M.get_name (| globals, "sender" |), "balance" |), + M.get_name (| globals, "endowment" |) + |), + ltac:(M.monadic ( + BoolOp.or (| + Compare.eq (| + M.get_field (| M.get_name (| globals, "sender" |), "nonce" |), + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + BinOp.sub (| + BinOp.pow (| + Constant.int 2, + Constant.int 64 + |), + Constant.int 1 + |) + ], + make_dict [] + |) + |), + ltac:(M.monadic ( + Compare.gt (| + BinOp.add (| + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "depth" |), + Constant.int 1 + |), + M.get_name (| globals, "STACK_DEPTH_LIMIT" |) + |) + )) + |) + )) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "gas_left" |), + M.get_name (| globals, "create_message_gas" |) + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.return_ (| + Constant.None_ + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, "account_has_code_or_nonce" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "env" |), "state" |); + M.get_name (| globals, "contract_address" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, "increment_nonce" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "env" |), "state" |); + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "current_target" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.return_ (| + Constant.None_ + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.call (| + M.get_name (| globals, "increment_nonce" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "env" |), "state" |); + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "current_target" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "child_message" , + M.call (| + M.get_name (| globals, "Message" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "child_evm" , + M.call (| + M.get_name (| globals, "process_create_message" |), + make_list [ + M.get_name (| globals, "child_message" |); + M.get_field (| M.get_name (| globals, "evm" |), "env" |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + M.get_field (| M.get_name (| globals, "child_evm" |), "error" |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, "incorporate_child_on_error" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "child_evm" |) + ], + make_dict [] + |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, "evm" |), "return_data" |), + M.get_field (| M.get_name (| globals, "child_evm" |), "output" |) + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + ], + make_dict [] + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, "incorporate_child_on_success" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "child_evm" |) + ], + make_dict [] + |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, "evm" |), "return_data" |), + Constant.bytes "" + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.call (| + M.get_field (| M.get_name (| globals, "U256" |), "from_be_bytes" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "child_evm" |), "message" |), "current_target" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_)). + +Definition create : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Creates a new account with associated code. + + Parameters + ---------- + evm : + The current EVM frame. + " in + let _ := M.assign_local (| + "endowment" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_start_position" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_size" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "extend_memory" , + M.call (| + M.get_name (| globals, "calculate_gas_extend_memory" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "memory" |); + make_list [ + make_tuple [ M.get_name (| globals, "memory_start_position" |); M.get_name (| globals, "memory_size" |) ] + ] + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "init_code_gas" , + M.call (| + M.get_name (| globals, "init_code_cost" |), + make_list [ + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.get_name (| globals, "memory_size" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + BinOp.add (| + BinOp.add (| + M.get_name (| globals, "GAS_CREATE" |), + M.get_field (| M.get_name (| globals, "extend_memory" |), "cost" |) + |), + M.get_name (| globals, "init_code_gas" |) + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "memory" |), + BinOp.mult (| + Constant.bytes "00", + M.get_field (| M.get_name (| globals, "extend_memory" |), "expand_by" |) + |) + |) in + let _ := M.assign_local (| + "contract_address" , + M.call (| + M.get_name (| globals, "compute_contract_address" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "current_target" |); + M.get_field (| M.call (| + M.get_name (| globals, "get_account" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "env" |), "state" |); + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "current_target" |) + ], + make_dict [] + |), "nonce" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "generic_create" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "endowment" |); + M.get_name (| globals, "contract_address" |); + M.get_name (| globals, "memory_start_position" |); + M.get_name (| globals, "memory_size" |); + M.get_name (| globals, "init_code_gas" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition create2 : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Creates a new account with associated code. + + It's similar to CREATE opcode except that the address of new account + depends on the init_code instead of the nonce of sender. + + Parameters + ---------- + evm : + The current EVM frame. + " in + let _ := M.assign_local (| + "endowment" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_start_position" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_size" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "salt" , + M.call (| + M.get_field (| M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |), "to_be_bytes32" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "extend_memory" , + M.call (| + M.get_name (| globals, "calculate_gas_extend_memory" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "memory" |); + make_list [ + make_tuple [ M.get_name (| globals, "memory_start_position" |); M.get_name (| globals, "memory_size" |) ] + ] + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "call_data_words" , + BinOp.floor_div (| + M.call (| + M.get_name (| globals, "ceil32" |), + make_list [ + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.get_name (| globals, "memory_size" |) + ], + make_dict [] + |) + ], + make_dict [] + |), + Constant.int 32 + |) + |) in + let _ := M.assign_local (| + "init_code_gas" , + M.call (| + M.get_name (| globals, "init_code_cost" |), + make_list [ + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.get_name (| globals, "memory_size" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + BinOp.add (| + BinOp.add (| + BinOp.add (| + M.get_name (| globals, "GAS_CREATE" |), + BinOp.mult (| + M.get_name (| globals, "GAS_KECCAK256_WORD" |), + M.get_name (| globals, "call_data_words" |) + |) + |), + M.get_field (| M.get_name (| globals, "extend_memory" |), "cost" |) + |), + M.get_name (| globals, "init_code_gas" |) + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "memory" |), + BinOp.mult (| + Constant.bytes "00", + M.get_field (| M.get_name (| globals, "extend_memory" |), "expand_by" |) + |) + |) in + let _ := M.assign_local (| + "contract_address" , + M.call (| + M.get_name (| globals, "compute_create2_contract_address" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "current_target" |); + M.get_name (| globals, "salt" |); + M.call (| + M.get_name (| globals, "memory_read_bytes" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "memory" |); + M.get_name (| globals, "memory_start_position" |); + M.get_name (| globals, "memory_size" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "generic_create" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "endowment" |); + M.get_name (| globals, "contract_address" |); + M.get_name (| globals, "memory_start_position" |); + M.get_name (| globals, "memory_size" |); + M.get_name (| globals, "init_code_gas" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition return_ : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Halts execution returning output data. + + Parameters + ---------- + evm : + The current EVM frame. + " in + let _ := M.assign_local (| + "memory_start_position" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_size" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "extend_memory" , + M.call (| + M.get_name (| globals, "calculate_gas_extend_memory" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "memory" |); + make_list [ + make_tuple [ M.get_name (| globals, "memory_start_position" |); M.get_name (| globals, "memory_size" |) ] + ] + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + BinOp.add (| + M.get_name (| globals, "GAS_ZERO" |), + M.get_field (| M.get_name (| globals, "extend_memory" |), "cost" |) + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "memory" |), + BinOp.mult (| + Constant.bytes "00", + M.get_field (| M.get_name (| globals, "extend_memory" |), "expand_by" |) + |) + |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, "evm" |), "output" |), + M.call (| + M.get_name (| globals, "memory_read_bytes" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "memory" |); + M.get_name (| globals, "memory_start_position" |); + M.get_name (| globals, "memory_size" |) + ], + make_dict [] + |) + |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, "evm" |), "running" |), + Constant.bool false + |) in + let _ := M.pass (| |) in + M.pure Constant.None_)). + +Definition generic_call : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm"; "gas"; "value"; "caller"; "to"; "code_address"; "should_transfer_value"; "is_staticcall"; "memory_input_start_position"; "memory_input_size"; "memory_output_start_position"; "memory_output_size" ] |) in + let _ := Constant.str " + Perform the core logic of the `CALL*` family of opcodes. + " in +(* At stmt: unsupported node type: ImportFrom *) + let _ := M.assign (| + M.get_field (| M.get_name (| globals, "evm" |), "return_data" |), + Constant.bytes "" + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.gt (| + BinOp.add (| + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "depth" |), + Constant.int 1 + |), + M.get_name (| globals, "STACK_DEPTH_LIMIT" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "gas_left" |), + M.get_name (| globals, "gas" |) + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.return_ (| + Constant.None_ + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "call_data" , + M.call (| + M.get_name (| globals, "memory_read_bytes" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "memory" |); + M.get_name (| globals, "memory_input_start_position" |); + M.get_name (| globals, "memory_input_size" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "code" , + M.get_field (| M.call (| + M.get_name (| globals, "get_account" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "env" |), "state" |); + M.get_name (| globals, "code_address" |) + ], + make_dict [] + |), "code" |) + |) in + let _ := M.assign_local (| + "child_message" , + M.call (| + M.get_name (| globals, "Message" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "child_evm" , + M.call (| + M.get_name (| globals, "process_message" |), + make_list [ + M.get_name (| globals, "child_message" |); + M.get_field (| M.get_name (| globals, "evm" |), "env" |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + M.get_field (| M.get_name (| globals, "child_evm" |), "error" |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, "incorporate_child_on_error" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "child_evm" |) + ], + make_dict [] + |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, "evm" |), "return_data" |), + M.get_field (| M.get_name (| globals, "child_evm" |), "output" |) + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + ], + make_dict [] + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, "incorporate_child_on_success" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "child_evm" |) + ], + make_dict [] + |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, "evm" |), "return_data" |), + M.get_field (| M.get_name (| globals, "child_evm" |), "output" |) + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 1 + ], + make_dict [] + |) + ], + make_dict [] + |) in + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "actual_output_size" , + M.call (| + M.get_name (| globals, "min" |), + make_list [ + M.get_name (| globals, "memory_output_size" |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_field (| M.get_name (| globals, "child_evm" |), "output" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "memory_write" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "memory" |); + M.get_name (| globals, "memory_output_start_position" |); + M.slice (| + M.get_field (| M.get_name (| globals, "child_evm" |), "output" |), + Constant.None_, + M.get_name (| globals, "actual_output_size" |), + Constant.None_ + |) + ], + make_dict [] + |) in + M.pure Constant.None_)). + +Definition call : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Message-call into an account. + + Parameters + ---------- + evm : + The current EVM frame. + " in + let _ := M.assign_local (| + "gas" , + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "to" , + M.call (| + M.get_name (| globals, "to_address" |), + make_list [ + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "value" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_input_start_position" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_input_size" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_output_start_position" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_output_size" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "extend_memory" , + M.call (| + M.get_name (| globals, "calculate_gas_extend_memory" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "memory" |); + make_list [ + make_tuple [ M.get_name (| globals, "memory_input_start_position" |); M.get_name (| globals, "memory_input_size" |) ]; + make_tuple [ M.get_name (| globals, "memory_output_start_position" |); M.get_name (| globals, "memory_output_size" |) ] + ] + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.in_ (| + M.get_name (| globals, "to" |), + M.get_field (| M.get_name (| globals, "evm" |), "accessed_addresses" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "access_gas_cost" , + M.get_name (| globals, "GAS_WARM_ACCESS" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "accessed_addresses" |), "add" |), + make_list [ + M.get_name (| globals, "to" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "access_gas_cost" , + M.get_name (| globals, "GAS_COLD_ACCOUNT_ACCESS" |) + |) in + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "create_gas_cost" , + (* if *) + M.if_then_else (| + BoolOp.or (| + M.call (| + M.get_name (| globals, "is_account_alive" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "env" |), "state" |); + M.get_name (| globals, "to" |) + ], + make_dict [] + |), + ltac:(M.monadic ( + Compare.eq (| + M.get_name (| globals, "value" |), + Constant.int 0 + |) + )) + |), + (* then *) + ltac:(M.monadic ( +M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + (* else *) + )), ltac:(M.monadic ( +M.get_name (| globals, "GAS_NEW_ACCOUNT" |) + )) |) + |) in + let _ := M.assign_local (| + "transfer_gas_cost" , + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, "value" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( +M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + (* else *) + )), ltac:(M.monadic ( +M.get_name (| globals, "GAS_CALL_VALUE" |) + )) |) + |) in + let _ := M.assign_local (| + "message_call_gas" , + M.call (| + M.get_name (| globals, "calculate_message_call_gas" |), + make_list [ + M.get_name (| globals, "value" |); + M.get_name (| globals, "gas" |); + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "gas_left" |) + ], + make_dict [] + |); + M.get_field (| M.get_name (| globals, "extend_memory" |), "cost" |); + BinOp.add (| + BinOp.add (| + M.get_name (| globals, "access_gas_cost" |), + M.get_name (| globals, "create_gas_cost" |) + |), + M.get_name (| globals, "transfer_gas_cost" |) + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + BinOp.add (| + M.get_field (| M.get_name (| globals, "message_call_gas" |), "cost" |), + M.get_field (| M.get_name (| globals, "extend_memory" |), "cost" |) + |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + BoolOp.or (| + UnOp.not (| M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "is_static" |) |), + ltac:(M.monadic ( + Compare.eq (| + M.get_name (| globals, "value" |), + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + |) + )) + |); + M.get_name (| globals, "WriteInStaticContext" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "memory" |), + BinOp.mult (| + Constant.bytes "00", + M.get_field (| M.get_name (| globals, "extend_memory" |), "expand_by" |) + |) + |) in + let _ := M.assign_local (| + "sender_balance" , + M.get_field (| M.call (| + M.get_name (| globals, "get_account" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "env" |), "state" |); + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "current_target" |) + ], + make_dict [] + |), "balance" |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.lt (| + M.get_name (| globals, "sender_balance" |), + M.get_name (| globals, "value" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, "evm" |), "return_data" |), + Constant.bytes "" + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "gas_left" |), + M.get_field (| M.get_name (| globals, "message_call_gas" |), "stipend" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, "generic_call" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_field (| M.get_name (| globals, "message_call_gas" |), "stipend" |); + M.get_name (| globals, "value" |); + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "current_target" |); + M.get_name (| globals, "to" |); + M.get_name (| globals, "to" |); + Constant.bool true; + Constant.bool false; + M.get_name (| globals, "memory_input_start_position" |); + M.get_name (| globals, "memory_input_size" |); + M.get_name (| globals, "memory_output_start_position" |); + M.get_name (| globals, "memory_output_size" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + )) |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition callcode : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Message-call into this account with alternative account’s code. + + Parameters + ---------- + evm : + The current EVM frame. + " in + let _ := M.assign_local (| + "gas" , + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "code_address" , + M.call (| + M.get_name (| globals, "to_address" |), + make_list [ + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "value" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_input_start_position" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_input_size" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_output_start_position" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_output_size" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "to" , + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "current_target" |) + |) in + let _ := M.assign_local (| + "extend_memory" , + M.call (| + M.get_name (| globals, "calculate_gas_extend_memory" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "memory" |); + make_list [ + make_tuple [ M.get_name (| globals, "memory_input_start_position" |); M.get_name (| globals, "memory_input_size" |) ]; + make_tuple [ M.get_name (| globals, "memory_output_start_position" |); M.get_name (| globals, "memory_output_size" |) ] + ] + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.in_ (| + M.get_name (| globals, "code_address" |), + M.get_field (| M.get_name (| globals, "evm" |), "accessed_addresses" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "access_gas_cost" , + M.get_name (| globals, "GAS_WARM_ACCESS" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "accessed_addresses" |), "add" |), + make_list [ + M.get_name (| globals, "code_address" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "access_gas_cost" , + M.get_name (| globals, "GAS_COLD_ACCOUNT_ACCESS" |) + |) in + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "transfer_gas_cost" , + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, "value" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( +M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + (* else *) + )), ltac:(M.monadic ( +M.get_name (| globals, "GAS_CALL_VALUE" |) + )) |) + |) in + let _ := M.assign_local (| + "message_call_gas" , + M.call (| + M.get_name (| globals, "calculate_message_call_gas" |), + make_list [ + M.get_name (| globals, "value" |); + M.get_name (| globals, "gas" |); + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "gas_left" |) + ], + make_dict [] + |); + M.get_field (| M.get_name (| globals, "extend_memory" |), "cost" |); + BinOp.add (| + M.get_name (| globals, "access_gas_cost" |), + M.get_name (| globals, "transfer_gas_cost" |) + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + BinOp.add (| + M.get_field (| M.get_name (| globals, "message_call_gas" |), "cost" |), + M.get_field (| M.get_name (| globals, "extend_memory" |), "cost" |) + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "memory" |), + BinOp.mult (| + Constant.bytes "00", + M.get_field (| M.get_name (| globals, "extend_memory" |), "expand_by" |) + |) + |) in + let _ := M.assign_local (| + "sender_balance" , + M.get_field (| M.call (| + M.get_name (| globals, "get_account" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "env" |), "state" |); + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "current_target" |) + ], + make_dict [] + |), "balance" |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.lt (| + M.get_name (| globals, "sender_balance" |), + M.get_name (| globals, "value" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, "evm" |), "return_data" |), + Constant.bytes "" + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "gas_left" |), + M.get_field (| M.get_name (| globals, "message_call_gas" |), "stipend" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, "generic_call" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_field (| M.get_name (| globals, "message_call_gas" |), "stipend" |); + M.get_name (| globals, "value" |); + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "current_target" |); + M.get_name (| globals, "to" |); + M.get_name (| globals, "code_address" |); + Constant.bool true; + Constant.bool false; + M.get_name (| globals, "memory_input_start_position" |); + M.get_name (| globals, "memory_input_size" |); + M.get_name (| globals, "memory_output_start_position" |); + M.get_name (| globals, "memory_output_size" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + )) |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition selfdestruct : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Halt execution and register account for later deletion. + + Parameters + ---------- + evm : + The current EVM frame. + " in + let _ := M.assign_local (| + "beneficiary" , + M.call (| + M.get_name (| globals, "to_address" |), + make_list [ + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "gas_cost" , + M.get_name (| globals, "GAS_SELF_DESTRUCT" |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.not_in (| + M.get_name (| globals, "beneficiary" |), + M.get_field (| M.get_name (| globals, "evm" |), "accessed_addresses" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "accessed_addresses" |), "add" |), + make_list [ + M.get_name (| globals, "beneficiary" |) + ], + make_dict [] + |) in + let _ := M.assign_op_local (| + BinOp.add, + "gas_cost", + M.get_name (| globals, "GAS_COLD_ACCOUNT_ACCESS" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + BoolOp.and (| + UnOp.not (| M.call (| + M.get_name (| globals, "is_account_alive" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "env" |), "state" |); + M.get_name (| globals, "beneficiary" |) + ], + make_dict [] + |) |), + ltac:(M.monadic ( + Compare.not_eq (| + M.get_field (| M.call (| + M.get_name (| globals, "get_account" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "env" |), "state" |); + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "current_target" |) + ], + make_dict [] + |), "balance" |), + Constant.int 0 + |) + )) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_op_local (| + BinOp.add, + "gas_cost", + M.get_name (| globals, "GAS_SELF_DESTRUCT_NEW_ACCOUNT" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "gas_cost" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + UnOp.not (| M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "is_static" |) |); + M.get_name (| globals, "WriteInStaticContext" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "originator" , + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "current_target" |) + |) in + let _ := M.assign_local (| + "beneficiary_balance" , + M.get_field (| M.call (| + M.get_name (| globals, "get_account" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "env" |), "state" |); + M.get_name (| globals, "beneficiary" |) + ], + make_dict [] + |), "balance" |) + |) in + let _ := M.assign_local (| + "originator_balance" , + M.get_field (| M.call (| + M.get_name (| globals, "get_account" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "env" |), "state" |); + M.get_name (| globals, "originator" |) + ], + make_dict [] + |), "balance" |) + |) in + let _ := M.call (| + M.get_name (| globals, "set_account_balance" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "env" |), "state" |); + M.get_name (| globals, "beneficiary" |); + BinOp.add (| + M.get_name (| globals, "beneficiary_balance" |), + M.get_name (| globals, "originator_balance" |) + |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "set_account_balance" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "env" |), "state" |); + M.get_name (| globals, "originator" |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "accounts_to_delete" |), "add" |), + make_list [ + M.get_name (| globals, "originator" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, "account_exists_and_is_empty" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "env" |), "state" |); + M.get_name (| globals, "beneficiary" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "touched_accounts" |), "add" |), + make_list [ + M.get_name (| globals, "beneficiary" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, "evm" |), "running" |), + Constant.bool false + |) in + let _ := M.pass (| |) in + M.pure Constant.None_)). + +Definition delegatecall : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Message-call into an account. + + Parameters + ---------- + evm : + The current EVM frame. + " in + let _ := M.assign_local (| + "gas" , + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "code_address" , + M.call (| + M.get_name (| globals, "to_address" |), + make_list [ + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_input_start_position" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_input_size" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_output_start_position" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_output_size" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "extend_memory" , + M.call (| + M.get_name (| globals, "calculate_gas_extend_memory" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "memory" |); + make_list [ + make_tuple [ M.get_name (| globals, "memory_input_start_position" |); M.get_name (| globals, "memory_input_size" |) ]; + make_tuple [ M.get_name (| globals, "memory_output_start_position" |); M.get_name (| globals, "memory_output_size" |) ] + ] + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.in_ (| + M.get_name (| globals, "code_address" |), + M.get_field (| M.get_name (| globals, "evm" |), "accessed_addresses" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "access_gas_cost" , + M.get_name (| globals, "GAS_WARM_ACCESS" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "accessed_addresses" |), "add" |), + make_list [ + M.get_name (| globals, "code_address" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "access_gas_cost" , + M.get_name (| globals, "GAS_COLD_ACCOUNT_ACCESS" |) + |) in + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "message_call_gas" , + M.call (| + M.get_name (| globals, "calculate_message_call_gas" |), + make_list [ + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |); + M.get_name (| globals, "gas" |); + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "gas_left" |) + ], + make_dict [] + |); + M.get_field (| M.get_name (| globals, "extend_memory" |), "cost" |); + M.get_name (| globals, "access_gas_cost" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + BinOp.add (| + M.get_field (| M.get_name (| globals, "message_call_gas" |), "cost" |), + M.get_field (| M.get_name (| globals, "extend_memory" |), "cost" |) + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "memory" |), + BinOp.mult (| + Constant.bytes "00", + M.get_field (| M.get_name (| globals, "extend_memory" |), "expand_by" |) + |) + |) in + let _ := M.call (| + M.get_name (| globals, "generic_call" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_field (| M.get_name (| globals, "message_call_gas" |), "stipend" |); + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "value" |); + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "caller" |); + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "current_target" |); + M.get_name (| globals, "code_address" |); + Constant.bool false; + Constant.bool false; + M.get_name (| globals, "memory_input_start_position" |); + M.get_name (| globals, "memory_input_size" |); + M.get_name (| globals, "memory_output_start_position" |); + M.get_name (| globals, "memory_output_size" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition staticcall : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Message-call into an account. + + Parameters + ---------- + evm : + The current EVM frame. + " in + let _ := M.assign_local (| + "gas" , + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "to" , + M.call (| + M.get_name (| globals, "to_address" |), + make_list [ + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_input_start_position" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_input_size" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_output_start_position" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_output_size" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "extend_memory" , + M.call (| + M.get_name (| globals, "calculate_gas_extend_memory" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "memory" |); + make_list [ + make_tuple [ M.get_name (| globals, "memory_input_start_position" |); M.get_name (| globals, "memory_input_size" |) ]; + make_tuple [ M.get_name (| globals, "memory_output_start_position" |); M.get_name (| globals, "memory_output_size" |) ] + ] + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.in_ (| + M.get_name (| globals, "to" |), + M.get_field (| M.get_name (| globals, "evm" |), "accessed_addresses" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "access_gas_cost" , + M.get_name (| globals, "GAS_WARM_ACCESS" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "accessed_addresses" |), "add" |), + make_list [ + M.get_name (| globals, "to" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "access_gas_cost" , + M.get_name (| globals, "GAS_COLD_ACCOUNT_ACCESS" |) + |) in + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "message_call_gas" , + M.call (| + M.get_name (| globals, "calculate_message_call_gas" |), + make_list [ + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |); + M.get_name (| globals, "gas" |); + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "gas_left" |) + ], + make_dict [] + |); + M.get_field (| M.get_name (| globals, "extend_memory" |), "cost" |); + M.get_name (| globals, "access_gas_cost" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + BinOp.add (| + M.get_field (| M.get_name (| globals, "message_call_gas" |), "cost" |), + M.get_field (| M.get_name (| globals, "extend_memory" |), "cost" |) + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "memory" |), + BinOp.mult (| + Constant.bytes "00", + M.get_field (| M.get_name (| globals, "extend_memory" |), "expand_by" |) + |) + |) in + let _ := M.call (| + M.get_name (| globals, "generic_call" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_field (| M.get_name (| globals, "message_call_gas" |), "stipend" |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |); + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "current_target" |); + M.get_name (| globals, "to" |); + M.get_name (| globals, "to" |); + Constant.bool true; + Constant.bool true; + M.get_name (| globals, "memory_input_start_position" |); + M.get_name (| globals, "memory_input_size" |); + M.get_name (| globals, "memory_output_start_position" |); + M.get_name (| globals, "memory_output_size" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition revert : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Stop execution and revert state changes, without consuming all provided gas + and also has the ability to return a reason + Parameters + ---------- + evm : + The current EVM frame. + " in + let _ := M.assign_local (| + "memory_start_index" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "size" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "extend_memory" , + M.call (| + M.get_name (| globals, "calculate_gas_extend_memory" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "memory" |); + make_list [ + make_tuple [ M.get_name (| globals, "memory_start_index" |); M.get_name (| globals, "size" |) ] + ] + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_field (| M.get_name (| globals, "extend_memory" |), "cost" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "memory" |), + BinOp.mult (| + Constant.bytes "00", + M.get_field (| M.get_name (| globals, "extend_memory" |), "expand_by" |) + |) + |) in + let _ := M.assign_local (| + "output" , + M.call (| + M.get_name (| globals, "memory_read_bytes" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "memory" |); + M.get_name (| globals, "memory_start_index" |); + M.get_name (| globals, "size" |) + ], + make_dict [] + |) + |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, "evm" |), "output" |), + M.call (| + M.get_name (| globals, "bytes" |), + make_list [ + M.get_name (| globals, "output" |) + ], + make_dict [] + |) + |) in + let _ := M.raise (| Some (M.get_name (| globals, "Revert" |)) |) in + let _ := M.pass (| |) in + M.pure Constant.None_)). diff --git a/CoqOfPython/ethereum/shanghai/vm/interpreter.v b/CoqOfPython/ethereum/shanghai/vm/interpreter.v new file mode 100644 index 0000000..f12f04a --- /dev/null +++ b/CoqOfPython/ethereum/shanghai/vm/interpreter.v @@ -0,0 +1,677 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.shanghai.vm.interpreter". + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) Interpreter +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +A straightforward interpreter that executes EVM code. +". + +Axiom dataclasses_imports_dataclass : + IsImported globals "dataclasses" "dataclass". + +Axiom typing_imports_Iterable : + IsImported globals "typing" "Iterable". +Axiom typing_imports_Optional : + IsImported globals "typing" "Optional". +Axiom typing_imports_Set : + IsImported globals "typing" "Set". +Axiom typing_imports_Tuple : + IsImported globals "typing" "Tuple". +Axiom typing_imports_Union : + IsImported globals "typing" "Union". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_Bytes0 : + IsImported globals "ethereum.base_types" "Bytes0". +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". + +Axiom ethereum_trace_imports_EvmStop : + IsImported globals "ethereum.trace" "EvmStop". +Axiom ethereum_trace_imports_OpEnd : + IsImported globals "ethereum.trace" "OpEnd". +Axiom ethereum_trace_imports_OpException : + IsImported globals "ethereum.trace" "OpException". +Axiom ethereum_trace_imports_OpStart : + IsImported globals "ethereum.trace" "OpStart". +Axiom ethereum_trace_imports_PrecompileEnd : + IsImported globals "ethereum.trace" "PrecompileEnd". +Axiom ethereum_trace_imports_PrecompileStart : + IsImported globals "ethereum.trace" "PrecompileStart". +Axiom ethereum_trace_imports_TransactionEnd : + IsImported globals "ethereum.trace" "TransactionEnd". +Axiom ethereum_trace_imports_evm_trace : + IsImported globals "ethereum.trace" "evm_trace". + +Axiom ethereum_utils_ensure_imports_ensure : + IsImported globals "ethereum.utils.ensure" "ensure". + +Axiom ethereum_shanghai_blocks_imports_Log : + IsImported globals "ethereum.shanghai.blocks" "Log". + +Axiom ethereum_shanghai_fork_types_imports_Address : + IsImported globals "ethereum.shanghai.fork_types" "Address". + +Axiom ethereum_shanghai_state_imports_account_exists_and_is_empty : + IsImported globals "ethereum.shanghai.state" "account_exists_and_is_empty". +Axiom ethereum_shanghai_state_imports_account_has_code_or_nonce : + IsImported globals "ethereum.shanghai.state" "account_has_code_or_nonce". +Axiom ethereum_shanghai_state_imports_begin_transaction : + IsImported globals "ethereum.shanghai.state" "begin_transaction". +Axiom ethereum_shanghai_state_imports_commit_transaction : + IsImported globals "ethereum.shanghai.state" "commit_transaction". +Axiom ethereum_shanghai_state_imports_destroy_storage : + IsImported globals "ethereum.shanghai.state" "destroy_storage". +Axiom ethereum_shanghai_state_imports_increment_nonce : + IsImported globals "ethereum.shanghai.state" "increment_nonce". +Axiom ethereum_shanghai_state_imports_mark_account_created : + IsImported globals "ethereum.shanghai.state" "mark_account_created". +Axiom ethereum_shanghai_state_imports_move_ether : + IsImported globals "ethereum.shanghai.state" "move_ether". +Axiom ethereum_shanghai_state_imports_rollback_transaction : + IsImported globals "ethereum.shanghai.state" "rollback_transaction". +Axiom ethereum_shanghai_state_imports_set_code : + IsImported globals "ethereum.shanghai.state" "set_code". +Axiom ethereum_shanghai_state_imports_touch_account : + IsImported globals "ethereum.shanghai.state" "touch_account". + +Axiom ethereum_shanghai_vm_imports_Message : + IsImported globals "ethereum.shanghai.vm" "Message". + +Axiom ethereum_shanghai_vm_gas_imports_GAS_CODE_DEPOSIT : + IsImported globals "ethereum.shanghai.vm.gas" "GAS_CODE_DEPOSIT". +Axiom ethereum_shanghai_vm_gas_imports_charge_gas : + IsImported globals "ethereum.shanghai.vm.gas" "charge_gas". + +Axiom ethereum_shanghai_vm_precompiled_contracts_mapping_imports_PRE_COMPILED_CONTRACTS : + IsImported globals "ethereum.shanghai.vm.precompiled_contracts.mapping" "PRE_COMPILED_CONTRACTS". + +Axiom ethereum_shanghai_vm_imports_Environment : + IsImported globals "ethereum.shanghai.vm" "Environment". +Axiom ethereum_shanghai_vm_imports_Evm : + IsImported globals "ethereum.shanghai.vm" "Evm". + +Axiom ethereum_shanghai_vm_exceptions_imports_AddressCollision : + IsImported globals "ethereum.shanghai.vm.exceptions" "AddressCollision". +Axiom ethereum_shanghai_vm_exceptions_imports_ExceptionalHalt : + IsImported globals "ethereum.shanghai.vm.exceptions" "ExceptionalHalt". +Axiom ethereum_shanghai_vm_exceptions_imports_InvalidContractPrefix : + IsImported globals "ethereum.shanghai.vm.exceptions" "InvalidContractPrefix". +Axiom ethereum_shanghai_vm_exceptions_imports_InvalidOpcode : + IsImported globals "ethereum.shanghai.vm.exceptions" "InvalidOpcode". +Axiom ethereum_shanghai_vm_exceptions_imports_OutOfGasError : + IsImported globals "ethereum.shanghai.vm.exceptions" "OutOfGasError". +Axiom ethereum_shanghai_vm_exceptions_imports_Revert : + IsImported globals "ethereum.shanghai.vm.exceptions" "Revert". +Axiom ethereum_shanghai_vm_exceptions_imports_StackDepthLimitError : + IsImported globals "ethereum.shanghai.vm.exceptions" "StackDepthLimitError". + +Axiom ethereum_shanghai_vm_instructions_imports_Ops : + IsImported globals "ethereum.shanghai.vm.instructions" "Ops". +Axiom ethereum_shanghai_vm_instructions_imports_op_implementation : + IsImported globals "ethereum.shanghai.vm.instructions" "op_implementation". + +Axiom ethereum_shanghai_vm_runtime_imports_get_valid_jump_destinations : + IsImported globals "ethereum.shanghai.vm.runtime" "get_valid_jump_destinations". + +Definition STACK_DEPTH_LIMIT : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 1024 + ], + make_dict [] + |) +)). + +Definition MAX_CODE_SIZE : Value.t := M.run ltac:(M.monadic ( + Constant.int 24576 +)). + +Definition MessageCallOutput : Value.t := + builtins.make_klass + [] + [ + + ] + [ + + ]. + +Definition process_message_call : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "message"; "env" ] |) in + let _ := Constant.str " + If `message.current` is empty then it creates a smart contract + else it executes a call from the `message.caller` to the `message.target`. + + Parameters + ---------- + message : + Transaction specific items. + + env : + External items required for EVM execution. + + Returns + ------- + output : `MessageCallOutput` + Output of the message call + " in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_field (| M.get_name (| globals, "message" |), "target" |), + M.call (| + M.get_name (| globals, "Bytes0" |), + make_list [ + Constant.bytes "" + ], + make_dict [] + |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "is_collision" , + M.call (| + M.get_name (| globals, "account_has_code_or_nonce" |), + make_list [ + M.get_field (| M.get_name (| globals, "env" |), "state" |); + M.get_field (| M.get_name (| globals, "message" |), "current_target" |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + M.get_name (| globals, "is_collision" |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + M.call (| + M.get_name (| globals, "MessageCallOutput" |), + make_list [ + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |); + M.call (| + M.get_name (| globals, "tuple" |), + make_list [], + make_dict [] + |); + M.call (| + M.get_name (| globals, "set" |), + make_list [], + make_dict [] + |); + M.call (| + M.get_name (| globals, "set" |), + make_list [], + make_dict [] + |); + M.call (| + M.get_name (| globals, "AddressCollision" |), + make_list [], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "evm" , + M.call (| + M.get_name (| globals, "process_create_message" |), + make_list [ + M.get_name (| globals, "message" |); + M.get_name (| globals, "env" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "evm" , + M.call (| + M.get_name (| globals, "process_message" |), + make_list [ + M.get_name (| globals, "message" |); + M.get_name (| globals, "env" |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, "account_exists_and_is_empty" |), + make_list [ + M.get_field (| M.get_name (| globals, "env" |), "state" |); + M.call (| + M.get_name (| globals, "Address" |), + make_list [ + M.get_field (| M.get_name (| globals, "message" |), "target" |) + ], + make_dict [] + |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "touched_accounts" |), "add" |), + make_list [ + M.call (| + M.get_name (| globals, "Address" |), + make_list [ + M.get_field (| M.get_name (| globals, "message" |), "target" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + M.get_field (| M.get_name (| globals, "evm" |), "error" |), + (* then *) + ltac:(M.monadic ( +(* At stmt: unsupported node type: AnnAssign *) + let _ := M.assign_local (| + "accounts_to_delete" , + M.call (| + M.get_name (| globals, "set" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "touched_accounts" , + M.call (| + M.get_name (| globals, "set" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "refund_counter" , + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "logs" , + M.get_field (| M.get_name (| globals, "evm" |), "logs" |) + |) in + let _ := M.assign_local (| + "accounts_to_delete" , + M.get_field (| M.get_name (| globals, "evm" |), "accounts_to_delete" |) + |) in + let _ := M.assign_local (| + "touched_accounts" , + M.get_field (| M.get_name (| globals, "evm" |), "touched_accounts" |) + |) in + let _ := M.assign_local (| + "refund_counter" , + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "refund_counter" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "tx_end" , + M.call (| + M.get_name (| globals, "TransactionEnd" |), + make_list [ + BinOp.sub (| + M.get_field (| M.get_name (| globals, "message" |), "gas" |), + M.get_field (| M.get_name (| globals, "evm" |), "gas_left" |) + |); + M.get_field (| M.get_name (| globals, "evm" |), "output" |); + M.get_field (| M.get_name (| globals, "evm" |), "error" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "evm_trace" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "tx_end" |) + ], + make_dict [] + |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, "MessageCallOutput" |), + make_list [], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Definition process_create_message : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "message"; "env" ] |) in + let _ := Constant.str " + Executes a call to create a smart contract. + + Parameters + ---------- + message : + Transaction specific items. + env : + External items required for EVM execution. + + Returns + ------- + evm: :py:class:`~ethereum.shanghai.vm.Evm` + Items containing execution specific objects. + " in + let _ := M.call (| + M.get_name (| globals, "begin_transaction" |), + make_list [ + M.get_field (| M.get_name (| globals, "env" |), "state" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "destroy_storage" |), + make_list [ + M.get_field (| M.get_name (| globals, "env" |), "state" |); + M.get_field (| M.get_name (| globals, "message" |), "current_target" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "mark_account_created" |), + make_list [ + M.get_field (| M.get_name (| globals, "env" |), "state" |); + M.get_field (| M.get_name (| globals, "message" |), "current_target" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "increment_nonce" |), + make_list [ + M.get_field (| M.get_name (| globals, "env" |), "state" |); + M.get_field (| M.get_name (| globals, "message" |), "current_target" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "evm" , + M.call (| + M.get_name (| globals, "process_message" |), + make_list [ + M.get_name (| globals, "message" |); + M.get_name (| globals, "env" |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + UnOp.not (| M.get_field (| M.get_name (| globals, "evm" |), "error" |) |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "contract_code" , + M.get_field (| M.get_name (| globals, "evm" |), "output" |) + |) in + let _ := M.assign_local (| + "contract_code_gas" , + BinOp.mult (| + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_name (| globals, "contract_code" |) + ], + make_dict [] + |), + M.get_name (| globals, "GAS_CODE_DEPOSIT" |) + |) + |) in +(* At stmt: unsupported node type: Try *) + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, "rollback_transaction" |), + make_list [ + M.get_field (| M.get_name (| globals, "env" |), "state" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + )) |) in + let _ := M.return_ (| + M.get_name (| globals, "evm" |) + |) in + M.pure Constant.None_)). + +Definition process_message : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "message"; "env" ] |) in + let _ := Constant.str " + Executes a call to create a smart contract. + + Parameters + ---------- + message : + Transaction specific items. + env : + External items required for EVM execution. + + Returns + ------- + evm: :py:class:`~ethereum.shanghai.vm.Evm` + Items containing execution specific objects + " in + let _ := + (* if *) + M.if_then_else (| + Compare.gt (| + M.get_field (| M.get_name (| globals, "message" |), "depth" |), + M.get_name (| globals, "STACK_DEPTH_LIMIT" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.call (| + M.get_name (| globals, "StackDepthLimitError" |), + make_list [ + Constant.str "Stack depth limit reached" + ], + make_dict [] + |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.call (| + M.get_name (| globals, "begin_transaction" |), + make_list [ + M.get_field (| M.get_name (| globals, "env" |), "state" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "touch_account" |), + make_list [ + M.get_field (| M.get_name (| globals, "env" |), "state" |); + M.get_field (| M.get_name (| globals, "message" |), "current_target" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + BoolOp.and (| + M.get_field (| M.get_name (| globals, "message" |), "should_transfer_value" |), + ltac:(M.monadic ( + Compare.not_eq (| + M.get_field (| M.get_name (| globals, "message" |), "value" |), + Constant.int 0 + |) + )) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, "move_ether" |), + make_list [ + M.get_field (| M.get_name (| globals, "env" |), "state" |); + M.get_field (| M.get_name (| globals, "message" |), "caller" |); + M.get_field (| M.get_name (| globals, "message" |), "current_target" |); + M.get_field (| M.get_name (| globals, "message" |), "value" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "evm" , + M.call (| + M.get_name (| globals, "execute_code" |), + make_list [ + M.get_name (| globals, "message" |); + M.get_name (| globals, "env" |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + M.get_field (| M.get_name (| globals, "evm" |), "error" |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, "rollback_transaction" |), + make_list [ + M.get_field (| M.get_name (| globals, "env" |), "state" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, "commit_transaction" |), + make_list [ + M.get_field (| M.get_name (| globals, "env" |), "state" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + )) |) in + let _ := M.return_ (| + M.get_name (| globals, "evm" |) + |) in + M.pure Constant.None_)). + +Definition execute_code : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "message"; "env" ] |) in + let _ := Constant.str " + Executes bytecode present in the `message`. + + Parameters + ---------- + message : + Transaction specific items. + env : + External items required for EVM execution. + + Returns + ------- + evm: `ethereum.vm.EVM` + Items containing execution specific objects + " in + let _ := M.assign_local (| + "code" , + M.get_field (| M.get_name (| globals, "message" |), "code" |) + |) in + let _ := M.assign_local (| + "valid_jump_destinations" , + M.call (| + M.get_name (| globals, "get_valid_jump_destinations" |), + make_list [ + M.get_name (| globals, "code" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "evm" , + M.call (| + M.get_name (| globals, "Evm" |), + make_list [], + make_dict [] + |) + |) in +(* At stmt: unsupported node type: Try *) + let _ := M.return_ (| + M.get_name (| globals, "evm" |) + |) in + M.pure Constant.None_)). diff --git a/CoqOfPython/ethereum/shanghai/vm/memory.v b/CoqOfPython/ethereum/shanghai/vm/memory.v new file mode 100644 index 0000000..6e9a8b2 --- /dev/null +++ b/CoqOfPython/ethereum/shanghai/vm/memory.v @@ -0,0 +1,166 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.shanghai.vm.memory". + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) Memory +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +EVM memory operations. +". + +Axiom ethereum_utils_byte_imports_right_pad_zero_bytes : + IsImported globals "ethereum.utils.byte" "right_pad_zero_bytes". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_Bytes : + IsImported globals "ethereum.base_types" "Bytes". +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". + +Definition memory_write : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "memory"; "start_position"; "value" ] |) in + let _ := Constant.str " + Writes to memory. + + Parameters + ---------- + memory : + Memory contents of the EVM. + start_position : + Starting pointer to the memory. + value : + Data to write to memory. + " in + let _ := M.assign (| + M.slice (| + M.get_name (| globals, "memory" |), + M.get_name (| globals, "start_position" |), + BinOp.add (| + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.get_name (| globals, "start_position" |) + ], + make_dict [] + |), + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_name (| globals, "value" |) + ], + make_dict [] + |) + |), + Constant.None_ + |), + M.get_name (| globals, "value" |) + |) in + M.pure Constant.None_)). + +Definition memory_read_bytes : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "memory"; "start_position"; "size" ] |) in + let _ := Constant.str " + Read bytes from memory. + + Parameters + ---------- + memory : + Memory contents of the EVM. + start_position : + Starting pointer to the memory. + size : + Size of the data that needs to be read from `start_position`. + + Returns + ------- + data_bytes : + Data read from memory. + " in + let _ := M.return_ (| + M.slice (| + M.get_name (| globals, "memory" |), + M.get_name (| globals, "start_position" |), + BinOp.add (| + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.get_name (| globals, "start_position" |) + ], + make_dict [] + |), + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.get_name (| globals, "size" |) + ], + make_dict [] + |) + |), + Constant.None_ + |) + |) in + M.pure Constant.None_)). + +Definition buffer_read : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "buffer"; "start_position"; "size" ] |) in + let _ := Constant.str " + Read bytes from a buffer. Padding with zeros if necessary. + + Parameters + ---------- + buffer : + Memory contents of the EVM. + start_position : + Starting pointer to the memory. + size : + Size of the data that needs to be read from `start_position`. + + Returns + ------- + data_bytes : + Data read from memory. + " in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, "right_pad_zero_bytes" |), + make_list [ + M.slice (| + M.get_name (| globals, "buffer" |), + M.get_name (| globals, "start_position" |), + BinOp.add (| + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.get_name (| globals, "start_position" |) + ], + make_dict [] + |), + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.get_name (| globals, "size" |) + ], + make_dict [] + |) + |), + Constant.None_ + |); + M.get_name (| globals, "size" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). diff --git a/CoqOfPython/ethereum/shanghai/vm/precompiled_contracts/__init__.v b/CoqOfPython/ethereum/shanghai/vm/precompiled_contracts/__init__.v new file mode 100644 index 0000000..4a90702 --- /dev/null +++ b/CoqOfPython/ethereum/shanghai/vm/precompiled_contracts/__init__.v @@ -0,0 +1,116 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.shanghai.vm.precompiled_contracts.__init__". + +Definition expr_1 : Value.t := + Constant.str " +Precompiled Contract Addresses +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Addresses of precompiled contracts and mappings to their +implementations. +". + +Axiom ethereum_shanghai_utils_hexadecimal_imports_hex_to_address : + IsImported globals "ethereum.shanghai.utils.hexadecimal" "hex_to_address". + +Definition __all__ : Value.t := M.run ltac:(M.monadic ( + make_tuple [ Constant.str "ECRECOVER_ADDRESS"; Constant.str "SHA256_ADDRESS"; Constant.str "RIPEMD160_ADDRESS"; Constant.str "IDENTITY_ADDRESS"; Constant.str "MODEXP_ADDRESS"; Constant.str "ALT_BN128_ADD_ADDRESS"; Constant.str "ALT_BN128_MUL_ADDRESS"; Constant.str "ALT_BN128_PAIRING_CHECK_ADDRESS"; Constant.str "BLAKE2F_ADDRESS" ] +)). + +Definition ECRECOVER_ADDRESS : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "hex_to_address" |), + make_list [ + Constant.str "0x01" + ], + make_dict [] + |) +)). + +Definition SHA256_ADDRESS : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "hex_to_address" |), + make_list [ + Constant.str "0x02" + ], + make_dict [] + |) +)). + +Definition RIPEMD160_ADDRESS : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "hex_to_address" |), + make_list [ + Constant.str "0x03" + ], + make_dict [] + |) +)). + +Definition IDENTITY_ADDRESS : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "hex_to_address" |), + make_list [ + Constant.str "0x04" + ], + make_dict [] + |) +)). + +Definition MODEXP_ADDRESS : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "hex_to_address" |), + make_list [ + Constant.str "0x05" + ], + make_dict [] + |) +)). + +Definition ALT_BN128_ADD_ADDRESS : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "hex_to_address" |), + make_list [ + Constant.str "0x06" + ], + make_dict [] + |) +)). + +Definition ALT_BN128_MUL_ADDRESS : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "hex_to_address" |), + make_list [ + Constant.str "0x07" + ], + make_dict [] + |) +)). + +Definition ALT_BN128_PAIRING_CHECK_ADDRESS : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "hex_to_address" |), + make_list [ + Constant.str "0x08" + ], + make_dict [] + |) +)). + +Definition BLAKE2F_ADDRESS : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "hex_to_address" |), + make_list [ + Constant.str "0x09" + ], + make_dict [] + |) +)). diff --git a/CoqOfPython/ethereum/shanghai/vm/precompiled_contracts/alt_bn128.v b/CoqOfPython/ethereum/shanghai/vm/precompiled_contracts/alt_bn128.v new file mode 100644 index 0000000..69c7cc0 --- /dev/null +++ b/CoqOfPython/ethereum/shanghai/vm/precompiled_contracts/alt_bn128.v @@ -0,0 +1,778 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.shanghai.vm.precompiled_contracts.alt_bn128". + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) ALT_BN128 CONTRACTS +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementation of the ALT_BN128 precompiled contracts. +". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". + +Axiom ethereum_crypto_alt_bn128_imports_ALT_BN128_CURVE_ORDER : + IsImported globals "ethereum.crypto.alt_bn128" "ALT_BN128_CURVE_ORDER". +Axiom ethereum_crypto_alt_bn128_imports_ALT_BN128_PRIME : + IsImported globals "ethereum.crypto.alt_bn128" "ALT_BN128_PRIME". +Axiom ethereum_crypto_alt_bn128_imports_BNF : + IsImported globals "ethereum.crypto.alt_bn128" "BNF". +Axiom ethereum_crypto_alt_bn128_imports_BNF2 : + IsImported globals "ethereum.crypto.alt_bn128" "BNF2". +Axiom ethereum_crypto_alt_bn128_imports_BNF12 : + IsImported globals "ethereum.crypto.alt_bn128" "BNF12". +Axiom ethereum_crypto_alt_bn128_imports_BNP : + IsImported globals "ethereum.crypto.alt_bn128" "BNP". +Axiom ethereum_crypto_alt_bn128_imports_BNP2 : + IsImported globals "ethereum.crypto.alt_bn128" "BNP2". +Axiom ethereum_crypto_alt_bn128_imports_pairing : + IsImported globals "ethereum.crypto.alt_bn128" "pairing". + +Axiom ethereum_utils_ensure_imports_ensure : + IsImported globals "ethereum.utils.ensure" "ensure". + +Axiom ethereum_shanghai_vm_imports_Evm : + IsImported globals "ethereum.shanghai.vm" "Evm". + +Axiom ethereum_shanghai_vm_gas_imports_charge_gas : + IsImported globals "ethereum.shanghai.vm.gas" "charge_gas". + +Axiom ethereum_shanghai_vm_memory_imports_buffer_read : + IsImported globals "ethereum.shanghai.vm.memory" "buffer_read". + +Axiom ethereum_shanghai_vm_exceptions_imports_OutOfGasError : + IsImported globals "ethereum.shanghai.vm.exceptions" "OutOfGasError". + +Definition alt_bn128_add : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + The ALT_BN128 addition precompiled contract. + + Parameters + ---------- + evm : + The current EVM frame. + " in + let _ := M.assign_local (| + "data" , + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "data" |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 150 + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "x0_bytes" , + M.call (| + M.get_name (| globals, "buffer_read" |), + make_list [ + M.get_name (| globals, "data" |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 32 + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "x0_value" , + M.call (| + M.get_field (| M.get_name (| globals, "U256" |), "from_be_bytes" |), + make_list [ + M.get_name (| globals, "x0_bytes" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "y0_bytes" , + M.call (| + M.get_name (| globals, "buffer_read" |), + make_list [ + M.get_name (| globals, "data" |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 32 + ], + make_dict [] + |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 32 + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "y0_value" , + M.call (| + M.get_field (| M.get_name (| globals, "U256" |), "from_be_bytes" |), + make_list [ + M.get_name (| globals, "y0_bytes" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "x1_bytes" , + M.call (| + M.get_name (| globals, "buffer_read" |), + make_list [ + M.get_name (| globals, "data" |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 64 + ], + make_dict [] + |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 32 + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "x1_value" , + M.call (| + M.get_field (| M.get_name (| globals, "U256" |), "from_be_bytes" |), + make_list [ + M.get_name (| globals, "x1_bytes" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "y1_bytes" , + M.call (| + M.get_name (| globals, "buffer_read" |), + make_list [ + M.get_name (| globals, "data" |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 96 + ], + make_dict [] + |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 32 + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "y1_value" , + M.call (| + M.get_field (| M.get_name (| globals, "U256" |), "from_be_bytes" |), + make_list [ + M.get_name (| globals, "y1_bytes" |) + ], + make_dict [] + |) + |) in + let _ := + M.for_ (| + M.get_name (| globals, "i" |), + make_tuple [ M.get_name (| globals, "x0_value" |); M.get_name (| globals, "y0_value" |); M.get_name (| globals, "x1_value" |); M.get_name (| globals, "y1_value" |) ], + ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + Compare.gt_e (| + M.get_name (| globals, "i" |), + M.get_name (| globals, "ALT_BN128_PRIME" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, "OutOfGasError" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in +(* At stmt: unsupported node type: Try *) + let _ := M.assign_local (| + "p" , + BinOp.add (| + M.get_name (| globals, "p0" |), + M.get_name (| globals, "p1" |) + |) + |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, "evm" |), "output" |), + BinOp.add (| + M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, "p" |), "x" |), "to_be_bytes32" |), + make_list [], + make_dict [] + |), + M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, "p" |), "y" |), "to_be_bytes32" |), + make_list [], + make_dict [] + |) + |) + |) in + M.pure Constant.None_)). + +Definition alt_bn128_mul : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + The ALT_BN128 multiplication precompiled contract. + + Parameters + ---------- + evm : + The current EVM frame. + " in + let _ := M.assign_local (| + "data" , + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "data" |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 6000 + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "x0_bytes" , + M.call (| + M.get_name (| globals, "buffer_read" |), + make_list [ + M.get_name (| globals, "data" |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 32 + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "x0_value" , + M.call (| + M.get_field (| M.get_name (| globals, "U256" |), "from_be_bytes" |), + make_list [ + M.get_name (| globals, "x0_bytes" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "y0_bytes" , + M.call (| + M.get_name (| globals, "buffer_read" |), + make_list [ + M.get_name (| globals, "data" |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 32 + ], + make_dict [] + |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 32 + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "y0_value" , + M.call (| + M.get_field (| M.get_name (| globals, "U256" |), "from_be_bytes" |), + make_list [ + M.get_name (| globals, "y0_bytes" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "n" , + M.call (| + M.get_field (| M.get_name (| globals, "U256" |), "from_be_bytes" |), + make_list [ + M.call (| + M.get_name (| globals, "buffer_read" |), + make_list [ + M.get_name (| globals, "data" |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 64 + ], + make_dict [] + |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 32 + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := + M.for_ (| + M.get_name (| globals, "i" |), + make_tuple [ M.get_name (| globals, "x0_value" |); M.get_name (| globals, "y0_value" |) ], + ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + Compare.gt_e (| + M.get_name (| globals, "i" |), + M.get_name (| globals, "ALT_BN128_PRIME" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, "OutOfGasError" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in +(* At stmt: unsupported node type: Try *) + let _ := M.assign_local (| + "p" , + M.call (| + M.get_field (| M.get_name (| globals, "p0" |), "mul_by" |), + make_list [ + M.get_name (| globals, "n" |) + ], + make_dict [] + |) + |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, "evm" |), "output" |), + BinOp.add (| + M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, "p" |), "x" |), "to_be_bytes32" |), + make_list [], + make_dict [] + |), + M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, "p" |), "y" |), "to_be_bytes32" |), + make_list [], + make_dict [] + |) + |) + |) in + M.pure Constant.None_)). + +Definition alt_bn128_pairing_check : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + The ALT_BN128 pairing check precompiled contract. + + Parameters + ---------- + evm : + The current EVM frame. + " in + let _ := M.assign_local (| + "data" , + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "data" |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + BinOp.add (| + BinOp.mult (| + Constant.int 34000, + BinOp.floor_div (| + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_name (| globals, "data" |) + ], + make_dict [] + |), + Constant.int 192 + |) + |), + Constant.int 45000 + |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.not_eq (| + BinOp.mod_ (| + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_name (| globals, "data" |) + ], + make_dict [] + |), + Constant.int 192 + |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, "OutOfGasError" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "result" , + M.call (| + M.get_field (| M.get_name (| globals, "BNF12" |), "from_int" |), + make_list [ + Constant.int 1 + ], + make_dict [] + |) + |) in + let _ := + M.for_ (| + M.get_name (| globals, "i" |), + M.call (| + M.get_name (| globals, "range" |), + make_list [ + BinOp.floor_div (| + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_name (| globals, "data" |) + ], + make_dict [] + |), + Constant.int 192 + |) + ], + make_dict [] + |), + ltac:(M.monadic ( + let _ := M.assign_local (| + "values" , + make_list [] + |) in + let _ := + M.for_ (| + M.get_name (| globals, "j" |), + M.call (| + M.get_name (| globals, "range" |), + make_list [ + Constant.int 6 + ], + make_dict [] + |), + ltac:(M.monadic ( + let _ := M.assign_local (| + "value" , + M.call (| + M.get_field (| M.get_name (| globals, "U256" |), "from_be_bytes" |), + make_list [ + M.slice (| + M.get_name (| globals, "data" |), + BinOp.add (| + BinOp.mult (| + M.get_name (| globals, "i" |), + Constant.int 192 + |), + BinOp.mult (| + Constant.int 32, + M.get_name (| globals, "j" |) + |) + |), + BinOp.add (| + BinOp.mult (| + M.get_name (| globals, "i" |), + Constant.int 192 + |), + BinOp.mult (| + Constant.int 32, + BinOp.add (| + M.get_name (| globals, "j" |), + Constant.int 1 + |) + |) + |), + Constant.None_ + |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.gt_e (| + M.get_name (| globals, "value" |), + M.get_name (| globals, "ALT_BN128_PRIME" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, "OutOfGasError" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.call (| + M.get_field (| M.get_name (| globals, "values" |), "append" |), + make_list [ + M.call (| + M.get_name (| globals, "int" |), + make_list [ + M.get_name (| globals, "value" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in +(* At stmt: unsupported node type: Try *) + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + Compare.eq (| + M.call (| + M.get_field (| M.get_name (| globals, "p" |), "mul_by" |), + make_list [ + M.get_name (| globals, "ALT_BN128_CURVE_ORDER" |) + ], + make_dict [] + |), + M.call (| + M.get_field (| M.get_name (| globals, "BNP" |), "point_at_infinity" |), + make_list [], + make_dict [] + |) + |); + M.get_name (| globals, "OutOfGasError" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + Compare.eq (| + M.call (| + M.get_field (| M.get_name (| globals, "q" |), "mul_by" |), + make_list [ + M.get_name (| globals, "ALT_BN128_CURVE_ORDER" |) + ], + make_dict [] + |), + M.call (| + M.get_field (| M.get_name (| globals, "BNP2" |), "point_at_infinity" |), + make_list [], + make_dict [] + |) + |); + M.get_name (| globals, "OutOfGasError" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + BoolOp.and (| + Compare.not_eq (| + M.get_name (| globals, "p" |), + M.call (| + M.get_field (| M.get_name (| globals, "BNP" |), "point_at_infinity" |), + make_list [], + make_dict [] + |) + |), + ltac:(M.monadic ( + Compare.not_eq (| + M.get_name (| globals, "q" |), + M.call (| + M.get_field (| M.get_name (| globals, "BNP2" |), "point_at_infinity" |), + make_list [], + make_dict [] + |) + |) + )) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "result" , + BinOp.mult (| + M.get_name (| globals, "result" |), + M.call (| + M.get_name (| globals, "pairing" |), + make_list [ + M.get_name (| globals, "q" |); + M.get_name (| globals, "p" |) + ], + make_dict [] + |) + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, "result" |), + M.call (| + M.get_field (| M.get_name (| globals, "BNF12" |), "from_int" |), + make_list [ + Constant.int 1 + ], + make_dict [] + |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign (| + M.get_field (| M.get_name (| globals, "evm" |), "output" |), + M.call (| + M.get_field (| M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 1 + ], + make_dict [] + |), "to_be_bytes32" |), + make_list [], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign (| + M.get_field (| M.get_name (| globals, "evm" |), "output" |), + M.call (| + M.get_field (| M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |), "to_be_bytes32" |), + make_list [], + make_dict [] + |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_)). diff --git a/CoqOfPython/ethereum/shanghai/vm/precompiled_contracts/blake2f.v b/CoqOfPython/ethereum/shanghai/vm/precompiled_contracts/blake2f.v new file mode 100644 index 0000000..1bef272 --- /dev/null +++ b/CoqOfPython/ethereum/shanghai/vm/precompiled_contracts/blake2f.v @@ -0,0 +1,127 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.shanghai.vm.precompiled_contracts.blake2f". + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) Blake2 PRECOMPILED CONTRACT +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementation of the `Blake2` precompiled contract. +". + +Axiom ethereum_crypto_blake2_imports_Blake2b : + IsImported globals "ethereum.crypto.blake2" "Blake2b". + +Axiom ethereum_utils_ensure_imports_ensure : + IsImported globals "ethereum.utils.ensure" "ensure". + +Axiom ethereum_shanghai_vm_imports_Evm : + IsImported globals "ethereum.shanghai.vm" "Evm". + +Axiom ethereum_shanghai_vm_gas_imports_GAS_BLAKE2_PER_ROUND : + IsImported globals "ethereum.shanghai.vm.gas" "GAS_BLAKE2_PER_ROUND". +Axiom ethereum_shanghai_vm_gas_imports_charge_gas : + IsImported globals "ethereum.shanghai.vm.gas" "charge_gas". + +Axiom ethereum_shanghai_vm_exceptions_imports_InvalidParameter : + IsImported globals "ethereum.shanghai.vm.exceptions" "InvalidParameter". + +Definition blake2f : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Writes the Blake2 hash to output. + + Parameters + ---------- + evm : + The current EVM frame. + " in + let _ := M.assign_local (| + "data" , + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "data" |) + |) in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + Compare.eq (| + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_name (| globals, "data" |) + ], + make_dict [] + |), + Constant.int 213 + |); + M.get_name (| globals, "InvalidParameter" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "blake2b" , + M.call (| + M.get_name (| globals, "Blake2b" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.assign (| + make_tuple [ M.get_name (| globals, "rounds" |); M.get_name (| globals, "h" |); M.get_name (| globals, "m" |); M.get_name (| globals, "t_0" |); M.get_name (| globals, "t_1" |); M.get_name (| globals, "f" |) ], + M.call (| + M.get_field (| M.get_name (| globals, "blake2b" |), "get_blake2_parameters" |), + make_list [ + M.get_name (| globals, "data" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + BinOp.mult (| + M.get_name (| globals, "GAS_BLAKE2_PER_ROUND" |), + M.get_name (| globals, "rounds" |) + |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + Compare.in_ (| + M.get_name (| globals, "f" |), + make_list [ + Constant.int 0; + Constant.int 1 + ] + |); + M.get_name (| globals, "InvalidParameter" |) + ], + make_dict [] + |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, "evm" |), "output" |), + M.call (| + M.get_field (| M.get_name (| globals, "blake2b" |), "compress" |), + make_list [ + M.get_name (| globals, "rounds" |); + M.get_name (| globals, "h" |); + M.get_name (| globals, "m" |); + M.get_name (| globals, "t_0" |); + M.get_name (| globals, "t_1" |); + M.get_name (| globals, "f" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). diff --git a/CoqOfPython/ethereum/shanghai/vm/precompiled_contracts/ecrecover.v b/CoqOfPython/ethereum/shanghai/vm/precompiled_contracts/ecrecover.v new file mode 100644 index 0000000..ac4b74e --- /dev/null +++ b/CoqOfPython/ethereum/shanghai/vm/precompiled_contracts/ecrecover.v @@ -0,0 +1,301 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.shanghai.vm.precompiled_contracts.ecrecover". + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) ECRECOVER PRECOMPILED CONTRACT +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementation of the ECRECOVER precompiled contract. +". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". + +Axiom ethereum_crypto_elliptic_curve_imports_SECP256K1N : + IsImported globals "ethereum.crypto.elliptic_curve" "SECP256K1N". +Axiom ethereum_crypto_elliptic_curve_imports_secp256k1_recover : + IsImported globals "ethereum.crypto.elliptic_curve" "secp256k1_recover". + +Axiom ethereum_crypto_hash_imports_Hash32 : + IsImported globals "ethereum.crypto.hash" "Hash32". +Axiom ethereum_crypto_hash_imports_keccak256 : + IsImported globals "ethereum.crypto.hash" "keccak256". + +Axiom ethereum_utils_byte_imports_left_pad_zero_bytes : + IsImported globals "ethereum.utils.byte" "left_pad_zero_bytes". + +Axiom ethereum_shanghai_vm_imports_Evm : + IsImported globals "ethereum.shanghai.vm" "Evm". + +Axiom ethereum_shanghai_vm_gas_imports_GAS_ECRECOVER : + IsImported globals "ethereum.shanghai.vm.gas" "GAS_ECRECOVER". +Axiom ethereum_shanghai_vm_gas_imports_charge_gas : + IsImported globals "ethereum.shanghai.vm.gas" "charge_gas". + +Axiom ethereum_shanghai_vm_memory_imports_buffer_read : + IsImported globals "ethereum.shanghai.vm.memory" "buffer_read". + +Definition ecrecover : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Decrypts the address using elliptic curve DSA recovery mechanism and writes + the address to output. + + Parameters + ---------- + evm : + The current EVM frame. + " in + let _ := M.assign_local (| + "data" , + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "data" |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_ECRECOVER" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "message_hash_bytes" , + M.call (| + M.get_name (| globals, "buffer_read" |), + make_list [ + M.get_name (| globals, "data" |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 32 + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "message_hash" , + M.call (| + M.get_name (| globals, "Hash32" |), + make_list [ + M.get_name (| globals, "message_hash_bytes" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "v" , + M.call (| + M.get_field (| M.get_name (| globals, "U256" |), "from_be_bytes" |), + make_list [ + M.call (| + M.get_name (| globals, "buffer_read" |), + make_list [ + M.get_name (| globals, "data" |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 32 + ], + make_dict [] + |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 32 + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "r" , + M.call (| + M.get_field (| M.get_name (| globals, "U256" |), "from_be_bytes" |), + make_list [ + M.call (| + M.get_name (| globals, "buffer_read" |), + make_list [ + M.get_name (| globals, "data" |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 64 + ], + make_dict [] + |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 32 + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "s" , + M.call (| + M.get_field (| M.get_name (| globals, "U256" |), "from_be_bytes" |), + make_list [ + M.call (| + M.get_name (| globals, "buffer_read" |), + make_list [ + M.get_name (| globals, "data" |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 96 + ], + make_dict [] + |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 32 + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + BoolOp.and (| + Compare.not_eq (| + M.get_name (| globals, "v" |), + Constant.int 27 + |), + ltac:(M.monadic ( + Compare.not_eq (| + M.get_name (| globals, "v" |), + Constant.int 28 + |) + )) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + Constant.None_ + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + BoolOp.or (| + Compare.gt_e (| + Constant.int 0, + M.get_name (| globals, "r" |) + |), + ltac:(M.monadic ( + Compare.gt_e (| + M.get_name (| globals, "r" |), + M.get_name (| globals, "SECP256K1N" |) + |) + )) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + Constant.None_ + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + BoolOp.or (| + Compare.gt_e (| + Constant.int 0, + M.get_name (| globals, "s" |) + |), + ltac:(M.monadic ( + Compare.gt_e (| + M.get_name (| globals, "s" |), + M.get_name (| globals, "SECP256K1N" |) + |) + )) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + Constant.None_ + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in +(* At stmt: unsupported node type: Try *) + let _ := M.assign_local (| + "address" , + M.slice (| + M.call (| + M.get_name (| globals, "keccak256" |), + make_list [ + M.get_name (| globals, "public_key" |) + ], + make_dict [] + |), + Constant.int 12, + Constant.int 32, + Constant.None_ + |) + |) in + let _ := M.assign_local (| + "padded_address" , + M.call (| + M.get_name (| globals, "left_pad_zero_bytes" |), + make_list [ + M.get_name (| globals, "address" |); + Constant.int 32 + ], + make_dict [] + |) + |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, "evm" |), "output" |), + M.get_name (| globals, "padded_address" |) + |) in + M.pure Constant.None_)). diff --git a/CoqOfPython/ethereum/shanghai/vm/precompiled_contracts/identity.v b/CoqOfPython/ethereum/shanghai/vm/precompiled_contracts/identity.v new file mode 100644 index 0000000..554096f --- /dev/null +++ b/CoqOfPython/ethereum/shanghai/vm/precompiled_contracts/identity.v @@ -0,0 +1,94 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.shanghai.vm.precompiled_contracts.identity". + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) IDENTITY PRECOMPILED CONTRACT +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementation of the `IDENTITY` precompiled contract. +". + +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". + +Axiom ethereum_utils_numeric_imports_ceil32 : + IsImported globals "ethereum.utils.numeric" "ceil32". + +Axiom ethereum_shanghai_vm_imports_Evm : + IsImported globals "ethereum.shanghai.vm" "Evm". + +Axiom ethereum_shanghai_vm_gas_imports_GAS_IDENTITY : + IsImported globals "ethereum.shanghai.vm.gas" "GAS_IDENTITY". +Axiom ethereum_shanghai_vm_gas_imports_GAS_IDENTITY_WORD : + IsImported globals "ethereum.shanghai.vm.gas" "GAS_IDENTITY_WORD". +Axiom ethereum_shanghai_vm_gas_imports_charge_gas : + IsImported globals "ethereum.shanghai.vm.gas" "charge_gas". + +Definition identity : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Writes the message data to output. + + Parameters + ---------- + evm : + The current EVM frame. + " in + let _ := M.assign_local (| + "data" , + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "data" |) + |) in + let _ := M.assign_local (| + "word_count" , + BinOp.floor_div (| + M.call (| + M.get_name (| globals, "ceil32" |), + make_list [ + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_name (| globals, "data" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |), + Constant.int 32 + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + BinOp.add (| + M.get_name (| globals, "GAS_IDENTITY" |), + BinOp.mult (| + M.get_name (| globals, "GAS_IDENTITY_WORD" |), + M.get_name (| globals, "word_count" |) + |) + |) + ], + make_dict [] + |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, "evm" |), "output" |), + M.get_name (| globals, "data" |) + |) in + M.pure Constant.None_)). diff --git a/CoqOfPython/ethereum/shanghai/vm/precompiled_contracts/mapping.v b/CoqOfPython/ethereum/shanghai/vm/precompiled_contracts/mapping.v new file mode 100644 index 0000000..9fd8e82 --- /dev/null +++ b/CoqOfPython/ethereum/shanghai/vm/precompiled_contracts/mapping.v @@ -0,0 +1,72 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.shanghai.vm.precompiled_contracts.mapping". + +Definition expr_1 : Value.t := + Constant.str " +Precompiled Contract Addresses +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Mapping of precompiled contracts their implementations. +". + +Axiom typing_imports_Callable : + IsImported globals "typing" "Callable". +Axiom typing_imports_Dict : + IsImported globals "typing" "Dict". + +Axiom ethereum_shanghai_fork_types_imports_Address : + IsImported globals "ethereum.shanghai.fork_types" "Address". + +Axiom ethereum_shanghai_vm_precompiled_contracts_imports_ALT_BN128_ADD_ADDRESS : + IsImported globals "ethereum.shanghai.vm.precompiled_contracts" "ALT_BN128_ADD_ADDRESS". +Axiom ethereum_shanghai_vm_precompiled_contracts_imports_ALT_BN128_MUL_ADDRESS : + IsImported globals "ethereum.shanghai.vm.precompiled_contracts" "ALT_BN128_MUL_ADDRESS". +Axiom ethereum_shanghai_vm_precompiled_contracts_imports_ALT_BN128_PAIRING_CHECK_ADDRESS : + IsImported globals "ethereum.shanghai.vm.precompiled_contracts" "ALT_BN128_PAIRING_CHECK_ADDRESS". +Axiom ethereum_shanghai_vm_precompiled_contracts_imports_BLAKE2F_ADDRESS : + IsImported globals "ethereum.shanghai.vm.precompiled_contracts" "BLAKE2F_ADDRESS". +Axiom ethereum_shanghai_vm_precompiled_contracts_imports_ECRECOVER_ADDRESS : + IsImported globals "ethereum.shanghai.vm.precompiled_contracts" "ECRECOVER_ADDRESS". +Axiom ethereum_shanghai_vm_precompiled_contracts_imports_IDENTITY_ADDRESS : + IsImported globals "ethereum.shanghai.vm.precompiled_contracts" "IDENTITY_ADDRESS". +Axiom ethereum_shanghai_vm_precompiled_contracts_imports_MODEXP_ADDRESS : + IsImported globals "ethereum.shanghai.vm.precompiled_contracts" "MODEXP_ADDRESS". +Axiom ethereum_shanghai_vm_precompiled_contracts_imports_RIPEMD160_ADDRESS : + IsImported globals "ethereum.shanghai.vm.precompiled_contracts" "RIPEMD160_ADDRESS". +Axiom ethereum_shanghai_vm_precompiled_contracts_imports_SHA256_ADDRESS : + IsImported globals "ethereum.shanghai.vm.precompiled_contracts" "SHA256_ADDRESS". + +Axiom ethereum_shanghai_vm_precompiled_contracts_alt_bn128_imports_alt_bn128_add : + IsImported globals "ethereum.shanghai.vm.precompiled_contracts.alt_bn128" "alt_bn128_add". +Axiom ethereum_shanghai_vm_precompiled_contracts_alt_bn128_imports_alt_bn128_mul : + IsImported globals "ethereum.shanghai.vm.precompiled_contracts.alt_bn128" "alt_bn128_mul". +Axiom ethereum_shanghai_vm_precompiled_contracts_alt_bn128_imports_alt_bn128_pairing_check : + IsImported globals "ethereum.shanghai.vm.precompiled_contracts.alt_bn128" "alt_bn128_pairing_check". + +Axiom ethereum_shanghai_vm_precompiled_contracts_blake2f_imports_blake2f : + IsImported globals "ethereum.shanghai.vm.precompiled_contracts.blake2f" "blake2f". + +Axiom ethereum_shanghai_vm_precompiled_contracts_ecrecover_imports_ecrecover : + IsImported globals "ethereum.shanghai.vm.precompiled_contracts.ecrecover" "ecrecover". + +Axiom ethereum_shanghai_vm_precompiled_contracts_identity_imports_identity : + IsImported globals "ethereum.shanghai.vm.precompiled_contracts.identity" "identity". + +Axiom ethereum_shanghai_vm_precompiled_contracts_modexp_imports_modexp : + IsImported globals "ethereum.shanghai.vm.precompiled_contracts.modexp" "modexp". + +Axiom ethereum_shanghai_vm_precompiled_contracts_ripemd160_imports_ripemd160 : + IsImported globals "ethereum.shanghai.vm.precompiled_contracts.ripemd160" "ripemd160". + +Axiom ethereum_shanghai_vm_precompiled_contracts_sha256_imports_sha256 : + IsImported globals "ethereum.shanghai.vm.precompiled_contracts.sha256" "sha256". + +(* At top_level_stmt: unsupported node type: AnnAssign *) diff --git a/CoqOfPython/ethereum/shanghai/vm/precompiled_contracts/modexp.v b/CoqOfPython/ethereum/shanghai/vm/precompiled_contracts/modexp.v new file mode 100644 index 0000000..9c94a82 --- /dev/null +++ b/CoqOfPython/ethereum/shanghai/vm/precompiled_contracts/modexp.v @@ -0,0 +1,676 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.shanghai.vm.precompiled_contracts.modexp". + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) MODEXP PRECOMPILED CONTRACT +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementation of the `MODEXP` precompiled contract. +". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_Bytes : + IsImported globals "ethereum.base_types" "Bytes". +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". + +Axiom ethereum_shanghai_vm_imports_Evm : + IsImported globals "ethereum.shanghai.vm" "Evm". + +Axiom ethereum_shanghai_vm_gas_imports_charge_gas : + IsImported globals "ethereum.shanghai.vm.gas" "charge_gas". + +Axiom ethereum_shanghai_vm_memory_imports_buffer_read : + IsImported globals "ethereum.shanghai.vm.memory" "buffer_read". + +Definition GQUADDIVISOR : Value.t := M.run ltac:(M.monadic ( + Constant.int 3 +)). + +Definition modexp : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Calculates `(base**exp) % modulus` for arbitrary sized `base`, `exp` and. + `modulus`. The return value is the same length as the modulus. + " in + let _ := M.assign_local (| + "data" , + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "data" |) + |) in + let _ := M.assign_local (| + "base_length" , + M.call (| + M.get_field (| M.get_name (| globals, "U256" |), "from_be_bytes" |), + make_list [ + M.call (| + M.get_name (| globals, "buffer_read" |), + make_list [ + M.get_name (| globals, "data" |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 32 + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "exp_length" , + M.call (| + M.get_field (| M.get_name (| globals, "U256" |), "from_be_bytes" |), + make_list [ + M.call (| + M.get_name (| globals, "buffer_read" |), + make_list [ + M.get_name (| globals, "data" |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 32 + ], + make_dict [] + |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 32 + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "modulus_length" , + M.call (| + M.get_field (| M.get_name (| globals, "U256" |), "from_be_bytes" |), + make_list [ + M.call (| + M.get_name (| globals, "buffer_read" |), + make_list [ + M.get_name (| globals, "data" |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 64 + ], + make_dict [] + |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 32 + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "exp_start" , + BinOp.add (| + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 96 + ], + make_dict [] + |), + M.get_name (| globals, "base_length" |) + |) + |) in + let _ := M.assign_local (| + "exp_head" , + M.call (| + M.get_field (| M.get_name (| globals, "Uint" |), "from_be_bytes" |), + make_list [ + M.call (| + M.get_name (| globals, "buffer_read" |), + make_list [ + M.get_name (| globals, "data" |); + M.get_name (| globals, "exp_start" |); + M.call (| + M.get_name (| globals, "min" |), + make_list [ + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 32 + ], + make_dict [] + |); + M.get_name (| globals, "exp_length" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.call (| + M.get_name (| globals, "gas_cost" |), + make_list [ + M.get_name (| globals, "base_length" |); + M.get_name (| globals, "modulus_length" |); + M.get_name (| globals, "exp_length" |); + M.get_name (| globals, "exp_head" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + BoolOp.and (| + Compare.eq (| + M.get_name (| globals, "base_length" |), + Constant.int 0 + |), + ltac:(M.monadic ( + Compare.eq (| + M.get_name (| globals, "modulus_length" |), + Constant.int 0 + |) + )) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign (| + M.get_field (| M.get_name (| globals, "evm" |), "output" |), + M.call (| + M.get_name (| globals, "Bytes" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.return_ (| + Constant.None_ + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "base" , + M.call (| + M.get_field (| M.get_name (| globals, "Uint" |), "from_be_bytes" |), + make_list [ + M.call (| + M.get_name (| globals, "buffer_read" |), + make_list [ + M.get_name (| globals, "data" |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 96 + ], + make_dict [] + |); + M.get_name (| globals, "base_length" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "exp" , + M.call (| + M.get_field (| M.get_name (| globals, "Uint" |), "from_be_bytes" |), + make_list [ + M.call (| + M.get_name (| globals, "buffer_read" |), + make_list [ + M.get_name (| globals, "data" |); + M.get_name (| globals, "exp_start" |); + M.get_name (| globals, "exp_length" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "modulus_start" , + BinOp.add (| + M.get_name (| globals, "exp_start" |), + M.get_name (| globals, "exp_length" |) + |) + |) in + let _ := M.assign_local (| + "modulus" , + M.call (| + M.get_field (| M.get_name (| globals, "Uint" |), "from_be_bytes" |), + make_list [ + M.call (| + M.get_name (| globals, "buffer_read" |), + make_list [ + M.get_name (| globals, "data" |); + M.get_name (| globals, "modulus_start" |); + M.get_name (| globals, "modulus_length" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, "modulus" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign (| + M.get_field (| M.get_name (| globals, "evm" |), "output" |), + BinOp.mult (| + M.call (| + M.get_name (| globals, "Bytes" |), + make_list [ + Constant.bytes "00" + ], + make_dict [] + |), + M.get_name (| globals, "modulus_length" |) + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign (| + M.get_field (| M.get_name (| globals, "evm" |), "output" |), + M.call (| + M.get_field (| M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, "pow" |), + make_list [ + M.get_name (| globals, "base" |); + M.get_name (| globals, "exp" |); + M.get_name (| globals, "modulus" |) + ], + make_dict [] + |) + ], + make_dict [] + |), "to_bytes" |), + make_list [ + M.get_name (| globals, "modulus_length" |); + Constant.str "big" + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_)). + +Definition complexity : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "base_length"; "modulus_length" ] |) in + let _ := Constant.str " + Estimate the complexity of performing a modular exponentiation. + + Parameters + ---------- + + base_length : + Length of the array representing the base integer. + + modulus_length : + Length of the array representing the modulus integer. + + Returns + ------- + + complexity : `Uint` + Complexity of performing the operation. + " in + let _ := M.assign_local (| + "max_length" , + M.call (| + M.get_name (| globals, "max" |), + make_list [ + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.get_name (| globals, "base_length" |) + ], + make_dict [] + |); + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.get_name (| globals, "modulus_length" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "words" , + BinOp.floor_div (| + BinOp.add (| + M.get_name (| globals, "max_length" |), + Constant.int 7 + |), + Constant.int 8 + |) + |) in + let _ := M.return_ (| + BinOp.pow (| + M.get_name (| globals, "words" |), + Constant.int 2 + |) + |) in + M.pure Constant.None_)). + +Definition iterations : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "exponent_length"; "exponent_head" ] |) in + let _ := Constant.str " + Calculate the number of iterations required to perform a modular + exponentiation. + + Parameters + ---------- + + exponent_length : + Length of the array representing the exponent integer. + + exponent_head : + First 32 bytes of the exponent (with leading zero padding if it is + shorter than 32 bytes), as an unsigned integer. + + Returns + ------- + + iterations : `Uint` + Number of iterations. + " in + let _ := + (* if *) + M.if_then_else (| + BoolOp.and (| + Compare.lt_e (| + M.get_name (| globals, "exponent_length" |), + Constant.int 32 + |), + ltac:(M.monadic ( + Compare.eq (| + M.get_name (| globals, "exponent_head" |), + Constant.int 0 + |) + )) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "count" , + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + Compare.lt_e (| + M.get_name (| globals, "exponent_length" |), + Constant.int 32 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "bit_length" , + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.call (| + M.get_field (| M.get_name (| globals, "exponent_head" |), "bit_length" |), + make_list [], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.gt (| + M.get_name (| globals, "bit_length" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_op_local (| + BinOp.sub, + "bit_length", + Constant.int 1 + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "count" , + M.get_name (| globals, "bit_length" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "length_part" , + BinOp.mult (| + Constant.int 8, + BinOp.sub (| + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.get_name (| globals, "exponent_length" |) + ], + make_dict [] + |), + Constant.int 32 + |) + |) + |) in + let _ := M.assign_local (| + "bits_part" , + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.call (| + M.get_field (| M.get_name (| globals, "exponent_head" |), "bit_length" |), + make_list [], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.gt (| + M.get_name (| globals, "bits_part" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_op_local (| + BinOp.sub, + "bits_part", + Constant.int 1 + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "count" , + BinOp.add (| + M.get_name (| globals, "length_part" |), + M.get_name (| globals, "bits_part" |) + |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )) |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, "max" |), + make_list [ + M.get_name (| globals, "count" |); + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 1 + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Definition gas_cost : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "base_length"; "modulus_length"; "exponent_length"; "exponent_head" ] |) in + let _ := Constant.str " + Calculate the gas cost of performing a modular exponentiation. + + Parameters + ---------- + + base_length : + Length of the array representing the base integer. + + modulus_length : + Length of the array representing the modulus integer. + + exponent_length : + Length of the array representing the exponent integer. + + exponent_head : + First 32 bytes of the exponent (with leading zero padding if it is + shorter than 32 bytes), as an unsigned integer. + + Returns + ------- + + gas_cost : `Uint` + Gas required for performing the operation. + " in + let _ := M.assign_local (| + "multiplication_complexity" , + M.call (| + M.get_name (| globals, "complexity" |), + make_list [ + M.get_name (| globals, "base_length" |); + M.get_name (| globals, "modulus_length" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "iteration_count" , + M.call (| + M.get_name (| globals, "iterations" |), + make_list [ + M.get_name (| globals, "exponent_length" |); + M.get_name (| globals, "exponent_head" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "cost" , + BinOp.mult (| + M.get_name (| globals, "multiplication_complexity" |), + M.get_name (| globals, "iteration_count" |) + |) + |) in + let _ := M.assign_op_local (| + BinOp.floor_div, + "cost", + M.get_name (| globals, "GQUADDIVISOR" |) + |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, "max" |), + make_list [ + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 200 + ], + make_dict [] + |); + M.get_name (| globals, "cost" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). diff --git a/CoqOfPython/ethereum/shanghai/vm/precompiled_contracts/ripemd160.v b/CoqOfPython/ethereum/shanghai/vm/precompiled_contracts/ripemd160.v new file mode 100644 index 0000000..9ca951c --- /dev/null +++ b/CoqOfPython/ethereum/shanghai/vm/precompiled_contracts/ripemd160.v @@ -0,0 +1,125 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.shanghai.vm.precompiled_contracts.ripemd160". + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) RIPEMD160 PRECOMPILED CONTRACT +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementation of the `RIPEMD160` precompiled contract. +". + +(* At top_level_stmt: unsupported node type: Import *) + +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". + +Axiom ethereum_utils_byte_imports_left_pad_zero_bytes : + IsImported globals "ethereum.utils.byte" "left_pad_zero_bytes". + +Axiom ethereum_utils_numeric_imports_ceil32 : + IsImported globals "ethereum.utils.numeric" "ceil32". + +Axiom ethereum_shanghai_vm_imports_Evm : + IsImported globals "ethereum.shanghai.vm" "Evm". + +Axiom ethereum_shanghai_vm_gas_imports_GAS_RIPEMD160 : + IsImported globals "ethereum.shanghai.vm.gas" "GAS_RIPEMD160". +Axiom ethereum_shanghai_vm_gas_imports_GAS_RIPEMD160_WORD : + IsImported globals "ethereum.shanghai.vm.gas" "GAS_RIPEMD160_WORD". +Axiom ethereum_shanghai_vm_gas_imports_charge_gas : + IsImported globals "ethereum.shanghai.vm.gas" "charge_gas". + +Definition ripemd160 : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Writes the ripemd160 hash to output. + + Parameters + ---------- + evm : + The current EVM frame. + " in + let _ := M.assign_local (| + "data" , + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "data" |) + |) in + let _ := M.assign_local (| + "word_count" , + BinOp.floor_div (| + M.call (| + M.get_name (| globals, "ceil32" |), + make_list [ + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_name (| globals, "data" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |), + Constant.int 32 + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + BinOp.add (| + M.get_name (| globals, "GAS_RIPEMD160" |), + BinOp.mult (| + M.get_name (| globals, "GAS_RIPEMD160_WORD" |), + M.get_name (| globals, "word_count" |) + |) + |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "hash_bytes" , + M.call (| + M.get_field (| M.call (| + M.get_field (| M.get_name (| globals, "hashlib" |), "new" |), + make_list [ + Constant.str "ripemd160"; + M.get_name (| globals, "data" |) + ], + make_dict [] + |), "digest" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "padded_hash" , + M.call (| + M.get_name (| globals, "left_pad_zero_bytes" |), + make_list [ + M.get_name (| globals, "hash_bytes" |); + Constant.int 32 + ], + make_dict [] + |) + |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, "evm" |), "output" |), + M.get_name (| globals, "padded_hash" |) + |) in + M.pure Constant.None_)). diff --git a/CoqOfPython/ethereum/shanghai/vm/precompiled_contracts/sha256.v b/CoqOfPython/ethereum/shanghai/vm/precompiled_contracts/sha256.v new file mode 100644 index 0000000..d8d222a --- /dev/null +++ b/CoqOfPython/ethereum/shanghai/vm/precompiled_contracts/sha256.v @@ -0,0 +1,106 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.shanghai.vm.precompiled_contracts.sha256". + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) SHA256 PRECOMPILED CONTRACT +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementation of the `SHA256` precompiled contract. +". + +(* At top_level_stmt: unsupported node type: Import *) + +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". + +Axiom ethereum_utils_numeric_imports_ceil32 : + IsImported globals "ethereum.utils.numeric" "ceil32". + +Axiom ethereum_shanghai_vm_imports_Evm : + IsImported globals "ethereum.shanghai.vm" "Evm". + +Axiom ethereum_shanghai_vm_gas_imports_GAS_SHA256 : + IsImported globals "ethereum.shanghai.vm.gas" "GAS_SHA256". +Axiom ethereum_shanghai_vm_gas_imports_GAS_SHA256_WORD : + IsImported globals "ethereum.shanghai.vm.gas" "GAS_SHA256_WORD". +Axiom ethereum_shanghai_vm_gas_imports_charge_gas : + IsImported globals "ethereum.shanghai.vm.gas" "charge_gas". + +Definition sha256 : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Writes the sha256 hash to output. + + Parameters + ---------- + evm : + The current EVM frame. + " in + let _ := M.assign_local (| + "data" , + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "data" |) + |) in + let _ := M.assign_local (| + "word_count" , + BinOp.floor_div (| + M.call (| + M.get_name (| globals, "ceil32" |), + make_list [ + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_name (| globals, "data" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |), + Constant.int 32 + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + BinOp.add (| + M.get_name (| globals, "GAS_SHA256" |), + BinOp.mult (| + M.get_name (| globals, "GAS_SHA256_WORD" |), + M.get_name (| globals, "word_count" |) + |) + |) + ], + make_dict [] + |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, "evm" |), "output" |), + M.call (| + M.get_field (| M.call (| + M.get_field (| M.get_name (| globals, "hashlib" |), "sha256" |), + make_list [ + M.get_name (| globals, "data" |) + ], + make_dict [] + |), "digest" |), + make_list [], + make_dict [] + |) + |) in + M.pure Constant.None_)). diff --git a/CoqOfPython/ethereum/shanghai/vm/runtime.v b/CoqOfPython/ethereum/shanghai/vm/runtime.v new file mode 100644 index 0000000..44bf9bf --- /dev/null +++ b/CoqOfPython/ethereum/shanghai/vm/runtime.v @@ -0,0 +1,157 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.shanghai.vm.runtime". + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) Runtime Operations +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Runtime related operations used while executing EVM code. +". + +Axiom typing_imports_Set : + IsImported globals "typing" "Set". + +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". + +Axiom ethereum_shanghai_vm_instructions_imports_Ops : + IsImported globals "ethereum.shanghai.vm.instructions" "Ops". + +Definition get_valid_jump_destinations : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "code" ] |) in + let _ := Constant.str " + Analyze the evm code to obtain the set of valid jump destinations. + + Valid jump destinations are defined as follows: + * The jump destination is less than the length of the code. + * The jump destination should have the `JUMPDEST` opcode (0x5B). + * The jump destination shouldn't be part of the data corresponding to + `PUSH-N` opcodes. + + Note - Jump destinations are 0-indexed. + + Parameters + ---------- + code : + The EVM code which is to be executed. + + Returns + ------- + valid_jump_destinations: `Set[Uint]` + The set of valid jump destinations in the code. + " in + let _ := M.assign_local (| + "valid_jump_destinations" , + M.call (| + M.get_name (| globals, "set" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "pc" , + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + |) in + let _ := + M.while (| + Compare.lt (| + M.get_name (| globals, "pc" |), + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_name (| globals, "code" |) + ], + make_dict [] + |) + |), + ltac:(M.monadic ( +(* At stmt: unsupported node type: Try *) + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, "current_opcode" |), + M.get_field (| M.get_name (| globals, "Ops" |), "JUMPDEST" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_field (| M.get_name (| globals, "valid_jump_destinations" |), "add" |), + make_list [ + M.get_name (| globals, "pc" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + BoolOp.and (| + Compare.lt_e (| + M.get_field (| M.get_field (| M.get_name (| globals, "Ops" |), "PUSH1" |), "value" |), + M.get_field (| M.get_name (| globals, "current_opcode" |), "value" |) + |), + ltac:(M.monadic ( + Compare.lt_e (| + M.get_field (| M.get_name (| globals, "current_opcode" |), "value" |), + M.get_field (| M.get_field (| M.get_name (| globals, "Ops" |), "PUSH32" |), "value" |) + |) + )) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "push_data_size" , + BinOp.add (| + BinOp.sub (| + M.get_field (| M.get_name (| globals, "current_opcode" |), "value" |), + M.get_field (| M.get_field (| M.get_name (| globals, "Ops" |), "PUSH1" |), "value" |) + |), + Constant.int 1 + |) + |) in + let _ := M.assign_op_local (| + BinOp.add, + "pc", + M.get_name (| globals, "push_data_size" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )) |) in + let _ := M.assign_op_local (| + BinOp.add, + "pc", + Constant.int 1 + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := M.return_ (| + M.get_name (| globals, "valid_jump_destinations" |) + |) in + M.pure Constant.None_)). diff --git a/CoqOfPython/ethereum/shanghai/vm/stack.v b/CoqOfPython/ethereum/shanghai/vm/stack.v new file mode 100644 index 0000000..cbab960 --- /dev/null +++ b/CoqOfPython/ethereum/shanghai/vm/stack.v @@ -0,0 +1,123 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.shanghai.vm.stack". + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) Stack +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementation of the stack operators for the EVM. +". + +Axiom typing_imports_List : + IsImported globals "typing" "List". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". + +Axiom ethereum_shanghai_vm_exceptions_imports_StackOverflowError : + IsImported globals "ethereum.shanghai.vm.exceptions" "StackOverflowError". +Axiom ethereum_shanghai_vm_exceptions_imports_StackUnderflowError : + IsImported globals "ethereum.shanghai.vm.exceptions" "StackUnderflowError". + +Definition pop : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "stack" ] |) in + let _ := Constant.str " + Pops the top item off of `stack`. + + Parameters + ---------- + stack : + EVM stack. + + Returns + ------- + value : `U256` + The top element on the stack. + + " in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_name (| globals, "stack" |) + ], + make_dict [] + |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, "StackUnderflowError" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.return_ (| + M.call (| + M.get_field (| M.get_name (| globals, "stack" |), "pop" |), + make_list [], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Definition push : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "stack"; "value" ] |) in + let _ := Constant.str " + Pushes `value` onto `stack`. + + Parameters + ---------- + stack : + EVM stack. + + value : + Item to be pushed onto `stack`. + + " in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_name (| globals, "stack" |) + ], + make_dict [] + |), + Constant.int 1024 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, "StackOverflowError" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.return_ (| + M.call (| + M.get_field (| M.get_name (| globals, "stack" |), "append" |), + make_list [ + M.get_name (| globals, "value" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). diff --git a/CoqOfPython/ethereum/spurious_dragon/__init__.v b/CoqOfPython/ethereum/spurious_dragon/__init__.v new file mode 100644 index 0000000..1f1b6ac --- /dev/null +++ b/CoqOfPython/ethereum/spurious_dragon/__init__.v @@ -0,0 +1,25 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.spurious_dragon.__init__". + +Definition expr_1 : Value.t := + Constant.str " +The Spurious Dragon fork is the second of two forks responding to a +denial-of-service attack on the Ethereum network. It tunes the prices of EVM +instructions, adds protection against replaying transaction on different +chains, limits the maximum size of contract code, and enables the removal of +empty accounts. +". + +Axiom ethereum_fork_criteria_imports_ByBlockNumber : + IsImported globals "ethereum.fork_criteria" "ByBlockNumber". + +Definition FORK_CRITERIA : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "ByBlockNumber" |), + make_list [ + Constant.int 2675000 + ], + make_dict [] + |) +)). diff --git a/CoqOfPython/ethereum/spurious_dragon/blocks.v b/CoqOfPython/ethereum/spurious_dragon/blocks.v new file mode 100644 index 0000000..1057a2e --- /dev/null +++ b/CoqOfPython/ethereum/spurious_dragon/blocks.v @@ -0,0 +1,87 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.spurious_dragon.blocks". + +Definition expr_1 : Value.t := + Constant.str " +A `Block` is a single link in the chain that is Ethereum. Each `Block` contains +a `Header` and zero or more transactions. Each `Header` contains associated +metadata like the block number, parent block hash, and how much gas was +consumed by its transactions. + +Together, these blocks form a cryptographically secure journal recording the +history of all state transitions that have happened since the genesis of the +chain. +". + +Axiom dataclasses_imports_dataclass : + IsImported globals "dataclasses" "dataclass". + +Axiom typing_imports_Tuple : + IsImported globals "typing" "Tuple". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_Bytes : + IsImported globals "ethereum.base_types" "Bytes". +Axiom ethereum_base_types_imports_Bytes8 : + IsImported globals "ethereum.base_types" "Bytes8". +Axiom ethereum_base_types_imports_Bytes32 : + IsImported globals "ethereum.base_types" "Bytes32". +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". +Axiom ethereum_base_types_imports_slotted_freezable : + IsImported globals "ethereum.base_types" "slotted_freezable". + +Axiom ethereum_crypto_hash_imports_Hash32 : + IsImported globals "ethereum.crypto.hash" "Hash32". + +Axiom ethereum_spurious_dragon_fork_types_imports_Address : + IsImported globals "ethereum.spurious_dragon.fork_types" "Address". +Axiom ethereum_spurious_dragon_fork_types_imports_Bloom : + IsImported globals "ethereum.spurious_dragon.fork_types" "Bloom". +Axiom ethereum_spurious_dragon_fork_types_imports_Root : + IsImported globals "ethereum.spurious_dragon.fork_types" "Root". + +Axiom ethereum_spurious_dragon_transactions_imports_Transaction : + IsImported globals "ethereum.spurious_dragon.transactions" "Transaction". + +Definition Header : Value.t := + builtins.make_klass + [] + [ + + ] + [ + + ]. + +Definition Block : Value.t := + builtins.make_klass + [] + [ + + ] + [ + + ]. + +Definition Log : Value.t := + builtins.make_klass + [] + [ + + ] + [ + + ]. + +Definition Receipt : Value.t := + builtins.make_klass + [] + [ + + ] + [ + + ]. diff --git a/CoqOfPython/ethereum/spurious_dragon/bloom.v b/CoqOfPython/ethereum/spurious_dragon/bloom.v new file mode 100644 index 0000000..ba09205 --- /dev/null +++ b/CoqOfPython/ethereum/spurious_dragon/bloom.v @@ -0,0 +1,207 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.spurious_dragon.bloom". + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Logs Bloom +^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +This modules defines functions for calculating bloom filters of logs. For the +general theory of bloom filters see e.g. `Wikipedia +`_. Bloom filters are used to allow +for efficient searching of logs by address and/or topic, by rapidly +eliminating blocks and receipts from their search. +". + +Axiom typing_imports_Tuple : + IsImported globals "typing" "Tuple". + +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". + +Axiom ethereum_crypto_hash_imports_keccak256 : + IsImported globals "ethereum.crypto.hash" "keccak256". + +Axiom ethereum_spurious_dragon_blocks_imports_Log : + IsImported globals "ethereum.spurious_dragon.blocks" "Log". + +Axiom ethereum_spurious_dragon_fork_types_imports_Bloom : + IsImported globals "ethereum.spurious_dragon.fork_types" "Bloom". + +Definition add_to_bloom : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "bloom"; "bloom_entry" ] |) in + let _ := Constant.str " + Add a bloom entry to the bloom filter (`bloom`). + + The number of hash functions used is 3. They are calculated by taking the + least significant 11 bits from the first 3 16-bit words of the + `keccak_256()` hash of `bloom_entry`. + + Parameters + ---------- + bloom : + The bloom filter. + bloom_entry : + An entry which is to be added to bloom filter. + " in + let _ := M.assign_local (| + "hash" , + M.call (| + M.get_name (| globals, "keccak256" |), + make_list [ + M.get_name (| globals, "bloom_entry" |) + ], + make_dict [] + |) + |) in + let _ := + M.for_ (| + M.get_name (| globals, "idx" |), + make_tuple [ Constant.int 0; Constant.int 2; Constant.int 4 ], + ltac:(M.monadic ( + let _ := M.assign_local (| + "bit_to_set" , + BinOp.bit_and (| + M.call (| + M.get_field (| M.get_name (| globals, "Uint" |), "from_be_bytes" |), + make_list [ + M.slice (| + M.get_name (| globals, "hash" |), + M.get_name (| globals, "idx" |), + BinOp.add (| + M.get_name (| globals, "idx" |), + Constant.int 2 + |), + Constant.None_ + |) + ], + make_dict [] + |), + Constant.int 2047 + |) + |) in + let _ := M.assign_local (| + "bit_index" , + BinOp.sub (| + Constant.int 2047, + M.get_name (| globals, "bit_to_set" |) + |) + |) in + let _ := M.assign_local (| + "byte_index" , + BinOp.floor_div (| + M.get_name (| globals, "bit_index" |), + Constant.int 8 + |) + |) in + let _ := M.assign_local (| + "bit_value" , + BinOp.l_shift (| + Constant.int 1, + BinOp.sub (| + Constant.int 7, + BinOp.mod_ (| + M.get_name (| globals, "bit_index" |), + Constant.int 8 + |) + |) + |) + |) in + let _ := M.assign (| + M.get_subscript (| + M.get_name (| globals, "bloom" |), + M.get_name (| globals, "byte_index" |) + |), + BinOp.bit_or (| + M.get_subscript (| + M.get_name (| globals, "bloom" |), + M.get_name (| globals, "byte_index" |) + |), + M.get_name (| globals, "bit_value" |) + |) + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + M.pure Constant.None_)). + +Definition logs_bloom : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "logs" ] |) in + let _ := Constant.str " + Obtain the logs bloom from a list of log entries. + + The address and each topic of a log are added to the bloom filter. + + Parameters + ---------- + logs : + List of logs for which the logs bloom is to be obtained. + + Returns + ------- + logs_bloom : `Bloom` + The logs bloom obtained which is 256 bytes with some bits set as per + the caller address and the log topics. + " in +(* At stmt: unsupported node type: AnnAssign *) + let _ := + M.for_ (| + M.get_name (| globals, "log" |), + M.get_name (| globals, "logs" |), + ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, "add_to_bloom" |), + make_list [ + M.get_name (| globals, "bloom" |); + M.get_field (| M.get_name (| globals, "log" |), "address" |) + ], + make_dict [] + |) in + let _ := + M.for_ (| + M.get_name (| globals, "topic" |), + M.get_field (| M.get_name (| globals, "log" |), "topics" |), + ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, "add_to_bloom" |), + make_list [ + M.get_name (| globals, "bloom" |); + M.get_name (| globals, "topic" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, "Bloom" |), + make_list [ + M.get_name (| globals, "bloom" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). diff --git a/CoqOfPython/ethereum/spurious_dragon/fork.v b/CoqOfPython/ethereum/spurious_dragon/fork.v new file mode 100644 index 0000000..db39a8f --- /dev/null +++ b/CoqOfPython/ethereum/spurious_dragon/fork.v @@ -0,0 +1,2621 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.spurious_dragon.fork". + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Specification +^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Entry point for the Ethereum specification. +". + +Axiom dataclasses_imports_dataclass : + IsImported globals "dataclasses" "dataclass". + +Axiom typing_imports_List : + IsImported globals "typing" "List". +Axiom typing_imports_Optional : + IsImported globals "typing" "Optional". +Axiom typing_imports_Set : + IsImported globals "typing" "Set". +Axiom typing_imports_Tuple : + IsImported globals "typing" "Tuple". + +Axiom ethereum_base_types_imports_Bytes0 : + IsImported globals "ethereum.base_types" "Bytes0". + +Axiom ethereum_crypto_elliptic_curve_imports_SECP256K1N : + IsImported globals "ethereum.crypto.elliptic_curve" "SECP256K1N". +Axiom ethereum_crypto_elliptic_curve_imports_secp256k1_recover : + IsImported globals "ethereum.crypto.elliptic_curve" "secp256k1_recover". + +Axiom ethereum_crypto_hash_imports_Hash32 : + IsImported globals "ethereum.crypto.hash" "Hash32". +Axiom ethereum_crypto_hash_imports_keccak256 : + IsImported globals "ethereum.crypto.hash" "keccak256". + +Axiom ethereum_ethash_imports_dataset_size : + IsImported globals "ethereum.ethash" "dataset_size". +Axiom ethereum_ethash_imports_generate_cache : + IsImported globals "ethereum.ethash" "generate_cache". +Axiom ethereum_ethash_imports_hashimoto_light : + IsImported globals "ethereum.ethash" "hashimoto_light". + +Axiom ethereum_exceptions_imports_InvalidBlock : + IsImported globals "ethereum.exceptions" "InvalidBlock". + +Axiom ethereum_utils_ensure_imports_ensure : + IsImported globals "ethereum.utils.ensure" "ensure". + +Axiom ethereum_imports_rlp : + IsImported globals "ethereum" "rlp". + +Axiom ethereum_base_types_imports_U64 : + IsImported globals "ethereum.base_types" "U64". +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_U256_CEIL_VALUE : + IsImported globals "ethereum.base_types" "U256_CEIL_VALUE". +Axiom ethereum_base_types_imports_Bytes : + IsImported globals "ethereum.base_types" "Bytes". +Axiom ethereum_base_types_imports_Bytes32 : + IsImported globals "ethereum.base_types" "Bytes32". +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". + +Axiom ethereum_spurious_dragon_imports_vm : + IsImported globals "ethereum.spurious_dragon" "vm". + +Axiom ethereum_spurious_dragon_blocks_imports_Block : + IsImported globals "ethereum.spurious_dragon.blocks" "Block". +Axiom ethereum_spurious_dragon_blocks_imports_Header : + IsImported globals "ethereum.spurious_dragon.blocks" "Header". +Axiom ethereum_spurious_dragon_blocks_imports_Log : + IsImported globals "ethereum.spurious_dragon.blocks" "Log". +Axiom ethereum_spurious_dragon_blocks_imports_Receipt : + IsImported globals "ethereum.spurious_dragon.blocks" "Receipt". + +Axiom ethereum_spurious_dragon_bloom_imports_logs_bloom : + IsImported globals "ethereum.spurious_dragon.bloom" "logs_bloom". + +Axiom ethereum_spurious_dragon_fork_types_imports_Address : + IsImported globals "ethereum.spurious_dragon.fork_types" "Address". +Axiom ethereum_spurious_dragon_fork_types_imports_Bloom : + IsImported globals "ethereum.spurious_dragon.fork_types" "Bloom". +Axiom ethereum_spurious_dragon_fork_types_imports_Root : + IsImported globals "ethereum.spurious_dragon.fork_types" "Root". + +Axiom ethereum_spurious_dragon_state_imports_State : + IsImported globals "ethereum.spurious_dragon.state" "State". +Axiom ethereum_spurious_dragon_state_imports_account_exists_and_is_empty : + IsImported globals "ethereum.spurious_dragon.state" "account_exists_and_is_empty". +Axiom ethereum_spurious_dragon_state_imports_create_ether : + IsImported globals "ethereum.spurious_dragon.state" "create_ether". +Axiom ethereum_spurious_dragon_state_imports_destroy_account : + IsImported globals "ethereum.spurious_dragon.state" "destroy_account". +Axiom ethereum_spurious_dragon_state_imports_get_account : + IsImported globals "ethereum.spurious_dragon.state" "get_account". +Axiom ethereum_spurious_dragon_state_imports_increment_nonce : + IsImported globals "ethereum.spurious_dragon.state" "increment_nonce". +Axiom ethereum_spurious_dragon_state_imports_set_account_balance : + IsImported globals "ethereum.spurious_dragon.state" "set_account_balance". +Axiom ethereum_spurious_dragon_state_imports_state_root : + IsImported globals "ethereum.spurious_dragon.state" "state_root". + +Axiom ethereum_spurious_dragon_transactions_imports_TX_BASE_COST : + IsImported globals "ethereum.spurious_dragon.transactions" "TX_BASE_COST". +Axiom ethereum_spurious_dragon_transactions_imports_TX_CREATE_COST : + IsImported globals "ethereum.spurious_dragon.transactions" "TX_CREATE_COST". +Axiom ethereum_spurious_dragon_transactions_imports_TX_DATA_COST_PER_NON_ZERO : + IsImported globals "ethereum.spurious_dragon.transactions" "TX_DATA_COST_PER_NON_ZERO". +Axiom ethereum_spurious_dragon_transactions_imports_TX_DATA_COST_PER_ZERO : + IsImported globals "ethereum.spurious_dragon.transactions" "TX_DATA_COST_PER_ZERO". +Axiom ethereum_spurious_dragon_transactions_imports_Transaction : + IsImported globals "ethereum.spurious_dragon.transactions" "Transaction". + +Axiom ethereum_spurious_dragon_trie_imports_Trie : + IsImported globals "ethereum.spurious_dragon.trie" "Trie". +Axiom ethereum_spurious_dragon_trie_imports_root : + IsImported globals "ethereum.spurious_dragon.trie" "root". +Axiom ethereum_spurious_dragon_trie_imports_trie_set : + IsImported globals "ethereum.spurious_dragon.trie" "trie_set". + +Axiom ethereum_spurious_dragon_utils_message_imports_prepare_message : + IsImported globals "ethereum.spurious_dragon.utils.message" "prepare_message". + +Axiom ethereum_spurious_dragon_vm_interpreter_imports_process_message_call : + IsImported globals "ethereum.spurious_dragon.vm.interpreter" "process_message_call". + +Definition BLOCK_REWARD : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + BinOp.mult (| + Constant.int 5, + BinOp.pow (| + Constant.int 10, + Constant.int 18 + |) + |) + ], + make_dict [] + |) +)). + +Definition GAS_LIMIT_ADJUSTMENT_FACTOR : Value.t := M.run ltac:(M.monadic ( + Constant.int 1024 +)). + +Definition GAS_LIMIT_MINIMUM : Value.t := M.run ltac:(M.monadic ( + Constant.int 5000 +)). + +Definition MINIMUM_DIFFICULTY : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 131072 + ], + make_dict [] + |) +)). + +Definition MAX_OMMER_DEPTH : Value.t := M.run ltac:(M.monadic ( + Constant.int 6 +)). + +Definition BlockChain : Value.t := + builtins.make_klass + [] + [ + + ] + [ + + ]. + +Definition apply_fork : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "old" ] |) in + let _ := Constant.str " + Transforms the state from the previous hard fork (`old`) into the block + chain object for this hard fork and returns it. + + When forks need to implement an irregular state transition, this function + is used to handle the irregularity. See the :ref:`DAO Fork ` for + an example. + + Parameters + ---------- + old : + Previous block chain object. + + Returns + ------- + new : `BlockChain` + Upgraded block chain object for this hard fork. + " in + let _ := M.return_ (| + M.get_name (| globals, "old" |) + |) in + M.pure Constant.None_)). + +Definition get_last_256_block_hashes : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "chain" ] |) in + let _ := Constant.str " + Obtain the list of hashes of the previous 256 blocks in order of + increasing block number. + + This function will return less hashes for the first 256 blocks. + + The ``BLOCKHASH`` opcode needs to access the latest hashes on the chain, + therefore this function retrieves them. + + Parameters + ---------- + chain : + History and current state. + + Returns + ------- + recent_block_hashes : `List[Hash32]` + Hashes of the recent 256 blocks in order of increasing block number. + " in + let _ := M.assign_local (| + "recent_blocks" , + M.slice (| + M.get_field (| M.get_name (| globals, "chain" |), "blocks" |), + UnOp.sub (| Constant.int 255 |), + Constant.None_, + Constant.None_ + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_name (| globals, "recent_blocks" |) + ], + make_dict [] + |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + make_list [] + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "recent_block_hashes" , + make_list [] + |) in + let _ := + M.for_ (| + M.get_name (| globals, "block" |), + M.get_name (| globals, "recent_blocks" |), + ltac:(M.monadic ( + let _ := M.assign_local (| + "prev_block_hash" , + M.get_field (| M.get_field (| M.get_name (| globals, "block" |), "header" |), "parent_hash" |) + |) in + let _ := M.call (| + M.get_field (| M.get_name (| globals, "recent_block_hashes" |), "append" |), + make_list [ + M.get_name (| globals, "prev_block_hash" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := M.assign_local (| + "most_recent_block_hash" , + M.call (| + M.get_name (| globals, "keccak256" |), + make_list [ + M.call (| + M.get_field (| M.get_name (| globals, "rlp" |), "encode" |), + make_list [ + M.get_field (| M.get_subscript (| + M.get_name (| globals, "recent_blocks" |), + UnOp.sub (| Constant.int 1 |) + |), "header" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_field (| M.get_name (| globals, "recent_block_hashes" |), "append" |), + make_list [ + M.get_name (| globals, "most_recent_block_hash" |) + ], + make_dict [] + |) in + let _ := M.return_ (| + M.get_name (| globals, "recent_block_hashes" |) + |) in + M.pure Constant.None_)). + +Definition state_transition : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "chain"; "block" ] |) in + let _ := Constant.str " + Attempts to apply a block to an existing block chain. + + All parts of the block's contents need to be verified before being added + to the chain. Blocks are verified by ensuring that the contents of the + block make logical sense with the contents of the parent block. The + information in the block's header must also match the corresponding + information in the block. + + To implement Ethereum, in theory clients are only required to store the + most recent 255 blocks of the chain since as far as execution is + concerned, only those blocks are accessed. Practically, however, clients + should store more blocks to handle reorgs. + + Parameters + ---------- + chain : + History and current state. + block : + Block to apply to `chain`. + " in + let _ := M.assign_local (| + "parent_header" , + M.get_field (| M.get_subscript (| + M.get_field (| M.get_name (| globals, "chain" |), "blocks" |), + UnOp.sub (| Constant.int 1 |) + |), "header" |) + |) in + let _ := M.call (| + M.get_name (| globals, "validate_header" |), + make_list [ + M.get_field (| M.get_name (| globals, "block" |), "header" |); + M.get_name (| globals, "parent_header" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "validate_ommers" |), + make_list [ + M.get_field (| M.get_name (| globals, "block" |), "ommers" |); + M.get_field (| M.get_name (| globals, "block" |), "header" |); + M.get_name (| globals, "chain" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "apply_body_output" , + M.call (| + M.get_name (| globals, "apply_body" |), + make_list [ + M.get_field (| M.get_name (| globals, "chain" |), "state" |); + M.call (| + M.get_name (| globals, "get_last_256_block_hashes" |), + make_list [ + M.get_name (| globals, "chain" |) + ], + make_dict [] + |); + M.get_field (| M.get_field (| M.get_name (| globals, "block" |), "header" |), "coinbase" |); + M.get_field (| M.get_field (| M.get_name (| globals, "block" |), "header" |), "number" |); + M.get_field (| M.get_field (| M.get_name (| globals, "block" |), "header" |), "gas_limit" |); + M.get_field (| M.get_field (| M.get_name (| globals, "block" |), "header" |), "timestamp" |); + M.get_field (| M.get_field (| M.get_name (| globals, "block" |), "header" |), "difficulty" |); + M.get_field (| M.get_name (| globals, "block" |), "transactions" |); + M.get_field (| M.get_name (| globals, "block" |), "ommers" |); + M.get_field (| M.get_name (| globals, "chain" |), "chain_id" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + Compare.eq (| + M.get_field (| M.get_name (| globals, "apply_body_output" |), "block_gas_used" |), + M.get_field (| M.get_field (| M.get_name (| globals, "block" |), "header" |), "gas_used" |) + |); + M.get_name (| globals, "InvalidBlock" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + Compare.eq (| + M.get_field (| M.get_name (| globals, "apply_body_output" |), "transactions_root" |), + M.get_field (| M.get_field (| M.get_name (| globals, "block" |), "header" |), "transactions_root" |) + |); + M.get_name (| globals, "InvalidBlock" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + Compare.eq (| + M.get_field (| M.get_name (| globals, "apply_body_output" |), "state_root" |), + M.get_field (| M.get_field (| M.get_name (| globals, "block" |), "header" |), "state_root" |) + |); + M.get_name (| globals, "InvalidBlock" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + Compare.eq (| + M.get_field (| M.get_name (| globals, "apply_body_output" |), "receipt_root" |), + M.get_field (| M.get_field (| M.get_name (| globals, "block" |), "header" |), "receipt_root" |) + |); + M.get_name (| globals, "InvalidBlock" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + Compare.eq (| + M.get_field (| M.get_name (| globals, "apply_body_output" |), "block_logs_bloom" |), + M.get_field (| M.get_field (| M.get_name (| globals, "block" |), "header" |), "bloom" |) + |); + M.get_name (| globals, "InvalidBlock" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, "chain" |), "blocks" |), "append" |), + make_list [ + M.get_name (| globals, "block" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.gt (| + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_field (| M.get_name (| globals, "chain" |), "blocks" |) + ], + make_dict [] + |), + Constant.int 255 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign (| + M.get_field (| M.get_name (| globals, "chain" |), "blocks" |), + M.slice (| + M.get_field (| M.get_name (| globals, "chain" |), "blocks" |), + UnOp.sub (| Constant.int 255 |), + Constant.None_, + Constant.None_ + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + M.pure Constant.None_)). + +Definition validate_header : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "header"; "parent_header" ] |) in + let _ := Constant.str " + Verifies a block header. + + In order to consider a block's header valid, the logic for the + quantities in the header should match the logic for the block itself. + For example the header timestamp should be greater than the block's parent + timestamp because the block was created *after* the parent block. + Additionally, the block's number should be directly following the parent + block's number since it is the next block in the sequence. + + Parameters + ---------- + header : + Header to check for correctness. + parent_header : + Parent Header of the header to check for correctness + " in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + Compare.gt (| + M.get_field (| M.get_name (| globals, "header" |), "timestamp" |), + M.get_field (| M.get_name (| globals, "parent_header" |), "timestamp" |) + |); + M.get_name (| globals, "InvalidBlock" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + Compare.eq (| + M.get_field (| M.get_name (| globals, "header" |), "number" |), + BinOp.add (| + M.get_field (| M.get_name (| globals, "parent_header" |), "number" |), + Constant.int 1 + |) + |); + M.get_name (| globals, "InvalidBlock" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + M.call (| + M.get_name (| globals, "check_gas_limit" |), + make_list [ + M.get_field (| M.get_name (| globals, "header" |), "gas_limit" |); + M.get_field (| M.get_name (| globals, "parent_header" |), "gas_limit" |) + ], + make_dict [] + |); + M.get_name (| globals, "InvalidBlock" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + Compare.lt_e (| + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_field (| M.get_name (| globals, "header" |), "extra_data" |) + ], + make_dict [] + |), + Constant.int 32 + |); + M.get_name (| globals, "InvalidBlock" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "block_difficulty" , + M.call (| + M.get_name (| globals, "calculate_block_difficulty" |), + make_list [ + M.get_field (| M.get_name (| globals, "header" |), "number" |); + M.get_field (| M.get_name (| globals, "header" |), "timestamp" |); + M.get_field (| M.get_name (| globals, "parent_header" |), "timestamp" |); + M.get_field (| M.get_name (| globals, "parent_header" |), "difficulty" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + Compare.eq (| + M.get_field (| M.get_name (| globals, "header" |), "difficulty" |), + M.get_name (| globals, "block_difficulty" |) + |); + M.get_name (| globals, "InvalidBlock" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "block_parent_hash" , + M.call (| + M.get_name (| globals, "keccak256" |), + make_list [ + M.call (| + M.get_field (| M.get_name (| globals, "rlp" |), "encode" |), + make_list [ + M.get_name (| globals, "parent_header" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + Compare.eq (| + M.get_field (| M.get_name (| globals, "header" |), "parent_hash" |), + M.get_name (| globals, "block_parent_hash" |) + |); + M.get_name (| globals, "InvalidBlock" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "validate_proof_of_work" |), + make_list [ + M.get_name (| globals, "header" |) + ], + make_dict [] + |) in + M.pure Constant.None_)). + +Definition generate_header_hash_for_pow : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "header" ] |) in + let _ := Constant.str " + Generate rlp hash of the header which is to be used for Proof-of-Work + verification. + + In other words, the PoW artefacts `mix_digest` and `nonce` are ignored + while calculating this hash. + + A particular PoW is valid for a single hash, that hash is computed by + this function. The `nonce` and `mix_digest` are omitted from this hash + because they are being changed by miners in their search for a sufficient + proof-of-work. + + Parameters + ---------- + header : + The header object for which the hash is to be generated. + + Returns + ------- + hash : `Hash32` + The PoW valid rlp hash of the passed in header. + " in + let _ := M.assign_local (| + "header_data_without_pow_artefacts" , + make_list [ + M.get_field (| M.get_name (| globals, "header" |), "parent_hash" |); + M.get_field (| M.get_name (| globals, "header" |), "ommers_hash" |); + M.get_field (| M.get_name (| globals, "header" |), "coinbase" |); + M.get_field (| M.get_name (| globals, "header" |), "state_root" |); + M.get_field (| M.get_name (| globals, "header" |), "transactions_root" |); + M.get_field (| M.get_name (| globals, "header" |), "receipt_root" |); + M.get_field (| M.get_name (| globals, "header" |), "bloom" |); + M.get_field (| M.get_name (| globals, "header" |), "difficulty" |); + M.get_field (| M.get_name (| globals, "header" |), "number" |); + M.get_field (| M.get_name (| globals, "header" |), "gas_limit" |); + M.get_field (| M.get_name (| globals, "header" |), "gas_used" |); + M.get_field (| M.get_name (| globals, "header" |), "timestamp" |); + M.get_field (| M.get_name (| globals, "header" |), "extra_data" |) + ] + |) in + let _ := M.return_ (| + M.call (| + M.get_field (| M.get_name (| globals, "rlp" |), "rlp_hash" |), + make_list [ + M.get_name (| globals, "header_data_without_pow_artefacts" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Definition validate_proof_of_work : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "header" ] |) in + let _ := Constant.str " + Validates the Proof of Work constraints. + + In order to verify that a miner's proof-of-work is valid for a block, a + ``mix-digest`` and ``result`` are calculated using the ``hashimoto_light`` + hash function. The mix digest is a hash of the header and the nonce that + is passed through and it confirms whether or not proof-of-work was done + on the correct block. The result is the actual hash value of the block. + + Parameters + ---------- + header : + Header of interest. + " in + let _ := M.assign_local (| + "header_hash" , + M.call (| + M.get_name (| globals, "generate_header_hash_for_pow" |), + make_list [ + M.get_name (| globals, "header" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "cache" , + M.call (| + M.get_name (| globals, "generate_cache" |), + make_list [ + M.get_field (| M.get_name (| globals, "header" |), "number" |) + ], + make_dict [] + |) + |) in + let _ := M.assign (| + make_tuple [ M.get_name (| globals, "mix_digest" |); M.get_name (| globals, "result" |) ], + M.call (| + M.get_name (| globals, "hashimoto_light" |), + make_list [ + M.get_name (| globals, "header_hash" |); + M.get_field (| M.get_name (| globals, "header" |), "nonce" |); + M.get_name (| globals, "cache" |); + M.call (| + M.get_name (| globals, "dataset_size" |), + make_list [ + M.get_field (| M.get_name (| globals, "header" |), "number" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + Compare.eq (| + M.get_name (| globals, "mix_digest" |), + M.get_field (| M.get_name (| globals, "header" |), "mix_digest" |) + |); + M.get_name (| globals, "InvalidBlock" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + Compare.lt_e (| + M.call (| + M.get_field (| M.get_name (| globals, "Uint" |), "from_be_bytes" |), + make_list [ + M.get_name (| globals, "result" |) + ], + make_dict [] + |), + BinOp.floor_div (| + M.get_name (| globals, "U256_CEIL_VALUE" |), + M.get_field (| M.get_name (| globals, "header" |), "difficulty" |) + |) + |); + M.get_name (| globals, "InvalidBlock" |) + ], + make_dict [] + |) in + M.pure Constant.None_)). + +Definition check_transaction : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "tx"; "gas_available"; "chain_id" ] |) in + let _ := Constant.str " + Check if the transaction is includable in the block. + + Parameters + ---------- + tx : + The transaction. + gas_available : + The gas remaining in the block. + chain_id : + The ID of the current chain. + + Returns + ------- + sender_address : + The sender of the transaction. + + Raises + ------ + InvalidBlock : + If the transaction is not includable. + " in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + Compare.lt_e (| + M.get_field (| M.get_name (| globals, "tx" |), "gas" |), + M.get_name (| globals, "gas_available" |) + |); + M.get_name (| globals, "InvalidBlock" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "sender_address" , + M.call (| + M.get_name (| globals, "recover_sender" |), + make_list [ + M.get_name (| globals, "chain_id" |); + M.get_name (| globals, "tx" |) + ], + make_dict [] + |) + |) in + let _ := M.return_ (| + M.get_name (| globals, "sender_address" |) + |) in + M.pure Constant.None_)). + +Definition make_receipt : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "tx"; "post_state"; "cumulative_gas_used"; "logs" ] |) in + let _ := Constant.str " + Make the receipt for a transaction that was executed. + + Parameters + ---------- + tx : + The executed transaction. + post_state : + The state root immediately after this transaction. + cumulative_gas_used : + The total gas used so far in the block after the transaction was + executed. + logs : + The logs produced by the transaction. + + Returns + ------- + receipt : + The receipt for the transaction. + " in + let _ := M.assign_local (| + "receipt" , + M.call (| + M.get_name (| globals, "Receipt" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.return_ (| + M.get_name (| globals, "receipt" |) + |) in + M.pure Constant.None_)). + +Definition ApplyBodyOutput : Value.t := + builtins.make_klass + [] + [ + + ] + [ + + ]. + +Definition apply_body : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "state"; "block_hashes"; "coinbase"; "block_number"; "block_gas_limit"; "block_time"; "block_difficulty"; "transactions"; "ommers"; "chain_id" ] |) in + let _ := Constant.str " + Executes a block. + + Many of the contents of a block are stored in data structures called + tries. There is a transactions trie which is similar to a ledger of the + transactions stored in the current block. There is also a receipts trie + which stores the results of executing a transaction, like the post state + and gas used. This function creates and executes the block that is to be + added to the chain. + + Parameters + ---------- + state : + Current account state. + block_hashes : + List of hashes of the previous 256 blocks in the order of + increasing block number. + coinbase : + Address of account which receives block reward and transaction fees. + block_number : + Position of the block within the chain. + block_gas_limit : + Initial amount of gas available for execution in this block. + block_time : + Time the block was produced, measured in seconds since the epoch. + block_difficulty : + Difficulty of the block. + transactions : + Transactions included in the block. + ommers : + Headers of ancestor blocks which are not direct parents (formerly + uncles.) + chain_id : + ID of the executing chain. + + Returns + ------- + apply_body_output : `ApplyBodyOutput` + Output of applying the block body to the state. + " in + let _ := M.assign_local (| + "gas_available" , + M.get_name (| globals, "block_gas_limit" |) + |) in +(* At stmt: unsupported node type: AnnAssign *) +(* At stmt: unsupported node type: AnnAssign *) +(* At stmt: unsupported node type: AnnAssign *) + let _ := + M.for_ (| + make_tuple [ M.get_name (| globals, "i" |); M.get_name (| globals, "tx" |) ], + M.call (| + M.get_name (| globals, "enumerate" |), + make_list [ + M.get_name (| globals, "transactions" |) + ], + make_dict [] + |), + ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, "trie_set" |), + make_list [ + M.get_name (| globals, "transactions_trie" |); + M.call (| + M.get_field (| M.get_name (| globals, "rlp" |), "encode" |), + make_list [ + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.get_name (| globals, "i" |) + ], + make_dict [] + |) + ], + make_dict [] + |); + M.get_name (| globals, "tx" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "sender_address" , + M.call (| + M.get_name (| globals, "check_transaction" |), + make_list [ + M.get_name (| globals, "tx" |); + M.get_name (| globals, "gas_available" |); + M.get_name (| globals, "chain_id" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "env" , + M.call (| + M.get_field (| M.get_name (| globals, "vm" |), "Environment" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.assign (| + make_tuple [ M.get_name (| globals, "gas_used" |); M.get_name (| globals, "logs" |) ], + M.call (| + M.get_name (| globals, "process_transaction" |), + make_list [ + M.get_name (| globals, "env" |); + M.get_name (| globals, "tx" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_op_local (| + BinOp.sub, + "gas_available", + M.get_name (| globals, "gas_used" |) + |) in + let _ := M.assign_local (| + "receipt" , + M.call (| + M.get_name (| globals, "make_receipt" |), + make_list [ + M.get_name (| globals, "tx" |); + M.call (| + M.get_name (| globals, "state_root" |), + make_list [ + M.get_name (| globals, "state" |) + ], + make_dict [] + |); + BinOp.sub (| + M.get_name (| globals, "block_gas_limit" |), + M.get_name (| globals, "gas_available" |) + |); + M.get_name (| globals, "logs" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "trie_set" |), + make_list [ + M.get_name (| globals, "receipts_trie" |); + M.call (| + M.get_field (| M.get_name (| globals, "rlp" |), "encode" |), + make_list [ + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.get_name (| globals, "i" |) + ], + make_dict [] + |) + ], + make_dict [] + |); + M.get_name (| globals, "receipt" |) + ], + make_dict [] + |) in + let _ := M.assign_op_local (| + BinOp.add, + "block_logs", + M.get_name (| globals, "logs" |) + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := M.call (| + M.get_name (| globals, "pay_rewards" |), + make_list [ + M.get_name (| globals, "state" |); + M.get_name (| globals, "block_number" |); + M.get_name (| globals, "coinbase" |); + M.get_name (| globals, "ommers" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "block_gas_used" , + BinOp.sub (| + M.get_name (| globals, "block_gas_limit" |), + M.get_name (| globals, "gas_available" |) + |) + |) in + let _ := M.assign_local (| + "block_logs_bloom" , + M.call (| + M.get_name (| globals, "logs_bloom" |), + make_list [ + M.get_name (| globals, "block_logs" |) + ], + make_dict [] + |) + |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, "ApplyBodyOutput" |), + make_list [ + M.get_name (| globals, "block_gas_used" |); + M.call (| + M.get_name (| globals, "root" |), + make_list [ + M.get_name (| globals, "transactions_trie" |) + ], + make_dict [] + |); + M.call (| + M.get_name (| globals, "root" |), + make_list [ + M.get_name (| globals, "receipts_trie" |) + ], + make_dict [] + |); + M.get_name (| globals, "block_logs_bloom" |); + M.call (| + M.get_name (| globals, "state_root" |), + make_list [ + M.get_name (| globals, "state" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Definition validate_ommers : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "ommers"; "block_header"; "chain" ] |) in + let _ := Constant.str " + Validates the ommers mentioned in the block. + + An ommer block is a block that wasn't canonically added to the + blockchain because it wasn't validated as fast as the canonical block + but was mined at the same time. + + To be considered valid, the ommers must adhere to the rules defined in + the Ethereum protocol. The maximum amount of ommers is 2 per block and + there cannot be duplicate ommers in a block. Many of the other ommer + constraints are listed in the in-line comments of this function. + + Parameters + ---------- + ommers : + List of ommers mentioned in the current block. + block_header: + The header of current block. + chain : + History and current state. + " in + let _ := M.assign_local (| + "block_hash" , + M.call (| + M.get_field (| M.get_name (| globals, "rlp" |), "rlp_hash" |), + make_list [ + M.get_name (| globals, "block_header" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + Compare.eq (| + M.call (| + M.get_field (| M.get_name (| globals, "rlp" |), "rlp_hash" |), + make_list [ + M.get_name (| globals, "ommers" |) + ], + make_dict [] + |), + M.get_field (| M.get_name (| globals, "block_header" |), "ommers_hash" |) + |); + M.get_name (| globals, "InvalidBlock" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_name (| globals, "ommers" |) + ], + make_dict [] + |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + Constant.None_ + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + M.for_ (| + M.get_name (| globals, "ommer" |), + M.get_name (| globals, "ommers" |), + ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + BoolOp.and (| + Compare.lt_e (| + Constant.int 1, + M.get_field (| M.get_name (| globals, "ommer" |), "number" |) + |), + ltac:(M.monadic ( + Compare.lt (| + M.get_field (| M.get_name (| globals, "ommer" |), "number" |), + M.get_field (| M.get_name (| globals, "block_header" |), "number" |) + |) + )) + |); + M.get_name (| globals, "InvalidBlock" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "ommer_parent_header" , + M.get_field (| M.get_subscript (| + M.get_field (| M.get_name (| globals, "chain" |), "blocks" |), + BinOp.sub (| + UnOp.sub (| BinOp.sub (| + M.get_field (| M.get_name (| globals, "block_header" |), "number" |), + M.get_field (| M.get_name (| globals, "ommer" |), "number" |) + |) |), + Constant.int 1 + |) + |), "header" |) + |) in + let _ := M.call (| + M.get_name (| globals, "validate_header" |), + make_list [ + M.get_name (| globals, "ommer" |); + M.get_name (| globals, "ommer_parent_header" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + Compare.lt_e (| + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_name (| globals, "ommers" |) + ], + make_dict [] + |), + Constant.int 2 + |); + M.get_name (| globals, "InvalidBlock" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "ommers_hashes" , + Constant.str "(* At expr: unsupported node type: ListComp *)" + |) in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + Compare.eq (| + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_name (| globals, "ommers_hashes" |) + ], + make_dict [] + |), + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.call (| + M.get_name (| globals, "set" |), + make_list [ + M.get_name (| globals, "ommers_hashes" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |); + M.get_name (| globals, "InvalidBlock" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "recent_canonical_blocks" , + M.slice (| + M.get_field (| M.get_name (| globals, "chain" |), "blocks" |), + UnOp.sub (| BinOp.add (| + M.get_name (| globals, "MAX_OMMER_DEPTH" |), + Constant.int 1 + |) |), + Constant.None_, + Constant.None_ + |) + |) in + let _ := M.assign_local (| + "recent_canonical_block_hashes" , + Constant.str "(* At expr: unsupported node type: SetComp *)" + |) in +(* At stmt: unsupported node type: AnnAssign *) + let _ := + M.for_ (| + M.get_name (| globals, "block" |), + M.get_name (| globals, "recent_canonical_blocks" |), + ltac:(M.monadic ( + let _ := M.assign_local (| + "recent_ommers_hashes" , + M.call (| + M.get_field (| M.get_name (| globals, "recent_ommers_hashes" |), "union" |), + make_list [ + Constant.str "(* At expr: unsupported node type: SetComp *)" + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := + M.for_ (| + make_tuple [ M.get_name (| globals, "ommer_index" |); M.get_name (| globals, "ommer" |) ], + M.call (| + M.get_name (| globals, "enumerate" |), + make_list [ + M.get_name (| globals, "ommers" |) + ], + make_dict [] + |), + ltac:(M.monadic ( + let _ := M.assign_local (| + "ommer_hash" , + M.get_subscript (| + M.get_name (| globals, "ommers_hashes" |), + M.get_name (| globals, "ommer_index" |) + |) + |) in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + Compare.not_eq (| + M.get_name (| globals, "ommer_hash" |), + M.get_name (| globals, "block_hash" |) + |); + M.get_name (| globals, "InvalidBlock" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + Compare.not_in (| + M.get_name (| globals, "ommer_hash" |), + M.get_name (| globals, "recent_canonical_block_hashes" |) + |); + M.get_name (| globals, "InvalidBlock" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + Compare.not_in (| + M.get_name (| globals, "ommer_hash" |), + M.get_name (| globals, "recent_ommers_hashes" |) + |); + M.get_name (| globals, "InvalidBlock" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "ommer_age" , + BinOp.sub (| + M.get_field (| M.get_name (| globals, "block_header" |), "number" |), + M.get_field (| M.get_name (| globals, "ommer" |), "number" |) + |) + |) in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + BoolOp.and (| + Compare.lt_e (| + Constant.int 1, + M.get_name (| globals, "ommer_age" |) + |), + ltac:(M.monadic ( + Compare.lt_e (| + M.get_name (| globals, "ommer_age" |), + M.get_name (| globals, "MAX_OMMER_DEPTH" |) + |) + )) + |); + M.get_name (| globals, "InvalidBlock" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + Compare.in_ (| + M.get_field (| M.get_name (| globals, "ommer" |), "parent_hash" |), + M.get_name (| globals, "recent_canonical_block_hashes" |) + |); + M.get_name (| globals, "InvalidBlock" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + Compare.not_eq (| + M.get_field (| M.get_name (| globals, "ommer" |), "parent_hash" |), + M.get_field (| M.get_name (| globals, "block_header" |), "parent_hash" |) + |); + M.get_name (| globals, "InvalidBlock" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + M.pure Constant.None_)). + +Definition pay_rewards : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "state"; "block_number"; "coinbase"; "ommers" ] |) in + let _ := Constant.str " + Pay rewards to the block miner as well as the ommers miners. + + The miner of the canonical block is rewarded with the predetermined + block reward, ``BLOCK_REWARD``, plus a variable award based off of the + number of ommer blocks that were mined around the same time, and included + in the canonical block's header. An ommer block is a block that wasn't + added to the canonical blockchain because it wasn't validated as fast as + the accepted block but was mined at the same time. Although not all blocks + that are mined are added to the canonical chain, miners are still paid a + reward for their efforts. This reward is called an ommer reward and is + calculated based on the number associated with the ommer block that they + mined. + + Parameters + ---------- + state : + Current account state. + block_number : + Position of the block within the chain. + coinbase : + Address of account which receives block reward and transaction fees. + ommers : + List of ommers mentioned in the current block. + " in + let _ := M.assign_local (| + "miner_reward" , + BinOp.add (| + M.get_name (| globals, "BLOCK_REWARD" |), + BinOp.mult (| + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_name (| globals, "ommers" |) + ], + make_dict [] + |), + BinOp.floor_div (| + M.get_name (| globals, "BLOCK_REWARD" |), + Constant.int 32 + |) + |) + |) + |) in + let _ := M.call (| + M.get_name (| globals, "create_ether" |), + make_list [ + M.get_name (| globals, "state" |); + M.get_name (| globals, "coinbase" |); + M.get_name (| globals, "miner_reward" |) + ], + make_dict [] + |) in + let _ := + M.for_ (| + M.get_name (| globals, "ommer" |), + M.get_name (| globals, "ommers" |), + ltac:(M.monadic ( + let _ := M.assign_local (| + "ommer_age" , + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + BinOp.sub (| + M.get_name (| globals, "block_number" |), + M.get_field (| M.get_name (| globals, "ommer" |), "number" |) + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "ommer_miner_reward" , + BinOp.floor_div (| + BinOp.mult (| + BinOp.sub (| + Constant.int 8, + M.get_name (| globals, "ommer_age" |) + |), + M.get_name (| globals, "BLOCK_REWARD" |) + |), + Constant.int 8 + |) + |) in + let _ := M.call (| + M.get_name (| globals, "create_ether" |), + make_list [ + M.get_name (| globals, "state" |); + M.get_field (| M.get_name (| globals, "ommer" |), "coinbase" |); + M.get_name (| globals, "ommer_miner_reward" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + M.pure Constant.None_)). + +Definition process_transaction : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "env"; "tx" ] |) in + let _ := Constant.str " + Execute a transaction against the provided environment. + + This function processes the actions needed to execute a transaction. + It decrements the sender's account after calculating the gas fee and + refunds them the proper amount after execution. Calling contracts, + deploying code, and incrementing nonces are all examples of actions that + happen within this function or from a call made within this function. + + Accounts that are marked for deletion are processed and destroyed after + execution. + + Parameters + ---------- + env : + Environment for the Ethereum Virtual Machine. + tx : + Transaction to execute. + + Returns + ------- + gas_left : `ethereum.base_types.U256` + Remaining gas after execution. + logs : `Tuple[ethereum.blocks.Log, ...]` + Logs generated during execution. + " in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + M.call (| + M.get_name (| globals, "validate_transaction" |), + make_list [ + M.get_name (| globals, "tx" |) + ], + make_dict [] + |); + M.get_name (| globals, "InvalidBlock" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "sender" , + M.get_field (| M.get_name (| globals, "env" |), "origin" |) + |) in + let _ := M.assign_local (| + "sender_account" , + M.call (| + M.get_name (| globals, "get_account" |), + make_list [ + M.get_field (| M.get_name (| globals, "env" |), "state" |); + M.get_name (| globals, "sender" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "gas_fee" , + BinOp.mult (| + M.get_field (| M.get_name (| globals, "tx" |), "gas" |), + M.get_field (| M.get_name (| globals, "tx" |), "gas_price" |) + |) + |) in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + Compare.eq (| + M.get_field (| M.get_name (| globals, "sender_account" |), "nonce" |), + M.get_field (| M.get_name (| globals, "tx" |), "nonce" |) + |); + M.get_name (| globals, "InvalidBlock" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + Compare.gt_e (| + M.get_field (| M.get_name (| globals, "sender_account" |), "balance" |), + BinOp.add (| + M.get_name (| globals, "gas_fee" |), + M.get_field (| M.get_name (| globals, "tx" |), "value" |) + |) + |); + M.get_name (| globals, "InvalidBlock" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + Compare.eq (| + M.get_field (| M.get_name (| globals, "sender_account" |), "code" |), + M.call (| + M.get_name (| globals, "bytearray" |), + make_list [], + make_dict [] + |) + |); + M.get_name (| globals, "InvalidBlock" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "gas" , + BinOp.sub (| + M.get_field (| M.get_name (| globals, "tx" |), "gas" |), + M.call (| + M.get_name (| globals, "calculate_intrinsic_cost" |), + make_list [ + M.get_name (| globals, "tx" |) + ], + make_dict [] + |) + |) + |) in + let _ := M.call (| + M.get_name (| globals, "increment_nonce" |), + make_list [ + M.get_field (| M.get_name (| globals, "env" |), "state" |); + M.get_name (| globals, "sender" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "sender_balance_after_gas_fee" , + BinOp.sub (| + M.get_field (| M.get_name (| globals, "sender_account" |), "balance" |), + M.get_name (| globals, "gas_fee" |) + |) + |) in + let _ := M.call (| + M.get_name (| globals, "set_account_balance" |), + make_list [ + M.get_field (| M.get_name (| globals, "env" |), "state" |); + M.get_name (| globals, "sender" |); + M.get_name (| globals, "sender_balance_after_gas_fee" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "message" , + M.call (| + M.get_name (| globals, "prepare_message" |), + make_list [ + M.get_name (| globals, "sender" |); + M.get_field (| M.get_name (| globals, "tx" |), "to" |); + M.get_field (| M.get_name (| globals, "tx" |), "value" |); + M.get_field (| M.get_name (| globals, "tx" |), "data" |); + M.get_name (| globals, "gas" |); + M.get_name (| globals, "env" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "output" , + M.call (| + M.get_name (| globals, "process_message_call" |), + make_list [ + M.get_name (| globals, "message" |); + M.get_name (| globals, "env" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "gas_used" , + BinOp.sub (| + M.get_field (| M.get_name (| globals, "tx" |), "gas" |), + M.get_field (| M.get_name (| globals, "output" |), "gas_left" |) + |) + |) in + let _ := M.assign_local (| + "gas_refund" , + M.call (| + M.get_name (| globals, "min" |), + make_list [ + BinOp.floor_div (| + M.get_name (| globals, "gas_used" |), + Constant.int 2 + |); + M.get_field (| M.get_name (| globals, "output" |), "refund_counter" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "gas_refund_amount" , + BinOp.mult (| + BinOp.add (| + M.get_field (| M.get_name (| globals, "output" |), "gas_left" |), + M.get_name (| globals, "gas_refund" |) + |), + M.get_field (| M.get_name (| globals, "tx" |), "gas_price" |) + |) + |) in + let _ := M.assign_local (| + "transaction_fee" , + BinOp.mult (| + BinOp.sub (| + BinOp.sub (| + M.get_field (| M.get_name (| globals, "tx" |), "gas" |), + M.get_field (| M.get_name (| globals, "output" |), "gas_left" |) + |), + M.get_name (| globals, "gas_refund" |) + |), + M.get_field (| M.get_name (| globals, "tx" |), "gas_price" |) + |) + |) in + let _ := M.assign_local (| + "total_gas_used" , + BinOp.sub (| + M.get_name (| globals, "gas_used" |), + M.get_name (| globals, "gas_refund" |) + |) + |) in + let _ := M.assign_local (| + "sender_balance_after_refund" , + BinOp.add (| + M.get_field (| M.call (| + M.get_name (| globals, "get_account" |), + make_list [ + M.get_field (| M.get_name (| globals, "env" |), "state" |); + M.get_name (| globals, "sender" |) + ], + make_dict [] + |), "balance" |), + M.get_name (| globals, "gas_refund_amount" |) + |) + |) in + let _ := M.call (| + M.get_name (| globals, "set_account_balance" |), + make_list [ + M.get_field (| M.get_name (| globals, "env" |), "state" |); + M.get_name (| globals, "sender" |); + M.get_name (| globals, "sender_balance_after_refund" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "coinbase_balance_after_mining_fee" , + BinOp.add (| + M.get_field (| M.call (| + M.get_name (| globals, "get_account" |), + make_list [ + M.get_field (| M.get_name (| globals, "env" |), "state" |); + M.get_field (| M.get_name (| globals, "env" |), "coinbase" |) + ], + make_dict [] + |), "balance" |), + M.get_name (| globals, "transaction_fee" |) + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.not_eq (| + M.get_name (| globals, "coinbase_balance_after_mining_fee" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, "set_account_balance" |), + make_list [ + M.get_field (| M.get_name (| globals, "env" |), "state" |); + M.get_field (| M.get_name (| globals, "env" |), "coinbase" |); + M.get_name (| globals, "coinbase_balance_after_mining_fee" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, "account_exists_and_is_empty" |), + make_list [ + M.get_field (| M.get_name (| globals, "env" |), "state" |); + M.get_field (| M.get_name (| globals, "env" |), "coinbase" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, "destroy_account" |), + make_list [ + M.get_field (| M.get_name (| globals, "env" |), "state" |); + M.get_field (| M.get_name (| globals, "env" |), "coinbase" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )) |) in + let _ := + M.for_ (| + M.get_name (| globals, "address" |), + M.get_field (| M.get_name (| globals, "output" |), "accounts_to_delete" |), + ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, "destroy_account" |), + make_list [ + M.get_field (| M.get_name (| globals, "env" |), "state" |); + M.get_name (| globals, "address" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := + M.for_ (| + M.get_name (| globals, "address" |), + M.get_field (| M.get_name (| globals, "output" |), "touched_accounts" |), + ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, "account_exists_and_is_empty" |), + make_list [ + M.get_field (| M.get_name (| globals, "env" |), "state" |); + M.get_name (| globals, "address" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, "destroy_account" |), + make_list [ + M.get_field (| M.get_name (| globals, "env" |), "state" |); + M.get_name (| globals, "address" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := M.return_ (| + make_tuple [ M.get_name (| globals, "total_gas_used" |); M.get_field (| M.get_name (| globals, "output" |), "logs" |) ] + |) in + M.pure Constant.None_)). + +Definition validate_transaction : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "tx" ] |) in + let _ := Constant.str " + Verifies a transaction. + + The gas in a transaction gets used to pay for the intrinsic cost of + operations, therefore if there is insufficient gas then it would not + be possible to execute a transaction and it will be declared invalid. + + Additionally, the nonce of a transaction must not equal or exceed the + limit defined in `EIP-2681 `_. + In practice, defining the limit as ``2**64-1`` has no impact because + sending ``2**64-1`` transactions is improbable. It's not strictly + impossible though, ``2**64-1`` transactions is the entire capacity of the + Ethereum blockchain at 2022 gas limits for a little over 22 years. + + Parameters + ---------- + tx : + Transaction to validate. + + Returns + ------- + verified : `bool` + True if the transaction can be executed, or False otherwise. + " in + let _ := M.return_ (| + BoolOp.and (| + Compare.lt_e (| + M.call (| + M.get_name (| globals, "calculate_intrinsic_cost" |), + make_list [ + M.get_name (| globals, "tx" |) + ], + make_dict [] + |), + M.get_field (| M.get_name (| globals, "tx" |), "gas" |) + |), + ltac:(M.monadic ( + Compare.lt (| + M.get_field (| M.get_name (| globals, "tx" |), "nonce" |), + BinOp.sub (| + BinOp.pow (| + Constant.int 2, + Constant.int 64 + |), + Constant.int 1 + |) + |) + )) + |) + |) in + M.pure Constant.None_)). + +Definition calculate_intrinsic_cost : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "tx" ] |) in + let _ := Constant.str " + Calculates the gas that is charged before execution is started. + + The intrinsic cost of the transaction is charged before execution has + begun. Functions/operations in the EVM cost money to execute so this + intrinsic cost is for the operations that need to be paid for as part of + the transaction. Data transfer, for example, is part of this intrinsic + cost. It costs ether to send data over the wire and that ether is + accounted for in the intrinsic cost calculated in this function. This + intrinsic cost must be calculated and paid for before execution in order + for all operations to be implemented. + + Parameters + ---------- + tx : + Transaction to compute the intrinsic cost of. + + Returns + ------- + verified : `ethereum.base_types.Uint` + The intrinsic cost of the transaction. + " in + let _ := M.assign_local (| + "data_cost" , + Constant.int 0 + |) in + let _ := + M.for_ (| + M.get_name (| globals, "byte" |), + M.get_field (| M.get_name (| globals, "tx" |), "data" |), + ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, "byte" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_op_local (| + BinOp.add, + "data_cost", + M.get_name (| globals, "TX_DATA_COST_PER_ZERO" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_op_local (| + BinOp.add, + "data_cost", + M.get_name (| globals, "TX_DATA_COST_PER_NON_ZERO" |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_field (| M.get_name (| globals, "tx" |), "to" |), + M.call (| + M.get_name (| globals, "Bytes0" |), + make_list [ + Constant.bytes "" + ], + make_dict [] + |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "create_cost" , + M.get_name (| globals, "TX_CREATE_COST" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "create_cost" , + Constant.int 0 + |) in + M.pure Constant.None_ + )) |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + BinOp.add (| + BinOp.add (| + M.get_name (| globals, "TX_BASE_COST" |), + M.get_name (| globals, "data_cost" |) + |), + M.get_name (| globals, "create_cost" |) + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Definition recover_sender : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "chain_id"; "tx" ] |) in + let _ := Constant.str " + Extracts the sender address from a transaction. + + The v, r, and s values are the three parts that make up the signature + of a transaction. In order to recover the sender of a transaction the two + components needed are the signature (``v``, ``r``, and ``s``) and the + signing hash of the transaction. The sender's public key can be obtained + with these two values and therefore the sender address can be retrieved. + + Parameters + ---------- + tx : + Transaction of interest. + chain_id : + ID of the executing chain. + + Returns + ------- + sender : `ethereum.fork_types.Address` + The address of the account that signed the transaction. + " in + let _ := M.assign (| + make_tuple [ M.get_name (| globals, "v" |); M.get_name (| globals, "r" |); M.get_name (| globals, "s" |) ], + make_tuple [ M.get_field (| M.get_name (| globals, "tx" |), "v" |); M.get_field (| M.get_name (| globals, "tx" |), "r" |); M.get_field (| M.get_name (| globals, "tx" |), "s" |) ] + |) in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + BoolOp.and (| + Compare.lt (| + Constant.int 0, + M.get_name (| globals, "r" |) + |), + ltac:(M.monadic ( + Compare.lt (| + M.get_name (| globals, "r" |), + M.get_name (| globals, "SECP256K1N" |) + |) + )) + |); + M.get_name (| globals, "InvalidBlock" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + BoolOp.and (| + Compare.lt (| + Constant.int 0, + M.get_name (| globals, "s" |) + |), + ltac:(M.monadic ( + Compare.lt_e (| + M.get_name (| globals, "s" |), + BinOp.floor_div (| + M.get_name (| globals, "SECP256K1N" |), + Constant.int 2 + |) + |) + )) + |); + M.get_name (| globals, "InvalidBlock" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + BoolOp.or (| + Compare.eq (| + M.get_name (| globals, "v" |), + Constant.int 27 + |), + ltac:(M.monadic ( + Compare.eq (| + M.get_name (| globals, "v" |), + Constant.int 28 + |) + )) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "public_key" , + M.call (| + M.get_name (| globals, "secp256k1_recover" |), + make_list [ + M.get_name (| globals, "r" |); + M.get_name (| globals, "s" |); + BinOp.sub (| + M.get_name (| globals, "v" |), + Constant.int 27 + |); + M.call (| + M.get_name (| globals, "signing_hash_pre155" |), + make_list [ + M.get_name (| globals, "tx" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + BoolOp.or (| + Compare.eq (| + M.get_name (| globals, "v" |), + BinOp.add (| + Constant.int 35, + BinOp.mult (| + M.get_name (| globals, "chain_id" |), + Constant.int 2 + |) + |) + |), + ltac:(M.monadic ( + Compare.eq (| + M.get_name (| globals, "v" |), + BinOp.add (| + Constant.int 36, + BinOp.mult (| + M.get_name (| globals, "chain_id" |), + Constant.int 2 + |) + |) + |) + )) + |); + M.get_name (| globals, "InvalidBlock" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "public_key" , + M.call (| + M.get_name (| globals, "secp256k1_recover" |), + make_list [ + M.get_name (| globals, "r" |); + M.get_name (| globals, "s" |); + BinOp.sub (| + BinOp.sub (| + M.get_name (| globals, "v" |), + Constant.int 35 + |), + BinOp.mult (| + M.get_name (| globals, "chain_id" |), + Constant.int 2 + |) + |); + M.call (| + M.get_name (| globals, "signing_hash_155" |), + make_list [ + M.get_name (| globals, "tx" |); + M.get_name (| globals, "chain_id" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + )) |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, "Address" |), + make_list [ + M.slice (| + M.call (| + M.get_name (| globals, "keccak256" |), + make_list [ + M.get_name (| globals, "public_key" |) + ], + make_dict [] + |), + Constant.int 12, + Constant.int 32, + Constant.None_ + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Definition signing_hash_pre155 : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "tx" ] |) in + let _ := Constant.str " + Compute the hash of a transaction used in a legacy (pre EIP 155) signature. + + Parameters + ---------- + tx : + Transaction of interest. + + Returns + ------- + hash : `ethereum.crypto.hash.Hash32` + Hash of the transaction. + " in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, "keccak256" |), + make_list [ + M.call (| + M.get_field (| M.get_name (| globals, "rlp" |), "encode" |), + make_list [ + make_tuple [ M.get_field (| M.get_name (| globals, "tx" |), "nonce" |); M.get_field (| M.get_name (| globals, "tx" |), "gas_price" |); M.get_field (| M.get_name (| globals, "tx" |), "gas" |); M.get_field (| M.get_name (| globals, "tx" |), "to" |); M.get_field (| M.get_name (| globals, "tx" |), "value" |); M.get_field (| M.get_name (| globals, "tx" |), "data" |) ] + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Definition signing_hash_155 : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "tx"; "chain_id" ] |) in + let _ := Constant.str " + Compute the hash of a transaction used in a EIP 155 signature. + + Parameters + ---------- + tx : + Transaction of interest. + chain_id : + The id of the current chain. + + Returns + ------- + hash : `ethereum.crypto.hash.Hash32` + Hash of the transaction. + " in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, "keccak256" |), + make_list [ + M.call (| + M.get_field (| M.get_name (| globals, "rlp" |), "encode" |), + make_list [ + make_tuple [ M.get_field (| M.get_name (| globals, "tx" |), "nonce" |); M.get_field (| M.get_name (| globals, "tx" |), "gas_price" |); M.get_field (| M.get_name (| globals, "tx" |), "gas" |); M.get_field (| M.get_name (| globals, "tx" |), "to" |); M.get_field (| M.get_name (| globals, "tx" |), "value" |); M.get_field (| M.get_name (| globals, "tx" |), "data" |); M.get_name (| globals, "chain_id" |); M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |); M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) ] + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Definition compute_header_hash : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "header" ] |) in + let _ := Constant.str " + Computes the hash of a block header. + + The header hash of a block is the canonical hash that is used to refer + to a specific block and completely distinguishes a block from another. + + ``keccak256`` is a function that produces a 256 bit hash of any input. + It also takes in any number of bytes as an input and produces a single + hash for them. A hash is a completely unique output for a single input. + So an input corresponds to one unique hash that can be used to identify + the input exactly. + + Prior to using the ``keccak256`` hash function, the header must be + encoded using the Recursive-Length Prefix. See :ref:`rlp`. + RLP encoding the header converts it into a space-efficient format that + allows for easy transfer of data between nodes. The purpose of RLP is to + encode arbitrarily nested arrays of binary data, and RLP is the primary + encoding method used to serialize objects in Ethereum's execution layer. + The only purpose of RLP is to encode structure; encoding specific data + types (e.g. strings, floats) is left up to higher-order protocols. + + Parameters + ---------- + header : + Header of interest. + + Returns + ------- + hash : `ethereum.crypto.hash.Hash32` + Hash of the header. + " in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, "keccak256" |), + make_list [ + M.call (| + M.get_field (| M.get_name (| globals, "rlp" |), "encode" |), + make_list [ + M.get_name (| globals, "header" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Definition check_gas_limit : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "gas_limit"; "parent_gas_limit" ] |) in + let _ := Constant.str " + Validates the gas limit for a block. + + The bounds of the gas limit, ``max_adjustment_delta``, is set as the + quotient of the parent block's gas limit and the + ``GAS_LIMIT_ADJUSTMENT_FACTOR``. Therefore, if the gas limit that is + passed through as a parameter is greater than or equal to the *sum* of + the parent's gas and the adjustment delta then the limit for gas is too + high and fails this function's check. Similarly, if the limit is less + than or equal to the *difference* of the parent's gas and the adjustment + delta *or* the predefined ``GAS_LIMIT_MINIMUM`` then this function's + check fails because the gas limit doesn't allow for a sufficient or + reasonable amount of gas to be used on a block. + + Parameters + ---------- + gas_limit : + Gas limit to validate. + + parent_gas_limit : + Gas limit of the parent block. + + Returns + ------- + check : `bool` + True if gas limit constraints are satisfied, False otherwise. + " in + let _ := M.assign_local (| + "max_adjustment_delta" , + BinOp.floor_div (| + M.get_name (| globals, "parent_gas_limit" |), + M.get_name (| globals, "GAS_LIMIT_ADJUSTMENT_FACTOR" |) + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.gt_e (| + M.get_name (| globals, "gas_limit" |), + BinOp.add (| + M.get_name (| globals, "parent_gas_limit" |), + M.get_name (| globals, "max_adjustment_delta" |) + |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + Constant.bool false + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + Compare.lt_e (| + M.get_name (| globals, "gas_limit" |), + BinOp.sub (| + M.get_name (| globals, "parent_gas_limit" |), + M.get_name (| globals, "max_adjustment_delta" |) + |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + Constant.bool false + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + Compare.lt (| + M.get_name (| globals, "gas_limit" |), + M.get_name (| globals, "GAS_LIMIT_MINIMUM" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + Constant.bool false + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.return_ (| + Constant.bool true + |) in + M.pure Constant.None_)). + +Definition calculate_block_difficulty : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "block_number"; "block_timestamp"; "parent_timestamp"; "parent_difficulty" ] |) in + let _ := Constant.str " + Computes difficulty of a block using its header and parent header. + + The difficulty is determined by the time the block was created after its + parent. The ``offset`` is calculated using the parent block's difficulty, + ``parent_difficulty``, and the timestamp between blocks. This offset is + then added to the parent difficulty and is stored as the ``difficulty`` + variable. If the time between the block and its parent is too short, the + offset will result in a positive number thus making the sum of + ``parent_difficulty`` and ``offset`` to be a greater value in order to + avoid mass forking. But, if the time is long enough, then the offset + results in a negative value making the block less difficult than + its parent. + + The base standard for a block's difficulty is the predefined value + set for the genesis block since it has no parent. So, a block + can't be less difficult than the genesis block, therefore each block's + difficulty is set to the maximum value between the calculated + difficulty and the ``GENESIS_DIFFICULTY``. + + Parameters + ---------- + block_number : + Block number of the block. + block_timestamp : + Timestamp of the block. + parent_timestamp : + Timestamp of the parent block. + parent_difficulty : + difficulty of the parent block. + + Returns + ------- + difficulty : `ethereum.base_types.Uint` + Computed difficulty for a block. + " in + let _ := M.assign_local (| + "offset" , + BinOp.mult (| + BinOp.floor_div (| + M.call (| + M.get_name (| globals, "int" |), + make_list [ + M.get_name (| globals, "parent_difficulty" |) + ], + make_dict [] + |), + Constant.int 2048 + |), + M.call (| + M.get_name (| globals, "max" |), + make_list [ + BinOp.sub (| + Constant.int 1, + BinOp.floor_div (| + M.call (| + M.get_name (| globals, "int" |), + make_list [ + BinOp.sub (| + M.get_name (| globals, "block_timestamp" |), + M.get_name (| globals, "parent_timestamp" |) + |) + ], + make_dict [] + |), + Constant.int 10 + |) + |); + UnOp.sub (| Constant.int 99 |) + ], + make_dict [] + |) + |) + |) in + let _ := M.assign_local (| + "difficulty" , + BinOp.add (| + M.call (| + M.get_name (| globals, "int" |), + make_list [ + M.get_name (| globals, "parent_difficulty" |) + ], + make_dict [] + |), + M.get_name (| globals, "offset" |) + |) + |) in + let _ := M.assign_local (| + "num_bomb_periods" , + BinOp.sub (| + BinOp.floor_div (| + M.call (| + M.get_name (| globals, "int" |), + make_list [ + M.get_name (| globals, "block_number" |) + ], + make_dict [] + |), + Constant.int 100000 + |), + Constant.int 2 + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.gt_e (| + M.get_name (| globals, "num_bomb_periods" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_op_local (| + BinOp.add, + "difficulty", + BinOp.pow (| + Constant.int 2, + M.get_name (| globals, "num_bomb_periods" |) + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, "max" |), + make_list [ + M.get_name (| globals, "difficulty" |); + M.get_name (| globals, "MINIMUM_DIFFICULTY" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). diff --git a/CoqOfPython/ethereum/spurious_dragon/fork_types.v b/CoqOfPython/ethereum/spurious_dragon/fork_types.v new file mode 100644 index 0000000..92672ad --- /dev/null +++ b/CoqOfPython/ethereum/spurious_dragon/fork_types.v @@ -0,0 +1,98 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.spurious_dragon.fork_types". + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Types +^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Types re-used throughout the specification, which are specific to Ethereum. +". + +Axiom dataclasses_imports_dataclass : + IsImported globals "dataclasses" "dataclass". + +Axiom ethereum_imports_rlp : + IsImported globals "ethereum" "rlp". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_Bytes : + IsImported globals "ethereum.base_types" "Bytes". +Axiom ethereum_base_types_imports_Bytes20 : + IsImported globals "ethereum.base_types" "Bytes20". +Axiom ethereum_base_types_imports_Bytes256 : + IsImported globals "ethereum.base_types" "Bytes256". +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". +Axiom ethereum_base_types_imports_slotted_freezable : + IsImported globals "ethereum.base_types" "slotted_freezable". + +Axiom ethereum_crypto_hash_imports_Hash32 : + IsImported globals "ethereum.crypto.hash" "Hash32". +Axiom ethereum_crypto_hash_imports_keccak256 : + IsImported globals "ethereum.crypto.hash" "keccak256". + +Definition Address : Value.t := M.run ltac:(M.monadic ( + M.get_name (| globals, "Bytes20" |) +)). + +Definition Root : Value.t := M.run ltac:(M.monadic ( + M.get_name (| globals, "Hash32" |) +)). + +Definition Bloom : Value.t := M.run ltac:(M.monadic ( + M.get_name (| globals, "Bytes256" |) +)). + +Definition Account : Value.t := + builtins.make_klass + [] + [ + + ] + [ + + ]. + +Definition EMPTY_ACCOUNT : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Account" |), + make_list [], + make_dict [] + |) +)). + +Definition encode_account : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "raw_account_data"; "storage_root" ] |) in + let _ := Constant.str " + Encode `Account` dataclass. + + Storage is not stored in the `Account` dataclass, so `Accounts` cannot be + encoded with providing a storage root. + " in + let _ := M.return_ (| + M.call (| + M.get_field (| M.get_name (| globals, "rlp" |), "encode" |), + make_list [ + make_tuple [ M.get_field (| M.get_name (| globals, "raw_account_data" |), "nonce" |); M.get_field (| M.get_name (| globals, "raw_account_data" |), "balance" |); M.get_name (| globals, "storage_root" |); M.call (| + M.get_name (| globals, "keccak256" |), + make_list [ + M.get_field (| M.get_name (| globals, "raw_account_data" |), "code" |) + ], + make_dict [] + |) ] + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). diff --git a/CoqOfPython/ethereum/spurious_dragon/state.v b/CoqOfPython/ethereum/spurious_dragon/state.v new file mode 100644 index 0000000..d7957d0 --- /dev/null +++ b/CoqOfPython/ethereum/spurious_dragon/state.v @@ -0,0 +1,1111 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.spurious_dragon.state". + +Definition expr_1 : Value.t := + Constant.str " +State +^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +The state contains all information that is preserved between transactions. + +It consists of a main account trie and storage tries for each contract. + +There is a distinction between an account that does not exist and +`EMPTY_ACCOUNT`. +". + +Axiom dataclasses_imports_dataclass : + IsImported globals "dataclasses" "dataclass". +Axiom dataclasses_imports_field : + IsImported globals "dataclasses" "field". + +Axiom typing_imports_Callable : + IsImported globals "typing" "Callable". +Axiom typing_imports_Dict : + IsImported globals "typing" "Dict". +Axiom typing_imports_List : + IsImported globals "typing" "List". +Axiom typing_imports_Optional : + IsImported globals "typing" "Optional". +Axiom typing_imports_Tuple : + IsImported globals "typing" "Tuple". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_Bytes : + IsImported globals "ethereum.base_types" "Bytes". +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". +Axiom ethereum_base_types_imports_modify : + IsImported globals "ethereum.base_types" "modify". + +Axiom ethereum_utils_ensure_imports_ensure : + IsImported globals "ethereum.utils.ensure" "ensure". + +Axiom ethereum_spurious_dragon_fork_types_imports_EMPTY_ACCOUNT : + IsImported globals "ethereum.spurious_dragon.fork_types" "EMPTY_ACCOUNT". +Axiom ethereum_spurious_dragon_fork_types_imports_Account : + IsImported globals "ethereum.spurious_dragon.fork_types" "Account". +Axiom ethereum_spurious_dragon_fork_types_imports_Address : + IsImported globals "ethereum.spurious_dragon.fork_types" "Address". +Axiom ethereum_spurious_dragon_fork_types_imports_Root : + IsImported globals "ethereum.spurious_dragon.fork_types" "Root". + +Axiom ethereum_spurious_dragon_trie_imports_EMPTY_TRIE_ROOT : + IsImported globals "ethereum.spurious_dragon.trie" "EMPTY_TRIE_ROOT". +Axiom ethereum_spurious_dragon_trie_imports_Trie : + IsImported globals "ethereum.spurious_dragon.trie" "Trie". +Axiom ethereum_spurious_dragon_trie_imports_copy_trie : + IsImported globals "ethereum.spurious_dragon.trie" "copy_trie". +Axiom ethereum_spurious_dragon_trie_imports_root : + IsImported globals "ethereum.spurious_dragon.trie" "root". +Axiom ethereum_spurious_dragon_trie_imports_trie_get : + IsImported globals "ethereum.spurious_dragon.trie" "trie_get". +Axiom ethereum_spurious_dragon_trie_imports_trie_set : + IsImported globals "ethereum.spurious_dragon.trie" "trie_set". + +Definition State : Value.t := + builtins.make_klass + [] + [ + + ] + [ + + ]. + +Definition close_state : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "state" ] |) in + let _ := Constant.str " + Free resources held by the state. Used by optimized implementations to + release file descriptors. + " in + let _ := M.delete (| M.get_field (| M.get_name (| globals, "state" |), "_main_trie" |) |) in + let _ := M.delete (| M.get_field (| M.get_name (| globals, "state" |), "_storage_tries" |) |) in + let _ := M.delete (| M.get_field (| M.get_name (| globals, "state" |), "_snapshots" |) |) in + M.pure Constant.None_)). + +Definition begin_transaction : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "state" ] |) in + let _ := Constant.str " + Start a state transaction. + + Transactions are entirely implicit and can be nested. It is not possible to + calculate the state root during a transaction. + + Parameters + ---------- + state : State + The state. + " in + let _ := M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, "state" |), "_snapshots" |), "append" |), + make_list [ + make_tuple [ M.call (| + M.get_name (| globals, "copy_trie" |), + make_list [ + M.get_field (| M.get_name (| globals, "state" |), "_main_trie" |) + ], + make_dict [] + |); Constant.str "(* At expr: unsupported node type: DictComp *)" ] + ], + make_dict [] + |) in + M.pure Constant.None_)). + +Definition commit_transaction : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "state" ] |) in + let _ := Constant.str " + Commit a state transaction. + + Parameters + ---------- + state : State + The state. + " in + let _ := M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, "state" |), "_snapshots" |), "pop" |), + make_list [], + make_dict [] + |) in + M.pure Constant.None_)). + +Definition rollback_transaction : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "state" ] |) in + let _ := Constant.str " + Rollback a state transaction, resetting the state to the point when the + corresponding `start_transaction()` call was made. + + Parameters + ---------- + state : State + The state. + " in + let _ := M.assign (| + make_tuple [ M.get_field (| M.get_name (| globals, "state" |), "_main_trie" |); M.get_field (| M.get_name (| globals, "state" |), "_storage_tries" |) ], + M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, "state" |), "_snapshots" |), "pop" |), + make_list [], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Definition get_account : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "state"; "address" ] |) in + let _ := Constant.str " + Get the `Account` object at an address. Returns `EMPTY_ACCOUNT` if there + is no account at the address. + + Use `get_account_optional()` if you care about the difference between a + non-existent account and `EMPTY_ACCOUNT`. + + Parameters + ---------- + state: `State` + The state + address : `Address` + Address to lookup. + + Returns + ------- + account : `Account` + Account at address. + " in + let _ := M.assign_local (| + "account" , + M.call (| + M.get_name (| globals, "get_account_optional" |), + make_list [ + M.get_name (| globals, "state" |); + M.get_name (| globals, "address" |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, "isinstance" |), + make_list [ + M.get_name (| globals, "account" |); + M.get_name (| globals, "Account" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + M.get_name (| globals, "account" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.return_ (| + M.get_name (| globals, "EMPTY_ACCOUNT" |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_)). + +Definition get_account_optional : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "state"; "address" ] |) in + let _ := Constant.str " + Get the `Account` object at an address. Returns `None` (rather than + `EMPTY_ACCOUNT`) if there is no account at the address. + + Parameters + ---------- + state: `State` + The state + address : `Address` + Address to lookup. + + Returns + ------- + account : `Account` + Account at address. + " in + let _ := M.assign_local (| + "account" , + M.call (| + M.get_name (| globals, "trie_get" |), + make_list [ + M.get_field (| M.get_name (| globals, "state" |), "_main_trie" |); + M.get_name (| globals, "address" |) + ], + make_dict [] + |) + |) in + let _ := M.return_ (| + M.get_name (| globals, "account" |) + |) in + M.pure Constant.None_)). + +Definition set_account : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "state"; "address"; "account" ] |) in + let _ := Constant.str " + Set the `Account` object at an address. Setting to `None` deletes + the account (but not its storage, see `destroy_account()`). + + Parameters + ---------- + state: `State` + The state + address : `Address` + Address to set. + account : `Account` + Account to set at address. + " in + let _ := M.call (| + M.get_name (| globals, "trie_set" |), + make_list [ + M.get_field (| M.get_name (| globals, "state" |), "_main_trie" |); + M.get_name (| globals, "address" |); + M.get_name (| globals, "account" |) + ], + make_dict [] + |) in + M.pure Constant.None_)). + +Definition destroy_account : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "state"; "address" ] |) in + let _ := Constant.str " + Completely remove the account at `address` and all of its storage. + + This function is made available exclusively for the `SELFDESTRUCT` + opcode. It is expected that `SELFDESTRUCT` will be disabled in a future + hardfork and this function will be removed. + + Parameters + ---------- + state: `State` + The state + address : `Address` + Address of account to destroy. + " in + let _ := M.call (| + M.get_name (| globals, "destroy_storage" |), + make_list [ + M.get_name (| globals, "state" |); + M.get_name (| globals, "address" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "set_account" |), + make_list [ + M.get_name (| globals, "state" |); + M.get_name (| globals, "address" |); + Constant.None_ + ], + make_dict [] + |) in + M.pure Constant.None_)). + +Definition destroy_storage : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "state"; "address" ] |) in + let _ := Constant.str " + Completely remove the storage at `address`. + + Parameters + ---------- + state: `State` + The state + address : `Address` + Address of account whose storage is to be deleted. + " in + let _ := + (* if *) + M.if_then_else (| + Compare.in_ (| + M.get_name (| globals, "address" |), + M.get_field (| M.get_name (| globals, "state" |), "_storage_tries" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.delete (| M.get_subscript (| + M.get_field (| M.get_name (| globals, "state" |), "_storage_tries" |), + M.get_name (| globals, "address" |) + |) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + M.pure Constant.None_)). + +Definition get_storage : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "state"; "address"; "key" ] |) in + let _ := Constant.str " + Get a value at a storage key on an account. Returns `U256(0)` if the + storage key has not been set previously. + + Parameters + ---------- + state: `State` + The state + address : `Address` + Address of the account. + key : `Bytes` + Key to lookup. + + Returns + ------- + value : `U256` + Value at the key. + " in + let _ := M.assign_local (| + "trie" , + M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, "state" |), "_storage_tries" |), "get" |), + make_list [ + M.get_name (| globals, "address" |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.is (| + M.get_name (| globals, "trie" |), + Constant.None_ + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "value" , + M.call (| + M.get_name (| globals, "trie_get" |), + make_list [ + M.get_name (| globals, "trie" |); + M.get_name (| globals, "key" |) + ], + make_dict [] + |) + |) in + let _ := M.assert (| M.call (| + M.get_name (| globals, "isinstance" |), + make_list [ + M.get_name (| globals, "value" |); + M.get_name (| globals, "U256" |) + ], + make_dict [] + |) |) in + let _ := M.return_ (| + M.get_name (| globals, "value" |) + |) in + M.pure Constant.None_)). + +Definition set_storage : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "state"; "address"; "key"; "value" ] |) in + let _ := Constant.str " + Set a value at a storage key on an account. Setting to `U256(0)` deletes + the key. + + Parameters + ---------- + state: `State` + The state + address : `Address` + Address of the account. + key : `Bytes` + Key to set. + value : `U256` + Value to set at the key. + " in + let _ := M.assert (| Compare.is_not (| + M.call (| + M.get_name (| globals, "trie_get" |), + make_list [ + M.get_field (| M.get_name (| globals, "state" |), "_main_trie" |); + M.get_name (| globals, "address" |) + ], + make_dict [] + |), + Constant.None_ + |) |) in + let _ := M.assign_local (| + "trie" , + M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, "state" |), "_storage_tries" |), "get" |), + make_list [ + M.get_name (| globals, "address" |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.is (| + M.get_name (| globals, "trie" |), + Constant.None_ + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "trie" , + M.call (| + M.get_name (| globals, "Trie" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.assign (| + M.get_subscript (| + M.get_field (| M.get_name (| globals, "state" |), "_storage_tries" |), + M.get_name (| globals, "address" |) + |), + M.get_name (| globals, "trie" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.call (| + M.get_name (| globals, "trie_set" |), + make_list [ + M.get_name (| globals, "trie" |); + M.get_name (| globals, "key" |); + M.get_name (| globals, "value" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_field (| M.get_name (| globals, "trie" |), "_data" |), + Constant.str "(* At expr: unsupported node type: Dict *)" + |), + (* then *) + ltac:(M.monadic ( + let _ := M.delete (| M.get_subscript (| + M.get_field (| M.get_name (| globals, "state" |), "_storage_tries" |), + M.get_name (| globals, "address" |) + |) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + M.pure Constant.None_)). + +Definition storage_root : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "state"; "address" ] |) in + let _ := Constant.str " + Calculate the storage root of an account. + + Parameters + ---------- + state: + The state + address : + Address of the account. + + Returns + ------- + root : `Root` + Storage root of the account. + " in + let _ := M.assert (| UnOp.not (| M.get_field (| M.get_name (| globals, "state" |), "_snapshots" |) |) |) in + let _ := + (* if *) + M.if_then_else (| + Compare.in_ (| + M.get_name (| globals, "address" |), + M.get_field (| M.get_name (| globals, "state" |), "_storage_tries" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + M.call (| + M.get_name (| globals, "root" |), + make_list [ + M.get_subscript (| + M.get_field (| M.get_name (| globals, "state" |), "_storage_tries" |), + M.get_name (| globals, "address" |) + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.return_ (| + M.get_name (| globals, "EMPTY_TRIE_ROOT" |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_)). + +Definition state_root : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "state" ] |) in + let _ := Constant.str " + Calculate the state root. + + Parameters + ---------- + state: + The current state. + + Returns + ------- + root : `Root` + The state root. + " in + let _ := M.assert (| UnOp.not (| M.get_field (| M.get_name (| globals, "state" |), "_snapshots" |) |) |) in +(* At stmt: unsupported node type: FunctionDef *) + let _ := M.return_ (| + M.call (| + M.get_name (| globals, "root" |), + make_list [ + M.get_field (| M.get_name (| globals, "state" |), "_main_trie" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Definition account_exists : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "state"; "address" ] |) in + let _ := Constant.str " + Checks if an account exists in the state trie + + Parameters + ---------- + state: + The state + address: + Address of the account that needs to be checked. + + Returns + ------- + account_exists : `bool` + True if account exists in the state trie, False otherwise + " in + let _ := M.return_ (| + Compare.is_not (| + M.call (| + M.get_name (| globals, "get_account_optional" |), + make_list [ + M.get_name (| globals, "state" |); + M.get_name (| globals, "address" |) + ], + make_dict [] + |), + Constant.None_ + |) + |) in + M.pure Constant.None_)). + +Definition account_has_code_or_nonce : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "state"; "address" ] |) in + let _ := Constant.str " + Checks if an account has non zero nonce or non empty code + + Parameters + ---------- + state: + The state + address: + Address of the account that needs to be checked. + + Returns + ------- + has_code_or_nonce : `bool` + True if if an account has non zero nonce or non empty code, + False otherwise. + " in + let _ := M.assign_local (| + "account" , + M.call (| + M.get_name (| globals, "get_account" |), + make_list [ + M.get_name (| globals, "state" |); + M.get_name (| globals, "address" |) + ], + make_dict [] + |) + |) in + let _ := M.return_ (| + BoolOp.or (| + Compare.not_eq (| + M.get_field (| M.get_name (| globals, "account" |), "nonce" |), + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + |), + ltac:(M.monadic ( + Compare.not_eq (| + M.get_field (| M.get_name (| globals, "account" |), "code" |), + Constant.bytes "" + |) + )) + |) + |) in + M.pure Constant.None_)). + +Definition is_account_empty : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "state"; "address" ] |) in + let _ := Constant.str " + Checks if an account has zero nonce, empty code and zero balance. + + Parameters + ---------- + state: + The state + address: + Address of the account that needs to be checked. + + Returns + ------- + is_empty : `bool` + True if if an account has zero nonce, empty code and zero balance, + False otherwise. + " in + let _ := M.assign_local (| + "account" , + M.call (| + M.get_name (| globals, "get_account" |), + make_list [ + M.get_name (| globals, "state" |); + M.get_name (| globals, "address" |) + ], + make_dict [] + |) + |) in + let _ := M.return_ (| + BoolOp.and (| + Compare.eq (| + M.get_field (| M.get_name (| globals, "account" |), "nonce" |), + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + |), + ltac:(M.monadic ( + BoolOp.and (| + Compare.eq (| + M.get_field (| M.get_name (| globals, "account" |), "code" |), + Constant.bytes "" + |), + ltac:(M.monadic ( + Compare.eq (| + M.get_field (| M.get_name (| globals, "account" |), "balance" |), + Constant.int 0 + |) + )) + |) + )) + |) + |) in + M.pure Constant.None_)). + +Definition account_exists_and_is_empty : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "state"; "address" ] |) in + let _ := Constant.str " + Checks if an account exists and has zero nonce, empty code and zero + balance. + + Parameters + ---------- + state: + The state + address: + Address of the account that needs to be checked. + + Returns + ------- + exists_and_is_empty : `bool` + True if an account exists and has zero nonce, empty code and zero + balance, False otherwise. + " in + let _ := M.assign_local (| + "account" , + M.call (| + M.get_name (| globals, "get_account_optional" |), + make_list [ + M.get_name (| globals, "state" |); + M.get_name (| globals, "address" |) + ], + make_dict [] + |) + |) in + let _ := M.return_ (| + BoolOp.and (| + Compare.is_not (| + M.get_name (| globals, "account" |), + Constant.None_ + |), + ltac:(M.monadic ( + BoolOp.and (| + Compare.eq (| + M.get_field (| M.get_name (| globals, "account" |), "nonce" |), + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + |), + ltac:(M.monadic ( + BoolOp.and (| + Compare.eq (| + M.get_field (| M.get_name (| globals, "account" |), "code" |), + Constant.bytes "" + |), + ltac:(M.monadic ( + Compare.eq (| + M.get_field (| M.get_name (| globals, "account" |), "balance" |), + Constant.int 0 + |) + )) + |) + )) + |) + )) + |) + |) in + M.pure Constant.None_)). + +Definition is_account_alive : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "state"; "address" ] |) in + let _ := Constant.str " + Check whether is an account is both in the state and non empty. + + Parameters + ---------- + state: + The state + address: + Address of the account that needs to be checked. + + Returns + ------- + is_alive : `bool` + True if the account is alive. + " in + let _ := M.assign_local (| + "account" , + M.call (| + M.get_name (| globals, "get_account_optional" |), + make_list [ + M.get_name (| globals, "state" |); + M.get_name (| globals, "address" |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.is (| + M.get_name (| globals, "account" |), + Constant.None_ + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + Constant.bool false + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.return_ (| + UnOp.not (| BoolOp.and (| + Compare.eq (| + M.get_field (| M.get_name (| globals, "account" |), "nonce" |), + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + |), + ltac:(M.monadic ( + BoolOp.and (| + Compare.eq (| + M.get_field (| M.get_name (| globals, "account" |), "code" |), + Constant.bytes "" + |), + ltac:(M.monadic ( + Compare.eq (| + M.get_field (| M.get_name (| globals, "account" |), "balance" |), + Constant.int 0 + |) + )) + |) + )) + |) |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_)). + +Definition modify_state : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "state"; "address"; "f" ] |) in + let _ := Constant.str " + Modify an `Account` in the `State`. + " in + let _ := M.call (| + M.get_name (| globals, "set_account" |), + make_list [ + M.get_name (| globals, "state" |); + M.get_name (| globals, "address" |); + M.call (| + M.get_name (| globals, "modify" |), + make_list [ + M.call (| + M.get_name (| globals, "get_account" |), + make_list [ + M.get_name (| globals, "state" |); + M.get_name (| globals, "address" |) + ], + make_dict [] + |); + M.get_name (| globals, "f" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + M.pure Constant.None_)). + +Definition move_ether : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "state"; "sender_address"; "recipient_address"; "amount" ] |) in + let _ := Constant.str " + Move funds between accounts. + " in +(* At stmt: unsupported node type: FunctionDef *) +(* At stmt: unsupported node type: FunctionDef *) + let _ := M.call (| + M.get_name (| globals, "modify_state" |), + make_list [ + M.get_name (| globals, "state" |); + M.get_name (| globals, "sender_address" |); + M.get_name (| globals, "reduce_sender_balance" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "modify_state" |), + make_list [ + M.get_name (| globals, "state" |); + M.get_name (| globals, "recipient_address" |); + M.get_name (| globals, "increase_recipient_balance" |) + ], + make_dict [] + |) in + M.pure Constant.None_)). + +Definition set_account_balance : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "state"; "address"; "amount" ] |) in + let _ := Constant.str " + Sets the balance of an account. + + Parameters + ---------- + state: + The current state. + + address: + Address of the account whose nonce needs to be incremented. + + amount: + The amount that needs to set in balance. + " in +(* At stmt: unsupported node type: FunctionDef *) + let _ := M.call (| + M.get_name (| globals, "modify_state" |), + make_list [ + M.get_name (| globals, "state" |); + M.get_name (| globals, "address" |); + M.get_name (| globals, "set_balance" |) + ], + make_dict [] + |) in + M.pure Constant.None_)). + +Definition touch_account : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "state"; "address" ] |) in + let _ := Constant.str " + Initializes an account to state. + + Parameters + ---------- + state: + The current state. + + address: + The address of the account that need to initialised. + " in + let _ := + (* if *) + M.if_then_else (| + UnOp.not (| M.call (| + M.get_name (| globals, "account_exists" |), + make_list [ + M.get_name (| globals, "state" |); + M.get_name (| globals, "address" |) + ], + make_dict [] + |) |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, "set_account" |), + make_list [ + M.get_name (| globals, "state" |); + M.get_name (| globals, "address" |); + M.get_name (| globals, "EMPTY_ACCOUNT" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + M.pure Constant.None_)). + +Definition increment_nonce : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "state"; "address" ] |) in + let _ := Constant.str " + Increments the nonce of an account. + + Parameters + ---------- + state: + The current state. + + address: + Address of the account whose nonce needs to be incremented. + " in +(* At stmt: unsupported node type: FunctionDef *) + let _ := M.call (| + M.get_name (| globals, "modify_state" |), + make_list [ + M.get_name (| globals, "state" |); + M.get_name (| globals, "address" |); + M.get_name (| globals, "increase_nonce" |) + ], + make_dict [] + |) in + M.pure Constant.None_)). + +Definition set_code : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "state"; "address"; "code" ] |) in + let _ := Constant.str " + Sets Account code. + + Parameters + ---------- + state: + The current state. + + address: + Address of the account whose code needs to be update. + + code: + The bytecode that needs to be set. + " in +(* At stmt: unsupported node type: FunctionDef *) + let _ := M.call (| + M.get_name (| globals, "modify_state" |), + make_list [ + M.get_name (| globals, "state" |); + M.get_name (| globals, "address" |); + M.get_name (| globals, "write_code" |) + ], + make_dict [] + |) in + M.pure Constant.None_)). + +Definition create_ether : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "state"; "address"; "amount" ] |) in + let _ := Constant.str " + Add newly created ether to an account. + + Parameters + ---------- + state: + The current state. + address: + Address of the account to which ether is added. + amount: + The amount of ether to be added to the account of interest. + " in +(* At stmt: unsupported node type: FunctionDef *) + let _ := M.call (| + M.get_name (| globals, "modify_state" |), + make_list [ + M.get_name (| globals, "state" |); + M.get_name (| globals, "address" |); + M.get_name (| globals, "increase_balance" |) + ], + make_dict [] + |) in + M.pure Constant.None_)). diff --git a/CoqOfPython/ethereum/spurious_dragon/transactions.v b/CoqOfPython/ethereum/spurious_dragon/transactions.v new file mode 100644 index 0000000..d563ae6 --- /dev/null +++ b/CoqOfPython/ethereum/spurious_dragon/transactions.v @@ -0,0 +1,56 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.spurious_dragon.transactions". + +Definition expr_1 : Value.t := + Constant.str " +Transactions are atomic units of work created externally to Ethereum and +submitted to be executed. If Ethereum is viewed as a state machine, +transactions are the events that move between states. +". + +Axiom dataclasses_imports_dataclass : + IsImported globals "dataclasses" "dataclass". + +Axiom typing_imports_Union : + IsImported globals "typing" "Union". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_Bytes : + IsImported globals "ethereum.base_types" "Bytes". +Axiom ethereum_base_types_imports_Bytes0 : + IsImported globals "ethereum.base_types" "Bytes0". +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". +Axiom ethereum_base_types_imports_slotted_freezable : + IsImported globals "ethereum.base_types" "slotted_freezable". + +Axiom ethereum_spurious_dragon_fork_types_imports_Address : + IsImported globals "ethereum.spurious_dragon.fork_types" "Address". + +Definition TX_BASE_COST : Value.t := M.run ltac:(M.monadic ( + Constant.int 21000 +)). + +Definition TX_DATA_COST_PER_NON_ZERO : Value.t := M.run ltac:(M.monadic ( + Constant.int 68 +)). + +Definition TX_DATA_COST_PER_ZERO : Value.t := M.run ltac:(M.monadic ( + Constant.int 4 +)). + +Definition TX_CREATE_COST : Value.t := M.run ltac:(M.monadic ( + Constant.int 32000 +)). + +Definition Transaction : Value.t := + builtins.make_klass + [] + [ + + ] + [ + + ]. diff --git a/CoqOfPython/ethereum/spurious_dragon/trie.v b/CoqOfPython/ethereum/spurious_dragon/trie.v new file mode 100644 index 0000000..acd6b08 --- /dev/null +++ b/CoqOfPython/ethereum/spurious_dragon/trie.v @@ -0,0 +1,1589 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.spurious_dragon.trie". + +Definition expr_1 : Value.t := + Constant.str " +State Trie +^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +The state trie is the structure responsible for storing +`.fork_types.Account` objects. +". + +(* At top_level_stmt: unsupported node type: Import *) + +Axiom dataclasses_imports_dataclass : + IsImported globals "dataclasses" "dataclass". +Axiom dataclasses_imports_field : + IsImported globals "dataclasses" "field". + +Axiom typing_imports_Callable : + IsImported globals "typing" "Callable". +Axiom typing_imports_Dict : + IsImported globals "typing" "Dict". +Axiom typing_imports_Generic : + IsImported globals "typing" "Generic". +Axiom typing_imports_List : + IsImported globals "typing" "List". +Axiom typing_imports_Mapping : + IsImported globals "typing" "Mapping". +Axiom typing_imports_MutableMapping : + IsImported globals "typing" "MutableMapping". +Axiom typing_imports_Optional : + IsImported globals "typing" "Optional". +Axiom typing_imports_Sequence : + IsImported globals "typing" "Sequence". +Axiom typing_imports_TypeVar : + IsImported globals "typing" "TypeVar". +Axiom typing_imports_Union : + IsImported globals "typing" "Union". +Axiom typing_imports_cast : + IsImported globals "typing" "cast". + +Axiom ethereum_crypto_hash_imports_keccak256 : + IsImported globals "ethereum.crypto.hash" "keccak256". + +Axiom ethereum_tangerine_whistle_imports_trie : + IsImported globals "ethereum.tangerine_whistle" "trie". + +Axiom ethereum_utils_ensure_imports_ensure : + IsImported globals "ethereum.utils.ensure" "ensure". + +Axiom ethereum_utils_hexadecimal_imports_hex_to_bytes : + IsImported globals "ethereum.utils.hexadecimal" "hex_to_bytes". + +Axiom ethereum_imports_rlp : + IsImported globals "ethereum" "rlp". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_Bytes : + IsImported globals "ethereum.base_types" "Bytes". +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". +Axiom ethereum_base_types_imports_slotted_freezable : + IsImported globals "ethereum.base_types" "slotted_freezable". + +Axiom ethereum_spurious_dragon_blocks_imports_Receipt : + IsImported globals "ethereum.spurious_dragon.blocks" "Receipt". + +Axiom ethereum_spurious_dragon_fork_types_imports_Account : + IsImported globals "ethereum.spurious_dragon.fork_types" "Account". +Axiom ethereum_spurious_dragon_fork_types_imports_Address : + IsImported globals "ethereum.spurious_dragon.fork_types" "Address". +Axiom ethereum_spurious_dragon_fork_types_imports_Root : + IsImported globals "ethereum.spurious_dragon.fork_types" "Root". +Axiom ethereum_spurious_dragon_fork_types_imports_encode_account : + IsImported globals "ethereum.spurious_dragon.fork_types" "encode_account". + +Axiom ethereum_spurious_dragon_transactions_imports_Transaction : + IsImported globals "ethereum.spurious_dragon.transactions" "Transaction". + +Definition EMPTY_TRIE_ROOT : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Root" |), + make_list [ + M.call (| + M.get_name (| globals, "hex_to_bytes" |), + make_list [ + Constant.str "56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421" + ], + make_dict [] + |) + ], + make_dict [] + |) +)). + +Definition Node : Value.t := M.run ltac:(M.monadic ( + M.get_subscript (| + M.get_name (| globals, "Union" |), + make_tuple [ M.get_name (| globals, "Account" |); M.get_name (| globals, "Bytes" |); M.get_name (| globals, "Transaction" |); M.get_name (| globals, "Receipt" |); M.get_name (| globals, "Uint" |); M.get_name (| globals, "U256" |); Constant.None_ ] + |) +)). + +Definition K : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "TypeVar" |), + make_list [ + Constant.str "K" + ], + make_dict [] + |) +)). + +Definition V : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "TypeVar" |), + make_list [ + Constant.str "V"; + M.get_subscript (| + M.get_name (| globals, "Optional" |), + M.get_name (| globals, "Account" |) + |); + M.get_subscript (| + M.get_name (| globals, "Optional" |), + M.get_name (| globals, "Bytes" |) + |); + M.get_name (| globals, "Bytes" |); + M.get_subscript (| + M.get_name (| globals, "Optional" |), + M.get_name (| globals, "Transaction" |) + |); + M.get_subscript (| + M.get_name (| globals, "Optional" |), + M.get_name (| globals, "Receipt" |) + |); + M.get_name (| globals, "Uint" |); + M.get_name (| globals, "U256" |) + ], + make_dict [] + |) +)). + +Definition LeafNode : Value.t := + builtins.make_klass + [] + [ + + ] + [ + + ]. + +Definition ExtensionNode : Value.t := + builtins.make_klass + [] + [ + + ] + [ + + ]. + +Definition BranchNode : Value.t := + builtins.make_klass + [] + [ + + ] + [ + + ]. + +Definition InternalNode : Value.t := M.run ltac:(M.monadic ( + M.get_subscript (| + M.get_name (| globals, "Union" |), + make_tuple [ M.get_name (| globals, "LeafNode" |); M.get_name (| globals, "ExtensionNode" |); M.get_name (| globals, "BranchNode" |) ] + |) +)). + +Definition encode_internal_node : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "node" ] |) in + let _ := Constant.str " + Encodes a Merkle Trie node into its RLP form. The RLP will then be + serialized into a `Bytes` and hashed unless it is less that 32 bytes + when serialized. + + This function also accepts `None`, representing the absence of a node, + which is encoded to `b""""`. + + Parameters + ---------- + node : Optional[InternalNode] + The node to encode. + + Returns + ------- + encoded : `rlp.RLP` + The node encoded as RLP. + " in +(* At stmt: unsupported node type: AnnAssign *) + let _ := + (* if *) + M.if_then_else (| + Compare.is (| + M.get_name (| globals, "node" |), + Constant.None_ + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "unencoded" , + Constant.bytes "" + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, "isinstance" |), + make_list [ + M.get_name (| globals, "node" |); + M.get_name (| globals, "LeafNode" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "unencoded" , + make_tuple [ M.call (| + M.get_name (| globals, "nibble_list_to_compact" |), + make_list [ + M.get_field (| M.get_name (| globals, "node" |), "rest_of_key" |); + Constant.bool true + ], + make_dict [] + |); M.get_field (| M.get_name (| globals, "node" |), "value" |) ] + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, "isinstance" |), + make_list [ + M.get_name (| globals, "node" |); + M.get_name (| globals, "ExtensionNode" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "unencoded" , + make_tuple [ M.call (| + M.get_name (| globals, "nibble_list_to_compact" |), + make_list [ + M.get_field (| M.get_name (| globals, "node" |), "key_segment" |); + Constant.bool false + ], + make_dict [] + |); M.get_field (| M.get_name (| globals, "node" |), "subnode" |) ] + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, "isinstance" |), + make_list [ + M.get_name (| globals, "node" |); + M.get_name (| globals, "BranchNode" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "unencoded" , + BinOp.add (| + M.get_field (| M.get_name (| globals, "node" |), "subnodes" |), + make_list [ + M.get_field (| M.get_name (| globals, "node" |), "value" |) + ] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.raise (| Some (M.call (| + M.get_name (| globals, "AssertionError" |), + make_list [ + Constant.str "(* At expr: unsupported node type: JoinedStr *)" + ], + make_dict [] + |)) |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "encoded" , + M.call (| + M.get_field (| M.get_name (| globals, "rlp" |), "encode" |), + make_list [ + M.get_name (| globals, "unencoded" |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.lt (| + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_name (| globals, "encoded" |) + ], + make_dict [] + |), + Constant.int 32 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + M.get_name (| globals, "unencoded" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.return_ (| + M.call (| + M.get_name (| globals, "keccak256" |), + make_list [ + M.get_name (| globals, "encoded" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_)). + +Definition encode_node : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "node"; "storage_root" ] |) in + let _ := Constant.str " + Encode a Node for storage in the Merkle Trie. + + Currently mostly an unimplemented stub. + " in + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, "isinstance" |), + make_list [ + M.get_name (| globals, "node" |); + M.get_name (| globals, "Account" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assert (| Compare.is_not (| + M.get_name (| globals, "storage_root" |), + Constant.None_ + |) |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, "encode_account" |), + make_list [ + M.get_name (| globals, "node" |); + M.get_name (| globals, "storage_root" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, "isinstance" |), + make_list [ + M.get_name (| globals, "node" |); + make_tuple [ M.get_name (| globals, "Transaction" |); M.get_name (| globals, "Receipt" |); M.get_name (| globals, "U256" |) ] + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + M.call (| + M.get_field (| M.get_name (| globals, "rlp" |), "encode" |), + make_list [ + M.call (| + M.get_name (| globals, "cast" |), + make_list [ + M.get_field (| M.get_name (| globals, "rlp" |), "RLP" |); + M.get_name (| globals, "node" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, "isinstance" |), + make_list [ + M.get_name (| globals, "node" |); + M.get_name (| globals, "Bytes" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + M.get_name (| globals, "node" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.return_ (| + M.call (| + M.get_field (| M.get_name (| globals, "previous_trie" |), "encode_node" |), + make_list [ + M.get_name (| globals, "node" |); + M.get_name (| globals, "storage_root" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_)). + +Definition Trie : Value.t := + builtins.make_klass + [(* At base: unsupported node type: Subscript *)] + [ + + ] + [ + + ]. + +Definition copy_trie : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "trie" ] |) in + let _ := Constant.str " + Create a copy of `trie`. Since only frozen objects may be stored in tries, + the contents are reused. + + Parameters + ---------- + trie: `Trie` + Trie to copy. + + Returns + ------- + new_trie : `Trie[K, V]` + A copy of the trie. + " in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, "Trie" |), + make_list [ + M.get_field (| M.get_name (| globals, "trie" |), "secured" |); + M.get_field (| M.get_name (| globals, "trie" |), "default" |); + M.call (| + M.get_field (| M.get_name (| globals, "copy" |), "copy" |), + make_list [ + M.get_field (| M.get_name (| globals, "trie" |), "_data" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Definition trie_set : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "trie"; "key"; "value" ] |) in + let _ := Constant.str " + Stores an item in a Merkle Trie. + + This method deletes the key if `value == trie.default`, because the Merkle + Trie represents the default value by omitting it from the trie. + + Parameters + ---------- + trie: `Trie` + Trie to store in. + key : `Bytes` + Key to lookup. + value : `V` + Node to insert at `key`. + " in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, "value" |), + M.get_field (| M.get_name (| globals, "trie" |), "default" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + Compare.in_ (| + M.get_name (| globals, "key" |), + M.get_field (| M.get_name (| globals, "trie" |), "_data" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.delete (| M.get_subscript (| + M.get_field (| M.get_name (| globals, "trie" |), "_data" |), + M.get_name (| globals, "key" |) + |) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign (| + M.get_subscript (| + M.get_field (| M.get_name (| globals, "trie" |), "_data" |), + M.get_name (| globals, "key" |) + |), + M.get_name (| globals, "value" |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_)). + +Definition trie_get : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "trie"; "key" ] |) in + let _ := Constant.str " + Gets an item from the Merkle Trie. + + This method returns `trie.default` if the key is missing. + + Parameters + ---------- + trie: + Trie to lookup in. + key : + Key to lookup. + + Returns + ------- + node : `V` + Node at `key` in the trie. + " in + let _ := M.return_ (| + M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, "trie" |), "_data" |), "get" |), + make_list [ + M.get_name (| globals, "key" |); + M.get_field (| M.get_name (| globals, "trie" |), "default" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Definition common_prefix_length : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "a"; "b" ] |) in + let _ := Constant.str " + Find the longest common prefix of two sequences. + " in + let _ := + M.for_ (| + M.get_name (| globals, "i" |), + M.call (| + M.get_name (| globals, "range" |), + make_list [ + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_name (| globals, "a" |) + ], + make_dict [] + |) + ], + make_dict [] + |), + ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + BoolOp.or (| + Compare.gt_e (| + M.get_name (| globals, "i" |), + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_name (| globals, "b" |) + ], + make_dict [] + |) + |), + ltac:(M.monadic ( + Compare.not_eq (| + M.get_subscript (| + M.get_name (| globals, "a" |), + M.get_name (| globals, "i" |) + |), + M.get_subscript (| + M.get_name (| globals, "b" |), + M.get_name (| globals, "i" |) + |) + |) + )) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + M.get_name (| globals, "i" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_name (| globals, "a" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Definition nibble_list_to_compact : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "x"; "is_leaf" ] |) in + let _ := Constant.str " + Compresses nibble-list into a standard byte array with a flag. + + A nibble-list is a list of byte values no greater than `15`. The flag is + encoded in high nibble of the highest byte. The flag nibble can be broken + down into two two-bit flags. + + Highest nibble:: + + +---+---+----------+--------+ + | _ | _ | is_leaf | parity | + +---+---+----------+--------+ + 3 2 1 0 + + + The lowest bit of the nibble encodes the parity of the length of the + remaining nibbles -- `0` when even and `1` when odd. The second lowest bit + is used to distinguish leaf and extension nodes. The other two bits are not + used. + + Parameters + ---------- + x : + Array of nibbles. + is_leaf : + True if this is part of a leaf node, or false if it is an extension + node. + + Returns + ------- + compressed : `bytearray` + Compact byte array. + " in + let _ := M.assign_local (| + "compact" , + M.call (| + M.get_name (| globals, "bytearray" |), + make_list [], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + BinOp.mod_ (| + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_name (| globals, "x" |) + ], + make_dict [] + |), + Constant.int 2 + |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_field (| M.get_name (| globals, "compact" |), "append" |), + make_list [ + BinOp.mult (| + Constant.int 16, + BinOp.mult (| + Constant.int 2, + M.get_name (| globals, "is_leaf" |) + |) + |) + ], + make_dict [] + |) in + let _ := + M.for_ (| + M.get_name (| globals, "i" |), + M.call (| + M.get_name (| globals, "range" |), + make_list [ + Constant.int 0; + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_name (| globals, "x" |) + ], + make_dict [] + |); + Constant.int 2 + ], + make_dict [] + |), + ltac:(M.monadic ( + let _ := M.call (| + M.get_field (| M.get_name (| globals, "compact" |), "append" |), + make_list [ + BinOp.add (| + BinOp.mult (| + Constant.int 16, + M.get_subscript (| + M.get_name (| globals, "x" |), + M.get_name (| globals, "i" |) + |) + |), + M.get_subscript (| + M.get_name (| globals, "x" |), + BinOp.add (| + M.get_name (| globals, "i" |), + Constant.int 1 + |) + |) + |) + ], + make_dict [] + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.call (| + M.get_field (| M.get_name (| globals, "compact" |), "append" |), + make_list [ + BinOp.add (| + BinOp.mult (| + Constant.int 16, + BinOp.add (| + BinOp.mult (| + Constant.int 2, + M.get_name (| globals, "is_leaf" |) + |), + Constant.int 1 + |) + |), + M.get_subscript (| + M.get_name (| globals, "x" |), + Constant.int 0 + |) + |) + ], + make_dict [] + |) in + let _ := + M.for_ (| + M.get_name (| globals, "i" |), + M.call (| + M.get_name (| globals, "range" |), + make_list [ + Constant.int 1; + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_name (| globals, "x" |) + ], + make_dict [] + |); + Constant.int 2 + ], + make_dict [] + |), + ltac:(M.monadic ( + let _ := M.call (| + M.get_field (| M.get_name (| globals, "compact" |), "append" |), + make_list [ + BinOp.add (| + BinOp.mult (| + Constant.int 16, + M.get_subscript (| + M.get_name (| globals, "x" |), + M.get_name (| globals, "i" |) + |) + |), + M.get_subscript (| + M.get_name (| globals, "x" |), + BinOp.add (| + M.get_name (| globals, "i" |), + Constant.int 1 + |) + |) + |) + ], + make_dict [] + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + M.pure Constant.None_ + )) |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, "Bytes" |), + make_list [ + M.get_name (| globals, "compact" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Definition bytes_to_nibble_list : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "bytes_" ] |) in + let _ := Constant.str " + Converts a `Bytes` into to a sequence of nibbles (bytes with value < 16). + + Parameters + ---------- + bytes_: + The `Bytes` to convert. + + Returns + ------- + nibble_list : `Bytes` + The `Bytes` in nibble-list format. + " in + let _ := M.assign_local (| + "nibble_list" , + M.call (| + M.get_name (| globals, "bytearray" |), + make_list [ + BinOp.mult (| + Constant.int 2, + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_name (| globals, "bytes_" |) + ], + make_dict [] + |) + |) + ], + make_dict [] + |) + |) in + let _ := + M.for_ (| + make_tuple [ M.get_name (| globals, "byte_index" |); M.get_name (| globals, "byte" |) ], + M.call (| + M.get_name (| globals, "enumerate" |), + make_list [ + M.get_name (| globals, "bytes_" |) + ], + make_dict [] + |), + ltac:(M.monadic ( + let _ := M.assign (| + M.get_subscript (| + M.get_name (| globals, "nibble_list" |), + BinOp.mult (| + M.get_name (| globals, "byte_index" |), + Constant.int 2 + |) + |), + BinOp.r_shift (| + BinOp.bit_and (| + M.get_name (| globals, "byte" |), + Constant.int 240 + |), + Constant.int 4 + |) + |) in + let _ := M.assign (| + M.get_subscript (| + M.get_name (| globals, "nibble_list" |), + BinOp.add (| + BinOp.mult (| + M.get_name (| globals, "byte_index" |), + Constant.int 2 + |), + Constant.int 1 + |) + |), + BinOp.bit_and (| + M.get_name (| globals, "byte" |), + Constant.int 15 + |) + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, "Bytes" |), + make_list [ + M.get_name (| globals, "nibble_list" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Definition _prepare_trie : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "trie"; "get_storage_root" ] |) in + let _ := Constant.str " + Prepares the trie for root calculation. Removes values that are empty, + hashes the keys (if `secured == True`) and encodes all the nodes. + + Parameters + ---------- + trie : + The `Trie` to prepare. + get_storage_root : + Function to get the storage root of an account. Needed to encode + `Account` objects. + + Returns + ------- + out : `Mapping[ethereum.base_types.Bytes, Node]` + Object with keys mapped to nibble-byte form. + " in +(* At stmt: unsupported node type: AnnAssign *) + let _ := + M.for_ (| + make_tuple [ M.get_name (| globals, "preimage" |); M.get_name (| globals, "value" |) ], + M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, "trie" |), "_data" |), "items" |), + make_list [], + make_dict [] + |), + ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, "isinstance" |), + make_list [ + M.get_name (| globals, "value" |); + M.get_name (| globals, "Account" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assert (| Compare.is_not (| + M.get_name (| globals, "get_storage_root" |), + Constant.None_ + |) |) in + let _ := M.assign_local (| + "address" , + M.call (| + M.get_name (| globals, "Address" |), + make_list [ + M.get_name (| globals, "preimage" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "encoded_value" , + M.call (| + M.get_name (| globals, "encode_node" |), + make_list [ + M.get_name (| globals, "value" |); + M.call (| + M.get_name (| globals, "get_storage_root" |), + make_list [ + M.get_name (| globals, "address" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "encoded_value" , + M.call (| + M.get_name (| globals, "encode_node" |), + make_list [ + M.get_name (| globals, "value" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + )) |) in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + Compare.not_eq (| + M.get_name (| globals, "encoded_value" |), + Constant.bytes "" + |); + M.get_name (| globals, "AssertionError" |) + ], + make_dict [] + |) in +(* At stmt: unsupported node type: AnnAssign *) + let _ := + (* if *) + M.if_then_else (| + M.get_field (| M.get_name (| globals, "trie" |), "secured" |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "key" , + M.call (| + M.get_name (| globals, "keccak256" |), + make_list [ + M.get_name (| globals, "preimage" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "key" , + M.get_name (| globals, "preimage" |) + |) in + M.pure Constant.None_ + )) |) in + let _ := M.assign (| + M.get_subscript (| + M.get_name (| globals, "mapped" |), + M.call (| + M.get_name (| globals, "bytes_to_nibble_list" |), + make_list [ + M.get_name (| globals, "key" |) + ], + make_dict [] + |) + |), + M.get_name (| globals, "encoded_value" |) + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := M.return_ (| + M.get_name (| globals, "mapped" |) + |) in + M.pure Constant.None_)). + +Definition root : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "trie"; "get_storage_root" ] |) in + let _ := Constant.str " + Computes the root of a modified merkle patricia trie (MPT). + + Parameters + ---------- + trie : + `Trie` to get the root of. + get_storage_root : + Function to get the storage root of an account. Needed to encode + `Account` objects. + + + Returns + ------- + root : `.fork_types.Root` + MPT root of the underlying key-value pairs. + " in + let _ := M.assign_local (| + "obj" , + M.call (| + M.get_name (| globals, "_prepare_trie" |), + make_list [ + M.get_name (| globals, "trie" |); + M.get_name (| globals, "get_storage_root" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "root_node" , + M.call (| + M.get_name (| globals, "encode_internal_node" |), + make_list [ + M.call (| + M.get_name (| globals, "patricialize" |), + make_list [ + M.get_name (| globals, "obj" |); + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.lt (| + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.call (| + M.get_field (| M.get_name (| globals, "rlp" |), "encode" |), + make_list [ + M.get_name (| globals, "root_node" |) + ], + make_dict [] + |) + ], + make_dict [] + |), + Constant.int 32 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + M.call (| + M.get_name (| globals, "keccak256" |), + make_list [ + M.call (| + M.get_field (| M.get_name (| globals, "rlp" |), "encode" |), + make_list [ + M.get_name (| globals, "root_node" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assert (| M.call (| + M.get_name (| globals, "isinstance" |), + make_list [ + M.get_name (| globals, "root_node" |); + M.get_name (| globals, "Bytes" |) + ], + make_dict [] + |) |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, "Root" |), + make_list [ + M.get_name (| globals, "root_node" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_)). + +Definition patricialize : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "obj"; "level" ] |) in + let _ := Constant.str " + Structural composition function. + + Used to recursively patricialize and merkleize a dictionary. Includes + memoization of the tree structure and hashes. + + Parameters + ---------- + obj : + Underlying trie key-value pairs, with keys in nibble-list format. + level : + Current trie level. + + Returns + ------- + node : `ethereum.base_types.Bytes` + Root node of `obj`. + " in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_name (| globals, "obj" |) + ], + make_dict [] + |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + Constant.None_ + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "arbitrary_key" , + M.call (| + M.get_name (| globals, "next" |), + make_list [ + M.call (| + M.get_name (| globals, "iter" |), + make_list [ + M.get_name (| globals, "obj" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_name (| globals, "obj" |) + ], + make_dict [] + |), + Constant.int 1 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "leaf" , + M.call (| + M.get_name (| globals, "LeafNode" |), + make_list [ + M.slice (| + M.get_name (| globals, "arbitrary_key" |), + M.get_name (| globals, "level" |), + Constant.None_, + Constant.None_ + |); + M.get_subscript (| + M.get_name (| globals, "obj" |), + M.get_name (| globals, "arbitrary_key" |) + |) + ], + make_dict [] + |) + |) in + let _ := M.return_ (| + M.get_name (| globals, "leaf" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "substring" , + M.slice (| + M.get_name (| globals, "arbitrary_key" |), + M.get_name (| globals, "level" |), + Constant.None_, + Constant.None_ + |) + |) in + let _ := M.assign_local (| + "prefix_length" , + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_name (| globals, "substring" |) + ], + make_dict [] + |) + |) in + let _ := + M.for_ (| + M.get_name (| globals, "key" |), + M.get_name (| globals, "obj" |), + ltac:(M.monadic ( + let _ := M.assign_local (| + "prefix_length" , + M.call (| + M.get_name (| globals, "min" |), + make_list [ + M.get_name (| globals, "prefix_length" |); + M.call (| + M.get_name (| globals, "common_prefix_length" |), + make_list [ + M.get_name (| globals, "substring" |); + M.slice (| + M.get_name (| globals, "key" |), + M.get_name (| globals, "level" |), + Constant.None_, + Constant.None_ + |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, "prefix_length" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.break (| |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.gt (| + M.get_name (| globals, "prefix_length" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "prefix" , + M.slice (| + M.get_name (| globals, "arbitrary_key" |), + M.get_name (| globals, "level" |), + BinOp.add (| + M.get_name (| globals, "level" |), + M.get_name (| globals, "prefix_length" |) + |), + Constant.None_ + |) + |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, "ExtensionNode" |), + make_list [ + M.get_name (| globals, "prefix" |); + M.call (| + M.get_name (| globals, "encode_internal_node" |), + make_list [ + M.call (| + M.get_name (| globals, "patricialize" |), + make_list [ + M.get_name (| globals, "obj" |); + BinOp.add (| + M.get_name (| globals, "level" |), + M.get_name (| globals, "prefix_length" |) + |) + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in +(* At stmt: unsupported node type: AnnAssign *) + let _ := + M.for_ (| + M.get_name (| globals, "_" |), + M.call (| + M.get_name (| globals, "range" |), + make_list [ + Constant.int 16 + ], + make_dict [] + |), + ltac:(M.monadic ( + let _ := M.call (| + M.get_field (| M.get_name (| globals, "branches" |), "append" |), + make_list [ + Constant.str "(* At expr: unsupported node type: Dict *)" + ], + make_dict [] + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := M.assign_local (| + "value" , + Constant.bytes "" + |) in + let _ := + M.for_ (| + M.get_name (| globals, "key" |), + M.get_name (| globals, "obj" |), + ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_name (| globals, "key" |) + ], + make_dict [] + |), + M.get_name (| globals, "level" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, "isinstance" |), + make_list [ + M.get_subscript (| + M.get_name (| globals, "obj" |), + M.get_name (| globals, "key" |) + |); + make_tuple [ M.get_name (| globals, "Account" |); M.get_name (| globals, "Receipt" |); M.get_name (| globals, "Uint" |) ] + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, "AssertionError" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "value" , + M.get_subscript (| + M.get_name (| globals, "obj" |), + M.get_name (| globals, "key" |) + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign (| + M.get_subscript (| + M.get_subscript (| + M.get_name (| globals, "branches" |), + M.get_subscript (| + M.get_name (| globals, "key" |), + M.get_name (| globals, "level" |) + |) + |), + M.get_name (| globals, "key" |) + |), + M.get_subscript (| + M.get_name (| globals, "obj" |), + M.get_name (| globals, "key" |) + |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, "BranchNode" |), + make_list [ + Constant.str "(* At expr: unsupported node type: ListComp *)"; + M.get_name (| globals, "value" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). diff --git a/CoqOfPython/ethereum/spurious_dragon/utils/__init__.v b/CoqOfPython/ethereum/spurious_dragon/utils/__init__.v new file mode 100644 index 0000000..05c126f --- /dev/null +++ b/CoqOfPython/ethereum/spurious_dragon/utils/__init__.v @@ -0,0 +1,8 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.spurious_dragon.utils.__init__". + +Definition expr_1 : Value.t := + Constant.str " +Utility functions unique to this particular fork. +". diff --git a/CoqOfPython/ethereum/spurious_dragon/utils/address.v b/CoqOfPython/ethereum/spurious_dragon/utils/address.v new file mode 100644 index 0000000..a4a5c3d --- /dev/null +++ b/CoqOfPython/ethereum/spurious_dragon/utils/address.v @@ -0,0 +1,144 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.spurious_dragon.utils.address". + +Definition expr_1 : Value.t := + Constant.str " +Hardfork Utility Functions For Addresses +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Address specific functions used in this spurious dragon version of +specification. +". + +Axiom typing_imports_Union : + IsImported globals "typing" "Union". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". + +Axiom ethereum_crypto_hash_imports_keccak256 : + IsImported globals "ethereum.crypto.hash" "keccak256". + +Axiom ethereum_utils_byte_imports_left_pad_zero_bytes : + IsImported globals "ethereum.utils.byte" "left_pad_zero_bytes". + +Axiom ethereum_imports_rlp : + IsImported globals "ethereum" "rlp". + +Axiom ethereum_spurious_dragon_fork_types_imports_Address : + IsImported globals "ethereum.spurious_dragon.fork_types" "Address". + +Definition to_address : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "data" ] |) in + let _ := Constant.str " + Convert a Uint or U256 value to a valid address (20 bytes). + + Parameters + ---------- + data : + The string to be converted to bytes. + + Returns + ------- + address : `Address` + The obtained address. + " in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, "Address" |), + make_list [ + M.slice (| + M.call (| + M.get_field (| M.get_name (| globals, "data" |), "to_be_bytes32" |), + make_list [], + make_dict [] + |), + UnOp.sub (| Constant.int 20 |), + Constant.None_, + Constant.None_ + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Definition compute_contract_address : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "address"; "nonce" ] |) in + let _ := Constant.str " + Computes address of the new account that needs to be created. + + Parameters + ---------- + address : + The address of the account that wants to create the new account. + nonce : + The transaction count of the account that wants to create the new + account. + + Returns + ------- + address: `ethereum.spurious_dragon.fork_types.Address` + The computed address of the new account. + " in + let _ := M.assign_local (| + "computed_address" , + M.call (| + M.get_name (| globals, "keccak256" |), + make_list [ + M.call (| + M.get_field (| M.get_name (| globals, "rlp" |), "encode" |), + make_list [ + make_list [ + M.get_name (| globals, "address" |); + M.get_name (| globals, "nonce" |) + ] + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "canonical_address" , + M.slice (| + M.get_name (| globals, "computed_address" |), + UnOp.sub (| Constant.int 20 |), + Constant.None_, + Constant.None_ + |) + |) in + let _ := M.assign_local (| + "padded_address" , + M.call (| + M.get_name (| globals, "left_pad_zero_bytes" |), + make_list [ + M.get_name (| globals, "canonical_address" |); + Constant.int 20 + ], + make_dict [] + |) + |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, "Address" |), + make_list [ + M.get_name (| globals, "padded_address" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). diff --git a/CoqOfPython/ethereum/spurious_dragon/utils/hexadecimal.v b/CoqOfPython/ethereum/spurious_dragon/utils/hexadecimal.v new file mode 100644 index 0000000..bbdbabf --- /dev/null +++ b/CoqOfPython/ethereum/spurious_dragon/utils/hexadecimal.v @@ -0,0 +1,153 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.spurious_dragon.utils.hexadecimal". + +Definition expr_1 : Value.t := + Constant.str " +Utility Functions For Hexadecimal Strings +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Hexadecimal utility functions used in this specification, specific to +Spurious Dragon types. +". + +Axiom ethereum_utils_hexadecimal_imports_remove_hex_prefix : + IsImported globals "ethereum.utils.hexadecimal" "remove_hex_prefix". + +Axiom ethereum_spurious_dragon_fork_types_imports_Address : + IsImported globals "ethereum.spurious_dragon.fork_types" "Address". +Axiom ethereum_spurious_dragon_fork_types_imports_Bloom : + IsImported globals "ethereum.spurious_dragon.fork_types" "Bloom". +Axiom ethereum_spurious_dragon_fork_types_imports_Root : + IsImported globals "ethereum.spurious_dragon.fork_types" "Root". + +Definition hex_to_root : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "hex_string" ] |) in + let _ := Constant.str " + Convert hex string to trie root. + + Parameters + ---------- + hex_string : + The hexadecimal string to be converted to trie root. + + Returns + ------- + root : `Root` + Trie root obtained from the given hexadecimal string. + " in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, "Root" |), + make_list [ + M.call (| + M.get_field (| M.get_name (| globals, "bytes" |), "fromhex" |), + make_list [ + M.call (| + M.get_name (| globals, "remove_hex_prefix" |), + make_list [ + M.get_name (| globals, "hex_string" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Definition hex_to_bloom : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "hex_string" ] |) in + let _ := Constant.str " + Convert hex string to bloom. + + Parameters + ---------- + hex_string : + The hexadecimal string to be converted to bloom. + + Returns + ------- + bloom : `Bloom` + Bloom obtained from the given hexadecimal string. + " in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, "Bloom" |), + make_list [ + M.call (| + M.get_field (| M.get_name (| globals, "bytes" |), "fromhex" |), + make_list [ + M.call (| + M.get_name (| globals, "remove_hex_prefix" |), + make_list [ + M.get_name (| globals, "hex_string" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Definition hex_to_address : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "hex_string" ] |) in + let _ := Constant.str " + Convert hex string to Address (20 bytes). + + Parameters + ---------- + hex_string : + The hexadecimal string to be converted to Address. + + Returns + ------- + address : `Address` + The address obtained from the given hexadecimal string. + " in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, "Address" |), + make_list [ + M.call (| + M.get_field (| M.get_name (| globals, "bytes" |), "fromhex" |), + make_list [ + M.call (| + M.get_field (| M.call (| + M.get_name (| globals, "remove_hex_prefix" |), + make_list [ + M.get_name (| globals, "hex_string" |) + ], + make_dict [] + |), "rjust" |), + make_list [ + Constant.int 40; + Constant.str "0" + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). diff --git a/CoqOfPython/ethereum/spurious_dragon/utils/message.v b/CoqOfPython/ethereum/spurious_dragon/utils/message.v new file mode 100644 index 0000000..a356277 --- /dev/null +++ b/CoqOfPython/ethereum/spurious_dragon/utils/message.v @@ -0,0 +1,209 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.spurious_dragon.utils.message". + +Definition expr_1 : Value.t := + Constant.str " +Hardfork Utility Functions For The Message Data-structure +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Message specific functions used in this spurious dragon version of +specification. +". + +Axiom typing_imports_Optional : + IsImported globals "typing" "Optional". +Axiom typing_imports_Union : + IsImported globals "typing" "Union". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_Bytes : + IsImported globals "ethereum.base_types" "Bytes". +Axiom ethereum_base_types_imports_Bytes0 : + IsImported globals "ethereum.base_types" "Bytes0". +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". + +Axiom ethereum_spurious_dragon_fork_types_imports_Address : + IsImported globals "ethereum.spurious_dragon.fork_types" "Address". + +Axiom ethereum_spurious_dragon_state_imports_get_account : + IsImported globals "ethereum.spurious_dragon.state" "get_account". + +Axiom ethereum_spurious_dragon_vm_imports_Environment : + IsImported globals "ethereum.spurious_dragon.vm" "Environment". +Axiom ethereum_spurious_dragon_vm_imports_Message : + IsImported globals "ethereum.spurious_dragon.vm" "Message". + +Axiom ethereum_spurious_dragon_utils_address_imports_compute_contract_address : + IsImported globals "ethereum.spurious_dragon.utils.address" "compute_contract_address". + +Definition prepare_message : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "caller"; "target"; "value"; "data"; "gas"; "env"; "code_address"; "should_transfer_value" ] |) in + let _ := Constant.str " + Execute a transaction against the provided environment. + + Parameters + ---------- + caller : + Address which initiated the transaction + target : + Address whose code will be executed + value : + Value to be transferred. + data : + Array of bytes provided to the code in `target`. + gas : + Gas provided for the code in `target`. + env : + Environment for the Ethereum Virtual Machine. + code_address : + This is usually same as the `target` address except when an alternative + accounts code needs to be executed. + eg. `CALLCODE` calling a precompile. + should_transfer_value : + if True ETH should be transferred while executing a message call. + + Returns + ------- + message: `ethereum.spurious_dragon.vm.Message` + Items containing contract creation or message call specific data. + " in + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, "isinstance" |), + make_list [ + M.get_name (| globals, "target" |); + M.get_name (| globals, "Bytes0" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "current_target" , + M.call (| + M.get_name (| globals, "compute_contract_address" |), + make_list [ + M.get_name (| globals, "caller" |); + BinOp.sub (| + M.get_field (| M.call (| + M.get_name (| globals, "get_account" |), + make_list [ + M.get_field (| M.get_name (| globals, "env" |), "state" |); + M.get_name (| globals, "caller" |) + ], + make_dict [] + |), "nonce" |), + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 1 + ], + make_dict [] + |) + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "msg_data" , + M.call (| + M.get_name (| globals, "Bytes" |), + make_list [ + Constant.bytes "" + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "code" , + M.get_name (| globals, "data" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, "isinstance" |), + make_list [ + M.get_name (| globals, "target" |); + M.get_name (| globals, "Address" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "current_target" , + M.get_name (| globals, "target" |) + |) in + let _ := M.assign_local (| + "msg_data" , + M.get_name (| globals, "data" |) + |) in + let _ := M.assign_local (| + "code" , + M.get_field (| M.call (| + M.get_name (| globals, "get_account" |), + make_list [ + M.get_field (| M.get_name (| globals, "env" |), "state" |); + M.get_name (| globals, "target" |) + ], + make_dict [] + |), "code" |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.is (| + M.get_name (| globals, "code_address" |), + Constant.None_ + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "code_address" , + M.get_name (| globals, "target" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.raise (| Some (M.call (| + M.get_name (| globals, "AssertionError" |), + make_list [ + Constant.str "Target must be address or empty bytes" + ], + make_dict [] + |)) |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )) |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, "Message" |), + make_list [], + make_dict [] + |) + |) in + M.pure Constant.None_)). diff --git a/CoqOfPython/ethereum/spurious_dragon/vm/__init__.v b/CoqOfPython/ethereum/spurious_dragon/vm/__init__.v new file mode 100644 index 0000000..9637d09 --- /dev/null +++ b/CoqOfPython/ethereum/spurious_dragon/vm/__init__.v @@ -0,0 +1,242 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.spurious_dragon.vm.__init__". + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +The abstract computer which runs the code stored in an +`.fork_types.Account`. +". + +Axiom dataclasses_imports_dataclass : + IsImported globals "dataclasses" "dataclass". + +Axiom typing_imports_List : + IsImported globals "typing" "List". +Axiom typing_imports_Optional : + IsImported globals "typing" "Optional". +Axiom typing_imports_Set : + IsImported globals "typing" "Set". +Axiom typing_imports_Tuple : + IsImported globals "typing" "Tuple". +Axiom typing_imports_Union : + IsImported globals "typing" "Union". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_Bytes : + IsImported globals "ethereum.base_types" "Bytes". +Axiom ethereum_base_types_imports_Bytes0 : + IsImported globals "ethereum.base_types" "Bytes0". +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". + +Axiom ethereum_crypto_hash_imports_Hash32 : + IsImported globals "ethereum.crypto.hash" "Hash32". + +Axiom ethereum_spurious_dragon_blocks_imports_Log : + IsImported globals "ethereum.spurious_dragon.blocks" "Log". + +Axiom ethereum_spurious_dragon_fork_types_imports_Address : + IsImported globals "ethereum.spurious_dragon.fork_types" "Address". + +Axiom ethereum_spurious_dragon_state_imports_State : + IsImported globals "ethereum.spurious_dragon.state" "State". +Axiom ethereum_spurious_dragon_state_imports_account_exists_and_is_empty : + IsImported globals "ethereum.spurious_dragon.state" "account_exists_and_is_empty". + +Axiom ethereum_spurious_dragon_vm_precompiled_contracts_imports_RIPEMD160_ADDRESS : + IsImported globals "ethereum.spurious_dragon.vm.precompiled_contracts" "RIPEMD160_ADDRESS". + +Definition __all__ : Value.t := M.run ltac:(M.monadic ( + make_tuple [ Constant.str "Environment"; Constant.str "Evm"; Constant.str "Message" ] +)). + +Definition Environment : Value.t := + builtins.make_klass + [] + [ + + ] + [ + + ]. + +Definition Message : Value.t := + builtins.make_klass + [] + [ + + ] + [ + + ]. + +Definition Evm : Value.t := + builtins.make_klass + [] + [ + + ] + [ + + ]. + +Definition incorporate_child_on_success : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm"; "child_evm" ] |) in + let _ := Constant.str " + Incorporate the state of a successful `child_evm` into the parent `evm`. + + Parameters + ---------- + evm : + The parent `EVM`. + child_evm : + The child evm to incorporate. + " in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "gas_left" |), + M.get_field (| M.get_name (| globals, "child_evm" |), "gas_left" |) + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "logs" |), + M.get_field (| M.get_name (| globals, "child_evm" |), "logs" |) + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "refund_counter" |), + M.get_field (| M.get_name (| globals, "child_evm" |), "refund_counter" |) + |) in + let _ := M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "accounts_to_delete" |), "update" |), + make_list [ + M.get_field (| M.get_name (| globals, "child_evm" |), "accounts_to_delete" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "touched_accounts" |), "update" |), + make_list [ + M.get_field (| M.get_name (| globals, "child_evm" |), "touched_accounts" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, "account_exists_and_is_empty" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "env" |), "state" |); + M.get_field (| M.get_field (| M.get_name (| globals, "child_evm" |), "message" |), "current_target" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "touched_accounts" |), "add" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "child_evm" |), "message" |), "current_target" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + M.pure Constant.None_)). + +Definition incorporate_child_on_error : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm"; "child_evm" ] |) in + let _ := Constant.str " + Incorporate the state of an unsuccessful `child_evm` into the parent `evm`. + + Parameters + ---------- + evm : + The parent `EVM`. + child_evm : + The child evm to incorporate. + " in + let _ := + (* if *) + M.if_then_else (| + Compare.in_ (| + M.get_name (| globals, "RIPEMD160_ADDRESS" |), + M.get_field (| M.get_name (| globals, "child_evm" |), "touched_accounts" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "touched_accounts" |), "add" |), + make_list [ + M.get_name (| globals, "RIPEMD160_ADDRESS" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_field (| M.get_field (| M.get_name (| globals, "child_evm" |), "message" |), "current_target" |), + M.get_name (| globals, "RIPEMD160_ADDRESS" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, "account_exists_and_is_empty" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "env" |), "state" |); + M.get_field (| M.get_field (| M.get_name (| globals, "child_evm" |), "message" |), "current_target" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "touched_accounts" |), "add" |), + make_list [ + M.get_name (| globals, "RIPEMD160_ADDRESS" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "gas_left" |), + M.get_field (| M.get_name (| globals, "child_evm" |), "gas_left" |) + |) in + M.pure Constant.None_)). diff --git a/CoqOfPython/ethereum/spurious_dragon/vm/exceptions.v b/CoqOfPython/ethereum/spurious_dragon/vm/exceptions.v new file mode 100644 index 0000000..5caf2c5 --- /dev/null +++ b/CoqOfPython/ethereum/spurious_dragon/vm/exceptions.v @@ -0,0 +1,121 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.spurious_dragon.vm.exceptions". + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) Exceptions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Exceptions which cause the EVM to halt exceptionally. +". + +Axiom ethereum_exceptions_imports_EthereumException : + IsImported globals "ethereum.exceptions" "EthereumException". + +Definition ExceptionalHalt : Value.t := + builtins.make_klass + [(globals, "EthereumException")] + [ + + ] + [ + + ]. + +Definition StackUnderflowError : Value.t := + builtins.make_klass + [(globals, "ExceptionalHalt")] + [ + + ] + [ + + ]. + +Definition StackOverflowError : Value.t := + builtins.make_klass + [(globals, "ExceptionalHalt")] + [ + + ] + [ + + ]. + +Definition OutOfGasError : Value.t := + builtins.make_klass + [(globals, "ExceptionalHalt")] + [ + + ] + [ + + ]. + +Definition InvalidOpcode : Value.t := + builtins.make_klass + [(globals, "ExceptionalHalt")] + [ + + ] + [ + ( + "__init__", + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "self"; "code" ] |) in + let _ := M.call (| + M.get_field (| M.call (| + M.get_name (| globals, "super" |), + make_list [], + make_dict [] + |), "__init__" |), + make_list [ + M.get_name (| globals, "code" |) + ], + make_dict [] + |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, "self" |), "code" |), + M.get_name (| globals, "code" |) + |) in + M.pure Constant.None_)) + ) + ]. + +Definition InvalidJumpDestError : Value.t := + builtins.make_klass + [(globals, "ExceptionalHalt")] + [ + + ] + [ + + ]. + +Definition StackDepthLimitError : Value.t := + builtins.make_klass + [(globals, "ExceptionalHalt")] + [ + + ] + [ + + ]. + +Definition AddressCollision : Value.t := + builtins.make_klass + [(globals, "ExceptionalHalt")] + [ + + ] + [ + + ]. diff --git a/CoqOfPython/ethereum/spurious_dragon/vm/gas.v b/CoqOfPython/ethereum/spurious_dragon/vm/gas.v new file mode 100644 index 0000000..6f64c28 --- /dev/null +++ b/CoqOfPython/ethereum/spurious_dragon/vm/gas.v @@ -0,0 +1,902 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.spurious_dragon.vm.gas". + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) Gas +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +EVM gas constants and calculators. +". + +Axiom dataclasses_imports_dataclass : + IsImported globals "dataclasses" "dataclass". + +Axiom typing_imports_List : + IsImported globals "typing" "List". +Axiom typing_imports_Tuple : + IsImported globals "typing" "Tuple". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". + +Axiom ethereum_trace_imports_GasAndRefund : + IsImported globals "ethereum.trace" "GasAndRefund". +Axiom ethereum_trace_imports_evm_trace : + IsImported globals "ethereum.trace" "evm_trace". + +Axiom ethereum_utils_numeric_imports_ceil32 : + IsImported globals "ethereum.utils.numeric" "ceil32". + +Axiom ethereum_spurious_dragon_vm_imports_Evm : + IsImported globals "ethereum.spurious_dragon.vm" "Evm". + +Axiom ethereum_spurious_dragon_vm_exceptions_imports_OutOfGasError : + IsImported globals "ethereum.spurious_dragon.vm.exceptions" "OutOfGasError". + +Definition GAS_JUMPDEST : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 1 + ], + make_dict [] + |) +)). + +Definition GAS_BASE : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 2 + ], + make_dict [] + |) +)). + +Definition GAS_VERY_LOW : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 3 + ], + make_dict [] + |) +)). + +Definition GAS_SLOAD : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 200 + ], + make_dict [] + |) +)). + +Definition GAS_STORAGE_SET : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 20000 + ], + make_dict [] + |) +)). + +Definition GAS_STORAGE_UPDATE : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 5000 + ], + make_dict [] + |) +)). + +Definition GAS_STORAGE_CLEAR_REFUND : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 15000 + ], + make_dict [] + |) +)). + +Definition GAS_LOW : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 5 + ], + make_dict [] + |) +)). + +Definition GAS_MID : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 8 + ], + make_dict [] + |) +)). + +Definition GAS_HIGH : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 10 + ], + make_dict [] + |) +)). + +Definition GAS_EXPONENTIATION : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 10 + ], + make_dict [] + |) +)). + +Definition GAS_EXPONENTIATION_PER_BYTE : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 50 + ], + make_dict [] + |) +)). + +Definition GAS_MEMORY : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 3 + ], + make_dict [] + |) +)). + +Definition GAS_KECCAK256 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 30 + ], + make_dict [] + |) +)). + +Definition GAS_KECCAK256_WORD : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 6 + ], + make_dict [] + |) +)). + +Definition GAS_COPY : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 3 + ], + make_dict [] + |) +)). + +Definition GAS_BLOCK_HASH : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 20 + ], + make_dict [] + |) +)). + +Definition GAS_EXTERNAL : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 700 + ], + make_dict [] + |) +)). + +Definition GAS_BALANCE : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 400 + ], + make_dict [] + |) +)). + +Definition GAS_LOG : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 375 + ], + make_dict [] + |) +)). + +Definition GAS_LOG_DATA : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 8 + ], + make_dict [] + |) +)). + +Definition GAS_LOG_TOPIC : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 375 + ], + make_dict [] + |) +)). + +Definition GAS_CREATE : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 32000 + ], + make_dict [] + |) +)). + +Definition GAS_CODE_DEPOSIT : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 200 + ], + make_dict [] + |) +)). + +Definition GAS_ZERO : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) +)). + +Definition GAS_CALL : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 700 + ], + make_dict [] + |) +)). + +Definition GAS_NEW_ACCOUNT : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 25000 + ], + make_dict [] + |) +)). + +Definition GAS_CALL_VALUE : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 9000 + ], + make_dict [] + |) +)). + +Definition GAS_CALL_STIPEND : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 2300 + ], + make_dict [] + |) +)). + +Definition GAS_SELF_DESTRUCT : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 5000 + ], + make_dict [] + |) +)). + +Definition GAS_SELF_DESTRUCT_NEW_ACCOUNT : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 25000 + ], + make_dict [] + |) +)). + +Definition REFUND_SELF_DESTRUCT : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 24000 + ], + make_dict [] + |) +)). + +Definition GAS_ECRECOVER : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 3000 + ], + make_dict [] + |) +)). + +Definition GAS_SHA256 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 60 + ], + make_dict [] + |) +)). + +Definition GAS_SHA256_WORD : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 12 + ], + make_dict [] + |) +)). + +Definition GAS_RIPEMD160 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 600 + ], + make_dict [] + |) +)). + +Definition GAS_RIPEMD160_WORD : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 120 + ], + make_dict [] + |) +)). + +Definition GAS_IDENTITY : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 15 + ], + make_dict [] + |) +)). + +Definition GAS_IDENTITY_WORD : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 3 + ], + make_dict [] + |) +)). + +Definition ExtendMemory : Value.t := + builtins.make_klass + [] + [ + + ] + [ + + ]. + +Definition MessageCallGas : Value.t := + builtins.make_klass + [] + [ + + ] + [ + + ]. + +Definition charge_gas : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm"; "amount" ] |) in + let _ := Constant.str " + Subtracts `amount` from `evm.gas_left`. + + Parameters + ---------- + evm : + The current EVM. + amount : + The amount of gas the current operation requires. + + " in + let _ := M.call (| + M.get_name (| globals, "evm_trace" |), + make_list [ + M.get_name (| globals, "evm" |); + M.call (| + M.get_name (| globals, "GasAndRefund" |), + make_list [ + M.get_name (| globals, "amount" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.lt (| + M.get_field (| M.get_name (| globals, "evm" |), "gas_left" |), + M.get_name (| globals, "amount" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, "OutOfGasError" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_op (| + BinOp.sub, + M.get_field (| M.get_name (| globals, "evm" |), "gas_left" |), + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + M.get_name (| globals, "amount" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_)). + +Definition calculate_memory_gas_cost : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "size_in_bytes" ] |) in + let _ := Constant.str " + Calculates the gas cost for allocating memory + to the smallest multiple of 32 bytes, + such that the allocated size is at least as big as the given size. + + Parameters + ---------- + size_in_bytes : + The size of the data in bytes. + + Returns + ------- + total_gas_cost : `ethereum.base_types.Uint` + The gas cost for storing data in memory. + " in + let _ := M.assign_local (| + "size_in_words" , + BinOp.floor_div (| + M.call (| + M.get_name (| globals, "ceil32" |), + make_list [ + M.get_name (| globals, "size_in_bytes" |) + ], + make_dict [] + |), + Constant.int 32 + |) + |) in + let _ := M.assign_local (| + "linear_cost" , + BinOp.mult (| + M.get_name (| globals, "size_in_words" |), + M.get_name (| globals, "GAS_MEMORY" |) + |) + |) in + let _ := M.assign_local (| + "quadratic_cost" , + BinOp.floor_div (| + BinOp.pow (| + M.get_name (| globals, "size_in_words" |), + Constant.int 2 + |), + Constant.int 512 + |) + |) in + let _ := M.assign_local (| + "total_gas_cost" , + BinOp.add (| + M.get_name (| globals, "linear_cost" |), + M.get_name (| globals, "quadratic_cost" |) + |) + |) in +(* At stmt: unsupported node type: Try *) + M.pure Constant.None_)). + +Definition calculate_gas_extend_memory : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "memory"; "extensions" ] |) in + let _ := Constant.str " + Calculates the gas amount to extend memory + + Parameters + ---------- + memory : + Memory contents of the EVM. + extensions: + List of extensions to be made to the memory. + Consists of a tuple of start position and size. + + Returns + ------- + extend_memory: `ExtendMemory` + " in + let _ := M.assign_local (| + "size_to_extend" , + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "to_be_paid" , + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "current_size" , + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_name (| globals, "memory" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := + M.for_ (| + make_tuple [ M.get_name (| globals, "start_position" |); M.get_name (| globals, "size" |) ], + M.get_name (| globals, "extensions" |), + ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, "size" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.continue (| |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "before_size" , + M.call (| + M.get_name (| globals, "ceil32" |), + make_list [ + M.get_name (| globals, "current_size" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "after_size" , + M.call (| + M.get_name (| globals, "ceil32" |), + make_list [ + BinOp.add (| + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.get_name (| globals, "start_position" |) + ], + make_dict [] + |), + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.get_name (| globals, "size" |) + ], + make_dict [] + |) + |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.lt_e (| + M.get_name (| globals, "after_size" |), + M.get_name (| globals, "before_size" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.continue (| |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_op_local (| + BinOp.add, + "size_to_extend", + BinOp.sub (| + M.get_name (| globals, "after_size" |), + M.get_name (| globals, "before_size" |) + |) + |) in + let _ := M.assign_local (| + "already_paid" , + M.call (| + M.get_name (| globals, "calculate_memory_gas_cost" |), + make_list [ + M.get_name (| globals, "before_size" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "total_cost" , + M.call (| + M.get_name (| globals, "calculate_memory_gas_cost" |), + make_list [ + M.get_name (| globals, "after_size" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_op_local (| + BinOp.add, + "to_be_paid", + BinOp.sub (| + M.get_name (| globals, "total_cost" |), + M.get_name (| globals, "already_paid" |) + |) + |) in + let _ := M.assign_local (| + "current_size" , + M.get_name (| globals, "after_size" |) + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, "ExtendMemory" |), + make_list [ + M.get_name (| globals, "to_be_paid" |); + M.get_name (| globals, "size_to_extend" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Definition calculate_message_call_gas : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "value"; "gas"; "gas_left"; "memory_cost"; "extra_gas"; "call_stipend" ] |) in + let _ := Constant.str " + Calculates the MessageCallGas (cost and stipend) for + executing call Opcodes. + + Parameters + ---------- + value: + The amount of `ETH` that needs to be transferred. + gas : + The amount of gas provided to the message-call. + gas_left : + The amount of gas left in the current frame. + memory_cost : + The amount needed to extend the memory in the current frame. + extra_gas : + The amount of gas needed for transferring value + creating a new + account inside a message call. + call_stipend : + The amount of stipend provided to a message call to execute code while + transferring value(ETH). + + Returns + ------- + message_call_gas: `MessageCallGas` + " in + let _ := M.assign_local (| + "call_stipend" , + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, "value" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( +M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + (* else *) + )), ltac:(M.monadic ( +M.get_name (| globals, "call_stipend" |) + )) |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.lt (| + M.get_name (| globals, "gas_left" |), + BinOp.add (| + M.get_name (| globals, "extra_gas" |), + M.get_name (| globals, "memory_cost" |) + |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + M.call (| + M.get_name (| globals, "MessageCallGas" |), + make_list [ + BinOp.add (| + M.get_name (| globals, "gas" |), + M.get_name (| globals, "extra_gas" |) + |); + BinOp.add (| + M.get_name (| globals, "gas" |), + M.get_name (| globals, "call_stipend" |) + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "gas" , + M.call (| + M.get_name (| globals, "min" |), + make_list [ + M.get_name (| globals, "gas" |); + M.call (| + M.get_name (| globals, "max_message_call_gas" |), + make_list [ + BinOp.sub (| + BinOp.sub (| + M.get_name (| globals, "gas_left" |), + M.get_name (| globals, "memory_cost" |) + |), + M.get_name (| globals, "extra_gas" |) + |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, "MessageCallGas" |), + make_list [ + BinOp.add (| + M.get_name (| globals, "gas" |), + M.get_name (| globals, "extra_gas" |) + |); + BinOp.add (| + M.get_name (| globals, "gas" |), + M.get_name (| globals, "call_stipend" |) + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Definition max_message_call_gas : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "gas" ] |) in + let _ := Constant.str " + Calculates the maximum gas that is allowed for making a message call + + Parameters + ---------- + gas : + The amount of gas provided to the message-call. + + Returns + ------- + max_allowed_message_call_gas: `ethereum.base_types.Uint` + The maximum gas allowed for making the message-call. + " in + let _ := M.return_ (| + BinOp.sub (| + M.get_name (| globals, "gas" |), + BinOp.floor_div (| + M.get_name (| globals, "gas" |), + Constant.int 64 + |) + |) + |) in + M.pure Constant.None_)). diff --git a/CoqOfPython/ethereum/spurious_dragon/vm/instructions/__init__.v b/CoqOfPython/ethereum/spurious_dragon/vm/instructions/__init__.v new file mode 100644 index 0000000..a4fd34b --- /dev/null +++ b/CoqOfPython/ethereum/spurious_dragon/vm/instructions/__init__.v @@ -0,0 +1,74 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.spurious_dragon.vm.instructions.__init__". + +Definition expr_1 : Value.t := + Constant.str " +EVM Instruction Encoding (Opcodes) +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Machine readable representations of EVM instructions, and a mapping to their +implementations. +". + +(* At top_level_stmt: unsupported node type: Import *) + +Axiom typing_imports_Callable : + IsImported globals "typing" "Callable". +Axiom typing_imports_Dict : + IsImported globals "typing" "Dict". + +Axiom ethereum_spurious_dragon_vm_instructions_imports_arithmetic : + IsImported globals "ethereum.spurious_dragon.vm.instructions" "arithmetic". + +Axiom ethereum_spurious_dragon_vm_instructions_imports_bitwise : + IsImported globals "ethereum.spurious_dragon.vm.instructions" "bitwise". + +Axiom ethereum_spurious_dragon_vm_instructions_imports_block : + IsImported globals "ethereum.spurious_dragon.vm.instructions" "block". + +Axiom ethereum_spurious_dragon_vm_instructions_imports_comparison : + IsImported globals "ethereum.spurious_dragon.vm.instructions" "comparison". + +Axiom ethereum_spurious_dragon_vm_instructions_imports_control_flow : + IsImported globals "ethereum.spurious_dragon.vm.instructions" "control_flow". + +Axiom ethereum_spurious_dragon_vm_instructions_imports_environment : + IsImported globals "ethereum.spurious_dragon.vm.instructions" "environment". + +Axiom ethereum_spurious_dragon_vm_instructions_imports_keccak : + IsImported globals "ethereum.spurious_dragon.vm.instructions" "keccak". + +Axiom ethereum_spurious_dragon_vm_instructions_imports_log : + IsImported globals "ethereum.spurious_dragon.vm.instructions" "log". + +Axiom ethereum_spurious_dragon_vm_instructions_imports_memory : + IsImported globals "ethereum.spurious_dragon.vm.instructions" "memory". + +Axiom ethereum_spurious_dragon_vm_instructions_imports_stack : + IsImported globals "ethereum.spurious_dragon.vm.instructions" "stack". + +Axiom ethereum_spurious_dragon_vm_instructions_imports_storage : + IsImported globals "ethereum.spurious_dragon.vm.instructions" "storage". + +Axiom ethereum_spurious_dragon_vm_instructions_imports_system : + IsImported globals "ethereum.spurious_dragon.vm.instructions" "system". + +Definition Ops : Value.t := + builtins.make_klass + [(* At base: unsupported node type: Attribute *)] + [ + + ] + [ + + ]. + +(* At top_level_stmt: unsupported node type: AnnAssign *) diff --git a/CoqOfPython/ethereum/spurious_dragon/vm/instructions/arithmetic.v b/CoqOfPython/ethereum/spurious_dragon/vm/instructions/arithmetic.v new file mode 100644 index 0000000..2256f4d --- /dev/null +++ b/CoqOfPython/ethereum/spurious_dragon/vm/instructions/arithmetic.v @@ -0,0 +1,1220 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.spurious_dragon.vm.instructions.arithmetic". + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) Arithmetic Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM Arithmetic instructions. +". + +Axiom ethereum_base_types_imports_U255_CEIL_VALUE : + IsImported globals "ethereum.base_types" "U255_CEIL_VALUE". +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_U256_CEIL_VALUE : + IsImported globals "ethereum.base_types" "U256_CEIL_VALUE". +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". + +Axiom ethereum_utils_numeric_imports_get_sign : + IsImported globals "ethereum.utils.numeric" "get_sign". + +Axiom ethereum_spurious_dragon_vm_imports_Evm : + IsImported globals "ethereum.spurious_dragon.vm" "Evm". + +Axiom ethereum_spurious_dragon_vm_gas_imports_GAS_EXPONENTIATION : + IsImported globals "ethereum.spurious_dragon.vm.gas" "GAS_EXPONENTIATION". +Axiom ethereum_spurious_dragon_vm_gas_imports_GAS_EXPONENTIATION_PER_BYTE : + IsImported globals "ethereum.spurious_dragon.vm.gas" "GAS_EXPONENTIATION_PER_BYTE". +Axiom ethereum_spurious_dragon_vm_gas_imports_GAS_LOW : + IsImported globals "ethereum.spurious_dragon.vm.gas" "GAS_LOW". +Axiom ethereum_spurious_dragon_vm_gas_imports_GAS_MID : + IsImported globals "ethereum.spurious_dragon.vm.gas" "GAS_MID". +Axiom ethereum_spurious_dragon_vm_gas_imports_GAS_VERY_LOW : + IsImported globals "ethereum.spurious_dragon.vm.gas" "GAS_VERY_LOW". +Axiom ethereum_spurious_dragon_vm_gas_imports_charge_gas : + IsImported globals "ethereum.spurious_dragon.vm.gas" "charge_gas". + +Axiom ethereum_spurious_dragon_vm_stack_imports_pop : + IsImported globals "ethereum.spurious_dragon.vm.stack" "pop". +Axiom ethereum_spurious_dragon_vm_stack_imports_push : + IsImported globals "ethereum.spurious_dragon.vm.stack" "push". + +Definition add : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Adds the top two elements of the stack together, and pushes the result back + on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "x" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "y" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_VERY_LOW" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "result" , + M.call (| + M.get_field (| M.get_name (| globals, "x" |), "wrapping_add" |), + make_list [ + M.get_name (| globals, "y" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.get_name (| globals, "result" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition sub : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Subtracts the top two elements of the stack, and pushes the result back + on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "x" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "y" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_VERY_LOW" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "result" , + M.call (| + M.get_field (| M.get_name (| globals, "x" |), "wrapping_sub" |), + make_list [ + M.get_name (| globals, "y" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.get_name (| globals, "result" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition mul : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Multiply the top two elements of the stack, and pushes the result back + on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "x" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "y" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_LOW" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "result" , + M.call (| + M.get_field (| M.get_name (| globals, "x" |), "wrapping_mul" |), + make_list [ + M.get_name (| globals, "y" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.get_name (| globals, "result" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition div : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Integer division of the top two elements of the stack. Pushes the result + back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "dividend" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "divisor" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_LOW" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, "divisor" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "quotient" , + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "quotient" , + BinOp.floor_div (| + M.get_name (| globals, "dividend" |), + M.get_name (| globals, "divisor" |) + |) + |) in + M.pure Constant.None_ + )) |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.get_name (| globals, "quotient" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition sdiv : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Signed integer division of the top two elements of the stack. Pushes the + result back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "dividend" , + M.call (| + M.get_field (| M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |), "to_signed" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "divisor" , + M.call (| + M.get_field (| M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |), "to_signed" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_LOW" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, "divisor" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "quotient" , + Constant.int 0 + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + BoolOp.and (| + Compare.eq (| + M.get_name (| globals, "dividend" |), + UnOp.sub (| M.get_name (| globals, "U255_CEIL_VALUE" |) |) + |), + ltac:(M.monadic ( + Compare.eq (| + M.get_name (| globals, "divisor" |), + UnOp.sub (| Constant.int 1 |) + |) + )) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "quotient" , + UnOp.sub (| M.get_name (| globals, "U255_CEIL_VALUE" |) |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "sign" , + M.call (| + M.get_name (| globals, "get_sign" |), + make_list [ + BinOp.mult (| + M.get_name (| globals, "dividend" |), + M.get_name (| globals, "divisor" |) + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "quotient" , + BinOp.mult (| + M.get_name (| globals, "sign" |), + BinOp.floor_div (| + M.call (| + M.get_name (| globals, "abs" |), + make_list [ + M.get_name (| globals, "dividend" |) + ], + make_dict [] + |), + M.call (| + M.get_name (| globals, "abs" |), + make_list [ + M.get_name (| globals, "divisor" |) + ], + make_dict [] + |) + |) + |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )) |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.call (| + M.get_field (| M.get_name (| globals, "U256" |), "from_signed" |), + make_list [ + M.get_name (| globals, "quotient" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition mod_ : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Modulo remainder of the top two elements of the stack. Pushes the result + back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "x" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "y" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_LOW" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, "y" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "remainder" , + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "remainder" , + BinOp.mod_ (| + M.get_name (| globals, "x" |), + M.get_name (| globals, "y" |) + |) + |) in + M.pure Constant.None_ + )) |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.get_name (| globals, "remainder" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition smod : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Signed modulo remainder of the top two elements of the stack. Pushes the + result back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "x" , + M.call (| + M.get_field (| M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |), "to_signed" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "y" , + M.call (| + M.get_field (| M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |), "to_signed" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_LOW" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, "y" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "remainder" , + Constant.int 0 + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "remainder" , + BinOp.mult (| + M.call (| + M.get_name (| globals, "get_sign" |), + make_list [ + M.get_name (| globals, "x" |) + ], + make_dict [] + |), + BinOp.mod_ (| + M.call (| + M.get_name (| globals, "abs" |), + make_list [ + M.get_name (| globals, "x" |) + ], + make_dict [] + |), + M.call (| + M.get_name (| globals, "abs" |), + make_list [ + M.get_name (| globals, "y" |) + ], + make_dict [] + |) + |) + |) + |) in + M.pure Constant.None_ + )) |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.call (| + M.get_field (| M.get_name (| globals, "U256" |), "from_signed" |), + make_list [ + M.get_name (| globals, "remainder" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition addmod : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Modulo addition of the top 2 elements with the 3rd element. Pushes the + result back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "x" , + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "y" , + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "z" , + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_MID" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, "z" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "result" , + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "result" , + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + BinOp.mod_ (| + BinOp.add (| + M.get_name (| globals, "x" |), + M.get_name (| globals, "y" |) + |), + M.get_name (| globals, "z" |) + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + )) |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.get_name (| globals, "result" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition mulmod : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Modulo multiplication of the top 2 elements with the 3rd element. Pushes + the result back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "x" , + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "y" , + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "z" , + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_MID" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, "z" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "result" , + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "result" , + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + BinOp.mod_ (| + BinOp.mult (| + M.get_name (| globals, "x" |), + M.get_name (| globals, "y" |) + |), + M.get_name (| globals, "z" |) + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + )) |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.get_name (| globals, "result" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition exp : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Exponential operation of the top 2 elements. Pushes the result back on + the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "base" , + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "exponent" , + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "exponent_bits" , + M.call (| + M.get_field (| M.get_name (| globals, "exponent" |), "bit_length" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "exponent_bytes" , + BinOp.floor_div (| + BinOp.add (| + M.get_name (| globals, "exponent_bits" |), + Constant.int 7 + |), + Constant.int 8 + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + BinOp.add (| + M.get_name (| globals, "GAS_EXPONENTIATION" |), + BinOp.mult (| + M.get_name (| globals, "GAS_EXPONENTIATION_PER_BYTE" |), + M.get_name (| globals, "exponent_bytes" |) + |) + |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "result" , + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + M.call (| + M.get_name (| globals, "pow" |), + make_list [ + M.get_name (| globals, "base" |); + M.get_name (| globals, "exponent" |); + M.get_name (| globals, "U256_CEIL_VALUE" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.get_name (| globals, "result" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition signextend : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Sign extend operation. In other words, extend a signed number which + fits in N bytes to 32 bytes. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "byte_num" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "value" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_LOW" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.gt (| + M.get_name (| globals, "byte_num" |), + Constant.int 31 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "result" , + M.get_name (| globals, "value" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "value_bytes" , + M.call (| + M.get_name (| globals, "bytes" |), + make_list [ + M.call (| + M.get_field (| M.get_name (| globals, "value" |), "to_be_bytes32" |), + make_list [], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "value_bytes" , + M.slice (| + M.get_name (| globals, "value_bytes" |), + BinOp.sub (| + Constant.int 31, + M.call (| + M.get_name (| globals, "int" |), + make_list [ + M.get_name (| globals, "byte_num" |) + ], + make_dict [] + |) + |), + Constant.None_, + Constant.None_ + |) + |) in + let _ := M.assign_local (| + "sign_bit" , + BinOp.r_shift (| + M.get_subscript (| + M.get_name (| globals, "value_bytes" |), + Constant.int 0 + |), + Constant.int 7 + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, "sign_bit" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "result" , + M.call (| + M.get_field (| M.get_name (| globals, "U256" |), "from_be_bytes" |), + make_list [ + M.get_name (| globals, "value_bytes" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "num_bytes_prepend" , + BinOp.sub (| + Constant.int 32, + BinOp.add (| + M.get_name (| globals, "byte_num" |), + Constant.int 1 + |) + |) + |) in + let _ := M.assign_local (| + "result" , + M.call (| + M.get_field (| M.get_name (| globals, "U256" |), "from_be_bytes" |), + make_list [ + BinOp.add (| + M.call (| + M.get_name (| globals, "bytearray" |), + make_list [ + BinOp.mult (| + make_list [ + Constant.int 255 + ], + M.get_name (| globals, "num_bytes_prepend" |) + |) + ], + make_dict [] + |), + M.get_name (| globals, "value_bytes" |) + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )) |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.get_name (| globals, "result" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). diff --git a/CoqOfPython/ethereum/spurious_dragon/vm/instructions/bitwise.v b/CoqOfPython/ethereum/spurious_dragon/vm/instructions/bitwise.v new file mode 100644 index 0000000..fc29c9b --- /dev/null +++ b/CoqOfPython/ethereum/spurious_dragon/vm/instructions/bitwise.v @@ -0,0 +1,372 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.spurious_dragon.vm.instructions.bitwise". + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) Bitwise Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM bitwise instructions. +". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". + +Axiom ethereum_spurious_dragon_vm_imports_Evm : + IsImported globals "ethereum.spurious_dragon.vm" "Evm". + +Axiom ethereum_spurious_dragon_vm_gas_imports_GAS_VERY_LOW : + IsImported globals "ethereum.spurious_dragon.vm.gas" "GAS_VERY_LOW". +Axiom ethereum_spurious_dragon_vm_gas_imports_charge_gas : + IsImported globals "ethereum.spurious_dragon.vm.gas" "charge_gas". + +Axiom ethereum_spurious_dragon_vm_stack_imports_pop : + IsImported globals "ethereum.spurious_dragon.vm.stack" "pop". +Axiom ethereum_spurious_dragon_vm_stack_imports_push : + IsImported globals "ethereum.spurious_dragon.vm.stack" "push". + +Definition bitwise_and : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Bitwise AND operation of the top 2 elements of the stack. Pushes the + result back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "x" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "y" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_VERY_LOW" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + BinOp.bit_and (| + M.get_name (| globals, "x" |), + M.get_name (| globals, "y" |) + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition bitwise_or : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Bitwise OR operation of the top 2 elements of the stack. Pushes the + result back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "x" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "y" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_VERY_LOW" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + BinOp.bit_or (| + M.get_name (| globals, "x" |), + M.get_name (| globals, "y" |) + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition bitwise_xor : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Bitwise XOR operation of the top 2 elements of the stack. Pushes the + result back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "x" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "y" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_VERY_LOW" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + BinOp.bit_xor (| + M.get_name (| globals, "x" |), + M.get_name (| globals, "y" |) + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition bitwise_not : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Bitwise NOT operation of the top element of the stack. Pushes the + result back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "x" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_VERY_LOW" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + UnOp.invert (| M.get_name (| globals, "x" |) |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition get_byte : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + For a word (defined by next top element of the stack), retrieve the + Nth byte (0-indexed and defined by top element of stack) from the + left (most significant) to right (least significant). + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "byte_index" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "word" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_VERY_LOW" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.gt_e (| + M.get_name (| globals, "byte_index" |), + Constant.int 32 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "result" , + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "extra_bytes_to_right" , + BinOp.sub (| + Constant.int 31, + M.get_name (| globals, "byte_index" |) + |) + |) in + let _ := M.assign_local (| + "word" , + BinOp.r_shift (| + M.get_name (| globals, "word" |), + BinOp.mult (| + M.get_name (| globals, "extra_bytes_to_right" |), + Constant.int 8 + |) + |) + |) in + let _ := M.assign_local (| + "word" , + BinOp.bit_and (| + M.get_name (| globals, "word" |), + Constant.int 255 + |) + |) in + let _ := M.assign_local (| + "result" , + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + M.get_name (| globals, "word" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + )) |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.get_name (| globals, "result" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). diff --git a/CoqOfPython/ethereum/spurious_dragon/vm/instructions/block.v b/CoqOfPython/ethereum/spurious_dragon/vm/instructions/block.v new file mode 100644 index 0000000..d8850a8 --- /dev/null +++ b/CoqOfPython/ethereum/spurious_dragon/vm/instructions/block.v @@ -0,0 +1,348 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.spurious_dragon.vm.instructions.block". + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) Block Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM block instructions. +". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". + +Axiom ethereum_spurious_dragon_vm_imports_Evm : + IsImported globals "ethereum.spurious_dragon.vm" "Evm". + +Axiom ethereum_spurious_dragon_vm_gas_imports_GAS_BASE : + IsImported globals "ethereum.spurious_dragon.vm.gas" "GAS_BASE". +Axiom ethereum_spurious_dragon_vm_gas_imports_GAS_BLOCK_HASH : + IsImported globals "ethereum.spurious_dragon.vm.gas" "GAS_BLOCK_HASH". +Axiom ethereum_spurious_dragon_vm_gas_imports_charge_gas : + IsImported globals "ethereum.spurious_dragon.vm.gas" "charge_gas". + +Axiom ethereum_spurious_dragon_vm_stack_imports_pop : + IsImported globals "ethereum.spurious_dragon.vm.stack" "pop". +Axiom ethereum_spurious_dragon_vm_stack_imports_push : + IsImported globals "ethereum.spurious_dragon.vm.stack" "push". + +Definition block_hash : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Push the hash of one of the 256 most recent complete blocks onto the + stack. The block number to hash is present at the top of the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "block_number" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_BLOCK_HASH" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + BoolOp.or (| + Compare.lt_e (| + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "env" |), "number" |), + M.get_name (| globals, "block_number" |) + |), + ltac:(M.monadic ( + Compare.gt (| + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "env" |), "number" |), + BinOp.add (| + M.get_name (| globals, "block_number" |), + Constant.int 256 + |) + |) + )) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "hash" , + Constant.bytes "00" + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "hash" , + M.get_subscript (| + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "env" |), "block_hashes" |), + UnOp.sub (| BinOp.sub (| + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "env" |), "number" |), + M.get_name (| globals, "block_number" |) + |) |) + |) + |) in + M.pure Constant.None_ + )) |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.call (| + M.get_field (| M.get_name (| globals, "U256" |), "from_be_bytes" |), + make_list [ + M.get_name (| globals, "hash" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition coinbase : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Push the current block's beneficiary address (address of the block miner) + onto the stack. + + Here the current block refers to the block in which the currently + executing transaction/call resides. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_BASE" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.call (| + M.get_field (| M.get_name (| globals, "U256" |), "from_be_bytes" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "env" |), "coinbase" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition timestamp : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Push the current block's timestamp onto the stack. Here the timestamp + being referred is actually the unix timestamp in seconds. + + Here the current block refers to the block in which the currently + executing transaction/call resides. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_BASE" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "env" |), "time" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition number : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Push the current block's number onto the stack. + + Here the current block refers to the block in which the currently + executing transaction/call resides. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_BASE" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "env" |), "number" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition difficulty : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Push the current block's difficulty onto the stack. + + Here the current block refers to the block in which the currently + executing transaction/call resides. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_BASE" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "env" |), "difficulty" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition gas_limit : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Push the current block's gas limit onto the stack. + + Here the current block refers to the block in which the currently + executing transaction/call resides. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_BASE" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "env" |), "gas_limit" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). diff --git a/CoqOfPython/ethereum/spurious_dragon/vm/instructions/comparison.v b/CoqOfPython/ethereum/spurious_dragon/vm/instructions/comparison.v new file mode 100644 index 0000000..e7f431c --- /dev/null +++ b/CoqOfPython/ethereum/spurious_dragon/vm/instructions/comparison.v @@ -0,0 +1,452 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.spurious_dragon.vm.instructions.comparison". + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) Comparison Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM Comparison instructions. +". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". + +Axiom ethereum_spurious_dragon_vm_imports_Evm : + IsImported globals "ethereum.spurious_dragon.vm" "Evm". + +Axiom ethereum_spurious_dragon_vm_gas_imports_GAS_VERY_LOW : + IsImported globals "ethereum.spurious_dragon.vm.gas" "GAS_VERY_LOW". +Axiom ethereum_spurious_dragon_vm_gas_imports_charge_gas : + IsImported globals "ethereum.spurious_dragon.vm.gas" "charge_gas". + +Axiom ethereum_spurious_dragon_vm_stack_imports_pop : + IsImported globals "ethereum.spurious_dragon.vm.stack" "pop". +Axiom ethereum_spurious_dragon_vm_stack_imports_push : + IsImported globals "ethereum.spurious_dragon.vm.stack" "push". + +Definition less_than : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Checks if the top element is less than the next top element. Pushes the + result back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "left" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "right" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_VERY_LOW" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "result" , + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Compare.lt (| + M.get_name (| globals, "left" |), + M.get_name (| globals, "right" |) + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.get_name (| globals, "result" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition signed_less_than : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Signed less-than comparison. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "left" , + M.call (| + M.get_field (| M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |), "to_signed" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "right" , + M.call (| + M.get_field (| M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |), "to_signed" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_VERY_LOW" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "result" , + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Compare.lt (| + M.get_name (| globals, "left" |), + M.get_name (| globals, "right" |) + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.get_name (| globals, "result" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition greater_than : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Checks if the top element is greater than the next top element. Pushes + the result back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "left" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "right" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_VERY_LOW" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "result" , + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Compare.gt (| + M.get_name (| globals, "left" |), + M.get_name (| globals, "right" |) + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.get_name (| globals, "result" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition signed_greater_than : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Signed greater-than comparison. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "left" , + M.call (| + M.get_field (| M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |), "to_signed" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "right" , + M.call (| + M.get_field (| M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |), "to_signed" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_VERY_LOW" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "result" , + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Compare.gt (| + M.get_name (| globals, "left" |), + M.get_name (| globals, "right" |) + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.get_name (| globals, "result" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition equal : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Checks if the top element is equal to the next top element. Pushes + the result back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "left" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "right" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_VERY_LOW" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "result" , + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Compare.eq (| + M.get_name (| globals, "left" |), + M.get_name (| globals, "right" |) + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.get_name (| globals, "result" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition is_zero : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Checks if the top element is equal to 0. Pushes the result back on the + stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "x" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_VERY_LOW" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "result" , + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Compare.eq (| + M.get_name (| globals, "x" |), + Constant.int 0 + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.get_name (| globals, "result" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). diff --git a/CoqOfPython/ethereum/spurious_dragon/vm/instructions/control_flow.v b/CoqOfPython/ethereum/spurious_dragon/vm/instructions/control_flow.v new file mode 100644 index 0000000..f96d87f --- /dev/null +++ b/CoqOfPython/ethereum/spurious_dragon/vm/instructions/control_flow.v @@ -0,0 +1,350 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.spurious_dragon.vm.instructions.control_flow". + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) Control Flow Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM control flow instructions. +". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". + +Axiom ethereum_spurious_dragon_vm_gas_imports_GAS_BASE : + IsImported globals "ethereum.spurious_dragon.vm.gas" "GAS_BASE". +Axiom ethereum_spurious_dragon_vm_gas_imports_GAS_HIGH : + IsImported globals "ethereum.spurious_dragon.vm.gas" "GAS_HIGH". +Axiom ethereum_spurious_dragon_vm_gas_imports_GAS_JUMPDEST : + IsImported globals "ethereum.spurious_dragon.vm.gas" "GAS_JUMPDEST". +Axiom ethereum_spurious_dragon_vm_gas_imports_GAS_MID : + IsImported globals "ethereum.spurious_dragon.vm.gas" "GAS_MID". +Axiom ethereum_spurious_dragon_vm_gas_imports_charge_gas : + IsImported globals "ethereum.spurious_dragon.vm.gas" "charge_gas". + +Axiom ethereum_spurious_dragon_vm_imports_Evm : + IsImported globals "ethereum.spurious_dragon.vm" "Evm". + +Axiom ethereum_spurious_dragon_vm_exceptions_imports_InvalidJumpDestError : + IsImported globals "ethereum.spurious_dragon.vm.exceptions" "InvalidJumpDestError". + +Axiom ethereum_spurious_dragon_vm_stack_imports_pop : + IsImported globals "ethereum.spurious_dragon.vm.stack" "pop". +Axiom ethereum_spurious_dragon_vm_stack_imports_push : + IsImported globals "ethereum.spurious_dragon.vm.stack" "push". + +Definition stop : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Stop further execution of EVM code. + + Parameters + ---------- + evm : + The current EVM frame. + " in + let _ := M.pass (| |) in + let _ := M.pass (| |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, "evm" |), "running" |), + Constant.bool false + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition jump : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Alter the program counter to the location specified by the top of the + stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "jump_dest" , + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_MID" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.not_in (| + M.get_name (| globals, "jump_dest" |), + M.get_field (| M.get_name (| globals, "evm" |), "valid_jump_destinations" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, "InvalidJumpDestError" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.get_name (| globals, "jump_dest" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Definition jumpi : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Alter the program counter to the specified location if and only if a + condition is true. If the condition is not true, then the program counter + would increase only by 1. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "jump_dest" , + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "conditional_value" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_HIGH" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, "conditional_value" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "destination" , + BinOp.add (| + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + Compare.not_in (| + M.get_name (| globals, "jump_dest" |), + M.get_field (| M.get_name (| globals, "evm" |), "valid_jump_destinations" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, "InvalidJumpDestError" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "destination" , + M.get_name (| globals, "jump_dest" |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )) |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.get_name (| globals, "destination" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Definition pc : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Push onto the stack the value of the program counter after reaching the + current instruction and without increasing it for the next instruction. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_BASE" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "pc" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition gas_left : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Push the amount of available gas (including the corresponding reduction + for the cost of this instruction) onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_BASE" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "gas_left" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition jumpdest : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Mark a valid destination for jumps. This is a noop, present only + to be used by `JUMP` and `JUMPI` opcodes to verify that their jump is + valid. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_JUMPDEST" |) + ], + make_dict [] + |) in + let _ := M.pass (| |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). diff --git a/CoqOfPython/ethereum/spurious_dragon/vm/instructions/environment.v b/CoqOfPython/ethereum/spurious_dragon/vm/instructions/environment.v new file mode 100644 index 0000000..00c40fe --- /dev/null +++ b/CoqOfPython/ethereum/spurious_dragon/vm/instructions/environment.v @@ -0,0 +1,993 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.spurious_dragon.vm.instructions.environment". + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) Environmental Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM environment related instructions. +". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". + +Axiom ethereum_utils_numeric_imports_ceil32 : + IsImported globals "ethereum.utils.numeric" "ceil32". + +Axiom ethereum_spurious_dragon_state_imports_get_account : + IsImported globals "ethereum.spurious_dragon.state" "get_account". + +Axiom ethereum_spurious_dragon_utils_address_imports_to_address : + IsImported globals "ethereum.spurious_dragon.utils.address" "to_address". + +Axiom ethereum_spurious_dragon_vm_memory_imports_buffer_read : + IsImported globals "ethereum.spurious_dragon.vm.memory" "buffer_read". +Axiom ethereum_spurious_dragon_vm_memory_imports_memory_write : + IsImported globals "ethereum.spurious_dragon.vm.memory" "memory_write". + +Axiom ethereum_spurious_dragon_vm_imports_Evm : + IsImported globals "ethereum.spurious_dragon.vm" "Evm". + +Axiom ethereum_spurious_dragon_vm_gas_imports_GAS_BALANCE : + IsImported globals "ethereum.spurious_dragon.vm.gas" "GAS_BALANCE". +Axiom ethereum_spurious_dragon_vm_gas_imports_GAS_BASE : + IsImported globals "ethereum.spurious_dragon.vm.gas" "GAS_BASE". +Axiom ethereum_spurious_dragon_vm_gas_imports_GAS_COPY : + IsImported globals "ethereum.spurious_dragon.vm.gas" "GAS_COPY". +Axiom ethereum_spurious_dragon_vm_gas_imports_GAS_EXTERNAL : + IsImported globals "ethereum.spurious_dragon.vm.gas" "GAS_EXTERNAL". +Axiom ethereum_spurious_dragon_vm_gas_imports_GAS_VERY_LOW : + IsImported globals "ethereum.spurious_dragon.vm.gas" "GAS_VERY_LOW". +Axiom ethereum_spurious_dragon_vm_gas_imports_calculate_gas_extend_memory : + IsImported globals "ethereum.spurious_dragon.vm.gas" "calculate_gas_extend_memory". +Axiom ethereum_spurious_dragon_vm_gas_imports_charge_gas : + IsImported globals "ethereum.spurious_dragon.vm.gas" "charge_gas". + +Axiom ethereum_spurious_dragon_vm_stack_imports_pop : + IsImported globals "ethereum.spurious_dragon.vm.stack" "pop". +Axiom ethereum_spurious_dragon_vm_stack_imports_push : + IsImported globals "ethereum.spurious_dragon.vm.stack" "push". + +Definition address : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Pushes the address of the current executing account to the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_BASE" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.call (| + M.get_field (| M.get_name (| globals, "U256" |), "from_be_bytes" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "current_target" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition balance : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Pushes the balance of the given account onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "address" , + M.call (| + M.get_name (| globals, "to_address" |), + make_list [ + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_BALANCE" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "balance" , + M.get_field (| M.call (| + M.get_name (| globals, "get_account" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "env" |), "state" |); + M.get_name (| globals, "address" |) + ], + make_dict [] + |), "balance" |) + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.get_name (| globals, "balance" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition origin : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Pushes the address of the original transaction sender to the stack. + The origin address can only be an EOA. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_BASE" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.call (| + M.get_field (| M.get_name (| globals, "U256" |), "from_be_bytes" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "env" |), "origin" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition caller : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Pushes the address of the caller onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_BASE" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.call (| + M.get_field (| M.get_name (| globals, "U256" |), "from_be_bytes" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "caller" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition callvalue : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Push the value (in wei) sent with the call onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_BASE" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "value" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition calldataload : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Push a word (32 bytes) of the input data belonging to the current + environment onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "start_index" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_VERY_LOW" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "value" , + M.call (| + M.get_name (| globals, "buffer_read" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "data" |); + M.get_name (| globals, "start_index" |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 32 + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.call (| + M.get_field (| M.get_name (| globals, "U256" |), "from_be_bytes" |), + make_list [ + M.get_name (| globals, "value" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition calldatasize : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Push the size of input data in current environment onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_BASE" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "data" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition calldatacopy : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Copy a portion of the input data in current environment to memory. + + This will also expand the memory, in case that the memory is insufficient + to store the data. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "memory_start_index" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "data_start_index" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "size" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "words" , + BinOp.floor_div (| + M.call (| + M.get_name (| globals, "ceil32" |), + make_list [ + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.get_name (| globals, "size" |) + ], + make_dict [] + |) + ], + make_dict [] + |), + Constant.int 32 + |) + |) in + let _ := M.assign_local (| + "copy_gas_cost" , + BinOp.mult (| + M.get_name (| globals, "GAS_COPY" |), + M.get_name (| globals, "words" |) + |) + |) in + let _ := M.assign_local (| + "extend_memory" , + M.call (| + M.get_name (| globals, "calculate_gas_extend_memory" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "memory" |); + make_list [ + make_tuple [ M.get_name (| globals, "memory_start_index" |); M.get_name (| globals, "size" |) ] + ] + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + BinOp.add (| + BinOp.add (| + M.get_name (| globals, "GAS_VERY_LOW" |), + M.get_name (| globals, "copy_gas_cost" |) + |), + M.get_field (| M.get_name (| globals, "extend_memory" |), "cost" |) + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "memory" |), + BinOp.mult (| + Constant.bytes "00", + M.get_field (| M.get_name (| globals, "extend_memory" |), "expand_by" |) + |) + |) in + let _ := M.assign_local (| + "value" , + M.call (| + M.get_name (| globals, "buffer_read" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "data" |); + M.get_name (| globals, "data_start_index" |); + M.get_name (| globals, "size" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "memory_write" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "memory" |); + M.get_name (| globals, "memory_start_index" |); + M.get_name (| globals, "value" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition codesize : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Push the size of code running in current environment onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_BASE" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "code" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition codecopy : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Copy a portion of the code in current environment to memory. + + This will also expand the memory, in case that the memory is insufficient + to store the data. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "memory_start_index" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "code_start_index" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "size" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "words" , + BinOp.floor_div (| + M.call (| + M.get_name (| globals, "ceil32" |), + make_list [ + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.get_name (| globals, "size" |) + ], + make_dict [] + |) + ], + make_dict [] + |), + Constant.int 32 + |) + |) in + let _ := M.assign_local (| + "copy_gas_cost" , + BinOp.mult (| + M.get_name (| globals, "GAS_COPY" |), + M.get_name (| globals, "words" |) + |) + |) in + let _ := M.assign_local (| + "extend_memory" , + M.call (| + M.get_name (| globals, "calculate_gas_extend_memory" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "memory" |); + make_list [ + make_tuple [ M.get_name (| globals, "memory_start_index" |); M.get_name (| globals, "size" |) ] + ] + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + BinOp.add (| + BinOp.add (| + M.get_name (| globals, "GAS_VERY_LOW" |), + M.get_name (| globals, "copy_gas_cost" |) + |), + M.get_field (| M.get_name (| globals, "extend_memory" |), "cost" |) + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "memory" |), + BinOp.mult (| + Constant.bytes "00", + M.get_field (| M.get_name (| globals, "extend_memory" |), "expand_by" |) + |) + |) in + let _ := M.assign_local (| + "value" , + M.call (| + M.get_name (| globals, "buffer_read" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "code" |); + M.get_name (| globals, "code_start_index" |); + M.get_name (| globals, "size" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "memory_write" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "memory" |); + M.get_name (| globals, "memory_start_index" |); + M.get_name (| globals, "value" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition gasprice : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Push the gas price used in current environment onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_BASE" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "env" |), "gas_price" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition extcodesize : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Push the code size of a given account onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "address" , + M.call (| + M.get_name (| globals, "to_address" |), + make_list [ + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_EXTERNAL" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "codesize" , + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_field (| M.call (| + M.get_name (| globals, "get_account" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "env" |), "state" |); + M.get_name (| globals, "address" |) + ], + make_dict [] + |), "code" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.get_name (| globals, "codesize" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition extcodecopy : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Copy a portion of an account's code to memory. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "address" , + M.call (| + M.get_name (| globals, "to_address" |), + make_list [ + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_start_index" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "code_start_index" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "size" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "words" , + BinOp.floor_div (| + M.call (| + M.get_name (| globals, "ceil32" |), + make_list [ + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.get_name (| globals, "size" |) + ], + make_dict [] + |) + ], + make_dict [] + |), + Constant.int 32 + |) + |) in + let _ := M.assign_local (| + "copy_gas_cost" , + BinOp.mult (| + M.get_name (| globals, "GAS_COPY" |), + M.get_name (| globals, "words" |) + |) + |) in + let _ := M.assign_local (| + "extend_memory" , + M.call (| + M.get_name (| globals, "calculate_gas_extend_memory" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "memory" |); + make_list [ + make_tuple [ M.get_name (| globals, "memory_start_index" |); M.get_name (| globals, "size" |) ] + ] + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + BinOp.add (| + BinOp.add (| + M.get_name (| globals, "GAS_EXTERNAL" |), + M.get_name (| globals, "copy_gas_cost" |) + |), + M.get_field (| M.get_name (| globals, "extend_memory" |), "cost" |) + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "memory" |), + BinOp.mult (| + Constant.bytes "00", + M.get_field (| M.get_name (| globals, "extend_memory" |), "expand_by" |) + |) + |) in + let _ := M.assign_local (| + "code" , + M.get_field (| M.call (| + M.get_name (| globals, "get_account" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "env" |), "state" |); + M.get_name (| globals, "address" |) + ], + make_dict [] + |), "code" |) + |) in + let _ := M.assign_local (| + "value" , + M.call (| + M.get_name (| globals, "buffer_read" |), + make_list [ + M.get_name (| globals, "code" |); + M.get_name (| globals, "code_start_index" |); + M.get_name (| globals, "size" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "memory_write" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "memory" |); + M.get_name (| globals, "memory_start_index" |); + M.get_name (| globals, "value" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). diff --git a/CoqOfPython/ethereum/spurious_dragon/vm/instructions/keccak.v b/CoqOfPython/ethereum/spurious_dragon/vm/instructions/keccak.v new file mode 100644 index 0000000..b4aecb5 --- /dev/null +++ b/CoqOfPython/ethereum/spurious_dragon/vm/instructions/keccak.v @@ -0,0 +1,188 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.spurious_dragon.vm.instructions.keccak". + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) Keccak Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM keccak instructions. +". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". + +Axiom ethereum_crypto_hash_imports_keccak256 : + IsImported globals "ethereum.crypto.hash" "keccak256". + +Axiom ethereum_utils_numeric_imports_ceil32 : + IsImported globals "ethereum.utils.numeric" "ceil32". + +Axiom ethereum_spurious_dragon_vm_imports_Evm : + IsImported globals "ethereum.spurious_dragon.vm" "Evm". + +Axiom ethereum_spurious_dragon_vm_gas_imports_GAS_KECCAK256 : + IsImported globals "ethereum.spurious_dragon.vm.gas" "GAS_KECCAK256". +Axiom ethereum_spurious_dragon_vm_gas_imports_GAS_KECCAK256_WORD : + IsImported globals "ethereum.spurious_dragon.vm.gas" "GAS_KECCAK256_WORD". +Axiom ethereum_spurious_dragon_vm_gas_imports_calculate_gas_extend_memory : + IsImported globals "ethereum.spurious_dragon.vm.gas" "calculate_gas_extend_memory". +Axiom ethereum_spurious_dragon_vm_gas_imports_charge_gas : + IsImported globals "ethereum.spurious_dragon.vm.gas" "charge_gas". + +Axiom ethereum_spurious_dragon_vm_memory_imports_memory_read_bytes : + IsImported globals "ethereum.spurious_dragon.vm.memory" "memory_read_bytes". + +Axiom ethereum_spurious_dragon_vm_stack_imports_pop : + IsImported globals "ethereum.spurious_dragon.vm.stack" "pop". +Axiom ethereum_spurious_dragon_vm_stack_imports_push : + IsImported globals "ethereum.spurious_dragon.vm.stack" "push". + +Definition keccak : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Pushes to the stack the Keccak-256 hash of a region of memory. + + This also expands the memory, in case the memory is insufficient to + access the data's memory location. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "memory_start_index" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "size" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "words" , + BinOp.floor_div (| + M.call (| + M.get_name (| globals, "ceil32" |), + make_list [ + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.get_name (| globals, "size" |) + ], + make_dict [] + |) + ], + make_dict [] + |), + Constant.int 32 + |) + |) in + let _ := M.assign_local (| + "word_gas_cost" , + BinOp.mult (| + M.get_name (| globals, "GAS_KECCAK256_WORD" |), + M.get_name (| globals, "words" |) + |) + |) in + let _ := M.assign_local (| + "extend_memory" , + M.call (| + M.get_name (| globals, "calculate_gas_extend_memory" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "memory" |); + make_list [ + make_tuple [ M.get_name (| globals, "memory_start_index" |); M.get_name (| globals, "size" |) ] + ] + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + BinOp.add (| + BinOp.add (| + M.get_name (| globals, "GAS_KECCAK256" |), + M.get_name (| globals, "word_gas_cost" |) + |), + M.get_field (| M.get_name (| globals, "extend_memory" |), "cost" |) + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "memory" |), + BinOp.mult (| + Constant.bytes "00", + M.get_field (| M.get_name (| globals, "extend_memory" |), "expand_by" |) + |) + |) in + let _ := M.assign_local (| + "data" , + M.call (| + M.get_name (| globals, "memory_read_bytes" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "memory" |); + M.get_name (| globals, "memory_start_index" |); + M.get_name (| globals, "size" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "hash" , + M.call (| + M.get_name (| globals, "keccak256" |), + make_list [ + M.get_name (| globals, "data" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.call (| + M.get_field (| M.get_name (| globals, "U256" |), "from_be_bytes" |), + make_list [ + M.get_name (| globals, "hash" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). diff --git a/CoqOfPython/ethereum/spurious_dragon/vm/instructions/log.v b/CoqOfPython/ethereum/spurious_dragon/vm/instructions/log.v new file mode 100644 index 0000000..db24bd8 --- /dev/null +++ b/CoqOfPython/ethereum/spurious_dragon/vm/instructions/log.v @@ -0,0 +1,242 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.spurious_dragon.vm.instructions.log". + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) Logging Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM logging instructions. +". + +Axiom functools_imports_partial : + IsImported globals "functools" "partial". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". + +Axiom ethereum_spurious_dragon_blocks_imports_Log : + IsImported globals "ethereum.spurious_dragon.blocks" "Log". + +Axiom ethereum_spurious_dragon_vm_imports_Evm : + IsImported globals "ethereum.spurious_dragon.vm" "Evm". + +Axiom ethereum_spurious_dragon_vm_gas_imports_GAS_LOG : + IsImported globals "ethereum.spurious_dragon.vm.gas" "GAS_LOG". +Axiom ethereum_spurious_dragon_vm_gas_imports_GAS_LOG_DATA : + IsImported globals "ethereum.spurious_dragon.vm.gas" "GAS_LOG_DATA". +Axiom ethereum_spurious_dragon_vm_gas_imports_GAS_LOG_TOPIC : + IsImported globals "ethereum.spurious_dragon.vm.gas" "GAS_LOG_TOPIC". +Axiom ethereum_spurious_dragon_vm_gas_imports_calculate_gas_extend_memory : + IsImported globals "ethereum.spurious_dragon.vm.gas" "calculate_gas_extend_memory". +Axiom ethereum_spurious_dragon_vm_gas_imports_charge_gas : + IsImported globals "ethereum.spurious_dragon.vm.gas" "charge_gas". + +Axiom ethereum_spurious_dragon_vm_memory_imports_memory_read_bytes : + IsImported globals "ethereum.spurious_dragon.vm.memory" "memory_read_bytes". + +Axiom ethereum_spurious_dragon_vm_stack_imports_pop : + IsImported globals "ethereum.spurious_dragon.vm.stack" "pop". + +Definition log_n : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm"; "num_topics" ] |) in + let _ := Constant.str " + Appends a log entry, having `num_topics` topics, to the evm logs. + + This will also expand the memory if the data (required by the log entry) + corresponding to the memory is not accessible. + + Parameters + ---------- + evm : + The current EVM frame. + num_topics : + The number of topics to be included in the log entry. + + " in + let _ := M.assign_local (| + "memory_start_index" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "size" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "topics" , + make_list [] + |) in + let _ := + M.for_ (| + M.get_name (| globals, "_" |), + M.call (| + M.get_name (| globals, "range" |), + make_list [ + M.get_name (| globals, "num_topics" |) + ], + make_dict [] + |), + ltac:(M.monadic ( + let _ := M.assign_local (| + "topic" , + M.call (| + M.get_field (| M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |), "to_be_bytes32" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_field (| M.get_name (| globals, "topics" |), "append" |), + make_list [ + M.get_name (| globals, "topic" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := M.assign_local (| + "extend_memory" , + M.call (| + M.get_name (| globals, "calculate_gas_extend_memory" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "memory" |); + make_list [ + make_tuple [ M.get_name (| globals, "memory_start_index" |); M.get_name (| globals, "size" |) ] + ] + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + BinOp.add (| + BinOp.add (| + BinOp.add (| + M.get_name (| globals, "GAS_LOG" |), + BinOp.mult (| + M.get_name (| globals, "GAS_LOG_DATA" |), + M.get_name (| globals, "size" |) + |) + |), + BinOp.mult (| + M.get_name (| globals, "GAS_LOG_TOPIC" |), + M.get_name (| globals, "num_topics" |) + |) + |), + M.get_field (| M.get_name (| globals, "extend_memory" |), "cost" |) + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "memory" |), + BinOp.mult (| + Constant.bytes "00", + M.get_field (| M.get_name (| globals, "extend_memory" |), "expand_by" |) + |) + |) in + let _ := M.assign_local (| + "log_entry" , + M.call (| + M.get_name (| globals, "Log" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, "evm" |), "logs" |), + BinOp.add (| + M.get_field (| M.get_name (| globals, "evm" |), "logs" |), + make_tuple [ M.get_name (| globals, "log_entry" |) ] + |) + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition log0 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "log_n" |) + ], + make_dict [] + |) +)). + +Definition log1 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "log_n" |) + ], + make_dict [] + |) +)). + +Definition log2 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "log_n" |) + ], + make_dict [] + |) +)). + +Definition log3 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "log_n" |) + ], + make_dict [] + |) +)). + +Definition log4 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "log_n" |) + ], + make_dict [] + |) +)). diff --git a/CoqOfPython/ethereum/spurious_dragon/vm/instructions/memory.v b/CoqOfPython/ethereum/spurious_dragon/vm/instructions/memory.v new file mode 100644 index 0000000..a320784 --- /dev/null +++ b/CoqOfPython/ethereum/spurious_dragon/vm/instructions/memory.v @@ -0,0 +1,393 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.spurious_dragon.vm.instructions.memory". + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) Memory Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM Memory instructions. +". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_Bytes : + IsImported globals "ethereum.base_types" "Bytes". + +Axiom ethereum_spurious_dragon_vm_imports_Evm : + IsImported globals "ethereum.spurious_dragon.vm" "Evm". + +Axiom ethereum_spurious_dragon_vm_gas_imports_GAS_BASE : + IsImported globals "ethereum.spurious_dragon.vm.gas" "GAS_BASE". +Axiom ethereum_spurious_dragon_vm_gas_imports_GAS_VERY_LOW : + IsImported globals "ethereum.spurious_dragon.vm.gas" "GAS_VERY_LOW". +Axiom ethereum_spurious_dragon_vm_gas_imports_calculate_gas_extend_memory : + IsImported globals "ethereum.spurious_dragon.vm.gas" "calculate_gas_extend_memory". +Axiom ethereum_spurious_dragon_vm_gas_imports_charge_gas : + IsImported globals "ethereum.spurious_dragon.vm.gas" "charge_gas". + +Axiom ethereum_spurious_dragon_vm_memory_imports_memory_read_bytes : + IsImported globals "ethereum.spurious_dragon.vm.memory" "memory_read_bytes". +Axiom ethereum_spurious_dragon_vm_memory_imports_memory_write : + IsImported globals "ethereum.spurious_dragon.vm.memory" "memory_write". + +Axiom ethereum_spurious_dragon_vm_stack_imports_pop : + IsImported globals "ethereum.spurious_dragon.vm.stack" "pop". +Axiom ethereum_spurious_dragon_vm_stack_imports_push : + IsImported globals "ethereum.spurious_dragon.vm.stack" "push". + +Definition mstore : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Stores a word to memory. + This also expands the memory, if the memory is + insufficient to store the word. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "start_position" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "value" , + M.call (| + M.get_field (| M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |), "to_be_bytes32" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "extend_memory" , + M.call (| + M.get_name (| globals, "calculate_gas_extend_memory" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "memory" |); + make_list [ + make_tuple [ M.get_name (| globals, "start_position" |); M.call (| + M.get_name (| globals, "U256" |), + make_list [ + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_name (| globals, "value" |) + ], + make_dict [] + |) + ], + make_dict [] + |) ] + ] + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + BinOp.add (| + M.get_name (| globals, "GAS_VERY_LOW" |), + M.get_field (| M.get_name (| globals, "extend_memory" |), "cost" |) + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "memory" |), + BinOp.mult (| + Constant.bytes "00", + M.get_field (| M.get_name (| globals, "extend_memory" |), "expand_by" |) + |) + |) in + let _ := M.call (| + M.get_name (| globals, "memory_write" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "memory" |); + M.get_name (| globals, "start_position" |); + M.get_name (| globals, "value" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition mstore8 : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Stores a byte to memory. + This also expands the memory, if the memory is + insufficient to store the word. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "start_position" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "value" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "extend_memory" , + M.call (| + M.get_name (| globals, "calculate_gas_extend_memory" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "memory" |); + make_list [ + make_tuple [ M.get_name (| globals, "start_position" |); M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 1 + ], + make_dict [] + |) ] + ] + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + BinOp.add (| + M.get_name (| globals, "GAS_VERY_LOW" |), + M.get_field (| M.get_name (| globals, "extend_memory" |), "cost" |) + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "memory" |), + BinOp.mult (| + Constant.bytes "00", + M.get_field (| M.get_name (| globals, "extend_memory" |), "expand_by" |) + |) + |) in + let _ := M.assign_local (| + "normalized_bytes_value" , + M.call (| + M.get_name (| globals, "Bytes" |), + make_list [ + make_list [ + BinOp.bit_and (| + M.get_name (| globals, "value" |), + Constant.int 255 + |) + ] + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "memory_write" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "memory" |); + M.get_name (| globals, "start_position" |); + M.get_name (| globals, "normalized_bytes_value" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition mload : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Load word from memory. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "start_position" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "extend_memory" , + M.call (| + M.get_name (| globals, "calculate_gas_extend_memory" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "memory" |); + make_list [ + make_tuple [ M.get_name (| globals, "start_position" |); M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 32 + ], + make_dict [] + |) ] + ] + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + BinOp.add (| + M.get_name (| globals, "GAS_VERY_LOW" |), + M.get_field (| M.get_name (| globals, "extend_memory" |), "cost" |) + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "memory" |), + BinOp.mult (| + Constant.bytes "00", + M.get_field (| M.get_name (| globals, "extend_memory" |), "expand_by" |) + |) + |) in + let _ := M.assign_local (| + "value" , + M.call (| + M.get_field (| M.get_name (| globals, "U256" |), "from_be_bytes" |), + make_list [ + M.call (| + M.get_name (| globals, "memory_read_bytes" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "memory" |); + M.get_name (| globals, "start_position" |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 32 + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.get_name (| globals, "value" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition msize : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Push the size of active memory in bytes onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_BASE" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "memory" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). diff --git a/CoqOfPython/ethereum/spurious_dragon/vm/instructions/stack.v b/CoqOfPython/ethereum/spurious_dragon/vm/instructions/stack.v new file mode 100644 index 0000000..4846fa5 --- /dev/null +++ b/CoqOfPython/ethereum/spurious_dragon/vm/instructions/stack.v @@ -0,0 +1,947 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.spurious_dragon.vm.instructions.stack". + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) Stack Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM stack related instructions. +". + +Axiom functools_imports_partial : + IsImported globals "functools" "partial". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". + +Axiom ethereum_utils_ensure_imports_ensure : + IsImported globals "ethereum.utils.ensure" "ensure". + +Axiom ethereum_spurious_dragon_vm_imports_Evm : + IsImported globals "ethereum.spurious_dragon.vm" "Evm". +Axiom ethereum_spurious_dragon_vm_imports_stack : + IsImported globals "ethereum.spurious_dragon.vm" "stack". + +Axiom ethereum_spurious_dragon_vm_exceptions_imports_StackUnderflowError : + IsImported globals "ethereum.spurious_dragon.vm.exceptions" "StackUnderflowError". + +Axiom ethereum_spurious_dragon_vm_gas_imports_GAS_BASE : + IsImported globals "ethereum.spurious_dragon.vm.gas" "GAS_BASE". +Axiom ethereum_spurious_dragon_vm_gas_imports_GAS_VERY_LOW : + IsImported globals "ethereum.spurious_dragon.vm.gas" "GAS_VERY_LOW". +Axiom ethereum_spurious_dragon_vm_gas_imports_charge_gas : + IsImported globals "ethereum.spurious_dragon.vm.gas" "charge_gas". + +Axiom ethereum_spurious_dragon_vm_memory_imports_buffer_read : + IsImported globals "ethereum.spurious_dragon.vm.memory" "buffer_read". + +Definition pop : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Remove item from stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.call (| + M.get_field (| M.get_name (| globals, "stack" |), "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_BASE" |) + ], + make_dict [] + |) in + let _ := M.pass (| |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition push_n : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm"; "num_bytes" ] |) in + let _ := Constant.str " + Pushes a N-byte immediate onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + num_bytes : + The number of immediate bytes to be read from the code and pushed to + the stack. + + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_VERY_LOW" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "data_to_push" , + M.call (| + M.get_field (| M.get_name (| globals, "U256" |), "from_be_bytes" |), + make_list [ + M.call (| + M.get_name (| globals, "buffer_read" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "code" |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + BinOp.add (| + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) + ], + make_dict [] + |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + M.get_name (| globals, "num_bytes" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_field (| M.get_name (| globals, "stack" |), "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.get_name (| globals, "data_to_push" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + BinOp.add (| + Constant.int 1, + M.get_name (| globals, "num_bytes" |) + |) + |) in + M.pure Constant.None_)). + +Definition dup_n : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm"; "item_number" ] |) in + let _ := Constant.str " + Duplicate the Nth stack item (from top of the stack) to the top of stack. + + Parameters + ---------- + evm : + The current EVM frame. + + item_number : + The stack item number (0-indexed from top of stack) to be duplicated + to the top of stack. + + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_VERY_LOW" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + Compare.lt (| + M.get_name (| globals, "item_number" |), + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |); + M.get_name (| globals, "StackUnderflowError" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "data_to_duplicate" , + M.get_subscript (| + M.get_field (| M.get_name (| globals, "evm" |), "stack" |), + BinOp.sub (| + BinOp.sub (| + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |), + Constant.int 1 + |), + M.get_name (| globals, "item_number" |) + |) + |) + |) in + let _ := M.call (| + M.get_field (| M.get_name (| globals, "stack" |), "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.get_name (| globals, "data_to_duplicate" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition swap_n : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm"; "item_number" ] |) in + let _ := Constant.str " + Swap the top and the `item_number` element of the stack, where + the top of the stack is position zero. + + If `item_number` is zero, this function does nothing (which should not be + possible, since there is no `SWAP0` instruction). + + Parameters + ---------- + evm : + The current EVM frame. + + item_number : + The stack item number (0-indexed from top of stack) to be swapped + with the top of stack element. + + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_VERY_LOW" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + Compare.lt (| + M.get_name (| globals, "item_number" |), + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |); + M.get_name (| globals, "StackUnderflowError" |) + ], + make_dict [] + |) in + let _ := M.assign (| + make_tuple [ M.get_subscript (| + M.get_field (| M.get_name (| globals, "evm" |), "stack" |), + UnOp.sub (| Constant.int 1 |) + |); M.get_subscript (| + M.get_field (| M.get_name (| globals, "evm" |), "stack" |), + BinOp.sub (| + UnOp.sub (| Constant.int 1 |), + M.get_name (| globals, "item_number" |) + |) + |) ], + make_tuple [ M.get_subscript (| + M.get_field (| M.get_name (| globals, "evm" |), "stack" |), + BinOp.sub (| + UnOp.sub (| Constant.int 1 |), + M.get_name (| globals, "item_number" |) + |) + |); M.get_subscript (| + M.get_field (| M.get_name (| globals, "evm" |), "stack" |), + UnOp.sub (| Constant.int 1 |) + |) ] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition push1 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push2 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push3 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push4 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push5 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push6 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push7 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push8 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push9 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push10 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push11 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push12 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push13 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push14 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push15 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push16 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push17 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push18 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push19 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push20 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push21 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push22 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push23 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push24 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push25 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push26 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push27 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push28 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push29 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push30 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push31 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push32 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "push_n" |) + ], + make_dict [] + |) +)). + +Definition dup1 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "dup_n" |) + ], + make_dict [] + |) +)). + +Definition dup2 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "dup_n" |) + ], + make_dict [] + |) +)). + +Definition dup3 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "dup_n" |) + ], + make_dict [] + |) +)). + +Definition dup4 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "dup_n" |) + ], + make_dict [] + |) +)). + +Definition dup5 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "dup_n" |) + ], + make_dict [] + |) +)). + +Definition dup6 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "dup_n" |) + ], + make_dict [] + |) +)). + +Definition dup7 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "dup_n" |) + ], + make_dict [] + |) +)). + +Definition dup8 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "dup_n" |) + ], + make_dict [] + |) +)). + +Definition dup9 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "dup_n" |) + ], + make_dict [] + |) +)). + +Definition dup10 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "dup_n" |) + ], + make_dict [] + |) +)). + +Definition dup11 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "dup_n" |) + ], + make_dict [] + |) +)). + +Definition dup12 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "dup_n" |) + ], + make_dict [] + |) +)). + +Definition dup13 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "dup_n" |) + ], + make_dict [] + |) +)). + +Definition dup14 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "dup_n" |) + ], + make_dict [] + |) +)). + +Definition dup15 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "dup_n" |) + ], + make_dict [] + |) +)). + +Definition dup16 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "dup_n" |) + ], + make_dict [] + |) +)). + +Definition swap1 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "swap_n" |) + ], + make_dict [] + |) +)). + +Definition swap2 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "swap_n" |) + ], + make_dict [] + |) +)). + +Definition swap3 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "swap_n" |) + ], + make_dict [] + |) +)). + +Definition swap4 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "swap_n" |) + ], + make_dict [] + |) +)). + +Definition swap5 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "swap_n" |) + ], + make_dict [] + |) +)). + +Definition swap6 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "swap_n" |) + ], + make_dict [] + |) +)). + +Definition swap7 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "swap_n" |) + ], + make_dict [] + |) +)). + +Definition swap8 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "swap_n" |) + ], + make_dict [] + |) +)). + +Definition swap9 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "swap_n" |) + ], + make_dict [] + |) +)). + +Definition swap10 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "swap_n" |) + ], + make_dict [] + |) +)). + +Definition swap11 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "swap_n" |) + ], + make_dict [] + |) +)). + +Definition swap12 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "swap_n" |) + ], + make_dict [] + |) +)). + +Definition swap13 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "swap_n" |) + ], + make_dict [] + |) +)). + +Definition swap14 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "swap_n" |) + ], + make_dict [] + |) +)). + +Definition swap15 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "swap_n" |) + ], + make_dict [] + |) +)). + +Definition swap16 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "swap_n" |) + ], + make_dict [] + |) +)). diff --git a/CoqOfPython/ethereum/spurious_dragon/vm/instructions/storage.v b/CoqOfPython/ethereum/spurious_dragon/vm/instructions/storage.v new file mode 100644 index 0000000..2c14d8c --- /dev/null +++ b/CoqOfPython/ethereum/spurious_dragon/vm/instructions/storage.v @@ -0,0 +1,234 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.spurious_dragon.vm.instructions.storage". + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) Storage Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM storage related instructions. +". + +Axiom ethereum_spurious_dragon_state_imports_get_storage : + IsImported globals "ethereum.spurious_dragon.state" "get_storage". +Axiom ethereum_spurious_dragon_state_imports_set_storage : + IsImported globals "ethereum.spurious_dragon.state" "set_storage". + +Axiom ethereum_spurious_dragon_vm_imports_Evm : + IsImported globals "ethereum.spurious_dragon.vm" "Evm". + +Axiom ethereum_spurious_dragon_vm_gas_imports_GAS_SLOAD : + IsImported globals "ethereum.spurious_dragon.vm.gas" "GAS_SLOAD". +Axiom ethereum_spurious_dragon_vm_gas_imports_GAS_STORAGE_CLEAR_REFUND : + IsImported globals "ethereum.spurious_dragon.vm.gas" "GAS_STORAGE_CLEAR_REFUND". +Axiom ethereum_spurious_dragon_vm_gas_imports_GAS_STORAGE_SET : + IsImported globals "ethereum.spurious_dragon.vm.gas" "GAS_STORAGE_SET". +Axiom ethereum_spurious_dragon_vm_gas_imports_GAS_STORAGE_UPDATE : + IsImported globals "ethereum.spurious_dragon.vm.gas" "GAS_STORAGE_UPDATE". +Axiom ethereum_spurious_dragon_vm_gas_imports_charge_gas : + IsImported globals "ethereum.spurious_dragon.vm.gas" "charge_gas". + +Axiom ethereum_spurious_dragon_vm_stack_imports_pop : + IsImported globals "ethereum.spurious_dragon.vm.stack" "pop". +Axiom ethereum_spurious_dragon_vm_stack_imports_push : + IsImported globals "ethereum.spurious_dragon.vm.stack" "push". + +Definition sload : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Loads to the stack, the value corresponding to a certain key from the + storage of the current account. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "key" , + M.call (| + M.get_field (| M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |), "to_be_bytes32" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_SLOAD" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "value" , + M.call (| + M.get_name (| globals, "get_storage" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "env" |), "state" |); + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "current_target" |); + M.get_name (| globals, "key" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.get_name (| globals, "value" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition sstore : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Stores a value at a certain key in the current context's storage. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "key" , + M.call (| + M.get_field (| M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |), "to_be_bytes32" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "new_value" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "current_value" , + M.call (| + M.get_name (| globals, "get_storage" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "env" |), "state" |); + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "current_target" |); + M.get_name (| globals, "key" |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + BoolOp.and (| + Compare.not_eq (| + M.get_name (| globals, "new_value" |), + Constant.int 0 + |), + ltac:(M.monadic ( + Compare.eq (| + M.get_name (| globals, "current_value" |), + Constant.int 0 + |) + )) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "gas_cost" , + M.get_name (| globals, "GAS_STORAGE_SET" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "gas_cost" , + M.get_name (| globals, "GAS_STORAGE_UPDATE" |) + |) in + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + BoolOp.and (| + Compare.eq (| + M.get_name (| globals, "new_value" |), + Constant.int 0 + |), + ltac:(M.monadic ( + Compare.not_eq (| + M.get_name (| globals, "current_value" |), + Constant.int 0 + |) + )) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "refund_counter" |), + M.get_name (| globals, "GAS_STORAGE_CLEAR_REFUND" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "gas_cost" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "set_storage" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "env" |), "state" |); + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "current_target" |); + M.get_name (| globals, "key" |); + M.get_name (| globals, "new_value" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). diff --git a/CoqOfPython/ethereum/spurious_dragon/vm/instructions/system.v b/CoqOfPython/ethereum/spurious_dragon/vm/instructions/system.v new file mode 100644 index 0000000..1bb34af --- /dev/null +++ b/CoqOfPython/ethereum/spurious_dragon/vm/instructions/system.v @@ -0,0 +1,1592 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.spurious_dragon.vm.instructions.system". + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) System Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM system related instructions. +". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_Bytes0 : + IsImported globals "ethereum.base_types" "Bytes0". +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". + +Axiom ethereum_spurious_dragon_fork_types_imports_Address : + IsImported globals "ethereum.spurious_dragon.fork_types" "Address". + +Axiom ethereum_spurious_dragon_state_imports_account_exists_and_is_empty : + IsImported globals "ethereum.spurious_dragon.state" "account_exists_and_is_empty". +Axiom ethereum_spurious_dragon_state_imports_account_has_code_or_nonce : + IsImported globals "ethereum.spurious_dragon.state" "account_has_code_or_nonce". +Axiom ethereum_spurious_dragon_state_imports_get_account : + IsImported globals "ethereum.spurious_dragon.state" "get_account". +Axiom ethereum_spurious_dragon_state_imports_increment_nonce : + IsImported globals "ethereum.spurious_dragon.state" "increment_nonce". +Axiom ethereum_spurious_dragon_state_imports_is_account_alive : + IsImported globals "ethereum.spurious_dragon.state" "is_account_alive". +Axiom ethereum_spurious_dragon_state_imports_set_account_balance : + IsImported globals "ethereum.spurious_dragon.state" "set_account_balance". + +Axiom ethereum_spurious_dragon_utils_address_imports_compute_contract_address : + IsImported globals "ethereum.spurious_dragon.utils.address" "compute_contract_address". +Axiom ethereum_spurious_dragon_utils_address_imports_to_address : + IsImported globals "ethereum.spurious_dragon.utils.address" "to_address". + +Axiom ethereum_spurious_dragon_vm_imports_Evm : + IsImported globals "ethereum.spurious_dragon.vm" "Evm". +Axiom ethereum_spurious_dragon_vm_imports_Message : + IsImported globals "ethereum.spurious_dragon.vm" "Message". +Axiom ethereum_spurious_dragon_vm_imports_incorporate_child_on_error : + IsImported globals "ethereum.spurious_dragon.vm" "incorporate_child_on_error". +Axiom ethereum_spurious_dragon_vm_imports_incorporate_child_on_success : + IsImported globals "ethereum.spurious_dragon.vm" "incorporate_child_on_success". + +Axiom ethereum_spurious_dragon_vm_gas_imports_GAS_CALL : + IsImported globals "ethereum.spurious_dragon.vm.gas" "GAS_CALL". +Axiom ethereum_spurious_dragon_vm_gas_imports_GAS_CALL_VALUE : + IsImported globals "ethereum.spurious_dragon.vm.gas" "GAS_CALL_VALUE". +Axiom ethereum_spurious_dragon_vm_gas_imports_GAS_CREATE : + IsImported globals "ethereum.spurious_dragon.vm.gas" "GAS_CREATE". +Axiom ethereum_spurious_dragon_vm_gas_imports_GAS_NEW_ACCOUNT : + IsImported globals "ethereum.spurious_dragon.vm.gas" "GAS_NEW_ACCOUNT". +Axiom ethereum_spurious_dragon_vm_gas_imports_GAS_SELF_DESTRUCT : + IsImported globals "ethereum.spurious_dragon.vm.gas" "GAS_SELF_DESTRUCT". +Axiom ethereum_spurious_dragon_vm_gas_imports_GAS_SELF_DESTRUCT_NEW_ACCOUNT : + IsImported globals "ethereum.spurious_dragon.vm.gas" "GAS_SELF_DESTRUCT_NEW_ACCOUNT". +Axiom ethereum_spurious_dragon_vm_gas_imports_GAS_ZERO : + IsImported globals "ethereum.spurious_dragon.vm.gas" "GAS_ZERO". +Axiom ethereum_spurious_dragon_vm_gas_imports_REFUND_SELF_DESTRUCT : + IsImported globals "ethereum.spurious_dragon.vm.gas" "REFUND_SELF_DESTRUCT". +Axiom ethereum_spurious_dragon_vm_gas_imports_calculate_gas_extend_memory : + IsImported globals "ethereum.spurious_dragon.vm.gas" "calculate_gas_extend_memory". +Axiom ethereum_spurious_dragon_vm_gas_imports_calculate_message_call_gas : + IsImported globals "ethereum.spurious_dragon.vm.gas" "calculate_message_call_gas". +Axiom ethereum_spurious_dragon_vm_gas_imports_charge_gas : + IsImported globals "ethereum.spurious_dragon.vm.gas" "charge_gas". +Axiom ethereum_spurious_dragon_vm_gas_imports_max_message_call_gas : + IsImported globals "ethereum.spurious_dragon.vm.gas" "max_message_call_gas". + +Axiom ethereum_spurious_dragon_vm_memory_imports_memory_read_bytes : + IsImported globals "ethereum.spurious_dragon.vm.memory" "memory_read_bytes". +Axiom ethereum_spurious_dragon_vm_memory_imports_memory_write : + IsImported globals "ethereum.spurious_dragon.vm.memory" "memory_write". + +Axiom ethereum_spurious_dragon_vm_stack_imports_pop : + IsImported globals "ethereum.spurious_dragon.vm.stack" "pop". +Axiom ethereum_spurious_dragon_vm_stack_imports_push : + IsImported globals "ethereum.spurious_dragon.vm.stack" "push". + +Definition create : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Creates a new account with associated code. + + Parameters + ---------- + evm : + The current EVM frame. + " in +(* At stmt: unsupported node type: ImportFrom *) + let _ := M.assign_local (| + "endowment" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_start_position" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_size" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "extend_memory" , + M.call (| + M.get_name (| globals, "calculate_gas_extend_memory" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "memory" |); + make_list [ + make_tuple [ M.get_name (| globals, "memory_start_position" |); M.get_name (| globals, "memory_size" |) ] + ] + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + BinOp.add (| + M.get_name (| globals, "GAS_CREATE" |), + M.get_field (| M.get_name (| globals, "extend_memory" |), "cost" |) + |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "create_message_gas" , + M.call (| + M.get_name (| globals, "max_message_call_gas" |), + make_list [ + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "gas_left" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_op (| + BinOp.sub, + M.get_field (| M.get_name (| globals, "evm" |), "gas_left" |), + M.get_name (| globals, "create_message_gas" |) + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "memory" |), + BinOp.mult (| + Constant.bytes "00", + M.get_field (| M.get_name (| globals, "extend_memory" |), "expand_by" |) + |) + |) in + let _ := M.assign_local (| + "sender_address" , + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "current_target" |) + |) in + let _ := M.assign_local (| + "sender" , + M.call (| + M.get_name (| globals, "get_account" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "env" |), "state" |); + M.get_name (| globals, "sender_address" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "contract_address" , + M.call (| + M.get_name (| globals, "compute_contract_address" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "current_target" |); + M.get_field (| M.call (| + M.get_name (| globals, "get_account" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "env" |), "state" |); + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "current_target" |) + ], + make_dict [] + |), "nonce" |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + BoolOp.or (| + Compare.lt (| + M.get_field (| M.get_name (| globals, "sender" |), "balance" |), + M.get_name (| globals, "endowment" |) + |), + ltac:(M.monadic ( + BoolOp.or (| + Compare.eq (| + M.get_field (| M.get_name (| globals, "sender" |), "nonce" |), + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + BinOp.sub (| + BinOp.pow (| + Constant.int 2, + Constant.int 64 + |), + Constant.int 1 + |) + ], + make_dict [] + |) + |), + ltac:(M.monadic ( + Compare.gt (| + BinOp.add (| + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "depth" |), + Constant.int 1 + |), + M.get_name (| globals, "STACK_DEPTH_LIMIT" |) + |) + )) + |) + )) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "gas_left" |), + M.get_name (| globals, "create_message_gas" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, "account_has_code_or_nonce" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "env" |), "state" |); + M.get_name (| globals, "contract_address" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, "increment_nonce" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "env" |), "state" |); + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "current_target" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + ], + make_dict [] + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "call_data" , + M.call (| + M.get_name (| globals, "memory_read_bytes" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "memory" |); + M.get_name (| globals, "memory_start_position" |); + M.get_name (| globals, "memory_size" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "increment_nonce" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "env" |), "state" |); + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "current_target" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "child_message" , + M.call (| + M.get_name (| globals, "Message" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "child_evm" , + M.call (| + M.get_name (| globals, "process_create_message" |), + make_list [ + M.get_name (| globals, "child_message" |); + M.get_field (| M.get_name (| globals, "evm" |), "env" |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + M.get_field (| M.get_name (| globals, "child_evm" |), "error" |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, "incorporate_child_on_error" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "child_evm" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + ], + make_dict [] + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, "incorporate_child_on_success" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "child_evm" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.call (| + M.get_field (| M.get_name (| globals, "U256" |), "from_be_bytes" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "child_evm" |), "message" |), "current_target" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )) |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition return_ : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Halts execution returning output data. + + Parameters + ---------- + evm : + The current EVM frame. + " in + let _ := M.assign_local (| + "memory_start_position" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_size" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "extend_memory" , + M.call (| + M.get_name (| globals, "calculate_gas_extend_memory" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "memory" |); + make_list [ + make_tuple [ M.get_name (| globals, "memory_start_position" |); M.get_name (| globals, "memory_size" |) ] + ] + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + BinOp.add (| + M.get_name (| globals, "GAS_ZERO" |), + M.get_field (| M.get_name (| globals, "extend_memory" |), "cost" |) + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "memory" |), + BinOp.mult (| + Constant.bytes "00", + M.get_field (| M.get_name (| globals, "extend_memory" |), "expand_by" |) + |) + |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, "evm" |), "output" |), + M.call (| + M.get_name (| globals, "memory_read_bytes" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "memory" |); + M.get_name (| globals, "memory_start_position" |); + M.get_name (| globals, "memory_size" |) + ], + make_dict [] + |) + |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, "evm" |), "running" |), + Constant.bool false + |) in + let _ := M.pass (| |) in + M.pure Constant.None_)). + +Definition generic_call : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm"; "gas"; "value"; "caller"; "to"; "code_address"; "should_transfer_value"; "memory_input_start_position"; "memory_input_size"; "memory_output_start_position"; "memory_output_size" ] |) in + let _ := Constant.str " + Perform the core logic of the `CALL*` family of opcodes. + " in +(* At stmt: unsupported node type: ImportFrom *) + let _ := + (* if *) + M.if_then_else (| + Compare.gt (| + BinOp.add (| + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "depth" |), + Constant.int 1 + |), + M.get_name (| globals, "STACK_DEPTH_LIMIT" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "gas_left" |), + M.get_name (| globals, "gas" |) + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.return_ (| + Constant.None_ + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "call_data" , + M.call (| + M.get_name (| globals, "memory_read_bytes" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "memory" |); + M.get_name (| globals, "memory_input_start_position" |); + M.get_name (| globals, "memory_input_size" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "code" , + M.get_field (| M.call (| + M.get_name (| globals, "get_account" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "env" |), "state" |); + M.get_name (| globals, "code_address" |) + ], + make_dict [] + |), "code" |) + |) in + let _ := M.assign_local (| + "child_message" , + M.call (| + M.get_name (| globals, "Message" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "child_evm" , + M.call (| + M.get_name (| globals, "process_message" |), + make_list [ + M.get_name (| globals, "child_message" |); + M.get_field (| M.get_name (| globals, "evm" |), "env" |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + M.get_field (| M.get_name (| globals, "child_evm" |), "error" |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, "incorporate_child_on_error" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "child_evm" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + ], + make_dict [] + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, "incorporate_child_on_success" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "child_evm" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 1 + ], + make_dict [] + |) + ], + make_dict [] + |) in + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "actual_output_size" , + M.call (| + M.get_name (| globals, "min" |), + make_list [ + M.get_name (| globals, "memory_output_size" |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_field (| M.get_name (| globals, "child_evm" |), "output" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "memory_write" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "memory" |); + M.get_name (| globals, "memory_output_start_position" |); + M.slice (| + M.get_field (| M.get_name (| globals, "child_evm" |), "output" |), + Constant.None_, + M.get_name (| globals, "actual_output_size" |), + Constant.None_ + |) + ], + make_dict [] + |) in + M.pure Constant.None_)). + +Definition call : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Message-call into an account. + + Parameters + ---------- + evm : + The current EVM frame. + " in + let _ := M.assign_local (| + "gas" , + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "to" , + M.call (| + M.get_name (| globals, "to_address" |), + make_list [ + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "value" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_input_start_position" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_input_size" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_output_start_position" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_output_size" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "extend_memory" , + M.call (| + M.get_name (| globals, "calculate_gas_extend_memory" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "memory" |); + make_list [ + make_tuple [ M.get_name (| globals, "memory_input_start_position" |); M.get_name (| globals, "memory_input_size" |) ]; + make_tuple [ M.get_name (| globals, "memory_output_start_position" |); M.get_name (| globals, "memory_output_size" |) ] + ] + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "create_gas_cost" , + (* if *) + M.if_then_else (| + BoolOp.or (| + Compare.eq (| + M.get_name (| globals, "value" |), + Constant.int 0 + |), + ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "is_account_alive" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "env" |), "state" |); + M.get_name (| globals, "to" |) + ], + make_dict [] + |) + )) + |), + (* then *) + ltac:(M.monadic ( +M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + (* else *) + )), ltac:(M.monadic ( +M.get_name (| globals, "GAS_NEW_ACCOUNT" |) + )) |) + |) in + let _ := M.assign_local (| + "transfer_gas_cost" , + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, "value" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( +M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + (* else *) + )), ltac:(M.monadic ( +M.get_name (| globals, "GAS_CALL_VALUE" |) + )) |) + |) in + let _ := M.assign_local (| + "message_call_gas" , + M.call (| + M.get_name (| globals, "calculate_message_call_gas" |), + make_list [ + M.get_name (| globals, "value" |); + M.get_name (| globals, "gas" |); + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "gas_left" |) + ], + make_dict [] + |); + M.get_field (| M.get_name (| globals, "extend_memory" |), "cost" |); + BinOp.add (| + BinOp.add (| + M.get_name (| globals, "GAS_CALL" |), + M.get_name (| globals, "create_gas_cost" |) + |), + M.get_name (| globals, "transfer_gas_cost" |) + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + BinOp.add (| + M.get_field (| M.get_name (| globals, "message_call_gas" |), "cost" |), + M.get_field (| M.get_name (| globals, "extend_memory" |), "cost" |) + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "memory" |), + BinOp.mult (| + Constant.bytes "00", + M.get_field (| M.get_name (| globals, "extend_memory" |), "expand_by" |) + |) + |) in + let _ := M.assign_local (| + "sender_balance" , + M.get_field (| M.call (| + M.get_name (| globals, "get_account" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "env" |), "state" |); + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "current_target" |) + ], + make_dict [] + |), "balance" |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.lt (| + M.get_name (| globals, "sender_balance" |), + M.get_name (| globals, "value" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "gas_left" |), + M.get_field (| M.get_name (| globals, "message_call_gas" |), "stipend" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, "generic_call" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_field (| M.get_name (| globals, "message_call_gas" |), "stipend" |); + M.get_name (| globals, "value" |); + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "current_target" |); + M.get_name (| globals, "to" |); + M.get_name (| globals, "to" |); + Constant.bool true; + M.get_name (| globals, "memory_input_start_position" |); + M.get_name (| globals, "memory_input_size" |); + M.get_name (| globals, "memory_output_start_position" |); + M.get_name (| globals, "memory_output_size" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + )) |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition callcode : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Message-call into this account with alternative account’s code. + + Parameters + ---------- + evm : + The current EVM frame. + " in + let _ := M.assign_local (| + "gas" , + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "code_address" , + M.call (| + M.get_name (| globals, "to_address" |), + make_list [ + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "value" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_input_start_position" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_input_size" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_output_start_position" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_output_size" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "to" , + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "current_target" |) + |) in + let _ := M.assign_local (| + "extend_memory" , + M.call (| + M.get_name (| globals, "calculate_gas_extend_memory" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "memory" |); + make_list [ + make_tuple [ M.get_name (| globals, "memory_input_start_position" |); M.get_name (| globals, "memory_input_size" |) ]; + make_tuple [ M.get_name (| globals, "memory_output_start_position" |); M.get_name (| globals, "memory_output_size" |) ] + ] + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "transfer_gas_cost" , + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, "value" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( +M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + (* else *) + )), ltac:(M.monadic ( +M.get_name (| globals, "GAS_CALL_VALUE" |) + )) |) + |) in + let _ := M.assign_local (| + "message_call_gas" , + M.call (| + M.get_name (| globals, "calculate_message_call_gas" |), + make_list [ + M.get_name (| globals, "value" |); + M.get_name (| globals, "gas" |); + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "gas_left" |) + ], + make_dict [] + |); + M.get_field (| M.get_name (| globals, "extend_memory" |), "cost" |); + BinOp.add (| + M.get_name (| globals, "GAS_CALL" |), + M.get_name (| globals, "transfer_gas_cost" |) + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + BinOp.add (| + M.get_field (| M.get_name (| globals, "message_call_gas" |), "cost" |), + M.get_field (| M.get_name (| globals, "extend_memory" |), "cost" |) + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "memory" |), + BinOp.mult (| + Constant.bytes "00", + M.get_field (| M.get_name (| globals, "extend_memory" |), "expand_by" |) + |) + |) in + let _ := M.assign_local (| + "sender_balance" , + M.get_field (| M.call (| + M.get_name (| globals, "get_account" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "env" |), "state" |); + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "current_target" |) + ], + make_dict [] + |), "balance" |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.lt (| + M.get_name (| globals, "sender_balance" |), + M.get_name (| globals, "value" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "gas_left" |), + M.get_field (| M.get_name (| globals, "message_call_gas" |), "stipend" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, "generic_call" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_field (| M.get_name (| globals, "message_call_gas" |), "stipend" |); + M.get_name (| globals, "value" |); + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "current_target" |); + M.get_name (| globals, "to" |); + M.get_name (| globals, "code_address" |); + Constant.bool true; + M.get_name (| globals, "memory_input_start_position" |); + M.get_name (| globals, "memory_input_size" |); + M.get_name (| globals, "memory_output_start_position" |); + M.get_name (| globals, "memory_output_size" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + )) |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition selfdestruct : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Halt execution and register account for later deletion. + + Parameters + ---------- + evm : + The current EVM frame. + " in + let _ := M.assign_local (| + "beneficiary" , + M.call (| + M.get_name (| globals, "to_address" |), + make_list [ + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "gas_cost" , + M.get_name (| globals, "GAS_SELF_DESTRUCT" |) + |) in + let _ := + (* if *) + M.if_then_else (| + BoolOp.and (| + UnOp.not (| M.call (| + M.get_name (| globals, "is_account_alive" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "env" |), "state" |); + M.get_name (| globals, "beneficiary" |) + ], + make_dict [] + |) |), + ltac:(M.monadic ( + Compare.not_eq (| + M.get_field (| M.call (| + M.get_name (| globals, "get_account" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "env" |), "state" |); + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "current_target" |) + ], + make_dict [] + |), "balance" |), + Constant.int 0 + |) + )) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_op_local (| + BinOp.add, + "gas_cost", + M.get_name (| globals, "GAS_SELF_DESTRUCT_NEW_ACCOUNT" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "originator" , + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "current_target" |) + |) in + let _ := M.assign_local (| + "refunded_accounts" , + M.get_field (| M.get_name (| globals, "evm" |), "accounts_to_delete" |) + |) in + let _ := M.assign_local (| + "parent_evm" , + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "parent_evm" |) + |) in + let _ := + M.while (| + Compare.is_not (| + M.get_name (| globals, "parent_evm" |), + Constant.None_ + |), + ltac:(M.monadic ( + let _ := M.call (| + M.get_field (| M.get_name (| globals, "refunded_accounts" |), "update" |), + make_list [ + M.get_field (| M.get_name (| globals, "parent_evm" |), "accounts_to_delete" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "parent_evm" , + M.get_field (| M.get_field (| M.get_name (| globals, "parent_evm" |), "message" |), "parent_evm" |) + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.not_in (| + M.get_name (| globals, "originator" |), + M.get_name (| globals, "refunded_accounts" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "refund_counter" |), + M.get_name (| globals, "REFUND_SELF_DESTRUCT" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "gas_cost" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "beneficiary_balance" , + M.get_field (| M.call (| + M.get_name (| globals, "get_account" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "env" |), "state" |); + M.get_name (| globals, "beneficiary" |) + ], + make_dict [] + |), "balance" |) + |) in + let _ := M.assign_local (| + "originator_balance" , + M.get_field (| M.call (| + M.get_name (| globals, "get_account" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "env" |), "state" |); + M.get_name (| globals, "originator" |) + ], + make_dict [] + |), "balance" |) + |) in + let _ := M.call (| + M.get_name (| globals, "set_account_balance" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "env" |), "state" |); + M.get_name (| globals, "beneficiary" |); + BinOp.add (| + M.get_name (| globals, "beneficiary_balance" |), + M.get_name (| globals, "originator_balance" |) + |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "set_account_balance" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "env" |), "state" |); + M.get_name (| globals, "originator" |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "accounts_to_delete" |), "add" |), + make_list [ + M.get_name (| globals, "originator" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, "account_exists_and_is_empty" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "env" |), "state" |); + M.get_name (| globals, "beneficiary" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "touched_accounts" |), "add" |), + make_list [ + M.get_name (| globals, "beneficiary" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, "evm" |), "running" |), + Constant.bool false + |) in + let _ := M.pass (| |) in + M.pure Constant.None_)). + +Definition delegatecall : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Message-call into an account. + + Parameters + ---------- + evm : + The current EVM frame. + " in + let _ := M.assign_local (| + "gas" , + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "code_address" , + M.call (| + M.get_name (| globals, "to_address" |), + make_list [ + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_input_start_position" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_input_size" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_output_start_position" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_output_size" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "extend_memory" , + M.call (| + M.get_name (| globals, "calculate_gas_extend_memory" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "memory" |); + make_list [ + make_tuple [ M.get_name (| globals, "memory_input_start_position" |); M.get_name (| globals, "memory_input_size" |) ]; + make_tuple [ M.get_name (| globals, "memory_output_start_position" |); M.get_name (| globals, "memory_output_size" |) ] + ] + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "message_call_gas" , + M.call (| + M.get_name (| globals, "calculate_message_call_gas" |), + make_list [ + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |); + M.get_name (| globals, "gas" |); + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "gas_left" |) + ], + make_dict [] + |); + M.get_field (| M.get_name (| globals, "extend_memory" |), "cost" |); + M.get_name (| globals, "GAS_CALL" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + BinOp.add (| + M.get_field (| M.get_name (| globals, "message_call_gas" |), "cost" |), + M.get_field (| M.get_name (| globals, "extend_memory" |), "cost" |) + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "memory" |), + BinOp.mult (| + Constant.bytes "00", + M.get_field (| M.get_name (| globals, "extend_memory" |), "expand_by" |) + |) + |) in + let _ := M.call (| + M.get_name (| globals, "generic_call" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_field (| M.get_name (| globals, "message_call_gas" |), "stipend" |); + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "value" |); + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "caller" |); + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "current_target" |); + M.get_name (| globals, "code_address" |); + Constant.bool false; + M.get_name (| globals, "memory_input_start_position" |); + M.get_name (| globals, "memory_input_size" |); + M.get_name (| globals, "memory_output_start_position" |); + M.get_name (| globals, "memory_output_size" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). diff --git a/CoqOfPython/ethereum/spurious_dragon/vm/interpreter.v b/CoqOfPython/ethereum/spurious_dragon/vm/interpreter.v new file mode 100644 index 0000000..e58aeba --- /dev/null +++ b/CoqOfPython/ethereum/spurious_dragon/vm/interpreter.v @@ -0,0 +1,655 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.spurious_dragon.vm.interpreter". + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) Interpreter +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +A straightforward interpreter that executes EVM code. +". + +Axiom dataclasses_imports_dataclass : + IsImported globals "dataclasses" "dataclass". + +Axiom typing_imports_Iterable : + IsImported globals "typing" "Iterable". +Axiom typing_imports_Optional : + IsImported globals "typing" "Optional". +Axiom typing_imports_Set : + IsImported globals "typing" "Set". +Axiom typing_imports_Tuple : + IsImported globals "typing" "Tuple". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_Bytes0 : + IsImported globals "ethereum.base_types" "Bytes0". +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". + +Axiom ethereum_trace_imports_EvmStop : + IsImported globals "ethereum.trace" "EvmStop". +Axiom ethereum_trace_imports_OpEnd : + IsImported globals "ethereum.trace" "OpEnd". +Axiom ethereum_trace_imports_OpException : + IsImported globals "ethereum.trace" "OpException". +Axiom ethereum_trace_imports_OpStart : + IsImported globals "ethereum.trace" "OpStart". +Axiom ethereum_trace_imports_PrecompileEnd : + IsImported globals "ethereum.trace" "PrecompileEnd". +Axiom ethereum_trace_imports_PrecompileStart : + IsImported globals "ethereum.trace" "PrecompileStart". +Axiom ethereum_trace_imports_TransactionEnd : + IsImported globals "ethereum.trace" "TransactionEnd". +Axiom ethereum_trace_imports_evm_trace : + IsImported globals "ethereum.trace" "evm_trace". + +Axiom ethereum_utils_ensure_imports_ensure : + IsImported globals "ethereum.utils.ensure" "ensure". + +Axiom ethereum_spurious_dragon_blocks_imports_Log : + IsImported globals "ethereum.spurious_dragon.blocks" "Log". + +Axiom ethereum_spurious_dragon_fork_types_imports_Address : + IsImported globals "ethereum.spurious_dragon.fork_types" "Address". + +Axiom ethereum_spurious_dragon_state_imports_account_exists_and_is_empty : + IsImported globals "ethereum.spurious_dragon.state" "account_exists_and_is_empty". +Axiom ethereum_spurious_dragon_state_imports_account_has_code_or_nonce : + IsImported globals "ethereum.spurious_dragon.state" "account_has_code_or_nonce". +Axiom ethereum_spurious_dragon_state_imports_begin_transaction : + IsImported globals "ethereum.spurious_dragon.state" "begin_transaction". +Axiom ethereum_spurious_dragon_state_imports_commit_transaction : + IsImported globals "ethereum.spurious_dragon.state" "commit_transaction". +Axiom ethereum_spurious_dragon_state_imports_destroy_storage : + IsImported globals "ethereum.spurious_dragon.state" "destroy_storage". +Axiom ethereum_spurious_dragon_state_imports_increment_nonce : + IsImported globals "ethereum.spurious_dragon.state" "increment_nonce". +Axiom ethereum_spurious_dragon_state_imports_move_ether : + IsImported globals "ethereum.spurious_dragon.state" "move_ether". +Axiom ethereum_spurious_dragon_state_imports_rollback_transaction : + IsImported globals "ethereum.spurious_dragon.state" "rollback_transaction". +Axiom ethereum_spurious_dragon_state_imports_set_code : + IsImported globals "ethereum.spurious_dragon.state" "set_code". +Axiom ethereum_spurious_dragon_state_imports_touch_account : + IsImported globals "ethereum.spurious_dragon.state" "touch_account". + +Axiom ethereum_spurious_dragon_vm_imports_Message : + IsImported globals "ethereum.spurious_dragon.vm" "Message". + +Axiom ethereum_spurious_dragon_vm_gas_imports_GAS_CODE_DEPOSIT : + IsImported globals "ethereum.spurious_dragon.vm.gas" "GAS_CODE_DEPOSIT". +Axiom ethereum_spurious_dragon_vm_gas_imports_charge_gas : + IsImported globals "ethereum.spurious_dragon.vm.gas" "charge_gas". + +Axiom ethereum_spurious_dragon_vm_precompiled_contracts_mapping_imports_PRE_COMPILED_CONTRACTS : + IsImported globals "ethereum.spurious_dragon.vm.precompiled_contracts.mapping" "PRE_COMPILED_CONTRACTS". + +Axiom ethereum_spurious_dragon_vm_imports_Environment : + IsImported globals "ethereum.spurious_dragon.vm" "Environment". +Axiom ethereum_spurious_dragon_vm_imports_Evm : + IsImported globals "ethereum.spurious_dragon.vm" "Evm". + +Axiom ethereum_spurious_dragon_vm_exceptions_imports_AddressCollision : + IsImported globals "ethereum.spurious_dragon.vm.exceptions" "AddressCollision". +Axiom ethereum_spurious_dragon_vm_exceptions_imports_ExceptionalHalt : + IsImported globals "ethereum.spurious_dragon.vm.exceptions" "ExceptionalHalt". +Axiom ethereum_spurious_dragon_vm_exceptions_imports_InvalidOpcode : + IsImported globals "ethereum.spurious_dragon.vm.exceptions" "InvalidOpcode". +Axiom ethereum_spurious_dragon_vm_exceptions_imports_OutOfGasError : + IsImported globals "ethereum.spurious_dragon.vm.exceptions" "OutOfGasError". +Axiom ethereum_spurious_dragon_vm_exceptions_imports_StackDepthLimitError : + IsImported globals "ethereum.spurious_dragon.vm.exceptions" "StackDepthLimitError". + +Axiom ethereum_spurious_dragon_vm_instructions_imports_Ops : + IsImported globals "ethereum.spurious_dragon.vm.instructions" "Ops". +Axiom ethereum_spurious_dragon_vm_instructions_imports_op_implementation : + IsImported globals "ethereum.spurious_dragon.vm.instructions" "op_implementation". + +Axiom ethereum_spurious_dragon_vm_runtime_imports_get_valid_jump_destinations : + IsImported globals "ethereum.spurious_dragon.vm.runtime" "get_valid_jump_destinations". + +Definition STACK_DEPTH_LIMIT : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 1024 + ], + make_dict [] + |) +)). + +Definition MAX_CODE_SIZE : Value.t := M.run ltac:(M.monadic ( + Constant.int 24576 +)). + +Definition MessageCallOutput : Value.t := + builtins.make_klass + [] + [ + + ] + [ + + ]. + +Definition process_message_call : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "message"; "env" ] |) in + let _ := Constant.str " + If `message.current` is empty then it creates a smart contract + else it executes a call from the `message.caller` to the `message.target`. + + Parameters + ---------- + message : + Transaction specific items. + + env : + External items required for EVM execution. + + Returns + ------- + output : `MessageCallOutput` + Output of the message call + " in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_field (| M.get_name (| globals, "message" |), "target" |), + M.call (| + M.get_name (| globals, "Bytes0" |), + make_list [ + Constant.bytes "" + ], + make_dict [] + |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "is_collision" , + M.call (| + M.get_name (| globals, "account_has_code_or_nonce" |), + make_list [ + M.get_field (| M.get_name (| globals, "env" |), "state" |); + M.get_field (| M.get_name (| globals, "message" |), "current_target" |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + M.get_name (| globals, "is_collision" |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + M.call (| + M.get_name (| globals, "MessageCallOutput" |), + make_list [ + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |); + M.call (| + M.get_name (| globals, "tuple" |), + make_list [], + make_dict [] + |); + M.call (| + M.get_name (| globals, "set" |), + make_list [], + make_dict [] + |); + M.call (| + M.get_name (| globals, "set" |), + make_list [], + make_dict [] + |); + M.call (| + M.get_name (| globals, "AddressCollision" |), + make_list [], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "evm" , + M.call (| + M.get_name (| globals, "process_create_message" |), + make_list [ + M.get_name (| globals, "message" |); + M.get_name (| globals, "env" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "evm" , + M.call (| + M.get_name (| globals, "process_message" |), + make_list [ + M.get_name (| globals, "message" |); + M.get_name (| globals, "env" |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, "account_exists_and_is_empty" |), + make_list [ + M.get_field (| M.get_name (| globals, "env" |), "state" |); + M.call (| + M.get_name (| globals, "Address" |), + make_list [ + M.get_field (| M.get_name (| globals, "message" |), "target" |) + ], + make_dict [] + |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "touched_accounts" |), "add" |), + make_list [ + M.call (| + M.get_name (| globals, "Address" |), + make_list [ + M.get_field (| M.get_name (| globals, "message" |), "target" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + M.get_field (| M.get_name (| globals, "evm" |), "error" |), + (* then *) + ltac:(M.monadic ( +(* At stmt: unsupported node type: AnnAssign *) + let _ := M.assign_local (| + "accounts_to_delete" , + M.call (| + M.get_name (| globals, "set" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "touched_accounts" , + M.call (| + M.get_name (| globals, "set" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "refund_counter" , + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "logs" , + M.get_field (| M.get_name (| globals, "evm" |), "logs" |) + |) in + let _ := M.assign_local (| + "accounts_to_delete" , + M.get_field (| M.get_name (| globals, "evm" |), "accounts_to_delete" |) + |) in + let _ := M.assign_local (| + "touched_accounts" , + M.get_field (| M.get_name (| globals, "evm" |), "touched_accounts" |) + |) in + let _ := M.assign_local (| + "refund_counter" , + M.get_field (| M.get_name (| globals, "evm" |), "refund_counter" |) + |) in + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "tx_end" , + M.call (| + M.get_name (| globals, "TransactionEnd" |), + make_list [ + BinOp.sub (| + M.get_field (| M.get_name (| globals, "message" |), "gas" |), + M.get_field (| M.get_name (| globals, "evm" |), "gas_left" |) + |); + M.get_field (| M.get_name (| globals, "evm" |), "output" |); + M.get_field (| M.get_name (| globals, "evm" |), "error" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "evm_trace" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "tx_end" |) + ], + make_dict [] + |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, "MessageCallOutput" |), + make_list [], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Definition process_create_message : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "message"; "env" ] |) in + let _ := Constant.str " + Executes a call to create a smart contract. + + Parameters + ---------- + message : + Transaction specific items. + env : + External items required for EVM execution. + + Returns + ------- + evm: :py:class:`~ethereum.spurious_dragon.vm.Evm` + Items containing execution specific objects. + " in + let _ := M.call (| + M.get_name (| globals, "begin_transaction" |), + make_list [ + M.get_field (| M.get_name (| globals, "env" |), "state" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "destroy_storage" |), + make_list [ + M.get_field (| M.get_name (| globals, "env" |), "state" |); + M.get_field (| M.get_name (| globals, "message" |), "current_target" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "increment_nonce" |), + make_list [ + M.get_field (| M.get_name (| globals, "env" |), "state" |); + M.get_field (| M.get_name (| globals, "message" |), "current_target" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "evm" , + M.call (| + M.get_name (| globals, "process_message" |), + make_list [ + M.get_name (| globals, "message" |); + M.get_name (| globals, "env" |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + UnOp.not (| M.get_field (| M.get_name (| globals, "evm" |), "error" |) |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "contract_code" , + M.get_field (| M.get_name (| globals, "evm" |), "output" |) + |) in + let _ := M.assign_local (| + "contract_code_gas" , + BinOp.mult (| + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_name (| globals, "contract_code" |) + ], + make_dict [] + |), + M.get_name (| globals, "GAS_CODE_DEPOSIT" |) + |) + |) in +(* At stmt: unsupported node type: Try *) + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, "rollback_transaction" |), + make_list [ + M.get_field (| M.get_name (| globals, "env" |), "state" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + )) |) in + let _ := M.return_ (| + M.get_name (| globals, "evm" |) + |) in + M.pure Constant.None_)). + +Definition process_message : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "message"; "env" ] |) in + let _ := Constant.str " + Executes a call to create a smart contract. + + Parameters + ---------- + message : + Transaction specific items. + env : + External items required for EVM execution. + + Returns + ------- + evm: :py:class:`~ethereum.spurious_dragon.vm.Evm` + Items containing execution specific objects + " in + let _ := + (* if *) + M.if_then_else (| + Compare.gt (| + M.get_field (| M.get_name (| globals, "message" |), "depth" |), + M.get_name (| globals, "STACK_DEPTH_LIMIT" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.call (| + M.get_name (| globals, "StackDepthLimitError" |), + make_list [ + Constant.str "Stack depth limit reached" + ], + make_dict [] + |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.call (| + M.get_name (| globals, "begin_transaction" |), + make_list [ + M.get_field (| M.get_name (| globals, "env" |), "state" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "touch_account" |), + make_list [ + M.get_field (| M.get_name (| globals, "env" |), "state" |); + M.get_field (| M.get_name (| globals, "message" |), "current_target" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + BoolOp.and (| + M.get_field (| M.get_name (| globals, "message" |), "should_transfer_value" |), + ltac:(M.monadic ( + Compare.not_eq (| + M.get_field (| M.get_name (| globals, "message" |), "value" |), + Constant.int 0 + |) + )) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, "move_ether" |), + make_list [ + M.get_field (| M.get_name (| globals, "env" |), "state" |); + M.get_field (| M.get_name (| globals, "message" |), "caller" |); + M.get_field (| M.get_name (| globals, "message" |), "current_target" |); + M.get_field (| M.get_name (| globals, "message" |), "value" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "evm" , + M.call (| + M.get_name (| globals, "execute_code" |), + make_list [ + M.get_name (| globals, "message" |); + M.get_name (| globals, "env" |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + M.get_field (| M.get_name (| globals, "evm" |), "error" |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, "rollback_transaction" |), + make_list [ + M.get_field (| M.get_name (| globals, "env" |), "state" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, "commit_transaction" |), + make_list [ + M.get_field (| M.get_name (| globals, "env" |), "state" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + )) |) in + let _ := M.return_ (| + M.get_name (| globals, "evm" |) + |) in + M.pure Constant.None_)). + +Definition execute_code : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "message"; "env" ] |) in + let _ := Constant.str " + Executes bytecode present in the `message`. + + Parameters + ---------- + message : + Transaction specific items. + env : + External items required for EVM execution. + + Returns + ------- + evm: `ethereum.vm.EVM` + Items containing execution specific objects + " in + let _ := M.assign_local (| + "code" , + M.get_field (| M.get_name (| globals, "message" |), "code" |) + |) in + let _ := M.assign_local (| + "valid_jump_destinations" , + M.call (| + M.get_name (| globals, "get_valid_jump_destinations" |), + make_list [ + M.get_name (| globals, "code" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "evm" , + M.call (| + M.get_name (| globals, "Evm" |), + make_list [], + make_dict [] + |) + |) in +(* At stmt: unsupported node type: Try *) + let _ := M.return_ (| + M.get_name (| globals, "evm" |) + |) in + M.pure Constant.None_)). diff --git a/CoqOfPython/ethereum/spurious_dragon/vm/memory.v b/CoqOfPython/ethereum/spurious_dragon/vm/memory.v new file mode 100644 index 0000000..b492085 --- /dev/null +++ b/CoqOfPython/ethereum/spurious_dragon/vm/memory.v @@ -0,0 +1,166 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.spurious_dragon.vm.memory". + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) Memory +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +EVM memory operations. +". + +Axiom ethereum_utils_byte_imports_right_pad_zero_bytes : + IsImported globals "ethereum.utils.byte" "right_pad_zero_bytes". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_Bytes : + IsImported globals "ethereum.base_types" "Bytes". +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". + +Definition memory_write : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "memory"; "start_position"; "value" ] |) in + let _ := Constant.str " + Writes to memory. + + Parameters + ---------- + memory : + Memory contents of the EVM. + start_position : + Starting pointer to the memory. + value : + Data to write to memory. + " in + let _ := M.assign (| + M.slice (| + M.get_name (| globals, "memory" |), + M.get_name (| globals, "start_position" |), + BinOp.add (| + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.get_name (| globals, "start_position" |) + ], + make_dict [] + |), + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_name (| globals, "value" |) + ], + make_dict [] + |) + |), + Constant.None_ + |), + M.get_name (| globals, "value" |) + |) in + M.pure Constant.None_)). + +Definition memory_read_bytes : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "memory"; "start_position"; "size" ] |) in + let _ := Constant.str " + Read bytes from memory. + + Parameters + ---------- + memory : + Memory contents of the EVM. + start_position : + Starting pointer to the memory. + size : + Size of the data that needs to be read from `start_position`. + + Returns + ------- + data_bytes : + Data read from memory. + " in + let _ := M.return_ (| + M.slice (| + M.get_name (| globals, "memory" |), + M.get_name (| globals, "start_position" |), + BinOp.add (| + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.get_name (| globals, "start_position" |) + ], + make_dict [] + |), + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.get_name (| globals, "size" |) + ], + make_dict [] + |) + |), + Constant.None_ + |) + |) in + M.pure Constant.None_)). + +Definition buffer_read : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "buffer"; "start_position"; "size" ] |) in + let _ := Constant.str " + Read bytes from a buffer. Padding with zeros if necessary. + + Parameters + ---------- + buffer : + Memory contents of the EVM. + start_position : + Starting pointer to the memory. + size : + Size of the data that needs to be read from `start_position`. + + Returns + ------- + data_bytes : + Data read from memory. + " in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, "right_pad_zero_bytes" |), + make_list [ + M.slice (| + M.get_name (| globals, "buffer" |), + M.get_name (| globals, "start_position" |), + BinOp.add (| + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.get_name (| globals, "start_position" |) + ], + make_dict [] + |), + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.get_name (| globals, "size" |) + ], + make_dict [] + |) + |), + Constant.None_ + |); + M.get_name (| globals, "size" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). diff --git a/CoqOfPython/ethereum/spurious_dragon/vm/precompiled_contracts/__init__.v b/CoqOfPython/ethereum/spurious_dragon/vm/precompiled_contracts/__init__.v new file mode 100644 index 0000000..1d7b891 --- /dev/null +++ b/CoqOfPython/ethereum/spurious_dragon/vm/precompiled_contracts/__init__.v @@ -0,0 +1,66 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.spurious_dragon.vm.precompiled_contracts.__init__". + +Definition expr_1 : Value.t := + Constant.str " +Precompiled Contract Addresses +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Addresses of precompiled contracts and mappings to their +implementations. +". + +Axiom ethereum_spurious_dragon_utils_hexadecimal_imports_hex_to_address : + IsImported globals "ethereum.spurious_dragon.utils.hexadecimal" "hex_to_address". + +Definition __all__ : Value.t := M.run ltac:(M.monadic ( + make_tuple [ Constant.str "ECRECOVER_ADDRESS"; Constant.str "SHA256_ADDRESS"; Constant.str "RIPEMD160_ADDRESS"; Constant.str "IDENTITY_ADDRESS" ] +)). + +Definition ECRECOVER_ADDRESS : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "hex_to_address" |), + make_list [ + Constant.str "0x01" + ], + make_dict [] + |) +)). + +Definition SHA256_ADDRESS : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "hex_to_address" |), + make_list [ + Constant.str "0x02" + ], + make_dict [] + |) +)). + +Definition RIPEMD160_ADDRESS : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "hex_to_address" |), + make_list [ + Constant.str "0x03" + ], + make_dict [] + |) +)). + +Definition IDENTITY_ADDRESS : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "hex_to_address" |), + make_list [ + Constant.str "0x04" + ], + make_dict [] + |) +)). diff --git a/CoqOfPython/ethereum/spurious_dragon/vm/precompiled_contracts/ecrecover.v b/CoqOfPython/ethereum/spurious_dragon/vm/precompiled_contracts/ecrecover.v new file mode 100644 index 0000000..c1ae66e --- /dev/null +++ b/CoqOfPython/ethereum/spurious_dragon/vm/precompiled_contracts/ecrecover.v @@ -0,0 +1,301 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.spurious_dragon.vm.precompiled_contracts.ecrecover". + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) ECRECOVER PRECOMPILED CONTRACT +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementation of the ECRECOVER precompiled contract. +". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". + +Axiom ethereum_crypto_elliptic_curve_imports_SECP256K1N : + IsImported globals "ethereum.crypto.elliptic_curve" "SECP256K1N". +Axiom ethereum_crypto_elliptic_curve_imports_secp256k1_recover : + IsImported globals "ethereum.crypto.elliptic_curve" "secp256k1_recover". + +Axiom ethereum_crypto_hash_imports_Hash32 : + IsImported globals "ethereum.crypto.hash" "Hash32". +Axiom ethereum_crypto_hash_imports_keccak256 : + IsImported globals "ethereum.crypto.hash" "keccak256". + +Axiom ethereum_utils_byte_imports_left_pad_zero_bytes : + IsImported globals "ethereum.utils.byte" "left_pad_zero_bytes". + +Axiom ethereum_spurious_dragon_vm_imports_Evm : + IsImported globals "ethereum.spurious_dragon.vm" "Evm". + +Axiom ethereum_spurious_dragon_vm_gas_imports_GAS_ECRECOVER : + IsImported globals "ethereum.spurious_dragon.vm.gas" "GAS_ECRECOVER". +Axiom ethereum_spurious_dragon_vm_gas_imports_charge_gas : + IsImported globals "ethereum.spurious_dragon.vm.gas" "charge_gas". + +Axiom ethereum_spurious_dragon_vm_memory_imports_buffer_read : + IsImported globals "ethereum.spurious_dragon.vm.memory" "buffer_read". + +Definition ecrecover : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Decrypts the address using elliptic curve DSA recovery mechanism and writes + the address to output. + + Parameters + ---------- + evm : + The current EVM frame. + " in + let _ := M.assign_local (| + "data" , + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "data" |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_ECRECOVER" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "message_hash_bytes" , + M.call (| + M.get_name (| globals, "buffer_read" |), + make_list [ + M.get_name (| globals, "data" |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 32 + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "message_hash" , + M.call (| + M.get_name (| globals, "Hash32" |), + make_list [ + M.get_name (| globals, "message_hash_bytes" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "v" , + M.call (| + M.get_field (| M.get_name (| globals, "U256" |), "from_be_bytes" |), + make_list [ + M.call (| + M.get_name (| globals, "buffer_read" |), + make_list [ + M.get_name (| globals, "data" |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 32 + ], + make_dict [] + |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 32 + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "r" , + M.call (| + M.get_field (| M.get_name (| globals, "U256" |), "from_be_bytes" |), + make_list [ + M.call (| + M.get_name (| globals, "buffer_read" |), + make_list [ + M.get_name (| globals, "data" |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 64 + ], + make_dict [] + |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 32 + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "s" , + M.call (| + M.get_field (| M.get_name (| globals, "U256" |), "from_be_bytes" |), + make_list [ + M.call (| + M.get_name (| globals, "buffer_read" |), + make_list [ + M.get_name (| globals, "data" |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 96 + ], + make_dict [] + |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 32 + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + BoolOp.and (| + Compare.not_eq (| + M.get_name (| globals, "v" |), + Constant.int 27 + |), + ltac:(M.monadic ( + Compare.not_eq (| + M.get_name (| globals, "v" |), + Constant.int 28 + |) + )) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + Constant.None_ + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + BoolOp.or (| + Compare.gt_e (| + Constant.int 0, + M.get_name (| globals, "r" |) + |), + ltac:(M.monadic ( + Compare.gt_e (| + M.get_name (| globals, "r" |), + M.get_name (| globals, "SECP256K1N" |) + |) + )) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + Constant.None_ + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + BoolOp.or (| + Compare.gt_e (| + Constant.int 0, + M.get_name (| globals, "s" |) + |), + ltac:(M.monadic ( + Compare.gt_e (| + M.get_name (| globals, "s" |), + M.get_name (| globals, "SECP256K1N" |) + |) + )) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + Constant.None_ + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in +(* At stmt: unsupported node type: Try *) + let _ := M.assign_local (| + "address" , + M.slice (| + M.call (| + M.get_name (| globals, "keccak256" |), + make_list [ + M.get_name (| globals, "public_key" |) + ], + make_dict [] + |), + Constant.int 12, + Constant.int 32, + Constant.None_ + |) + |) in + let _ := M.assign_local (| + "padded_address" , + M.call (| + M.get_name (| globals, "left_pad_zero_bytes" |), + make_list [ + M.get_name (| globals, "address" |); + Constant.int 32 + ], + make_dict [] + |) + |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, "evm" |), "output" |), + M.get_name (| globals, "padded_address" |) + |) in + M.pure Constant.None_)). diff --git a/CoqOfPython/ethereum/spurious_dragon/vm/precompiled_contracts/identity.v b/CoqOfPython/ethereum/spurious_dragon/vm/precompiled_contracts/identity.v new file mode 100644 index 0000000..c36d5ee --- /dev/null +++ b/CoqOfPython/ethereum/spurious_dragon/vm/precompiled_contracts/identity.v @@ -0,0 +1,94 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.spurious_dragon.vm.precompiled_contracts.identity". + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) IDENTITY PRECOMPILED CONTRACT +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementation of the `IDENTITY` precompiled contract. +". + +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". + +Axiom ethereum_utils_numeric_imports_ceil32 : + IsImported globals "ethereum.utils.numeric" "ceil32". + +Axiom ethereum_spurious_dragon_vm_imports_Evm : + IsImported globals "ethereum.spurious_dragon.vm" "Evm". + +Axiom ethereum_spurious_dragon_vm_gas_imports_GAS_IDENTITY : + IsImported globals "ethereum.spurious_dragon.vm.gas" "GAS_IDENTITY". +Axiom ethereum_spurious_dragon_vm_gas_imports_GAS_IDENTITY_WORD : + IsImported globals "ethereum.spurious_dragon.vm.gas" "GAS_IDENTITY_WORD". +Axiom ethereum_spurious_dragon_vm_gas_imports_charge_gas : + IsImported globals "ethereum.spurious_dragon.vm.gas" "charge_gas". + +Definition identity : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Writes the message data to output. + + Parameters + ---------- + evm : + The current EVM frame. + " in + let _ := M.assign_local (| + "data" , + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "data" |) + |) in + let _ := M.assign_local (| + "word_count" , + BinOp.floor_div (| + M.call (| + M.get_name (| globals, "ceil32" |), + make_list [ + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_name (| globals, "data" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |), + Constant.int 32 + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + BinOp.add (| + M.get_name (| globals, "GAS_IDENTITY" |), + BinOp.mult (| + M.get_name (| globals, "GAS_IDENTITY_WORD" |), + M.get_name (| globals, "word_count" |) + |) + |) + ], + make_dict [] + |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, "evm" |), "output" |), + M.get_name (| globals, "data" |) + |) in + M.pure Constant.None_)). diff --git a/CoqOfPython/ethereum/spurious_dragon/vm/precompiled_contracts/mapping.v b/CoqOfPython/ethereum/spurious_dragon/vm/precompiled_contracts/mapping.v new file mode 100644 index 0000000..cba9815 --- /dev/null +++ b/CoqOfPython/ethereum/spurious_dragon/vm/precompiled_contracts/mapping.v @@ -0,0 +1,49 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.spurious_dragon.vm.precompiled_contracts.mapping". + +Definition expr_1 : Value.t := + Constant.str " +Precompiled Contract Addresses +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Mapping of precompiled contracts their implementations. +". + +Axiom typing_imports_Callable : + IsImported globals "typing" "Callable". +Axiom typing_imports_Dict : + IsImported globals "typing" "Dict". + +Axiom ethereum_spurious_dragon_fork_types_imports_Address : + IsImported globals "ethereum.spurious_dragon.fork_types" "Address". + +Axiom ethereum_spurious_dragon_vm_precompiled_contracts_imports_ECRECOVER_ADDRESS : + IsImported globals "ethereum.spurious_dragon.vm.precompiled_contracts" "ECRECOVER_ADDRESS". +Axiom ethereum_spurious_dragon_vm_precompiled_contracts_imports_IDENTITY_ADDRESS : + IsImported globals "ethereum.spurious_dragon.vm.precompiled_contracts" "IDENTITY_ADDRESS". +Axiom ethereum_spurious_dragon_vm_precompiled_contracts_imports_RIPEMD160_ADDRESS : + IsImported globals "ethereum.spurious_dragon.vm.precompiled_contracts" "RIPEMD160_ADDRESS". +Axiom ethereum_spurious_dragon_vm_precompiled_contracts_imports_SHA256_ADDRESS : + IsImported globals "ethereum.spurious_dragon.vm.precompiled_contracts" "SHA256_ADDRESS". + +Axiom ethereum_spurious_dragon_vm_precompiled_contracts_ecrecover_imports_ecrecover : + IsImported globals "ethereum.spurious_dragon.vm.precompiled_contracts.ecrecover" "ecrecover". + +Axiom ethereum_spurious_dragon_vm_precompiled_contracts_identity_imports_identity : + IsImported globals "ethereum.spurious_dragon.vm.precompiled_contracts.identity" "identity". + +Axiom ethereum_spurious_dragon_vm_precompiled_contracts_ripemd160_imports_ripemd160 : + IsImported globals "ethereum.spurious_dragon.vm.precompiled_contracts.ripemd160" "ripemd160". + +Axiom ethereum_spurious_dragon_vm_precompiled_contracts_sha256_imports_sha256 : + IsImported globals "ethereum.spurious_dragon.vm.precompiled_contracts.sha256" "sha256". + +(* At top_level_stmt: unsupported node type: AnnAssign *) diff --git a/CoqOfPython/ethereum/spurious_dragon/vm/precompiled_contracts/ripemd160.v b/CoqOfPython/ethereum/spurious_dragon/vm/precompiled_contracts/ripemd160.v new file mode 100644 index 0000000..029a148 --- /dev/null +++ b/CoqOfPython/ethereum/spurious_dragon/vm/precompiled_contracts/ripemd160.v @@ -0,0 +1,125 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.spurious_dragon.vm.precompiled_contracts.ripemd160". + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) RIPEMD160 PRECOMPILED CONTRACT +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementation of the `RIPEMD160` precompiled contract. +". + +(* At top_level_stmt: unsupported node type: Import *) + +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". + +Axiom ethereum_utils_byte_imports_left_pad_zero_bytes : + IsImported globals "ethereum.utils.byte" "left_pad_zero_bytes". + +Axiom ethereum_utils_numeric_imports_ceil32 : + IsImported globals "ethereum.utils.numeric" "ceil32". + +Axiom ethereum_spurious_dragon_vm_imports_Evm : + IsImported globals "ethereum.spurious_dragon.vm" "Evm". + +Axiom ethereum_spurious_dragon_vm_gas_imports_GAS_RIPEMD160 : + IsImported globals "ethereum.spurious_dragon.vm.gas" "GAS_RIPEMD160". +Axiom ethereum_spurious_dragon_vm_gas_imports_GAS_RIPEMD160_WORD : + IsImported globals "ethereum.spurious_dragon.vm.gas" "GAS_RIPEMD160_WORD". +Axiom ethereum_spurious_dragon_vm_gas_imports_charge_gas : + IsImported globals "ethereum.spurious_dragon.vm.gas" "charge_gas". + +Definition ripemd160 : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Writes the ripemd160 hash to output. + + Parameters + ---------- + evm : + The current EVM frame. + " in + let _ := M.assign_local (| + "data" , + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "data" |) + |) in + let _ := M.assign_local (| + "word_count" , + BinOp.floor_div (| + M.call (| + M.get_name (| globals, "ceil32" |), + make_list [ + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_name (| globals, "data" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |), + Constant.int 32 + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + BinOp.add (| + M.get_name (| globals, "GAS_RIPEMD160" |), + BinOp.mult (| + M.get_name (| globals, "GAS_RIPEMD160_WORD" |), + M.get_name (| globals, "word_count" |) + |) + |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "hash_bytes" , + M.call (| + M.get_field (| M.call (| + M.get_field (| M.get_name (| globals, "hashlib" |), "new" |), + make_list [ + Constant.str "ripemd160"; + M.get_name (| globals, "data" |) + ], + make_dict [] + |), "digest" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "padded_hash" , + M.call (| + M.get_name (| globals, "left_pad_zero_bytes" |), + make_list [ + M.get_name (| globals, "hash_bytes" |); + Constant.int 32 + ], + make_dict [] + |) + |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, "evm" |), "output" |), + M.get_name (| globals, "padded_hash" |) + |) in + M.pure Constant.None_)). diff --git a/CoqOfPython/ethereum/spurious_dragon/vm/precompiled_contracts/sha256.v b/CoqOfPython/ethereum/spurious_dragon/vm/precompiled_contracts/sha256.v new file mode 100644 index 0000000..c155fe7 --- /dev/null +++ b/CoqOfPython/ethereum/spurious_dragon/vm/precompiled_contracts/sha256.v @@ -0,0 +1,106 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.spurious_dragon.vm.precompiled_contracts.sha256". + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) SHA256 PRECOMPILED CONTRACT +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementation of the `SHA256` precompiled contract. +". + +(* At top_level_stmt: unsupported node type: Import *) + +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". + +Axiom ethereum_utils_numeric_imports_ceil32 : + IsImported globals "ethereum.utils.numeric" "ceil32". + +Axiom ethereum_spurious_dragon_vm_imports_Evm : + IsImported globals "ethereum.spurious_dragon.vm" "Evm". + +Axiom ethereum_spurious_dragon_vm_gas_imports_GAS_SHA256 : + IsImported globals "ethereum.spurious_dragon.vm.gas" "GAS_SHA256". +Axiom ethereum_spurious_dragon_vm_gas_imports_GAS_SHA256_WORD : + IsImported globals "ethereum.spurious_dragon.vm.gas" "GAS_SHA256_WORD". +Axiom ethereum_spurious_dragon_vm_gas_imports_charge_gas : + IsImported globals "ethereum.spurious_dragon.vm.gas" "charge_gas". + +Definition sha256 : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Writes the sha256 hash to output. + + Parameters + ---------- + evm : + The current EVM frame. + " in + let _ := M.assign_local (| + "data" , + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "data" |) + |) in + let _ := M.assign_local (| + "word_count" , + BinOp.floor_div (| + M.call (| + M.get_name (| globals, "ceil32" |), + make_list [ + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_name (| globals, "data" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |), + Constant.int 32 + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + BinOp.add (| + M.get_name (| globals, "GAS_SHA256" |), + BinOp.mult (| + M.get_name (| globals, "GAS_SHA256_WORD" |), + M.get_name (| globals, "word_count" |) + |) + |) + ], + make_dict [] + |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, "evm" |), "output" |), + M.call (| + M.get_field (| M.call (| + M.get_field (| M.get_name (| globals, "hashlib" |), "sha256" |), + make_list [ + M.get_name (| globals, "data" |) + ], + make_dict [] + |), "digest" |), + make_list [], + make_dict [] + |) + |) in + M.pure Constant.None_)). diff --git a/CoqOfPython/ethereum/spurious_dragon/vm/runtime.v b/CoqOfPython/ethereum/spurious_dragon/vm/runtime.v new file mode 100644 index 0000000..9f6ecd8 --- /dev/null +++ b/CoqOfPython/ethereum/spurious_dragon/vm/runtime.v @@ -0,0 +1,157 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.spurious_dragon.vm.runtime". + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) Runtime Operations +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Runtime related operations used while executing EVM code. +". + +Axiom typing_imports_Set : + IsImported globals "typing" "Set". + +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". + +Axiom ethereum_spurious_dragon_vm_instructions_imports_Ops : + IsImported globals "ethereum.spurious_dragon.vm.instructions" "Ops". + +Definition get_valid_jump_destinations : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "code" ] |) in + let _ := Constant.str " + Analyze the evm code to obtain the set of valid jump destinations. + + Valid jump destinations are defined as follows: + * The jump destination is less than the length of the code. + * The jump destination should have the `JUMPDEST` opcode (0x5B). + * The jump destination shouldn't be part of the data corresponding to + `PUSH-N` opcodes. + + Note - Jump destinations are 0-indexed. + + Parameters + ---------- + code : + The EVM code which is to be executed. + + Returns + ------- + valid_jump_destinations: `Set[Uint]` + The set of valid jump destinations in the code. + " in + let _ := M.assign_local (| + "valid_jump_destinations" , + M.call (| + M.get_name (| globals, "set" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "pc" , + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + |) in + let _ := + M.while (| + Compare.lt (| + M.get_name (| globals, "pc" |), + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_name (| globals, "code" |) + ], + make_dict [] + |) + |), + ltac:(M.monadic ( +(* At stmt: unsupported node type: Try *) + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, "current_opcode" |), + M.get_field (| M.get_name (| globals, "Ops" |), "JUMPDEST" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_field (| M.get_name (| globals, "valid_jump_destinations" |), "add" |), + make_list [ + M.get_name (| globals, "pc" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + BoolOp.and (| + Compare.lt_e (| + M.get_field (| M.get_field (| M.get_name (| globals, "Ops" |), "PUSH1" |), "value" |), + M.get_field (| M.get_name (| globals, "current_opcode" |), "value" |) + |), + ltac:(M.monadic ( + Compare.lt_e (| + M.get_field (| M.get_name (| globals, "current_opcode" |), "value" |), + M.get_field (| M.get_field (| M.get_name (| globals, "Ops" |), "PUSH32" |), "value" |) + |) + )) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "push_data_size" , + BinOp.add (| + BinOp.sub (| + M.get_field (| M.get_name (| globals, "current_opcode" |), "value" |), + M.get_field (| M.get_field (| M.get_name (| globals, "Ops" |), "PUSH1" |), "value" |) + |), + Constant.int 1 + |) + |) in + let _ := M.assign_op_local (| + BinOp.add, + "pc", + M.get_name (| globals, "push_data_size" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )) |) in + let _ := M.assign_op_local (| + BinOp.add, + "pc", + Constant.int 1 + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := M.return_ (| + M.get_name (| globals, "valid_jump_destinations" |) + |) in + M.pure Constant.None_)). diff --git a/CoqOfPython/ethereum/spurious_dragon/vm/stack.v b/CoqOfPython/ethereum/spurious_dragon/vm/stack.v new file mode 100644 index 0000000..b6fb48a --- /dev/null +++ b/CoqOfPython/ethereum/spurious_dragon/vm/stack.v @@ -0,0 +1,123 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.spurious_dragon.vm.stack". + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) Stack +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementation of the stack operators for the EVM. +". + +Axiom typing_imports_List : + IsImported globals "typing" "List". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". + +Axiom ethereum_spurious_dragon_vm_exceptions_imports_StackOverflowError : + IsImported globals "ethereum.spurious_dragon.vm.exceptions" "StackOverflowError". +Axiom ethereum_spurious_dragon_vm_exceptions_imports_StackUnderflowError : + IsImported globals "ethereum.spurious_dragon.vm.exceptions" "StackUnderflowError". + +Definition pop : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "stack" ] |) in + let _ := Constant.str " + Pops the top item off of `stack`. + + Parameters + ---------- + stack : + EVM stack. + + Returns + ------- + value : `U256` + The top element on the stack. + + " in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_name (| globals, "stack" |) + ], + make_dict [] + |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, "StackUnderflowError" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.return_ (| + M.call (| + M.get_field (| M.get_name (| globals, "stack" |), "pop" |), + make_list [], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Definition push : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "stack"; "value" ] |) in + let _ := Constant.str " + Pushes `value` onto `stack`. + + Parameters + ---------- + stack : + EVM stack. + + value : + Item to be pushed onto `stack`. + + " in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_name (| globals, "stack" |) + ], + make_dict [] + |), + Constant.int 1024 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, "StackOverflowError" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.return_ (| + M.call (| + M.get_field (| M.get_name (| globals, "stack" |), "append" |), + make_list [ + M.get_name (| globals, "value" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). diff --git a/CoqOfPython/ethereum/tangerine_whistle/__init__.v b/CoqOfPython/ethereum/tangerine_whistle/__init__.v new file mode 100644 index 0000000..fd543a7 --- /dev/null +++ b/CoqOfPython/ethereum/tangerine_whistle/__init__.v @@ -0,0 +1,24 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.tangerine_whistle.__init__". + +Definition expr_1 : Value.t := + Constant.str " +The Tangerine Whistle fork is the first of two forks responding to a +denial-of-service attack on the Ethereum network. It tunes the price of various +EVM instructions, and reduces the state size by removing a number of empty +accounts. +". + +Axiom ethereum_fork_criteria_imports_ByBlockNumber : + IsImported globals "ethereum.fork_criteria" "ByBlockNumber". + +Definition FORK_CRITERIA : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "ByBlockNumber" |), + make_list [ + Constant.int 2463000 + ], + make_dict [] + |) +)). diff --git a/CoqOfPython/ethereum/tangerine_whistle/blocks.v b/CoqOfPython/ethereum/tangerine_whistle/blocks.v new file mode 100644 index 0000000..b921a0d --- /dev/null +++ b/CoqOfPython/ethereum/tangerine_whistle/blocks.v @@ -0,0 +1,87 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.tangerine_whistle.blocks". + +Definition expr_1 : Value.t := + Constant.str " +A `Block` is a single link in the chain that is Ethereum. Each `Block` contains +a `Header` and zero or more transactions. Each `Header` contains associated +metadata like the block number, parent block hash, and how much gas was +consumed by its transactions. + +Together, these blocks form a cryptographically secure journal recording the +history of all state transitions that have happened since the genesis of the +chain. +". + +Axiom dataclasses_imports_dataclass : + IsImported globals "dataclasses" "dataclass". + +Axiom typing_imports_Tuple : + IsImported globals "typing" "Tuple". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_Bytes : + IsImported globals "ethereum.base_types" "Bytes". +Axiom ethereum_base_types_imports_Bytes8 : + IsImported globals "ethereum.base_types" "Bytes8". +Axiom ethereum_base_types_imports_Bytes32 : + IsImported globals "ethereum.base_types" "Bytes32". +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". +Axiom ethereum_base_types_imports_slotted_freezable : + IsImported globals "ethereum.base_types" "slotted_freezable". + +Axiom ethereum_crypto_hash_imports_Hash32 : + IsImported globals "ethereum.crypto.hash" "Hash32". + +Axiom ethereum_tangerine_whistle_fork_types_imports_Address : + IsImported globals "ethereum.tangerine_whistle.fork_types" "Address". +Axiom ethereum_tangerine_whistle_fork_types_imports_Bloom : + IsImported globals "ethereum.tangerine_whistle.fork_types" "Bloom". +Axiom ethereum_tangerine_whistle_fork_types_imports_Root : + IsImported globals "ethereum.tangerine_whistle.fork_types" "Root". + +Axiom ethereum_tangerine_whistle_transactions_imports_Transaction : + IsImported globals "ethereum.tangerine_whistle.transactions" "Transaction". + +Definition Header : Value.t := + builtins.make_klass + [] + [ + + ] + [ + + ]. + +Definition Block : Value.t := + builtins.make_klass + [] + [ + + ] + [ + + ]. + +Definition Log : Value.t := + builtins.make_klass + [] + [ + + ] + [ + + ]. + +Definition Receipt : Value.t := + builtins.make_klass + [] + [ + + ] + [ + + ]. diff --git a/CoqOfPython/ethereum/tangerine_whistle/bloom.v b/CoqOfPython/ethereum/tangerine_whistle/bloom.v new file mode 100644 index 0000000..ccf56cd --- /dev/null +++ b/CoqOfPython/ethereum/tangerine_whistle/bloom.v @@ -0,0 +1,207 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.tangerine_whistle.bloom". + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Logs Bloom +^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +This modules defines functions for calculating bloom filters of logs. For the +general theory of bloom filters see e.g. `Wikipedia +`_. Bloom filters are used to allow +for efficient searching of logs by address and/or topic, by rapidly +eliminating blocks and receipts from their search. +". + +Axiom typing_imports_Tuple : + IsImported globals "typing" "Tuple". + +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". + +Axiom ethereum_crypto_hash_imports_keccak256 : + IsImported globals "ethereum.crypto.hash" "keccak256". + +Axiom ethereum_tangerine_whistle_blocks_imports_Log : + IsImported globals "ethereum.tangerine_whistle.blocks" "Log". + +Axiom ethereum_tangerine_whistle_fork_types_imports_Bloom : + IsImported globals "ethereum.tangerine_whistle.fork_types" "Bloom". + +Definition add_to_bloom : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "bloom"; "bloom_entry" ] |) in + let _ := Constant.str " + Add a bloom entry to the bloom filter (`bloom`). + + The number of hash functions used is 3. They are calculated by taking the + least significant 11 bits from the first 3 16-bit words of the + `keccak_256()` hash of `bloom_entry`. + + Parameters + ---------- + bloom : + The bloom filter. + bloom_entry : + An entry which is to be added to bloom filter. + " in + let _ := M.assign_local (| + "hash" , + M.call (| + M.get_name (| globals, "keccak256" |), + make_list [ + M.get_name (| globals, "bloom_entry" |) + ], + make_dict [] + |) + |) in + let _ := + M.for_ (| + M.get_name (| globals, "idx" |), + make_tuple [ Constant.int 0; Constant.int 2; Constant.int 4 ], + ltac:(M.monadic ( + let _ := M.assign_local (| + "bit_to_set" , + BinOp.bit_and (| + M.call (| + M.get_field (| M.get_name (| globals, "Uint" |), "from_be_bytes" |), + make_list [ + M.slice (| + M.get_name (| globals, "hash" |), + M.get_name (| globals, "idx" |), + BinOp.add (| + M.get_name (| globals, "idx" |), + Constant.int 2 + |), + Constant.None_ + |) + ], + make_dict [] + |), + Constant.int 2047 + |) + |) in + let _ := M.assign_local (| + "bit_index" , + BinOp.sub (| + Constant.int 2047, + M.get_name (| globals, "bit_to_set" |) + |) + |) in + let _ := M.assign_local (| + "byte_index" , + BinOp.floor_div (| + M.get_name (| globals, "bit_index" |), + Constant.int 8 + |) + |) in + let _ := M.assign_local (| + "bit_value" , + BinOp.l_shift (| + Constant.int 1, + BinOp.sub (| + Constant.int 7, + BinOp.mod_ (| + M.get_name (| globals, "bit_index" |), + Constant.int 8 + |) + |) + |) + |) in + let _ := M.assign (| + M.get_subscript (| + M.get_name (| globals, "bloom" |), + M.get_name (| globals, "byte_index" |) + |), + BinOp.bit_or (| + M.get_subscript (| + M.get_name (| globals, "bloom" |), + M.get_name (| globals, "byte_index" |) + |), + M.get_name (| globals, "bit_value" |) + |) + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + M.pure Constant.None_)). + +Definition logs_bloom : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "logs" ] |) in + let _ := Constant.str " + Obtain the logs bloom from a list of log entries. + + The address and each topic of a log are added to the bloom filter. + + Parameters + ---------- + logs : + List of logs for which the logs bloom is to be obtained. + + Returns + ------- + logs_bloom : `Bloom` + The logs bloom obtained which is 256 bytes with some bits set as per + the caller address and the log topics. + " in +(* At stmt: unsupported node type: AnnAssign *) + let _ := + M.for_ (| + M.get_name (| globals, "log" |), + M.get_name (| globals, "logs" |), + ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, "add_to_bloom" |), + make_list [ + M.get_name (| globals, "bloom" |); + M.get_field (| M.get_name (| globals, "log" |), "address" |) + ], + make_dict [] + |) in + let _ := + M.for_ (| + M.get_name (| globals, "topic" |), + M.get_field (| M.get_name (| globals, "log" |), "topics" |), + ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, "add_to_bloom" |), + make_list [ + M.get_name (| globals, "bloom" |); + M.get_name (| globals, "topic" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, "Bloom" |), + make_list [ + M.get_name (| globals, "bloom" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). diff --git a/CoqOfPython/ethereum/tangerine_whistle/fork.v b/CoqOfPython/ethereum/tangerine_whistle/fork.v new file mode 100644 index 0000000..bc0e99d --- /dev/null +++ b/CoqOfPython/ethereum/tangerine_whistle/fork.v @@ -0,0 +1,2427 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.tangerine_whistle.fork". + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Specification +^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Entry point for the Ethereum specification. +". + +Axiom dataclasses_imports_dataclass : + IsImported globals "dataclasses" "dataclass". + +Axiom typing_imports_List : + IsImported globals "typing" "List". +Axiom typing_imports_Optional : + IsImported globals "typing" "Optional". +Axiom typing_imports_Set : + IsImported globals "typing" "Set". +Axiom typing_imports_Tuple : + IsImported globals "typing" "Tuple". + +Axiom ethereum_base_types_imports_Bytes0 : + IsImported globals "ethereum.base_types" "Bytes0". + +Axiom ethereum_crypto_elliptic_curve_imports_SECP256K1N : + IsImported globals "ethereum.crypto.elliptic_curve" "SECP256K1N". +Axiom ethereum_crypto_elliptic_curve_imports_secp256k1_recover : + IsImported globals "ethereum.crypto.elliptic_curve" "secp256k1_recover". + +Axiom ethereum_crypto_hash_imports_Hash32 : + IsImported globals "ethereum.crypto.hash" "Hash32". +Axiom ethereum_crypto_hash_imports_keccak256 : + IsImported globals "ethereum.crypto.hash" "keccak256". + +Axiom ethereum_ethash_imports_dataset_size : + IsImported globals "ethereum.ethash" "dataset_size". +Axiom ethereum_ethash_imports_generate_cache : + IsImported globals "ethereum.ethash" "generate_cache". +Axiom ethereum_ethash_imports_hashimoto_light : + IsImported globals "ethereum.ethash" "hashimoto_light". + +Axiom ethereum_exceptions_imports_InvalidBlock : + IsImported globals "ethereum.exceptions" "InvalidBlock". + +Axiom ethereum_utils_ensure_imports_ensure : + IsImported globals "ethereum.utils.ensure" "ensure". + +Axiom ethereum_imports_rlp : + IsImported globals "ethereum" "rlp". + +Axiom ethereum_base_types_imports_U64 : + IsImported globals "ethereum.base_types" "U64". +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_U256_CEIL_VALUE : + IsImported globals "ethereum.base_types" "U256_CEIL_VALUE". +Axiom ethereum_base_types_imports_Bytes : + IsImported globals "ethereum.base_types" "Bytes". +Axiom ethereum_base_types_imports_Bytes32 : + IsImported globals "ethereum.base_types" "Bytes32". +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". + +Axiom ethereum_tangerine_whistle_imports_vm : + IsImported globals "ethereum.tangerine_whistle" "vm". + +Axiom ethereum_tangerine_whistle_blocks_imports_Block : + IsImported globals "ethereum.tangerine_whistle.blocks" "Block". +Axiom ethereum_tangerine_whistle_blocks_imports_Header : + IsImported globals "ethereum.tangerine_whistle.blocks" "Header". +Axiom ethereum_tangerine_whistle_blocks_imports_Log : + IsImported globals "ethereum.tangerine_whistle.blocks" "Log". +Axiom ethereum_tangerine_whistle_blocks_imports_Receipt : + IsImported globals "ethereum.tangerine_whistle.blocks" "Receipt". + +Axiom ethereum_tangerine_whistle_bloom_imports_logs_bloom : + IsImported globals "ethereum.tangerine_whistle.bloom" "logs_bloom". + +Axiom ethereum_tangerine_whistle_fork_types_imports_Address : + IsImported globals "ethereum.tangerine_whistle.fork_types" "Address". +Axiom ethereum_tangerine_whistle_fork_types_imports_Bloom : + IsImported globals "ethereum.tangerine_whistle.fork_types" "Bloom". +Axiom ethereum_tangerine_whistle_fork_types_imports_Root : + IsImported globals "ethereum.tangerine_whistle.fork_types" "Root". + +Axiom ethereum_tangerine_whistle_state_imports_State : + IsImported globals "ethereum.tangerine_whistle.state" "State". +Axiom ethereum_tangerine_whistle_state_imports_create_ether : + IsImported globals "ethereum.tangerine_whistle.state" "create_ether". +Axiom ethereum_tangerine_whistle_state_imports_destroy_account : + IsImported globals "ethereum.tangerine_whistle.state" "destroy_account". +Axiom ethereum_tangerine_whistle_state_imports_get_account : + IsImported globals "ethereum.tangerine_whistle.state" "get_account". +Axiom ethereum_tangerine_whistle_state_imports_increment_nonce : + IsImported globals "ethereum.tangerine_whistle.state" "increment_nonce". +Axiom ethereum_tangerine_whistle_state_imports_set_account_balance : + IsImported globals "ethereum.tangerine_whistle.state" "set_account_balance". +Axiom ethereum_tangerine_whistle_state_imports_state_root : + IsImported globals "ethereum.tangerine_whistle.state" "state_root". + +Axiom ethereum_tangerine_whistle_transactions_imports_TX_BASE_COST : + IsImported globals "ethereum.tangerine_whistle.transactions" "TX_BASE_COST". +Axiom ethereum_tangerine_whistle_transactions_imports_TX_CREATE_COST : + IsImported globals "ethereum.tangerine_whistle.transactions" "TX_CREATE_COST". +Axiom ethereum_tangerine_whistle_transactions_imports_TX_DATA_COST_PER_NON_ZERO : + IsImported globals "ethereum.tangerine_whistle.transactions" "TX_DATA_COST_PER_NON_ZERO". +Axiom ethereum_tangerine_whistle_transactions_imports_TX_DATA_COST_PER_ZERO : + IsImported globals "ethereum.tangerine_whistle.transactions" "TX_DATA_COST_PER_ZERO". +Axiom ethereum_tangerine_whistle_transactions_imports_Transaction : + IsImported globals "ethereum.tangerine_whistle.transactions" "Transaction". + +Axiom ethereum_tangerine_whistle_trie_imports_Trie : + IsImported globals "ethereum.tangerine_whistle.trie" "Trie". +Axiom ethereum_tangerine_whistle_trie_imports_root : + IsImported globals "ethereum.tangerine_whistle.trie" "root". +Axiom ethereum_tangerine_whistle_trie_imports_trie_set : + IsImported globals "ethereum.tangerine_whistle.trie" "trie_set". + +Axiom ethereum_tangerine_whistle_utils_message_imports_prepare_message : + IsImported globals "ethereum.tangerine_whistle.utils.message" "prepare_message". + +Axiom ethereum_tangerine_whistle_vm_interpreter_imports_process_message_call : + IsImported globals "ethereum.tangerine_whistle.vm.interpreter" "process_message_call". + +Definition BLOCK_REWARD : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + BinOp.mult (| + Constant.int 5, + BinOp.pow (| + Constant.int 10, + Constant.int 18 + |) + |) + ], + make_dict [] + |) +)). + +Definition GAS_LIMIT_ADJUSTMENT_FACTOR : Value.t := M.run ltac:(M.monadic ( + Constant.int 1024 +)). + +Definition GAS_LIMIT_MINIMUM : Value.t := M.run ltac:(M.monadic ( + Constant.int 5000 +)). + +Definition MINIMUM_DIFFICULTY : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 131072 + ], + make_dict [] + |) +)). + +Definition MAX_OMMER_DEPTH : Value.t := M.run ltac:(M.monadic ( + Constant.int 6 +)). + +Definition BlockChain : Value.t := + builtins.make_klass + [] + [ + + ] + [ + + ]. + +Definition apply_fork : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "old" ] |) in + let _ := Constant.str " + Transforms the state from the previous hard fork (`old`) into the block + chain object for this hard fork and returns it. + + When forks need to implement an irregular state transition, this function + is used to handle the irregularity. See the :ref:`DAO Fork ` for + an example. + + Parameters + ---------- + old : + Previous block chain object. + + Returns + ------- + new : `BlockChain` + Upgraded block chain object for this hard fork. + " in + let _ := M.return_ (| + M.get_name (| globals, "old" |) + |) in + M.pure Constant.None_)). + +Definition get_last_256_block_hashes : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "chain" ] |) in + let _ := Constant.str " + Obtain the list of hashes of the previous 256 blocks in order of + increasing block number. + + This function will return less hashes for the first 256 blocks. + + The ``BLOCKHASH`` opcode needs to access the latest hashes on the chain, + therefore this function retrieves them. + + Parameters + ---------- + chain : + History and current state. + + Returns + ------- + recent_block_hashes : `List[Hash32]` + Hashes of the recent 256 blocks in order of increasing block number. + " in + let _ := M.assign_local (| + "recent_blocks" , + M.slice (| + M.get_field (| M.get_name (| globals, "chain" |), "blocks" |), + UnOp.sub (| Constant.int 255 |), + Constant.None_, + Constant.None_ + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_name (| globals, "recent_blocks" |) + ], + make_dict [] + |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + make_list [] + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "recent_block_hashes" , + make_list [] + |) in + let _ := + M.for_ (| + M.get_name (| globals, "block" |), + M.get_name (| globals, "recent_blocks" |), + ltac:(M.monadic ( + let _ := M.assign_local (| + "prev_block_hash" , + M.get_field (| M.get_field (| M.get_name (| globals, "block" |), "header" |), "parent_hash" |) + |) in + let _ := M.call (| + M.get_field (| M.get_name (| globals, "recent_block_hashes" |), "append" |), + make_list [ + M.get_name (| globals, "prev_block_hash" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := M.assign_local (| + "most_recent_block_hash" , + M.call (| + M.get_name (| globals, "keccak256" |), + make_list [ + M.call (| + M.get_field (| M.get_name (| globals, "rlp" |), "encode" |), + make_list [ + M.get_field (| M.get_subscript (| + M.get_name (| globals, "recent_blocks" |), + UnOp.sub (| Constant.int 1 |) + |), "header" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_field (| M.get_name (| globals, "recent_block_hashes" |), "append" |), + make_list [ + M.get_name (| globals, "most_recent_block_hash" |) + ], + make_dict [] + |) in + let _ := M.return_ (| + M.get_name (| globals, "recent_block_hashes" |) + |) in + M.pure Constant.None_)). + +Definition state_transition : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "chain"; "block" ] |) in + let _ := Constant.str " + Attempts to apply a block to an existing block chain. + + All parts of the block's contents need to be verified before being added + to the chain. Blocks are verified by ensuring that the contents of the + block make logical sense with the contents of the parent block. The + information in the block's header must also match the corresponding + information in the block. + + To implement Ethereum, in theory clients are only required to store the + most recent 255 blocks of the chain since as far as execution is + concerned, only those blocks are accessed. Practically, however, clients + should store more blocks to handle reorgs. + + Parameters + ---------- + chain : + History and current state. + block : + Block to apply to `chain`. + " in + let _ := M.assign_local (| + "parent_header" , + M.get_field (| M.get_subscript (| + M.get_field (| M.get_name (| globals, "chain" |), "blocks" |), + UnOp.sub (| Constant.int 1 |) + |), "header" |) + |) in + let _ := M.call (| + M.get_name (| globals, "validate_header" |), + make_list [ + M.get_field (| M.get_name (| globals, "block" |), "header" |); + M.get_name (| globals, "parent_header" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "validate_ommers" |), + make_list [ + M.get_field (| M.get_name (| globals, "block" |), "ommers" |); + M.get_field (| M.get_name (| globals, "block" |), "header" |); + M.get_name (| globals, "chain" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "apply_body_output" , + M.call (| + M.get_name (| globals, "apply_body" |), + make_list [ + M.get_field (| M.get_name (| globals, "chain" |), "state" |); + M.call (| + M.get_name (| globals, "get_last_256_block_hashes" |), + make_list [ + M.get_name (| globals, "chain" |) + ], + make_dict [] + |); + M.get_field (| M.get_field (| M.get_name (| globals, "block" |), "header" |), "coinbase" |); + M.get_field (| M.get_field (| M.get_name (| globals, "block" |), "header" |), "number" |); + M.get_field (| M.get_field (| M.get_name (| globals, "block" |), "header" |), "gas_limit" |); + M.get_field (| M.get_field (| M.get_name (| globals, "block" |), "header" |), "timestamp" |); + M.get_field (| M.get_field (| M.get_name (| globals, "block" |), "header" |), "difficulty" |); + M.get_field (| M.get_name (| globals, "block" |), "transactions" |); + M.get_field (| M.get_name (| globals, "block" |), "ommers" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + Compare.eq (| + M.get_field (| M.get_name (| globals, "apply_body_output" |), "block_gas_used" |), + M.get_field (| M.get_field (| M.get_name (| globals, "block" |), "header" |), "gas_used" |) + |); + M.get_name (| globals, "InvalidBlock" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + Compare.eq (| + M.get_field (| M.get_name (| globals, "apply_body_output" |), "transactions_root" |), + M.get_field (| M.get_field (| M.get_name (| globals, "block" |), "header" |), "transactions_root" |) + |); + M.get_name (| globals, "InvalidBlock" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + Compare.eq (| + M.get_field (| M.get_name (| globals, "apply_body_output" |), "state_root" |), + M.get_field (| M.get_field (| M.get_name (| globals, "block" |), "header" |), "state_root" |) + |); + M.get_name (| globals, "InvalidBlock" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + Compare.eq (| + M.get_field (| M.get_name (| globals, "apply_body_output" |), "receipt_root" |), + M.get_field (| M.get_field (| M.get_name (| globals, "block" |), "header" |), "receipt_root" |) + |); + M.get_name (| globals, "InvalidBlock" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + Compare.eq (| + M.get_field (| M.get_name (| globals, "apply_body_output" |), "block_logs_bloom" |), + M.get_field (| M.get_field (| M.get_name (| globals, "block" |), "header" |), "bloom" |) + |); + M.get_name (| globals, "InvalidBlock" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, "chain" |), "blocks" |), "append" |), + make_list [ + M.get_name (| globals, "block" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.gt (| + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_field (| M.get_name (| globals, "chain" |), "blocks" |) + ], + make_dict [] + |), + Constant.int 255 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign (| + M.get_field (| M.get_name (| globals, "chain" |), "blocks" |), + M.slice (| + M.get_field (| M.get_name (| globals, "chain" |), "blocks" |), + UnOp.sub (| Constant.int 255 |), + Constant.None_, + Constant.None_ + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + M.pure Constant.None_)). + +Definition validate_header : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "header"; "parent_header" ] |) in + let _ := Constant.str " + Verifies a block header. + + In order to consider a block's header valid, the logic for the + quantities in the header should match the logic for the block itself. + For example the header timestamp should be greater than the block's parent + timestamp because the block was created *after* the parent block. + Additionally, the block's number should be directly following the parent + block's number since it is the next block in the sequence. + + Parameters + ---------- + header : + Header to check for correctness. + parent_header : + Parent Header of the header to check for correctness + " in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + Compare.gt (| + M.get_field (| M.get_name (| globals, "header" |), "timestamp" |), + M.get_field (| M.get_name (| globals, "parent_header" |), "timestamp" |) + |); + M.get_name (| globals, "InvalidBlock" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + Compare.eq (| + M.get_field (| M.get_name (| globals, "header" |), "number" |), + BinOp.add (| + M.get_field (| M.get_name (| globals, "parent_header" |), "number" |), + Constant.int 1 + |) + |); + M.get_name (| globals, "InvalidBlock" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + M.call (| + M.get_name (| globals, "check_gas_limit" |), + make_list [ + M.get_field (| M.get_name (| globals, "header" |), "gas_limit" |); + M.get_field (| M.get_name (| globals, "parent_header" |), "gas_limit" |) + ], + make_dict [] + |); + M.get_name (| globals, "InvalidBlock" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + Compare.lt_e (| + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_field (| M.get_name (| globals, "header" |), "extra_data" |) + ], + make_dict [] + |), + Constant.int 32 + |); + M.get_name (| globals, "InvalidBlock" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "block_difficulty" , + M.call (| + M.get_name (| globals, "calculate_block_difficulty" |), + make_list [ + M.get_field (| M.get_name (| globals, "header" |), "number" |); + M.get_field (| M.get_name (| globals, "header" |), "timestamp" |); + M.get_field (| M.get_name (| globals, "parent_header" |), "timestamp" |); + M.get_field (| M.get_name (| globals, "parent_header" |), "difficulty" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + Compare.eq (| + M.get_field (| M.get_name (| globals, "header" |), "difficulty" |), + M.get_name (| globals, "block_difficulty" |) + |); + M.get_name (| globals, "InvalidBlock" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "block_parent_hash" , + M.call (| + M.get_name (| globals, "keccak256" |), + make_list [ + M.call (| + M.get_field (| M.get_name (| globals, "rlp" |), "encode" |), + make_list [ + M.get_name (| globals, "parent_header" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + Compare.eq (| + M.get_field (| M.get_name (| globals, "header" |), "parent_hash" |), + M.get_name (| globals, "block_parent_hash" |) + |); + M.get_name (| globals, "InvalidBlock" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "validate_proof_of_work" |), + make_list [ + M.get_name (| globals, "header" |) + ], + make_dict [] + |) in + M.pure Constant.None_)). + +Definition generate_header_hash_for_pow : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "header" ] |) in + let _ := Constant.str " + Generate rlp hash of the header which is to be used for Proof-of-Work + verification. + + In other words, the PoW artefacts `mix_digest` and `nonce` are ignored + while calculating this hash. + + A particular PoW is valid for a single hash, that hash is computed by + this function. The `nonce` and `mix_digest` are omitted from this hash + because they are being changed by miners in their search for a sufficient + proof-of-work. + + Parameters + ---------- + header : + The header object for which the hash is to be generated. + + Returns + ------- + hash : `Hash32` + The PoW valid rlp hash of the passed in header. + " in + let _ := M.assign_local (| + "header_data_without_pow_artefacts" , + make_list [ + M.get_field (| M.get_name (| globals, "header" |), "parent_hash" |); + M.get_field (| M.get_name (| globals, "header" |), "ommers_hash" |); + M.get_field (| M.get_name (| globals, "header" |), "coinbase" |); + M.get_field (| M.get_name (| globals, "header" |), "state_root" |); + M.get_field (| M.get_name (| globals, "header" |), "transactions_root" |); + M.get_field (| M.get_name (| globals, "header" |), "receipt_root" |); + M.get_field (| M.get_name (| globals, "header" |), "bloom" |); + M.get_field (| M.get_name (| globals, "header" |), "difficulty" |); + M.get_field (| M.get_name (| globals, "header" |), "number" |); + M.get_field (| M.get_name (| globals, "header" |), "gas_limit" |); + M.get_field (| M.get_name (| globals, "header" |), "gas_used" |); + M.get_field (| M.get_name (| globals, "header" |), "timestamp" |); + M.get_field (| M.get_name (| globals, "header" |), "extra_data" |) + ] + |) in + let _ := M.return_ (| + M.call (| + M.get_field (| M.get_name (| globals, "rlp" |), "rlp_hash" |), + make_list [ + M.get_name (| globals, "header_data_without_pow_artefacts" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Definition validate_proof_of_work : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "header" ] |) in + let _ := Constant.str " + Validates the Proof of Work constraints. + + In order to verify that a miner's proof-of-work is valid for a block, a + ``mix-digest`` and ``result`` are calculated using the ``hashimoto_light`` + hash function. The mix digest is a hash of the header and the nonce that + is passed through and it confirms whether or not proof-of-work was done + on the correct block. The result is the actual hash value of the block. + + Parameters + ---------- + header : + Header of interest. + " in + let _ := M.assign_local (| + "header_hash" , + M.call (| + M.get_name (| globals, "generate_header_hash_for_pow" |), + make_list [ + M.get_name (| globals, "header" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "cache" , + M.call (| + M.get_name (| globals, "generate_cache" |), + make_list [ + M.get_field (| M.get_name (| globals, "header" |), "number" |) + ], + make_dict [] + |) + |) in + let _ := M.assign (| + make_tuple [ M.get_name (| globals, "mix_digest" |); M.get_name (| globals, "result" |) ], + M.call (| + M.get_name (| globals, "hashimoto_light" |), + make_list [ + M.get_name (| globals, "header_hash" |); + M.get_field (| M.get_name (| globals, "header" |), "nonce" |); + M.get_name (| globals, "cache" |); + M.call (| + M.get_name (| globals, "dataset_size" |), + make_list [ + M.get_field (| M.get_name (| globals, "header" |), "number" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + Compare.eq (| + M.get_name (| globals, "mix_digest" |), + M.get_field (| M.get_name (| globals, "header" |), "mix_digest" |) + |); + M.get_name (| globals, "InvalidBlock" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + Compare.lt_e (| + M.call (| + M.get_field (| M.get_name (| globals, "Uint" |), "from_be_bytes" |), + make_list [ + M.get_name (| globals, "result" |) + ], + make_dict [] + |), + BinOp.floor_div (| + M.get_name (| globals, "U256_CEIL_VALUE" |), + M.get_field (| M.get_name (| globals, "header" |), "difficulty" |) + |) + |); + M.get_name (| globals, "InvalidBlock" |) + ], + make_dict [] + |) in + M.pure Constant.None_)). + +Definition check_transaction : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "tx"; "gas_available" ] |) in + let _ := Constant.str " + Check if the transaction is includable in the block. + + Parameters + ---------- + tx : + The transaction. + gas_available : + The gas remaining in the block. + + Returns + ------- + sender_address : + The sender of the transaction. + + Raises + ------ + InvalidBlock : + If the transaction is not includable. + " in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + Compare.lt_e (| + M.get_field (| M.get_name (| globals, "tx" |), "gas" |), + M.get_name (| globals, "gas_available" |) + |); + M.get_name (| globals, "InvalidBlock" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "sender_address" , + M.call (| + M.get_name (| globals, "recover_sender" |), + make_list [ + M.get_name (| globals, "tx" |) + ], + make_dict [] + |) + |) in + let _ := M.return_ (| + M.get_name (| globals, "sender_address" |) + |) in + M.pure Constant.None_)). + +Definition make_receipt : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "tx"; "post_state"; "cumulative_gas_used"; "logs" ] |) in + let _ := Constant.str " + Make the receipt for a transaction that was executed. + + Parameters + ---------- + tx : + The executed transaction. + post_state : + The state root immediately after this transaction. + cumulative_gas_used : + The total gas used so far in the block after the transaction was + executed. + logs : + The logs produced by the transaction. + + Returns + ------- + receipt : + The receipt for the transaction. + " in + let _ := M.assign_local (| + "receipt" , + M.call (| + M.get_name (| globals, "Receipt" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.return_ (| + M.get_name (| globals, "receipt" |) + |) in + M.pure Constant.None_)). + +Definition ApplyBodyOutput : Value.t := + builtins.make_klass + [] + [ + + ] + [ + + ]. + +Definition apply_body : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "state"; "block_hashes"; "coinbase"; "block_number"; "block_gas_limit"; "block_time"; "block_difficulty"; "transactions"; "ommers" ] |) in + let _ := Constant.str " + Executes a block. + + Many of the contents of a block are stored in data structures called + tries. There is a transactions trie which is similar to a ledger of the + transactions stored in the current block. There is also a receipts trie + which stores the results of executing a transaction, like the post state + and gas used. This function creates and executes the block that is to be + added to the chain. + + Parameters + ---------- + state : + Current account state. + block_hashes : + List of hashes of the previous 256 blocks in the order of + increasing block number. + coinbase : + Address of account which receives block reward and transaction fees. + block_number : + Position of the block within the chain. + block_gas_limit : + Initial amount of gas available for execution in this block. + block_time : + Time the block was produced, measured in seconds since the epoch. + block_difficulty : + Difficulty of the block. + transactions : + Transactions included in the block. + ommers : + Headers of ancestor blocks which are not direct parents (formerly + uncles.) + + Returns + ------- + apply_body_output : `ApplyBodyOutput` + Output of applying the block body to the state. + " in + let _ := M.assign_local (| + "gas_available" , + M.get_name (| globals, "block_gas_limit" |) + |) in +(* At stmt: unsupported node type: AnnAssign *) +(* At stmt: unsupported node type: AnnAssign *) +(* At stmt: unsupported node type: AnnAssign *) + let _ := + M.for_ (| + make_tuple [ M.get_name (| globals, "i" |); M.get_name (| globals, "tx" |) ], + M.call (| + M.get_name (| globals, "enumerate" |), + make_list [ + M.get_name (| globals, "transactions" |) + ], + make_dict [] + |), + ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, "trie_set" |), + make_list [ + M.get_name (| globals, "transactions_trie" |); + M.call (| + M.get_field (| M.get_name (| globals, "rlp" |), "encode" |), + make_list [ + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.get_name (| globals, "i" |) + ], + make_dict [] + |) + ], + make_dict [] + |); + M.get_name (| globals, "tx" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "sender_address" , + M.call (| + M.get_name (| globals, "check_transaction" |), + make_list [ + M.get_name (| globals, "tx" |); + M.get_name (| globals, "gas_available" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "env" , + M.call (| + M.get_field (| M.get_name (| globals, "vm" |), "Environment" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.assign (| + make_tuple [ M.get_name (| globals, "gas_used" |); M.get_name (| globals, "logs" |) ], + M.call (| + M.get_name (| globals, "process_transaction" |), + make_list [ + M.get_name (| globals, "env" |); + M.get_name (| globals, "tx" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_op_local (| + BinOp.sub, + "gas_available", + M.get_name (| globals, "gas_used" |) + |) in + let _ := M.assign_local (| + "receipt" , + M.call (| + M.get_name (| globals, "make_receipt" |), + make_list [ + M.get_name (| globals, "tx" |); + M.call (| + M.get_name (| globals, "state_root" |), + make_list [ + M.get_name (| globals, "state" |) + ], + make_dict [] + |); + BinOp.sub (| + M.get_name (| globals, "block_gas_limit" |), + M.get_name (| globals, "gas_available" |) + |); + M.get_name (| globals, "logs" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "trie_set" |), + make_list [ + M.get_name (| globals, "receipts_trie" |); + M.call (| + M.get_field (| M.get_name (| globals, "rlp" |), "encode" |), + make_list [ + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.get_name (| globals, "i" |) + ], + make_dict [] + |) + ], + make_dict [] + |); + M.get_name (| globals, "receipt" |) + ], + make_dict [] + |) in + let _ := M.assign_op_local (| + BinOp.add, + "block_logs", + M.get_name (| globals, "logs" |) + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := M.call (| + M.get_name (| globals, "pay_rewards" |), + make_list [ + M.get_name (| globals, "state" |); + M.get_name (| globals, "block_number" |); + M.get_name (| globals, "coinbase" |); + M.get_name (| globals, "ommers" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "block_gas_used" , + BinOp.sub (| + M.get_name (| globals, "block_gas_limit" |), + M.get_name (| globals, "gas_available" |) + |) + |) in + let _ := M.assign_local (| + "block_logs_bloom" , + M.call (| + M.get_name (| globals, "logs_bloom" |), + make_list [ + M.get_name (| globals, "block_logs" |) + ], + make_dict [] + |) + |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, "ApplyBodyOutput" |), + make_list [ + M.get_name (| globals, "block_gas_used" |); + M.call (| + M.get_name (| globals, "root" |), + make_list [ + M.get_name (| globals, "transactions_trie" |) + ], + make_dict [] + |); + M.call (| + M.get_name (| globals, "root" |), + make_list [ + M.get_name (| globals, "receipts_trie" |) + ], + make_dict [] + |); + M.get_name (| globals, "block_logs_bloom" |); + M.call (| + M.get_name (| globals, "state_root" |), + make_list [ + M.get_name (| globals, "state" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Definition validate_ommers : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "ommers"; "block_header"; "chain" ] |) in + let _ := Constant.str " + Validates the ommers mentioned in the block. + + An ommer block is a block that wasn't canonically added to the + blockchain because it wasn't validated as fast as the canonical block + but was mined at the same time. + + To be considered valid, the ommers must adhere to the rules defined in + the Ethereum protocol. The maximum amount of ommers is 2 per block and + there cannot be duplicate ommers in a block. Many of the other ommer + constraints are listed in the in-line comments of this function. + + Parameters + ---------- + ommers : + List of ommers mentioned in the current block. + block_header: + The header of current block. + chain : + History and current state. + " in + let _ := M.assign_local (| + "block_hash" , + M.call (| + M.get_field (| M.get_name (| globals, "rlp" |), "rlp_hash" |), + make_list [ + M.get_name (| globals, "block_header" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + Compare.eq (| + M.call (| + M.get_field (| M.get_name (| globals, "rlp" |), "rlp_hash" |), + make_list [ + M.get_name (| globals, "ommers" |) + ], + make_dict [] + |), + M.get_field (| M.get_name (| globals, "block_header" |), "ommers_hash" |) + |); + M.get_name (| globals, "InvalidBlock" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_name (| globals, "ommers" |) + ], + make_dict [] + |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + Constant.None_ + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + M.for_ (| + M.get_name (| globals, "ommer" |), + M.get_name (| globals, "ommers" |), + ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + BoolOp.and (| + Compare.lt_e (| + Constant.int 1, + M.get_field (| M.get_name (| globals, "ommer" |), "number" |) + |), + ltac:(M.monadic ( + Compare.lt (| + M.get_field (| M.get_name (| globals, "ommer" |), "number" |), + M.get_field (| M.get_name (| globals, "block_header" |), "number" |) + |) + )) + |); + M.get_name (| globals, "InvalidBlock" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "ommer_parent_header" , + M.get_field (| M.get_subscript (| + M.get_field (| M.get_name (| globals, "chain" |), "blocks" |), + BinOp.sub (| + UnOp.sub (| BinOp.sub (| + M.get_field (| M.get_name (| globals, "block_header" |), "number" |), + M.get_field (| M.get_name (| globals, "ommer" |), "number" |) + |) |), + Constant.int 1 + |) + |), "header" |) + |) in + let _ := M.call (| + M.get_name (| globals, "validate_header" |), + make_list [ + M.get_name (| globals, "ommer" |); + M.get_name (| globals, "ommer_parent_header" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + Compare.lt_e (| + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_name (| globals, "ommers" |) + ], + make_dict [] + |), + Constant.int 2 + |); + M.get_name (| globals, "InvalidBlock" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "ommers_hashes" , + Constant.str "(* At expr: unsupported node type: ListComp *)" + |) in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + Compare.eq (| + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_name (| globals, "ommers_hashes" |) + ], + make_dict [] + |), + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.call (| + M.get_name (| globals, "set" |), + make_list [ + M.get_name (| globals, "ommers_hashes" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |); + M.get_name (| globals, "InvalidBlock" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "recent_canonical_blocks" , + M.slice (| + M.get_field (| M.get_name (| globals, "chain" |), "blocks" |), + UnOp.sub (| BinOp.add (| + M.get_name (| globals, "MAX_OMMER_DEPTH" |), + Constant.int 1 + |) |), + Constant.None_, + Constant.None_ + |) + |) in + let _ := M.assign_local (| + "recent_canonical_block_hashes" , + Constant.str "(* At expr: unsupported node type: SetComp *)" + |) in +(* At stmt: unsupported node type: AnnAssign *) + let _ := + M.for_ (| + M.get_name (| globals, "block" |), + M.get_name (| globals, "recent_canonical_blocks" |), + ltac:(M.monadic ( + let _ := M.assign_local (| + "recent_ommers_hashes" , + M.call (| + M.get_field (| M.get_name (| globals, "recent_ommers_hashes" |), "union" |), + make_list [ + Constant.str "(* At expr: unsupported node type: SetComp *)" + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := + M.for_ (| + make_tuple [ M.get_name (| globals, "ommer_index" |); M.get_name (| globals, "ommer" |) ], + M.call (| + M.get_name (| globals, "enumerate" |), + make_list [ + M.get_name (| globals, "ommers" |) + ], + make_dict [] + |), + ltac:(M.monadic ( + let _ := M.assign_local (| + "ommer_hash" , + M.get_subscript (| + M.get_name (| globals, "ommers_hashes" |), + M.get_name (| globals, "ommer_index" |) + |) + |) in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + Compare.not_eq (| + M.get_name (| globals, "ommer_hash" |), + M.get_name (| globals, "block_hash" |) + |); + M.get_name (| globals, "InvalidBlock" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + Compare.not_in (| + M.get_name (| globals, "ommer_hash" |), + M.get_name (| globals, "recent_canonical_block_hashes" |) + |); + M.get_name (| globals, "InvalidBlock" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + Compare.not_in (| + M.get_name (| globals, "ommer_hash" |), + M.get_name (| globals, "recent_ommers_hashes" |) + |); + M.get_name (| globals, "InvalidBlock" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "ommer_age" , + BinOp.sub (| + M.get_field (| M.get_name (| globals, "block_header" |), "number" |), + M.get_field (| M.get_name (| globals, "ommer" |), "number" |) + |) + |) in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + BoolOp.and (| + Compare.lt_e (| + Constant.int 1, + M.get_name (| globals, "ommer_age" |) + |), + ltac:(M.monadic ( + Compare.lt_e (| + M.get_name (| globals, "ommer_age" |), + M.get_name (| globals, "MAX_OMMER_DEPTH" |) + |) + )) + |); + M.get_name (| globals, "InvalidBlock" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + Compare.in_ (| + M.get_field (| M.get_name (| globals, "ommer" |), "parent_hash" |), + M.get_name (| globals, "recent_canonical_block_hashes" |) + |); + M.get_name (| globals, "InvalidBlock" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + Compare.not_eq (| + M.get_field (| M.get_name (| globals, "ommer" |), "parent_hash" |), + M.get_field (| M.get_name (| globals, "block_header" |), "parent_hash" |) + |); + M.get_name (| globals, "InvalidBlock" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + M.pure Constant.None_)). + +Definition pay_rewards : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "state"; "block_number"; "coinbase"; "ommers" ] |) in + let _ := Constant.str " + Pay rewards to the block miner as well as the ommers miners. + + The miner of the canonical block is rewarded with the predetermined + block reward, ``BLOCK_REWARD``, plus a variable award based off of the + number of ommer blocks that were mined around the same time, and included + in the canonical block's header. An ommer block is a block that wasn't + added to the canonical blockchain because it wasn't validated as fast as + the accepted block but was mined at the same time. Although not all blocks + that are mined are added to the canonical chain, miners are still paid a + reward for their efforts. This reward is called an ommer reward and is + calculated based on the number associated with the ommer block that they + mined. + + Parameters + ---------- + state : + Current account state. + block_number : + Position of the block within the chain. + coinbase : + Address of account which receives block reward and transaction fees. + ommers : + List of ommers mentioned in the current block. + " in + let _ := M.assign_local (| + "miner_reward" , + BinOp.add (| + M.get_name (| globals, "BLOCK_REWARD" |), + BinOp.mult (| + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_name (| globals, "ommers" |) + ], + make_dict [] + |), + BinOp.floor_div (| + M.get_name (| globals, "BLOCK_REWARD" |), + Constant.int 32 + |) + |) + |) + |) in + let _ := M.call (| + M.get_name (| globals, "create_ether" |), + make_list [ + M.get_name (| globals, "state" |); + M.get_name (| globals, "coinbase" |); + M.get_name (| globals, "miner_reward" |) + ], + make_dict [] + |) in + let _ := + M.for_ (| + M.get_name (| globals, "ommer" |), + M.get_name (| globals, "ommers" |), + ltac:(M.monadic ( + let _ := M.assign_local (| + "ommer_age" , + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + BinOp.sub (| + M.get_name (| globals, "block_number" |), + M.get_field (| M.get_name (| globals, "ommer" |), "number" |) + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "ommer_miner_reward" , + BinOp.floor_div (| + BinOp.mult (| + BinOp.sub (| + Constant.int 8, + M.get_name (| globals, "ommer_age" |) + |), + M.get_name (| globals, "BLOCK_REWARD" |) + |), + Constant.int 8 + |) + |) in + let _ := M.call (| + M.get_name (| globals, "create_ether" |), + make_list [ + M.get_name (| globals, "state" |); + M.get_field (| M.get_name (| globals, "ommer" |), "coinbase" |); + M.get_name (| globals, "ommer_miner_reward" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + M.pure Constant.None_)). + +Definition process_transaction : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "env"; "tx" ] |) in + let _ := Constant.str " + Execute a transaction against the provided environment. + + This function processes the actions needed to execute a transaction. + It decrements the sender's account after calculating the gas fee and + refunds them the proper amount after execution. Calling contracts, + deploying code, and incrementing nonces are all examples of actions that + happen within this function or from a call made within this function. + + Accounts that are marked for deletion are processed and destroyed after + execution. + + Parameters + ---------- + env : + Environment for the Ethereum Virtual Machine. + tx : + Transaction to execute. + + Returns + ------- + gas_left : `ethereum.base_types.U256` + Remaining gas after execution. + logs : `Tuple[ethereum.blocks.Log, ...]` + Logs generated during execution. + " in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + M.call (| + M.get_name (| globals, "validate_transaction" |), + make_list [ + M.get_name (| globals, "tx" |) + ], + make_dict [] + |); + M.get_name (| globals, "InvalidBlock" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "sender" , + M.get_field (| M.get_name (| globals, "env" |), "origin" |) + |) in + let _ := M.assign_local (| + "sender_account" , + M.call (| + M.get_name (| globals, "get_account" |), + make_list [ + M.get_field (| M.get_name (| globals, "env" |), "state" |); + M.get_name (| globals, "sender" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "gas_fee" , + BinOp.mult (| + M.get_field (| M.get_name (| globals, "tx" |), "gas" |), + M.get_field (| M.get_name (| globals, "tx" |), "gas_price" |) + |) + |) in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + Compare.eq (| + M.get_field (| M.get_name (| globals, "sender_account" |), "nonce" |), + M.get_field (| M.get_name (| globals, "tx" |), "nonce" |) + |); + M.get_name (| globals, "InvalidBlock" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + Compare.gt_e (| + M.get_field (| M.get_name (| globals, "sender_account" |), "balance" |), + BinOp.add (| + M.get_name (| globals, "gas_fee" |), + M.get_field (| M.get_name (| globals, "tx" |), "value" |) + |) + |); + M.get_name (| globals, "InvalidBlock" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + Compare.eq (| + M.get_field (| M.get_name (| globals, "sender_account" |), "code" |), + M.call (| + M.get_name (| globals, "bytearray" |), + make_list [], + make_dict [] + |) + |); + M.get_name (| globals, "InvalidBlock" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "gas" , + BinOp.sub (| + M.get_field (| M.get_name (| globals, "tx" |), "gas" |), + M.call (| + M.get_name (| globals, "calculate_intrinsic_cost" |), + make_list [ + M.get_name (| globals, "tx" |) + ], + make_dict [] + |) + |) + |) in + let _ := M.call (| + M.get_name (| globals, "increment_nonce" |), + make_list [ + M.get_field (| M.get_name (| globals, "env" |), "state" |); + M.get_name (| globals, "sender" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "sender_balance_after_gas_fee" , + BinOp.sub (| + M.get_field (| M.get_name (| globals, "sender_account" |), "balance" |), + M.get_name (| globals, "gas_fee" |) + |) + |) in + let _ := M.call (| + M.get_name (| globals, "set_account_balance" |), + make_list [ + M.get_field (| M.get_name (| globals, "env" |), "state" |); + M.get_name (| globals, "sender" |); + M.get_name (| globals, "sender_balance_after_gas_fee" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "message" , + M.call (| + M.get_name (| globals, "prepare_message" |), + make_list [ + M.get_name (| globals, "sender" |); + M.get_field (| M.get_name (| globals, "tx" |), "to" |); + M.get_field (| M.get_name (| globals, "tx" |), "value" |); + M.get_field (| M.get_name (| globals, "tx" |), "data" |); + M.get_name (| globals, "gas" |); + M.get_name (| globals, "env" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "output" , + M.call (| + M.get_name (| globals, "process_message_call" |), + make_list [ + M.get_name (| globals, "message" |); + M.get_name (| globals, "env" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "gas_used" , + BinOp.sub (| + M.get_field (| M.get_name (| globals, "tx" |), "gas" |), + M.get_field (| M.get_name (| globals, "output" |), "gas_left" |) + |) + |) in + let _ := M.assign_local (| + "gas_refund" , + M.call (| + M.get_name (| globals, "min" |), + make_list [ + BinOp.floor_div (| + M.get_name (| globals, "gas_used" |), + Constant.int 2 + |); + M.get_field (| M.get_name (| globals, "output" |), "refund_counter" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "gas_refund_amount" , + BinOp.mult (| + BinOp.add (| + M.get_field (| M.get_name (| globals, "output" |), "gas_left" |), + M.get_name (| globals, "gas_refund" |) + |), + M.get_field (| M.get_name (| globals, "tx" |), "gas_price" |) + |) + |) in + let _ := M.assign_local (| + "transaction_fee" , + BinOp.mult (| + BinOp.sub (| + BinOp.sub (| + M.get_field (| M.get_name (| globals, "tx" |), "gas" |), + M.get_field (| M.get_name (| globals, "output" |), "gas_left" |) + |), + M.get_name (| globals, "gas_refund" |) + |), + M.get_field (| M.get_name (| globals, "tx" |), "gas_price" |) + |) + |) in + let _ := M.assign_local (| + "total_gas_used" , + BinOp.sub (| + M.get_name (| globals, "gas_used" |), + M.get_name (| globals, "gas_refund" |) + |) + |) in + let _ := M.assign_local (| + "sender_balance_after_refund" , + BinOp.add (| + M.get_field (| M.call (| + M.get_name (| globals, "get_account" |), + make_list [ + M.get_field (| M.get_name (| globals, "env" |), "state" |); + M.get_name (| globals, "sender" |) + ], + make_dict [] + |), "balance" |), + M.get_name (| globals, "gas_refund_amount" |) + |) + |) in + let _ := M.call (| + M.get_name (| globals, "set_account_balance" |), + make_list [ + M.get_field (| M.get_name (| globals, "env" |), "state" |); + M.get_name (| globals, "sender" |); + M.get_name (| globals, "sender_balance_after_refund" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "coinbase_balance_after_mining_fee" , + BinOp.add (| + M.get_field (| M.call (| + M.get_name (| globals, "get_account" |), + make_list [ + M.get_field (| M.get_name (| globals, "env" |), "state" |); + M.get_field (| M.get_name (| globals, "env" |), "coinbase" |) + ], + make_dict [] + |), "balance" |), + M.get_name (| globals, "transaction_fee" |) + |) + |) in + let _ := M.call (| + M.get_name (| globals, "set_account_balance" |), + make_list [ + M.get_field (| M.get_name (| globals, "env" |), "state" |); + M.get_field (| M.get_name (| globals, "env" |), "coinbase" |); + M.get_name (| globals, "coinbase_balance_after_mining_fee" |) + ], + make_dict [] + |) in + let _ := + M.for_ (| + M.get_name (| globals, "address" |), + M.get_field (| M.get_name (| globals, "output" |), "accounts_to_delete" |), + ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, "destroy_account" |), + make_list [ + M.get_field (| M.get_name (| globals, "env" |), "state" |); + M.get_name (| globals, "address" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := M.return_ (| + make_tuple [ M.get_name (| globals, "total_gas_used" |); M.get_field (| M.get_name (| globals, "output" |), "logs" |) ] + |) in + M.pure Constant.None_)). + +Definition validate_transaction : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "tx" ] |) in + let _ := Constant.str " + Verifies a transaction. + + The gas in a transaction gets used to pay for the intrinsic cost of + operations, therefore if there is insufficient gas then it would not + be possible to execute a transaction and it will be declared invalid. + + Additionally, the nonce of a transaction must not equal or exceed the + limit defined in `EIP-2681 `_. + In practice, defining the limit as ``2**64-1`` has no impact because + sending ``2**64-1`` transactions is improbable. It's not strictly + impossible though, ``2**64-1`` transactions is the entire capacity of the + Ethereum blockchain at 2022 gas limits for a little over 22 years. + + Parameters + ---------- + tx : + Transaction to validate. + + Returns + ------- + verified : `bool` + True if the transaction can be executed, or False otherwise. + " in + let _ := M.return_ (| + BoolOp.and (| + Compare.lt_e (| + M.call (| + M.get_name (| globals, "calculate_intrinsic_cost" |), + make_list [ + M.get_name (| globals, "tx" |) + ], + make_dict [] + |), + M.get_field (| M.get_name (| globals, "tx" |), "gas" |) + |), + ltac:(M.monadic ( + Compare.lt (| + M.get_field (| M.get_name (| globals, "tx" |), "nonce" |), + BinOp.sub (| + BinOp.pow (| + Constant.int 2, + Constant.int 64 + |), + Constant.int 1 + |) + |) + )) + |) + |) in + M.pure Constant.None_)). + +Definition calculate_intrinsic_cost : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "tx" ] |) in + let _ := Constant.str " + Calculates the gas that is charged before execution is started. + + The intrinsic cost of the transaction is charged before execution has + begun. Functions/operations in the EVM cost money to execute so this + intrinsic cost is for the operations that need to be paid for as part of + the transaction. Data transfer, for example, is part of this intrinsic + cost. It costs ether to send data over the wire and that ether is + accounted for in the intrinsic cost calculated in this function. This + intrinsic cost must be calculated and paid for before execution in order + for all operations to be implemented. + + Parameters + ---------- + tx : + Transaction to compute the intrinsic cost of. + + Returns + ------- + verified : `ethereum.base_types.Uint` + The intrinsic cost of the transaction. + " in + let _ := M.assign_local (| + "data_cost" , + Constant.int 0 + |) in + let _ := + M.for_ (| + M.get_name (| globals, "byte" |), + M.get_field (| M.get_name (| globals, "tx" |), "data" |), + ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, "byte" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_op_local (| + BinOp.add, + "data_cost", + M.get_name (| globals, "TX_DATA_COST_PER_ZERO" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_op_local (| + BinOp.add, + "data_cost", + M.get_name (| globals, "TX_DATA_COST_PER_NON_ZERO" |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_field (| M.get_name (| globals, "tx" |), "to" |), + M.call (| + M.get_name (| globals, "Bytes0" |), + make_list [ + Constant.bytes "" + ], + make_dict [] + |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "create_cost" , + M.get_name (| globals, "TX_CREATE_COST" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "create_cost" , + Constant.int 0 + |) in + M.pure Constant.None_ + )) |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + BinOp.add (| + BinOp.add (| + M.get_name (| globals, "TX_BASE_COST" |), + M.get_name (| globals, "data_cost" |) + |), + M.get_name (| globals, "create_cost" |) + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Definition recover_sender : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "tx" ] |) in + let _ := Constant.str " + Extracts the sender address from a transaction. + + The v, r, and s values are the three parts that make up the signature + of a transaction. In order to recover the sender of a transaction the two + components needed are the signature (``v``, ``r``, and ``s``) and the + signing hash of the transaction. The sender's public key can be obtained + with these two values and therefore the sender address can be retrieved. + + Parameters + ---------- + tx : + Transaction of interest. + + Returns + ------- + sender : `ethereum.fork_types.Address` + The address of the account that signed the transaction. + " in + let _ := M.assign (| + make_tuple [ M.get_name (| globals, "v" |); M.get_name (| globals, "r" |); M.get_name (| globals, "s" |) ], + make_tuple [ M.get_field (| M.get_name (| globals, "tx" |), "v" |); M.get_field (| M.get_name (| globals, "tx" |), "r" |); M.get_field (| M.get_name (| globals, "tx" |), "s" |) ] + |) in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + BoolOp.or (| + Compare.eq (| + M.get_name (| globals, "v" |), + Constant.int 27 + |), + ltac:(M.monadic ( + Compare.eq (| + M.get_name (| globals, "v" |), + Constant.int 28 + |) + )) + |); + M.get_name (| globals, "InvalidBlock" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + BoolOp.and (| + Compare.lt (| + Constant.int 0, + M.get_name (| globals, "r" |) + |), + ltac:(M.monadic ( + Compare.lt (| + M.get_name (| globals, "r" |), + M.get_name (| globals, "SECP256K1N" |) + |) + )) + |); + M.get_name (| globals, "InvalidBlock" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + BoolOp.and (| + Compare.lt (| + Constant.int 0, + M.get_name (| globals, "s" |) + |), + ltac:(M.monadic ( + Compare.lt_e (| + M.get_name (| globals, "s" |), + BinOp.floor_div (| + M.get_name (| globals, "SECP256K1N" |), + Constant.int 2 + |) + |) + )) + |); + M.get_name (| globals, "InvalidBlock" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "public_key" , + M.call (| + M.get_name (| globals, "secp256k1_recover" |), + make_list [ + M.get_name (| globals, "r" |); + M.get_name (| globals, "s" |); + BinOp.sub (| + M.get_name (| globals, "v" |), + Constant.int 27 + |); + M.call (| + M.get_name (| globals, "signing_hash" |), + make_list [ + M.get_name (| globals, "tx" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, "Address" |), + make_list [ + M.slice (| + M.call (| + M.get_name (| globals, "keccak256" |), + make_list [ + M.get_name (| globals, "public_key" |) + ], + make_dict [] + |), + Constant.int 12, + Constant.int 32, + Constant.None_ + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Definition signing_hash : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "tx" ] |) in + let _ := Constant.str " + Compute the hash of a transaction used in the signature. + + The values that are used to compute the signing hash set the rules for a + transaction. For example, signing over the gas sets a limit for the + amount of money that is allowed to be pulled out of the sender's account. + + Parameters + ---------- + tx : + Transaction of interest. + + Returns + ------- + hash : `ethereum.crypto.hash.Hash32` + Hash of the transaction. + " in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, "keccak256" |), + make_list [ + M.call (| + M.get_field (| M.get_name (| globals, "rlp" |), "encode" |), + make_list [ + make_tuple [ M.get_field (| M.get_name (| globals, "tx" |), "nonce" |); M.get_field (| M.get_name (| globals, "tx" |), "gas_price" |); M.get_field (| M.get_name (| globals, "tx" |), "gas" |); M.get_field (| M.get_name (| globals, "tx" |), "to" |); M.get_field (| M.get_name (| globals, "tx" |), "value" |); M.get_field (| M.get_name (| globals, "tx" |), "data" |) ] + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Definition compute_header_hash : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "header" ] |) in + let _ := Constant.str " + Computes the hash of a block header. + + The header hash of a block is the canonical hash that is used to refer + to a specific block and completely distinguishes a block from another. + + ``keccak256`` is a function that produces a 256 bit hash of any input. + It also takes in any number of bytes as an input and produces a single + hash for them. A hash is a completely unique output for a single input. + So an input corresponds to one unique hash that can be used to identify + the input exactly. + + Prior to using the ``keccak256`` hash function, the header must be + encoded using the Recursive-Length Prefix. See :ref:`rlp`. + RLP encoding the header converts it into a space-efficient format that + allows for easy transfer of data between nodes. The purpose of RLP is to + encode arbitrarily nested arrays of binary data, and RLP is the primary + encoding method used to serialize objects in Ethereum's execution layer. + The only purpose of RLP is to encode structure; encoding specific data + types (e.g. strings, floats) is left up to higher-order protocols. + + Parameters + ---------- + header : + Header of interest. + + Returns + ------- + hash : `ethereum.crypto.hash.Hash32` + Hash of the header. + " in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, "keccak256" |), + make_list [ + M.call (| + M.get_field (| M.get_name (| globals, "rlp" |), "encode" |), + make_list [ + M.get_name (| globals, "header" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Definition check_gas_limit : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "gas_limit"; "parent_gas_limit" ] |) in + let _ := Constant.str " + Validates the gas limit for a block. + + The bounds of the gas limit, ``max_adjustment_delta``, is set as the + quotient of the parent block's gas limit and the + ``GAS_LIMIT_ADJUSTMENT_FACTOR``. Therefore, if the gas limit that is + passed through as a parameter is greater than or equal to the *sum* of + the parent's gas and the adjustment delta then the limit for gas is too + high and fails this function's check. Similarly, if the limit is less + than or equal to the *difference* of the parent's gas and the adjustment + delta *or* the predefined ``GAS_LIMIT_MINIMUM`` then this function's + check fails because the gas limit doesn't allow for a sufficient or + reasonable amount of gas to be used on a block. + + Parameters + ---------- + gas_limit : + Gas limit to validate. + + parent_gas_limit : + Gas limit of the parent block. + + Returns + ------- + check : `bool` + True if gas limit constraints are satisfied, False otherwise. + " in + let _ := M.assign_local (| + "max_adjustment_delta" , + BinOp.floor_div (| + M.get_name (| globals, "parent_gas_limit" |), + M.get_name (| globals, "GAS_LIMIT_ADJUSTMENT_FACTOR" |) + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.gt_e (| + M.get_name (| globals, "gas_limit" |), + BinOp.add (| + M.get_name (| globals, "parent_gas_limit" |), + M.get_name (| globals, "max_adjustment_delta" |) + |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + Constant.bool false + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + Compare.lt_e (| + M.get_name (| globals, "gas_limit" |), + BinOp.sub (| + M.get_name (| globals, "parent_gas_limit" |), + M.get_name (| globals, "max_adjustment_delta" |) + |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + Constant.bool false + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + Compare.lt (| + M.get_name (| globals, "gas_limit" |), + M.get_name (| globals, "GAS_LIMIT_MINIMUM" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + Constant.bool false + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.return_ (| + Constant.bool true + |) in + M.pure Constant.None_)). + +Definition calculate_block_difficulty : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "block_number"; "block_timestamp"; "parent_timestamp"; "parent_difficulty" ] |) in + let _ := Constant.str " + Computes difficulty of a block using its header and parent header. + + The difficulty is determined by the time the block was created after its + parent. The ``offset`` is calculated using the parent block's difficulty, + ``parent_difficulty``, and the timestamp between blocks. This offset is + then added to the parent difficulty and is stored as the ``difficulty`` + variable. If the time between the block and its parent is too short, the + offset will result in a positive number thus making the sum of + ``parent_difficulty`` and ``offset`` to be a greater value in order to + avoid mass forking. But, if the time is long enough, then the offset + results in a negative value making the block less difficult than + its parent. + + The base standard for a block's difficulty is the predefined value + set for the genesis block since it has no parent. So, a block + can't be less difficult than the genesis block, therefore each block's + difficulty is set to the maximum value between the calculated + difficulty and the ``GENESIS_DIFFICULTY``. + + Parameters + ---------- + block_number : + Block number of the block. + block_timestamp : + Timestamp of the block. + parent_timestamp : + Timestamp of the parent block. + parent_difficulty : + difficulty of the parent block. + + Returns + ------- + difficulty : `ethereum.base_types.Uint` + Computed difficulty for a block. + " in + let _ := M.assign_local (| + "offset" , + BinOp.mult (| + BinOp.floor_div (| + M.call (| + M.get_name (| globals, "int" |), + make_list [ + M.get_name (| globals, "parent_difficulty" |) + ], + make_dict [] + |), + Constant.int 2048 + |), + M.call (| + M.get_name (| globals, "max" |), + make_list [ + BinOp.sub (| + Constant.int 1, + BinOp.floor_div (| + M.call (| + M.get_name (| globals, "int" |), + make_list [ + BinOp.sub (| + M.get_name (| globals, "block_timestamp" |), + M.get_name (| globals, "parent_timestamp" |) + |) + ], + make_dict [] + |), + Constant.int 10 + |) + |); + UnOp.sub (| Constant.int 99 |) + ], + make_dict [] + |) + |) + |) in + let _ := M.assign_local (| + "difficulty" , + BinOp.add (| + M.call (| + M.get_name (| globals, "int" |), + make_list [ + M.get_name (| globals, "parent_difficulty" |) + ], + make_dict [] + |), + M.get_name (| globals, "offset" |) + |) + |) in + let _ := M.assign_local (| + "num_bomb_periods" , + BinOp.sub (| + BinOp.floor_div (| + M.call (| + M.get_name (| globals, "int" |), + make_list [ + M.get_name (| globals, "block_number" |) + ], + make_dict [] + |), + Constant.int 100000 + |), + Constant.int 2 + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.gt_e (| + M.get_name (| globals, "num_bomb_periods" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_op_local (| + BinOp.add, + "difficulty", + BinOp.pow (| + Constant.int 2, + M.get_name (| globals, "num_bomb_periods" |) + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, "max" |), + make_list [ + M.get_name (| globals, "difficulty" |); + M.get_name (| globals, "MINIMUM_DIFFICULTY" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). diff --git a/CoqOfPython/ethereum/tangerine_whistle/fork_types.v b/CoqOfPython/ethereum/tangerine_whistle/fork_types.v new file mode 100644 index 0000000..d749dca --- /dev/null +++ b/CoqOfPython/ethereum/tangerine_whistle/fork_types.v @@ -0,0 +1,98 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.tangerine_whistle.fork_types". + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Types +^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Types re-used throughout the specification, which are specific to Ethereum. +". + +Axiom dataclasses_imports_dataclass : + IsImported globals "dataclasses" "dataclass". + +Axiom ethereum_imports_rlp : + IsImported globals "ethereum" "rlp". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_Bytes : + IsImported globals "ethereum.base_types" "Bytes". +Axiom ethereum_base_types_imports_Bytes20 : + IsImported globals "ethereum.base_types" "Bytes20". +Axiom ethereum_base_types_imports_Bytes256 : + IsImported globals "ethereum.base_types" "Bytes256". +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". +Axiom ethereum_base_types_imports_slotted_freezable : + IsImported globals "ethereum.base_types" "slotted_freezable". + +Axiom ethereum_crypto_hash_imports_Hash32 : + IsImported globals "ethereum.crypto.hash" "Hash32". +Axiom ethereum_crypto_hash_imports_keccak256 : + IsImported globals "ethereum.crypto.hash" "keccak256". + +Definition Address : Value.t := M.run ltac:(M.monadic ( + M.get_name (| globals, "Bytes20" |) +)). + +Definition Root : Value.t := M.run ltac:(M.monadic ( + M.get_name (| globals, "Hash32" |) +)). + +Definition Bloom : Value.t := M.run ltac:(M.monadic ( + M.get_name (| globals, "Bytes256" |) +)). + +Definition Account : Value.t := + builtins.make_klass + [] + [ + + ] + [ + + ]. + +Definition EMPTY_ACCOUNT : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Account" |), + make_list [], + make_dict [] + |) +)). + +Definition encode_account : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "raw_account_data"; "storage_root" ] |) in + let _ := Constant.str " + Encode `Account` dataclass. + + Storage is not stored in the `Account` dataclass, so `Accounts` cannot be + encoded with providing a storage root. + " in + let _ := M.return_ (| + M.call (| + M.get_field (| M.get_name (| globals, "rlp" |), "encode" |), + make_list [ + make_tuple [ M.get_field (| M.get_name (| globals, "raw_account_data" |), "nonce" |); M.get_field (| M.get_name (| globals, "raw_account_data" |), "balance" |); M.get_name (| globals, "storage_root" |); M.call (| + M.get_name (| globals, "keccak256" |), + make_list [ + M.get_field (| M.get_name (| globals, "raw_account_data" |), "code" |) + ], + make_dict [] + |) ] + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). diff --git a/CoqOfPython/ethereum/tangerine_whistle/state.v b/CoqOfPython/ethereum/tangerine_whistle/state.v new file mode 100644 index 0000000..ffd4f3b --- /dev/null +++ b/CoqOfPython/ethereum/tangerine_whistle/state.v @@ -0,0 +1,906 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.tangerine_whistle.state". + +Definition expr_1 : Value.t := + Constant.str " +State +^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +The state contains all information that is preserved between transactions. + +It consists of a main account trie and storage tries for each contract. + +There is a distinction between an account that does not exist and +`EMPTY_ACCOUNT`. +". + +Axiom dataclasses_imports_dataclass : + IsImported globals "dataclasses" "dataclass". +Axiom dataclasses_imports_field : + IsImported globals "dataclasses" "field". + +Axiom typing_imports_Callable : + IsImported globals "typing" "Callable". +Axiom typing_imports_Dict : + IsImported globals "typing" "Dict". +Axiom typing_imports_List : + IsImported globals "typing" "List". +Axiom typing_imports_Optional : + IsImported globals "typing" "Optional". +Axiom typing_imports_Tuple : + IsImported globals "typing" "Tuple". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_Bytes : + IsImported globals "ethereum.base_types" "Bytes". +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". +Axiom ethereum_base_types_imports_modify : + IsImported globals "ethereum.base_types" "modify". + +Axiom ethereum_utils_ensure_imports_ensure : + IsImported globals "ethereum.utils.ensure" "ensure". + +Axiom ethereum_tangerine_whistle_fork_types_imports_EMPTY_ACCOUNT : + IsImported globals "ethereum.tangerine_whistle.fork_types" "EMPTY_ACCOUNT". +Axiom ethereum_tangerine_whistle_fork_types_imports_Account : + IsImported globals "ethereum.tangerine_whistle.fork_types" "Account". +Axiom ethereum_tangerine_whistle_fork_types_imports_Address : + IsImported globals "ethereum.tangerine_whistle.fork_types" "Address". +Axiom ethereum_tangerine_whistle_fork_types_imports_Root : + IsImported globals "ethereum.tangerine_whistle.fork_types" "Root". + +Axiom ethereum_tangerine_whistle_trie_imports_EMPTY_TRIE_ROOT : + IsImported globals "ethereum.tangerine_whistle.trie" "EMPTY_TRIE_ROOT". +Axiom ethereum_tangerine_whistle_trie_imports_Trie : + IsImported globals "ethereum.tangerine_whistle.trie" "Trie". +Axiom ethereum_tangerine_whistle_trie_imports_copy_trie : + IsImported globals "ethereum.tangerine_whistle.trie" "copy_trie". +Axiom ethereum_tangerine_whistle_trie_imports_root : + IsImported globals "ethereum.tangerine_whistle.trie" "root". +Axiom ethereum_tangerine_whistle_trie_imports_trie_get : + IsImported globals "ethereum.tangerine_whistle.trie" "trie_get". +Axiom ethereum_tangerine_whistle_trie_imports_trie_set : + IsImported globals "ethereum.tangerine_whistle.trie" "trie_set". + +Definition State : Value.t := + builtins.make_klass + [] + [ + + ] + [ + + ]. + +Definition close_state : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "state" ] |) in + let _ := Constant.str " + Free resources held by the state. Used by optimized implementations to + release file descriptors. + " in + let _ := M.delete (| M.get_field (| M.get_name (| globals, "state" |), "_main_trie" |) |) in + let _ := M.delete (| M.get_field (| M.get_name (| globals, "state" |), "_storage_tries" |) |) in + let _ := M.delete (| M.get_field (| M.get_name (| globals, "state" |), "_snapshots" |) |) in + M.pure Constant.None_)). + +Definition begin_transaction : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "state" ] |) in + let _ := Constant.str " + Start a state transaction. + + Transactions are entirely implicit and can be nested. It is not possible to + calculate the state root during a transaction. + + Parameters + ---------- + state : State + The state. + " in + let _ := M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, "state" |), "_snapshots" |), "append" |), + make_list [ + make_tuple [ M.call (| + M.get_name (| globals, "copy_trie" |), + make_list [ + M.get_field (| M.get_name (| globals, "state" |), "_main_trie" |) + ], + make_dict [] + |); Constant.str "(* At expr: unsupported node type: DictComp *)" ] + ], + make_dict [] + |) in + M.pure Constant.None_)). + +Definition commit_transaction : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "state" ] |) in + let _ := Constant.str " + Commit a state transaction. + + Parameters + ---------- + state : State + The state. + " in + let _ := M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, "state" |), "_snapshots" |), "pop" |), + make_list [], + make_dict [] + |) in + M.pure Constant.None_)). + +Definition rollback_transaction : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "state" ] |) in + let _ := Constant.str " + Rollback a state transaction, resetting the state to the point when the + corresponding `start_transaction()` call was made. + + Parameters + ---------- + state : State + The state. + " in + let _ := M.assign (| + make_tuple [ M.get_field (| M.get_name (| globals, "state" |), "_main_trie" |); M.get_field (| M.get_name (| globals, "state" |), "_storage_tries" |) ], + M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, "state" |), "_snapshots" |), "pop" |), + make_list [], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Definition get_account : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "state"; "address" ] |) in + let _ := Constant.str " + Get the `Account` object at an address. Returns `EMPTY_ACCOUNT` if there + is no account at the address. + + Use `get_account_optional()` if you care about the difference between a + non-existent account and `EMPTY_ACCOUNT`. + + Parameters + ---------- + state: `State` + The state + address : `Address` + Address to lookup. + + Returns + ------- + account : `Account` + Account at address. + " in + let _ := M.assign_local (| + "account" , + M.call (| + M.get_name (| globals, "get_account_optional" |), + make_list [ + M.get_name (| globals, "state" |); + M.get_name (| globals, "address" |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, "isinstance" |), + make_list [ + M.get_name (| globals, "account" |); + M.get_name (| globals, "Account" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + M.get_name (| globals, "account" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.return_ (| + M.get_name (| globals, "EMPTY_ACCOUNT" |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_)). + +Definition get_account_optional : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "state"; "address" ] |) in + let _ := Constant.str " + Get the `Account` object at an address. Returns `None` (rather than + `EMPTY_ACCOUNT`) if there is no account at the address. + + Parameters + ---------- + state: `State` + The state + address : `Address` + Address to lookup. + + Returns + ------- + account : `Account` + Account at address. + " in + let _ := M.assign_local (| + "account" , + M.call (| + M.get_name (| globals, "trie_get" |), + make_list [ + M.get_field (| M.get_name (| globals, "state" |), "_main_trie" |); + M.get_name (| globals, "address" |) + ], + make_dict [] + |) + |) in + let _ := M.return_ (| + M.get_name (| globals, "account" |) + |) in + M.pure Constant.None_)). + +Definition set_account : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "state"; "address"; "account" ] |) in + let _ := Constant.str " + Set the `Account` object at an address. Setting to `None` deletes + the account (but not its storage, see `destroy_account()`). + + Parameters + ---------- + state: `State` + The state + address : `Address` + Address to set. + account : `Account` + Account to set at address. + " in + let _ := M.call (| + M.get_name (| globals, "trie_set" |), + make_list [ + M.get_field (| M.get_name (| globals, "state" |), "_main_trie" |); + M.get_name (| globals, "address" |); + M.get_name (| globals, "account" |) + ], + make_dict [] + |) in + M.pure Constant.None_)). + +Definition destroy_account : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "state"; "address" ] |) in + let _ := Constant.str " + Completely remove the account at `address` and all of its storage. + + This function is made available exclusively for the `SELFDESTRUCT` + opcode. It is expected that `SELFDESTRUCT` will be disabled in a future + hardfork and this function will be removed. + + Parameters + ---------- + state: `State` + The state + address : `Address` + Address of account to destroy. + " in + let _ := M.call (| + M.get_name (| globals, "destroy_storage" |), + make_list [ + M.get_name (| globals, "state" |); + M.get_name (| globals, "address" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "set_account" |), + make_list [ + M.get_name (| globals, "state" |); + M.get_name (| globals, "address" |); + Constant.None_ + ], + make_dict [] + |) in + M.pure Constant.None_)). + +Definition destroy_storage : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "state"; "address" ] |) in + let _ := Constant.str " + Completely remove the storage at `address`. + + Parameters + ---------- + state: `State` + The state + address : `Address` + Address of account whose storage is to be deleted. + " in + let _ := + (* if *) + M.if_then_else (| + Compare.in_ (| + M.get_name (| globals, "address" |), + M.get_field (| M.get_name (| globals, "state" |), "_storage_tries" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.delete (| M.get_subscript (| + M.get_field (| M.get_name (| globals, "state" |), "_storage_tries" |), + M.get_name (| globals, "address" |) + |) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + M.pure Constant.None_)). + +Definition get_storage : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "state"; "address"; "key" ] |) in + let _ := Constant.str " + Get a value at a storage key on an account. Returns `U256(0)` if the + storage key has not been set previously. + + Parameters + ---------- + state: `State` + The state + address : `Address` + Address of the account. + key : `Bytes` + Key to lookup. + + Returns + ------- + value : `U256` + Value at the key. + " in + let _ := M.assign_local (| + "trie" , + M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, "state" |), "_storage_tries" |), "get" |), + make_list [ + M.get_name (| globals, "address" |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.is (| + M.get_name (| globals, "trie" |), + Constant.None_ + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "value" , + M.call (| + M.get_name (| globals, "trie_get" |), + make_list [ + M.get_name (| globals, "trie" |); + M.get_name (| globals, "key" |) + ], + make_dict [] + |) + |) in + let _ := M.assert (| M.call (| + M.get_name (| globals, "isinstance" |), + make_list [ + M.get_name (| globals, "value" |); + M.get_name (| globals, "U256" |) + ], + make_dict [] + |) |) in + let _ := M.return_ (| + M.get_name (| globals, "value" |) + |) in + M.pure Constant.None_)). + +Definition set_storage : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "state"; "address"; "key"; "value" ] |) in + let _ := Constant.str " + Set a value at a storage key on an account. Setting to `U256(0)` deletes + the key. + + Parameters + ---------- + state: `State` + The state + address : `Address` + Address of the account. + key : `Bytes` + Key to set. + value : `U256` + Value to set at the key. + " in + let _ := M.assert (| Compare.is_not (| + M.call (| + M.get_name (| globals, "trie_get" |), + make_list [ + M.get_field (| M.get_name (| globals, "state" |), "_main_trie" |); + M.get_name (| globals, "address" |) + ], + make_dict [] + |), + Constant.None_ + |) |) in + let _ := M.assign_local (| + "trie" , + M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, "state" |), "_storage_tries" |), "get" |), + make_list [ + M.get_name (| globals, "address" |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.is (| + M.get_name (| globals, "trie" |), + Constant.None_ + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "trie" , + M.call (| + M.get_name (| globals, "Trie" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.assign (| + M.get_subscript (| + M.get_field (| M.get_name (| globals, "state" |), "_storage_tries" |), + M.get_name (| globals, "address" |) + |), + M.get_name (| globals, "trie" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.call (| + M.get_name (| globals, "trie_set" |), + make_list [ + M.get_name (| globals, "trie" |); + M.get_name (| globals, "key" |); + M.get_name (| globals, "value" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_field (| M.get_name (| globals, "trie" |), "_data" |), + Constant.str "(* At expr: unsupported node type: Dict *)" + |), + (* then *) + ltac:(M.monadic ( + let _ := M.delete (| M.get_subscript (| + M.get_field (| M.get_name (| globals, "state" |), "_storage_tries" |), + M.get_name (| globals, "address" |) + |) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + M.pure Constant.None_)). + +Definition storage_root : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "state"; "address" ] |) in + let _ := Constant.str " + Calculate the storage root of an account. + + Parameters + ---------- + state: + The state + address : + Address of the account. + + Returns + ------- + root : `Root` + Storage root of the account. + " in + let _ := M.assert (| UnOp.not (| M.get_field (| M.get_name (| globals, "state" |), "_snapshots" |) |) |) in + let _ := + (* if *) + M.if_then_else (| + Compare.in_ (| + M.get_name (| globals, "address" |), + M.get_field (| M.get_name (| globals, "state" |), "_storage_tries" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + M.call (| + M.get_name (| globals, "root" |), + make_list [ + M.get_subscript (| + M.get_field (| M.get_name (| globals, "state" |), "_storage_tries" |), + M.get_name (| globals, "address" |) + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.return_ (| + M.get_name (| globals, "EMPTY_TRIE_ROOT" |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_)). + +Definition state_root : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "state" ] |) in + let _ := Constant.str " + Calculate the state root. + + Parameters + ---------- + state: + The current state. + + Returns + ------- + root : `Root` + The state root. + " in + let _ := M.assert (| UnOp.not (| M.get_field (| M.get_name (| globals, "state" |), "_snapshots" |) |) |) in +(* At stmt: unsupported node type: FunctionDef *) + let _ := M.return_ (| + M.call (| + M.get_name (| globals, "root" |), + make_list [ + M.get_field (| M.get_name (| globals, "state" |), "_main_trie" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Definition account_exists : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "state"; "address" ] |) in + let _ := Constant.str " + Checks if an account exists in the state trie + + Parameters + ---------- + state: + The state + address: + Address of the account that needs to be checked. + + Returns + ------- + account_exists : `bool` + True if account exists in the state trie, False otherwise + " in + let _ := M.return_ (| + Compare.is_not (| + M.call (| + M.get_name (| globals, "get_account_optional" |), + make_list [ + M.get_name (| globals, "state" |); + M.get_name (| globals, "address" |) + ], + make_dict [] + |), + Constant.None_ + |) + |) in + M.pure Constant.None_)). + +Definition account_has_code_or_nonce : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "state"; "address" ] |) in + let _ := Constant.str " + Checks if an account has non zero nonce or non empty code + + Parameters + ---------- + state: + The state + address: + Address of the account that needs to be checked. + + Returns + ------- + has_code_or_nonce : `bool` + True if if an account has non zero nonce or non empty code, + False otherwise. + " in + let _ := M.assign_local (| + "account" , + M.call (| + M.get_name (| globals, "get_account" |), + make_list [ + M.get_name (| globals, "state" |); + M.get_name (| globals, "address" |) + ], + make_dict [] + |) + |) in + let _ := M.return_ (| + BoolOp.or (| + Compare.not_eq (| + M.get_field (| M.get_name (| globals, "account" |), "nonce" |), + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + |), + ltac:(M.monadic ( + Compare.not_eq (| + M.get_field (| M.get_name (| globals, "account" |), "code" |), + Constant.bytes "" + |) + )) + |) + |) in + M.pure Constant.None_)). + +Definition modify_state : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "state"; "address"; "f" ] |) in + let _ := Constant.str " + Modify an `Account` in the `State`. + " in + let _ := M.call (| + M.get_name (| globals, "set_account" |), + make_list [ + M.get_name (| globals, "state" |); + M.get_name (| globals, "address" |); + M.call (| + M.get_name (| globals, "modify" |), + make_list [ + M.call (| + M.get_name (| globals, "get_account" |), + make_list [ + M.get_name (| globals, "state" |); + M.get_name (| globals, "address" |) + ], + make_dict [] + |); + M.get_name (| globals, "f" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + M.pure Constant.None_)). + +Definition move_ether : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "state"; "sender_address"; "recipient_address"; "amount" ] |) in + let _ := Constant.str " + Move funds between accounts. + " in +(* At stmt: unsupported node type: FunctionDef *) +(* At stmt: unsupported node type: FunctionDef *) + let _ := M.call (| + M.get_name (| globals, "modify_state" |), + make_list [ + M.get_name (| globals, "state" |); + M.get_name (| globals, "sender_address" |); + M.get_name (| globals, "reduce_sender_balance" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "modify_state" |), + make_list [ + M.get_name (| globals, "state" |); + M.get_name (| globals, "recipient_address" |); + M.get_name (| globals, "increase_recipient_balance" |) + ], + make_dict [] + |) in + M.pure Constant.None_)). + +Definition set_account_balance : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "state"; "address"; "amount" ] |) in + let _ := Constant.str " + Sets the balance of an account. + + Parameters + ---------- + state: + The current state. + + address: + Address of the account whose nonce needs to be incremented. + + amount: + The amount that needs to set in balance. + " in +(* At stmt: unsupported node type: FunctionDef *) + let _ := M.call (| + M.get_name (| globals, "modify_state" |), + make_list [ + M.get_name (| globals, "state" |); + M.get_name (| globals, "address" |); + M.get_name (| globals, "set_balance" |) + ], + make_dict [] + |) in + M.pure Constant.None_)). + +Definition touch_account : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "state"; "address" ] |) in + let _ := Constant.str " + Initializes an account to state. + + Parameters + ---------- + state: + The current state. + + address: + The address of the account that need to initialised. + " in + let _ := + (* if *) + M.if_then_else (| + UnOp.not (| M.call (| + M.get_name (| globals, "account_exists" |), + make_list [ + M.get_name (| globals, "state" |); + M.get_name (| globals, "address" |) + ], + make_dict [] + |) |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, "set_account" |), + make_list [ + M.get_name (| globals, "state" |); + M.get_name (| globals, "address" |); + M.get_name (| globals, "EMPTY_ACCOUNT" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + M.pure Constant.None_)). + +Definition increment_nonce : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "state"; "address" ] |) in + let _ := Constant.str " + Increments the nonce of an account. + + Parameters + ---------- + state: + The current state. + + address: + Address of the account whose nonce needs to be incremented. + " in +(* At stmt: unsupported node type: FunctionDef *) + let _ := M.call (| + M.get_name (| globals, "modify_state" |), + make_list [ + M.get_name (| globals, "state" |); + M.get_name (| globals, "address" |); + M.get_name (| globals, "increase_nonce" |) + ], + make_dict [] + |) in + M.pure Constant.None_)). + +Definition set_code : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "state"; "address"; "code" ] |) in + let _ := Constant.str " + Sets Account code. + + Parameters + ---------- + state: + The current state. + + address: + Address of the account whose code needs to be update. + + code: + The bytecode that needs to be set. + " in +(* At stmt: unsupported node type: FunctionDef *) + let _ := M.call (| + M.get_name (| globals, "modify_state" |), + make_list [ + M.get_name (| globals, "state" |); + M.get_name (| globals, "address" |); + M.get_name (| globals, "write_code" |) + ], + make_dict [] + |) in + M.pure Constant.None_)). + +Definition create_ether : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "state"; "address"; "amount" ] |) in + let _ := Constant.str " + Add newly created ether to an account. + + Parameters + ---------- + state: + The current state. + address: + Address of the account to which ether is added. + amount: + The amount of ether to be added to the account of interest. + " in +(* At stmt: unsupported node type: FunctionDef *) + let _ := M.call (| + M.get_name (| globals, "modify_state" |), + make_list [ + M.get_name (| globals, "state" |); + M.get_name (| globals, "address" |); + M.get_name (| globals, "increase_balance" |) + ], + make_dict [] + |) in + M.pure Constant.None_)). diff --git a/CoqOfPython/ethereum/tangerine_whistle/transactions.v b/CoqOfPython/ethereum/tangerine_whistle/transactions.v new file mode 100644 index 0000000..cfb821b --- /dev/null +++ b/CoqOfPython/ethereum/tangerine_whistle/transactions.v @@ -0,0 +1,56 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.tangerine_whistle.transactions". + +Definition expr_1 : Value.t := + Constant.str " +Transactions are atomic units of work created externally to Ethereum and +submitted to be executed. If Ethereum is viewed as a state machine, +transactions are the events that move between states. +". + +Axiom dataclasses_imports_dataclass : + IsImported globals "dataclasses" "dataclass". + +Axiom typing_imports_Union : + IsImported globals "typing" "Union". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_Bytes : + IsImported globals "ethereum.base_types" "Bytes". +Axiom ethereum_base_types_imports_Bytes0 : + IsImported globals "ethereum.base_types" "Bytes0". +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". +Axiom ethereum_base_types_imports_slotted_freezable : + IsImported globals "ethereum.base_types" "slotted_freezable". + +Axiom ethereum_tangerine_whistle_fork_types_imports_Address : + IsImported globals "ethereum.tangerine_whistle.fork_types" "Address". + +Definition TX_BASE_COST : Value.t := M.run ltac:(M.monadic ( + Constant.int 21000 +)). + +Definition TX_DATA_COST_PER_NON_ZERO : Value.t := M.run ltac:(M.monadic ( + Constant.int 68 +)). + +Definition TX_DATA_COST_PER_ZERO : Value.t := M.run ltac:(M.monadic ( + Constant.int 4 +)). + +Definition TX_CREATE_COST : Value.t := M.run ltac:(M.monadic ( + Constant.int 32000 +)). + +Definition Transaction : Value.t := + builtins.make_klass + [] + [ + + ] + [ + + ]. diff --git a/CoqOfPython/ethereum/tangerine_whistle/trie.v b/CoqOfPython/ethereum/tangerine_whistle/trie.v new file mode 100644 index 0000000..1390bd6 --- /dev/null +++ b/CoqOfPython/ethereum/tangerine_whistle/trie.v @@ -0,0 +1,1589 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.tangerine_whistle.trie". + +Definition expr_1 : Value.t := + Constant.str " +State Trie +^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +The state trie is the structure responsible for storing +`.fork_types.Account` objects. +". + +(* At top_level_stmt: unsupported node type: Import *) + +Axiom dataclasses_imports_dataclass : + IsImported globals "dataclasses" "dataclass". +Axiom dataclasses_imports_field : + IsImported globals "dataclasses" "field". + +Axiom typing_imports_Callable : + IsImported globals "typing" "Callable". +Axiom typing_imports_Dict : + IsImported globals "typing" "Dict". +Axiom typing_imports_Generic : + IsImported globals "typing" "Generic". +Axiom typing_imports_List : + IsImported globals "typing" "List". +Axiom typing_imports_Mapping : + IsImported globals "typing" "Mapping". +Axiom typing_imports_MutableMapping : + IsImported globals "typing" "MutableMapping". +Axiom typing_imports_Optional : + IsImported globals "typing" "Optional". +Axiom typing_imports_Sequence : + IsImported globals "typing" "Sequence". +Axiom typing_imports_TypeVar : + IsImported globals "typing" "TypeVar". +Axiom typing_imports_Union : + IsImported globals "typing" "Union". +Axiom typing_imports_cast : + IsImported globals "typing" "cast". + +Axiom ethereum_crypto_hash_imports_keccak256 : + IsImported globals "ethereum.crypto.hash" "keccak256". + +Axiom ethereum_dao_fork_imports_trie : + IsImported globals "ethereum.dao_fork" "trie". + +Axiom ethereum_utils_ensure_imports_ensure : + IsImported globals "ethereum.utils.ensure" "ensure". + +Axiom ethereum_utils_hexadecimal_imports_hex_to_bytes : + IsImported globals "ethereum.utils.hexadecimal" "hex_to_bytes". + +Axiom ethereum_imports_rlp : + IsImported globals "ethereum" "rlp". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_Bytes : + IsImported globals "ethereum.base_types" "Bytes". +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". +Axiom ethereum_base_types_imports_slotted_freezable : + IsImported globals "ethereum.base_types" "slotted_freezable". + +Axiom ethereum_tangerine_whistle_blocks_imports_Receipt : + IsImported globals "ethereum.tangerine_whistle.blocks" "Receipt". + +Axiom ethereum_tangerine_whistle_fork_types_imports_Account : + IsImported globals "ethereum.tangerine_whistle.fork_types" "Account". +Axiom ethereum_tangerine_whistle_fork_types_imports_Address : + IsImported globals "ethereum.tangerine_whistle.fork_types" "Address". +Axiom ethereum_tangerine_whistle_fork_types_imports_Root : + IsImported globals "ethereum.tangerine_whistle.fork_types" "Root". +Axiom ethereum_tangerine_whistle_fork_types_imports_encode_account : + IsImported globals "ethereum.tangerine_whistle.fork_types" "encode_account". + +Axiom ethereum_tangerine_whistle_transactions_imports_Transaction : + IsImported globals "ethereum.tangerine_whistle.transactions" "Transaction". + +Definition EMPTY_TRIE_ROOT : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Root" |), + make_list [ + M.call (| + M.get_name (| globals, "hex_to_bytes" |), + make_list [ + Constant.str "56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421" + ], + make_dict [] + |) + ], + make_dict [] + |) +)). + +Definition Node : Value.t := M.run ltac:(M.monadic ( + M.get_subscript (| + M.get_name (| globals, "Union" |), + make_tuple [ M.get_name (| globals, "Account" |); M.get_name (| globals, "Bytes" |); M.get_name (| globals, "Transaction" |); M.get_name (| globals, "Receipt" |); M.get_name (| globals, "Uint" |); M.get_name (| globals, "U256" |); Constant.None_ ] + |) +)). + +Definition K : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "TypeVar" |), + make_list [ + Constant.str "K" + ], + make_dict [] + |) +)). + +Definition V : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "TypeVar" |), + make_list [ + Constant.str "V"; + M.get_subscript (| + M.get_name (| globals, "Optional" |), + M.get_name (| globals, "Account" |) + |); + M.get_subscript (| + M.get_name (| globals, "Optional" |), + M.get_name (| globals, "Bytes" |) + |); + M.get_name (| globals, "Bytes" |); + M.get_subscript (| + M.get_name (| globals, "Optional" |), + M.get_name (| globals, "Transaction" |) + |); + M.get_subscript (| + M.get_name (| globals, "Optional" |), + M.get_name (| globals, "Receipt" |) + |); + M.get_name (| globals, "Uint" |); + M.get_name (| globals, "U256" |) + ], + make_dict [] + |) +)). + +Definition LeafNode : Value.t := + builtins.make_klass + [] + [ + + ] + [ + + ]. + +Definition ExtensionNode : Value.t := + builtins.make_klass + [] + [ + + ] + [ + + ]. + +Definition BranchNode : Value.t := + builtins.make_klass + [] + [ + + ] + [ + + ]. + +Definition InternalNode : Value.t := M.run ltac:(M.monadic ( + M.get_subscript (| + M.get_name (| globals, "Union" |), + make_tuple [ M.get_name (| globals, "LeafNode" |); M.get_name (| globals, "ExtensionNode" |); M.get_name (| globals, "BranchNode" |) ] + |) +)). + +Definition encode_internal_node : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "node" ] |) in + let _ := Constant.str " + Encodes a Merkle Trie node into its RLP form. The RLP will then be + serialized into a `Bytes` and hashed unless it is less that 32 bytes + when serialized. + + This function also accepts `None`, representing the absence of a node, + which is encoded to `b""""`. + + Parameters + ---------- + node : Optional[InternalNode] + The node to encode. + + Returns + ------- + encoded : `rlp.RLP` + The node encoded as RLP. + " in +(* At stmt: unsupported node type: AnnAssign *) + let _ := + (* if *) + M.if_then_else (| + Compare.is (| + M.get_name (| globals, "node" |), + Constant.None_ + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "unencoded" , + Constant.bytes "" + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, "isinstance" |), + make_list [ + M.get_name (| globals, "node" |); + M.get_name (| globals, "LeafNode" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "unencoded" , + make_tuple [ M.call (| + M.get_name (| globals, "nibble_list_to_compact" |), + make_list [ + M.get_field (| M.get_name (| globals, "node" |), "rest_of_key" |); + Constant.bool true + ], + make_dict [] + |); M.get_field (| M.get_name (| globals, "node" |), "value" |) ] + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, "isinstance" |), + make_list [ + M.get_name (| globals, "node" |); + M.get_name (| globals, "ExtensionNode" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "unencoded" , + make_tuple [ M.call (| + M.get_name (| globals, "nibble_list_to_compact" |), + make_list [ + M.get_field (| M.get_name (| globals, "node" |), "key_segment" |); + Constant.bool false + ], + make_dict [] + |); M.get_field (| M.get_name (| globals, "node" |), "subnode" |) ] + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, "isinstance" |), + make_list [ + M.get_name (| globals, "node" |); + M.get_name (| globals, "BranchNode" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "unencoded" , + BinOp.add (| + M.get_field (| M.get_name (| globals, "node" |), "subnodes" |), + make_list [ + M.get_field (| M.get_name (| globals, "node" |), "value" |) + ] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.raise (| Some (M.call (| + M.get_name (| globals, "AssertionError" |), + make_list [ + Constant.str "(* At expr: unsupported node type: JoinedStr *)" + ], + make_dict [] + |)) |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "encoded" , + M.call (| + M.get_field (| M.get_name (| globals, "rlp" |), "encode" |), + make_list [ + M.get_name (| globals, "unencoded" |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.lt (| + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_name (| globals, "encoded" |) + ], + make_dict [] + |), + Constant.int 32 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + M.get_name (| globals, "unencoded" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.return_ (| + M.call (| + M.get_name (| globals, "keccak256" |), + make_list [ + M.get_name (| globals, "encoded" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_)). + +Definition encode_node : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "node"; "storage_root" ] |) in + let _ := Constant.str " + Encode a Node for storage in the Merkle Trie. + + Currently mostly an unimplemented stub. + " in + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, "isinstance" |), + make_list [ + M.get_name (| globals, "node" |); + M.get_name (| globals, "Account" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assert (| Compare.is_not (| + M.get_name (| globals, "storage_root" |), + Constant.None_ + |) |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, "encode_account" |), + make_list [ + M.get_name (| globals, "node" |); + M.get_name (| globals, "storage_root" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, "isinstance" |), + make_list [ + M.get_name (| globals, "node" |); + make_tuple [ M.get_name (| globals, "Transaction" |); M.get_name (| globals, "Receipt" |); M.get_name (| globals, "U256" |) ] + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + M.call (| + M.get_field (| M.get_name (| globals, "rlp" |), "encode" |), + make_list [ + M.call (| + M.get_name (| globals, "cast" |), + make_list [ + M.get_field (| M.get_name (| globals, "rlp" |), "RLP" |); + M.get_name (| globals, "node" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, "isinstance" |), + make_list [ + M.get_name (| globals, "node" |); + M.get_name (| globals, "Bytes" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + M.get_name (| globals, "node" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.return_ (| + M.call (| + M.get_field (| M.get_name (| globals, "previous_trie" |), "encode_node" |), + make_list [ + M.get_name (| globals, "node" |); + M.get_name (| globals, "storage_root" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_)). + +Definition Trie : Value.t := + builtins.make_klass + [(* At base: unsupported node type: Subscript *)] + [ + + ] + [ + + ]. + +Definition copy_trie : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "trie" ] |) in + let _ := Constant.str " + Create a copy of `trie`. Since only frozen objects may be stored in tries, + the contents are reused. + + Parameters + ---------- + trie: `Trie` + Trie to copy. + + Returns + ------- + new_trie : `Trie[K, V]` + A copy of the trie. + " in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, "Trie" |), + make_list [ + M.get_field (| M.get_name (| globals, "trie" |), "secured" |); + M.get_field (| M.get_name (| globals, "trie" |), "default" |); + M.call (| + M.get_field (| M.get_name (| globals, "copy" |), "copy" |), + make_list [ + M.get_field (| M.get_name (| globals, "trie" |), "_data" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Definition trie_set : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "trie"; "key"; "value" ] |) in + let _ := Constant.str " + Stores an item in a Merkle Trie. + + This method deletes the key if `value == trie.default`, because the Merkle + Trie represents the default value by omitting it from the trie. + + Parameters + ---------- + trie: `Trie` + Trie to store in. + key : `Bytes` + Key to lookup. + value : `V` + Node to insert at `key`. + " in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, "value" |), + M.get_field (| M.get_name (| globals, "trie" |), "default" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + Compare.in_ (| + M.get_name (| globals, "key" |), + M.get_field (| M.get_name (| globals, "trie" |), "_data" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.delete (| M.get_subscript (| + M.get_field (| M.get_name (| globals, "trie" |), "_data" |), + M.get_name (| globals, "key" |) + |) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign (| + M.get_subscript (| + M.get_field (| M.get_name (| globals, "trie" |), "_data" |), + M.get_name (| globals, "key" |) + |), + M.get_name (| globals, "value" |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_)). + +Definition trie_get : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "trie"; "key" ] |) in + let _ := Constant.str " + Gets an item from the Merkle Trie. + + This method returns `trie.default` if the key is missing. + + Parameters + ---------- + trie: + Trie to lookup in. + key : + Key to lookup. + + Returns + ------- + node : `V` + Node at `key` in the trie. + " in + let _ := M.return_ (| + M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, "trie" |), "_data" |), "get" |), + make_list [ + M.get_name (| globals, "key" |); + M.get_field (| M.get_name (| globals, "trie" |), "default" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Definition common_prefix_length : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "a"; "b" ] |) in + let _ := Constant.str " + Find the longest common prefix of two sequences. + " in + let _ := + M.for_ (| + M.get_name (| globals, "i" |), + M.call (| + M.get_name (| globals, "range" |), + make_list [ + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_name (| globals, "a" |) + ], + make_dict [] + |) + ], + make_dict [] + |), + ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + BoolOp.or (| + Compare.gt_e (| + M.get_name (| globals, "i" |), + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_name (| globals, "b" |) + ], + make_dict [] + |) + |), + ltac:(M.monadic ( + Compare.not_eq (| + M.get_subscript (| + M.get_name (| globals, "a" |), + M.get_name (| globals, "i" |) + |), + M.get_subscript (| + M.get_name (| globals, "b" |), + M.get_name (| globals, "i" |) + |) + |) + )) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + M.get_name (| globals, "i" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_name (| globals, "a" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Definition nibble_list_to_compact : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "x"; "is_leaf" ] |) in + let _ := Constant.str " + Compresses nibble-list into a standard byte array with a flag. + + A nibble-list is a list of byte values no greater than `15`. The flag is + encoded in high nibble of the highest byte. The flag nibble can be broken + down into two two-bit flags. + + Highest nibble:: + + +---+---+----------+--------+ + | _ | _ | is_leaf | parity | + +---+---+----------+--------+ + 3 2 1 0 + + + The lowest bit of the nibble encodes the parity of the length of the + remaining nibbles -- `0` when even and `1` when odd. The second lowest bit + is used to distinguish leaf and extension nodes. The other two bits are not + used. + + Parameters + ---------- + x : + Array of nibbles. + is_leaf : + True if this is part of a leaf node, or false if it is an extension + node. + + Returns + ------- + compressed : `bytearray` + Compact byte array. + " in + let _ := M.assign_local (| + "compact" , + M.call (| + M.get_name (| globals, "bytearray" |), + make_list [], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + BinOp.mod_ (| + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_name (| globals, "x" |) + ], + make_dict [] + |), + Constant.int 2 + |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_field (| M.get_name (| globals, "compact" |), "append" |), + make_list [ + BinOp.mult (| + Constant.int 16, + BinOp.mult (| + Constant.int 2, + M.get_name (| globals, "is_leaf" |) + |) + |) + ], + make_dict [] + |) in + let _ := + M.for_ (| + M.get_name (| globals, "i" |), + M.call (| + M.get_name (| globals, "range" |), + make_list [ + Constant.int 0; + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_name (| globals, "x" |) + ], + make_dict [] + |); + Constant.int 2 + ], + make_dict [] + |), + ltac:(M.monadic ( + let _ := M.call (| + M.get_field (| M.get_name (| globals, "compact" |), "append" |), + make_list [ + BinOp.add (| + BinOp.mult (| + Constant.int 16, + M.get_subscript (| + M.get_name (| globals, "x" |), + M.get_name (| globals, "i" |) + |) + |), + M.get_subscript (| + M.get_name (| globals, "x" |), + BinOp.add (| + M.get_name (| globals, "i" |), + Constant.int 1 + |) + |) + |) + ], + make_dict [] + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.call (| + M.get_field (| M.get_name (| globals, "compact" |), "append" |), + make_list [ + BinOp.add (| + BinOp.mult (| + Constant.int 16, + BinOp.add (| + BinOp.mult (| + Constant.int 2, + M.get_name (| globals, "is_leaf" |) + |), + Constant.int 1 + |) + |), + M.get_subscript (| + M.get_name (| globals, "x" |), + Constant.int 0 + |) + |) + ], + make_dict [] + |) in + let _ := + M.for_ (| + M.get_name (| globals, "i" |), + M.call (| + M.get_name (| globals, "range" |), + make_list [ + Constant.int 1; + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_name (| globals, "x" |) + ], + make_dict [] + |); + Constant.int 2 + ], + make_dict [] + |), + ltac:(M.monadic ( + let _ := M.call (| + M.get_field (| M.get_name (| globals, "compact" |), "append" |), + make_list [ + BinOp.add (| + BinOp.mult (| + Constant.int 16, + M.get_subscript (| + M.get_name (| globals, "x" |), + M.get_name (| globals, "i" |) + |) + |), + M.get_subscript (| + M.get_name (| globals, "x" |), + BinOp.add (| + M.get_name (| globals, "i" |), + Constant.int 1 + |) + |) + |) + ], + make_dict [] + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + M.pure Constant.None_ + )) |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, "Bytes" |), + make_list [ + M.get_name (| globals, "compact" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Definition bytes_to_nibble_list : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "bytes_" ] |) in + let _ := Constant.str " + Converts a `Bytes` into to a sequence of nibbles (bytes with value < 16). + + Parameters + ---------- + bytes_: + The `Bytes` to convert. + + Returns + ------- + nibble_list : `Bytes` + The `Bytes` in nibble-list format. + " in + let _ := M.assign_local (| + "nibble_list" , + M.call (| + M.get_name (| globals, "bytearray" |), + make_list [ + BinOp.mult (| + Constant.int 2, + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_name (| globals, "bytes_" |) + ], + make_dict [] + |) + |) + ], + make_dict [] + |) + |) in + let _ := + M.for_ (| + make_tuple [ M.get_name (| globals, "byte_index" |); M.get_name (| globals, "byte" |) ], + M.call (| + M.get_name (| globals, "enumerate" |), + make_list [ + M.get_name (| globals, "bytes_" |) + ], + make_dict [] + |), + ltac:(M.monadic ( + let _ := M.assign (| + M.get_subscript (| + M.get_name (| globals, "nibble_list" |), + BinOp.mult (| + M.get_name (| globals, "byte_index" |), + Constant.int 2 + |) + |), + BinOp.r_shift (| + BinOp.bit_and (| + M.get_name (| globals, "byte" |), + Constant.int 240 + |), + Constant.int 4 + |) + |) in + let _ := M.assign (| + M.get_subscript (| + M.get_name (| globals, "nibble_list" |), + BinOp.add (| + BinOp.mult (| + M.get_name (| globals, "byte_index" |), + Constant.int 2 + |), + Constant.int 1 + |) + |), + BinOp.bit_and (| + M.get_name (| globals, "byte" |), + Constant.int 15 + |) + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, "Bytes" |), + make_list [ + M.get_name (| globals, "nibble_list" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Definition _prepare_trie : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "trie"; "get_storage_root" ] |) in + let _ := Constant.str " + Prepares the trie for root calculation. Removes values that are empty, + hashes the keys (if `secured == True`) and encodes all the nodes. + + Parameters + ---------- + trie : + The `Trie` to prepare. + get_storage_root : + Function to get the storage root of an account. Needed to encode + `Account` objects. + + Returns + ------- + out : `Mapping[ethereum.base_types.Bytes, Node]` + Object with keys mapped to nibble-byte form. + " in +(* At stmt: unsupported node type: AnnAssign *) + let _ := + M.for_ (| + make_tuple [ M.get_name (| globals, "preimage" |); M.get_name (| globals, "value" |) ], + M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, "trie" |), "_data" |), "items" |), + make_list [], + make_dict [] + |), + ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, "isinstance" |), + make_list [ + M.get_name (| globals, "value" |); + M.get_name (| globals, "Account" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assert (| Compare.is_not (| + M.get_name (| globals, "get_storage_root" |), + Constant.None_ + |) |) in + let _ := M.assign_local (| + "address" , + M.call (| + M.get_name (| globals, "Address" |), + make_list [ + M.get_name (| globals, "preimage" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "encoded_value" , + M.call (| + M.get_name (| globals, "encode_node" |), + make_list [ + M.get_name (| globals, "value" |); + M.call (| + M.get_name (| globals, "get_storage_root" |), + make_list [ + M.get_name (| globals, "address" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "encoded_value" , + M.call (| + M.get_name (| globals, "encode_node" |), + make_list [ + M.get_name (| globals, "value" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + )) |) in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + Compare.not_eq (| + M.get_name (| globals, "encoded_value" |), + Constant.bytes "" + |); + M.get_name (| globals, "AssertionError" |) + ], + make_dict [] + |) in +(* At stmt: unsupported node type: AnnAssign *) + let _ := + (* if *) + M.if_then_else (| + M.get_field (| M.get_name (| globals, "trie" |), "secured" |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "key" , + M.call (| + M.get_name (| globals, "keccak256" |), + make_list [ + M.get_name (| globals, "preimage" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "key" , + M.get_name (| globals, "preimage" |) + |) in + M.pure Constant.None_ + )) |) in + let _ := M.assign (| + M.get_subscript (| + M.get_name (| globals, "mapped" |), + M.call (| + M.get_name (| globals, "bytes_to_nibble_list" |), + make_list [ + M.get_name (| globals, "key" |) + ], + make_dict [] + |) + |), + M.get_name (| globals, "encoded_value" |) + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := M.return_ (| + M.get_name (| globals, "mapped" |) + |) in + M.pure Constant.None_)). + +Definition root : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "trie"; "get_storage_root" ] |) in + let _ := Constant.str " + Computes the root of a modified merkle patricia trie (MPT). + + Parameters + ---------- + trie : + `Trie` to get the root of. + get_storage_root : + Function to get the storage root of an account. Needed to encode + `Account` objects. + + + Returns + ------- + root : `.fork_types.Root` + MPT root of the underlying key-value pairs. + " in + let _ := M.assign_local (| + "obj" , + M.call (| + M.get_name (| globals, "_prepare_trie" |), + make_list [ + M.get_name (| globals, "trie" |); + M.get_name (| globals, "get_storage_root" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "root_node" , + M.call (| + M.get_name (| globals, "encode_internal_node" |), + make_list [ + M.call (| + M.get_name (| globals, "patricialize" |), + make_list [ + M.get_name (| globals, "obj" |); + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.lt (| + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.call (| + M.get_field (| M.get_name (| globals, "rlp" |), "encode" |), + make_list [ + M.get_name (| globals, "root_node" |) + ], + make_dict [] + |) + ], + make_dict [] + |), + Constant.int 32 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + M.call (| + M.get_name (| globals, "keccak256" |), + make_list [ + M.call (| + M.get_field (| M.get_name (| globals, "rlp" |), "encode" |), + make_list [ + M.get_name (| globals, "root_node" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assert (| M.call (| + M.get_name (| globals, "isinstance" |), + make_list [ + M.get_name (| globals, "root_node" |); + M.get_name (| globals, "Bytes" |) + ], + make_dict [] + |) |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, "Root" |), + make_list [ + M.get_name (| globals, "root_node" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_)). + +Definition patricialize : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "obj"; "level" ] |) in + let _ := Constant.str " + Structural composition function. + + Used to recursively patricialize and merkleize a dictionary. Includes + memoization of the tree structure and hashes. + + Parameters + ---------- + obj : + Underlying trie key-value pairs, with keys in nibble-list format. + level : + Current trie level. + + Returns + ------- + node : `ethereum.base_types.Bytes` + Root node of `obj`. + " in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_name (| globals, "obj" |) + ], + make_dict [] + |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + Constant.None_ + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "arbitrary_key" , + M.call (| + M.get_name (| globals, "next" |), + make_list [ + M.call (| + M.get_name (| globals, "iter" |), + make_list [ + M.get_name (| globals, "obj" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_name (| globals, "obj" |) + ], + make_dict [] + |), + Constant.int 1 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "leaf" , + M.call (| + M.get_name (| globals, "LeafNode" |), + make_list [ + M.slice (| + M.get_name (| globals, "arbitrary_key" |), + M.get_name (| globals, "level" |), + Constant.None_, + Constant.None_ + |); + M.get_subscript (| + M.get_name (| globals, "obj" |), + M.get_name (| globals, "arbitrary_key" |) + |) + ], + make_dict [] + |) + |) in + let _ := M.return_ (| + M.get_name (| globals, "leaf" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "substring" , + M.slice (| + M.get_name (| globals, "arbitrary_key" |), + M.get_name (| globals, "level" |), + Constant.None_, + Constant.None_ + |) + |) in + let _ := M.assign_local (| + "prefix_length" , + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_name (| globals, "substring" |) + ], + make_dict [] + |) + |) in + let _ := + M.for_ (| + M.get_name (| globals, "key" |), + M.get_name (| globals, "obj" |), + ltac:(M.monadic ( + let _ := M.assign_local (| + "prefix_length" , + M.call (| + M.get_name (| globals, "min" |), + make_list [ + M.get_name (| globals, "prefix_length" |); + M.call (| + M.get_name (| globals, "common_prefix_length" |), + make_list [ + M.get_name (| globals, "substring" |); + M.slice (| + M.get_name (| globals, "key" |), + M.get_name (| globals, "level" |), + Constant.None_, + Constant.None_ + |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, "prefix_length" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.break (| |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.gt (| + M.get_name (| globals, "prefix_length" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "prefix" , + M.slice (| + M.get_name (| globals, "arbitrary_key" |), + M.get_name (| globals, "level" |), + BinOp.add (| + M.get_name (| globals, "level" |), + M.get_name (| globals, "prefix_length" |) + |), + Constant.None_ + |) + |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, "ExtensionNode" |), + make_list [ + M.get_name (| globals, "prefix" |); + M.call (| + M.get_name (| globals, "encode_internal_node" |), + make_list [ + M.call (| + M.get_name (| globals, "patricialize" |), + make_list [ + M.get_name (| globals, "obj" |); + BinOp.add (| + M.get_name (| globals, "level" |), + M.get_name (| globals, "prefix_length" |) + |) + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in +(* At stmt: unsupported node type: AnnAssign *) + let _ := + M.for_ (| + M.get_name (| globals, "_" |), + M.call (| + M.get_name (| globals, "range" |), + make_list [ + Constant.int 16 + ], + make_dict [] + |), + ltac:(M.monadic ( + let _ := M.call (| + M.get_field (| M.get_name (| globals, "branches" |), "append" |), + make_list [ + Constant.str "(* At expr: unsupported node type: Dict *)" + ], + make_dict [] + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := M.assign_local (| + "value" , + Constant.bytes "" + |) in + let _ := + M.for_ (| + M.get_name (| globals, "key" |), + M.get_name (| globals, "obj" |), + ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_name (| globals, "key" |) + ], + make_dict [] + |), + M.get_name (| globals, "level" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, "isinstance" |), + make_list [ + M.get_subscript (| + M.get_name (| globals, "obj" |), + M.get_name (| globals, "key" |) + |); + make_tuple [ M.get_name (| globals, "Account" |); M.get_name (| globals, "Receipt" |); M.get_name (| globals, "Uint" |) ] + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, "AssertionError" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "value" , + M.get_subscript (| + M.get_name (| globals, "obj" |), + M.get_name (| globals, "key" |) + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign (| + M.get_subscript (| + M.get_subscript (| + M.get_name (| globals, "branches" |), + M.get_subscript (| + M.get_name (| globals, "key" |), + M.get_name (| globals, "level" |) + |) + |), + M.get_name (| globals, "key" |) + |), + M.get_subscript (| + M.get_name (| globals, "obj" |), + M.get_name (| globals, "key" |) + |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, "BranchNode" |), + make_list [ + Constant.str "(* At expr: unsupported node type: ListComp *)"; + M.get_name (| globals, "value" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). diff --git a/CoqOfPython/ethereum/tangerine_whistle/utils/__init__.v b/CoqOfPython/ethereum/tangerine_whistle/utils/__init__.v new file mode 100644 index 0000000..c4428f6 --- /dev/null +++ b/CoqOfPython/ethereum/tangerine_whistle/utils/__init__.v @@ -0,0 +1,8 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.tangerine_whistle.utils.__init__". + +Definition expr_1 : Value.t := + Constant.str " +Utility functions unique to this particular fork. +". diff --git a/CoqOfPython/ethereum/tangerine_whistle/utils/address.v b/CoqOfPython/ethereum/tangerine_whistle/utils/address.v new file mode 100644 index 0000000..e130a74 --- /dev/null +++ b/CoqOfPython/ethereum/tangerine_whistle/utils/address.v @@ -0,0 +1,144 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.tangerine_whistle.utils.address". + +Definition expr_1 : Value.t := + Constant.str " +Hardfork Utility Functions For Addresses +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Address specific functions used in this tangerine whistle version of +specification. +". + +Axiom typing_imports_Union : + IsImported globals "typing" "Union". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". + +Axiom ethereum_crypto_hash_imports_keccak256 : + IsImported globals "ethereum.crypto.hash" "keccak256". + +Axiom ethereum_utils_byte_imports_left_pad_zero_bytes : + IsImported globals "ethereum.utils.byte" "left_pad_zero_bytes". + +Axiom ethereum_imports_rlp : + IsImported globals "ethereum" "rlp". + +Axiom ethereum_tangerine_whistle_fork_types_imports_Address : + IsImported globals "ethereum.tangerine_whistle.fork_types" "Address". + +Definition to_address : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "data" ] |) in + let _ := Constant.str " + Convert a Uint or U256 value to a valid address (20 bytes). + + Parameters + ---------- + data : + The string to be converted to bytes. + + Returns + ------- + address : `Address` + The obtained address. + " in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, "Address" |), + make_list [ + M.slice (| + M.call (| + M.get_field (| M.get_name (| globals, "data" |), "to_be_bytes32" |), + make_list [], + make_dict [] + |), + UnOp.sub (| Constant.int 20 |), + Constant.None_, + Constant.None_ + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Definition compute_contract_address : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "address"; "nonce" ] |) in + let _ := Constant.str " + Computes address of the new account that needs to be created. + + Parameters + ---------- + address : + The address of the account that wants to create the new account. + nonce : + The transaction count of the account that wants to create the new + account. + + Returns + ------- + address: `ethereum.tangerine_whistle.fork_types.Address` + The computed address of the new account. + " in + let _ := M.assign_local (| + "computed_address" , + M.call (| + M.get_name (| globals, "keccak256" |), + make_list [ + M.call (| + M.get_field (| M.get_name (| globals, "rlp" |), "encode" |), + make_list [ + make_list [ + M.get_name (| globals, "address" |); + M.get_name (| globals, "nonce" |) + ] + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "canonical_address" , + M.slice (| + M.get_name (| globals, "computed_address" |), + UnOp.sub (| Constant.int 20 |), + Constant.None_, + Constant.None_ + |) + |) in + let _ := M.assign_local (| + "padded_address" , + M.call (| + M.get_name (| globals, "left_pad_zero_bytes" |), + make_list [ + M.get_name (| globals, "canonical_address" |); + Constant.int 20 + ], + make_dict [] + |) + |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, "Address" |), + make_list [ + M.get_name (| globals, "padded_address" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). diff --git a/CoqOfPython/ethereum/tangerine_whistle/utils/hexadecimal.v b/CoqOfPython/ethereum/tangerine_whistle/utils/hexadecimal.v new file mode 100644 index 0000000..0079ced --- /dev/null +++ b/CoqOfPython/ethereum/tangerine_whistle/utils/hexadecimal.v @@ -0,0 +1,153 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.tangerine_whistle.utils.hexadecimal". + +Definition expr_1 : Value.t := + Constant.str " +Utility Functions For Hexadecimal Strings +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Hexadecimal utility functions used in this specification, specific to +Tangerine Whistle types. +". + +Axiom ethereum_utils_hexadecimal_imports_remove_hex_prefix : + IsImported globals "ethereum.utils.hexadecimal" "remove_hex_prefix". + +Axiom ethereum_tangerine_whistle_fork_types_imports_Address : + IsImported globals "ethereum.tangerine_whistle.fork_types" "Address". +Axiom ethereum_tangerine_whistle_fork_types_imports_Bloom : + IsImported globals "ethereum.tangerine_whistle.fork_types" "Bloom". +Axiom ethereum_tangerine_whistle_fork_types_imports_Root : + IsImported globals "ethereum.tangerine_whistle.fork_types" "Root". + +Definition hex_to_root : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "hex_string" ] |) in + let _ := Constant.str " + Convert hex string to trie root. + + Parameters + ---------- + hex_string : + The hexadecimal string to be converted to trie root. + + Returns + ------- + root : `Root` + Trie root obtained from the given hexadecimal string. + " in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, "Root" |), + make_list [ + M.call (| + M.get_field (| M.get_name (| globals, "bytes" |), "fromhex" |), + make_list [ + M.call (| + M.get_name (| globals, "remove_hex_prefix" |), + make_list [ + M.get_name (| globals, "hex_string" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Definition hex_to_bloom : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "hex_string" ] |) in + let _ := Constant.str " + Convert hex string to bloom. + + Parameters + ---------- + hex_string : + The hexadecimal string to be converted to bloom. + + Returns + ------- + bloom : `Bloom` + Bloom obtained from the given hexadecimal string. + " in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, "Bloom" |), + make_list [ + M.call (| + M.get_field (| M.get_name (| globals, "bytes" |), "fromhex" |), + make_list [ + M.call (| + M.get_name (| globals, "remove_hex_prefix" |), + make_list [ + M.get_name (| globals, "hex_string" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Definition hex_to_address : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "hex_string" ] |) in + let _ := Constant.str " + Convert hex string to Address (20 bytes). + + Parameters + ---------- + hex_string : + The hexadecimal string to be converted to Address. + + Returns + ------- + address : `Address` + The address obtained from the given hexadecimal string. + " in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, "Address" |), + make_list [ + M.call (| + M.get_field (| M.get_name (| globals, "bytes" |), "fromhex" |), + make_list [ + M.call (| + M.get_field (| M.call (| + M.get_name (| globals, "remove_hex_prefix" |), + make_list [ + M.get_name (| globals, "hex_string" |) + ], + make_dict [] + |), "rjust" |), + make_list [ + Constant.int 40; + Constant.str "0" + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). diff --git a/CoqOfPython/ethereum/tangerine_whistle/utils/message.v b/CoqOfPython/ethereum/tangerine_whistle/utils/message.v new file mode 100644 index 0000000..8382bfd --- /dev/null +++ b/CoqOfPython/ethereum/tangerine_whistle/utils/message.v @@ -0,0 +1,209 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.tangerine_whistle.utils.message". + +Definition expr_1 : Value.t := + Constant.str " +Hardfork Utility Functions For The Message Data-structure +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Message specific functions used in this tangerine whistle version of +specification. +". + +Axiom typing_imports_Optional : + IsImported globals "typing" "Optional". +Axiom typing_imports_Union : + IsImported globals "typing" "Union". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_Bytes : + IsImported globals "ethereum.base_types" "Bytes". +Axiom ethereum_base_types_imports_Bytes0 : + IsImported globals "ethereum.base_types" "Bytes0". +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". + +Axiom ethereum_tangerine_whistle_fork_types_imports_Address : + IsImported globals "ethereum.tangerine_whistle.fork_types" "Address". + +Axiom ethereum_tangerine_whistle_state_imports_get_account : + IsImported globals "ethereum.tangerine_whistle.state" "get_account". + +Axiom ethereum_tangerine_whistle_vm_imports_Environment : + IsImported globals "ethereum.tangerine_whistle.vm" "Environment". +Axiom ethereum_tangerine_whistle_vm_imports_Message : + IsImported globals "ethereum.tangerine_whistle.vm" "Message". + +Axiom ethereum_tangerine_whistle_utils_address_imports_compute_contract_address : + IsImported globals "ethereum.tangerine_whistle.utils.address" "compute_contract_address". + +Definition prepare_message : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "caller"; "target"; "value"; "data"; "gas"; "env"; "code_address"; "should_transfer_value" ] |) in + let _ := Constant.str " + Execute a transaction against the provided environment. + + Parameters + ---------- + caller : + Address which initiated the transaction + target : + Address whose code will be executed + value : + Value to be transferred. + data : + Array of bytes provided to the code in `target`. + gas : + Gas provided for the code in `target`. + env : + Environment for the Ethereum Virtual Machine. + code_address : + This is usually same as the `target` address except when an alternative + accounts code needs to be executed. + eg. `CALLCODE` calling a precompile. + should_transfer_value : + if True ETH should be transferred while executing a message call. + + Returns + ------- + message: `ethereum.tangerine_whistle.vm.Message` + Items containing contract creation or message call specific data. + " in + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, "isinstance" |), + make_list [ + M.get_name (| globals, "target" |); + M.get_name (| globals, "Bytes0" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "current_target" , + M.call (| + M.get_name (| globals, "compute_contract_address" |), + make_list [ + M.get_name (| globals, "caller" |); + BinOp.sub (| + M.get_field (| M.call (| + M.get_name (| globals, "get_account" |), + make_list [ + M.get_field (| M.get_name (| globals, "env" |), "state" |); + M.get_name (| globals, "caller" |) + ], + make_dict [] + |), "nonce" |), + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 1 + ], + make_dict [] + |) + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "msg_data" , + M.call (| + M.get_name (| globals, "Bytes" |), + make_list [ + Constant.bytes "" + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "code" , + M.get_name (| globals, "data" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, "isinstance" |), + make_list [ + M.get_name (| globals, "target" |); + M.get_name (| globals, "Address" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "current_target" , + M.get_name (| globals, "target" |) + |) in + let _ := M.assign_local (| + "msg_data" , + M.get_name (| globals, "data" |) + |) in + let _ := M.assign_local (| + "code" , + M.get_field (| M.call (| + M.get_name (| globals, "get_account" |), + make_list [ + M.get_field (| M.get_name (| globals, "env" |), "state" |); + M.get_name (| globals, "target" |) + ], + make_dict [] + |), "code" |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.is (| + M.get_name (| globals, "code_address" |), + Constant.None_ + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "code_address" , + M.get_name (| globals, "target" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.raise (| Some (M.call (| + M.get_name (| globals, "AssertionError" |), + make_list [ + Constant.str "Target must be address or empty bytes" + ], + make_dict [] + |)) |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )) |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, "Message" |), + make_list [], + make_dict [] + |) + |) in + M.pure Constant.None_)). diff --git a/CoqOfPython/ethereum/tangerine_whistle/vm/__init__.v b/CoqOfPython/ethereum/tangerine_whistle/vm/__init__.v new file mode 100644 index 0000000..fb5763a --- /dev/null +++ b/CoqOfPython/ethereum/tangerine_whistle/vm/__init__.v @@ -0,0 +1,145 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.tangerine_whistle.vm.__init__". + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +The abstract computer which runs the code stored in an +`.fork_types.Account`. +". + +Axiom dataclasses_imports_dataclass : + IsImported globals "dataclasses" "dataclass". + +Axiom typing_imports_List : + IsImported globals "typing" "List". +Axiom typing_imports_Optional : + IsImported globals "typing" "Optional". +Axiom typing_imports_Set : + IsImported globals "typing" "Set". +Axiom typing_imports_Tuple : + IsImported globals "typing" "Tuple". +Axiom typing_imports_Union : + IsImported globals "typing" "Union". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_Bytes : + IsImported globals "ethereum.base_types" "Bytes". +Axiom ethereum_base_types_imports_Bytes0 : + IsImported globals "ethereum.base_types" "Bytes0". +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". + +Axiom ethereum_crypto_hash_imports_Hash32 : + IsImported globals "ethereum.crypto.hash" "Hash32". + +Axiom ethereum_tangerine_whistle_blocks_imports_Log : + IsImported globals "ethereum.tangerine_whistle.blocks" "Log". + +Axiom ethereum_tangerine_whistle_fork_types_imports_Address : + IsImported globals "ethereum.tangerine_whistle.fork_types" "Address". + +Axiom ethereum_tangerine_whistle_state_imports_State : + IsImported globals "ethereum.tangerine_whistle.state" "State". + +Definition __all__ : Value.t := M.run ltac:(M.monadic ( + make_tuple [ Constant.str "Environment"; Constant.str "Evm"; Constant.str "Message" ] +)). + +Definition Environment : Value.t := + builtins.make_klass + [] + [ + + ] + [ + + ]. + +Definition Message : Value.t := + builtins.make_klass + [] + [ + + ] + [ + + ]. + +Definition Evm : Value.t := + builtins.make_klass + [] + [ + + ] + [ + + ]. + +Definition incorporate_child_on_success : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm"; "child_evm" ] |) in + let _ := Constant.str " + Incorporate the state of a successful `child_evm` into the parent `evm`. + + Parameters + ---------- + evm : + The parent `EVM`. + child_evm : + The child evm to incorporate. + " in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "gas_left" |), + M.get_field (| M.get_name (| globals, "child_evm" |), "gas_left" |) + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "logs" |), + M.get_field (| M.get_name (| globals, "child_evm" |), "logs" |) + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "refund_counter" |), + M.get_field (| M.get_name (| globals, "child_evm" |), "refund_counter" |) + |) in + let _ := M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "accounts_to_delete" |), "update" |), + make_list [ + M.get_field (| M.get_name (| globals, "child_evm" |), "accounts_to_delete" |) + ], + make_dict [] + |) in + M.pure Constant.None_)). + +Definition incorporate_child_on_error : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm"; "child_evm" ] |) in + let _ := Constant.str " + Incorporate the state of an unsuccessful `child_evm` into the parent `evm`. + + Parameters + ---------- + evm : + The parent `EVM`. + child_evm : + The child evm to incorporate. + " in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "gas_left" |), + M.get_field (| M.get_name (| globals, "child_evm" |), "gas_left" |) + |) in + M.pure Constant.None_)). diff --git a/CoqOfPython/ethereum/tangerine_whistle/vm/exceptions.v b/CoqOfPython/ethereum/tangerine_whistle/vm/exceptions.v new file mode 100644 index 0000000..97898c1 --- /dev/null +++ b/CoqOfPython/ethereum/tangerine_whistle/vm/exceptions.v @@ -0,0 +1,121 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.tangerine_whistle.vm.exceptions". + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) Exceptions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Exceptions which cause the EVM to halt exceptionally. +". + +Axiom ethereum_exceptions_imports_EthereumException : + IsImported globals "ethereum.exceptions" "EthereumException". + +Definition ExceptionalHalt : Value.t := + builtins.make_klass + [(globals, "EthereumException")] + [ + + ] + [ + + ]. + +Definition StackUnderflowError : Value.t := + builtins.make_klass + [(globals, "ExceptionalHalt")] + [ + + ] + [ + + ]. + +Definition StackOverflowError : Value.t := + builtins.make_klass + [(globals, "ExceptionalHalt")] + [ + + ] + [ + + ]. + +Definition OutOfGasError : Value.t := + builtins.make_klass + [(globals, "ExceptionalHalt")] + [ + + ] + [ + + ]. + +Definition InvalidOpcode : Value.t := + builtins.make_klass + [(globals, "ExceptionalHalt")] + [ + + ] + [ + ( + "__init__", + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "self"; "code" ] |) in + let _ := M.call (| + M.get_field (| M.call (| + M.get_name (| globals, "super" |), + make_list [], + make_dict [] + |), "__init__" |), + make_list [ + M.get_name (| globals, "code" |) + ], + make_dict [] + |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, "self" |), "code" |), + M.get_name (| globals, "code" |) + |) in + M.pure Constant.None_)) + ) + ]. + +Definition InvalidJumpDestError : Value.t := + builtins.make_klass + [(globals, "ExceptionalHalt")] + [ + + ] + [ + + ]. + +Definition StackDepthLimitError : Value.t := + builtins.make_klass + [(globals, "ExceptionalHalt")] + [ + + ] + [ + + ]. + +Definition AddressCollision : Value.t := + builtins.make_klass + [(globals, "ExceptionalHalt")] + [ + + ] + [ + + ]. diff --git a/CoqOfPython/ethereum/tangerine_whistle/vm/gas.v b/CoqOfPython/ethereum/tangerine_whistle/vm/gas.v new file mode 100644 index 0000000..716b689 --- /dev/null +++ b/CoqOfPython/ethereum/tangerine_whistle/vm/gas.v @@ -0,0 +1,902 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.tangerine_whistle.vm.gas". + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) Gas +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +EVM gas constants and calculators. +". + +Axiom dataclasses_imports_dataclass : + IsImported globals "dataclasses" "dataclass". + +Axiom typing_imports_List : + IsImported globals "typing" "List". +Axiom typing_imports_Tuple : + IsImported globals "typing" "Tuple". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". + +Axiom ethereum_trace_imports_GasAndRefund : + IsImported globals "ethereum.trace" "GasAndRefund". +Axiom ethereum_trace_imports_evm_trace : + IsImported globals "ethereum.trace" "evm_trace". + +Axiom ethereum_utils_numeric_imports_ceil32 : + IsImported globals "ethereum.utils.numeric" "ceil32". + +Axiom ethereum_tangerine_whistle_vm_imports_Evm : + IsImported globals "ethereum.tangerine_whistle.vm" "Evm". + +Axiom ethereum_tangerine_whistle_vm_exceptions_imports_OutOfGasError : + IsImported globals "ethereum.tangerine_whistle.vm.exceptions" "OutOfGasError". + +Definition GAS_JUMPDEST : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 1 + ], + make_dict [] + |) +)). + +Definition GAS_BASE : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 2 + ], + make_dict [] + |) +)). + +Definition GAS_VERY_LOW : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 3 + ], + make_dict [] + |) +)). + +Definition GAS_SLOAD : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 200 + ], + make_dict [] + |) +)). + +Definition GAS_STORAGE_SET : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 20000 + ], + make_dict [] + |) +)). + +Definition GAS_STORAGE_UPDATE : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 5000 + ], + make_dict [] + |) +)). + +Definition GAS_STORAGE_CLEAR_REFUND : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 15000 + ], + make_dict [] + |) +)). + +Definition GAS_LOW : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 5 + ], + make_dict [] + |) +)). + +Definition GAS_MID : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 8 + ], + make_dict [] + |) +)). + +Definition GAS_HIGH : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 10 + ], + make_dict [] + |) +)). + +Definition GAS_EXPONENTIATION : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 10 + ], + make_dict [] + |) +)). + +Definition GAS_EXPONENTIATION_PER_BYTE : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 10 + ], + make_dict [] + |) +)). + +Definition GAS_MEMORY : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 3 + ], + make_dict [] + |) +)). + +Definition GAS_KECCAK256 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 30 + ], + make_dict [] + |) +)). + +Definition GAS_KECCAK256_WORD : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 6 + ], + make_dict [] + |) +)). + +Definition GAS_COPY : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 3 + ], + make_dict [] + |) +)). + +Definition GAS_BLOCK_HASH : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 20 + ], + make_dict [] + |) +)). + +Definition GAS_EXTERNAL : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 700 + ], + make_dict [] + |) +)). + +Definition GAS_BALANCE : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 400 + ], + make_dict [] + |) +)). + +Definition GAS_LOG : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 375 + ], + make_dict [] + |) +)). + +Definition GAS_LOG_DATA : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 8 + ], + make_dict [] + |) +)). + +Definition GAS_LOG_TOPIC : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 375 + ], + make_dict [] + |) +)). + +Definition GAS_CREATE : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 32000 + ], + make_dict [] + |) +)). + +Definition GAS_CODE_DEPOSIT : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 200 + ], + make_dict [] + |) +)). + +Definition GAS_ZERO : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) +)). + +Definition GAS_CALL : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 700 + ], + make_dict [] + |) +)). + +Definition GAS_NEW_ACCOUNT : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 25000 + ], + make_dict [] + |) +)). + +Definition GAS_CALL_VALUE : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 9000 + ], + make_dict [] + |) +)). + +Definition GAS_CALL_STIPEND : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 2300 + ], + make_dict [] + |) +)). + +Definition GAS_SELF_DESTRUCT : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 5000 + ], + make_dict [] + |) +)). + +Definition GAS_SELF_DESTRUCT_NEW_ACCOUNT : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 25000 + ], + make_dict [] + |) +)). + +Definition REFUND_SELF_DESTRUCT : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 24000 + ], + make_dict [] + |) +)). + +Definition GAS_ECRECOVER : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 3000 + ], + make_dict [] + |) +)). + +Definition GAS_SHA256 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 60 + ], + make_dict [] + |) +)). + +Definition GAS_SHA256_WORD : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 12 + ], + make_dict [] + |) +)). + +Definition GAS_RIPEMD160 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 600 + ], + make_dict [] + |) +)). + +Definition GAS_RIPEMD160_WORD : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 120 + ], + make_dict [] + |) +)). + +Definition GAS_IDENTITY : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 15 + ], + make_dict [] + |) +)). + +Definition GAS_IDENTITY_WORD : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 3 + ], + make_dict [] + |) +)). + +Definition ExtendMemory : Value.t := + builtins.make_klass + [] + [ + + ] + [ + + ]. + +Definition MessageCallGas : Value.t := + builtins.make_klass + [] + [ + + ] + [ + + ]. + +Definition charge_gas : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm"; "amount" ] |) in + let _ := Constant.str " + Subtracts `amount` from `evm.gas_left`. + + Parameters + ---------- + evm : + The current EVM. + amount : + The amount of gas the current operation requires. + + " in + let _ := M.call (| + M.get_name (| globals, "evm_trace" |), + make_list [ + M.get_name (| globals, "evm" |); + M.call (| + M.get_name (| globals, "GasAndRefund" |), + make_list [ + M.get_name (| globals, "amount" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.lt (| + M.get_field (| M.get_name (| globals, "evm" |), "gas_left" |), + M.get_name (| globals, "amount" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, "OutOfGasError" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_op (| + BinOp.sub, + M.get_field (| M.get_name (| globals, "evm" |), "gas_left" |), + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + M.get_name (| globals, "amount" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_)). + +Definition calculate_memory_gas_cost : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "size_in_bytes" ] |) in + let _ := Constant.str " + Calculates the gas cost for allocating memory + to the smallest multiple of 32 bytes, + such that the allocated size is at least as big as the given size. + + Parameters + ---------- + size_in_bytes : + The size of the data in bytes. + + Returns + ------- + total_gas_cost : `ethereum.base_types.Uint` + The gas cost for storing data in memory. + " in + let _ := M.assign_local (| + "size_in_words" , + BinOp.floor_div (| + M.call (| + M.get_name (| globals, "ceil32" |), + make_list [ + M.get_name (| globals, "size_in_bytes" |) + ], + make_dict [] + |), + Constant.int 32 + |) + |) in + let _ := M.assign_local (| + "linear_cost" , + BinOp.mult (| + M.get_name (| globals, "size_in_words" |), + M.get_name (| globals, "GAS_MEMORY" |) + |) + |) in + let _ := M.assign_local (| + "quadratic_cost" , + BinOp.floor_div (| + BinOp.pow (| + M.get_name (| globals, "size_in_words" |), + Constant.int 2 + |), + Constant.int 512 + |) + |) in + let _ := M.assign_local (| + "total_gas_cost" , + BinOp.add (| + M.get_name (| globals, "linear_cost" |), + M.get_name (| globals, "quadratic_cost" |) + |) + |) in +(* At stmt: unsupported node type: Try *) + M.pure Constant.None_)). + +Definition calculate_gas_extend_memory : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "memory"; "extensions" ] |) in + let _ := Constant.str " + Calculates the gas amount to extend memory + + Parameters + ---------- + memory : + Memory contents of the EVM. + extensions: + List of extensions to be made to the memory. + Consists of a tuple of start position and size. + + Returns + ------- + extend_memory: `ExtendMemory` + " in + let _ := M.assign_local (| + "size_to_extend" , + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "to_be_paid" , + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "current_size" , + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_name (| globals, "memory" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := + M.for_ (| + make_tuple [ M.get_name (| globals, "start_position" |); M.get_name (| globals, "size" |) ], + M.get_name (| globals, "extensions" |), + ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, "size" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.continue (| |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "before_size" , + M.call (| + M.get_name (| globals, "ceil32" |), + make_list [ + M.get_name (| globals, "current_size" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "after_size" , + M.call (| + M.get_name (| globals, "ceil32" |), + make_list [ + BinOp.add (| + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.get_name (| globals, "start_position" |) + ], + make_dict [] + |), + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.get_name (| globals, "size" |) + ], + make_dict [] + |) + |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.lt_e (| + M.get_name (| globals, "after_size" |), + M.get_name (| globals, "before_size" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.continue (| |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_op_local (| + BinOp.add, + "size_to_extend", + BinOp.sub (| + M.get_name (| globals, "after_size" |), + M.get_name (| globals, "before_size" |) + |) + |) in + let _ := M.assign_local (| + "already_paid" , + M.call (| + M.get_name (| globals, "calculate_memory_gas_cost" |), + make_list [ + M.get_name (| globals, "before_size" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "total_cost" , + M.call (| + M.get_name (| globals, "calculate_memory_gas_cost" |), + make_list [ + M.get_name (| globals, "after_size" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_op_local (| + BinOp.add, + "to_be_paid", + BinOp.sub (| + M.get_name (| globals, "total_cost" |), + M.get_name (| globals, "already_paid" |) + |) + |) in + let _ := M.assign_local (| + "current_size" , + M.get_name (| globals, "after_size" |) + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, "ExtendMemory" |), + make_list [ + M.get_name (| globals, "to_be_paid" |); + M.get_name (| globals, "size_to_extend" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Definition calculate_message_call_gas : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "value"; "gas"; "gas_left"; "memory_cost"; "extra_gas"; "call_stipend" ] |) in + let _ := Constant.str " + Calculates the MessageCallGas (cost and stipend) for + executing call Opcodes. + + Parameters + ---------- + value: + The amount of `ETH` that needs to be transferred. + gas : + The amount of gas provided to the message-call. + gas_left : + The amount of gas left in the current frame. + memory_cost : + The amount needed to extend the memory in the current frame. + extra_gas : + The amount of gas needed for transferring value + creating a new + account inside a message call. + call_stipend : + The amount of stipend provided to a message call to execute code while + transferring value(ETH). + + Returns + ------- + message_call_gas: `MessageCallGas` + " in + let _ := M.assign_local (| + "call_stipend" , + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, "value" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( +M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + (* else *) + )), ltac:(M.monadic ( +M.get_name (| globals, "call_stipend" |) + )) |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.lt (| + M.get_name (| globals, "gas_left" |), + BinOp.add (| + M.get_name (| globals, "extra_gas" |), + M.get_name (| globals, "memory_cost" |) + |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + M.call (| + M.get_name (| globals, "MessageCallGas" |), + make_list [ + BinOp.add (| + M.get_name (| globals, "gas" |), + M.get_name (| globals, "extra_gas" |) + |); + BinOp.add (| + M.get_name (| globals, "gas" |), + M.get_name (| globals, "call_stipend" |) + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "gas" , + M.call (| + M.get_name (| globals, "min" |), + make_list [ + M.get_name (| globals, "gas" |); + M.call (| + M.get_name (| globals, "max_message_call_gas" |), + make_list [ + BinOp.sub (| + BinOp.sub (| + M.get_name (| globals, "gas_left" |), + M.get_name (| globals, "memory_cost" |) + |), + M.get_name (| globals, "extra_gas" |) + |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, "MessageCallGas" |), + make_list [ + BinOp.add (| + M.get_name (| globals, "gas" |), + M.get_name (| globals, "extra_gas" |) + |); + BinOp.add (| + M.get_name (| globals, "gas" |), + M.get_name (| globals, "call_stipend" |) + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Definition max_message_call_gas : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "gas" ] |) in + let _ := Constant.str " + Calculates the maximum gas that is allowed for making a message call + + Parameters + ---------- + gas : + The amount of gas provided to the message-call. + + Returns + ------- + max_allowed_message_call_gas: `ethereum.base_types.Uint` + The maximum gas allowed for making the message-call. + " in + let _ := M.return_ (| + BinOp.sub (| + M.get_name (| globals, "gas" |), + BinOp.floor_div (| + M.get_name (| globals, "gas" |), + Constant.int 64 + |) + |) + |) in + M.pure Constant.None_)). diff --git a/CoqOfPython/ethereum/tangerine_whistle/vm/instructions/__init__.v b/CoqOfPython/ethereum/tangerine_whistle/vm/instructions/__init__.v new file mode 100644 index 0000000..22a0b88 --- /dev/null +++ b/CoqOfPython/ethereum/tangerine_whistle/vm/instructions/__init__.v @@ -0,0 +1,74 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.tangerine_whistle.vm.instructions.__init__". + +Definition expr_1 : Value.t := + Constant.str " +EVM Instruction Encoding (Opcodes) +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Machine readable representations of EVM instructions, and a mapping to their +implementations. +". + +(* At top_level_stmt: unsupported node type: Import *) + +Axiom typing_imports_Callable : + IsImported globals "typing" "Callable". +Axiom typing_imports_Dict : + IsImported globals "typing" "Dict". + +Axiom ethereum_tangerine_whistle_vm_instructions_imports_arithmetic : + IsImported globals "ethereum.tangerine_whistle.vm.instructions" "arithmetic". + +Axiom ethereum_tangerine_whistle_vm_instructions_imports_bitwise : + IsImported globals "ethereum.tangerine_whistle.vm.instructions" "bitwise". + +Axiom ethereum_tangerine_whistle_vm_instructions_imports_block : + IsImported globals "ethereum.tangerine_whistle.vm.instructions" "block". + +Axiom ethereum_tangerine_whistle_vm_instructions_imports_comparison : + IsImported globals "ethereum.tangerine_whistle.vm.instructions" "comparison". + +Axiom ethereum_tangerine_whistle_vm_instructions_imports_control_flow : + IsImported globals "ethereum.tangerine_whistle.vm.instructions" "control_flow". + +Axiom ethereum_tangerine_whistle_vm_instructions_imports_environment : + IsImported globals "ethereum.tangerine_whistle.vm.instructions" "environment". + +Axiom ethereum_tangerine_whistle_vm_instructions_imports_keccak : + IsImported globals "ethereum.tangerine_whistle.vm.instructions" "keccak". + +Axiom ethereum_tangerine_whistle_vm_instructions_imports_log : + IsImported globals "ethereum.tangerine_whistle.vm.instructions" "log". + +Axiom ethereum_tangerine_whistle_vm_instructions_imports_memory : + IsImported globals "ethereum.tangerine_whistle.vm.instructions" "memory". + +Axiom ethereum_tangerine_whistle_vm_instructions_imports_stack : + IsImported globals "ethereum.tangerine_whistle.vm.instructions" "stack". + +Axiom ethereum_tangerine_whistle_vm_instructions_imports_storage : + IsImported globals "ethereum.tangerine_whistle.vm.instructions" "storage". + +Axiom ethereum_tangerine_whistle_vm_instructions_imports_system : + IsImported globals "ethereum.tangerine_whistle.vm.instructions" "system". + +Definition Ops : Value.t := + builtins.make_klass + [(* At base: unsupported node type: Attribute *)] + [ + + ] + [ + + ]. + +(* At top_level_stmt: unsupported node type: AnnAssign *) diff --git a/CoqOfPython/ethereum/tangerine_whistle/vm/instructions/arithmetic.v b/CoqOfPython/ethereum/tangerine_whistle/vm/instructions/arithmetic.v new file mode 100644 index 0000000..6908f7e --- /dev/null +++ b/CoqOfPython/ethereum/tangerine_whistle/vm/instructions/arithmetic.v @@ -0,0 +1,1220 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.tangerine_whistle.vm.instructions.arithmetic". + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) Arithmetic Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM Arithmetic instructions. +". + +Axiom ethereum_base_types_imports_U255_CEIL_VALUE : + IsImported globals "ethereum.base_types" "U255_CEIL_VALUE". +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_U256_CEIL_VALUE : + IsImported globals "ethereum.base_types" "U256_CEIL_VALUE". +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". + +Axiom ethereum_utils_numeric_imports_get_sign : + IsImported globals "ethereum.utils.numeric" "get_sign". + +Axiom ethereum_tangerine_whistle_vm_imports_Evm : + IsImported globals "ethereum.tangerine_whistle.vm" "Evm". + +Axiom ethereum_tangerine_whistle_vm_gas_imports_GAS_EXPONENTIATION : + IsImported globals "ethereum.tangerine_whistle.vm.gas" "GAS_EXPONENTIATION". +Axiom ethereum_tangerine_whistle_vm_gas_imports_GAS_EXPONENTIATION_PER_BYTE : + IsImported globals "ethereum.tangerine_whistle.vm.gas" "GAS_EXPONENTIATION_PER_BYTE". +Axiom ethereum_tangerine_whistle_vm_gas_imports_GAS_LOW : + IsImported globals "ethereum.tangerine_whistle.vm.gas" "GAS_LOW". +Axiom ethereum_tangerine_whistle_vm_gas_imports_GAS_MID : + IsImported globals "ethereum.tangerine_whistle.vm.gas" "GAS_MID". +Axiom ethereum_tangerine_whistle_vm_gas_imports_GAS_VERY_LOW : + IsImported globals "ethereum.tangerine_whistle.vm.gas" "GAS_VERY_LOW". +Axiom ethereum_tangerine_whistle_vm_gas_imports_charge_gas : + IsImported globals "ethereum.tangerine_whistle.vm.gas" "charge_gas". + +Axiom ethereum_tangerine_whistle_vm_stack_imports_pop : + IsImported globals "ethereum.tangerine_whistle.vm.stack" "pop". +Axiom ethereum_tangerine_whistle_vm_stack_imports_push : + IsImported globals "ethereum.tangerine_whistle.vm.stack" "push". + +Definition add : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Adds the top two elements of the stack together, and pushes the result back + on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "x" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "y" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_VERY_LOW" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "result" , + M.call (| + M.get_field (| M.get_name (| globals, "x" |), "wrapping_add" |), + make_list [ + M.get_name (| globals, "y" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.get_name (| globals, "result" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition sub : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Subtracts the top two elements of the stack, and pushes the result back + on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "x" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "y" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_VERY_LOW" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "result" , + M.call (| + M.get_field (| M.get_name (| globals, "x" |), "wrapping_sub" |), + make_list [ + M.get_name (| globals, "y" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.get_name (| globals, "result" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition mul : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Multiply the top two elements of the stack, and pushes the result back + on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "x" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "y" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_LOW" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "result" , + M.call (| + M.get_field (| M.get_name (| globals, "x" |), "wrapping_mul" |), + make_list [ + M.get_name (| globals, "y" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.get_name (| globals, "result" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition div : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Integer division of the top two elements of the stack. Pushes the result + back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "dividend" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "divisor" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_LOW" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, "divisor" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "quotient" , + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "quotient" , + BinOp.floor_div (| + M.get_name (| globals, "dividend" |), + M.get_name (| globals, "divisor" |) + |) + |) in + M.pure Constant.None_ + )) |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.get_name (| globals, "quotient" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition sdiv : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Signed integer division of the top two elements of the stack. Pushes the + result back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "dividend" , + M.call (| + M.get_field (| M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |), "to_signed" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "divisor" , + M.call (| + M.get_field (| M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |), "to_signed" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_LOW" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, "divisor" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "quotient" , + Constant.int 0 + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + BoolOp.and (| + Compare.eq (| + M.get_name (| globals, "dividend" |), + UnOp.sub (| M.get_name (| globals, "U255_CEIL_VALUE" |) |) + |), + ltac:(M.monadic ( + Compare.eq (| + M.get_name (| globals, "divisor" |), + UnOp.sub (| Constant.int 1 |) + |) + )) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "quotient" , + UnOp.sub (| M.get_name (| globals, "U255_CEIL_VALUE" |) |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "sign" , + M.call (| + M.get_name (| globals, "get_sign" |), + make_list [ + BinOp.mult (| + M.get_name (| globals, "dividend" |), + M.get_name (| globals, "divisor" |) + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "quotient" , + BinOp.mult (| + M.get_name (| globals, "sign" |), + BinOp.floor_div (| + M.call (| + M.get_name (| globals, "abs" |), + make_list [ + M.get_name (| globals, "dividend" |) + ], + make_dict [] + |), + M.call (| + M.get_name (| globals, "abs" |), + make_list [ + M.get_name (| globals, "divisor" |) + ], + make_dict [] + |) + |) + |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )) |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.call (| + M.get_field (| M.get_name (| globals, "U256" |), "from_signed" |), + make_list [ + M.get_name (| globals, "quotient" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition mod_ : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Modulo remainder of the top two elements of the stack. Pushes the result + back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "x" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "y" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_LOW" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, "y" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "remainder" , + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "remainder" , + BinOp.mod_ (| + M.get_name (| globals, "x" |), + M.get_name (| globals, "y" |) + |) + |) in + M.pure Constant.None_ + )) |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.get_name (| globals, "remainder" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition smod : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Signed modulo remainder of the top two elements of the stack. Pushes the + result back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "x" , + M.call (| + M.get_field (| M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |), "to_signed" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "y" , + M.call (| + M.get_field (| M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |), "to_signed" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_LOW" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, "y" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "remainder" , + Constant.int 0 + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "remainder" , + BinOp.mult (| + M.call (| + M.get_name (| globals, "get_sign" |), + make_list [ + M.get_name (| globals, "x" |) + ], + make_dict [] + |), + BinOp.mod_ (| + M.call (| + M.get_name (| globals, "abs" |), + make_list [ + M.get_name (| globals, "x" |) + ], + make_dict [] + |), + M.call (| + M.get_name (| globals, "abs" |), + make_list [ + M.get_name (| globals, "y" |) + ], + make_dict [] + |) + |) + |) + |) in + M.pure Constant.None_ + )) |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.call (| + M.get_field (| M.get_name (| globals, "U256" |), "from_signed" |), + make_list [ + M.get_name (| globals, "remainder" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition addmod : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Modulo addition of the top 2 elements with the 3rd element. Pushes the + result back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "x" , + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "y" , + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "z" , + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_MID" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, "z" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "result" , + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "result" , + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + BinOp.mod_ (| + BinOp.add (| + M.get_name (| globals, "x" |), + M.get_name (| globals, "y" |) + |), + M.get_name (| globals, "z" |) + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + )) |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.get_name (| globals, "result" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition mulmod : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Modulo multiplication of the top 2 elements with the 3rd element. Pushes + the result back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "x" , + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "y" , + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "z" , + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_MID" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, "z" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "result" , + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "result" , + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + BinOp.mod_ (| + BinOp.mult (| + M.get_name (| globals, "x" |), + M.get_name (| globals, "y" |) + |), + M.get_name (| globals, "z" |) + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + )) |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.get_name (| globals, "result" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition exp : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Exponential operation of the top 2 elements. Pushes the result back on + the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "base" , + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "exponent" , + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "exponent_bits" , + M.call (| + M.get_field (| M.get_name (| globals, "exponent" |), "bit_length" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "exponent_bytes" , + BinOp.floor_div (| + BinOp.add (| + M.get_name (| globals, "exponent_bits" |), + Constant.int 7 + |), + Constant.int 8 + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + BinOp.add (| + M.get_name (| globals, "GAS_EXPONENTIATION" |), + BinOp.mult (| + M.get_name (| globals, "GAS_EXPONENTIATION_PER_BYTE" |), + M.get_name (| globals, "exponent_bytes" |) + |) + |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "result" , + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + M.call (| + M.get_name (| globals, "pow" |), + make_list [ + M.get_name (| globals, "base" |); + M.get_name (| globals, "exponent" |); + M.get_name (| globals, "U256_CEIL_VALUE" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.get_name (| globals, "result" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition signextend : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Sign extend operation. In other words, extend a signed number which + fits in N bytes to 32 bytes. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "byte_num" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "value" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_LOW" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.gt (| + M.get_name (| globals, "byte_num" |), + Constant.int 31 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "result" , + M.get_name (| globals, "value" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "value_bytes" , + M.call (| + M.get_name (| globals, "bytes" |), + make_list [ + M.call (| + M.get_field (| M.get_name (| globals, "value" |), "to_be_bytes32" |), + make_list [], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "value_bytes" , + M.slice (| + M.get_name (| globals, "value_bytes" |), + BinOp.sub (| + Constant.int 31, + M.call (| + M.get_name (| globals, "int" |), + make_list [ + M.get_name (| globals, "byte_num" |) + ], + make_dict [] + |) + |), + Constant.None_, + Constant.None_ + |) + |) in + let _ := M.assign_local (| + "sign_bit" , + BinOp.r_shift (| + M.get_subscript (| + M.get_name (| globals, "value_bytes" |), + Constant.int 0 + |), + Constant.int 7 + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, "sign_bit" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "result" , + M.call (| + M.get_field (| M.get_name (| globals, "U256" |), "from_be_bytes" |), + make_list [ + M.get_name (| globals, "value_bytes" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "num_bytes_prepend" , + BinOp.sub (| + Constant.int 32, + BinOp.add (| + M.get_name (| globals, "byte_num" |), + Constant.int 1 + |) + |) + |) in + let _ := M.assign_local (| + "result" , + M.call (| + M.get_field (| M.get_name (| globals, "U256" |), "from_be_bytes" |), + make_list [ + BinOp.add (| + M.call (| + M.get_name (| globals, "bytearray" |), + make_list [ + BinOp.mult (| + make_list [ + Constant.int 255 + ], + M.get_name (| globals, "num_bytes_prepend" |) + |) + ], + make_dict [] + |), + M.get_name (| globals, "value_bytes" |) + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )) |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.get_name (| globals, "result" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). diff --git a/CoqOfPython/ethereum/tangerine_whistle/vm/instructions/bitwise.v b/CoqOfPython/ethereum/tangerine_whistle/vm/instructions/bitwise.v new file mode 100644 index 0000000..b526d4e --- /dev/null +++ b/CoqOfPython/ethereum/tangerine_whistle/vm/instructions/bitwise.v @@ -0,0 +1,372 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.tangerine_whistle.vm.instructions.bitwise". + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) Bitwise Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM bitwise instructions. +". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". + +Axiom ethereum_tangerine_whistle_vm_imports_Evm : + IsImported globals "ethereum.tangerine_whistle.vm" "Evm". + +Axiom ethereum_tangerine_whistle_vm_gas_imports_GAS_VERY_LOW : + IsImported globals "ethereum.tangerine_whistle.vm.gas" "GAS_VERY_LOW". +Axiom ethereum_tangerine_whistle_vm_gas_imports_charge_gas : + IsImported globals "ethereum.tangerine_whistle.vm.gas" "charge_gas". + +Axiom ethereum_tangerine_whistle_vm_stack_imports_pop : + IsImported globals "ethereum.tangerine_whistle.vm.stack" "pop". +Axiom ethereum_tangerine_whistle_vm_stack_imports_push : + IsImported globals "ethereum.tangerine_whistle.vm.stack" "push". + +Definition bitwise_and : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Bitwise AND operation of the top 2 elements of the stack. Pushes the + result back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "x" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "y" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_VERY_LOW" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + BinOp.bit_and (| + M.get_name (| globals, "x" |), + M.get_name (| globals, "y" |) + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition bitwise_or : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Bitwise OR operation of the top 2 elements of the stack. Pushes the + result back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "x" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "y" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_VERY_LOW" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + BinOp.bit_or (| + M.get_name (| globals, "x" |), + M.get_name (| globals, "y" |) + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition bitwise_xor : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Bitwise XOR operation of the top 2 elements of the stack. Pushes the + result back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "x" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "y" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_VERY_LOW" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + BinOp.bit_xor (| + M.get_name (| globals, "x" |), + M.get_name (| globals, "y" |) + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition bitwise_not : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Bitwise NOT operation of the top element of the stack. Pushes the + result back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "x" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_VERY_LOW" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + UnOp.invert (| M.get_name (| globals, "x" |) |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition get_byte : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + For a word (defined by next top element of the stack), retrieve the + Nth byte (0-indexed and defined by top element of stack) from the + left (most significant) to right (least significant). + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "byte_index" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "word" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_VERY_LOW" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.gt_e (| + M.get_name (| globals, "byte_index" |), + Constant.int 32 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "result" , + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "extra_bytes_to_right" , + BinOp.sub (| + Constant.int 31, + M.get_name (| globals, "byte_index" |) + |) + |) in + let _ := M.assign_local (| + "word" , + BinOp.r_shift (| + M.get_name (| globals, "word" |), + BinOp.mult (| + M.get_name (| globals, "extra_bytes_to_right" |), + Constant.int 8 + |) + |) + |) in + let _ := M.assign_local (| + "word" , + BinOp.bit_and (| + M.get_name (| globals, "word" |), + Constant.int 255 + |) + |) in + let _ := M.assign_local (| + "result" , + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + M.get_name (| globals, "word" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + )) |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.get_name (| globals, "result" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). diff --git a/CoqOfPython/ethereum/tangerine_whistle/vm/instructions/block.v b/CoqOfPython/ethereum/tangerine_whistle/vm/instructions/block.v new file mode 100644 index 0000000..22c744e --- /dev/null +++ b/CoqOfPython/ethereum/tangerine_whistle/vm/instructions/block.v @@ -0,0 +1,348 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.tangerine_whistle.vm.instructions.block". + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) Block Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM block instructions. +". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". + +Axiom ethereum_tangerine_whistle_vm_imports_Evm : + IsImported globals "ethereum.tangerine_whistle.vm" "Evm". + +Axiom ethereum_tangerine_whistle_vm_gas_imports_GAS_BASE : + IsImported globals "ethereum.tangerine_whistle.vm.gas" "GAS_BASE". +Axiom ethereum_tangerine_whistle_vm_gas_imports_GAS_BLOCK_HASH : + IsImported globals "ethereum.tangerine_whistle.vm.gas" "GAS_BLOCK_HASH". +Axiom ethereum_tangerine_whistle_vm_gas_imports_charge_gas : + IsImported globals "ethereum.tangerine_whistle.vm.gas" "charge_gas". + +Axiom ethereum_tangerine_whistle_vm_stack_imports_pop : + IsImported globals "ethereum.tangerine_whistle.vm.stack" "pop". +Axiom ethereum_tangerine_whistle_vm_stack_imports_push : + IsImported globals "ethereum.tangerine_whistle.vm.stack" "push". + +Definition block_hash : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Push the hash of one of the 256 most recent complete blocks onto the + stack. The block number to hash is present at the top of the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "block_number" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_BLOCK_HASH" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + BoolOp.or (| + Compare.lt_e (| + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "env" |), "number" |), + M.get_name (| globals, "block_number" |) + |), + ltac:(M.monadic ( + Compare.gt (| + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "env" |), "number" |), + BinOp.add (| + M.get_name (| globals, "block_number" |), + Constant.int 256 + |) + |) + )) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "hash" , + Constant.bytes "00" + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "hash" , + M.get_subscript (| + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "env" |), "block_hashes" |), + UnOp.sub (| BinOp.sub (| + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "env" |), "number" |), + M.get_name (| globals, "block_number" |) + |) |) + |) + |) in + M.pure Constant.None_ + )) |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.call (| + M.get_field (| M.get_name (| globals, "U256" |), "from_be_bytes" |), + make_list [ + M.get_name (| globals, "hash" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition coinbase : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Push the current block's beneficiary address (address of the block miner) + onto the stack. + + Here the current block refers to the block in which the currently + executing transaction/call resides. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_BASE" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.call (| + M.get_field (| M.get_name (| globals, "U256" |), "from_be_bytes" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "env" |), "coinbase" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition timestamp : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Push the current block's timestamp onto the stack. Here the timestamp + being referred is actually the unix timestamp in seconds. + + Here the current block refers to the block in which the currently + executing transaction/call resides. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_BASE" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "env" |), "time" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition number : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Push the current block's number onto the stack. + + Here the current block refers to the block in which the currently + executing transaction/call resides. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_BASE" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "env" |), "number" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition difficulty : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Push the current block's difficulty onto the stack. + + Here the current block refers to the block in which the currently + executing transaction/call resides. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_BASE" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "env" |), "difficulty" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition gas_limit : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Push the current block's gas limit onto the stack. + + Here the current block refers to the block in which the currently + executing transaction/call resides. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_BASE" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "env" |), "gas_limit" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). diff --git a/CoqOfPython/ethereum/tangerine_whistle/vm/instructions/comparison.v b/CoqOfPython/ethereum/tangerine_whistle/vm/instructions/comparison.v new file mode 100644 index 0000000..7e7ac0d --- /dev/null +++ b/CoqOfPython/ethereum/tangerine_whistle/vm/instructions/comparison.v @@ -0,0 +1,452 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.tangerine_whistle.vm.instructions.comparison". + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) Comparison Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM Comparison instructions. +". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". + +Axiom ethereum_tangerine_whistle_vm_imports_Evm : + IsImported globals "ethereum.tangerine_whistle.vm" "Evm". + +Axiom ethereum_tangerine_whistle_vm_gas_imports_GAS_VERY_LOW : + IsImported globals "ethereum.tangerine_whistle.vm.gas" "GAS_VERY_LOW". +Axiom ethereum_tangerine_whistle_vm_gas_imports_charge_gas : + IsImported globals "ethereum.tangerine_whistle.vm.gas" "charge_gas". + +Axiom ethereum_tangerine_whistle_vm_stack_imports_pop : + IsImported globals "ethereum.tangerine_whistle.vm.stack" "pop". +Axiom ethereum_tangerine_whistle_vm_stack_imports_push : + IsImported globals "ethereum.tangerine_whistle.vm.stack" "push". + +Definition less_than : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Checks if the top element is less than the next top element. Pushes the + result back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "left" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "right" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_VERY_LOW" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "result" , + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Compare.lt (| + M.get_name (| globals, "left" |), + M.get_name (| globals, "right" |) + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.get_name (| globals, "result" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition signed_less_than : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Signed less-than comparison. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "left" , + M.call (| + M.get_field (| M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |), "to_signed" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "right" , + M.call (| + M.get_field (| M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |), "to_signed" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_VERY_LOW" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "result" , + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Compare.lt (| + M.get_name (| globals, "left" |), + M.get_name (| globals, "right" |) + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.get_name (| globals, "result" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition greater_than : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Checks if the top element is greater than the next top element. Pushes + the result back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "left" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "right" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_VERY_LOW" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "result" , + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Compare.gt (| + M.get_name (| globals, "left" |), + M.get_name (| globals, "right" |) + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.get_name (| globals, "result" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition signed_greater_than : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Signed greater-than comparison. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "left" , + M.call (| + M.get_field (| M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |), "to_signed" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "right" , + M.call (| + M.get_field (| M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |), "to_signed" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_VERY_LOW" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "result" , + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Compare.gt (| + M.get_name (| globals, "left" |), + M.get_name (| globals, "right" |) + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.get_name (| globals, "result" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition equal : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Checks if the top element is equal to the next top element. Pushes + the result back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "left" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "right" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_VERY_LOW" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "result" , + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Compare.eq (| + M.get_name (| globals, "left" |), + M.get_name (| globals, "right" |) + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.get_name (| globals, "result" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition is_zero : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Checks if the top element is equal to 0. Pushes the result back on the + stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "x" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_VERY_LOW" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "result" , + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Compare.eq (| + M.get_name (| globals, "x" |), + Constant.int 0 + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.get_name (| globals, "result" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). diff --git a/CoqOfPython/ethereum/tangerine_whistle/vm/instructions/control_flow.v b/CoqOfPython/ethereum/tangerine_whistle/vm/instructions/control_flow.v new file mode 100644 index 0000000..6ba53bf --- /dev/null +++ b/CoqOfPython/ethereum/tangerine_whistle/vm/instructions/control_flow.v @@ -0,0 +1,350 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.tangerine_whistle.vm.instructions.control_flow". + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) Control Flow Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM control flow instructions. +". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". + +Axiom ethereum_tangerine_whistle_vm_gas_imports_GAS_BASE : + IsImported globals "ethereum.tangerine_whistle.vm.gas" "GAS_BASE". +Axiom ethereum_tangerine_whistle_vm_gas_imports_GAS_HIGH : + IsImported globals "ethereum.tangerine_whistle.vm.gas" "GAS_HIGH". +Axiom ethereum_tangerine_whistle_vm_gas_imports_GAS_JUMPDEST : + IsImported globals "ethereum.tangerine_whistle.vm.gas" "GAS_JUMPDEST". +Axiom ethereum_tangerine_whistle_vm_gas_imports_GAS_MID : + IsImported globals "ethereum.tangerine_whistle.vm.gas" "GAS_MID". +Axiom ethereum_tangerine_whistle_vm_gas_imports_charge_gas : + IsImported globals "ethereum.tangerine_whistle.vm.gas" "charge_gas". + +Axiom ethereum_tangerine_whistle_vm_imports_Evm : + IsImported globals "ethereum.tangerine_whistle.vm" "Evm". + +Axiom ethereum_tangerine_whistle_vm_exceptions_imports_InvalidJumpDestError : + IsImported globals "ethereum.tangerine_whistle.vm.exceptions" "InvalidJumpDestError". + +Axiom ethereum_tangerine_whistle_vm_stack_imports_pop : + IsImported globals "ethereum.tangerine_whistle.vm.stack" "pop". +Axiom ethereum_tangerine_whistle_vm_stack_imports_push : + IsImported globals "ethereum.tangerine_whistle.vm.stack" "push". + +Definition stop : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Stop further execution of EVM code. + + Parameters + ---------- + evm : + The current EVM frame. + " in + let _ := M.pass (| |) in + let _ := M.pass (| |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, "evm" |), "running" |), + Constant.bool false + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition jump : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Alter the program counter to the location specified by the top of the + stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "jump_dest" , + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_MID" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.not_in (| + M.get_name (| globals, "jump_dest" |), + M.get_field (| M.get_name (| globals, "evm" |), "valid_jump_destinations" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, "InvalidJumpDestError" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.get_name (| globals, "jump_dest" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Definition jumpi : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Alter the program counter to the specified location if and only if a + condition is true. If the condition is not true, then the program counter + would increase only by 1. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "jump_dest" , + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "conditional_value" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_HIGH" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, "conditional_value" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "destination" , + BinOp.add (| + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + Compare.not_in (| + M.get_name (| globals, "jump_dest" |), + M.get_field (| M.get_name (| globals, "evm" |), "valid_jump_destinations" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, "InvalidJumpDestError" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "destination" , + M.get_name (| globals, "jump_dest" |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )) |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.get_name (| globals, "destination" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Definition pc : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Push onto the stack the value of the program counter after reaching the + current instruction and without increasing it for the next instruction. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_BASE" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "pc" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition gas_left : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Push the amount of available gas (including the corresponding reduction + for the cost of this instruction) onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_BASE" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "gas_left" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition jumpdest : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Mark a valid destination for jumps. This is a noop, present only + to be used by `JUMP` and `JUMPI` opcodes to verify that their jump is + valid. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_JUMPDEST" |) + ], + make_dict [] + |) in + let _ := M.pass (| |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). diff --git a/CoqOfPython/ethereum/tangerine_whistle/vm/instructions/environment.v b/CoqOfPython/ethereum/tangerine_whistle/vm/instructions/environment.v new file mode 100644 index 0000000..6f5e691 --- /dev/null +++ b/CoqOfPython/ethereum/tangerine_whistle/vm/instructions/environment.v @@ -0,0 +1,993 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.tangerine_whistle.vm.instructions.environment". + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) Environmental Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM environment related instructions. +". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". + +Axiom ethereum_utils_numeric_imports_ceil32 : + IsImported globals "ethereum.utils.numeric" "ceil32". + +Axiom ethereum_tangerine_whistle_state_imports_get_account : + IsImported globals "ethereum.tangerine_whistle.state" "get_account". + +Axiom ethereum_tangerine_whistle_utils_address_imports_to_address : + IsImported globals "ethereum.tangerine_whistle.utils.address" "to_address". + +Axiom ethereum_tangerine_whistle_vm_memory_imports_buffer_read : + IsImported globals "ethereum.tangerine_whistle.vm.memory" "buffer_read". +Axiom ethereum_tangerine_whistle_vm_memory_imports_memory_write : + IsImported globals "ethereum.tangerine_whistle.vm.memory" "memory_write". + +Axiom ethereum_tangerine_whistle_vm_imports_Evm : + IsImported globals "ethereum.tangerine_whistle.vm" "Evm". + +Axiom ethereum_tangerine_whistle_vm_gas_imports_GAS_BALANCE : + IsImported globals "ethereum.tangerine_whistle.vm.gas" "GAS_BALANCE". +Axiom ethereum_tangerine_whistle_vm_gas_imports_GAS_BASE : + IsImported globals "ethereum.tangerine_whistle.vm.gas" "GAS_BASE". +Axiom ethereum_tangerine_whistle_vm_gas_imports_GAS_COPY : + IsImported globals "ethereum.tangerine_whistle.vm.gas" "GAS_COPY". +Axiom ethereum_tangerine_whistle_vm_gas_imports_GAS_EXTERNAL : + IsImported globals "ethereum.tangerine_whistle.vm.gas" "GAS_EXTERNAL". +Axiom ethereum_tangerine_whistle_vm_gas_imports_GAS_VERY_LOW : + IsImported globals "ethereum.tangerine_whistle.vm.gas" "GAS_VERY_LOW". +Axiom ethereum_tangerine_whistle_vm_gas_imports_calculate_gas_extend_memory : + IsImported globals "ethereum.tangerine_whistle.vm.gas" "calculate_gas_extend_memory". +Axiom ethereum_tangerine_whistle_vm_gas_imports_charge_gas : + IsImported globals "ethereum.tangerine_whistle.vm.gas" "charge_gas". + +Axiom ethereum_tangerine_whistle_vm_stack_imports_pop : + IsImported globals "ethereum.tangerine_whistle.vm.stack" "pop". +Axiom ethereum_tangerine_whistle_vm_stack_imports_push : + IsImported globals "ethereum.tangerine_whistle.vm.stack" "push". + +Definition address : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Pushes the address of the current executing account to the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_BASE" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.call (| + M.get_field (| M.get_name (| globals, "U256" |), "from_be_bytes" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "current_target" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition balance : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Pushes the balance of the given account onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "address" , + M.call (| + M.get_name (| globals, "to_address" |), + make_list [ + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_BALANCE" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "balance" , + M.get_field (| M.call (| + M.get_name (| globals, "get_account" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "env" |), "state" |); + M.get_name (| globals, "address" |) + ], + make_dict [] + |), "balance" |) + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.get_name (| globals, "balance" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition origin : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Pushes the address of the original transaction sender to the stack. + The origin address can only be an EOA. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_BASE" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.call (| + M.get_field (| M.get_name (| globals, "U256" |), "from_be_bytes" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "env" |), "origin" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition caller : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Pushes the address of the caller onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_BASE" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.call (| + M.get_field (| M.get_name (| globals, "U256" |), "from_be_bytes" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "caller" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition callvalue : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Push the value (in wei) sent with the call onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_BASE" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "value" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition calldataload : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Push a word (32 bytes) of the input data belonging to the current + environment onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "start_index" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_VERY_LOW" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "value" , + M.call (| + M.get_name (| globals, "buffer_read" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "data" |); + M.get_name (| globals, "start_index" |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 32 + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.call (| + M.get_field (| M.get_name (| globals, "U256" |), "from_be_bytes" |), + make_list [ + M.get_name (| globals, "value" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition calldatasize : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Push the size of input data in current environment onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_BASE" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "data" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition calldatacopy : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Copy a portion of the input data in current environment to memory. + + This will also expand the memory, in case that the memory is insufficient + to store the data. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "memory_start_index" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "data_start_index" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "size" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "words" , + BinOp.floor_div (| + M.call (| + M.get_name (| globals, "ceil32" |), + make_list [ + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.get_name (| globals, "size" |) + ], + make_dict [] + |) + ], + make_dict [] + |), + Constant.int 32 + |) + |) in + let _ := M.assign_local (| + "copy_gas_cost" , + BinOp.mult (| + M.get_name (| globals, "GAS_COPY" |), + M.get_name (| globals, "words" |) + |) + |) in + let _ := M.assign_local (| + "extend_memory" , + M.call (| + M.get_name (| globals, "calculate_gas_extend_memory" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "memory" |); + make_list [ + make_tuple [ M.get_name (| globals, "memory_start_index" |); M.get_name (| globals, "size" |) ] + ] + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + BinOp.add (| + BinOp.add (| + M.get_name (| globals, "GAS_VERY_LOW" |), + M.get_name (| globals, "copy_gas_cost" |) + |), + M.get_field (| M.get_name (| globals, "extend_memory" |), "cost" |) + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "memory" |), + BinOp.mult (| + Constant.bytes "00", + M.get_field (| M.get_name (| globals, "extend_memory" |), "expand_by" |) + |) + |) in + let _ := M.assign_local (| + "value" , + M.call (| + M.get_name (| globals, "buffer_read" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "data" |); + M.get_name (| globals, "data_start_index" |); + M.get_name (| globals, "size" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "memory_write" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "memory" |); + M.get_name (| globals, "memory_start_index" |); + M.get_name (| globals, "value" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition codesize : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Push the size of code running in current environment onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_BASE" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "code" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition codecopy : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Copy a portion of the code in current environment to memory. + + This will also expand the memory, in case that the memory is insufficient + to store the data. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "memory_start_index" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "code_start_index" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "size" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "words" , + BinOp.floor_div (| + M.call (| + M.get_name (| globals, "ceil32" |), + make_list [ + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.get_name (| globals, "size" |) + ], + make_dict [] + |) + ], + make_dict [] + |), + Constant.int 32 + |) + |) in + let _ := M.assign_local (| + "copy_gas_cost" , + BinOp.mult (| + M.get_name (| globals, "GAS_COPY" |), + M.get_name (| globals, "words" |) + |) + |) in + let _ := M.assign_local (| + "extend_memory" , + M.call (| + M.get_name (| globals, "calculate_gas_extend_memory" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "memory" |); + make_list [ + make_tuple [ M.get_name (| globals, "memory_start_index" |); M.get_name (| globals, "size" |) ] + ] + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + BinOp.add (| + BinOp.add (| + M.get_name (| globals, "GAS_VERY_LOW" |), + M.get_name (| globals, "copy_gas_cost" |) + |), + M.get_field (| M.get_name (| globals, "extend_memory" |), "cost" |) + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "memory" |), + BinOp.mult (| + Constant.bytes "00", + M.get_field (| M.get_name (| globals, "extend_memory" |), "expand_by" |) + |) + |) in + let _ := M.assign_local (| + "value" , + M.call (| + M.get_name (| globals, "buffer_read" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "code" |); + M.get_name (| globals, "code_start_index" |); + M.get_name (| globals, "size" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "memory_write" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "memory" |); + M.get_name (| globals, "memory_start_index" |); + M.get_name (| globals, "value" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition gasprice : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Push the gas price used in current environment onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_BASE" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "env" |), "gas_price" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition extcodesize : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Push the code size of a given account onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "address" , + M.call (| + M.get_name (| globals, "to_address" |), + make_list [ + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_EXTERNAL" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "codesize" , + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_field (| M.call (| + M.get_name (| globals, "get_account" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "env" |), "state" |); + M.get_name (| globals, "address" |) + ], + make_dict [] + |), "code" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.get_name (| globals, "codesize" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition extcodecopy : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Copy a portion of an account's code to memory. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "address" , + M.call (| + M.get_name (| globals, "to_address" |), + make_list [ + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_start_index" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "code_start_index" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "size" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "words" , + BinOp.floor_div (| + M.call (| + M.get_name (| globals, "ceil32" |), + make_list [ + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.get_name (| globals, "size" |) + ], + make_dict [] + |) + ], + make_dict [] + |), + Constant.int 32 + |) + |) in + let _ := M.assign_local (| + "copy_gas_cost" , + BinOp.mult (| + M.get_name (| globals, "GAS_COPY" |), + M.get_name (| globals, "words" |) + |) + |) in + let _ := M.assign_local (| + "extend_memory" , + M.call (| + M.get_name (| globals, "calculate_gas_extend_memory" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "memory" |); + make_list [ + make_tuple [ M.get_name (| globals, "memory_start_index" |); M.get_name (| globals, "size" |) ] + ] + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + BinOp.add (| + BinOp.add (| + M.get_name (| globals, "GAS_EXTERNAL" |), + M.get_name (| globals, "copy_gas_cost" |) + |), + M.get_field (| M.get_name (| globals, "extend_memory" |), "cost" |) + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "memory" |), + BinOp.mult (| + Constant.bytes "00", + M.get_field (| M.get_name (| globals, "extend_memory" |), "expand_by" |) + |) + |) in + let _ := M.assign_local (| + "code" , + M.get_field (| M.call (| + M.get_name (| globals, "get_account" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "env" |), "state" |); + M.get_name (| globals, "address" |) + ], + make_dict [] + |), "code" |) + |) in + let _ := M.assign_local (| + "value" , + M.call (| + M.get_name (| globals, "buffer_read" |), + make_list [ + M.get_name (| globals, "code" |); + M.get_name (| globals, "code_start_index" |); + M.get_name (| globals, "size" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "memory_write" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "memory" |); + M.get_name (| globals, "memory_start_index" |); + M.get_name (| globals, "value" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). diff --git a/CoqOfPython/ethereum/tangerine_whistle/vm/instructions/keccak.v b/CoqOfPython/ethereum/tangerine_whistle/vm/instructions/keccak.v new file mode 100644 index 0000000..d8e8086 --- /dev/null +++ b/CoqOfPython/ethereum/tangerine_whistle/vm/instructions/keccak.v @@ -0,0 +1,188 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.tangerine_whistle.vm.instructions.keccak". + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) Keccak Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM keccak instructions. +". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". + +Axiom ethereum_crypto_hash_imports_keccak256 : + IsImported globals "ethereum.crypto.hash" "keccak256". + +Axiom ethereum_utils_numeric_imports_ceil32 : + IsImported globals "ethereum.utils.numeric" "ceil32". + +Axiom ethereum_tangerine_whistle_vm_imports_Evm : + IsImported globals "ethereum.tangerine_whistle.vm" "Evm". + +Axiom ethereum_tangerine_whistle_vm_gas_imports_GAS_KECCAK256 : + IsImported globals "ethereum.tangerine_whistle.vm.gas" "GAS_KECCAK256". +Axiom ethereum_tangerine_whistle_vm_gas_imports_GAS_KECCAK256_WORD : + IsImported globals "ethereum.tangerine_whistle.vm.gas" "GAS_KECCAK256_WORD". +Axiom ethereum_tangerine_whistle_vm_gas_imports_calculate_gas_extend_memory : + IsImported globals "ethereum.tangerine_whistle.vm.gas" "calculate_gas_extend_memory". +Axiom ethereum_tangerine_whistle_vm_gas_imports_charge_gas : + IsImported globals "ethereum.tangerine_whistle.vm.gas" "charge_gas". + +Axiom ethereum_tangerine_whistle_vm_memory_imports_memory_read_bytes : + IsImported globals "ethereum.tangerine_whistle.vm.memory" "memory_read_bytes". + +Axiom ethereum_tangerine_whistle_vm_stack_imports_pop : + IsImported globals "ethereum.tangerine_whistle.vm.stack" "pop". +Axiom ethereum_tangerine_whistle_vm_stack_imports_push : + IsImported globals "ethereum.tangerine_whistle.vm.stack" "push". + +Definition keccak : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Pushes to the stack the Keccak-256 hash of a region of memory. + + This also expands the memory, in case the memory is insufficient to + access the data's memory location. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "memory_start_index" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "size" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "words" , + BinOp.floor_div (| + M.call (| + M.get_name (| globals, "ceil32" |), + make_list [ + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.get_name (| globals, "size" |) + ], + make_dict [] + |) + ], + make_dict [] + |), + Constant.int 32 + |) + |) in + let _ := M.assign_local (| + "word_gas_cost" , + BinOp.mult (| + M.get_name (| globals, "GAS_KECCAK256_WORD" |), + M.get_name (| globals, "words" |) + |) + |) in + let _ := M.assign_local (| + "extend_memory" , + M.call (| + M.get_name (| globals, "calculate_gas_extend_memory" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "memory" |); + make_list [ + make_tuple [ M.get_name (| globals, "memory_start_index" |); M.get_name (| globals, "size" |) ] + ] + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + BinOp.add (| + BinOp.add (| + M.get_name (| globals, "GAS_KECCAK256" |), + M.get_name (| globals, "word_gas_cost" |) + |), + M.get_field (| M.get_name (| globals, "extend_memory" |), "cost" |) + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "memory" |), + BinOp.mult (| + Constant.bytes "00", + M.get_field (| M.get_name (| globals, "extend_memory" |), "expand_by" |) + |) + |) in + let _ := M.assign_local (| + "data" , + M.call (| + M.get_name (| globals, "memory_read_bytes" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "memory" |); + M.get_name (| globals, "memory_start_index" |); + M.get_name (| globals, "size" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "hash" , + M.call (| + M.get_name (| globals, "keccak256" |), + make_list [ + M.get_name (| globals, "data" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.call (| + M.get_field (| M.get_name (| globals, "U256" |), "from_be_bytes" |), + make_list [ + M.get_name (| globals, "hash" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). diff --git a/CoqOfPython/ethereum/tangerine_whistle/vm/instructions/log.v b/CoqOfPython/ethereum/tangerine_whistle/vm/instructions/log.v new file mode 100644 index 0000000..45018dd --- /dev/null +++ b/CoqOfPython/ethereum/tangerine_whistle/vm/instructions/log.v @@ -0,0 +1,242 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.tangerine_whistle.vm.instructions.log". + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) Logging Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM logging instructions. +". + +Axiom functools_imports_partial : + IsImported globals "functools" "partial". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". + +Axiom ethereum_tangerine_whistle_blocks_imports_Log : + IsImported globals "ethereum.tangerine_whistle.blocks" "Log". + +Axiom ethereum_tangerine_whistle_vm_imports_Evm : + IsImported globals "ethereum.tangerine_whistle.vm" "Evm". + +Axiom ethereum_tangerine_whistle_vm_gas_imports_GAS_LOG : + IsImported globals "ethereum.tangerine_whistle.vm.gas" "GAS_LOG". +Axiom ethereum_tangerine_whistle_vm_gas_imports_GAS_LOG_DATA : + IsImported globals "ethereum.tangerine_whistle.vm.gas" "GAS_LOG_DATA". +Axiom ethereum_tangerine_whistle_vm_gas_imports_GAS_LOG_TOPIC : + IsImported globals "ethereum.tangerine_whistle.vm.gas" "GAS_LOG_TOPIC". +Axiom ethereum_tangerine_whistle_vm_gas_imports_calculate_gas_extend_memory : + IsImported globals "ethereum.tangerine_whistle.vm.gas" "calculate_gas_extend_memory". +Axiom ethereum_tangerine_whistle_vm_gas_imports_charge_gas : + IsImported globals "ethereum.tangerine_whistle.vm.gas" "charge_gas". + +Axiom ethereum_tangerine_whistle_vm_memory_imports_memory_read_bytes : + IsImported globals "ethereum.tangerine_whistle.vm.memory" "memory_read_bytes". + +Axiom ethereum_tangerine_whistle_vm_stack_imports_pop : + IsImported globals "ethereum.tangerine_whistle.vm.stack" "pop". + +Definition log_n : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm"; "num_topics" ] |) in + let _ := Constant.str " + Appends a log entry, having `num_topics` topics, to the evm logs. + + This will also expand the memory if the data (required by the log entry) + corresponding to the memory is not accessible. + + Parameters + ---------- + evm : + The current EVM frame. + num_topics : + The number of topics to be included in the log entry. + + " in + let _ := M.assign_local (| + "memory_start_index" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "size" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "topics" , + make_list [] + |) in + let _ := + M.for_ (| + M.get_name (| globals, "_" |), + M.call (| + M.get_name (| globals, "range" |), + make_list [ + M.get_name (| globals, "num_topics" |) + ], + make_dict [] + |), + ltac:(M.monadic ( + let _ := M.assign_local (| + "topic" , + M.call (| + M.get_field (| M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |), "to_be_bytes32" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_field (| M.get_name (| globals, "topics" |), "append" |), + make_list [ + M.get_name (| globals, "topic" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := M.assign_local (| + "extend_memory" , + M.call (| + M.get_name (| globals, "calculate_gas_extend_memory" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "memory" |); + make_list [ + make_tuple [ M.get_name (| globals, "memory_start_index" |); M.get_name (| globals, "size" |) ] + ] + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + BinOp.add (| + BinOp.add (| + BinOp.add (| + M.get_name (| globals, "GAS_LOG" |), + BinOp.mult (| + M.get_name (| globals, "GAS_LOG_DATA" |), + M.get_name (| globals, "size" |) + |) + |), + BinOp.mult (| + M.get_name (| globals, "GAS_LOG_TOPIC" |), + M.get_name (| globals, "num_topics" |) + |) + |), + M.get_field (| M.get_name (| globals, "extend_memory" |), "cost" |) + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "memory" |), + BinOp.mult (| + Constant.bytes "00", + M.get_field (| M.get_name (| globals, "extend_memory" |), "expand_by" |) + |) + |) in + let _ := M.assign_local (| + "log_entry" , + M.call (| + M.get_name (| globals, "Log" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, "evm" |), "logs" |), + BinOp.add (| + M.get_field (| M.get_name (| globals, "evm" |), "logs" |), + make_tuple [ M.get_name (| globals, "log_entry" |) ] + |) + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition log0 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "log_n" |) + ], + make_dict [] + |) +)). + +Definition log1 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "log_n" |) + ], + make_dict [] + |) +)). + +Definition log2 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "log_n" |) + ], + make_dict [] + |) +)). + +Definition log3 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "log_n" |) + ], + make_dict [] + |) +)). + +Definition log4 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "log_n" |) + ], + make_dict [] + |) +)). diff --git a/CoqOfPython/ethereum/tangerine_whistle/vm/instructions/memory.v b/CoqOfPython/ethereum/tangerine_whistle/vm/instructions/memory.v new file mode 100644 index 0000000..ca0b278 --- /dev/null +++ b/CoqOfPython/ethereum/tangerine_whistle/vm/instructions/memory.v @@ -0,0 +1,393 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.tangerine_whistle.vm.instructions.memory". + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) Memory Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM Memory instructions. +". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_Bytes : + IsImported globals "ethereum.base_types" "Bytes". + +Axiom ethereum_tangerine_whistle_vm_imports_Evm : + IsImported globals "ethereum.tangerine_whistle.vm" "Evm". + +Axiom ethereum_tangerine_whistle_vm_gas_imports_GAS_BASE : + IsImported globals "ethereum.tangerine_whistle.vm.gas" "GAS_BASE". +Axiom ethereum_tangerine_whistle_vm_gas_imports_GAS_VERY_LOW : + IsImported globals "ethereum.tangerine_whistle.vm.gas" "GAS_VERY_LOW". +Axiom ethereum_tangerine_whistle_vm_gas_imports_calculate_gas_extend_memory : + IsImported globals "ethereum.tangerine_whistle.vm.gas" "calculate_gas_extend_memory". +Axiom ethereum_tangerine_whistle_vm_gas_imports_charge_gas : + IsImported globals "ethereum.tangerine_whistle.vm.gas" "charge_gas". + +Axiom ethereum_tangerine_whistle_vm_memory_imports_memory_read_bytes : + IsImported globals "ethereum.tangerine_whistle.vm.memory" "memory_read_bytes". +Axiom ethereum_tangerine_whistle_vm_memory_imports_memory_write : + IsImported globals "ethereum.tangerine_whistle.vm.memory" "memory_write". + +Axiom ethereum_tangerine_whistle_vm_stack_imports_pop : + IsImported globals "ethereum.tangerine_whistle.vm.stack" "pop". +Axiom ethereum_tangerine_whistle_vm_stack_imports_push : + IsImported globals "ethereum.tangerine_whistle.vm.stack" "push". + +Definition mstore : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Stores a word to memory. + This also expands the memory, if the memory is + insufficient to store the word. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "start_position" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "value" , + M.call (| + M.get_field (| M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |), "to_be_bytes32" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "extend_memory" , + M.call (| + M.get_name (| globals, "calculate_gas_extend_memory" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "memory" |); + make_list [ + make_tuple [ M.get_name (| globals, "start_position" |); M.call (| + M.get_name (| globals, "U256" |), + make_list [ + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_name (| globals, "value" |) + ], + make_dict [] + |) + ], + make_dict [] + |) ] + ] + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + BinOp.add (| + M.get_name (| globals, "GAS_VERY_LOW" |), + M.get_field (| M.get_name (| globals, "extend_memory" |), "cost" |) + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "memory" |), + BinOp.mult (| + Constant.bytes "00", + M.get_field (| M.get_name (| globals, "extend_memory" |), "expand_by" |) + |) + |) in + let _ := M.call (| + M.get_name (| globals, "memory_write" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "memory" |); + M.get_name (| globals, "start_position" |); + M.get_name (| globals, "value" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition mstore8 : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Stores a byte to memory. + This also expands the memory, if the memory is + insufficient to store the word. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "start_position" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "value" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "extend_memory" , + M.call (| + M.get_name (| globals, "calculate_gas_extend_memory" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "memory" |); + make_list [ + make_tuple [ M.get_name (| globals, "start_position" |); M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 1 + ], + make_dict [] + |) ] + ] + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + BinOp.add (| + M.get_name (| globals, "GAS_VERY_LOW" |), + M.get_field (| M.get_name (| globals, "extend_memory" |), "cost" |) + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "memory" |), + BinOp.mult (| + Constant.bytes "00", + M.get_field (| M.get_name (| globals, "extend_memory" |), "expand_by" |) + |) + |) in + let _ := M.assign_local (| + "normalized_bytes_value" , + M.call (| + M.get_name (| globals, "Bytes" |), + make_list [ + make_list [ + BinOp.bit_and (| + M.get_name (| globals, "value" |), + Constant.int 255 + |) + ] + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "memory_write" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "memory" |); + M.get_name (| globals, "start_position" |); + M.get_name (| globals, "normalized_bytes_value" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition mload : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Load word from memory. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "start_position" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "extend_memory" , + M.call (| + M.get_name (| globals, "calculate_gas_extend_memory" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "memory" |); + make_list [ + make_tuple [ M.get_name (| globals, "start_position" |); M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 32 + ], + make_dict [] + |) ] + ] + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + BinOp.add (| + M.get_name (| globals, "GAS_VERY_LOW" |), + M.get_field (| M.get_name (| globals, "extend_memory" |), "cost" |) + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "memory" |), + BinOp.mult (| + Constant.bytes "00", + M.get_field (| M.get_name (| globals, "extend_memory" |), "expand_by" |) + |) + |) in + let _ := M.assign_local (| + "value" , + M.call (| + M.get_field (| M.get_name (| globals, "U256" |), "from_be_bytes" |), + make_list [ + M.call (| + M.get_name (| globals, "memory_read_bytes" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "memory" |); + M.get_name (| globals, "start_position" |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 32 + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.get_name (| globals, "value" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition msize : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Push the size of active memory in bytes onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_BASE" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "memory" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). diff --git a/CoqOfPython/ethereum/tangerine_whistle/vm/instructions/stack.v b/CoqOfPython/ethereum/tangerine_whistle/vm/instructions/stack.v new file mode 100644 index 0000000..91f636b --- /dev/null +++ b/CoqOfPython/ethereum/tangerine_whistle/vm/instructions/stack.v @@ -0,0 +1,947 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.tangerine_whistle.vm.instructions.stack". + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) Stack Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM stack related instructions. +". + +Axiom functools_imports_partial : + IsImported globals "functools" "partial". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". + +Axiom ethereum_utils_ensure_imports_ensure : + IsImported globals "ethereum.utils.ensure" "ensure". + +Axiom ethereum_tangerine_whistle_vm_imports_Evm : + IsImported globals "ethereum.tangerine_whistle.vm" "Evm". +Axiom ethereum_tangerine_whistle_vm_imports_stack : + IsImported globals "ethereum.tangerine_whistle.vm" "stack". + +Axiom ethereum_tangerine_whistle_vm_exceptions_imports_StackUnderflowError : + IsImported globals "ethereum.tangerine_whistle.vm.exceptions" "StackUnderflowError". + +Axiom ethereum_tangerine_whistle_vm_gas_imports_GAS_BASE : + IsImported globals "ethereum.tangerine_whistle.vm.gas" "GAS_BASE". +Axiom ethereum_tangerine_whistle_vm_gas_imports_GAS_VERY_LOW : + IsImported globals "ethereum.tangerine_whistle.vm.gas" "GAS_VERY_LOW". +Axiom ethereum_tangerine_whistle_vm_gas_imports_charge_gas : + IsImported globals "ethereum.tangerine_whistle.vm.gas" "charge_gas". + +Axiom ethereum_tangerine_whistle_vm_memory_imports_buffer_read : + IsImported globals "ethereum.tangerine_whistle.vm.memory" "buffer_read". + +Definition pop : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Remove item from stack. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.call (| + M.get_field (| M.get_name (| globals, "stack" |), "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_BASE" |) + ], + make_dict [] + |) in + let _ := M.pass (| |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition push_n : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm"; "num_bytes" ] |) in + let _ := Constant.str " + Pushes a N-byte immediate onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + num_bytes : + The number of immediate bytes to be read from the code and pushed to + the stack. + + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_VERY_LOW" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "data_to_push" , + M.call (| + M.get_field (| M.get_name (| globals, "U256" |), "from_be_bytes" |), + make_list [ + M.call (| + M.get_name (| globals, "buffer_read" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "code" |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + BinOp.add (| + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) + ], + make_dict [] + |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + M.get_name (| globals, "num_bytes" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_field (| M.get_name (| globals, "stack" |), "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.get_name (| globals, "data_to_push" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + BinOp.add (| + Constant.int 1, + M.get_name (| globals, "num_bytes" |) + |) + |) in + M.pure Constant.None_)). + +Definition dup_n : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm"; "item_number" ] |) in + let _ := Constant.str " + Duplicate the Nth stack item (from top of the stack) to the top of stack. + + Parameters + ---------- + evm : + The current EVM frame. + + item_number : + The stack item number (0-indexed from top of stack) to be duplicated + to the top of stack. + + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_VERY_LOW" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + Compare.lt (| + M.get_name (| globals, "item_number" |), + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |); + M.get_name (| globals, "StackUnderflowError" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "data_to_duplicate" , + M.get_subscript (| + M.get_field (| M.get_name (| globals, "evm" |), "stack" |), + BinOp.sub (| + BinOp.sub (| + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |), + Constant.int 1 + |), + M.get_name (| globals, "item_number" |) + |) + |) + |) in + let _ := M.call (| + M.get_field (| M.get_name (| globals, "stack" |), "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.get_name (| globals, "data_to_duplicate" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition swap_n : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm"; "item_number" ] |) in + let _ := Constant.str " + Swap the top and the `item_number` element of the stack, where + the top of the stack is position zero. + + If `item_number` is zero, this function does nothing (which should not be + possible, since there is no `SWAP0` instruction). + + Parameters + ---------- + evm : + The current EVM frame. + + item_number : + The stack item number (0-indexed from top of stack) to be swapped + with the top of stack element. + + " in + let _ := M.pass (| |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_VERY_LOW" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "ensure" |), + make_list [ + Compare.lt (| + M.get_name (| globals, "item_number" |), + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |); + M.get_name (| globals, "StackUnderflowError" |) + ], + make_dict [] + |) in + let _ := M.assign (| + make_tuple [ M.get_subscript (| + M.get_field (| M.get_name (| globals, "evm" |), "stack" |), + UnOp.sub (| Constant.int 1 |) + |); M.get_subscript (| + M.get_field (| M.get_name (| globals, "evm" |), "stack" |), + BinOp.sub (| + UnOp.sub (| Constant.int 1 |), + M.get_name (| globals, "item_number" |) + |) + |) ], + make_tuple [ M.get_subscript (| + M.get_field (| M.get_name (| globals, "evm" |), "stack" |), + BinOp.sub (| + UnOp.sub (| Constant.int 1 |), + M.get_name (| globals, "item_number" |) + |) + |); M.get_subscript (| + M.get_field (| M.get_name (| globals, "evm" |), "stack" |), + UnOp.sub (| Constant.int 1 |) + |) ] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition push1 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push2 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push3 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push4 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push5 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push6 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push7 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push8 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push9 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push10 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push11 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push12 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push13 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push14 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push15 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push16 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push17 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push18 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push19 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push20 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push21 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push22 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push23 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push24 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push25 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push26 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push27 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push28 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push29 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push30 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push31 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "push_n" |) + ], + make_dict [] + |) +)). + +Definition push32 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "push_n" |) + ], + make_dict [] + |) +)). + +Definition dup1 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "dup_n" |) + ], + make_dict [] + |) +)). + +Definition dup2 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "dup_n" |) + ], + make_dict [] + |) +)). + +Definition dup3 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "dup_n" |) + ], + make_dict [] + |) +)). + +Definition dup4 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "dup_n" |) + ], + make_dict [] + |) +)). + +Definition dup5 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "dup_n" |) + ], + make_dict [] + |) +)). + +Definition dup6 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "dup_n" |) + ], + make_dict [] + |) +)). + +Definition dup7 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "dup_n" |) + ], + make_dict [] + |) +)). + +Definition dup8 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "dup_n" |) + ], + make_dict [] + |) +)). + +Definition dup9 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "dup_n" |) + ], + make_dict [] + |) +)). + +Definition dup10 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "dup_n" |) + ], + make_dict [] + |) +)). + +Definition dup11 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "dup_n" |) + ], + make_dict [] + |) +)). + +Definition dup12 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "dup_n" |) + ], + make_dict [] + |) +)). + +Definition dup13 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "dup_n" |) + ], + make_dict [] + |) +)). + +Definition dup14 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "dup_n" |) + ], + make_dict [] + |) +)). + +Definition dup15 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "dup_n" |) + ], + make_dict [] + |) +)). + +Definition dup16 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "dup_n" |) + ], + make_dict [] + |) +)). + +Definition swap1 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "swap_n" |) + ], + make_dict [] + |) +)). + +Definition swap2 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "swap_n" |) + ], + make_dict [] + |) +)). + +Definition swap3 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "swap_n" |) + ], + make_dict [] + |) +)). + +Definition swap4 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "swap_n" |) + ], + make_dict [] + |) +)). + +Definition swap5 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "swap_n" |) + ], + make_dict [] + |) +)). + +Definition swap6 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "swap_n" |) + ], + make_dict [] + |) +)). + +Definition swap7 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "swap_n" |) + ], + make_dict [] + |) +)). + +Definition swap8 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "swap_n" |) + ], + make_dict [] + |) +)). + +Definition swap9 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "swap_n" |) + ], + make_dict [] + |) +)). + +Definition swap10 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "swap_n" |) + ], + make_dict [] + |) +)). + +Definition swap11 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "swap_n" |) + ], + make_dict [] + |) +)). + +Definition swap12 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "swap_n" |) + ], + make_dict [] + |) +)). + +Definition swap13 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "swap_n" |) + ], + make_dict [] + |) +)). + +Definition swap14 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "swap_n" |) + ], + make_dict [] + |) +)). + +Definition swap15 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "swap_n" |) + ], + make_dict [] + |) +)). + +Definition swap16 : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "partial" |), + make_list [ + M.get_name (| globals, "swap_n" |) + ], + make_dict [] + |) +)). diff --git a/CoqOfPython/ethereum/tangerine_whistle/vm/instructions/storage.v b/CoqOfPython/ethereum/tangerine_whistle/vm/instructions/storage.v new file mode 100644 index 0000000..d1261c9 --- /dev/null +++ b/CoqOfPython/ethereum/tangerine_whistle/vm/instructions/storage.v @@ -0,0 +1,234 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.tangerine_whistle.vm.instructions.storage". + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) Storage Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM storage related instructions. +". + +Axiom ethereum_tangerine_whistle_state_imports_get_storage : + IsImported globals "ethereum.tangerine_whistle.state" "get_storage". +Axiom ethereum_tangerine_whistle_state_imports_set_storage : + IsImported globals "ethereum.tangerine_whistle.state" "set_storage". + +Axiom ethereum_tangerine_whistle_vm_imports_Evm : + IsImported globals "ethereum.tangerine_whistle.vm" "Evm". + +Axiom ethereum_tangerine_whistle_vm_gas_imports_GAS_SLOAD : + IsImported globals "ethereum.tangerine_whistle.vm.gas" "GAS_SLOAD". +Axiom ethereum_tangerine_whistle_vm_gas_imports_GAS_STORAGE_CLEAR_REFUND : + IsImported globals "ethereum.tangerine_whistle.vm.gas" "GAS_STORAGE_CLEAR_REFUND". +Axiom ethereum_tangerine_whistle_vm_gas_imports_GAS_STORAGE_SET : + IsImported globals "ethereum.tangerine_whistle.vm.gas" "GAS_STORAGE_SET". +Axiom ethereum_tangerine_whistle_vm_gas_imports_GAS_STORAGE_UPDATE : + IsImported globals "ethereum.tangerine_whistle.vm.gas" "GAS_STORAGE_UPDATE". +Axiom ethereum_tangerine_whistle_vm_gas_imports_charge_gas : + IsImported globals "ethereum.tangerine_whistle.vm.gas" "charge_gas". + +Axiom ethereum_tangerine_whistle_vm_stack_imports_pop : + IsImported globals "ethereum.tangerine_whistle.vm.stack" "pop". +Axiom ethereum_tangerine_whistle_vm_stack_imports_push : + IsImported globals "ethereum.tangerine_whistle.vm.stack" "push". + +Definition sload : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Loads to the stack, the value corresponding to a certain key from the + storage of the current account. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "key" , + M.call (| + M.get_field (| M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |), "to_be_bytes32" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_SLOAD" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "value" , + M.call (| + M.get_name (| globals, "get_storage" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "env" |), "state" |); + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "current_target" |); + M.get_name (| globals, "key" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.get_name (| globals, "value" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition sstore : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Stores a value at a certain key in the current context's storage. + + Parameters + ---------- + evm : + The current EVM frame. + + " in + let _ := M.assign_local (| + "key" , + M.call (| + M.get_field (| M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |), "to_be_bytes32" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "new_value" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "current_value" , + M.call (| + M.get_name (| globals, "get_storage" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "env" |), "state" |); + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "current_target" |); + M.get_name (| globals, "key" |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + BoolOp.and (| + Compare.not_eq (| + M.get_name (| globals, "new_value" |), + Constant.int 0 + |), + ltac:(M.monadic ( + Compare.eq (| + M.get_name (| globals, "current_value" |), + Constant.int 0 + |) + )) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "gas_cost" , + M.get_name (| globals, "GAS_STORAGE_SET" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "gas_cost" , + M.get_name (| globals, "GAS_STORAGE_UPDATE" |) + |) in + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + BoolOp.and (| + Compare.eq (| + M.get_name (| globals, "new_value" |), + Constant.int 0 + |), + ltac:(M.monadic ( + Compare.not_eq (| + M.get_name (| globals, "current_value" |), + Constant.int 0 + |) + )) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "refund_counter" |), + M.get_name (| globals, "GAS_STORAGE_CLEAR_REFUND" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "gas_cost" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "set_storage" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "env" |), "state" |); + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "current_target" |); + M.get_name (| globals, "key" |); + M.get_name (| globals, "new_value" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). diff --git a/CoqOfPython/ethereum/tangerine_whistle/vm/instructions/system.v b/CoqOfPython/ethereum/tangerine_whistle/vm/instructions/system.v new file mode 100644 index 0000000..a103f8e --- /dev/null +++ b/CoqOfPython/ethereum/tangerine_whistle/vm/instructions/system.v @@ -0,0 +1,1546 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.tangerine_whistle.vm.instructions.system". + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) System Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM system related instructions. +". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_Bytes0 : + IsImported globals "ethereum.base_types" "Bytes0". +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". + +Axiom ethereum_tangerine_whistle_fork_types_imports_Address : + IsImported globals "ethereum.tangerine_whistle.fork_types" "Address". + +Axiom ethereum_tangerine_whistle_state_imports_account_exists : + IsImported globals "ethereum.tangerine_whistle.state" "account_exists". +Axiom ethereum_tangerine_whistle_state_imports_account_has_code_or_nonce : + IsImported globals "ethereum.tangerine_whistle.state" "account_has_code_or_nonce". +Axiom ethereum_tangerine_whistle_state_imports_get_account : + IsImported globals "ethereum.tangerine_whistle.state" "get_account". +Axiom ethereum_tangerine_whistle_state_imports_increment_nonce : + IsImported globals "ethereum.tangerine_whistle.state" "increment_nonce". +Axiom ethereum_tangerine_whistle_state_imports_set_account_balance : + IsImported globals "ethereum.tangerine_whistle.state" "set_account_balance". + +Axiom ethereum_tangerine_whistle_utils_address_imports_compute_contract_address : + IsImported globals "ethereum.tangerine_whistle.utils.address" "compute_contract_address". +Axiom ethereum_tangerine_whistle_utils_address_imports_to_address : + IsImported globals "ethereum.tangerine_whistle.utils.address" "to_address". + +Axiom ethereum_tangerine_whistle_vm_imports_Evm : + IsImported globals "ethereum.tangerine_whistle.vm" "Evm". +Axiom ethereum_tangerine_whistle_vm_imports_Message : + IsImported globals "ethereum.tangerine_whistle.vm" "Message". +Axiom ethereum_tangerine_whistle_vm_imports_incorporate_child_on_error : + IsImported globals "ethereum.tangerine_whistle.vm" "incorporate_child_on_error". +Axiom ethereum_tangerine_whistle_vm_imports_incorporate_child_on_success : + IsImported globals "ethereum.tangerine_whistle.vm" "incorporate_child_on_success". + +Axiom ethereum_tangerine_whistle_vm_gas_imports_GAS_CALL : + IsImported globals "ethereum.tangerine_whistle.vm.gas" "GAS_CALL". +Axiom ethereum_tangerine_whistle_vm_gas_imports_GAS_CALL_VALUE : + IsImported globals "ethereum.tangerine_whistle.vm.gas" "GAS_CALL_VALUE". +Axiom ethereum_tangerine_whistle_vm_gas_imports_GAS_CREATE : + IsImported globals "ethereum.tangerine_whistle.vm.gas" "GAS_CREATE". +Axiom ethereum_tangerine_whistle_vm_gas_imports_GAS_NEW_ACCOUNT : + IsImported globals "ethereum.tangerine_whistle.vm.gas" "GAS_NEW_ACCOUNT". +Axiom ethereum_tangerine_whistle_vm_gas_imports_GAS_SELF_DESTRUCT : + IsImported globals "ethereum.tangerine_whistle.vm.gas" "GAS_SELF_DESTRUCT". +Axiom ethereum_tangerine_whistle_vm_gas_imports_GAS_SELF_DESTRUCT_NEW_ACCOUNT : + IsImported globals "ethereum.tangerine_whistle.vm.gas" "GAS_SELF_DESTRUCT_NEW_ACCOUNT". +Axiom ethereum_tangerine_whistle_vm_gas_imports_GAS_ZERO : + IsImported globals "ethereum.tangerine_whistle.vm.gas" "GAS_ZERO". +Axiom ethereum_tangerine_whistle_vm_gas_imports_REFUND_SELF_DESTRUCT : + IsImported globals "ethereum.tangerine_whistle.vm.gas" "REFUND_SELF_DESTRUCT". +Axiom ethereum_tangerine_whistle_vm_gas_imports_calculate_gas_extend_memory : + IsImported globals "ethereum.tangerine_whistle.vm.gas" "calculate_gas_extend_memory". +Axiom ethereum_tangerine_whistle_vm_gas_imports_calculate_message_call_gas : + IsImported globals "ethereum.tangerine_whistle.vm.gas" "calculate_message_call_gas". +Axiom ethereum_tangerine_whistle_vm_gas_imports_charge_gas : + IsImported globals "ethereum.tangerine_whistle.vm.gas" "charge_gas". +Axiom ethereum_tangerine_whistle_vm_gas_imports_max_message_call_gas : + IsImported globals "ethereum.tangerine_whistle.vm.gas" "max_message_call_gas". + +Axiom ethereum_tangerine_whistle_vm_memory_imports_memory_read_bytes : + IsImported globals "ethereum.tangerine_whistle.vm.memory" "memory_read_bytes". +Axiom ethereum_tangerine_whistle_vm_memory_imports_memory_write : + IsImported globals "ethereum.tangerine_whistle.vm.memory" "memory_write". + +Axiom ethereum_tangerine_whistle_vm_stack_imports_pop : + IsImported globals "ethereum.tangerine_whistle.vm.stack" "pop". +Axiom ethereum_tangerine_whistle_vm_stack_imports_push : + IsImported globals "ethereum.tangerine_whistle.vm.stack" "push". + +Definition create : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Creates a new account with associated code. + + Parameters + ---------- + evm : + The current EVM frame. + " in +(* At stmt: unsupported node type: ImportFrom *) + let _ := M.assign_local (| + "endowment" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_start_position" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_size" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "extend_memory" , + M.call (| + M.get_name (| globals, "calculate_gas_extend_memory" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "memory" |); + make_list [ + make_tuple [ M.get_name (| globals, "memory_start_position" |); M.get_name (| globals, "memory_size" |) ] + ] + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + BinOp.add (| + M.get_name (| globals, "GAS_CREATE" |), + M.get_field (| M.get_name (| globals, "extend_memory" |), "cost" |) + |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "create_message_gas" , + M.call (| + M.get_name (| globals, "max_message_call_gas" |), + make_list [ + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "gas_left" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_op (| + BinOp.sub, + M.get_field (| M.get_name (| globals, "evm" |), "gas_left" |), + M.get_name (| globals, "create_message_gas" |) + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "memory" |), + BinOp.mult (| + Constant.bytes "00", + M.get_field (| M.get_name (| globals, "extend_memory" |), "expand_by" |) + |) + |) in + let _ := M.assign_local (| + "sender_address" , + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "current_target" |) + |) in + let _ := M.assign_local (| + "sender" , + M.call (| + M.get_name (| globals, "get_account" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "env" |), "state" |); + M.get_name (| globals, "sender_address" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "contract_address" , + M.call (| + M.get_name (| globals, "compute_contract_address" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "current_target" |); + M.get_field (| M.call (| + M.get_name (| globals, "get_account" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "env" |), "state" |); + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "current_target" |) + ], + make_dict [] + |), "nonce" |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + BoolOp.or (| + Compare.lt (| + M.get_field (| M.get_name (| globals, "sender" |), "balance" |), + M.get_name (| globals, "endowment" |) + |), + ltac:(M.monadic ( + BoolOp.or (| + Compare.eq (| + M.get_field (| M.get_name (| globals, "sender" |), "nonce" |), + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + BinOp.sub (| + BinOp.pow (| + Constant.int 2, + Constant.int 64 + |), + Constant.int 1 + |) + ], + make_dict [] + |) + |), + ltac:(M.monadic ( + Compare.gt (| + BinOp.add (| + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "depth" |), + Constant.int 1 + |), + M.get_name (| globals, "STACK_DEPTH_LIMIT" |) + |) + )) + |) + )) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "gas_left" |), + M.get_name (| globals, "create_message_gas" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, "account_has_code_or_nonce" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "env" |), "state" |); + M.get_name (| globals, "contract_address" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, "increment_nonce" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "env" |), "state" |); + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "current_target" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + ], + make_dict [] + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "call_data" , + M.call (| + M.get_name (| globals, "memory_read_bytes" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "memory" |); + M.get_name (| globals, "memory_start_position" |); + M.get_name (| globals, "memory_size" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "increment_nonce" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "env" |), "state" |); + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "current_target" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "child_message" , + M.call (| + M.get_name (| globals, "Message" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "child_evm" , + M.call (| + M.get_name (| globals, "process_create_message" |), + make_list [ + M.get_name (| globals, "child_message" |); + M.get_field (| M.get_name (| globals, "evm" |), "env" |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + M.get_field (| M.get_name (| globals, "child_evm" |), "error" |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, "incorporate_child_on_error" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "child_evm" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + ], + make_dict [] + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, "incorporate_child_on_success" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "child_evm" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.call (| + M.get_field (| M.get_name (| globals, "U256" |), "from_be_bytes" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "child_evm" |), "message" |), "current_target" |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )) |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition return_ : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Halts execution returning output data. + + Parameters + ---------- + evm : + The current EVM frame. + " in + let _ := M.assign_local (| + "memory_start_position" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_size" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "extend_memory" , + M.call (| + M.get_name (| globals, "calculate_gas_extend_memory" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "memory" |); + make_list [ + make_tuple [ M.get_name (| globals, "memory_start_position" |); M.get_name (| globals, "memory_size" |) ] + ] + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + BinOp.add (| + M.get_name (| globals, "GAS_ZERO" |), + M.get_field (| M.get_name (| globals, "extend_memory" |), "cost" |) + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "memory" |), + BinOp.mult (| + Constant.bytes "00", + M.get_field (| M.get_name (| globals, "extend_memory" |), "expand_by" |) + |) + |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, "evm" |), "output" |), + M.call (| + M.get_name (| globals, "memory_read_bytes" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "memory" |); + M.get_name (| globals, "memory_start_position" |); + M.get_name (| globals, "memory_size" |) + ], + make_dict [] + |) + |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, "evm" |), "running" |), + Constant.bool false + |) in + let _ := M.pass (| |) in + M.pure Constant.None_)). + +Definition generic_call : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm"; "gas"; "value"; "caller"; "to"; "code_address"; "should_transfer_value"; "memory_input_start_position"; "memory_input_size"; "memory_output_start_position"; "memory_output_size" ] |) in + let _ := Constant.str " + Perform the core logic of the `CALL*` family of opcodes. + " in +(* At stmt: unsupported node type: ImportFrom *) + let _ := + (* if *) + M.if_then_else (| + Compare.gt (| + BinOp.add (| + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "depth" |), + Constant.int 1 + |), + M.get_name (| globals, "STACK_DEPTH_LIMIT" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "gas_left" |), + M.get_name (| globals, "gas" |) + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.return_ (| + Constant.None_ + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "call_data" , + M.call (| + M.get_name (| globals, "memory_read_bytes" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "memory" |); + M.get_name (| globals, "memory_input_start_position" |); + M.get_name (| globals, "memory_input_size" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "code" , + M.get_field (| M.call (| + M.get_name (| globals, "get_account" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "env" |), "state" |); + M.get_name (| globals, "code_address" |) + ], + make_dict [] + |), "code" |) + |) in + let _ := M.assign_local (| + "child_message" , + M.call (| + M.get_name (| globals, "Message" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "child_evm" , + M.call (| + M.get_name (| globals, "process_message" |), + make_list [ + M.get_name (| globals, "child_message" |); + M.get_field (| M.get_name (| globals, "evm" |), "env" |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + M.get_field (| M.get_name (| globals, "child_evm" |), "error" |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, "incorporate_child_on_error" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "child_evm" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + ], + make_dict [] + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, "incorporate_child_on_success" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "child_evm" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 1 + ], + make_dict [] + |) + ], + make_dict [] + |) in + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "actual_output_size" , + M.call (| + M.get_name (| globals, "min" |), + make_list [ + M.get_name (| globals, "memory_output_size" |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_field (| M.get_name (| globals, "child_evm" |), "output" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "memory_write" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "memory" |); + M.get_name (| globals, "memory_output_start_position" |); + M.slice (| + M.get_field (| M.get_name (| globals, "child_evm" |), "output" |), + Constant.None_, + M.get_name (| globals, "actual_output_size" |), + Constant.None_ + |) + ], + make_dict [] + |) in + M.pure Constant.None_)). + +Definition call : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Message-call into an account. + + Parameters + ---------- + evm : + The current EVM frame. + " in + let _ := M.assign_local (| + "gas" , + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "to" , + M.call (| + M.get_name (| globals, "to_address" |), + make_list [ + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "value" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_input_start_position" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_input_size" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_output_start_position" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_output_size" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "extend_memory" , + M.call (| + M.get_name (| globals, "calculate_gas_extend_memory" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "memory" |); + make_list [ + make_tuple [ M.get_name (| globals, "memory_input_start_position" |); M.get_name (| globals, "memory_input_size" |) ]; + make_tuple [ M.get_name (| globals, "memory_output_start_position" |); M.get_name (| globals, "memory_output_size" |) ] + ] + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "_account_exists" , + M.call (| + M.get_name (| globals, "account_exists" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "env" |), "state" |); + M.get_name (| globals, "to" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "create_gas_cost" , + (* if *) + M.if_then_else (| + M.get_name (| globals, "_account_exists" |), + (* then *) + ltac:(M.monadic ( +M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + (* else *) + )), ltac:(M.monadic ( +M.get_name (| globals, "GAS_NEW_ACCOUNT" |) + )) |) + |) in + let _ := M.assign_local (| + "transfer_gas_cost" , + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, "value" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( +M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + (* else *) + )), ltac:(M.monadic ( +M.get_name (| globals, "GAS_CALL_VALUE" |) + )) |) + |) in + let _ := M.assign_local (| + "message_call_gas" , + M.call (| + M.get_name (| globals, "calculate_message_call_gas" |), + make_list [ + M.get_name (| globals, "value" |); + M.get_name (| globals, "gas" |); + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "gas_left" |) + ], + make_dict [] + |); + M.get_field (| M.get_name (| globals, "extend_memory" |), "cost" |); + BinOp.add (| + BinOp.add (| + M.get_name (| globals, "GAS_CALL" |), + M.get_name (| globals, "create_gas_cost" |) + |), + M.get_name (| globals, "transfer_gas_cost" |) + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + BinOp.add (| + M.get_field (| M.get_name (| globals, "message_call_gas" |), "cost" |), + M.get_field (| M.get_name (| globals, "extend_memory" |), "cost" |) + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "memory" |), + BinOp.mult (| + Constant.bytes "00", + M.get_field (| M.get_name (| globals, "extend_memory" |), "expand_by" |) + |) + |) in + let _ := M.assign_local (| + "sender_balance" , + M.get_field (| M.call (| + M.get_name (| globals, "get_account" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "env" |), "state" |); + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "current_target" |) + ], + make_dict [] + |), "balance" |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.lt (| + M.get_name (| globals, "sender_balance" |), + M.get_name (| globals, "value" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "gas_left" |), + M.get_field (| M.get_name (| globals, "message_call_gas" |), "stipend" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, "generic_call" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_field (| M.get_name (| globals, "message_call_gas" |), "stipend" |); + M.get_name (| globals, "value" |); + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "current_target" |); + M.get_name (| globals, "to" |); + M.get_name (| globals, "to" |); + Constant.bool true; + M.get_name (| globals, "memory_input_start_position" |); + M.get_name (| globals, "memory_input_size" |); + M.get_name (| globals, "memory_output_start_position" |); + M.get_name (| globals, "memory_output_size" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + )) |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition callcode : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Message-call into this account with alternative account’s code. + + Parameters + ---------- + evm : + The current EVM frame. + " in + let _ := M.assign_local (| + "gas" , + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "code_address" , + M.call (| + M.get_name (| globals, "to_address" |), + make_list [ + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "value" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_input_start_position" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_input_size" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_output_start_position" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_output_size" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "to" , + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "current_target" |) + |) in + let _ := M.assign_local (| + "extend_memory" , + M.call (| + M.get_name (| globals, "calculate_gas_extend_memory" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "memory" |); + make_list [ + make_tuple [ M.get_name (| globals, "memory_input_start_position" |); M.get_name (| globals, "memory_input_size" |) ]; + make_tuple [ M.get_name (| globals, "memory_output_start_position" |); M.get_name (| globals, "memory_output_size" |) ] + ] + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "transfer_gas_cost" , + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, "value" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( +M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + (* else *) + )), ltac:(M.monadic ( +M.get_name (| globals, "GAS_CALL_VALUE" |) + )) |) + |) in + let _ := M.assign_local (| + "message_call_gas" , + M.call (| + M.get_name (| globals, "calculate_message_call_gas" |), + make_list [ + M.get_name (| globals, "value" |); + M.get_name (| globals, "gas" |); + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "gas_left" |) + ], + make_dict [] + |); + M.get_field (| M.get_name (| globals, "extend_memory" |), "cost" |); + BinOp.add (| + M.get_name (| globals, "GAS_CALL" |), + M.get_name (| globals, "transfer_gas_cost" |) + |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + BinOp.add (| + M.get_field (| M.get_name (| globals, "message_call_gas" |), "cost" |), + M.get_field (| M.get_name (| globals, "extend_memory" |), "cost" |) + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "memory" |), + BinOp.mult (| + Constant.bytes "00", + M.get_field (| M.get_name (| globals, "extend_memory" |), "expand_by" |) + |) + |) in + let _ := M.assign_local (| + "sender_balance" , + M.get_field (| M.call (| + M.get_name (| globals, "get_account" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "env" |), "state" |); + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "current_target" |) + ], + make_dict [] + |), "balance" |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.lt (| + M.get_name (| globals, "sender_balance" |), + M.get_name (| globals, "value" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, "push" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "gas_left" |), + M.get_field (| M.get_name (| globals, "message_call_gas" |), "stipend" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, "generic_call" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_field (| M.get_name (| globals, "message_call_gas" |), "stipend" |); + M.get_name (| globals, "value" |); + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "current_target" |); + M.get_name (| globals, "to" |); + M.get_name (| globals, "code_address" |); + Constant.bool true; + M.get_name (| globals, "memory_input_start_position" |); + M.get_name (| globals, "memory_input_size" |); + M.get_name (| globals, "memory_output_start_position" |); + M.get_name (| globals, "memory_output_size" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + )) |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). + +Definition selfdestruct : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Halt execution and register account for later deletion. + + Parameters + ---------- + evm : + The current EVM frame. + " in + let _ := M.assign_local (| + "beneficiary" , + M.call (| + M.get_name (| globals, "to_address" |), + make_list [ + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "gas_cost" , + M.get_name (| globals, "GAS_SELF_DESTRUCT" |) + |) in + let _ := + (* if *) + M.if_then_else (| + UnOp.not (| M.call (| + M.get_name (| globals, "account_exists" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "env" |), "state" |); + M.get_name (| globals, "beneficiary" |) + ], + make_dict [] + |) |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_op_local (| + BinOp.add, + "gas_cost", + M.get_name (| globals, "GAS_SELF_DESTRUCT_NEW_ACCOUNT" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "originator" , + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "current_target" |) + |) in + let _ := M.assign_local (| + "refunded_accounts" , + M.get_field (| M.get_name (| globals, "evm" |), "accounts_to_delete" |) + |) in + let _ := M.assign_local (| + "parent_evm" , + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "parent_evm" |) + |) in + let _ := + M.while (| + Compare.is_not (| + M.get_name (| globals, "parent_evm" |), + Constant.None_ + |), + ltac:(M.monadic ( + let _ := M.call (| + M.get_field (| M.get_name (| globals, "refunded_accounts" |), "update" |), + make_list [ + M.get_field (| M.get_name (| globals, "parent_evm" |), "accounts_to_delete" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "parent_evm" , + M.get_field (| M.get_field (| M.get_name (| globals, "parent_evm" |), "message" |), "parent_evm" |) + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.not_in (| + M.get_name (| globals, "originator" |), + M.get_name (| globals, "refunded_accounts" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "refund_counter" |), + M.get_name (| globals, "REFUND_SELF_DESTRUCT" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "gas_cost" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "beneficiary_balance" , + M.get_field (| M.call (| + M.get_name (| globals, "get_account" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "env" |), "state" |); + M.get_name (| globals, "beneficiary" |) + ], + make_dict [] + |), "balance" |) + |) in + let _ := M.assign_local (| + "originator_balance" , + M.get_field (| M.call (| + M.get_name (| globals, "get_account" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "env" |), "state" |); + M.get_name (| globals, "originator" |) + ], + make_dict [] + |), "balance" |) + |) in + let _ := M.call (| + M.get_name (| globals, "set_account_balance" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "env" |), "state" |); + M.get_name (| globals, "beneficiary" |); + BinOp.add (| + M.get_name (| globals, "beneficiary_balance" |), + M.get_name (| globals, "originator_balance" |) + |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "set_account_balance" |), + make_list [ + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "env" |), "state" |); + M.get_name (| globals, "originator" |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "accounts_to_delete" |), "add" |), + make_list [ + M.get_name (| globals, "originator" |) + ], + make_dict [] + |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, "evm" |), "running" |), + Constant.bool false + |) in + let _ := M.pass (| |) in + M.pure Constant.None_)). + +Definition delegatecall : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Message-call into an account. + + Parameters + ---------- + evm : + The current EVM frame. + " in + let _ := M.assign_local (| + "gas" , + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "code_address" , + M.call (| + M.get_name (| globals, "to_address" |), + make_list [ + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_input_start_position" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_input_size" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_output_start_position" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "memory_output_size" , + M.call (| + M.get_name (| globals, "pop" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "stack" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "extend_memory" , + M.call (| + M.get_name (| globals, "calculate_gas_extend_memory" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "memory" |); + make_list [ + make_tuple [ M.get_name (| globals, "memory_input_start_position" |); M.get_name (| globals, "memory_input_size" |) ]; + make_tuple [ M.get_name (| globals, "memory_output_start_position" |); M.get_name (| globals, "memory_output_size" |) ] + ] + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "message_call_gas" , + M.call (| + M.get_name (| globals, "calculate_message_call_gas" |), + make_list [ + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |); + M.get_name (| globals, "gas" |); + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.get_field (| M.get_name (| globals, "evm" |), "gas_left" |) + ], + make_dict [] + |); + M.get_field (| M.get_name (| globals, "extend_memory" |), "cost" |); + M.get_name (| globals, "GAS_CALL" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + BinOp.add (| + M.get_field (| M.get_name (| globals, "message_call_gas" |), "cost" |), + M.get_field (| M.get_name (| globals, "extend_memory" |), "cost" |) + |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "memory" |), + BinOp.mult (| + Constant.bytes "00", + M.get_field (| M.get_name (| globals, "extend_memory" |), "expand_by" |) + |) + |) in + let _ := M.call (| + M.get_name (| globals, "generic_call" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_field (| M.get_name (| globals, "message_call_gas" |), "stipend" |); + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "value" |); + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "caller" |); + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "current_target" |); + M.get_name (| globals, "code_address" |); + Constant.bool false; + M.get_name (| globals, "memory_input_start_position" |); + M.get_name (| globals, "memory_input_size" |); + M.get_name (| globals, "memory_output_start_position" |); + M.get_name (| globals, "memory_output_size" |) + ], + make_dict [] + |) in + let _ := M.assign_op (| + BinOp.add, + M.get_field (| M.get_name (| globals, "evm" |), "pc" |), + Constant.int 1 + |) in + M.pure Constant.None_)). diff --git a/CoqOfPython/ethereum/tangerine_whistle/vm/interpreter.v b/CoqOfPython/ethereum/tangerine_whistle/vm/interpreter.v new file mode 100644 index 0000000..df0b3aa --- /dev/null +++ b/CoqOfPython/ethereum/tangerine_whistle/vm/interpreter.v @@ -0,0 +1,578 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.tangerine_whistle.vm.interpreter". + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) Interpreter +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +A straightforward interpreter that executes EVM code. +". + +Axiom dataclasses_imports_dataclass : + IsImported globals "dataclasses" "dataclass". + +Axiom typing_imports_Optional : + IsImported globals "typing" "Optional". +Axiom typing_imports_Set : + IsImported globals "typing" "Set". +Axiom typing_imports_Tuple : + IsImported globals "typing" "Tuple". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_Bytes0 : + IsImported globals "ethereum.base_types" "Bytes0". +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". + +Axiom ethereum_trace_imports_EvmStop : + IsImported globals "ethereum.trace" "EvmStop". +Axiom ethereum_trace_imports_OpEnd : + IsImported globals "ethereum.trace" "OpEnd". +Axiom ethereum_trace_imports_OpException : + IsImported globals "ethereum.trace" "OpException". +Axiom ethereum_trace_imports_OpStart : + IsImported globals "ethereum.trace" "OpStart". +Axiom ethereum_trace_imports_PrecompileEnd : + IsImported globals "ethereum.trace" "PrecompileEnd". +Axiom ethereum_trace_imports_PrecompileStart : + IsImported globals "ethereum.trace" "PrecompileStart". +Axiom ethereum_trace_imports_TransactionEnd : + IsImported globals "ethereum.trace" "TransactionEnd". +Axiom ethereum_trace_imports_evm_trace : + IsImported globals "ethereum.trace" "evm_trace". + +Axiom ethereum_tangerine_whistle_blocks_imports_Log : + IsImported globals "ethereum.tangerine_whistle.blocks" "Log". + +Axiom ethereum_tangerine_whistle_fork_types_imports_Address : + IsImported globals "ethereum.tangerine_whistle.fork_types" "Address". + +Axiom ethereum_tangerine_whistle_state_imports_account_has_code_or_nonce : + IsImported globals "ethereum.tangerine_whistle.state" "account_has_code_or_nonce". +Axiom ethereum_tangerine_whistle_state_imports_begin_transaction : + IsImported globals "ethereum.tangerine_whistle.state" "begin_transaction". +Axiom ethereum_tangerine_whistle_state_imports_commit_transaction : + IsImported globals "ethereum.tangerine_whistle.state" "commit_transaction". +Axiom ethereum_tangerine_whistle_state_imports_destroy_storage : + IsImported globals "ethereum.tangerine_whistle.state" "destroy_storage". +Axiom ethereum_tangerine_whistle_state_imports_move_ether : + IsImported globals "ethereum.tangerine_whistle.state" "move_ether". +Axiom ethereum_tangerine_whistle_state_imports_rollback_transaction : + IsImported globals "ethereum.tangerine_whistle.state" "rollback_transaction". +Axiom ethereum_tangerine_whistle_state_imports_set_code : + IsImported globals "ethereum.tangerine_whistle.state" "set_code". +Axiom ethereum_tangerine_whistle_state_imports_touch_account : + IsImported globals "ethereum.tangerine_whistle.state" "touch_account". + +Axiom ethereum_tangerine_whistle_vm_imports_Message : + IsImported globals "ethereum.tangerine_whistle.vm" "Message". + +Axiom ethereum_tangerine_whistle_vm_gas_imports_GAS_CODE_DEPOSIT : + IsImported globals "ethereum.tangerine_whistle.vm.gas" "GAS_CODE_DEPOSIT". +Axiom ethereum_tangerine_whistle_vm_gas_imports_charge_gas : + IsImported globals "ethereum.tangerine_whistle.vm.gas" "charge_gas". + +Axiom ethereum_tangerine_whistle_vm_precompiled_contracts_mapping_imports_PRE_COMPILED_CONTRACTS : + IsImported globals "ethereum.tangerine_whistle.vm.precompiled_contracts.mapping" "PRE_COMPILED_CONTRACTS". + +Axiom ethereum_tangerine_whistle_vm_imports_Environment : + IsImported globals "ethereum.tangerine_whistle.vm" "Environment". +Axiom ethereum_tangerine_whistle_vm_imports_Evm : + IsImported globals "ethereum.tangerine_whistle.vm" "Evm". + +Axiom ethereum_tangerine_whistle_vm_exceptions_imports_AddressCollision : + IsImported globals "ethereum.tangerine_whistle.vm.exceptions" "AddressCollision". +Axiom ethereum_tangerine_whistle_vm_exceptions_imports_ExceptionalHalt : + IsImported globals "ethereum.tangerine_whistle.vm.exceptions" "ExceptionalHalt". +Axiom ethereum_tangerine_whistle_vm_exceptions_imports_InvalidOpcode : + IsImported globals "ethereum.tangerine_whistle.vm.exceptions" "InvalidOpcode". +Axiom ethereum_tangerine_whistle_vm_exceptions_imports_StackDepthLimitError : + IsImported globals "ethereum.tangerine_whistle.vm.exceptions" "StackDepthLimitError". + +Axiom ethereum_tangerine_whistle_vm_instructions_imports_Ops : + IsImported globals "ethereum.tangerine_whistle.vm.instructions" "Ops". +Axiom ethereum_tangerine_whistle_vm_instructions_imports_op_implementation : + IsImported globals "ethereum.tangerine_whistle.vm.instructions" "op_implementation". + +Axiom ethereum_tangerine_whistle_vm_runtime_imports_get_valid_jump_destinations : + IsImported globals "ethereum.tangerine_whistle.vm.runtime" "get_valid_jump_destinations". + +Definition STACK_DEPTH_LIMIT : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 1024 + ], + make_dict [] + |) +)). + +Definition MessageCallOutput : Value.t := + builtins.make_klass + [] + [ + + ] + [ + + ]. + +Definition process_message_call : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "message"; "env" ] |) in + let _ := Constant.str " + If `message.current` is empty then it creates a smart contract + else it executes a call from the `message.caller` to the `message.target`. + + Parameters + ---------- + message : + Transaction specific items. + + env : + External items required for EVM execution. + + Returns + ------- + output : `MessageCallOutput` + Output of the message call + " in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_field (| M.get_name (| globals, "message" |), "target" |), + M.call (| + M.get_name (| globals, "Bytes0" |), + make_list [ + Constant.bytes "" + ], + make_dict [] + |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "is_collision" , + M.call (| + M.get_name (| globals, "account_has_code_or_nonce" |), + make_list [ + M.get_field (| M.get_name (| globals, "env" |), "state" |); + M.get_field (| M.get_name (| globals, "message" |), "current_target" |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + M.get_name (| globals, "is_collision" |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + M.call (| + M.get_name (| globals, "MessageCallOutput" |), + make_list [ + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |); + M.call (| + M.get_name (| globals, "tuple" |), + make_list [], + make_dict [] + |); + M.call (| + M.get_name (| globals, "set" |), + make_list [], + make_dict [] + |); + M.call (| + M.get_name (| globals, "AddressCollision" |), + make_list [], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "evm" , + M.call (| + M.get_name (| globals, "process_create_message" |), + make_list [ + M.get_name (| globals, "message" |); + M.get_name (| globals, "env" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "evm" , + M.call (| + M.get_name (| globals, "process_message" |), + make_list [ + M.get_name (| globals, "message" |); + M.get_name (| globals, "env" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + M.get_field (| M.get_name (| globals, "evm" |), "error" |), + (* then *) + ltac:(M.monadic ( +(* At stmt: unsupported node type: AnnAssign *) + let _ := M.assign_local (| + "accounts_to_delete" , + M.call (| + M.get_name (| globals, "set" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "refund_counter" , + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.assign_local (| + "logs" , + M.get_field (| M.get_name (| globals, "evm" |), "logs" |) + |) in + let _ := M.assign_local (| + "accounts_to_delete" , + M.get_field (| M.get_name (| globals, "evm" |), "accounts_to_delete" |) + |) in + let _ := M.assign_local (| + "refund_counter" , + M.get_field (| M.get_name (| globals, "evm" |), "refund_counter" |) + |) in + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "tx_end" , + M.call (| + M.get_name (| globals, "TransactionEnd" |), + make_list [ + BinOp.sub (| + M.get_field (| M.get_name (| globals, "message" |), "gas" |), + M.get_field (| M.get_name (| globals, "evm" |), "gas_left" |) + |); + M.get_field (| M.get_name (| globals, "evm" |), "output" |); + M.get_field (| M.get_name (| globals, "evm" |), "error" |) + ], + make_dict [] + |) + |) in + let _ := M.call (| + M.get_name (| globals, "evm_trace" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "tx_end" |) + ], + make_dict [] + |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, "MessageCallOutput" |), + make_list [], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Definition process_create_message : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "message"; "env" ] |) in + let _ := Constant.str " + Executes a call to create a smart contract. + + Parameters + ---------- + message : + Transaction specific items. + env : + External items required for EVM execution. + + Returns + ------- + evm: :py:class:`~ethereum.tangerine_whistle.vm.Evm` + Items containing execution specific objects. + " in + let _ := M.call (| + M.get_name (| globals, "begin_transaction" |), + make_list [ + M.get_field (| M.get_name (| globals, "env" |), "state" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "destroy_storage" |), + make_list [ + M.get_field (| M.get_name (| globals, "env" |), "state" |); + M.get_field (| M.get_name (| globals, "message" |), "current_target" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "evm" , + M.call (| + M.get_name (| globals, "process_message" |), + make_list [ + M.get_name (| globals, "message" |); + M.get_name (| globals, "env" |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + UnOp.not (| M.get_field (| M.get_name (| globals, "evm" |), "error" |) |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "contract_code" , + M.get_field (| M.get_name (| globals, "evm" |), "output" |) + |) in + let _ := M.assign_local (| + "contract_code_gas" , + BinOp.mult (| + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_name (| globals, "contract_code" |) + ], + make_dict [] + |), + M.get_name (| globals, "GAS_CODE_DEPOSIT" |) + |) + |) in +(* At stmt: unsupported node type: Try *) + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, "rollback_transaction" |), + make_list [ + M.get_field (| M.get_name (| globals, "env" |), "state" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + )) |) in + let _ := M.return_ (| + M.get_name (| globals, "evm" |) + |) in + M.pure Constant.None_)). + +Definition process_message : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "message"; "env" ] |) in + let _ := Constant.str " + Executes a call to create a smart contract. + + Parameters + ---------- + message : + Transaction specific items. + env : + External items required for EVM execution. + + Returns + ------- + evm: :py:class:`~ethereum.tangerine_whistle.vm.Evm` + Items containing execution specific objects + " in + let _ := + (* if *) + M.if_then_else (| + Compare.gt (| + M.get_field (| M.get_name (| globals, "message" |), "depth" |), + M.get_name (| globals, "STACK_DEPTH_LIMIT" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.call (| + M.get_name (| globals, "StackDepthLimitError" |), + make_list [ + Constant.str "Stack depth limit reached" + ], + make_dict [] + |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.call (| + M.get_name (| globals, "begin_transaction" |), + make_list [ + M.get_field (| M.get_name (| globals, "env" |), "state" |) + ], + make_dict [] + |) in + let _ := M.call (| + M.get_name (| globals, "touch_account" |), + make_list [ + M.get_field (| M.get_name (| globals, "env" |), "state" |); + M.get_field (| M.get_name (| globals, "message" |), "current_target" |) + ], + make_dict [] + |) in + let _ := + (* if *) + M.if_then_else (| + BoolOp.and (| + M.get_field (| M.get_name (| globals, "message" |), "should_transfer_value" |), + ltac:(M.monadic ( + Compare.not_eq (| + M.get_field (| M.get_name (| globals, "message" |), "value" |), + Constant.int 0 + |) + )) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, "move_ether" |), + make_list [ + M.get_field (| M.get_name (| globals, "env" |), "state" |); + M.get_field (| M.get_name (| globals, "message" |), "caller" |); + M.get_field (| M.get_name (| globals, "message" |), "current_target" |); + M.get_field (| M.get_name (| globals, "message" |), "value" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.assign_local (| + "evm" , + M.call (| + M.get_name (| globals, "execute_code" |), + make_list [ + M.get_name (| globals, "message" |); + M.get_name (| globals, "env" |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + M.get_field (| M.get_name (| globals, "evm" |), "error" |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, "rollback_transaction" |), + make_list [ + M.get_field (| M.get_name (| globals, "env" |), "state" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.call (| + M.get_name (| globals, "commit_transaction" |), + make_list [ + M.get_field (| M.get_name (| globals, "env" |), "state" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + )) |) in + let _ := M.return_ (| + M.get_name (| globals, "evm" |) + |) in + M.pure Constant.None_)). + +Definition execute_code : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "message"; "env" ] |) in + let _ := Constant.str " + Executes bytecode present in the `message`. + + Parameters + ---------- + message : + Transaction specific items. + env : + External items required for EVM execution. + + Returns + ------- + evm: `ethereum.vm.EVM` + Items containing execution specific objects + " in + let _ := M.assign_local (| + "code" , + M.get_field (| M.get_name (| globals, "message" |), "code" |) + |) in + let _ := M.assign_local (| + "valid_jump_destinations" , + M.call (| + M.get_name (| globals, "get_valid_jump_destinations" |), + make_list [ + M.get_name (| globals, "code" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "evm" , + M.call (| + M.get_name (| globals, "Evm" |), + make_list [], + make_dict [] + |) + |) in +(* At stmt: unsupported node type: Try *) + let _ := M.return_ (| + M.get_name (| globals, "evm" |) + |) in + M.pure Constant.None_)). diff --git a/CoqOfPython/ethereum/tangerine_whistle/vm/memory.v b/CoqOfPython/ethereum/tangerine_whistle/vm/memory.v new file mode 100644 index 0000000..e8d40e2 --- /dev/null +++ b/CoqOfPython/ethereum/tangerine_whistle/vm/memory.v @@ -0,0 +1,166 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.tangerine_whistle.vm.memory". + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) Memory +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +EVM memory operations. +". + +Axiom ethereum_utils_byte_imports_right_pad_zero_bytes : + IsImported globals "ethereum.utils.byte" "right_pad_zero_bytes". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_Bytes : + IsImported globals "ethereum.base_types" "Bytes". +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". + +Definition memory_write : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "memory"; "start_position"; "value" ] |) in + let _ := Constant.str " + Writes to memory. + + Parameters + ---------- + memory : + Memory contents of the EVM. + start_position : + Starting pointer to the memory. + value : + Data to write to memory. + " in + let _ := M.assign (| + M.slice (| + M.get_name (| globals, "memory" |), + M.get_name (| globals, "start_position" |), + BinOp.add (| + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.get_name (| globals, "start_position" |) + ], + make_dict [] + |), + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_name (| globals, "value" |) + ], + make_dict [] + |) + |), + Constant.None_ + |), + M.get_name (| globals, "value" |) + |) in + M.pure Constant.None_)). + +Definition memory_read_bytes : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "memory"; "start_position"; "size" ] |) in + let _ := Constant.str " + Read bytes from memory. + + Parameters + ---------- + memory : + Memory contents of the EVM. + start_position : + Starting pointer to the memory. + size : + Size of the data that needs to be read from `start_position`. + + Returns + ------- + data_bytes : + Data read from memory. + " in + let _ := M.return_ (| + M.slice (| + M.get_name (| globals, "memory" |), + M.get_name (| globals, "start_position" |), + BinOp.add (| + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.get_name (| globals, "start_position" |) + ], + make_dict [] + |), + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.get_name (| globals, "size" |) + ], + make_dict [] + |) + |), + Constant.None_ + |) + |) in + M.pure Constant.None_)). + +Definition buffer_read : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "buffer"; "start_position"; "size" ] |) in + let _ := Constant.str " + Read bytes from a buffer. Padding with zeros if necessary. + + Parameters + ---------- + buffer : + Memory contents of the EVM. + start_position : + Starting pointer to the memory. + size : + Size of the data that needs to be read from `start_position`. + + Returns + ------- + data_bytes : + Data read from memory. + " in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, "right_pad_zero_bytes" |), + make_list [ + M.slice (| + M.get_name (| globals, "buffer" |), + M.get_name (| globals, "start_position" |), + BinOp.add (| + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.get_name (| globals, "start_position" |) + ], + make_dict [] + |), + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.get_name (| globals, "size" |) + ], + make_dict [] + |) + |), + Constant.None_ + |); + M.get_name (| globals, "size" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). diff --git a/CoqOfPython/ethereum/tangerine_whistle/vm/precompiled_contracts/__init__.v b/CoqOfPython/ethereum/tangerine_whistle/vm/precompiled_contracts/__init__.v new file mode 100644 index 0000000..8931f02 --- /dev/null +++ b/CoqOfPython/ethereum/tangerine_whistle/vm/precompiled_contracts/__init__.v @@ -0,0 +1,66 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.tangerine_whistle.vm.precompiled_contracts.__init__". + +Definition expr_1 : Value.t := + Constant.str " +Precompiled Contract Addresses +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Addresses of precompiled contracts and mappings to their +implementations. +". + +Axiom ethereum_tangerine_whistle_utils_hexadecimal_imports_hex_to_address : + IsImported globals "ethereum.tangerine_whistle.utils.hexadecimal" "hex_to_address". + +Definition __all__ : Value.t := M.run ltac:(M.monadic ( + make_tuple [ Constant.str "ECRECOVER_ADDRESS"; Constant.str "SHA256_ADDRESS"; Constant.str "RIPEMD160_ADDRESS"; Constant.str "IDENTITY_ADDRESS" ] +)). + +Definition ECRECOVER_ADDRESS : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "hex_to_address" |), + make_list [ + Constant.str "0x01" + ], + make_dict [] + |) +)). + +Definition SHA256_ADDRESS : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "hex_to_address" |), + make_list [ + Constant.str "0x02" + ], + make_dict [] + |) +)). + +Definition RIPEMD160_ADDRESS : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "hex_to_address" |), + make_list [ + Constant.str "0x03" + ], + make_dict [] + |) +)). + +Definition IDENTITY_ADDRESS : Value.t := M.run ltac:(M.monadic ( + M.call (| + M.get_name (| globals, "hex_to_address" |), + make_list [ + Constant.str "0x04" + ], + make_dict [] + |) +)). diff --git a/CoqOfPython/ethereum/tangerine_whistle/vm/precompiled_contracts/ecrecover.v b/CoqOfPython/ethereum/tangerine_whistle/vm/precompiled_contracts/ecrecover.v new file mode 100644 index 0000000..1d6afbb --- /dev/null +++ b/CoqOfPython/ethereum/tangerine_whistle/vm/precompiled_contracts/ecrecover.v @@ -0,0 +1,301 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.tangerine_whistle.vm.precompiled_contracts.ecrecover". + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) ECRECOVER PRECOMPILED CONTRACT +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementation of the ECRECOVER precompiled contract. +". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". + +Axiom ethereum_crypto_elliptic_curve_imports_SECP256K1N : + IsImported globals "ethereum.crypto.elliptic_curve" "SECP256K1N". +Axiom ethereum_crypto_elliptic_curve_imports_secp256k1_recover : + IsImported globals "ethereum.crypto.elliptic_curve" "secp256k1_recover". + +Axiom ethereum_crypto_hash_imports_Hash32 : + IsImported globals "ethereum.crypto.hash" "Hash32". +Axiom ethereum_crypto_hash_imports_keccak256 : + IsImported globals "ethereum.crypto.hash" "keccak256". + +Axiom ethereum_utils_byte_imports_left_pad_zero_bytes : + IsImported globals "ethereum.utils.byte" "left_pad_zero_bytes". + +Axiom ethereum_tangerine_whistle_vm_imports_Evm : + IsImported globals "ethereum.tangerine_whistle.vm" "Evm". + +Axiom ethereum_tangerine_whistle_vm_gas_imports_GAS_ECRECOVER : + IsImported globals "ethereum.tangerine_whistle.vm.gas" "GAS_ECRECOVER". +Axiom ethereum_tangerine_whistle_vm_gas_imports_charge_gas : + IsImported globals "ethereum.tangerine_whistle.vm.gas" "charge_gas". + +Axiom ethereum_tangerine_whistle_vm_memory_imports_buffer_read : + IsImported globals "ethereum.tangerine_whistle.vm.memory" "buffer_read". + +Definition ecrecover : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Decrypts the address using elliptic curve DSA recovery mechanism and writes + the address to output. + + Parameters + ---------- + evm : + The current EVM frame. + " in + let _ := M.assign_local (| + "data" , + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "data" |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + M.get_name (| globals, "GAS_ECRECOVER" |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "message_hash_bytes" , + M.call (| + M.get_name (| globals, "buffer_read" |), + make_list [ + M.get_name (| globals, "data" |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 32 + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "message_hash" , + M.call (| + M.get_name (| globals, "Hash32" |), + make_list [ + M.get_name (| globals, "message_hash_bytes" |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "v" , + M.call (| + M.get_field (| M.get_name (| globals, "U256" |), "from_be_bytes" |), + make_list [ + M.call (| + M.get_name (| globals, "buffer_read" |), + make_list [ + M.get_name (| globals, "data" |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 32 + ], + make_dict [] + |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 32 + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "r" , + M.call (| + M.get_field (| M.get_name (| globals, "U256" |), "from_be_bytes" |), + make_list [ + M.call (| + M.get_name (| globals, "buffer_read" |), + make_list [ + M.get_name (| globals, "data" |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 64 + ], + make_dict [] + |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 32 + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "s" , + M.call (| + M.get_field (| M.get_name (| globals, "U256" |), "from_be_bytes" |), + make_list [ + M.call (| + M.get_name (| globals, "buffer_read" |), + make_list [ + M.get_name (| globals, "data" |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 96 + ], + make_dict [] + |); + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + Constant.int 32 + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + let _ := + (* if *) + M.if_then_else (| + BoolOp.and (| + Compare.not_eq (| + M.get_name (| globals, "v" |), + Constant.int 27 + |), + ltac:(M.monadic ( + Compare.not_eq (| + M.get_name (| globals, "v" |), + Constant.int 28 + |) + )) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + Constant.None_ + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + BoolOp.or (| + Compare.gt_e (| + Constant.int 0, + M.get_name (| globals, "r" |) + |), + ltac:(M.monadic ( + Compare.gt_e (| + M.get_name (| globals, "r" |), + M.get_name (| globals, "SECP256K1N" |) + |) + )) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + Constant.None_ + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + (* if *) + M.if_then_else (| + BoolOp.or (| + Compare.gt_e (| + Constant.int 0, + M.get_name (| globals, "s" |) + |), + ltac:(M.monadic ( + Compare.gt_e (| + M.get_name (| globals, "s" |), + M.get_name (| globals, "SECP256K1N" |) + |) + )) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + Constant.None_ + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in +(* At stmt: unsupported node type: Try *) + let _ := M.assign_local (| + "address" , + M.slice (| + M.call (| + M.get_name (| globals, "keccak256" |), + make_list [ + M.get_name (| globals, "public_key" |) + ], + make_dict [] + |), + Constant.int 12, + Constant.int 32, + Constant.None_ + |) + |) in + let _ := M.assign_local (| + "padded_address" , + M.call (| + M.get_name (| globals, "left_pad_zero_bytes" |), + make_list [ + M.get_name (| globals, "address" |); + Constant.int 32 + ], + make_dict [] + |) + |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, "evm" |), "output" |), + M.get_name (| globals, "padded_address" |) + |) in + M.pure Constant.None_)). diff --git a/CoqOfPython/ethereum/tangerine_whistle/vm/precompiled_contracts/identity.v b/CoqOfPython/ethereum/tangerine_whistle/vm/precompiled_contracts/identity.v new file mode 100644 index 0000000..9226b27 --- /dev/null +++ b/CoqOfPython/ethereum/tangerine_whistle/vm/precompiled_contracts/identity.v @@ -0,0 +1,94 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.tangerine_whistle.vm.precompiled_contracts.identity". + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) IDENTITY PRECOMPILED CONTRACT +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementation of the `IDENTITY` precompiled contract. +". + +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". + +Axiom ethereum_utils_numeric_imports_ceil32 : + IsImported globals "ethereum.utils.numeric" "ceil32". + +Axiom ethereum_tangerine_whistle_vm_imports_Evm : + IsImported globals "ethereum.tangerine_whistle.vm" "Evm". + +Axiom ethereum_tangerine_whistle_vm_gas_imports_GAS_IDENTITY : + IsImported globals "ethereum.tangerine_whistle.vm.gas" "GAS_IDENTITY". +Axiom ethereum_tangerine_whistle_vm_gas_imports_GAS_IDENTITY_WORD : + IsImported globals "ethereum.tangerine_whistle.vm.gas" "GAS_IDENTITY_WORD". +Axiom ethereum_tangerine_whistle_vm_gas_imports_charge_gas : + IsImported globals "ethereum.tangerine_whistle.vm.gas" "charge_gas". + +Definition identity : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Writes the message data to output. + + Parameters + ---------- + evm : + The current EVM frame. + " in + let _ := M.assign_local (| + "data" , + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "data" |) + |) in + let _ := M.assign_local (| + "word_count" , + BinOp.floor_div (| + M.call (| + M.get_name (| globals, "ceil32" |), + make_list [ + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_name (| globals, "data" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |), + Constant.int 32 + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + BinOp.add (| + M.get_name (| globals, "GAS_IDENTITY" |), + BinOp.mult (| + M.get_name (| globals, "GAS_IDENTITY_WORD" |), + M.get_name (| globals, "word_count" |) + |) + |) + ], + make_dict [] + |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, "evm" |), "output" |), + M.get_name (| globals, "data" |) + |) in + M.pure Constant.None_)). diff --git a/CoqOfPython/ethereum/tangerine_whistle/vm/precompiled_contracts/mapping.v b/CoqOfPython/ethereum/tangerine_whistle/vm/precompiled_contracts/mapping.v new file mode 100644 index 0000000..450b048 --- /dev/null +++ b/CoqOfPython/ethereum/tangerine_whistle/vm/precompiled_contracts/mapping.v @@ -0,0 +1,49 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.tangerine_whistle.vm.precompiled_contracts.mapping". + +Definition expr_1 : Value.t := + Constant.str " +Precompiled Contract Addresses +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Mapping of precompiled contracts their implementations. +". + +Axiom typing_imports_Callable : + IsImported globals "typing" "Callable". +Axiom typing_imports_Dict : + IsImported globals "typing" "Dict". + +Axiom ethereum_tangerine_whistle_fork_types_imports_Address : + IsImported globals "ethereum.tangerine_whistle.fork_types" "Address". + +Axiom ethereum_tangerine_whistle_vm_precompiled_contracts_imports_ECRECOVER_ADDRESS : + IsImported globals "ethereum.tangerine_whistle.vm.precompiled_contracts" "ECRECOVER_ADDRESS". +Axiom ethereum_tangerine_whistle_vm_precompiled_contracts_imports_IDENTITY_ADDRESS : + IsImported globals "ethereum.tangerine_whistle.vm.precompiled_contracts" "IDENTITY_ADDRESS". +Axiom ethereum_tangerine_whistle_vm_precompiled_contracts_imports_RIPEMD160_ADDRESS : + IsImported globals "ethereum.tangerine_whistle.vm.precompiled_contracts" "RIPEMD160_ADDRESS". +Axiom ethereum_tangerine_whistle_vm_precompiled_contracts_imports_SHA256_ADDRESS : + IsImported globals "ethereum.tangerine_whistle.vm.precompiled_contracts" "SHA256_ADDRESS". + +Axiom ethereum_tangerine_whistle_vm_precompiled_contracts_ecrecover_imports_ecrecover : + IsImported globals "ethereum.tangerine_whistle.vm.precompiled_contracts.ecrecover" "ecrecover". + +Axiom ethereum_tangerine_whistle_vm_precompiled_contracts_identity_imports_identity : + IsImported globals "ethereum.tangerine_whistle.vm.precompiled_contracts.identity" "identity". + +Axiom ethereum_tangerine_whistle_vm_precompiled_contracts_ripemd160_imports_ripemd160 : + IsImported globals "ethereum.tangerine_whistle.vm.precompiled_contracts.ripemd160" "ripemd160". + +Axiom ethereum_tangerine_whistle_vm_precompiled_contracts_sha256_imports_sha256 : + IsImported globals "ethereum.tangerine_whistle.vm.precompiled_contracts.sha256" "sha256". + +(* At top_level_stmt: unsupported node type: AnnAssign *) diff --git a/CoqOfPython/ethereum/tangerine_whistle/vm/precompiled_contracts/ripemd160.v b/CoqOfPython/ethereum/tangerine_whistle/vm/precompiled_contracts/ripemd160.v new file mode 100644 index 0000000..52fd66f --- /dev/null +++ b/CoqOfPython/ethereum/tangerine_whistle/vm/precompiled_contracts/ripemd160.v @@ -0,0 +1,125 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.tangerine_whistle.vm.precompiled_contracts.ripemd160". + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) RIPEMD160 PRECOMPILED CONTRACT +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementation of the `RIPEMD160` precompiled contract. +". + +(* At top_level_stmt: unsupported node type: Import *) + +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". + +Axiom ethereum_utils_byte_imports_left_pad_zero_bytes : + IsImported globals "ethereum.utils.byte" "left_pad_zero_bytes". + +Axiom ethereum_utils_numeric_imports_ceil32 : + IsImported globals "ethereum.utils.numeric" "ceil32". + +Axiom ethereum_tangerine_whistle_vm_imports_Evm : + IsImported globals "ethereum.tangerine_whistle.vm" "Evm". + +Axiom ethereum_tangerine_whistle_vm_gas_imports_GAS_RIPEMD160 : + IsImported globals "ethereum.tangerine_whistle.vm.gas" "GAS_RIPEMD160". +Axiom ethereum_tangerine_whistle_vm_gas_imports_GAS_RIPEMD160_WORD : + IsImported globals "ethereum.tangerine_whistle.vm.gas" "GAS_RIPEMD160_WORD". +Axiom ethereum_tangerine_whistle_vm_gas_imports_charge_gas : + IsImported globals "ethereum.tangerine_whistle.vm.gas" "charge_gas". + +Definition ripemd160 : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Writes the ripemd160 hash to output. + + Parameters + ---------- + evm : + The current EVM frame. + " in + let _ := M.assign_local (| + "data" , + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "data" |) + |) in + let _ := M.assign_local (| + "word_count" , + BinOp.floor_div (| + M.call (| + M.get_name (| globals, "ceil32" |), + make_list [ + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_name (| globals, "data" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |), + Constant.int 32 + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + BinOp.add (| + M.get_name (| globals, "GAS_RIPEMD160" |), + BinOp.mult (| + M.get_name (| globals, "GAS_RIPEMD160_WORD" |), + M.get_name (| globals, "word_count" |) + |) + |) + ], + make_dict [] + |) in + let _ := M.assign_local (| + "hash_bytes" , + M.call (| + M.get_field (| M.call (| + M.get_field (| M.get_name (| globals, "hashlib" |), "new" |), + make_list [ + Constant.str "ripemd160"; + M.get_name (| globals, "data" |) + ], + make_dict [] + |), "digest" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "padded_hash" , + M.call (| + M.get_name (| globals, "left_pad_zero_bytes" |), + make_list [ + M.get_name (| globals, "hash_bytes" |); + Constant.int 32 + ], + make_dict [] + |) + |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, "evm" |), "output" |), + M.get_name (| globals, "padded_hash" |) + |) in + M.pure Constant.None_)). diff --git a/CoqOfPython/ethereum/tangerine_whistle/vm/precompiled_contracts/sha256.v b/CoqOfPython/ethereum/tangerine_whistle/vm/precompiled_contracts/sha256.v new file mode 100644 index 0000000..5144a3e --- /dev/null +++ b/CoqOfPython/ethereum/tangerine_whistle/vm/precompiled_contracts/sha256.v @@ -0,0 +1,106 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.tangerine_whistle.vm.precompiled_contracts.sha256". + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) SHA256 PRECOMPILED CONTRACT +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementation of the `SHA256` precompiled contract. +". + +(* At top_level_stmt: unsupported node type: Import *) + +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". + +Axiom ethereum_utils_numeric_imports_ceil32 : + IsImported globals "ethereum.utils.numeric" "ceil32". + +Axiom ethereum_tangerine_whistle_vm_imports_Evm : + IsImported globals "ethereum.tangerine_whistle.vm" "Evm". + +Axiom ethereum_tangerine_whistle_vm_gas_imports_GAS_SHA256 : + IsImported globals "ethereum.tangerine_whistle.vm.gas" "GAS_SHA256". +Axiom ethereum_tangerine_whistle_vm_gas_imports_GAS_SHA256_WORD : + IsImported globals "ethereum.tangerine_whistle.vm.gas" "GAS_SHA256_WORD". +Axiom ethereum_tangerine_whistle_vm_gas_imports_charge_gas : + IsImported globals "ethereum.tangerine_whistle.vm.gas" "charge_gas". + +Definition sha256 : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm" ] |) in + let _ := Constant.str " + Writes the sha256 hash to output. + + Parameters + ---------- + evm : + The current EVM frame. + " in + let _ := M.assign_local (| + "data" , + M.get_field (| M.get_field (| M.get_name (| globals, "evm" |), "message" |), "data" |) + |) in + let _ := M.assign_local (| + "word_count" , + BinOp.floor_div (| + M.call (| + M.get_name (| globals, "ceil32" |), + make_list [ + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_name (| globals, "data" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |), + Constant.int 32 + |) + |) in + let _ := M.call (| + M.get_name (| globals, "charge_gas" |), + make_list [ + M.get_name (| globals, "evm" |); + BinOp.add (| + M.get_name (| globals, "GAS_SHA256" |), + BinOp.mult (| + M.get_name (| globals, "GAS_SHA256_WORD" |), + M.get_name (| globals, "word_count" |) + |) + |) + ], + make_dict [] + |) in + let _ := M.assign (| + M.get_field (| M.get_name (| globals, "evm" |), "output" |), + M.call (| + M.get_field (| M.call (| + M.get_field (| M.get_name (| globals, "hashlib" |), "sha256" |), + make_list [ + M.get_name (| globals, "data" |) + ], + make_dict [] + |), "digest" |), + make_list [], + make_dict [] + |) + |) in + M.pure Constant.None_)). diff --git a/CoqOfPython/ethereum/tangerine_whistle/vm/runtime.v b/CoqOfPython/ethereum/tangerine_whistle/vm/runtime.v new file mode 100644 index 0000000..fc5eb03 --- /dev/null +++ b/CoqOfPython/ethereum/tangerine_whistle/vm/runtime.v @@ -0,0 +1,157 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.tangerine_whistle.vm.runtime". + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) Runtime Operations +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Runtime related operations used while executing EVM code. +". + +Axiom typing_imports_Set : + IsImported globals "typing" "Set". + +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". + +Axiom ethereum_tangerine_whistle_vm_instructions_imports_Ops : + IsImported globals "ethereum.tangerine_whistle.vm.instructions" "Ops". + +Definition get_valid_jump_destinations : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "code" ] |) in + let _ := Constant.str " + Analyze the evm code to obtain the set of valid jump destinations. + + Valid jump destinations are defined as follows: + * The jump destination is less than the length of the code. + * The jump destination should have the `JUMPDEST` opcode (0x5B). + * The jump destination shouldn't be part of the data corresponding to + `PUSH-N` opcodes. + + Note - Jump destinations are 0-indexed. + + Parameters + ---------- + code : + The EVM code which is to be executed. + + Returns + ------- + valid_jump_destinations: `Set[Uint]` + The set of valid jump destinations in the code. + " in + let _ := M.assign_local (| + "valid_jump_destinations" , + M.call (| + M.get_name (| globals, "set" |), + make_list [], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "pc" , + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + |) in + let _ := + M.while (| + Compare.lt (| + M.get_name (| globals, "pc" |), + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_name (| globals, "code" |) + ], + make_dict [] + |) + |), + ltac:(M.monadic ( +(* At stmt: unsupported node type: Try *) + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, "current_opcode" |), + M.get_field (| M.get_name (| globals, "Ops" |), "JUMPDEST" |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.call (| + M.get_field (| M.get_name (| globals, "valid_jump_destinations" |), "add" |), + make_list [ + M.get_name (| globals, "pc" |) + ], + make_dict [] + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + BoolOp.and (| + Compare.lt_e (| + M.get_field (| M.get_field (| M.get_name (| globals, "Ops" |), "PUSH1" |), "value" |), + M.get_field (| M.get_name (| globals, "current_opcode" |), "value" |) + |), + ltac:(M.monadic ( + Compare.lt_e (| + M.get_field (| M.get_name (| globals, "current_opcode" |), "value" |), + M.get_field (| M.get_field (| M.get_name (| globals, "Ops" |), "PUSH32" |), "value" |) + |) + )) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.assign_local (| + "push_data_size" , + BinOp.add (| + BinOp.sub (| + M.get_field (| M.get_name (| globals, "current_opcode" |), "value" |), + M.get_field (| M.get_field (| M.get_name (| globals, "Ops" |), "PUSH1" |), "value" |) + |), + Constant.int 1 + |) + |) in + let _ := M.assign_op_local (| + BinOp.add, + "pc", + M.get_name (| globals, "push_data_size" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )) |) in + let _ := M.assign_op_local (| + BinOp.add, + "pc", + Constant.int 1 + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := M.return_ (| + M.get_name (| globals, "valid_jump_destinations" |) + |) in + M.pure Constant.None_)). diff --git a/CoqOfPython/ethereum/tangerine_whistle/vm/stack.v b/CoqOfPython/ethereum/tangerine_whistle/vm/stack.v new file mode 100644 index 0000000..6311bf2 --- /dev/null +++ b/CoqOfPython/ethereum/tangerine_whistle/vm/stack.v @@ -0,0 +1,123 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.tangerine_whistle.vm.stack". + +Definition expr_1 : Value.t := + Constant.str " +Ethereum Virtual Machine (EVM) Stack +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementation of the stack operators for the EVM. +". + +Axiom typing_imports_List : + IsImported globals "typing" "List". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". + +Axiom ethereum_tangerine_whistle_vm_exceptions_imports_StackOverflowError : + IsImported globals "ethereum.tangerine_whistle.vm.exceptions" "StackOverflowError". +Axiom ethereum_tangerine_whistle_vm_exceptions_imports_StackUnderflowError : + IsImported globals "ethereum.tangerine_whistle.vm.exceptions" "StackUnderflowError". + +Definition pop : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "stack" ] |) in + let _ := Constant.str " + Pops the top item off of `stack`. + + Parameters + ---------- + stack : + EVM stack. + + Returns + ------- + value : `U256` + The top element on the stack. + + " in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_name (| globals, "stack" |) + ], + make_dict [] + |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, "StackUnderflowError" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.return_ (| + M.call (| + M.get_field (| M.get_name (| globals, "stack" |), "pop" |), + make_list [], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Definition push : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "stack"; "value" ] |) in + let _ := Constant.str " + Pushes `value` onto `stack`. + + Parameters + ---------- + stack : + EVM stack. + + value : + Item to be pushed onto `stack`. + + " in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_name (| globals, "stack" |) + ], + make_dict [] + |), + Constant.int 1024 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.raise (| Some (M.get_name (| globals, "StackOverflowError" |)) |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.return_ (| + M.call (| + M.get_field (| M.get_name (| globals, "stack" |), "append" |), + make_list [ + M.get_name (| globals, "value" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). diff --git a/CoqOfPython/ethereum/trace.v b/CoqOfPython/ethereum/trace.v new file mode 100644 index 0000000..c659277 --- /dev/null +++ b/CoqOfPython/ethereum/trace.v @@ -0,0 +1,136 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.trace". + +Definition expr_1 : Value.t := + Constant.str " +.. _trace: + +EVM Trace +^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Defines the functions required for creating evm traces during execution. +". + +(* At top_level_stmt: unsupported node type: Import *) + +Axiom dataclasses_imports_dataclass : + IsImported globals "dataclasses" "dataclass". + +Axiom typing_imports_Optional : + IsImported globals "typing" "Optional". +Axiom typing_imports_Union : + IsImported globals "typing" "Union". + +Definition TransactionStart : Value.t := + builtins.make_klass + [] + [ + + ] + [ + + ]. + +Definition TransactionEnd : Value.t := + builtins.make_klass + [] + [ + + ] + [ + + ]. + +Definition PrecompileStart : Value.t := + builtins.make_klass + [] + [ + + ] + [ + + ]. + +Definition PrecompileEnd : Value.t := + builtins.make_klass + [] + [ + + ] + [ + + ]. + +Definition OpStart : Value.t := + builtins.make_klass + [] + [ + + ] + [ + + ]. + +Definition OpEnd : Value.t := + builtins.make_klass + [] + [ + + ] + [ + + ]. + +Definition OpException : Value.t := + builtins.make_klass + [] + [ + + ] + [ + + ]. + +Definition EvmStop : Value.t := + builtins.make_klass + [] + [ + + ] + [ + + ]. + +Definition GasAndRefund : Value.t := + builtins.make_klass + [] + [ + + ] + [ + + ]. + +Definition TraceEvent : Value.t := M.run ltac:(M.monadic ( + M.get_subscript (| + M.get_name (| globals, "Union" |), + make_tuple [ M.get_name (| globals, "TransactionStart" |); M.get_name (| globals, "TransactionEnd" |); M.get_name (| globals, "PrecompileStart" |); M.get_name (| globals, "PrecompileEnd" |); M.get_name (| globals, "OpStart" |); M.get_name (| globals, "OpEnd" |); M.get_name (| globals, "OpException" |); M.get_name (| globals, "EvmStop" |); M.get_name (| globals, "GasAndRefund" |) ] + |) +)). + +Definition evm_trace : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "evm"; "event"; "trace_memory"; "trace_stack"; "trace_return_data" ] |) in + let _ := Constant.str " + Create a trace of the event. + " in + let _ := M.pass (| |) in + M.pure Constant.None_)). diff --git a/CoqOfPython/ethereum/utils/__init__.v b/CoqOfPython/ethereum/utils/__init__.v new file mode 100644 index 0000000..aa7d70b --- /dev/null +++ b/CoqOfPython/ethereum/utils/__init__.v @@ -0,0 +1,8 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.utils.__init__". + +Definition expr_1 : Value.t := + Constant.str " +Utility functions used in this specification. +". diff --git a/CoqOfPython/ethereum/utils/byte.v b/CoqOfPython/ethereum/utils/byte.v new file mode 100644 index 0000000..07efce7 --- /dev/null +++ b/CoqOfPython/ethereum/utils/byte.v @@ -0,0 +1,81 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.utils.byte". + +Definition expr_1 : Value.t := + Constant.str " +Utility Functions For Byte Strings +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Byte specific utility functions used in this specification. +". + +Axiom ethereum_base_types_imports_Bytes : + IsImported globals "ethereum.base_types" "Bytes". + +Definition left_pad_zero_bytes : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "value"; "size" ] |) in + let _ := Constant.str " + Left pad zeroes to `value` if it's length is less than the given `size`. + + Parameters + ---------- + value : + The byte string that needs to be padded. + size : + The number of bytes that need that need to be padded. + + Returns + ------- + left_padded_value: `ethereum.base_types.Bytes` + left padded byte string of given `size`. + " in + let _ := M.return_ (| + M.call (| + M.get_field (| M.get_name (| globals, "value" |), "rjust" |), + make_list [ + M.get_name (| globals, "size" |); + Constant.bytes "00" + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Definition right_pad_zero_bytes : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "value"; "size" ] |) in + let _ := Constant.str " + Right pad zeroes to `value` if it's length is less than the given `size`. + + Parameters + ---------- + value : + The byte string that needs to be padded. + size : + The number of bytes that need that need to be padded. + + Returns + ------- + right_padded_value: `ethereum.base_types.Bytes` + right padded byte string of given `size`. + " in + let _ := M.return_ (| + M.call (| + M.get_field (| M.get_name (| globals, "value" |), "ljust" |), + make_list [ + M.get_name (| globals, "size" |); + Constant.bytes "00" + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). diff --git a/CoqOfPython/ethereum/utils/ensure.v b/CoqOfPython/ethereum/utils/ensure.v new file mode 100644 index 0000000..88c6e02 --- /dev/null +++ b/CoqOfPython/ethereum/utils/ensure.v @@ -0,0 +1,56 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.utils.ensure". + +Definition expr_1 : Value.t := + Constant.str " +Ensure (Assertion) Utilities +^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Functions that simplify checking assertions and raising exceptions. +". + +Axiom typing_imports_Type : + IsImported globals "typing" "Type". +Axiom typing_imports_Union : + IsImported globals "typing" "Union". + +Definition ensure : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "value"; "exception" ] |) in + let _ := Constant.str " + Does nothing if `value` is truthy, otherwise raises the exception returned + by `exception_class`. + + Parameters + ---------- + + value : + Value that should be true. + + exception : + Constructor for the exception to raise. + " in + let _ := + (* if *) + M.if_then_else (| + M.get_name (| globals, "value" |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + Constant.None_ + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.raise (| Some (M.get_name (| globals, "exception" |)) |) in + M.pure Constant.None_)). diff --git a/CoqOfPython/ethereum/utils/hexadecimal.v b/CoqOfPython/ethereum/utils/hexadecimal.v new file mode 100644 index 0000000..822bc50 --- /dev/null +++ b/CoqOfPython/ethereum/utils/hexadecimal.v @@ -0,0 +1,494 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.utils.hexadecimal". + +Definition expr_1 : Value.t := + Constant.str " +Utility Functions For Hexadecimal Strings +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Hexadecimal strings specific utility functions used in this specification. +". + +Axiom ethereum_base_types_imports_U64 : + IsImported globals "ethereum.base_types" "U64". +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_Bytes : + IsImported globals "ethereum.base_types" "Bytes". +Axiom ethereum_base_types_imports_Bytes8 : + IsImported globals "ethereum.base_types" "Bytes8". +Axiom ethereum_base_types_imports_Bytes20 : + IsImported globals "ethereum.base_types" "Bytes20". +Axiom ethereum_base_types_imports_Bytes32 : + IsImported globals "ethereum.base_types" "Bytes32". +Axiom ethereum_base_types_imports_Bytes256 : + IsImported globals "ethereum.base_types" "Bytes256". +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". + +Axiom ethereum_crypto_hash_imports_Hash32 : + IsImported globals "ethereum.crypto.hash" "Hash32". + +Definition has_hex_prefix : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "hex_string" ] |) in + let _ := Constant.str " + Check if a hex string starts with hex prefix (0x). + + Parameters + ---------- + hex_string : + The hexadecimal string to be checked for presence of prefix. + + Returns + ------- + has_prefix : `bool` + Boolean indicating whether the hex string has 0x prefix. + " in + let _ := M.return_ (| + M.call (| + M.get_field (| M.get_name (| globals, "hex_string" |), "startswith" |), + make_list [ + Constant.str "0x" + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Definition remove_hex_prefix : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "hex_string" ] |) in + let _ := Constant.str " + Remove 0x prefix from a hex string if present. This function returns the + passed hex string if it isn't prefixed with 0x. + + Parameters + ---------- + hex_string : + The hexadecimal string whose prefix is to be removed. + + Returns + ------- + modified_hex_string : `str` + The hexadecimal string with the 0x prefix removed if present. + " in + let _ := + (* if *) + M.if_then_else (| + M.call (| + M.get_name (| globals, "has_hex_prefix" |), + make_list [ + M.get_name (| globals, "hex_string" |) + ], + make_dict [] + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + M.slice (| + M.get_name (| globals, "hex_string" |), + M.call (| + M.get_name (| globals, "len" |), + make_list [ + Constant.str "0x" + ], + make_dict [] + |), + Constant.None_, + Constant.None_ + |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := M.return_ (| + M.get_name (| globals, "hex_string" |) + |) in + M.pure Constant.None_)). + +Definition hex_to_bytes : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "hex_string" ] |) in + let _ := Constant.str " + Convert hex string to bytes. + + Parameters + ---------- + hex_string : + The hexadecimal string to be converted to bytes. + + Returns + ------- + byte_stream : `bytes` + Byte stream corresponding to the given hexadecimal string. + " in + let _ := M.return_ (| + M.call (| + M.get_field (| M.get_name (| globals, "bytes" |), "fromhex" |), + make_list [ + M.call (| + M.get_name (| globals, "remove_hex_prefix" |), + make_list [ + M.get_name (| globals, "hex_string" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Definition hex_to_bytes8 : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "hex_string" ] |) in + let _ := Constant.str " + Convert hex string to 8 bytes. + + Parameters + ---------- + hex_string : + The hexadecimal string to be converted to 8 bytes. + + Returns + ------- + 8_byte_stream : `Bytes8` + 8-byte stream corresponding to the given hexadecimal string. + " in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, "Bytes8" |), + make_list [ + M.call (| + M.get_field (| M.get_name (| globals, "bytes" |), "fromhex" |), + make_list [ + M.call (| + M.get_field (| M.call (| + M.get_name (| globals, "remove_hex_prefix" |), + make_list [ + M.get_name (| globals, "hex_string" |) + ], + make_dict [] + |), "rjust" |), + make_list [ + Constant.int 16; + Constant.str "0" + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Definition hex_to_bytes20 : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "hex_string" ] |) in + let _ := Constant.str " + Convert hex string to 20 bytes. + + Parameters + ---------- + hex_string : + The hexadecimal string to be converted to 20 bytes. + + Returns + ------- + 20_byte_stream : `Bytes20` + 20-byte stream corresponding to the given hexadecimal string. + " in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, "Bytes20" |), + make_list [ + M.call (| + M.get_field (| M.get_name (| globals, "bytes" |), "fromhex" |), + make_list [ + M.call (| + M.get_field (| M.call (| + M.get_name (| globals, "remove_hex_prefix" |), + make_list [ + M.get_name (| globals, "hex_string" |) + ], + make_dict [] + |), "rjust" |), + make_list [ + Constant.int 20; + Constant.str "0" + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Definition hex_to_bytes32 : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "hex_string" ] |) in + let _ := Constant.str " + Convert hex string to 32 bytes. + + Parameters + ---------- + hex_string : + The hexadecimal string to be converted to 32 bytes. + + Returns + ------- + 32_byte_stream : `Bytes32` + 32-byte stream corresponding to the given hexadecimal string. + " in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, "Bytes32" |), + make_list [ + M.call (| + M.get_field (| M.get_name (| globals, "bytes" |), "fromhex" |), + make_list [ + M.call (| + M.get_field (| M.call (| + M.get_name (| globals, "remove_hex_prefix" |), + make_list [ + M.get_name (| globals, "hex_string" |) + ], + make_dict [] + |), "rjust" |), + make_list [ + Constant.int 64; + Constant.str "0" + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Definition hex_to_bytes256 : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "hex_string" ] |) in + let _ := Constant.str " + Convert hex string to 256 bytes. + + Parameters + ---------- + hex_string : + The hexadecimal string to be converted to 256 bytes. + + Returns + ------- + 256_byte_stream : `Bytes256` + 256-byte stream corresponding to the given hexadecimal string. + " in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, "Bytes256" |), + make_list [ + M.call (| + M.get_field (| M.get_name (| globals, "bytes" |), "fromhex" |), + make_list [ + M.call (| + M.get_field (| M.call (| + M.get_name (| globals, "remove_hex_prefix" |), + make_list [ + M.get_name (| globals, "hex_string" |) + ], + make_dict [] + |), "rjust" |), + make_list [ + Constant.int 512; + Constant.str "0" + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Definition hex_to_hash : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "hex_string" ] |) in + let _ := Constant.str " + Convert hex string to hash32 (32 bytes). + + Parameters + ---------- + hex_string : + The hexadecimal string to be converted to hash32. + + Returns + ------- + hash : `Hash32` + 32-byte stream obtained from the given hexadecimal string. + " in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, "Hash32" |), + make_list [ + M.call (| + M.get_field (| M.get_name (| globals, "bytes" |), "fromhex" |), + make_list [ + M.call (| + M.get_name (| globals, "remove_hex_prefix" |), + make_list [ + M.get_name (| globals, "hex_string" |) + ], + make_dict [] + |) + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Definition hex_to_uint : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "hex_string" ] |) in + let _ := Constant.str " + Convert hex string to Uint. + + Parameters + ---------- + hex_string : + The hexadecimal string to be converted to Uint. + + Returns + ------- + converted : `Uint` + The unsigned integer obtained from the given hexadecimal string. + " in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + M.call (| + M.get_name (| globals, "int" |), + make_list [ + M.call (| + M.get_name (| globals, "remove_hex_prefix" |), + make_list [ + M.get_name (| globals, "hex_string" |) + ], + make_dict [] + |); + Constant.int 16 + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Definition hex_to_u64 : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "hex_string" ] |) in + let _ := Constant.str " + Convert hex string to U64. + + Parameters + ---------- + hex_string : + The hexadecimal string to be converted to U256. + + Returns + ------- + converted : `U64` + The U64 integer obtained from the given hexadecimal string. + " in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, "U64" |), + make_list [ + M.call (| + M.get_name (| globals, "int" |), + make_list [ + M.call (| + M.get_name (| globals, "remove_hex_prefix" |), + make_list [ + M.get_name (| globals, "hex_string" |) + ], + make_dict [] + |); + Constant.int 16 + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Definition hex_to_u256 : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "hex_string" ] |) in + let _ := Constant.str " + Convert hex string to U256. + + Parameters + ---------- + hex_string : + The hexadecimal string to be converted to U256. + + Returns + ------- + converted : `U256` + The U256 integer obtained from the given hexadecimal string. + " in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, "U256" |), + make_list [ + M.call (| + M.get_name (| globals, "int" |), + make_list [ + M.call (| + M.get_name (| globals, "remove_hex_prefix" |), + make_list [ + M.get_name (| globals, "hex_string" |) + ], + make_dict [] + |); + Constant.int 16 + ], + make_dict [] + |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). diff --git a/CoqOfPython/ethereum/utils/numeric.v b/CoqOfPython/ethereum/utils/numeric.v new file mode 100644 index 0000000..a3fc348 --- /dev/null +++ b/CoqOfPython/ethereum/utils/numeric.v @@ -0,0 +1,499 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.utils.numeric". + +Definition expr_1 : Value.t := + Constant.str " +Utility Functions For Numeric Operations +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Numeric operations specific utility functions used in this specification. +". + +Axiom typing_imports_Sequence : + IsImported globals "typing" "Sequence". +Axiom typing_imports_Tuple : + IsImported globals "typing" "Tuple". + +Axiom ethereum_base_types_imports_U32 : + IsImported globals "ethereum.base_types" "U32". +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". + +Definition get_sign : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "value" ] |) in + let _ := Constant.str " + Determines the sign of a number. + + Parameters + ---------- + value : + The value whose sign is to be determined. + + Returns + ------- + sign : `int` + The sign of the number (-1 or 0 or 1). + The return value is based on math signum function. + " in + let _ := + (* if *) + M.if_then_else (| + Compare.lt (| + M.get_name (| globals, "value" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + UnOp.sub (| Constant.int 1 |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, "value" |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + Constant.int 0 + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.return_ (| + Constant.int 1 + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_)). + +Definition ceil32 : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "value" ] |) in + let _ := Constant.str " + Converts a unsigned integer to the next closest multiple of 32. + + Parameters + ---------- + value : + The value whose ceil32 is to be calculated. + + Returns + ------- + ceil32 : `ethereum.base_types.U256` + The same value if it's a perfect multiple of 32 + else it returns the smallest multiple of 32 + that is greater than `value`. + " in + let _ := M.assign_local (| + "ceiling" , + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 32 + ], + make_dict [] + |) + |) in + let _ := M.assign_local (| + "remainder" , + BinOp.mod_ (| + M.get_name (| globals, "value" |), + M.get_name (| globals, "ceiling" |) + |) + |) in + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + M.get_name (| globals, "remainder" |), + M.call (| + M.get_name (| globals, "Uint" |), + make_list [ + Constant.int 0 + ], + make_dict [] + |) + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + M.get_name (| globals, "value" |) + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + let _ := M.return_ (| + BinOp.sub (| + BinOp.add (| + M.get_name (| globals, "value" |), + M.get_name (| globals, "ceiling" |) + |), + M.get_name (| globals, "remainder" |) + |) + |) in + M.pure Constant.None_ + )) |) in + M.pure Constant.None_)). + +Definition is_prime : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "number" ] |) in + let _ := Constant.str " + Checks if `number` is a prime number. + + Parameters + ---------- + number : + The number to check for primality. + + Returns + ------- + is_number_prime : `bool` + Boolean indicating if `number` is prime or not. + " in + let _ := + (* if *) + M.if_then_else (| + Compare.lt_e (| + M.get_name (| globals, "number" |), + Constant.int 1 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + Constant.bool false + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + let _ := + M.for_ (| + M.get_name (| globals, "x" |), + M.call (| + M.get_name (| globals, "range" |), + make_list [ + Constant.int 2; + BinOp.add (| + M.call (| + M.get_name (| globals, "int" |), + make_list [ + BinOp.pow (| + M.get_name (| globals, "number" |), + Constant.float "0.5" + |) + ], + make_dict [] + |), + Constant.int 1 + |) + ], + make_dict [] + |), + ltac:(M.monadic ( + let _ := + (* if *) + M.if_then_else (| + Compare.eq (| + BinOp.mod_ (| + M.get_name (| globals, "number" |), + M.get_name (| globals, "x" |) + |), + Constant.int 0 + |), + (* then *) + ltac:(M.monadic ( + let _ := M.return_ (| + Constant.bool false + |) in + M.pure Constant.None_ + (* else *) + )), ltac:(M.monadic ( + M.pure Constant.None_ + )) |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := M.return_ (| + Constant.bool true + |) in + M.pure Constant.None_)). + +Definition le_bytes_to_uint32_sequence : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "data" ] |) in + let _ := Constant.str " + Convert little endian byte stream `data` to a little endian U32 + sequence i.e., the first U32 number of the sequence is the least + significant U32 number. + + Parameters + ---------- + data : + The byte stream (little endian) which is to be converted to a U32 + stream. + + Returns + ------- + uint32_sequence : `Tuple[U32, ...]` + Sequence of U32 numbers obtained from the little endian byte + stream. + " in + let _ := M.assign_local (| + "sequence" , + make_list [] + |) in + let _ := + M.for_ (| + M.get_name (| globals, "i" |), + M.call (| + M.get_name (| globals, "range" |), + make_list [ + Constant.int 0; + M.call (| + M.get_name (| globals, "len" |), + make_list [ + M.get_name (| globals, "data" |) + ], + make_dict [] + |); + Constant.int 4 + ], + make_dict [] + |), + ltac:(M.monadic ( + let _ := M.call (| + M.get_field (| M.get_name (| globals, "sequence" |), "append" |), + make_list [ + M.call (| + M.get_field (| M.get_name (| globals, "U32" |), "from_le_bytes" |), + make_list [ + M.slice (| + M.get_name (| globals, "data" |), + M.get_name (| globals, "i" |), + BinOp.add (| + M.get_name (| globals, "i" |), + Constant.int 4 + |), + Constant.None_ + |) + ], + make_dict [] + |) + ], + make_dict [] + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := M.return_ (| + M.call (| + M.get_name (| globals, "tuple" |), + make_list [ + M.get_name (| globals, "sequence" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Definition le_uint32_sequence_to_bytes : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "sequence" ] |) in + let _ := Constant.str " + Obtain little endian byte stream from a little endian U32 sequence + i.e., the first U32 number of the sequence is the least significant + U32 number. + + Note - In this conversion, the most significant byte (byte at the end of + the little endian stream) may have leading zeroes. This function doesn't + take care of removing these leading zeroes as shown in below example. + + >>> le_uint32_sequence_to_bytes([U32(8)]) + b'\x08\x00\x00\x00' + + + Parameters + ---------- + sequence : + The U32 stream (little endian) which is to be converted to a + little endian byte stream. + + Returns + ------- + result : `bytes` + The byte stream obtained from the little endian U32 stream. + " in + let _ := M.assign_local (| + "result_bytes" , + Constant.bytes "" + |) in + let _ := + M.for_ (| + M.get_name (| globals, "item" |), + M.get_name (| globals, "sequence" |), + ltac:(M.monadic ( + let _ := M.assign_op_local (| + BinOp.add, + "result_bytes", + M.call (| + M.get_field (| M.get_name (| globals, "item" |), "to_le_bytes4" |), + make_list [], + make_dict [] + |) + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := M.return_ (| + M.get_name (| globals, "result_bytes" |) + |) in + M.pure Constant.None_)). + +Definition le_uint32_sequence_to_uint : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "sequence" ] |) in + let _ := Constant.str " + Obtain Uint from a U32 sequence assuming that this sequence is little + endian i.e., the first U32 number of the sequence is the least + significant U32 number. + + Parameters + ---------- + sequence : + The U32 stream (little endian) which is to be converted to a Uint. + + Returns + ------- + value : `Uint` + The Uint number obtained from the conversion of the little endian + U32 stream. + " in + let _ := M.assign_local (| + "sequence_as_bytes" , + M.call (| + M.get_name (| globals, "le_uint32_sequence_to_bytes" |), + make_list [ + M.get_name (| globals, "sequence" |) + ], + make_dict [] + |) + |) in + let _ := M.return_ (| + M.call (| + M.get_field (| M.get_name (| globals, "Uint" |), "from_le_bytes" |), + make_list [ + M.get_name (| globals, "sequence_as_bytes" |) + ], + make_dict [] + |) + |) in + M.pure Constant.None_)). + +Definition taylor_exponential : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ "factor"; "numerator"; "denominator" ] |) in + let _ := Constant.str " + Approximates factor * e ** (numerator / denominator) using + Taylor expansion. + + Parameters + ---------- + factor : + The factor. + numerator : + The numerator of the exponential. + denominator : + The denominator of the exponential. + + Returns + ------- + output : `ethereum.base_types.Uint` + The approximation of factor * e ** (numerator / denominator). + + " in + let _ := M.assign_local (| + "i" , + Constant.int 1 + |) in + let _ := M.assign_local (| + "output" , + Constant.int 0 + |) in + let _ := M.assign_local (| + "numerator_accumulated" , + BinOp.mult (| + M.get_name (| globals, "factor" |), + M.get_name (| globals, "denominator" |) + |) + |) in + let _ := + M.while (| + Compare.gt (| + M.get_name (| globals, "numerator_accumulated" |), + Constant.int 0 + |), + ltac:(M.monadic ( + let _ := M.assign_op_local (| + BinOp.add, + "output", + M.get_name (| globals, "numerator_accumulated" |) + |) in + let _ := M.assign_local (| + "numerator_accumulated" , + BinOp.floor_div (| + BinOp.mult (| + M.get_name (| globals, "numerator_accumulated" |), + M.get_name (| globals, "numerator" |) + |), + BinOp.mult (| + M.get_name (| globals, "denominator" |), + M.get_name (| globals, "i" |) + |) + |) + |) in + let _ := M.assign_op_local (| + BinOp.add, + "i", + Constant.int 1 + |) in + M.pure Constant.None_ + )), + ltac:(M.monadic ( + M.pure Constant.None_ + )) + |) in + let _ := M.return_ (| + BinOp.floor_div (| + M.get_name (| globals, "output" |), + M.get_name (| globals, "denominator" |) + |) + |) in + M.pure Constant.None_)). diff --git a/CoqOfPython/ethereum/utils/safe_arithmetic.v b/CoqOfPython/ethereum/utils/safe_arithmetic.v new file mode 100644 index 0000000..0702f0e --- /dev/null +++ b/CoqOfPython/ethereum/utils/safe_arithmetic.v @@ -0,0 +1,99 @@ +Require Import CoqOfPython.CoqOfPython. + +Definition globals : string := "ethereum.utils.safe_arithmetic". + +Definition expr_1 : Value.t := + Constant.str " +Safe Arithmetic for U256 Integer Type +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Safe arithmetic utility functions for U256 integer type. +". + +Axiom typing_imports_Optional : + IsImported globals "typing" "Optional". +Axiom typing_imports_Type : + IsImported globals "typing" "Type". +Axiom typing_imports_Union : + IsImported globals "typing" "Union". + +Axiom ethereum_base_types_imports_U256 : + IsImported globals "ethereum.base_types" "U256". +Axiom ethereum_base_types_imports_Uint : + IsImported globals "ethereum.base_types" "Uint". + +Definition u256_safe_add : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ ] |) in + let _ := Constant.str " + Adds together the given sequence of numbers. If the total sum of the + numbers exceeds `U256.MAX_VALUE` then an exception is raised. + If `exception_type` = None then the exception raised defaults to the one + raised by `U256` when `U256.value > U256.MAX_VALUE` + else `exception_type` is raised. + + Parameters + ---------- + numbers : + The sequence of numbers that need to be added together. + + exception_type: + The exception that needs to be raised if the sum of the `numbers` + exceeds `U256.MAX_VALUE`. + + Returns + ------- + result : `ethereum.base_types.U256` + The sum of the given sequence of numbers if the total is less than + `U256.MAX_VALUE` else an exception is raised. + If `exception_type` = None then the exception raised defaults to the + one raised by `U256` when `U256.value > U256.MAX_VALUE` + else `exception_type` is raised. + " in +(* At stmt: unsupported node type: Try *) + M.pure Constant.None_)). + +Definition u256_safe_multiply : Value.t -> Value.t -> M := + fun (args kwargs : Value.t) => ltac:(M.monadic ( + let _ := M.set_locals (| args, kwargs, [ ] |) in + let _ := Constant.str " + Multiplies together the given sequence of numbers. If the net product of + the numbers exceeds `U256.MAX_VALUE` then an exception is raised. + If `exception_type` = None then the exception raised defaults to the one + raised by `U256` when `U256.value > U256.MAX_VALUE` else + `exception_type` is raised. + + Parameters + ---------- + numbers : + The sequence of numbers that need to be multiplies together. + + exception_type: + The exception that needs to be raised if the sum of the `numbers` + exceeds `U256.MAX_VALUE`. + + Returns + ------- + result : `ethereum.base_types.U256` + The multiplication product of the given sequence of numbers if the + net product is less than `U256.MAX_VALUE` else an exception is raised. + If `exception_type` = None then the exception raised defaults to the + one raised by `U256` when `U256.value > U256.MAX_VALUE` + else `exception_type` is raised. + " in + let _ := M.assign_local (| + "result" , + M.get_subscript (| + M.get_name (| globals, "numbers" |), + Constant.int 0 + |) + |) in +(* At stmt: unsupported node type: Try *) + M.pure Constant.None_)). diff --git a/CoqOfPython/functools.v b/CoqOfPython/functools.v new file mode 100644 index 0000000..98750ac --- /dev/null +++ b/CoqOfPython/functools.v @@ -0,0 +1,3 @@ +Require Import CoqOfPython.CoqOfPython. + +Inductive globals : Set :=. diff --git a/CoqOfPython/typing_extensions.v b/CoqOfPython/typing_extensions.v new file mode 100644 index 0000000..98750ac --- /dev/null +++ b/CoqOfPython/typing_extensions.v @@ -0,0 +1,3 @@ +Require Import CoqOfPython.CoqOfPython. + +Inductive globals : Set :=. diff --git a/convert_all.py b/convert_all.py index 71b0041..5e85864 100644 --- a/convert_all.py +++ b/convert_all.py @@ -1,4 +1,6 @@ import os +import subprocess +import sys folder_to_convert = "../execution-specs/src/ethereum" @@ -8,7 +10,17 @@ if file.endswith(".py"): # convert the file full_path = root + "/" + file - # print("Converting file: " + full_path) short_path = full_path[(len(folder_to_convert) + 1):] + print("") print("Converting file: " + short_path) - os.system("python main.py " + short_path) + + try: + command = "python main.py " + folder_to_convert + " " + short_path + print(command) + subprocess.run(command, shell=True, check=True) + except subprocess.CalledProcessError as e: + print(f"Error occurred: {e}") + sys.exit(1) + except KeyboardInterrupt: + print("Ctrl-C pressed, interrupting the script.") + sys.exit(1) diff --git a/main.py b/main.py index 7cb21f3..332e894 100644 --- a/main.py +++ b/main.py @@ -1,4 +1,5 @@ import ast +import os import sys @@ -14,6 +15,9 @@ def generate_error(kind, node): print(message, file=sys.stderr) + if kind == "expr": + return f"Constant.str \"{message}\"" + return message @@ -54,14 +58,18 @@ def generate_constant(node, value): elif isinstance(value, int): return f"Constant.int {str(value)}" elif isinstance(value, float): - return f"Value.Float {str(value)}" + return f"Constant.float \"{str(value)}\"" elif isinstance(value, str): - return "Constant.str \"" + value.replace("\"", "\"\"\"") + "\"" + return "Constant.str \"" + value.replace("\"", "\"\"") + "\"" + elif isinstance(value, bytes): + return "Constant.bytes \"" + value.hex() + "\"" + elif value == ...: + return "Constant.ellipsis" else: - return generate_error("constant", node) + return generate_error(f"constant {type(value)}", node) -def generate_mod(node): +def generate_mod(node: ast.mod): if isinstance(node, ast.Module): return "\n\n".join(generate_top_level_stmt(stmt) for stmt in node.body) elif isinstance(node, ast.Interactive): @@ -74,16 +82,32 @@ def generate_mod(node): return generate_error("mod", node) -def generate_top_level_stmt(node): +def get_globals_of_import(node: ast.ImportFrom) -> str: + module = node.module.replace(".", "/") if node.module is not None else "" + + # If this is an absolute import + if node.level == 0: + return module.replace("/", ".") + + # If this is a relative path + actual_path = input_file_name + for _ in range(node.level): + actual_path = os.path.dirname(actual_path) + if module != "": + actual_path += "/" + module + + return actual_path.replace("/", ".") + + +def generate_top_level_stmt(node: ast.stmt): if isinstance(node, ast.FunctionDef): - return f"Definition {node.name} : Value.t -> Value.t -> M :=\n" + \ + return f"Definition {generate_name(node.name)} : Value.t -> Value.t -> M :=\n" + \ generate_indent(1) + generate_function_def_body(1, node) + "." elif isinstance(node, ast.AsyncFunctionDef): return generate_error("top_level_stmt", node) elif isinstance(node, ast.ClassDef): text = f"Definition {generate_name(node.name)} : Value.t :=\n" - text += generate_indent(1) + \ - "builtins.make_klass\n" + text += generate_indent(1) + "builtins.make_klass\n" # Bases text += generate_indent(2) + "[" @@ -149,17 +173,15 @@ def generate_top_level_stmt(node): elif isinstance(node, ast.Import): return generate_error("top_level_stmt", node) elif isinstance(node, ast.ImportFrom): - module = node.module if node.module is not None else "__init__" + module = get_globals_of_import(node) snake_module = module.replace(".", "_") - return f"Require {module}.\n" + \ - "\n".join( - f"Axiom {snake_module}_{generate_name(alias.name)} :\n" + - generate_indent(1) + - f"IsGlobalAlias globals {module}.globals " + - f"\"{generate_name(alias.name)}\"." - for alias in node.names - ) + return "\n".join( + f"Axiom {snake_module}_imports_{alias.name} :\n" + + generate_indent(1) + + f"IsImported globals \"{module}\" \"{alias.name}\"." + for alias in node.names + ) elif isinstance(node, ast.Global): return generate_error("top_level_stmt", node) elif isinstance(node, ast.Nonlocal): @@ -181,27 +203,38 @@ def generate_function_def_body(indent, node): body + "))" -def generate_if_then_else(indent, condition, success, error): +def generate_if_then_else( + indent, + condition: ast.expr, + success: ast.expr | list[ast.stmt], + error: ast.expr | list[ast.stmt], +): return generate_indent(indent) + "(* if *)\n" + \ generate_indent(indent) + "M.if_then_else (|\n" + \ generate_indent(indent + 1) + generate_expr(indent + 1, False, condition) + ",\n" + \ generate_indent(indent) + "(* then *)\n" + \ generate_indent(indent) + "ltac:(M.monadic (\n" + \ - generate_stmts(indent + 1, success) + "\n" + \ + (generate_expr(indent + 1, False, success) + if isinstance(success, ast.expr) + else generate_stmts(indent + 1, success)) + \ + "\n" + \ generate_indent(indent) + "(* else *)\n" + \ generate_indent(indent) + ")), ltac:(M.monadic (\n" + \ - generate_stmts(indent + 1, error) + "\n" + \ + (generate_expr(indent + 1, False, error) + if isinstance(error, ast.expr) + else generate_stmts(indent + 1, error)) + \ + "\n" + \ generate_indent(indent) + ")) |)" -def generate_stmts(indent, nodes): +def generate_stmts(indent, nodes: list[ast.stmt]): return "\n".join( [generate_stmt(indent, stmt) for stmt in nodes] + [generate_indent(indent) + "M.pure Constant.None_"] ) -def generate_stmt(indent, node): +def generate_stmt(indent, node: ast.stmt): if isinstance(node, ast.FunctionDef): return generate_error("stmt", node) elif isinstance(node, ast.AsyncFunctionDef): @@ -211,7 +244,10 @@ def generate_stmt(indent, node): elif isinstance(node, ast.Return): return generate_indent(indent) + "let _ := M.return_ (|\n" + \ generate_indent(indent + 1) + \ - generate_expr(indent + 1, False, node.value) + "\n" + \ + (generate_expr(indent + 1, False, node.value) + if node.value is not None + else "Constant.None_") + \ + "\n" + \ generate_indent(indent) + "|) in" elif isinstance(node, ast.Delete): return "\n".join( @@ -226,9 +262,12 @@ def generate_stmt(indent, node): target = node.targets[0] if isinstance(target, ast.Name): - return generate_indent(indent) + "let " + target.id + " :=\n" + \ + return generate_indent(indent) + "let _ := M.assign_local (|\n" + \ generate_indent(indent + 1) + \ - generate_expr(indent + 1, False, node.value) + " in" + "\"" + target.id + "\" ,\n" + \ + generate_indent(indent + 1) + \ + generate_expr(indent + 1, False, node.value) + "\n" + \ + generate_indent(indent) + "|) in" return generate_indent(indent) + "let _ := M.assign (|\n" + \ generate_indent(indent + 1) + \ @@ -240,11 +279,11 @@ def generate_stmt(indent, node): # return generate_error("stmt", node) elif isinstance(node, ast.AugAssign): if isinstance(node.target, ast.Name): - return generate_indent(indent) + "let " + node.target.id + " := " + \ - generate_operator(node.op) + "\n" + \ - generate_indent(indent + 1) + generate_expr(1, False, node.value) + "\n" + \ - generate_indent(indent + 1) + \ - generate_expr(1, False, node.value) + " in" + return generate_indent(indent) + "let _ := M.assign_op_local (|\n" + \ + generate_indent(indent + 1) + generate_operator(node.op) + ",\n" + \ + generate_indent(indent + 1) + "\"" + node.target.id + "\",\n" + \ + generate_indent(indent + 1) + generate_expr(1, False, node.value) + "\n" +\ + generate_indent(indent) + "|) in" return generate_indent(indent) + "let _ := M.assign_op (|\n" + \ generate_indent(indent + 1) + generate_operator(node.op) + ",\n" + \ @@ -254,16 +293,30 @@ def generate_stmt(indent, node): elif isinstance(node, ast.AnnAssign): return generate_error("stmt", node) elif isinstance(node, ast.For): - return generate_indent(indent) + "For " + generate_expr(1, False, node.target) + " in " + \ - generate_expr(1, False, node.iter) + " do\n" + \ - "\n".join(generate_stmt(indent + 1, stmt) for stmt in node.body) + "\n" + \ - generate_indent(indent) + "EndFor." + return generate_indent(indent) + "let _ :=\n" + \ + generate_indent(indent + 1) + "M.for_ (|\n" + \ + generate_indent(indent + 2) + generate_expr(2, False, node.target) + ",\n" + \ + generate_indent(indent + 2) + generate_expr(2, False, node.iter) + ",\n" + \ + generate_indent(indent + 2) + "ltac:(M.monadic (\n" + \ + generate_stmts(indent + 3, node.body) + "\n" + \ + generate_indent(indent + 2) + ")),\n" + \ + generate_indent(indent + 2) + "ltac:(M.monadic (\n" + \ + generate_stmts(indent + 3, node.orelse) + "\n" + \ + generate_indent(indent + 2) + "))\n" + \ + generate_indent(indent) + "|) in" elif isinstance(node, ast.AsyncFor): return generate_error("stmt", node) elif isinstance(node, ast.While): - return generate_indent(indent) + "While " + generate_expr(1, False, node.test) + " do\n" + \ - "\n".join(generate_stmt(indent + 1, stmt) for stmt in node.body) + "\n" + \ - generate_indent(indent) + "EndWhile." + return generate_indent(indent) + "let _ :=\n" + \ + generate_indent(indent + 1) + "M.while (|\n" + \ + generate_indent(indent + 2) + generate_expr(2, False, node.test) + ",\n" + \ + generate_indent(indent + 2) + "ltac:(M.monadic (\n" + \ + generate_stmts(indent + 3, node.body) + "\n" + \ + generate_indent(indent + 2) + ")),\n" + \ + generate_indent(indent + 2) + "ltac:(M.monadic (\n" + \ + generate_stmts(indent + 3, node.orelse) + "\n" + \ + generate_indent(indent + 2) + "))\n" + \ + generate_indent(indent) + "|) in" elif isinstance(node, ast.If): return generate_indent(indent) + "let _ :=\n" + \ generate_if_then_else(indent + 1, node.test, node.body, node.orelse) + \ @@ -276,7 +329,10 @@ def generate_stmt(indent, node): return generate_error("stmt", node) elif isinstance(node, ast.Raise): return generate_indent(indent) + "let _ := M.raise (| " + \ - generate_expr(indent, False, node.exc) + " |) in" + ("Some (" + generate_expr(indent, False, node.exc) + ")" + if node.exc is not None + else "None") + \ + " |) in" elif isinstance(node, ast.Try): return generate_error("stmt", node) # elif isinstance(node, ast.TryStar): @@ -312,11 +368,11 @@ def generate_bool_op(indent, is_with_paren, op, nodes): if len(nodes) == 0: return generate_error("expr", nodes) elif len(nodes) == 1: - return generate_expr(indent + 1, False, nodes[0]) + return generate_expr(indent, False, nodes[0]) return paren( is_with_paren, - generate_boolop(op) + " (|\n" + + op + " (|\n" + generate_indent(indent + 1) + generate_expr(indent + 1, False, nodes[0]) + ",\n" + generate_indent(indent + 1) + "ltac:(M.monadic (\n" + @@ -327,6 +383,38 @@ def generate_bool_op(indent, is_with_paren, op, nodes): ) +def generate_compare(indent, is_with_paren, op, left, right): + return paren( + is_with_paren, + generate_cmpop(op) + " (|\n" + + generate_indent(indent + 1) + + generate_expr(indent + 1, False, left) + ",\n" + + generate_indent(indent + 1) + + generate_expr(indent + 1, False, right) + "\n" + + generate_indent(indent) + "|)" + ) + + +def generate_compares(indent, is_with_paren, left, ops, comparators): + if len(ops) == 0: + raise ValueError("No comparison operators provided") + elif len(ops) == 1: + return generate_compare(indent, is_with_paren, ops[0], left, comparators[0]) + + return paren( + is_with_paren, + "BoolOp.and (|\n" + + generate_indent(indent + 1) + + generate_compare(indent + 1, is_with_paren, ops[0], left, comparators[0]) + ",\n" + + generate_indent(indent + 1) + "ltac:(M.monadic (\n" + + generate_indent(indent + 2) + + generate_compares(indent + 2, False, comparators[0], ops[1:], comparators[1:]) + + "\n" + + generate_indent(indent + 1) + "))\n" + + generate_indent(indent) + "|)" + ) + + def generate_single_list_or_node(indent, is_with_paren, nodes): if isinstance(nodes, list): return paren( @@ -381,9 +469,11 @@ def generate_list(indent, is_with_paren, nodes): ) -def generate_expr(indent, is_with_paren, node): +def generate_expr(indent, is_with_paren, node: ast.expr): if isinstance(node, ast.BoolOp): - return generate_bool_op(indent, is_with_paren, node.op, node.values) + return generate_bool_op( + indent, is_with_paren, generate_boolop(node.op), node.values + ) elif isinstance(node, ast.NamedExpr): return generate_error("expr", node) elif isinstance(node, ast.BinOp): @@ -406,25 +496,25 @@ def generate_expr(indent, is_with_paren, node): elif isinstance(node, ast.Lambda): return paren( is_with_paren, - f"fun {generate_expr(indent, False, node.args)} => {generate_expr(indent, False, node.body)}" + f"fun (args kwargs : Value.t) => {generate_expr(indent, False, node.body)}" ) elif isinstance(node, ast.IfExp): return paren( is_with_paren, - generate_if_then_else(0, node.test, node.body, node.orelse) + generate_if_then_else(indent, node.test, node.body, node.orelse) ) elif isinstance(node, ast.Dict): - return "{" + ", ".join(generate_expr(indent, False, key) + ": " + generate_expr(indent, False, value) for key, value in zip(node.keys, node.values)) + "}" + return generate_error("expr", node) elif isinstance(node, ast.Set): - return "{" + ", ".join(generate_expr(indent, False, elt) for elt in node.elts) + "}" + return generate_error("expr", node) elif isinstance(node, ast.ListComp): - return f"[{generate_expr(indent, False, node.elt)} for {generate_expr(indent, False, node.generators)}]" + return generate_error("expr", node) elif isinstance(node, ast.SetComp): - return f"{{{generate_expr(indent, False, node.elt)} for {generate_expr(indent, False, node.generators)}}}" + return generate_error("expr", node) elif isinstance(node, ast.DictComp): - return f"{{{generate_expr(indent, False, node.key)}: {generate_expr(indent, False, node.value)} for {generate_expr(indent, False, node.generators)}}}" + return generate_error("expr", node) elif isinstance(node, ast.GeneratorExp): - return f"({generate_expr(indent, False, node.elt)} for {generate_expr(indent, False, node.generators)})" + return generate_error("expr", node) elif isinstance(node, ast.Await): return paren( is_with_paren, @@ -433,7 +523,11 @@ def generate_expr(indent, is_with_paren, node): elif isinstance(node, ast.Yield): return paren( is_with_paren, - f"M.yield (| {generate_expr(indent, False, node.value)} |)" + "M.yield (| " + + (generate_expr(indent, False, node.value) + if node.value is not None + else "Constant.None_") + + " |)" ) elif isinstance(node, ast.YieldFrom): return paren( @@ -441,12 +535,8 @@ def generate_expr(indent, is_with_paren, node): f"M.yield_from (| {generate_expr(indent, False, node.value)} |)" ) elif isinstance(node, ast.Compare): - if len(node.ops) >= 2 or len(node.comparators) >= 2: - return generate_error("expr", node) - - return paren( - is_with_paren, - f"{generate_cmpop(node.ops[0])} (| {generate_expr(indent, False, node.left)}, {generate_expr(indent, False, node.comparators[0])} |)" + return generate_compares( + indent, is_with_paren, node.left, node.ops, node.comparators ) elif isinstance(node, ast.Call): return paren( @@ -474,9 +564,37 @@ def generate_expr(indent, is_with_paren, node): f"M.get_field (| {generate_expr(indent, False, node.value)}, \"{node.attr}\" |)" ) elif isinstance(node, ast.Subscript): + slice = node.slice + + if isinstance(slice, ast.Slice): + return paren( + is_with_paren, + "M.slice (|\n" + + generate_indent(indent + 1) + + generate_expr(indent + 1, False, node.value) + ",\n" + + generate_indent(indent + 1) + + (generate_expr(indent + 1, False, slice.lower) + if slice.lower is not None + else "Constant.None_") + ",\n" + + generate_indent(indent + 1) + + (generate_expr(indent + 1, False, slice.upper) + if slice.upper is not None + else "Constant.None_") + ",\n" + + generate_indent(indent + 1) + + (generate_expr(indent + 1, False, slice.step) + if slice.step is not None + else "Constant.None_") + "\n" + + generate_indent(indent) + "|)" + ) + return paren( is_with_paren, - f"M.get_subscript (| {generate_expr(indent, False, node.value)}, {generate_expr(indent, False, node.slice)} |)" + "M.get_subscript (|\n" + + generate_indent(indent + 1) + + generate_expr(indent + 1, False, node.value) + ",\n" + + generate_indent(indent + 1) + + generate_expr(indent + 1, False, slice) + "\n" + + generate_indent(indent) + "|)" ) elif isinstance(node, ast.Starred): # We should handle this kind of expression as part of the enclosing expression @@ -496,9 +614,19 @@ def generate_expr(indent, is_with_paren, node): " ]" ) elif isinstance(node, ast.Slice): + # This case is supposed to only appear as part of a Subscript node, so we + # do not handle it here. return paren( is_with_paren, - f"{generate_expr(indent, False, node.lower)}:{generate_expr(indent, False, node.upper)}" + "M.slice (| " + + (generate_expr(indent, False, node.lower) + if node.lower is not None + else "Constant.None_") + + ", " + + (generate_expr(indent, False, node.upper) + if node.upper is not None + else "Constant.None_") + + " |)" ) else: return generate_error("expr", node) @@ -575,7 +703,7 @@ def generate_cmpop(node): elif isinstance(node, ast.IsNot): return "Compare.is_not" elif isinstance(node, ast.In): - return "Compare.in" + return "Compare.in_" elif isinstance(node, ast.NotIn): return "Compare.not_in" else: @@ -586,21 +714,33 @@ def generate_arg(node): return generate_name(node.arg) -input_file_name = "../execution-specs/src/ethereum/" + sys.argv[1] -output_file_name = "CoqOfPython/ethereum/" + sys.argv[1].replace(".py", ".v") +input_file_name = sys.argv[1] +output_file_name = "../../translate-ethereum-specs/CoqOfPython/" + \ + input_file_name.replace(".py", ".v") file_content = open(input_file_name).read() parsed_tree = ast.parse(file_content) +globals = input_file_name.replace("/", ".").replace(".py", "") + # Generate Coq code from the AST coq_code = f"""Require Import CoqOfPython.CoqOfPython. -Inductive globals : Set :=. +Definition globals : string := "{globals}". {generate_mod(parsed_tree)} """ -# Output the generated Coq code +# Ensure that the directory exists +output_directory = os.path.dirname(output_file_name) +if not os.path.exists(output_directory): + os.makedirs(output_directory) + +# Output the generated Coq code only if the content changed +if os.path.exists(output_file_name): + with open(output_file_name, "r") as output_file: + if output_file.read() == coq_code: + sys.exit(0) with open(output_file_name, "w") as output_file: output_file.write(coq_code)