ckb_debugger/
machine_assign.rs1use ckb_script::{CoreMachine as CkbScriptCoreMachineType, DataLocation, ROOT_VM_ID, RunMode, Scheduler, VmArgs};
2use ckb_traits::{CellDataProvider, ExtensionProvider, HeaderProvider};
3use ckb_vm::cost_model::estimate_cycles;
4use ckb_vm::decoder::Decoder;
5use ckb_vm::instructions::execute;
6use ckb_vm::registers::A7;
7use ckb_vm::{Bytes, CoreMachine, Error, Machine, SupportMachine, Syscalls};
8
9pub struct MachineAssign<DL>
10where
11 DL: CellDataProvider + HeaderProvider + ExtensionProvider + Send + Sync + Clone + 'static,
12{
13 pub id: u64,
14 pub scheduler: Scheduler<DL>,
15 pub expand_cycles: u64,
16 pub expand_syscalls: Vec<Box<(dyn Syscalls<CkbScriptCoreMachineType>)>>,
17}
18
19impl<DL> CoreMachine for MachineAssign<DL>
20where
21 DL: CellDataProvider + HeaderProvider + ExtensionProvider + Send + Sync + Clone + 'static,
22{
23 type REG = u64;
24 type MEM = <CkbScriptCoreMachineType as CoreMachine>::MEM;
25
26 fn pc(&self) -> &Self::REG {
27 let dm = &self.scheduler.instantiated.get(&self.id).unwrap().1.machine;
28 dm.pc()
29 }
30
31 fn update_pc(&mut self, pc: Self::REG) {
32 let dm = &mut self.scheduler.instantiated.get_mut(&self.id).unwrap().1.machine;
33 dm.update_pc(pc)
34 }
35
36 fn commit_pc(&mut self) {
37 let dm = &mut self.scheduler.instantiated.get_mut(&self.id).unwrap().1.machine;
38 dm.commit_pc()
39 }
40
41 fn memory(&self) -> &Self::MEM {
42 let dm = &self.scheduler.instantiated.get(&self.id).unwrap().1.machine;
43 dm.memory()
44 }
45
46 fn memory_mut(&mut self) -> &mut Self::MEM {
47 let dm = &mut self.scheduler.instantiated.get_mut(&self.id).unwrap().1.machine;
48 dm.memory_mut()
49 }
50
51 fn registers(&self) -> &[Self::REG] {
52 let dm = &self.scheduler.instantiated.get(&self.id).unwrap().1.machine;
53 dm.registers()
54 }
55
56 fn set_register(&mut self, idx: usize, value: Self::REG) {
57 let dm = &mut self.scheduler.instantiated.get_mut(&self.id).unwrap().1.machine;
58 dm.set_register(idx, value)
59 }
60
61 fn version(&self) -> u32 {
62 let dm = &self.scheduler.instantiated.get(&self.id).unwrap().1.machine;
63 dm.version()
64 }
65
66 fn isa(&self) -> u8 {
67 let dm = &self.scheduler.instantiated.get(&self.id).unwrap().1.machine;
68 dm.isa()
69 }
70}
71impl<DL> SupportMachine for MachineAssign<DL>
72where
73 DL: CellDataProvider + HeaderProvider + ExtensionProvider + Send + Sync + Clone + 'static,
74{
75 fn cycles(&self) -> u64 {
76 let dm = &self.scheduler.instantiated.get(&self.id).unwrap().1.machine;
77 dm.cycles()
78 }
79
80 fn set_cycles(&mut self, cycles: u64) {
81 let dm = &mut self.scheduler.instantiated.get_mut(&self.id).unwrap().1.machine;
82 dm.set_cycles(cycles)
83 }
84
85 fn max_cycles(&self) -> u64 {
86 let dm = &self.scheduler.instantiated.get(&self.id).unwrap().1.machine;
87 dm.max_cycles()
88 }
89
90 fn set_max_cycles(&mut self, cycles: u64) {
91 let dm = &mut self.scheduler.instantiated.get_mut(&self.id).unwrap().1.machine;
92 dm.set_max_cycles(cycles);
93 }
94
95 fn running(&self) -> bool {
96 let dm = &self.scheduler.instantiated.get(&self.id).unwrap().1.machine;
97 dm.running()
98 }
99
100 fn set_running(&mut self, running: bool) {
101 let dm = &mut self.scheduler.instantiated.get_mut(&self.id).unwrap().1.machine;
102 dm.set_running(running)
103 }
104
105 fn reset(&mut self, max_cycles: u64) {
106 let dm = &mut self.scheduler.instantiated.get_mut(&self.id).unwrap().1.machine;
107 dm.reset(max_cycles)
108 }
109
110 fn reset_signal(&mut self) -> bool {
111 let dm = &mut self.scheduler.instantiated.get_mut(&self.id).unwrap().1.machine;
112 dm.reset_signal()
113 }
114
115 fn code(&self) -> &Bytes {
116 let dm = &self.scheduler.instantiated.get(&self.id).unwrap().1.machine;
117 dm.code()
118 }
119}
120
121impl<DL> Machine for MachineAssign<DL>
122where
123 DL: CellDataProvider + HeaderProvider + ExtensionProvider + Send + Sync + Clone + 'static,
124{
125 fn ecall(&mut self) -> Result<(), Error> {
126 let dm = &mut self.scheduler.instantiated.get_mut(&self.id).unwrap().1.machine;
127 for i in 0..self.expand_syscalls.len() {
128 if self.expand_syscalls[i].ecall(dm.inner_mut())? {
129 return Ok(());
130 }
131 }
132 let dm = &mut self.scheduler.instantiated.get_mut(&self.id).unwrap().1.machine;
133 let result = dm.ecall();
134 let cycles = dm.cycles();
135 let sid = dm.registers()[A7];
136 if result == Err(Error::Yield) {
137 dm.set_cycles(0);
138 self.scheduler.iterate_process_results(self.id, Err(Error::Yield))?;
139 self.consume_cycles(cycles)?;
140 self.wait()?;
141 if sid == 2043 {
142 let dm = &mut self.scheduler.instantiated.get_mut(&self.id).unwrap().1.machine;
144 dm.set_running(true)
145 }
146 return Ok(());
147 }
148 if sid == 93 {
149 dm.set_cycles(0);
150 self.consume_cycles(cycles)?;
151 return Ok(());
152 }
153 result
154 }
155
156 fn ebreak(&mut self) -> Result<(), Error> {
157 let dm = &mut self.scheduler.instantiated.get_mut(&self.id).unwrap().1.machine;
158 dm.ebreak()
159 }
160}
161
162impl<DL> std::fmt::Display for MachineAssign<DL>
163where
164 DL: CellDataProvider + HeaderProvider + ExtensionProvider + Send + Sync + Clone + 'static,
165{
166 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
167 let dm = &self.scheduler.instantiated.get(&self.id).unwrap().1.machine;
168 dm.fmt(f)
169 }
170}
171
172impl<DL> MachineAssign<DL>
173where
174 DL: CellDataProvider + HeaderProvider + ExtensionProvider + Send + Sync + Clone + 'static,
175{
176 pub fn new(id: u64, args: &[Bytes], scheduler: Scheduler<DL>) -> Result<Self, Error> {
177 let mut r = Self { id, scheduler, expand_cycles: u64::MAX, expand_syscalls: vec![] };
178 if r.scheduler.states.is_empty() {
179 let location = DataLocation {
180 data_piece_id: r.scheduler.sg_data.sg_info.program_data_piece_id.clone(),
181 offset: 0,
182 length: u64::MAX,
183 };
184 assert_eq!(r.scheduler.boot_vm(&location, VmArgs::Vector(args.to_vec()))?, ROOT_VM_ID);
185 }
186 Ok(r)
187 }
188
189 pub fn consume_cycles(&mut self, cycles: u64) -> Result<(), Error> {
190 self.scheduler.consume_cycles(cycles)?;
191 self.expand_cycles = self.expand_cycles.checked_sub(cycles).ok_or(Error::CyclesExceeded)?;
192 Ok(())
193 }
194
195 pub fn exit_code(&self) -> i8 {
196 let root_vm = &self.scheduler.instantiated[&ROOT_VM_ID];
197 root_vm.1.machine.exit_code()
198 }
199
200 pub fn step(&mut self, decoder: &mut Decoder) -> Result<(), Error> {
201 let instruction = {
202 let pc = *self.pc();
203 let memory = self.memory_mut();
204 decoder.decode(memory, pc)?
205 };
206 let cycles = estimate_cycles(instruction);
207 self.add_cycles(cycles)?;
208 execute(instruction, self)
209 }
210
211 pub fn wait(&mut self) -> Result<(), Error> {
212 loop {
213 let im = self.scheduler.iterate_prepare_machine()?;
214 let id = im.0;
215 let vm = im.1;
216 if self.id == id {
217 break;
218 }
219 let result = vm.run();
220 let cycles = vm.machine.cycles();
221 vm.machine.set_cycles(0);
222 self.scheduler.iterate_process_results(id, result)?;
223 self.consume_cycles(cycles)?;
224 }
225 Ok(())
226 }
227
228 pub fn done(&mut self) -> Result<(), Error> {
229 let dm = &mut self.scheduler.instantiated.get_mut(&self.id).unwrap().1.machine;
230 let dmexit = dm.exit_code();
231 self.scheduler.iterate_process_results(self.id, Ok(dmexit))?;
232 self.scheduler.run(RunMode::LimitCycles(self.expand_cycles))?;
233 return Ok(());
234 }
235}