1"use strict";(globalThis.webpackChunkdocs=globalThis.webpackChunkdocs||[]).push([[647],{96837(e,n,t){t.d(n,{Ay:()=>o});var i=t(74848),s=t(28453);function r(e){const n={a:"a",admonition:"admonition",p:"p",strong:"strong",...(0,s.R)(),...e.components};return(0,i.jsxs)(n.admonition,{title:"Experimental Feature",type:"caution",children:[(0,i.jsx)(n.p,{children:"This feature is experimental. The documentation may be incomplete or out of date, which means it could change in future versions, potentially causing unexpected behavior or not working as expected."}),(0,i.jsxs)(n.p,{children:[(0,i.jsx)(n.strong,{children:"Contributions Welcome:"})," If you notice any inaccuracies or potential improvements, please consider contributing. Visit our GitHub repository to make your contributions: ",(0,i.jsx)(n.a,{href:"https://github.com/noir-lang/noir",children:"Contribute Here"}),"."]})]})}function o(e={}){const{wrapper:n}={...(0,s.R)(),...e.components};return n?(0,i.jsx)(n,{...e,children:(0,i.jsx)(r,{...e})}):r(e)}t.d(n,["RM",0,[]])},37890(e,n,t){t.r(n),t.d(n,{assets:()=>a,contentTitle:()=>d,default:()=>h,frontMatter:()=>c,metadata:()=>i,toc:()=>u});const i=JSON.parse('{"id":"guides/debugging/debugging_with_the_repl","title":"Using the REPL Debugger","description":"Step-by-step guide on how to debug your Noir circuits with the REPL Debugger.","source":"@site/versioned_docs/version-v1.0.0-rc.1/guides/debugging/debugging_with_the_repl.mdx","sourceDirName":"guides/
1debugging","slug":"/guides/debugging/debugging_with_the_repl","permalink":"/docs/v1.0.0-rc.1/guides/debugging/debugging_with_the_repl","draft":false,"unlisted":false,"editUrl":"https://github.com/noir-lang/noir/edit/master/docs/versioned_docs/version-v1.0.0-rc.1/guides/debugging/debugging_with_the_repl.mdx","tags":[],"version":"v1.0.0-rc.1","frontMatter":{"title":"Using the REPL Debugger","description":"Step-by-step guide on how to debug your Noir circuits with the REPL Debugger.","keywords":["Nargo","Noir CLI","Noir Debugger","REPL"]},"sidebar":"sidebar","previous":{"title":"Using the VS Code Debugger","permalink":"/docs/v1.0.0-rc.1/guides/debugging/debugging_with_vs_code"},"next":{"title":"Thinking in Circuits","permalink":"/docs/v1.0.0-rc.1/guides/thinking_in_circuits"}}');var s=t(74848),r=t(28453),o=t(96837);const c={title:"Using the REPL Debugger",description:"Step-by-step guide on how to debug your Noir circuits with the REPL Debugger.",keywords:["Nargo","Noir CLI","Noir Debugger","REPL"]},d=void 0,a={},u=[...o.RM,{value:"Pre-requisites",id:"pre-requisites",level:4},{value:"Debugging a simple circuit",id:"debugging-a-simple-circuit",level:2},{value:"Debugging a test function",id:"debugging-a-test-function",level:2},{value:"Test result",id:"test-result",level:3}];function l(e){const n={a:"a",code:"code",h2:"h2",h3:"h3",h4:"h4",p:"p",pre:"pre",...(0,r.R)(),...e.components};return(0,s.jsxs)(s.Fragment,{children:[(0,s.jsx)(o.Ay,{}),"\n",(0,s.jsx)(n.h4,{id:"pre-requisites",children:"Pre-requisites"}),"\n",(0,s.jsx)(n.p,{children:"In order to use the REPL debugger, first you need to install recent enough versions of Nargo."}),"\n",(0,s.jsx)(n.h2,{id:"debugging-a-simple-circuit",children:"Debugging a simple circuit"}),"\n",(0,s.jsx)(n.p,{children:"Let's debug a simple circuit:"}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-rust",children:"fn main(x : Field, y : pub Field) {\n assert(x != y);\n}\n"})}),"\n",(0,s.jsx)(n.p,{children:"To start the REPL debugger, using a terminal, go to a Noir circuit's home directory. Then:"}),"\n",(0,s.jsx)(n.p,{children:(0,s.jsx)(n.code,{children:"$ nargo debug"})}),"\n",(0,s.jsx)(n.p,{children:"You should be seeing this in your terminal:"}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{children:"[main] Starting debugger\nAt ~/noir-examples/recursion/circuits/main/src/main.nr:1:9\n 1 -> fn main(x : Field, y : pub Field) {\n 2 assert(x != y);\n 3 }\n>\n"})}),"\n",(0,s.jsx)(n.p,{children:"The debugger displays the current Noir code location, and it is now waiting for us to drive it."}),"\n",(0,s.jsxs)(n.p,{children:["Let's first take a look at the available commands. For that we'll use the ",(0,s.jsx)(n.code,{children:"help"})," command."]}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{children:"> help\nAvailable commands:\n\n opcodes display ACIR opcodes\n into step into to the next opcode\n next step until a new source location is reached\n out step until a new source location is reached\n and the current stack frame is finished\n break LOCATION:OpcodeLocation add a breakpoint at an opcode location\n over step until a new source location is reached\n without diving into function calls\n restart restart the debugging session\n delete LOCATION:OpcodeLocation delete breakpoint at an opcode location\n witness show witness map\n witness index:u32 display a single witness from the witness map\n witness index:u32 value:String update a witness with the given value\n memset index:usize value:String update a memory cell with the given\n value\n continue continue execution until the end of the\n program\n vars show variable values available at this point\
1n in execution\n stacktrace display the current stack trace\n memory show memory (valid when executing unconstrained code)\n step step to the next ACIR opcode\n\nOther commands:\n\n help Show this help message\n quit Quit repl\n\n"})}),"\n",(0,s.jsxs)(n.p,{children:["Some commands operate only for unconstrained functions, such as ",(0,s.jsx)(n.code,{children:"memory"})," and ",(0,s.jsx)(n.code,{children:"memset"}),". If you try to use them while execution is paused at an ACIR opcode, the debugger will simply inform you that you are not executing unconstrained code:"]}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{children:"> memory\nUnconstrained VM memory not available\n>\n"})}),"\n",(0,s.jsx)(n.p,{children:"Before continuing, we can take a look at the initial witness map:"}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{children:"> witness\n_0 = 1\n_1 = 2\n>\n"})}),"\n",(0,s.jsxs)(n.p,{children:["Cool, since ",(0,s.jsx)(n.code,{children:"x==1"}),", ",(0,s.jsx)(n.code,{children:"y==2"}),", and we want to check that ",(0,s.jsx)(n.code,{children:"x != y"}),", our circuit should succeed. At this point we could intervene and use the witness setter command to change one of the witnesses. Let's set ",(0,s.jsx)(n.code,{children:"y=3"}),", then back to 2, so we don't affect the expected result:"]}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{children:"> witness\n_0 = 1\n_1 = 2\n> witness 1 3\n_1 = 3\n> witness\n_0 = 1\n_1 = 3\n> witness 1 2\n_1 = 2\n> witness\n_0 = 1\n_1 = 2\n>\n"})}),"\n",(0,s.jsxs)(n.p,{children:["Now we can inspect the current state of local variables. For that we use the ",(0,s.jsx)(n.code,{children:"vars"})," command."]}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{children:"> vars\n>\n"})}),"\n",(0,s.jsxs)(n.p,{children:["We currently have no vars in context, since we are at the entry point of the program. Let's use ",(0,s.jsx)(n.code,{children:"next"})," to execute until the next point in the program."]}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{children:"> vars\n> next\nAt ~/noir-examples/recursion/circuits/main/src/main.nr:1:20\n 1 -> fn main(x : Field, y : pub Field) {\n 2 assert(x != y);\n 3 }\n> vars\nx:Field = 0x01\n"})}),"\n",(0,s.jsxs)(n.p,{children:["As a result of stepping, the variable ",(0,s.jsx)(n.code,{children:"x"}),", whose initial value comes from the witness map, is now in context and returned by ",(0,s.jsx)(n.code,{children:"vars"}),"."]}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{children:"> next\n 1 fn main(x : Field, y : pub Field) {\n 2 -> assert(x != y);\n 3 }\n> vars\ny:Field = 0x02\nx:Field = 0x01\n"})}),"\n",(0,s.jsx)(n.p,{children:"Stepping again we can finally see both variables and their values. And now we can see that the next assertion should succeed."}),"\n",(0,s.jsx)(n.p,{children:"Let's continue to the end:"}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{children:"> continue\n(Continuing execution...)\nFinished execution\n> q\n[main] Circuit witness successfully solved\n"})}),"\n",(0,s.jsxs)(n.p,{children:["Upon quitting the debugger after a solved circuit, the resulting circuit witness gets saved, equivalent to what would happen if we had run the same circuit with ",(0,s.jsx)(n.code,{children:"nargo execute"}),"."]}),"\n",(0,s.jsxs)(n.p,{children:["We just went through the basics of debugging using Noir REPL debugger. For a comprehensive reference, check out ",(0,s.jsx)(n.a,{href:"/docs/v1.0.0-rc.1/tooling/debugger/debugger_repl",children:"the reference page"}),"."]}),"\n",(0,s.jsx)(n.h2,{id:"debugging-a-test-function",children:"Debugging a test function"}),"\n",(0,s.jsx)(n.p,{children:"Let's debug a simple test:"}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-rust",children:'#[test]\nfn test_simple_equal() {\n let x = 2;\n let y = 1 + 1;\n assert(x == y, "should be equal");\n}\n'})}),"\n",(0,s.jsxs)(n.p,{children:["To debug a test function using the REPL debugger, navigate to a Noir project directory inside a terminal, and run the ",(0,s.jsx)(n.code,{children:"nargo debug"})," command passing the ",(0,s.jsx)(n.code,{children:"--test-name your_test_name_here"})," argument."]}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-bash",children:"nargo debug --test-name test_simple_equal\n"})}),"\n",(0,s.jsx)(n.p,{children:"After that, the debugger has started and works the same as debugging a main function, you can use any of the above explained commands to control the execution of the test function."}),"\n",(0,s.jsx)(n.h3,{id:"test-result",children:"Test result"}),"\n",(0,s.jsxs)(n.p,{children:["The debugger does not end the session automatically. Once you finish debugging the execution of the test function you will notice that the debugger remains in the ",(0,s.jsx)(n.code,{children:"Execution finished"})," state. When you are done debugging the test function you can exit the debugger by using the ",(0,s.jsx)(n.code,{children:"quit"}
1)," command. Once you finish the debugging session you should see the test result."]}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-text",children:"$ nargo debug --test-name test_simple_equal\n[simple_noir_project] Starting debugger\nAt opcode 0:0 :: BRILLIG CALL func 0: inputs: [], outputs: []\n> continue\n(Continuing execution...)\nFinished execution\n> quit\n[simple_noir_project] Circuit witness successfully solved\n[simple_noir_project] Testing test_simple_equal... ok\n"})})]})}function h(e={}){const{wrapper:n}={...(0,r.R)(),...e.components};return n?(0,s.jsx)(n,{...e,children:(0,s.jsx)(l,{...e})}):l(e)}},28453(e,n,t){t.d(n,{R:()=>o,x:()=>c});var i=t(96540);const s={},r=i.createContext(s);function o(e){const n=i.useContext(r);return i.useMemo(function(){return"function"==typeof e?e(n):{...n,...e}},[n,e])}function c(e){let n;return n=e.disableParentContext?"function"==typeof e.components?e.components(s):e.components||s:o(e.components),i.createElement(r.Provider,{value:n},e.children)}}}]);
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.