git ssb

0+

wanderer🌟 / js-primea-hypervisor



Commit 49dfa5e4a80eda9422f7a27a0d55fb30ffc77639

Merge pull request #46 from ewasm/call

Merge create/call paths in runTx
Alex Beregszaszi authored on 8/28/2016, 9:25:41 PM
GitHub committed on 8/28/2016, 9:25:41 PM
Parent: 807065e92512168f27868090b0395f77d4c52705
Parent: a7368ae614730b38e21a3792049310c00d65a725

Files changed

environment.jschanged
index.jschanged
interface.jschanged
transaction.jschanged
environment.jsView
@@ -21,8 +21,9 @@
2121 // the ROM
2222 code: new Uint8Array(), // the current running code
2323 // output calls
2424 logs: [],
25+ selfDestruct: false,
2526 selfDestructAddress: new Address('0x0000000000000000000000000000000000000000'),
2627 // more output calls
2728 returnValue: new Uint8Array()
2829 }
index.jsView
@@ -119,16 +119,25 @@
119119
120120 const kernel = new Kernel(environment)
121121 kernel.codeHandler(code, new Interface(environment))
122122
123+ // self destructed
124+ if (environment.selfDestruct) {
125+ const balance = this.state.get(call.to.toString()).get('balance')
126+ const beneficiary = this.state.get(environment.selfDestructAddress)
127+ beneficiary.set('balance', beneficiary.get('balance').add(balance))
128+ this.state.delete(call.to.toString())
129+ }
130+
123131 // generate new stateroot
124132 // this.environment.state.set(address, { stateRoot: stateRoot })
125133
126134 return {
127135 executionOutcome: 1, // success
128136 gasLeft: new U256(environment.gasLeft),
129137 gasRefund: new U256(environment.gasRefund),
130138 returnValue: environment.returnValue,
139+ selfDestruct: environment.selfDestruct,
131140 selfDestructAddress: environment.selfDestructAddress,
132141 logs: environment.logs
133142 }
134143 }
@@ -152,12 +161,18 @@
152161 // Run code and take return value as contract code
153162 // FIXME: decide if these are the right values here: value: 0, data: ''
154163 code = this.callHandler({ from: create.from, to: address, gasLimit: create.gasLimit, value: new U256(0), data: new Uint8Array() }).returnValue
155164
165+ // FIXME: special handling for selfdestruct
166+
156167 this.environment.state.get(address.toString()).set('code', code)
157168
158169 return {
159- accountCreated: address
170+ executionOutcome: 1, // success
171+ gasLeft: new U256(this.environment.gasLeft),
172+ gasRefund: new U256(this.environment.gasRefund),
173+ accountCreated: address,
174+ logs: this.environment.logs
160175 }
161176 }
162177
163178 // run tx; the tx message handler
@@ -182,58 +197,57 @@
182197 }
183198
184199 fromAccount.set('nonce', fromAccount.get('nonce').add(new U256(1)))
185200
201+ let isCreation = false
202+
186203 // Special case: contract deployment
187- if (tx.to.isZero()) {
188- if (tx.data.length !== 0) {
189- console.log('This is a contract deployment transaction')
190-
191- // FIXME: deduct fees
192-
193- return this.createHandler({
194- from: tx.from,
195- gasLimit: tx.gasLimit,
196- value: tx.value,
197- data: tx.data
198- })
199- }
204+ if (tx.to.isZero() && (tx.data.length !== 0)) {
205+ console.log('This is a contract deployment transaction')
206+ isCreation = true
200207 }
201208
202- // deduct gasLimit * gasPrice from sender
203- if (fromAccount.get('balance').lt(tx.gasLimit.mul(tx.gasPrice))) {
204- throw new Error(`Insufficient account balance: ${fromAccount.get('balance').toString()} < ${tx.gasLimit.mul(tx.gasPrice).toString()}`)
205- }
206-
207- fromAccount.set('balance', fromAccount.get('balance').sub(tx.gasLimit.mul(tx.gasPrice)))
208-
209209 // This cost will not be refunded
210- let txCost = 21000
210+ let txCost = 21000 + (isCreation ? 32000 : 0)
211211 tx.data.forEach((item) => {
212212 if (item === 0) {
213213 txCost += 4
214214 } else {
215215 txCost += 68
216216 }
217217 })
218218
219- let ret = this.callHandler({
219+ if (tx.gasLimit.lt(new U256(txCost))) {
220+ throw new Error(`Minimum transaction gas limit not met: ${txCost}`)
221+ }
222+
223+ if (fromAccount.get('balance').lt(tx.gasLimit.mul(tx.gasPrice))) {
224+ throw new Error(`Insufficient account balance: ${fromAccount.get('balance').toString()} < ${tx.gasLimit.mul(tx.gasPrice).toString()}`)
225+ }
226+
227+ // deduct gasLimit * gasPrice from sender
228+ fromAccount.set('balance', fromAccount.get('balance').sub(tx.gasLimit.mul(tx.gasPrice)))
229+
230+ const handler = isCreation ? this.createHandler.bind(this) : this.callHandler.bind(this)
231+ let ret = handler({
220232 to: tx.to,
221233 from: tx.from,
222234 gasLimit: tx.gasLimit - txCost,
223235 value: tx.value,
224236 data: tx.data
225237 })
226238
227- // refund gas
239+ // refund unused gas
228240 if (ret.executionOutcome === 1) {
229241 fromAccount.set('balance', fromAccount.get('balance').add(tx.gasPrice.mul(ret.gasLeft.add(ret.gasRefund))))
230242 }
231243
232244 // save new state?
233245
234246 return {
235- returnValue: ret.returnValue,
247+ executionOutcome: ret.executionOutcome,
248+ accountCreated: isCreation ? ret.accountCreated : undefined,
249+ returnValue: isCreation ? undefined : ret.returnValue,
236250 gasLeft: ret.gasLeft,
237251 logs: ret.logs
238252 }
239253 }
interface.jsView
@@ -392,9 +392,9 @@
392392
393393 // Special case for non-zero value
394394 if (!value.isZero()) {
395395 this.takeGas(9000)
396- gas += 2300;
396+ gas += 2300
397397 }
398398
399399 const [errorCode, result] = this.environment.call(gas, address, value, data)
400400 this.setMemory(resultOffset, resultLength, result)
@@ -504,9 +504,10 @@
504504 * balance to an address path
505505 * @param {integer} offset the offset to load the address from
506506 */
507507 selfDestruct (addressOffset) {
508- this.environment.suicideAddress = Address.fromMemory(this.getMemory(addressOffset, ADDRESS_SIZE_BYTES))
508+ this.environment.selfDestruct = true
509+ this.environment.selfDestructAddress = Address.fromMemory(this.getMemory(addressOffset, ADDRESS_SIZE_BYTES))
509510 this.environment.gasRefund += 24000
510511 }
511512
512513 getMemory (offset, length) {
transaction.jsView
@@ -45,14 +45,5 @@
4545 return new Address('0x0000000000000000000000000000000000000000')
4646 }
4747 return new Address(this._tx.to)
4848 }
49-
50- get isSend () {
51- }
52-
53- get isContractCall () {
54- }
55-
56- get isContractDeployment () {
57- }
5849 }

Built with git-ssb-web