---
# System prepended metadata

title: New SMT-LIB Code Generation
tags: [design]

---

# New SMT-LIB Code Generation

How should the different types of identifiers look in the smt code we generate?

What would natural encodings be?

There are a million options.

We tried to have package data structures only once *per package* rather than *per instance*.
Similarly for games. In these cases, game / package type params need to be included.

```smt
(declare-const const-proof-{proofname}-{name} {type})
(declare-const const-game-{proofname}-{gameinstname}-{name} {type})
(assert (=
  const-proof-{proofname}-{name}
  const-game-{proofname}-{gameinstname}-{name}))
```

This works for consts, but not for state. We can just keep that in a state datatype, bind that to easy names at the start of a function, and then create and return a new state datatype value containing the values of our bound variables. We can even include the available constants in the initial binding:

```smt

; we have talked about this before:
; the package state should not be identified by the package instance,
; but just the package type and the package's type parameters.
; this way we can reuse them better.
; for now, let's ignore the type params in the implementation,
; but keep a notice there to remind us
(define-datatype
  PackageState-{packagename}-{type-params}
  (mk-PackageState-{pkgname}-{type-params}
    (PackageState-{pkgname}-{type-params}-T (Array Int Bits_n))))

; Similar with the game state.
; however, it of course references all the package states by package instance name.
(define-datatype
  GameState-{gamename}-{game-type-params}
  (mk-GameState-{gamename}-{game-type-params}
    (GameState-{gamename}-{game-type-params}-{pkginst} PackageState-{pkgname}-{pkg-type-params})
    (GameState-{gamename}-{game-type-params}-{mi-pkginst} (Array Integer PackageState-{pkgname}-{pkg-type-params}))))

; the const params of a package. can be shared between different package isntances that use the same type params.
(define-datatype
  PackageConstParams-{pkg-name}-{type-params}
  (mk-PackageConstParams-{pkgname}-{type-params}
    ((PackageConstParams-{pkgname}-{type-params}-n Int))))

; the same for games.
(define-datatype
  GameConstParams-{game-name}-{game-type-params}
  (mk-GameConstParams-{game-name}-{game-type-params}
    ((GameConstParams-{game-name}-{game-type-params}-n Int))))

; this maps the game's parameters to the parameters of a package instance in the game.
; basically it is the smt represenation of the params block in a package instantiation.
; this should also contain the type params of the game and the package in the function name, but i was too lazy to include it.
; the function can be called in 
(define-function game-pkg-const-param-mapping-{game-name}-{pkg-inst-name} (params GameConstParams-{game-name}) PackageConstParams-{pkg-name} 
  ...
)

; while this is pretty, it doesn't work for function parameters (at least as long as we
; try to be SMT-LIB 2.6-compatible). So what we do here instead is
; - for game-level function params, just declare free functions
; - for package-level function params, define functions that call the game's function
;   that is assigned to it in the package instantiation.

; the return type is basically like before
(define-datatype
  OracleReturn-{game-name}-{game-type-params}-{pkg-name}-{pkg-type-params}-{oracle-name}
  (ok-OracleReturn-{game-name}-{game-type-params}-{pkg-name}-{pkg-type-params}-{oracle-name}
     (OracleReturn-{game-name}-{game-type-params}-{pkg-name}-{pkg-type-params}-{oracle-name}-gamestate GameState-{game-name}-{game-type-params})
     (OracleReturn-{game-name}-{game-type-params}-{pkg-name}-{pkg-type-params}-{oracle-name}-return    {type})
  abort-OracleReturn-{game-name}-{game-type-params}-{pkg-name}-{pkg-type-params}-{oracle-name})


; the oracles need to be specific to the the package instance, because the called oracles
; depend on the wires the oracle is connected to.
; Whether it is specific to the game inst depends on how we handle const params.
; If const params are just a bunch of loose globals, we need to be specific because we
;   must know which of the loose global to use, and these are specific to the game instances.
; However, if we have a consts struct specific to the game, then we can pass that in and
;   extract the values from there. The proof can then pass different values in there
; We can then compute the package const params from the game const params, using the mapping function.
(define-fun
  oracle-{proofname}-{gameinstname}-{pkginstname}-{oracle-name}
  ((<state> GameState-{game-name}-{game-type-params}))
  ((<game-consts> GameConstParams-{game-name}-{game-type-params}))
  OracleReturn-{game-name}-{game-type-params}-{pkg-inst-name}-{pkg-type-params}-{oracle-name}
  (let* ( ; I am not sure if SMT-LIB has 'let*' --- the idea is that we can reference values bound within the let header
      (<pkg-consts> (game-pkg-const-param-mapping-{game-name}-{pkg-inst-name} <game-consts>))
      (T (PackageState-{pkgname}-{type-params} (GameState-{gameinstname}-T state)))
      (n (PackageConstParams-{pkgname}-{type-params}-n <pkg-consts>)))
    (...
      (let ((x ...))
        (...
          (ok-OracleReturn-{pkgname}-{typeconst}
            (mk-GameState-{gameinstname}
              (mk-PackageState-{pkgname}-{typeparams} T))
            x))))))



; This explores multi instance indices. This code hasn't been ported to use the game const params struct, it still uses the globals.
; Hence, it is still specific to the game instance.
(define-fun
  mi-oracle-{proofname}-{game-inst-name}-{mi-pkg-inst-name}-{oracle-name}
  (
    (<state> GameState-{game-inst-name})
    (<mi-idx> Integer))
  OracleReturn-{game-inst-name}-{mi-pkg-inst-name}-{oracle-name}
  (let (
      (T (PackageState-{pkg-name}-{type-params}-T (select (GameState-{game-inst-name}-{mi-pkg-inst-name} <state>))) <mi-idx>)
      (n game-{proof-name}-{game-inst-name}-const-n))
    (...
      (let ((x ...))
        (...
          (ok-OracleReturn-{pkgname}-{typeconst}
            (mk-GameState-{gameinstname}
              (store GameState-{game-inst-name}-{mi-pkg-inst-name} <mi-idx> (mk-PackageState-{pkg-name}-{type-params} T)))
            x))))))
```

Where we use `<name>` for system variables, so they can't collide with user variables

## Action Items

- [ ] Implement generating Package Const instantiation functions
- [ ] Bind Package Consts at oracle start
- [ ] Use plain variable names for consts in oracle code
- [ ] Implement proof -> game inst const instantiation code