Git Product home page Git Product logo

cannon's People

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  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  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

cannon's Issues

Resurrect valid geth tests

Minigeth removes all tests from upstream geth.

However, these could be quite useful in bolstering our confidence in the system.

An easy win would be to run a script over all tests in geth (in particular, in l2-geth-head), and reimport those tests that pass without modification.

Later, we can choose to put int the work to resurrect other tests as needed / convenient.

Test block 13284053 is failing

This is due to missing a Trie node when we do a delete. From trie/trie.go

				// If the remaining entry is a short node, it replaces
				// n and its key gets the missing nibble tacked to the
				// front. This avoids creating an invalid
				// shortNode{..., shortNode{...}}.  Since the entry
				// might not be loaded yet, resolve it just for this
				// check.

Now since the trie is a "SecureTrie" which hashes the key, we can't easily request the missing storage node, since we don't know the preimage of the key.

This issue can be fixed with a new API in upstream geth to fetch the trie node, but I'd really like to be able to do it with eth_getProof. Best idea I've had so far is brute forcing the SecureTrie. Any better ideas? We have the future.

Todo: Run Linux VM instead of EVM

I'm (only) half joking, when I ask: how hard would it be to run an optimistic Linux on the virtual MIPS processor validated by on-chain interactive fraud proofs?

Lib_Keccak256.sol doesn't work

kafka@largee:~/build/cannon$ npx hardhat test

  MIPSMemory contract
deployed at 0x5FbDB2315678afecb367f032d93F642f64180aa3 by 0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266
preimage initted
preimage updated
comp hash is 0x4a3d5976edd24a1a22f7fae2985b3bd41798eb1176802b50e5612f3e739d3c97
real hash is 0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470

    1) Keccak should work

Not returning the correct empty hash. Easy to reproduce, who wants to fix it? 🥇

It's ported from https://github.com/firefly/wallet/blob/master/source/libs/ethers/src/keccak256.c, I would go about debugging this by diffing the two implementations and disabling rounds/transforms until you find the one that doesn't match.

Block 13284494 fails, wrong transition

kafka@largee:~/build/cannon$ ./run.sh 13284494
commited transactions 0xf25acd2e5000017b76529e3e73d59ce3e4f63903462ad989ff2d673fba27c420 <nil>
processing state: 13284494 -> 13284495
read 105 transactions
made block, parent: 0xdadf0d0316d11c06fb9261e03671f2d785d82125cbbe501d5a23c6bb0081e217
.........................................................................................................consensus finalize
new Root 0xd476aaff23fd5887c5aed68924d6133ad32a09dfdee8ffb8b60de5881fa9545b
process done with hash 0x24af08febef9f49b40f35169b4612f11ac7ea6ececc03098010a44ff8d1dcab0 -> 0xd476aaff23fd5887c5aed68924d6133ad32a09dfdee8ffb8b60de5881fa9545b
0xd476aaff23fd5887c5aed68924d6133ad32a09dfdee8ffb8b60de5881fa9545b != 0x00000000000000000000000000000000000000000000000000000000614cf617
panic: BAD transition :((

Block 13284493 fails, missing preimage

kafka@largee:~/build/cannon$ ./run.sh 13284493
commited transactions 0x9f84940fa9c98c4c41f7956640e08ca6ecfc728ae7b807a49debab2d46f17e01 <nil>
processing state: 13284493 -> 13284494
read 229 transactions
made block, parent: 0x9cdfab0f52c329507439d2452d31dc2b0de879eba491f11a3dd61cfa4b4b6df9
...................................................................................................................................................................................................................
..................consensus finalize
can't find preimage 0x16197e2a0eacc44c1ebdfddcfcfcafb3538de557c759a66e0ba95263b23d9007
panic: corruption in hash 0x16197e2a0eacc44c1ebdfddcfcfcafb3538de557c759a66e0ba95263b23d9007

Block 13284499 fails

kafka@largee:~/build/cannon$ ./run.sh 13284499
commited transactions 0x9f61dbb6689a972edbc9bbccf9e43942a7043906bd7591be88e0fdc01e198d24 <nil>
processing state: 13284499 -> 13284500
read 253 transactions
made block, parent: 0x7a444f4f7f7a72d95226defd75e52115515892bfb76fcf443e7f48e259e7aa79
.............................................................................................................................................................................................................................................................consensus finalize
new Root 0xd810b54e3fa86717ce9aaa954f3a9b5e5b2d2d5098cf401455c74f4dad10e19a
process done with hash 0x493b20c4171c2d50ba1b2fe6f8b8aa9750d54d9ee1ee81f3737b7223f5ae1e38 -> 0xd810b54e3fa86717ce9aaa954f3a9b5e5b2d2d5098cf401455c74f4dad10e19a
0xd810b54e3fa86717ce9aaa954f3a9b5e5b2d2d5098cf401455c74f4dad10e19a != 0x5066fa5532b4ece51f5f2e6a8d66f8fea499abdfd4570c789c696f736c84fc71
panic: BAD transition :((

goroutine 1 [running]:
github.com/ethereum/go-ethereum/oracle.Output({0xd8, 0x10, 0xb5, 0x4e, 0x3f, 0xa8, 0x67, 0x17, 0xce, 0x9a, ...})
        /Users/kafka/build/cannon/minigeth/oracle/prefetch.go:201 +0x17b
main.main()
        /Users/kafka/build/cannon/minigeth/main.go:123 +0x11ab

State Oracle must have a way to obey rules of L1 Gaslimit

From README:

Preimage(hash) -> value # hash(value) == hash

In the naive case, it is easy to verify this on-chain using the SHA3 opcode. However, if the size of value is sufficiently large it becomes harder.

SHA3 uses a 1600-bit intermediate state which is fed constant-sized pieces of the input one single step at a time. However, it is not possible to verify that an individual piece of the preimage is correct up front, for the same reason. This is problematic because of the risk of an attacker inserting malicious pieces--you can't trustlessly bisect down to a single step as an honest user, since the divergent step might be a valid application of the SHA algorithm, just with invalid inputs, and this doesn't give L1 enough information to discern which party is wrong.

I tried to consider whether using a merkle tree of the data with fixed sized leaves is useful but I couldn't think of anything; it actually feels equivalent to steps where each step is a single-piece input to the SHA. Bounding the size of value is an obvious solution but not ideal.

Block 13284471 fails

kafka@largee:~/build/cannon$ ./run.sh 13284471
commited transactions 0xe4706629337549d4195c9c6eeeb3d75b08518c56b1a1bc6a722ce39b18bcc0fb <nil>
processing state: 13284471 -> 13284472
read 39 transactions
made block, parent: 0x9d338064eacdf196474a8760630babaf7953d76896779f7269ae4f7f7f09ba18
.......................................consensus finalize
new Root 0xed325951f9e187a1fc83633f510c6347ddcd66ea0d6545f256439e338031ae0d
receipt count 39 hash 0x06e0a4a084be8f74aa37c34120e3c4d5908dbc8770f14252ae365d71cfe610a1
process done with hash 0xc39c5ef72a57365f826793e71bd080d929a9317663fd878f3cfcee86775164b7 -> 0xed325951f9e187a1fc83633f510c6347ddcd66ea0d6545f256439e338031ae0d
0xed325951f9e187a1fc83633f510c6347ddcd66ea0d6545f256439e338031ae0d != 0xe5cdd94c3ea6936920331c5a21ebaba85c446f21e67e6e56fce286caf37bc3d9
0x06e0a4a084be8f74aa37c34120e3c4d5908dbc8770f14252ae365d71cfe610a1 != 0xd47004eef427c0b9a19fc0f32027fc3666d731935d1fe1e8a630c7ec7b2af495
panic: BAD transition :((

goroutine 1 [running]:
github.com/ethereum/go-ethereum/oracle.Output({0xed, 0x32, 0x59, 0x51, 0xf9, 0xe1, 0x87, 0xa1, 0xfc, 0x83, ...}, ...)
        /Users/kafka/build/cannon/minigeth/oracle/prefetch.go:202 +0x29f
main.main()
        /Users/kafka/build/cannon/minigeth/main.go:126 +0x136d

Epic: Improve Documentation

  • document syscalls
    • in mipsevm/run_unicorn.go
    • in contract/MIPS.sol
    • document the alternative: stub out the syscalls in compile.py
    • add links to syscall references
  • misc notes
    • mipigo/compile.py: document the fact that it's not easy to fully disable the GC with an env variable, because the thread is still created in case GC gets programatically re-enabled
    • document the sanity checking in mipsevm/main.go, cf. my comments here
      • for register fault, the number is the step number where the register will be modified

Make Solidity MIPS faster!

It's running 5M+ instructions without issue now, but it's a bit too slow to use in practice. I really don't want to maintain two implementations.

Profile and optimize, the dream is to run small blocks in 1 minute and large blocks in 10.

We can of course fast forward to the input oracle read, but that's meh.

Find failing blocks!

./test.sh <pick a post London block number>

Will exit if a transition fails. Looking good so far!

Tested 13284475-13284575

Use upstream Unicorn

Currently, this repo uses a fork of Unicorn made by @geohot https://github.com/geohot/unicorn.git

George said he made a few fixes to it, which do have to upstream and/or merged upstream before we can switch over, so we should track, push for the fixes to be merged and switch when we can.

Quick search releaved the following issue: unicorn-engine/unicorn#1470 but that seem to be fixed, but there seems to be more than that here: https://github.com/geohot/unicorn/commits/master

@geohot Could you comment as to what we need?

Epic: Overhaul Challenge Game

The game challenge game is a scaffold that was meant to facilitate the Cannon bug bounty. It is not secure as-is, as it assumes an honest defender, doesn't handle bonding (and probably has more issues).

This repository should inform the final design.

Implement the challenger & defender agents

  • The challenger agent is started by a verifier when he computes different output roots than the one the sequencer posted to L1. It is reponsible for playing the challenge game and proving that the output root is faulty.
  • The defender agent is run by the sequencer and monitors the L1 chain for new challenges, and plays the challenge game to deny the assertion that the output root is faulty.

See implementation sketch and additional comments below.

Remove the honest defender assumption

The current challenge game assumes that the defender acts honestly.

Things that are needed, at minimum, we need to introduce a challenge period after which the last player to answer in the binary search wins by default if the binary search.

I would also like to take care of the issue that arises when the challenger and the defender disagree on the last step of the challenge game. In this case, the defender won't have supplied a state hash for the post state of that transition, and thus it can not prove the challenger wrong (but wins by default if the challenger doesn't prove he's right). I'd like to at least get ride of the ChallengerLosesByDefault event (as the previous paragraph implies a robust system for determining who loses by default if the challenge period expires without a clear winner). It might also make sense to allow the defender to provide the post state when proving the last step (in which case we must explicitly verify that the assert post-state is different than the one asserted by the challenger).

Upgrade JS dependencies

Dependabot is flagging a bunch of security issues with some indirect dependencies, it's probably time to update them.

Fix up Merkle trie library

Is there a library that, instead of needing each proof as a string, uses something similar to the preimage oracle?

It should also be able to write to the oracle/hashmap to allow full running of MIPS on chain with trie state.

Add a time delay to the challenge payment

This has to do with enabling manual intervention in case of a software bug.

If an incorrect, but unchallengeable output root is posted, governance will have 7 days to act and update the system.

However, if a correct but challengeable output root is posted, the current (unimplemented) design implies that a challenger will be able to claim the proposer bond, even though the proposer was honest and it's the system that was buggy. To avoid this, we would add a time delay (probably 7 days too) so that governance can take appropriate action.

isNil()

you seem to be able to get rid of the

if err != nil {
  panic("processor error")
}

by doing a function like this according to : check nil interface

func isNil(i interface{}) {
  if i != nil {
     panic("processor error")
  }
}

then just call it like :
isNil(err)
But i dont know how to make it so you can access that function everywhere 🤣 so if this is right it should be a simple pull request for someone :)

Add the demo scripts to the CI

My PR broke the demo scripts multiple times, it would be good to ensure that the CI verifies that they still run as expected.

Fix timeout in fault injection challenge scenario

The example fault injection scenario times out on my machine, on the very last step (the defender assertion).
This might be a hardhat issue, but it would be good to figure it out.

cf. #52 (comment)

Once that is done, we might want to add these scenarios to the CI.

Many MIPS tests failing

kafka@largee:~/build/cannon/mipsevm$ ./evm.sh
Nothing to compile
hello
<nil> 916142 512.61µs 1 1 dead0000 test/bin/add.bin
<nil> 916813 484.401µs 1 1 dead0000 test/bin/addi.bin
<nil> 916715 468.807µs 1 1 dead0000 test/bin/addiu.bin
<nil> 916125 481.487µs 1 1 dead0000 test/bin/addu.bin
<nil> 905925 545.431µs 1 1 dead0000 test/bin/and.bin
<nil> 918999 457.992µs 1 1 dead0000 test/bin/andi.bin
<nil> 907735 532.294µs 1 1 dead0000 test/bin/bds_mtc0.bin
<nil> 910593 535.372µs 1 0 dead0000 test/bin/beq.bin
...

Should all be "1 1 dead0000", notice how beq.bin is failing

Help fix them!

Clarify geth diff

Goal: have a more precise understanding of what's changed compared to mainline geth (at first, only compared to the reference commit (geth v1.10.8 release).

Setup

(You don't necessarily need to understand this, but it helps me keep things straight.)

Currently, unmodified geth files are listed in files_minigeth and synced via sync-minigeth.sh. This leaves a few added and modified files.

The new branch ns/clarify-geth-diff adds a few scripts + result files to figure this out:

  • sync_minigeth2.sh
    • emits a list of added or modified (but not removed) files compared to the original commit
    • ... which it writes to minigeth2_modified_added_files
    • ... which it concatenates this with files_minigeth into files_minigeth_inc_modified_added
  • sync_minigeth3.sh
    • takes files_minigeth_inc_modified_added as input
    • emits the list of changed (only) files to minigeth3_modified_files
    • emits the list of added (only) files to minigeth3_added_files
    • emits a git diff (not sure if a valid patch, it's a concat of individual git diff outputs) to minigeth3_diff_modified

Added Files

Modified Files

If necessary we could also manufacture a commit showcasing this diff.

About the design of Cannon

One promise of L2 rollup is that one can recover L2 state purely from L1, if you only submit header to L1, it will break this promise IMO.

Mipigo build fails with Unicorn API version error

Describe the bug

While following the README instructions per #39 to build unicorn2 and add it to the path, then running (cd mipigo && pip3 install -r requirements.txt && ./build.sh), the build script fails in compile.py with:

minigeth: ELF 32-bit MSB executable, MIPS, MIPS32 version 1 (SYSV), statically linked, Go BuildID=bDYCrfVpTyMfiuLGtgZF/2QGo5f3BgyUSXs3lAsHt/1mOX1QQLpy7Zu7LDoXo9/8OegC7znh-c8tNFpPm6U, not stripped
Trying to load shared library /Users/maurelian/Projects/O/cannon/unicorn2/libunicorn.dylib
SUCCESS
Traceback (most recent call last):
  File "/Users/maurelian/Projects/O/cannon/mipigo/./compile.py", line 74, in <module>
    mu = Uc(UC_ARCH_MIPS, UC_MODE_32 + UC_MODE_BIG_ENDIAN)
  File "/Users/maurelian/Projects/O/cannon/venv/lib/python3.9/site-packages/unicorn/unicorn.py", line 312, in __init__
    raise UcError(uc.UC_ERR_VERSION)
unicorn.unicorn.UcError: Different API version between core & binding (UC_ERR_VERSION)

By adding some print statements to unicorn.py, it appears that the python package is expecting a v1 engine, but the core unicorn lib is v2.

Cannon cannon cannon

Cannon cannon cannon cannon cannon cannon cannon cannon cannon cannon cannon cannon cannon cannon cannon cannon cannon cannon cannon cannon cannon cannon cannon cannon?

Cannon cannon cannon cannon cannon cannon cannon cannon:

Cannon: cannon cannon cannon cannon
Cannon: cannon
Cannon: cannon cannon cannon cannon cannon cannon cannon cannon

Cannon cannon cannon cannon cannon cannon cannon cannon cannon cannon cannon cannon cannon cannon cannon cannon cannon cannon cannon cannon cannon cannon cannon cannon cannon cannon cannon cannon cannon cannon.

File io must be slow

There is a literal ton of files being written to the cache, even if you have a SSD, this has to be one of the slower parts of the operations being done (took quite some time to remove 50GB of tiny tiny files even with rm -rf /tmp/eth) 😄
Even though its done in the Preimageand PrefetchBlock, i still guess it counts to the overall time "handling" a block.
Right?

I guess storing it directly in memory, and forgetting it when done has its own set of problems, like using a ton of memory and problematic to find each blocks data, and it wouldnt serve as a cache either...

and just having one file for /tmp/eth/0xblock and /tmp/eth/json_block which you open once, then read/write to as long as the test.sh is running ...yeah that causes problems aswell.

just thinking out "loud".
please close if gibberish :)

Replace Merkle Trie with simpler Hash Trie

Currently, the MIPS memory is merkleized by mipsevm (this is termed a checkpoint), and required nodes are uploaded to the MIPSMemory.sol contract (via the AddTrieNode function). MIPS execution on the EVM then reads from the trie whenever it needs to access MIPS memory.

The Merkle Patricia Trie logic that we use matches that used in Ethereum itself. It's very complex and brittle (e.g. it uses RLP encoding and various space-saving tricks). There is no reason to use this format for the MIPS memory (besides that it's already implemented in Go by geth).

The suggested replacement is a simple 16-branch hash trie. Each node is the hash of the concatenation of all of its children (or 0x0 if there is not children at a given slot). Leaves are 4 bytes MIPS words (left-padded with 28 0 bytes for hashing purposes in non-leave nodes).

Note that when merkleizing the memory, we only store memory locations that have been actually written. The rest is implicitly zero.

However, this is probably too inefficient. In particular preimages of normal nodes are 16*32 = 512 bytes, and every address read needs to traverse 8 nodes to get to the leaf depth. We probably want to reintroduce some compression techniques, but we want them vastly simpler than the MPT ones. Here's a suggestion:

  • Node compression: Start with a 32 bytes index made of 16 uint16, whose value are to be interpreted as follows:

    • a value of 0x0000 indicates the absence of a child
    • another value indicates the index in the preimage where the 32 bytes node hash starts
    • (This makes nodes with two children 96 bytes instead of the previous 512 bytes.)
  • Continuation nodes: if a sub-tree forms "a linked-list of nodes" (i.e. each node in the subtree has a single child), then we could replace the hash for this subtree by hash(full_address ++ leaf_mips_word). When getting the preimage for a node, we just have to check the length of the preimage to distinguish normal nodes from continuation nodes: continuation nodes are 8 bytes (address + value), while normal nodes are >= 96 bytes (32 byte sof index + at least 2 hash of 32 bytes each).

Fix the BDS accounting

By fixing the Go code to properly count BDS steps, we can avoid needing to disassemble the instructions in Python, and we should be able to make the Python fast.

Profiling in MIPS

Half the time is spend in btcec. 10% is in keccak.

github.com/btcsuite/btcd/btcec.(*fieldVal).SquareVal                             : 26.57%                                                                                 
github.com/btcsuite/btcd/btcec.(*fieldVal).Mul2                                  : 24.66%                                                                                 
golang.org/x/crypto/sha3.keccakF1600                                             : 11.23%                                                                                 
github.com/ethereum/go-ethereum/core/vm.codeBitmapInternal                       : 3.68%                                                                                  
github.com/btcsuite/btcd/btcec.(*fieldVal).Normalize                             : 3.03%                                                                                  
runtime.mallocgc                                                                 : 2.81%                                                                                  
github.com/ethereum/go-ethereum/core/vm.(*EVMInterpreter).Run                    : 1.61%                                                                                  
github.com/btcsuite/btcd/btcec.(*KoblitzCurve).addZ2EqualsOne                    : 1.46%                                                                                  
github.com/btcsuite/btcd/btcec.(*KoblitzCurve).doubleGeneric                     : 1.21%                                                                                  
runtime.heapBitsSetType                                                          : 1.09%  

with a heavier block this is less true

github.com/btcsuite/btcd/btcec.(*fieldVal).SquareVal                             : 17.67%                                                                     
github.com/btcsuite/btcd/btcec.(*fieldVal).Mul2                                  : 17.50%                                                                 
github.com/ethereum/go-ethereum/core/vm.codeBitmapInternal                       : 7.16%                                                                    
golang.org/x/crypto/sha3.keccakF1600                                             : 5.72%                                                                  
github.com/ethereum/go-ethereum/core/vm.(*EVMInterpreter).Run                    : 5.13%                                                        
runtime.mallocgc                                                                 : 4.33%                                                                                  
github.com/btcsuite/btcd/btcec.(*fieldVal).Normalize                             : 1.84%                                                                  
runtime.heapBitsSetType                                                          : 1.44%                                                                 
runtime.memmove                                                                  : 1.28%                                                                                  
github.com/ethereum/go-ethereum/core/vm.(*Memory).Set32                          : 1.21%  

What a waste of time on the CGO stuff

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.