|
|
|
@ -14,9 +14,7 @@ export class VMProvider { |
|
|
|
|
sendAsync: (query: JSONRPCRequestPayload, callback: JSONRPCResponseCallback) => void |
|
|
|
|
} |
|
|
|
|
newAccountCallback: {[stamp: number]: (error: Error, address: string) => void} |
|
|
|
|
plugin: Plugin |
|
|
|
|
constructor (executionContext: ExecutionContext, plugin: Plugin) { |
|
|
|
|
this.plugin = plugin |
|
|
|
|
constructor (executionContext: ExecutionContext) { |
|
|
|
|
this.executionContext = executionContext |
|
|
|
|
this.worker = null |
|
|
|
|
this.provider = null |
|
|
|
@ -32,66 +30,41 @@ export class VMProvider { |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
async resetEnvironment () { |
|
|
|
|
if (this.worker) this.worker.terminate() |
|
|
|
|
this.worker = new Worker(new URL('./worker-vm', import.meta.url)) |
|
|
|
|
if (this.worker) { |
|
|
|
|
const provider = this.executionContext.getProviderObject() |
|
|
|
|
|
|
|
|
|
let incr = 0 |
|
|
|
|
const stamps = {} |
|
|
|
|
|
|
|
|
|
return new Promise((resolve, reject) => { |
|
|
|
|
this.worker.addEventListener('message', (msg) => { |
|
|
|
|
if (msg.data.cmd === 'sendAsyncResult' && stamps[msg.data.stamp]) { |
|
|
|
|
if (stamps[msg.data.stamp].callback) { |
|
|
|
|
stamps[msg.data.stamp].callback(msg.data.error, msg.data.result) |
|
|
|
|
return |
|
|
|
|
} |
|
|
|
|
if (msg.data.error) { |
|
|
|
|
stamps[msg.data.stamp].reject(msg.data.error) |
|
|
|
|
} else { |
|
|
|
|
stamps[msg.data.stamp].resolve(msg.data.result) |
|
|
|
|
}
|
|
|
|
|
} else if (msg.data.cmd === 'initiateResult') { |
|
|
|
|
if (!msg.data.error) { |
|
|
|
|
this.provider = { |
|
|
|
|
sendAsync: (query, callback) => { |
|
|
|
|
return new Promise((resolve, reject) => { |
|
|
|
|
const stamp = Date.now() + incr |
|
|
|
|
incr++ |
|
|
|
|
stamps[stamp] = { callback, resolve, reject } |
|
|
|
|
this.worker.postMessage({ cmd: 'sendAsync', query, stamp })
|
|
|
|
|
this.worker.postMessage({ |
|
|
|
|
cmd: 'init', |
|
|
|
|
fork: this.executionContext.getCurrentFork(), |
|
|
|
|
nodeUrl: provider?.options['nodeUrl'], |
|
|
|
|
blockNumber: provider?.options['blockNumber'] |
|
|
|
|
}) |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
this.web3 = new Web3(this.provider as LegacySendAsyncProvider) |
|
|
|
|
this.web3.setConfig({ defaultTransactionType: '0x0' }) |
|
|
|
|
extend(this.web3) |
|
|
|
|
this.executionContext.setWeb3(this.executionContext.getProvider(), this.web3) |
|
|
|
|
resolve({}) |
|
|
|
|
} else { |
|
|
|
|
reject(new Error(msg.data.error)) |
|
|
|
|
} |
|
|
|
|
} else if (msg.data.cmd === 'newAccountResult') { |
|
|
|
|
if (this.newAccountCallback[msg.data.stamp]) { |
|
|
|
|
this.newAccountCallback[msg.data.stamp](msg.data.error, msg.data.result) |
|
|
|
|
delete this.newAccountCallback[msg.data.stamp] |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
this.worker = new Worker(new URL('./worker-vm', import.meta.url)) |
|
|
|
|
this.setWorkerEventListeners(this.worker) |
|
|
|
|
const provider = this.executionContext.getProviderObject() |
|
|
|
|
|
|
|
|
|
this.worker.postMessage({ |
|
|
|
|
cmd: 'init', |
|
|
|
|
fork: this.executionContext.getCurrentFork(), |
|
|
|
|
nodeUrl: provider?.options['nodeUrl'], |
|
|
|
|
blockNumber: provider?.options['blockNumber'] |
|
|
|
|
}) |
|
|
|
|
const init = async () => { |
|
|
|
|
let stateDb |
|
|
|
|
if (await this.plugin.call('fileManager', 'exists', '.states/state.json')) { |
|
|
|
|
stateDb = await this.plugin.call('fileManager', 'readFile', '.states/state.json') |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
async loadContext (stringifiedStateDb: string) { |
|
|
|
|
if (this.worker) this.worker.terminate() |
|
|
|
|
this.worker = new Worker(new URL('./worker-vm', import.meta.url)) |
|
|
|
|
this.setWorkerEventListeners(this.worker) |
|
|
|
|
const provider = this.executionContext.getProviderObject() |
|
|
|
|
|
|
|
|
|
this.worker.postMessage({ |
|
|
|
|
cmd: 'init', |
|
|
|
|
fork: this.executionContext.getCurrentFork(), |
|
|
|
|
nodeUrl: provider?.options['nodeUrl'], |
|
|
|
|
blockNumber: provider?.options['blockNumber'], |
|
|
|
|
stateDb |
|
|
|
|
}) |
|
|
|
|
} |
|
|
|
|
init() |
|
|
|
|
stateDb: stringifiedStateDb |
|
|
|
|
}) |
|
|
|
|
} |
|
|
|
|
|
|
|
|
@ -131,4 +104,49 @@ export class VMProvider { |
|
|
|
|
getProvider () { |
|
|
|
|
return this.executionContext.getProvider() |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
private setWorkerEventListeners (worker: Worker) { |
|
|
|
|
if (!worker) throw new Error('Worker not initialized') |
|
|
|
|
let incr = 0 |
|
|
|
|
const stamps = {} |
|
|
|
|
|
|
|
|
|
worker.addEventListener('message', (msg) => { |
|
|
|
|
if (msg.data.cmd === 'sendAsyncResult' && stamps[msg.data.stamp]) { |
|
|
|
|
if (stamps[msg.data.stamp].callback) { |
|
|
|
|
stamps[msg.data.stamp].callback(msg.data.error, msg.data.result) |
|
|
|
|
return |
|
|
|
|
} |
|
|
|
|
if (msg.data.error) { |
|
|
|
|
stamps[msg.data.stamp].reject(msg.data.error) |
|
|
|
|
} else { |
|
|
|
|
stamps[msg.data.stamp].resolve(msg.data.result) |
|
|
|
|
}
|
|
|
|
|
} else if (msg.data.cmd === 'initiateResult') { |
|
|
|
|
if (!msg.data.error) { |
|
|
|
|
this.provider = { |
|
|
|
|
sendAsync: (query, callback) => { |
|
|
|
|
return new Promise((resolve, reject) => { |
|
|
|
|
const stamp = Date.now() + incr |
|
|
|
|
incr++ |
|
|
|
|
stamps[stamp] = { callback, resolve, reject } |
|
|
|
|
worker.postMessage({ cmd: 'sendAsync', query, stamp })
|
|
|
|
|
}) |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
this.web3 = new Web3(this.provider as LegacySendAsyncProvider) |
|
|
|
|
this.web3.setConfig({ defaultTransactionType: '0x0' }) |
|
|
|
|
extend(this.web3) |
|
|
|
|
this.executionContext.setWeb3(this.executionContext.getProvider(), this.web3) |
|
|
|
|
} else { |
|
|
|
|
console.error(msg.data.error) |
|
|
|
|
throw new Error(msg.data.error) |
|
|
|
|
} |
|
|
|
|
} else if (msg.data.cmd === 'newAccountResult') { |
|
|
|
|
if (this.newAccountCallback[msg.data.stamp]) { |
|
|
|
|
this.newAccountCallback[msg.data.stamp](msg.data.error, msg.data.result) |
|
|
|
|
delete this.newAccountCallback[msg.data.stamp] |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
}) |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|