Skip to content

Commit

Permalink
Turing replica state
Browse files Browse the repository at this point in the history
  • Loading branch information
InoMurko committed Oct 30, 2023
1 parent 81c5ca1 commit ac70a6a
Show file tree
Hide file tree
Showing 5 changed files with 125 additions and 42 deletions.
29 changes: 28 additions & 1 deletion boba_examples/turing-hello-world/contracts/HelloTuring.sol
Original file line number Diff line number Diff line change
Expand Up @@ -37,9 +37,36 @@ contract HelloTuring {
return product;
}

// Tests error handling when a contract tries to make more than one call
// per Tx, using the "multFloatNumbers" offchain handler.
// Multiple calls from the same stack depth are permitted for legacy reasons
// but should not be used in new code.
function callTwice(string memory _url, string memory a, string memory b, uint32 mode)
public returns (uint256) {

bytes memory encRequest;
bytes memory encResponse;

if (mode == 2) {
// Call from a different stack depth
HelloTuring(address(this)).callTwice(_url, a, b, 0);
} else if (mode == 1) {
// Call from same stack depth
encRequest = abi.encode(b);
encResponse = myHelper.TuringTxV2(_url, encRequest);
}

encRequest = abi.encode(a);
encResponse = myHelper.TuringTxV2(_url, encRequest);

uint256 product = abi.decode(encResponse, (uint256));
emit MultFloatNumbers(product);
return product;
}

// Tests a Turing method which returns a variable-length array.
// The parameters 'a' and 'b' are passed in the request, returing
// an array of 'b' elements each with value 'a'. This function
// an array of 'a' elements each with value 'b'. This function
// adds all of the returned values and returns a total of (a*b)
function multArray(string memory _url, uint256 a, uint256 b)
public {
Expand Down
51 changes: 48 additions & 3 deletions boba_examples/turing-hello-world/test/local-webserver.ts
Original file line number Diff line number Diff line change
Expand Up @@ -204,7 +204,7 @@ if (hre.network.name === "boba_local") {

it('Should fund your Turing helper contract in turingCredit', async () => {

const depositAmount = utils.parseEther('0.5')
const depositAmount = utils.parseEther('1.5')
const preBalance = await turingCredit.prepaidBalance(helper.address)

const bobaBalance = await L2BOBAToken.balanceOf(deployerWallet.address)
Expand Down Expand Up @@ -283,7 +283,6 @@ if (hre.network.name === "boba_local") {
it("should charge extra gas for L1 calldata storage", async() => {
const g1 = (await hello.estimateGas.multArray(urlStr2, 1, 10, gasOverride)).toNumber()
const g2 = (await hello.estimateGas.multArray(urlStr2, 101, 10, gasOverride)).toNumber()

// Larger calldata costs more gas inside the contract itself. We need to test for
// additional usage on top of this from the L1 calldata calculation. The exact value
// depends on the L1 gas price so this test doesn't look for a specific number
Expand All @@ -304,11 +303,57 @@ if (hre.network.name === "boba_local") {
expect(result).to.equal(nElem * 55)
})

it("should allow repeated calls (legacy support)", async () => {
await hello.estimateGas.callTwice(urlStr, '6', '6', 1, gasOverride)
let tr = await hello.callTwice(urlStr, '6', '6', 1, gasOverride)
const res = await tr.wait()
expect(res).to.be.ok

const ev = res.events.find(e => e.event === "MultFloatNumbers")
const result = parseInt(ev.data.slice(-64), 16) / 100
expect(result.toFixed(5)).to.equal('904.78000')
})

it("should disallow repeated calls with different input", async () => {
try {
await hello.estimateGas.callTwice(urlStr, '6', '7', 1, gasOverride)
expect(1).to.equal(0)
} catch (e) {
// generic error code indicating that a tx reverted
expect(e.error.toString()).to.contain("gas required exceeds allowance")
}

try {
let tr = await hello.callTwice(urlStr, '6', '7', 1, gasOverride)
const res = await tr.wait()
expect(1).to.equal(0)
} catch (e) {
expect(e.toString()).to.contain("transaction failed")
}
})

it("should disallow repeated calls at different depth", async () => {
try {
await hello.estimateGas.callTwice(urlStr, '8', '8', 2, gasOverride)
expect(1).to.equal(0)
} catch (e) {
expect(e.error.toString()).to.contain("gas required exceeds allowance")
}
try {
let tr = await hello.callTwice(urlStr, '8', '8', 2, gasOverride)
const res = await tr.wait()
expect(1).to.equal(0)
} catch (e) {
expect(e.toString()).to.contain("transaction failed")
}
})

it("final balance", async () => {
const postBalance = await turingCredit.prepaidBalance(
helper.address
)
//expect(postBalance).to.equal( utils.parseEther('0.5'))
// Change expected value if tests are added or skipped above
expect(postBalance).to.equal( utils.parseEther('0.9'))
})
})
} else {
Expand Down
77 changes: 40 additions & 37 deletions integration-tests/test/eth-l2/turing.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -73,45 +73,48 @@ describe('Turing 256 Bit Random Number Test', async () => {
).attach(L1StandardBridgeAddress)
/* eslint-disable */
const http = require('http')
const ip = require("ip")
const ip = require('ip')
// start local server
const server = module.exports = http.createServer(async function (req, res) {

if (req.headers['content-type'] === 'application/json') {

let body = '';

req.on('data', function (chunk) {
body += chunk.toString()
})

req.on('end', async function () {
const jsonBody = JSON.parse(body)
const input = JSON.parse(body).params[0]
let result

const args = utils.defaultAbiCoder.decode(['uint256','uint256'], input)
if (req.url === "/echo") {
const randomPrice = Math.floor(Math.random() * 1000)
result = input
let response = {
"jsonrpc": "2.0",
"id": jsonBody.id,
"result": result
const server = (module.exports = http
.createServer(async function (req, res) {
if (req.headers['content-type'] === 'application/json') {
let body = ''

req.on('data', function (chunk) {
body += chunk.toString()
})

req.on('end', async function () {
const jsonBody = JSON.parse(body)
const input = JSON.parse(body).params[0]
let result

const args = utils.defaultAbiCoder.decode(
['uint256', 'uint256'],
input
)
if (req.url === '/echo') {
const randomPrice = Math.floor(Math.random() * 1000)
result = input
let response = {
jsonrpc: '2.0',
id: jsonBody.id,
result: result,
}
res.end(JSON.stringify(response))
server.emit('success', body)
} else {
res.writeHead(400, { 'Content-Type': 'text/plain' })
res.end('Bad request')
}
res.end(JSON.stringify(response))
server.emit('success', body)
} else {
res.writeHead(400, { 'Content-Type': 'text/plain' })
res.end('Bad request')
}
});
} else {
console.log("Other request:", req)
res.writeHead(400, { 'Content-Type': 'text/plain' })
res.end('Expected content-type: application/json')
}
}).listen(apiPort)
})
} else {
console.log('Other request:', req)
res.writeHead(400, { 'Content-Type': 'text/plain' })
res.end('Expected content-type: application/json')
}
})
.listen(apiPort))
URL = `http://${ip.address()}:${apiPort}/echo`
/* eslint-enable */
})
Expand Down
8 changes: 8 additions & 0 deletions l2geth/core/vm/evm.go
Original file line number Diff line number Diff line change
Expand Up @@ -749,6 +749,14 @@ func (evm *EVM) Call(caller ContractRef, addr common.Address, input []byte, gas
// We are in Verifier/Replica mode
// Turing for this Transaction has already been run elsewhere - replay using
// information from the EVM context
if evm.Context.TuringInput == nil {
evm.Context.TuringInput = make([]byte, len(input))
copy(evm.Context.TuringInput, input)
evm.Context.TuringVMDepth = evm.depth
} else if !bytes.Equal(input, evm.Context.TuringInput) || evm.depth != evm.Context.TuringVMDepth {
log.Debug("TURING ERROR: evm.Context.Turing already set")
return nil, gas, ErrTuringDepth
}
ret, err = run(evm, contract, evm.Context.Turing, false)
log.Trace("TURING REPLAY", "evm.Context.Turing", evm.Context.Turing)
}
Expand Down
2 changes: 1 addition & 1 deletion ops/docker-compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -418,7 +418,7 @@ services:
environment:
L1_NODE_WEB3_URL: http://l1_chain:8545
L1_CONFIRMATIONS: 8
L2_NODE_WEB3_URL: http://l2geth:8545
L2_NODE_WEB3_URL: http://replica:8545
L2_CHECK_INTERVAL: 10
VERIFIER_WEB3_URL: http://verifier:8545
ADDRESS_MANAGER_ADDRESS: "0x5FbDB2315678afecb367f032d93F642f64180aa3"
Expand Down

0 comments on commit ac70a6a

Please sign in to comment.