Code Monkey home page Code Monkey logo

sigmastate-interpreter's Introduction

CI codecov

ErgoScript compiler and ErgoTree interpreter

This repository contains implementations of ErgoScript compiler and ErgoTree Interpreter for a family of Sigma-protocol based authentication languages (or simply Sigma language).

This library is used internally in Ergo Node and ergo-wallet, the public interfaces are subject to change.

For development of Ergo applications using JVM languages (Java/Scala/Kotlin/etc) a better alternative is to use Appkit.

The library is cross-compiled to JS using Scala.js and the main abstractions can be used from JS directly by importing NPM module. See README for details.

Sigma Language Background

Every coin in Bitcoin is protected by a program in the stack-based Script language. An interpreter for the language is evaluating the program against a context (few variables containing information about a spending transaction and the blockchain), producing a single boolean value as a result. While Bitcoin Script allows for some contracts to be programmed, its abilities are limited. Also, to add new cryptographic primitives, for example, ring signatures, a hard-fork is required.

Generalizing the Bitcoin Script, ErgoScript compiler and ErgoTree interpreter implement an authentication language which allows to express coin spending conditions. The ErgoScript Compiler compiles the source code into ErgoTree byte code, which can be saved in UTXO coins to protect their spending (same as in Bitcoin).

ErgoTree, in turn, is a bytecode language and memory representation which can be deterministically interpreted in the given blockchain context. ErgoTree defines guarding proposition for a coin as a logic formula which combines predicates over a context and cryptographic statements provable via Σ-protocols with AND, OR, k-out-of-n connectives.

An interacting party willing to spend the coin first constructs a prover with a set of secrets it knows and then the prover is executed in two steps:

  • Reduction - the prover uses the ErgoTree interpreter and deterministically reduces the ErgoTree proposition to a compound cryptographic statement(aka sigma proposition, Σ-protocol) by evaluating ErgoTree over known shared context (state of the blockchain system and a spending transaction). This step produces a value of the SigmaBoolean type.

  • Signing - the prover is turning the obtained (and possibly complex) Σ-proposition into a signature with the help of a Fiat-Shamir transformation. This step produces a proof that the party knows the secrets such that the knowledge can be verified before the spending transaction is added to the blockchain.

To allow valid coin spending a verifier is running the ErgoTree interpreter with the following three inputs:

  • a guarding proposition given by an ErgoTree
  • a blockchain context of the transaction being verified
  • a proof (aka transaction signature) generated by a prover

The verifier is executed as part of transaction validation for each input and is executed in tree steps:

  • Reduction - same as prover, the verifier uses the ErgoTree interpreter and deterministically produces a value of the SigmaBoolean type. However, this step must finish evaluation for any possible inputs within concrete fixed time limit (aka maximum cost), which is checked by the interpreter.

  • Cost estimation - the verifier estimates the complexity of cryptographic Sigma proposition (based in the size and the concrete nodes of SigmaBoolean tree). The spending fails if the estimated cost exceeds the maximum limit.

  • Signature verification - the signature checker takes 1) the proof, 2) the SigmaBoolean (aka sigma protocol proposition) and 3) the signed message (e.g. transaction bytes). The checker than verifies the proof, which means it verifies that all the necessary secrets has been known and used to construct the proof (i.e. sign the transaction).

Getting Started

This library is publishied on Maven repository and can be added to the SBT configuration of Scala project.

libraryDependencies += "org.scorexfoundation" %% "sigma-state" % "5.0.14"

Repository Organization

sub-module description
core contains core classes of Sigma library
data contains classes for working with ErgoTree, addresses and all related serializers
docs Collection of documents
interpreter contains an implementation of ErgoTree Interpreter
sdk contains and implementation of transaction reduction and signing
parsers contains an implementation of ErgoScript parsers using FastParse library
sc contains an implementation of ErgoScript compiler
sigma-js root directory of sigmastate-js JS module (see package.json)

Contributing

We welcome contributions to this project! If you are interested in contributing, here are a few ways to get started:

Report bugs: If you have found a bug please open an issue on the issue tracker.

Fix bugs or implement features: If you would like to fix a bug or implement a new feature, please fork the repository and open a pull request with your changes. Please make sure to include a clear description of the changes you have made and why you think they should be included in the project.

Improve documentation: If you notice that the documentation could be improved, please feel free to make changes and open a pull request.

Review pull requests: If you would like to help review pull requests, please take a look at the open pull requests and leave comments on any that you would like to review.

Before you start working on a contribution, please make sure to read the contributing guidelines. These documents outline the expectations for contributions to this project.

Thank you for your interest in contributing to this project! Your help is always appreciated!

Please submit a pull request or create an issue to add a new cryptographic primitives or better implementations.

Acknowledgments

We thank JetBrains for supporting this project since 2021 by providing All Products Pack subscription.

We thank YourKit for support of open source projects with its full-featured Java Profiler. YourKit, LLC is the creator of YourKit Java Profiler and YourKit .NET Profiler, innovative and intelligent tools for profiling Java and .NET applications.

References

sigmastate-interpreter's People

Contributors

andyceo avatar arobsn avatar aslesarenko avatar catena2w avatar darkdrag00nv2 avatar dmdv avatar ergomorphic avatar flysky9981 avatar gagarin55 avatar greenhat avatar jozanek avatar kii-dot avatar knizhnik avatar kushti avatar megatron00999 avatar mike-aksarin avatar mrstahlfelge avatar oskin1 avatar pragmaxim avatar reyzin avatar robkorn avatar ross-weir avatar scalahub avatar sethdusek avatar terjokhin avatar thub1271 avatar tolsi avatar victormikheev avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar

sigmastate-interpreter's Issues

Consider limitations of a deserialized script

A deserialized script probably could not contain following nodes:

Inputs
Outputs
Self
Height
LastBlockUtxoRootHash
TaggedVariable[_]

as this nodes are to be rewritten in the same bottom-up rewrite, which is to be executed once.

Is this limitation serious? Should we do something with it, or just document it?

Rework Cost Calculation

  1. Check that cost() everywhere includes costs of node's children
  2. Add some argument to cost to define cost of involved parts of the box and context, in TaggedVariable[] and Extract[] families

Format code

Now it is formatted incorrectly in a lot of places. Better to do it at some point, with no PR to avoid merging

Colored coins

Think about colored coins example and implement.
Some ideas:

  • Use special output and AVL tree with coin state
  • Use special data type to define a coin color. Ergo may not be a special case.
  • Predefine all possible coins in genesis block, allow anyone to take them with increasing fee

Make proposition of ergo box immutable

Right now proposition ins't fully immutable, cause some leaf could substitute by their final value, it means this OR(EQ(IntConstant(1),IntConstant(1), EQ(IntConstant(1),IntConstant(2))) will appear as OR(TrueLeaf,FalseLeaf)

Potential problem with type casts in ProverInterpreter

In the following line of ProverInterpreter.prove

val step4 = simulations(step3).get.asInstanceOf[UnprovenTree]

when simulations is executing the following case:

case su: UnprovenSchnorr =>
     if (su.simulated) {
       assert(su.challengeOpt.isDefined)
       SchnorrSigner(su.proposition, None).prove(su.challengeOpt.get)
     } else {
       val (r, commitment) = DLogInteractiveProver.firstMessage(su.proposition)
       su.copy(commitmentOpt = Some(commitment), randomnessOpt = Some(r))
     }

if su.simulated == true, prove will return UncheckedTree, and there will be type cast error

Oracle example

Make a test which is a show-case of an oracle usage scenario

Implement execution of serialized scripts

We may want to parameterise ErgoScript with another script, given as serialised Array[Byte].
However we cannot allow user to manipulate script bytes, so we cannot just provide generic execute[T](bytes) function because it will be impossible to implement cost function in general case.
Actual script representation should be hidden from the user.
However we can assume that some Context variables and Box registers may be executed as scripts, which may look like this

let x = execute[Int](24)  // execute context variable 24 as script returning Int
let y = box.executeRegister[Boolean](5)

The location of script bytes is different in these cases, but the execution procedure in similar.
Execution is performed before cost estimation and have the following steps:

  1. Deserialize bytes to Value[T] for some T, which become known after deserialization
  2. Check that T is equal to parameter type (Int or Boolean in the examples above)
  3. Insert deserialized tree instead of function invocation

Subtasks:

  • add class ExecuteContextScript
  • implement execute as global function
  • add class ExecuteRegisterScript
  • implement executeRegister as method of Box

forward references

There are quite a lot of forward references, found by code inspection. Looks like there are even cyclic references, e.g. sigmastate.lang.Type and sigmastate.lang.TypeBounds

Remove SCAPI dependency

As SCAPI is no longer supported, and the dependency carried in the form of binaries located in the "lib/" folder is pretty problematic, there is a need to remove the dependency.

Ensure that 2^t < q

To get ORs and thresholds (what SCAPI calls ORMultiple) to work securely, we must make sure the space of possible challenges fits within modulo q. The current implementation does not do that and IS INSECURE AGAINST MALICIOUS PROVERS FOR THE CASE OF MULTIPLE ORS.

ByIndex problems

  • index should not be Scala Int. Value[SInt.type] expected
  • default value may me useful

relates to #87, #88, #98

Extract collection from register

I can't find an example of collection extraction from a register, and expected way to do this like ExtractRegisterAs[SCollection[Boolean]](Self, R4)(SCollection[Boolean]) does not work

Elliptic curve

  • Choose concrete curve
  • Check DDH
  • Points serialization
  • Insecure Fiat-shamir

Generalize ContextVariables

This is required for #98, #88.
Currently we have family of classes TaggedInt, TaggedBox, etc to access context variables.
This is problematic for extensions, in particular for implementation of #98.

We need to do the following changes:

  • rename TaggedVariable -> ContextVariable
  • instead of all TaggedXXX classes implement one class
  case class TaggedVariable[T <: SType](override val id: Byte, override val tpe: T) 
    extends ContextVariable[T]
       with NotReadyValue[T]
  • instead of functions like taggedInt(23) we need one generic function getVariable[Int](23), which will access tagged parameter in the context and check its type. In particular taggedByteArray(23) can be replaced with getVariable[Array[Byte]](23)

Hash

  • Check sha1 collision
  • Check how secure blake2b is with 192 (?) bits

Update BouncyCastle dependency version

Currently SCAPI is using old version 1.46 of the BouncyCastle. Newer versions are causing an exception. Update for the BouncyCastle version is needed after removing the SCAPI dependency ( #13 ).

SByteArray is not a collection

Now it's not possible to work with SByteArray as with collection, e.g. this code does not compile:

EQ(SizeOf(ExtractRegisterAs[SByteArray.type](Self, R4)), bitsInString)

Relates to #71

More collections examples

We need more examples of collection usages in CollectionOperationsSpecification

  • Examples with custom collections
  • Examples with Slice, Append, Where, etc.

relates to #87, #88, #98, #99

Remove Not

Not conjecture is really problematic, as you can use it with sigma-statements, e.g. Not/If example could be rewritten in the following way:

EQ(ByteArrayConstant(hash),
CalcBlake2b256(
If(Not(pubkey),
ExtractRegisterAs[SByteArray.type](ByIndex(Inputs, 1), R3),
ExtractRegisterAs[SByteArray.type](ByIndex(Inputs, 2), R3))))

which does not make sense and causing interpreter to crash

specificTransformations called more than once

@ergomorphic :

By design, a verifier is making one non-circular phase named "specificTransformations" and then estimating cost of the script. All rewrites after the phase should not increase the tree.

Based on that, invocation of specificTransformations in following code in Interpreter is problematic:

val rules: Strategy = strategy[Value[_ <: SType]] { case node =>
  var rewritten = evaluateNode(context, node)
  if (rewritten == null) {
    rewritten = specificTransformations(context, node)
  }
  if (rewritten != null) {
    wasRewritten = true
    Some(rewritten)
  }
  else
    None
}

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.