kumavis / ethereum-simulator

:money_with_wings: [Out-of-date] An intereactive simulator for ethereum contracts
https://kumavis.github.io/ethereum-simulator
MIT License
44 stars 13 forks source link

Sub-currency example silently fails #25

Closed benjaminbradley closed 10 years ago

benjaminbradley commented 10 years ago

I'm trying to get the sub-currency example from the whitepaper to work and it never runs the contract (storage is never updated), it just accumulates credits from the incoming transactions. There is no indication as to what is failing. It's possible it's a syntax error - I've attempted to adapt the CLL from the whitepaper into JS for the simulator. Here is what I'm submitting as the contract code:

if (tx.value < 100 * block.basefee) {
    return
} else if (contract.storage[1000]) {
    var from = tx.sender
    var to = tx.data[0]
    var value = tx.data[1]
    if (to <= 1000){
        return
    }
    if (contract.storage[from] < value){
        return
    }
    contract.storage[from] = contract.storage[from] - value
    contract.storage[to] = contract.storage[to] + value
} else {
    contract.storage[MYCREATOR] = 10^18
    contract.storage[1000] = 1
}
kumavis commented 10 years ago

MYCREATOR is undefined

MYCREATOR is not provided by this simulator's implementation, nor is it by the AlethZero Client. In the whitepaper I assume it was left in as a placeholder for a constant.

It fails silently b/c javascript fails silently ¯\_(ツ)_/¯

Here is the execution scope of the contract https://github.com/k1n0k0/ethereum-simulator/blob/master/lib/simulator.js#L106-L131

benjaminbradley commented 10 years ago

Got it, I swear I tried quoting 'MYCREATOR' so it would use the string as the hash key, but when I tried it again just now, it worked!

kumavis commented 10 years ago

I'd be happy to add this example as a default in the simulator if you like

benjaminbradley commented 10 years ago

Javascript doesn't seem to support a built-in exponent operator so the 10^18 expression is not calculated as intended (I think it's doing a bitwise or maybe? the result is 24). I changed it to a hard-coded decimal number. I also altered MYCREATOR so it instead uses the first transaction's sender address as the holder of the initial currency stock. I replaced the cryptic '1000' storage address with the string 'initialized' which is easier to read. Here is the resulting js code:

if (tx.value < 100 * block.basefee) {
    return
} else if (contract.storage['initialized']) {
    var from = tx.sender
    var to = tx.data[0]
    var value = tx.data[1]
    if (to <= 1000) {
        return
    }
    if (contract.storage[from] < value) {
        return
    }
    contract.storage[from] = contract.storage[from] - value
    contract.storage[to] = contract.storage[to] + value
} else {
    contract.storage[tx.sender] = 100000000
    contract.storage['initialized'] = 1
}

I'm getting unusual behavior that looks like the contract storage space is not initialized to 0 (as described in the white paper). My first "transfer value" transaction to this contract results in the destination account value being "undefinedXXX" where XXX is the value that I'm sending. I've been unsuccessful in reproducing the issue in a simpler example so I haven't submitted it as a separate issue yet. Is the contract memory space a dictionary hash or a 0-based array? The self-protection syntax [if (to <= 1000) ] seems to imply it's an integer-indexed array, but in practice it seems that the key can be any string or number.

kumavis commented 10 years ago

It is a dictionary hash (standard javascript object), where numbers are converted to strings when used as keys. Because of this, I don't think there's a way to initialize the values to zero, as we can't know what keys will be used, it would be impractical to set every possible key to zero, and there's no way to instrument an object with a catchall getter function.

kumavis commented 10 years ago

But that is an important point, it does deviate from the whitepaper. This project is also behind the released yellowpaper (latest protocol implementation guidelines). I'll need to bring it up to speed sometime soon.

kumavis commented 10 years ago

I would modify the lines in this way

original:

contract.storage[from] = contract.storage[from] - value
contract.storage[to] = contract.storage[to] + value

modified:

// initialize accounts if necessary
contract.storage[from] = contract.storage[from] || 0
contract.storage[to] = contract.storage[to] || 0
// transfer value
contract.storage[from] -= value
contract.storage[to] += value
kumavis commented 10 years ago

Sidenote:

On github, you can use three backticks and the language name to create a codeblock.

var message = 'woah'
console.log(message)

this makes your code easier to read

var message = 'woah'
console.log(message)

I modified your posts and added this formatting