Commit caca8779 authored by George Hotz's avatar George Hotz

progress on block, gas limit reached

parent 0324ee64
...@@ -3,7 +3,7 @@ Implement as a MIPS instruction? ...@@ -3,7 +3,7 @@ Implement as a MIPS instruction?
InputOracle -- Preagreed upon inputs (TODO: replace with memory reads from given address range) InputOracle -- Preagreed upon inputs (TODO: replace with memory reads from given address range)
$a0 = input choice $a0 = input choice
0 -- StateRoot(n) 0 -- BlockHash(n)
1 -- Transactions(n+1) 1 -- Transactions(n+1)
2 -- Coinbase(n+1) 2 -- Coinbase(n+1)
3 -- Uncles(n+1) 3 -- Uncles(n+1)
......
...@@ -77,20 +77,16 @@ contract Challenge { ...@@ -77,20 +77,16 @@ contract Challenge {
return challengeId; return challengeId;
} }
function InitiateChallenge(uint blockNumberN, function InitiateChallenge(uint blockNumberN, bytes calldata blockHeaderNp1,
bytes calldata blockHeaderN, bytes calldata blockHeaderNp1,
bytes32 assertionRoot, bytes32 finalSystemState, uint256 stepCount) external returns (uint256) { bytes32 assertionRoot, bytes32 finalSystemState, uint256 stepCount) external returns (uint256) {
require(blockhash(blockNumberN) == keccak256(blockHeaderN), "start block hash wrong");
require(blockhash(blockNumberN+1) == keccak256(blockHeaderNp1), "end block hash wrong"); require(blockhash(blockNumberN+1) == keccak256(blockHeaderNp1), "end block hash wrong");
// decode the blocks // decode the blocks
Lib_RLPReader.RLPItem[] memory blockN = Lib_RLPReader.readList(blockHeaderN);
Lib_RLPReader.RLPItem[] memory blockNp1 = Lib_RLPReader.readList(blockHeaderNp1); Lib_RLPReader.RLPItem[] memory blockNp1 = Lib_RLPReader.readList(blockHeaderNp1);
bytes32 newroot = Lib_RLPReader.readBytes32(blockNp1[3]); bytes32 newroot = Lib_RLPReader.readBytes32(blockNp1[3]);
require(assertionRoot != newroot, "asserting that the real state is correct is not a challenge"); require(assertionRoot != newroot, "asserting that the real state is correct is not a challenge");
// input oracle info // input oracle info
bytes32 root = Lib_RLPReader.readBytes32(blockN[3]);
bytes32 txhash = Lib_RLPReader.readBytes32(blockNp1[4]); bytes32 txhash = Lib_RLPReader.readBytes32(blockNp1[4]);
address coinbase = Lib_RLPReader.readAddress(blockNp1[2]); address coinbase = Lib_RLPReader.readAddress(blockNp1[2]);
bytes32 uncles = Lib_RLPReader.readBytes32(blockNp1[1]); bytes32 uncles = Lib_RLPReader.readBytes32(blockNp1[1]);
...@@ -99,7 +95,7 @@ contract Challenge { ...@@ -99,7 +95,7 @@ contract Challenge {
// we both agree at the beginning // we both agree at the beginning
// the first instruction executed in MIPS should be an access of startState // the first instruction executed in MIPS should be an access of startState
bytes32 startState = GlobalStartState; bytes32 startState = GlobalStartState;
startState = writeBytes32(startState, 0xD0000000, root); startState = writeBytes32(startState, 0xD0000000, blockhash(blockNumberN));
startState = writeBytes32(startState, 0xD0000020, txhash); startState = writeBytes32(startState, 0xD0000020, txhash);
startState = writeBytes32(startState, 0xD0000040, bytes32(uint256(coinbase))); startState = writeBytes32(startState, 0xD0000040, bytes32(uint256(coinbase)));
startState = writeBytes32(startState, 0xD0000060, uncles); startState = writeBytes32(startState, 0xD0000060, uncles);
......
// Copyright 2021 The go-ethereum Authors
// This file is part of the go-ethereum library.
//
// The go-ethereum library is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// The go-ethereum library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public License
// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
package misc
import (
"fmt"
"math/big"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/common/math"
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/params"
)
// VerifyEip1559Header verifies some header attributes which were changed in EIP-1559,
// - gas limit check
// - basefee check
func VerifyEip1559Header(config *params.ChainConfig, parent, header *types.Header) error {
// Verify that the gas limit remains within allowed bounds
parentGasLimit := parent.GasLimit
if !config.IsLondon(parent.Number) {
parentGasLimit = parent.GasLimit * params.ElasticityMultiplier
}
if err := VerifyGaslimit(parentGasLimit, header.GasLimit); err != nil {
return err
}
// Verify the header is not malformed
if header.BaseFee == nil {
return fmt.Errorf("header is missing baseFee")
}
// Verify the baseFee is correct based on the parent header.
expectedBaseFee := CalcBaseFee(config, parent)
if header.BaseFee.Cmp(expectedBaseFee) != 0 {
return fmt.Errorf("invalid baseFee: have %s, want %s, parentBaseFee %s, parentGasUsed %d",
expectedBaseFee, header.BaseFee, parent.BaseFee, parent.GasUsed)
}
return nil
}
// CalcBaseFee calculates the basefee of the header.
func CalcBaseFee(config *params.ChainConfig, parent *types.Header) *big.Int {
// If the current block is the first EIP-1559 block, return the InitialBaseFee.
if !config.IsLondon(parent.Number) {
return new(big.Int).SetUint64(params.InitialBaseFee)
}
var (
parentGasTarget = parent.GasLimit / params.ElasticityMultiplier
parentGasTargetBig = new(big.Int).SetUint64(parentGasTarget)
baseFeeChangeDenominator = new(big.Int).SetUint64(params.BaseFeeChangeDenominator)
)
// If the parent gasUsed is the same as the target, the baseFee remains unchanged.
if parent.GasUsed == parentGasTarget {
return new(big.Int).Set(parent.BaseFee)
}
if parent.GasUsed > parentGasTarget {
// If the parent block used more gas than its target, the baseFee should increase.
gasUsedDelta := new(big.Int).SetUint64(parent.GasUsed - parentGasTarget)
x := new(big.Int).Mul(parent.BaseFee, gasUsedDelta)
y := x.Div(x, parentGasTargetBig)
baseFeeDelta := math.BigMax(
x.Div(y, baseFeeChangeDenominator),
common.Big1,
)
return x.Add(parent.BaseFee, baseFeeDelta)
} else {
// Otherwise if the parent block used less gas than its target, the baseFee should decrease.
gasUsedDelta := new(big.Int).SetUint64(parentGasTarget - parent.GasUsed)
x := new(big.Int).Mul(parent.BaseFee, gasUsedDelta)
y := x.Div(x, parentGasTargetBig)
baseFeeDelta := x.Div(y, baseFeeChangeDenominator)
return math.BigMax(
x.Sub(parent.BaseFee, baseFeeDelta),
common.Big0,
)
}
}
// Copyright 2021 The go-ethereum Authors
// This file is part of the go-ethereum library.
//
// The go-ethereum library is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// The go-ethereum library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public License
// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
package misc
import (
"errors"
"fmt"
"github.com/ethereum/go-ethereum/params"
)
// VerifyGaslimit verifies the header gas limit according increase/decrease
// in relation to the parent gas limit.
func VerifyGaslimit(parentGasLimit, headerGasLimit uint64) error {
// Verify that the gas limit remains within allowed bounds
diff := int64(parentGasLimit) - int64(headerGasLimit)
if diff < 0 {
diff *= -1
}
limit := parentGasLimit / params.GasLimitBoundDivisor
if uint64(diff) >= limit {
return fmt.Errorf("invalid gas limit: have %d, want %d +-= %d", headerGasLimit, parentGasLimit, limit-1)
}
if headerGasLimit < params.MinGasLimit {
return errors.New("invalid gas limit below 5000")
}
return nil
}
...@@ -2,14 +2,18 @@ package main ...@@ -2,14 +2,18 @@ package main
import ( import (
"fmt" "fmt"
"log"
"math/big"
"os" "os"
"strconv" "strconv"
"github.com/ethereum/go-ethereum/consensus/misc"
"github.com/ethereum/go-ethereum/core" "github.com/ethereum/go-ethereum/core"
"github.com/ethereum/go-ethereum/core/state" "github.com/ethereum/go-ethereum/core/state"
"github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/core/vm" "github.com/ethereum/go-ethereum/core/vm"
"github.com/ethereum/go-ethereum/crypto" "github.com/ethereum/go-ethereum/crypto"
"github.com/ethereum/go-ethereum/oracle"
"github.com/ethereum/go-ethereum/params" "github.com/ethereum/go-ethereum/params"
"github.com/ethereum/go-ethereum/rlp" "github.com/ethereum/go-ethereum/rlp"
"github.com/ethereum/go-ethereum/trie" "github.com/ethereum/go-ethereum/trie"
...@@ -24,29 +28,34 @@ func main() { ...@@ -24,29 +28,34 @@ func main() {
blockNumber, _ := strconv.Atoi(os.Args[1]) blockNumber, _ := strconv.Atoi(os.Args[1])
// read header // non mips
var header types.Header oracle.PrefetchBlock(big.NewInt(int64(blockNumber)), true, trie.NewStackTrie(nil))
{ oracle.PrefetchBlock(big.NewInt(int64(blockNumber)+1), false, trie.NewStackTrie(nil))
f, _ := os.Open(fmt.Sprintf("data/block_%d", blockNumber))
rlpheader := rlp.NewStream(f, 0) // read start block header
rlpheader.Decode(&header) var parent types.Header
f.Close() rlperr := rlp.DecodeBytes(oracle.Preimage(oracle.Input(0)), &parent)
fmt.Println("read old block") if rlperr != nil {
log.Fatal(rlperr)
} }
// read header // read header
var newheader types.Header var newheader types.Header
{ newheader.ParentHash = parent.Hash()
newheader.TxHash = oracle.Input(1)
newheader.Number = big.NewInt(0).Add(parent.Number, big.NewInt(1))
newheader.BaseFee = misc.CalcBaseFee(params.MainnetChainConfig, &parent)
/*{
f, _ := os.Open(fmt.Sprintf("data/block_%d", blockNumber+1)) f, _ := os.Open(fmt.Sprintf("data/block_%d", blockNumber+1))
rlpheader := rlp.NewStream(f, 0) rlpheader := rlp.NewStream(f, 0)
rlpheader.Decode(&newheader) rlpheader.Decode(&newheader)
f.Close() f.Close()
fmt.Println("read new block") fmt.Println("read new block")
} }*/
bc := core.NewBlockChain() bc := core.NewBlockChain()
database := state.NewDatabase(header) database := state.NewDatabase(parent)
statedb, _ := state.New(header.Root, database, nil) statedb, _ := state.New(parent.Root, database, nil)
vmconfig := vm.Config{} vmconfig := vm.Config{}
processor := core.NewStateProcessor(params.MainnetChainConfig, bc, bc.Engine()) processor := core.NewStateProcessor(params.MainnetChainConfig, bc, bc.Engine())
fmt.Println("made state processor") fmt.Println("made state processor")
...@@ -64,7 +73,7 @@ func main() { ...@@ -64,7 +73,7 @@ func main() {
var uncles []*types.Header var uncles []*types.Header
var receipts []*types.Receipt var receipts []*types.Receipt
block := types.NewBlock(&newheader, txs, uncles, receipts, trie.NewStackTrie(nil)) block := types.NewBlock(&newheader, txs, uncles, receipts, trie.NewStackTrie(nil))
fmt.Println("made block, parent:", header.ParentHash) fmt.Println("made block, parent:", newheader.ParentHash)
// if this is correct, the trie is working // if this is correct, the trie is working
// TODO: it's the previous block now // TODO: it's the previous block now
...@@ -74,10 +83,10 @@ func main() { ...@@ -74,10 +83,10 @@ func main() {
_, _, _, err := processor.Process(block, statedb, vmconfig) _, _, _, err := processor.Process(block, statedb, vmconfig)
if err != nil { if err != nil {
panic("processor error") log.Fatal(err)
} }
fmt.Println("process done with hash", header.Root, "->", block.Header().Root, "real", newheader.Root) fmt.Println("process done with hash", parent.Root, "->", block.Header().Root, "real", newheader.Root)
if block.Header().Root == newheader.Root { if block.Header().Root == newheader.Root {
fmt.Println("good transition") fmt.Println("good transition")
} else { } else {
......
//go:build !mips
// +build !mips
package oracle
import (
"math/big"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/common/hexutil"
"github.com/ethereum/go-ethereum/core/types"
)
// SendTxArgs represents the arguments to submit a transaction
// This struct is identical to ethapi.TransactionArgs, except for the usage of
// common.MixedcaseAddress in From and To
type SendTxArgs struct {
From common.MixedcaseAddress `json:"from"`
To *common.MixedcaseAddress `json:"to"`
Gas hexutil.Uint64 `json:"gas"`
GasPrice *hexutil.Big `json:"gasPrice"`
MaxFeePerGas *hexutil.Big `json:"maxFeePerGas"`
MaxPriorityFeePerGas *hexutil.Big `json:"maxPriorityFeePerGas"`
Value hexutil.Big `json:"value"`
Nonce hexutil.Uint64 `json:"nonce"`
// We accept "data" and "input" for backwards-compatibility reasons.
// "input" is the newer name and should be preferred by clients.
// Issue detail: https://github.com/ethereum/go-ethereum/issues/15628
Data *hexutil.Bytes `json:"data"`
Input *hexutil.Bytes `json:"input,omitempty"`
// For non-legacy transactions
AccessList *types.AccessList `json:"accessList,omitempty"`
ChainID *hexutil.Big `json:"chainId,omitempty"`
}
type Header struct {
ParentHash *common.Hash `json:"parentHash" gencodec:"required"`
UncleHash *common.Hash `json:"sha3Uncles" gencodec:"required"`
Coinbase *common.Address `json:"miner" gencodec:"required"`
Root *common.Hash `json:"stateRoot" gencodec:"required"`
TxHash *common.Hash `json:"transactionsRoot" gencodec:"required"`
ReceiptHash *common.Hash `json:"receiptsRoot" gencodec:"required"`
Bloom *types.Bloom `json:"logsBloom" gencodec:"required"`
Difficulty *hexutil.Big `json:"difficulty" gencodec:"required"`
Number *hexutil.Big `json:"number" gencodec:"required"`
GasLimit *hexutil.Uint64 `json:"gasLimit" gencodec:"required"`
GasUsed *hexutil.Uint64 `json:"gasUsed" gencodec:"required"`
Time *hexutil.Uint64 `json:"timestamp" gencodec:"required"`
Extra *hexutil.Bytes `json:"extraData" gencodec:"required"`
MixDigest *common.Hash `json:"mixHash"`
Nonce *types.BlockNonce `json:"nonce"`
BaseFee *hexutil.Big `json:"baseFeePerGas" rlp:"optional"`
// transactions
Transactions []SendTxArgs `json:"transactions"`
}
func (dec *Header) ToHeader() types.Header {
var h types.Header
h.ParentHash = *dec.ParentHash
h.UncleHash = *dec.UncleHash
h.Coinbase = *dec.Coinbase
h.Root = *dec.Root
h.TxHash = *dec.TxHash
h.ReceiptHash = *dec.ReceiptHash
h.Bloom = *dec.Bloom
h.Difficulty = (*big.Int)(dec.Difficulty)
h.Number = (*big.Int)(dec.Number)
h.GasLimit = uint64(*dec.GasLimit)
h.GasUsed = uint64(*dec.GasUsed)
h.Time = uint64(*dec.Time)
h.Extra = *dec.Extra
if dec.MixDigest != nil {
h.MixDigest = *dec.MixDigest
}
if dec.Nonce != nil {
h.Nonce = *dec.Nonce
}
if dec.BaseFee != nil {
h.BaseFee = (*big.Int)(dec.BaseFee)
}
return h
}
// ToTransaction converts the arguments to a transaction.
func (args *SendTxArgs) ToTransaction() *types.Transaction {
// Add the To-field, if specified
var to *common.Address
if args.To != nil {
dstAddr := args.To.Address()
to = &dstAddr
}
var input []byte
if args.Input != nil {
input = *args.Input
} else if args.Data != nil {
input = *args.Data
}
var data types.TxData
switch {
case args.MaxFeePerGas != nil:
al := types.AccessList{}
if args.AccessList != nil {
al = *args.AccessList
}
data = &types.DynamicFeeTx{
To: to,
ChainID: (*big.Int)(args.ChainID),
Nonce: uint64(args.Nonce),
Gas: uint64(args.Gas),
GasFeeCap: (*big.Int)(args.MaxFeePerGas),
GasTipCap: (*big.Int)(args.MaxPriorityFeePerGas),
Value: (*big.Int)(&args.Value),
Data: input,
AccessList: al,
}
case args.AccessList != nil:
data = &types.AccessListTx{
To: to,
ChainID: (*big.Int)(args.ChainID),
Nonce: uint64(args.Nonce),
Gas: uint64(args.Gas),
GasPrice: (*big.Int)(args.GasPrice),
Value: (*big.Int)(&args.Value),
Data: input,
AccessList: *args.AccessList,
}
default:
data = &types.LegacyTx{
To: to,
Nonce: uint64(args.Nonce),
Gas: uint64(args.Gas),
GasPrice: (*big.Int)(args.GasPrice),
Value: (*big.Int)(&args.Value),
Data: input,
}
}
return types.NewTx(data)
}
...@@ -41,6 +41,7 @@ func Preimage(hash common.Hash) []byte { ...@@ -41,6 +41,7 @@ func Preimage(hash common.Hash) []byte {
} }
// these are stubs in embedded world // these are stubs in embedded world
func PrefetchStorage(blockNumber *big.Int, addr common.Address, skey common.Hash) {} func PrefetchStorage(blockNumber *big.Int, addr common.Address, skey common.Hash) {}
func PrefetchAccount(blockNumber *big.Int, addr common.Address) {} func PrefetchAccount(blockNumber *big.Int, addr common.Address) {}
func PrefetchCode(blockNumber *big.Int, addrHash common.Hash) {} func PrefetchCode(blockNumber *big.Int, addrHash common.Hash) {}
func PrefetchBlock(blockNumber *big.Int, startBlock bool, hasher types.TrieHasher) {}
...@@ -16,7 +16,9 @@ import ( ...@@ -16,7 +16,9 @@ import (
"github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/common/hexutil" "github.com/ethereum/go-ethereum/common/hexutil"
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/crypto" "github.com/ethereum/go-ethereum/crypto"
"github.com/ethereum/go-ethereum/rlp"
) )
type jsonreq struct { type jsonreq struct {
...@@ -38,6 +40,12 @@ type jsonresps struct { ...@@ -38,6 +40,12 @@ type jsonresps struct {
Result string `json:"result"` Result string `json:"result"`
} }
type jsonrespt struct {
Jsonrpc string `json:"jsonrpc"`
Id uint64 `json:"id"`
Result Header `json:"result"`
}
// Result structs for GetProof // Result structs for GetProof
type AccountResult struct { type AccountResult struct {
Address common.Address `json:"address"` Address common.Address `json:"address"`
...@@ -151,8 +159,61 @@ func PrefetchCode(blockNumber *big.Int, addrHash common.Hash) { ...@@ -151,8 +159,61 @@ func PrefetchCode(blockNumber *big.Int, addrHash common.Hash) {
preimages[hash] = ret preimages[hash] = ret
} }
func PrefetchBlock(blockNumber *big.Int) { var inputs [4]common.Hash
// TODO: Write this.
func Input(index int) common.Hash {
return inputs[index]
}
func PrefetchBlock(blockNumber *big.Int, startBlock bool, hasher types.TrieHasher) {
r := jsonreq{Jsonrpc: "2.0", Method: "eth_getBlockByNumber", Id: 1}
r.Params = make([]interface{}, 2)
r.Params[0] = fmt.Sprintf("0x%x", blockNumber.Int64())
r.Params[1] = true
jsonData, _ := json.Marshal(r)
/*dat, _ := ioutil.ReadAll(getAPI(jsonData))
fmt.Println(string(dat))*/
jr := jsonrespt{}
err := json.NewDecoder(getAPI(jsonData)).Decode(&jr)
if err != nil {
panic("bad block prefetch")
}
//fmt.Println(jr.Result)
blockHeader := jr.Result.ToHeader()
// put in the start block header
if startBlock {
blockHeaderRlp, _ := rlp.EncodeToBytes(blockHeader)
hash := crypto.Keccak256Hash(blockHeaderRlp)
preimages[hash] = blockHeaderRlp
inputs[0] = hash
return
}
// second block
if blockHeader.ParentHash != Input(0) {
fmt.Println(blockHeader.ParentHash, Input(0))
panic("block transition isn't correct")
}
inputs[1] = blockHeader.TxHash
inputs[2] = blockHeader.Coinbase.Hash()
inputs[3] = blockHeader.UncleHash
txs := make([]*types.Transaction, len(jr.Result.Transactions))
for i := 0; i < len(jr.Result.Transactions); i++ {
txs[i] = jr.Result.Transactions[i].ToTransaction()
}
// put in transaction trie
//return blockHeader, txs
/*var uncles []*types.Header
var receipts []*types.Receipt
block := types.NewBlock(&blockHeader, txs, uncles, receipts, trie.NewStackTrie(nil))*/
} }
func getProofAccount(blockNumber *big.Int, addr common.Address, skey common.Hash, storage bool) []string { func getProofAccount(blockNumber *big.Int, addr common.Address, skey common.Hash, storage bool) []string {
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment