New Ethereum talks, every Monday. The week's conference uploads by event, in your inbox.

Loading player…

Introduction and Demo of the Truffle Debugger by Nick D'Andrea

DevconFri, Oct 9, 2020, 12:00 AM

In the early days, the Mix debugger shared the same code base as the Solidity compiler and thus it was easy for it to retrieve required information about the internals of a smart contract. Since then, the type system and the optimizer have become way more complex and it is not as easy anymore to decipher what is going on behind the scenes. Some months ago, the Truffle team has kicked off an initiative for the compiler to provide more detailed debugging information, but debugging information is not only relevant for debuggers, but also for general analysis tools. This discussion will be about collecting needs about debugging information and starting to standardize the data format.

Transcript

I wanted to provide some background to all of the different moving parts that truffle provides for debugging and decoding and you've already seen quite a bit of the effort involved in decoding with mapping keys so to kind of give an overview of it there's a number of core components involved and the one that is perhaps most recognizable is this truffle debug command that's a command line command line debugger you give it a transaction hash and it gives you a ripple where you can type step next step over etc but this is powered by a library truffle debugger and truffle the truffle debugger library just takes like a web 3 provider and a list of compilations and gives an interface a JavaScript interface for doing that stepping and and so what truffle debug does is it just wraps this with a repple interpreter and a bunch of display logic but besides that besides our core debugger functionality we have to decode all this data and so we have two packages for doing decoding firstly we have truffle decoder which is a new high-level package you give it you know contract instance or a project and it will let you see all the state variables in that same level of detail that Harry showed with mapping keys like nested mappings nested structure raised etc truffle decoder gives an interface for getting a lossless representation of those now both of these two packages are powered under the hood by a package called truffle codec which handles all of that core decoding logic itself in a way that requires very few dependencies like the only dependencies that truffle codec requires are things like BN and and other data manipulation packages but it makes no network connections of its own it's just the standalone piece that knows how solidity organizes its storage as part of this package we need a way to you know represent these decoded values in this lossless way and so we have a sub-module codec top format which provides this lossless machine readable representation of both values and types so you can see if you're dealing with EU and 256 or u in 128 and then all of this stuff is used in several other places but most notably it's used in truffle test which today decodes events using our decoding functionality and as of tomorrow when we do a release you'll see it will report stack traces so that's kind of the those are the moving parts I can now switch over to show you a demo I'll start with the demo of the debugger just really to increase awareness since we think it's really quite robust these days and so I wanted to show off some features so I rather than write some complicated solidity code myself I decided to find a project and so I tornado cache has some pretty complicated solidity code so I decided to use that as an example and you'll see I'm going to be debugging they have a contract your t20 tornado for those of you that are not familiar tornado caches of privacy mixer mixes tokens using Merkel proofs and tornado is implemented as a base contract tornado and then it has a derived instance for ERT 20 and then in separate derived instance for F itself will be debugging ERC 20 tornado now because it's a little more interesting so if we look at contract tornado we're going to be debugging the withdraw function with draw function is defined in core NATO but we're going to be calling er t20 tornado and I'll show you where this starts what are we going to debug well I put this and this is an experimental feature we have intestine bugging where you can take any truffle contract interaction the poor might change the code look like this okay this is just a truffle test it does a tornado dot withdrawal and so for this demo I'm just going to put a debug invocation here and then we're going to do a truffle test - debug and while that's going I'll just make sure I haven't disconnected cool pardon my computer for being slow it seems to slow down with screen shares so this is starting up truffle test yeah it's doing a fresh compilation here to make sure it can get all the information it needs to actually run the debugger and this is just the tornado's tests this is they're just running so their tests print out those two addresses and then it will proceed with the tests and you'll see shortly so that's out of order okay well that's a preview of the next demo but when we get to the withdraw you'll see that this will break and get into a debugger instance any day just a quick question hi Victor here where you're adding a weight debug into that code so this is just adding specifically the debug functionality onto toreano caches already existing truffled tests that's correct yeah so truffle gives you this is it's experimental it doesn't work in all cases but it it gives you this global this debug global which wraps a truffle contract interaction so this is like tornado is a truffle contract instance and this is an existing line of code and we just wrap it and truffle test then hooks into this it's like oh you made a transaction here you go let's debug it and if you don't put the debug flag on your truffle test command it won't run this it'll give you a warning saying you use the debug global but you didn't pass the - - debug flag okay thank you and this acts as a pass through so if you continue the tests after the debugger you'll still get logs the tests will still run I'm so anyway here we're into the debugger now so why don't I pull up that contract again your seat or NATO right and we're gonna go next and immediately the debugger knows that we're no longer in the same file right withdraw is not defined by e receipt or new year C 20 tornado it's defined by the base tornado and so we have to recognize the jump from one source file to another and that's fine so I'll just hit n to step next or and we find ourselves in another file so the truffle debugger keeps track of all of this by knowing thanks to solidity source maps that they provide and our own logic to figure out you know what are the base contracts because if you look at tornado tornado itself is a derived by a derived contract of a Merkel tree with history in a reentrant C guard and it works just fine so let's let's jump to a somewhere deep in this transaction there's this verifier that is stored well first we're on this tornado contract and we have to deal with this verifier so what is that well we don't know what it is that's fine let's set a breakpoint so let's look at the verifier contract and there's a verified function somewhere in here that takes some input I don't know any how any of this stuff works it just looked complicated let's give up this so what line is this 192 so we'll set a break point for verifier that's all on line 192 and let's just step let's just continue to that point can you move up your window a little because the lower half is usually blocked by on how this thanks yep and I think it's a little off the screen too cool so we're in this verify function but how do we get here well we let's just look at the stack trace - yeah we're on verifier line 192 when we came from line 2 - 4 and from there we came from 233 we can look at all of the variables here so you notice that proof was passed in as a memory struct so what does that look like well it has a bunch of fields and need to the fields have a bunch of fields you can see that we decode those just fine if we step to the next line let's step over so we can get a value for a different memory struct see what that looks like well it's a different abstract you can see this all the codes with no problem that's where we all right we're still coming from there so let's just step up out can ask an annoying question yeah please can you step back no you can't texture supports is just never been implemented okay well supports the loose word Harry don't correct me see ya notice now that we are on two to four if we step out again we're gonna be on two three three if we step out again we're gonna get pretty close to the end of this transaction right run tornado it's all 87 and you know there's more I could show but in the effort of time I'll just show one more thing which is that if you want to see a list of all the variables that are available in scope at a particular point in time you can just type V and you can see all these this includes any decoded mapping keys that were aware of and pretty much the codes anything we can figure out called a two variables well call data pointers memory variables etc and all the various Global's are provided as well so that's pretty much it for the debugger portion of this demo does anyone have any questions before I move on to show off the chord decoding functionality I have one question let's say I have this train of contract and it's breaking somewhere else a you just you know muddled it in the code and you broke something and you call this debugger how would the debugger show you what is breaking or where it's breaking you know really yeah so as of last week's release truffle debugger will print in read the stack trace when it gets to the end of the transaction saying this is why it failed but you could step through yourself manually to kind of identify the place where it failed but hopefully the stack traces will assist that like what happens now is the stack trace is captured when there's a revert and this is all thanks to Harry's recent work when we hit a revert we figure out what the stack trace was and we save that for the end so that we can report it does that help and so I've been using truffle here and there as in development platform for testing and generally when something goes wrong there's times where I feel Oh something reverted and then I have to go through and you know manually try and figure it out I'm not very good with debugging this this is something new right this is a new feature yeah yeah so stack traces are in the debugger itself were released last week we're going to be putting this functionality into truffle tests in this week's release cool yeah so stay tuned for that I'm not I wasn't I was tempted to show off that functionality but I'll wait for the release so as for the decoder so I have some examples here I have test decoder KAS and this I freeze drip down in quartz two packages the decoder and the codec it grabs the ERC 20 tornado and then it grabs all related artifacts what do we do well we got the deployed instance then we construct a decoder and we just want to see what all the decoder variables are let's see what that looks like hold test and I'll just explicitly say I want decoder Koshchei yes and there they all are note that we know not only what the value of each of these variables is but what the inherited where which inherited contract they come from right like zeros is not defined in ERC 20 tornado it's defined inside tornado inside Merkel treat with history and you can get this information and that this is in a human readable format using our result inspector but let me show you one more example which is this Koda raw because this decoded information is represented in a machine readable format and this is to address kind of a need that we've seen in the community where existing decoders solidity data or ABI decoders they just convert to the native JavaScript types like in the JavaScript ecosystem if you use you know one of the existing decoders you're just gonna string literal and you don't know if it's a if it's supposed to be a bikes array if it's supposed to be you know static length bytes array a dynamic length bytes array and so we wanted to make sure that we could capture that information in our decoding so that we can control the presentation and you can see what that looks like so if you look at you know the token state variable token is an address so we know that we say oh it's token is of type address and it's not payable and here's the value and if you wanted as a you know as a string you can get it like that but we can also look at more complex types like verifier verifier is a contract so how do we represent that well we have a type class contract and so what is it well it's a known contract at this address I don't even know what the name of the contract is and so you can see this information provides this lossless representation so you can have this very clear window into what data is stored by your contract but more this represents this this package truffle code I can travel decoder they can be used not only to look at state variables just for this demo I just state variables but we also use it to decode events we can use it to decode return values revert strings and inside the debugger we use it to decode values on the stack and memory storage etc and we have a question make oh please hmm NX does the debugger support assembly blocks eg displaying variables from assembly books I guess even the tornado code may have it for calling the pairing pre-compile uh harry does the debuggers if the debugger will step through assembly both variable yes the decoder does not currently support displaying assembly variables yes I mean I guess it's so I noticed that recently I did I wasn't paying attention to this until recently I noticed recently the format for in the ast for assembly stuff changed so that now that might actually be possible but the old format that wouldn't really have been possible but um yeah that's limp that's something I could look into yeah yeah and then the next question would be any plans for supporting assembly Mariah's yeah that's totally something I could look into absolutely

Automatic transcript — names and jargon may be misspelled.