git ssb

0+

wanderer🌟 / js-primea-hypervisor



Tree: 2229ecba408cfd0e6ff15bcdbdce4e5324729188

Files: 2229ecba408cfd0e6ff15bcdbdce4e5324729188 / runTx.js

2323 bytesRaw
1
2 // run tx; the tx message handler
3 runTx (tx, environment = new Environment()) {
4 this.environment = environment
5
6 if (Buffer.isBuffer(tx) || typeof tx === 'string') {
7 tx = new Transaction(tx)
8 if (!tx.valid) {
9 throw new Error('Invalid transaction signature')
10 }
11 }
12
13 // look up sender
14 let fromAccount = this.environment.state.get(tx.from.toString())
15 if (!fromAccount) {
16 throw new Error('Sender account not found: ' + tx.from.toString())
17 }
18
19 if (fromAccount.get('nonce').gt(tx.nonce)) {
20 throw new Error(`Invalid nonce: ${fromAccount.get('nonce')} > ${tx.nonce}`)
21 }
22
23 fromAccount.set('nonce', fromAccount.get('nonce').add(new U256(1)))
24
25 let isCreation = false
26
27 // Special case: contract deployment
28 if (tx.to.isZero() && (tx.data.length !== 0)) {
29 console.log('This is a contract deployment transaction')
30 isCreation = true
31 }
32
33 // This cost will not be refunded
34 let txCost = 21000 + (isCreation ? 32000 : 0)
35 tx.data.forEach((item) => {
36 if (item === 0) {
37 txCost += 4
38 } else {
39 txCost += 68
40 }
41 })
42
43 if (tx.gasLimit.lt(new U256(txCost))) {
44 throw new Error(`Minimum transaction gas limit not met: ${txCost}`)
45 }
46
47 if (fromAccount.get('balance').lt(tx.gasLimit.mul(tx.gasPrice))) {
48 throw new Error(`Insufficient account balance: ${fromAccount.get('balance').toString()} < ${tx.gasLimit.mul(tx.gasPrice).toString()}`)
49 }
50
51 // deduct gasLimit * gasPrice from sender
52 fromAccount.set('balance', fromAccount.get('balance').sub(tx.gasLimit.mul(tx.gasPrice)))
53
54 const handler = isCreation ? this.createHandler.bind(this) : this.callHandler.bind(this)
55 let ret = handler({
56 to: tx.to,
57 from: tx.from,
58 gasLimit: tx.gasLimit - txCost,
59 value: tx.value,
60 data: tx.data
61 })
62
63 // refund unused gas
64 if (ret.executionOutcome === 1) {
65 fromAccount.set('balance', fromAccount.get('balance').add(tx.gasPrice.mul(ret.gasLeft.add(ret.gasRefund))))
66 }
67
68 // save new state?
69
70 return {
71 executionOutcome: ret.executionOutcome,
72 accountCreated: isCreation ? ret.accountCreated : undefined,
73 returnValue: isCreation ? undefined : ret.returnValue,
74 gasLeft: ret.gasLeft,
75 logs: ret.logs
76 }
77 }
78

Built with git-ssb-web