 All right, I'm so glad to be back in San Francisco I I think there are a few places in the world where I would be introduced into a Japanese founded Workshop hacker space Gathering people talking about Bitcoin development and Bitcoin scripting with a phrase. I will sprinkle some lube So Today's talk is different from some of the other talks I've done so bear with me We're gonna do this kind of slowly and in a very casual manner. This is not One of my usual talks where I'm gonna tell you about big picture vision and stuff like that So I'm going to do a very quick introduction to some of the fundamentals of Bitcoin script And then we're gonna dive into some more advanced topics around conditionals and flow control and guard clauses time locks All the way up to if we get to it Some of the scripts you see in Lightning part of what I'm gonna be talking about is some of the new content from the second edition of Mastering Bitcoin as you probably know that book as with the first edition was written on GitHub in public all the laundry out in public everything for everyone to see and criticize and Notice all of the horrific mistakes. I made hopefully do pull requests before it goes into final production Which is next week hint hint? I will also be saying some things here tonight that are wrong Extra points if one you notice And to you send me a message afterwards and help me fix them in the book If I do say things here that are wrong It's because I don't know they're wrong, which is why I need your help if you do know they're wrong That's really what I could use So no promises any of this is gonna work or that is correct But it will give you some greater insights into how Bitcoin script works So let's get started. I'm gonna use the whiteboard most thing Bitcoin script is a forth like stack based Language that uses a reverse Polish notation. How many people did I lose? So far, okay And what that means is that it uses as its fundamental elements stack and The stack evaluates Functions or script operands in the opposite order than you would expect The parameters of functions or operators come before the operators themselves so an example of reverse Polish notation script is Let's say you want to do one plus one Okay, start with the easy stuff. How do you write that? It's one one plus And the reason it's like that is because this gets evaluated Evaluated through a stack Oops a stack is a data structure where you push things into the stack or you pop things from the stack Think of a stack of Dishes, right? You can only access the top most dish in order to get the one below it You have to pop off the top one and then you get to the second one, right? So if you want to evaluate this and I'll use this notation, which is the one I use in my book So let's say this is the stack, right? So the system will start by evaluating the first item in the script and If it's just a number it gets pushed on to the stack So the one goes here Script pointer moves the next item Goes here got another one push that onto the stack great Now we've got one item on the stack, which is the plus operator Now when you get to an operator Usually an operator takes a few parameters the plus operator takes put two parameters the two things it's adding together Where does it find those two parameters? It pops two items off the stack So a plus operator is to find us an operator that pops two items off a stack adds them together and pushes the result Back onto the stack, right? So pop pop add push pop pop add Them together and push the result onto the stack And the program terminates That's how you do one plus one is two It's a bit weird, right? Okay, now in Bitcoin the Scripting language works like this. We often use the prefix off to denote operators so in Bitcoin script this would look like off one off one all app and and off one just pushes one to the stack and off one pushes one to the stack not bad pops two items adds them together and pushes The result onto the stack the end result is to same thing right for the rest of these examples. I will not use the off prefix it's implied The only reason the off prefix exists there is because in the actual code that implements Bitcoin For example Bitcoin core or Bitcoin or the Bitcoin The variables that are used to denote these operators are written with the prefix up many programming languages Actually don't allow you to start a variable with a number They require the first Part of a variable name to be a letter So hence prefix off underscore whatever right, but it's redundant everything has off underscore in front of this We just drop it from everything when we continue this conversation so far so good. Who's with me? Hey, very good Okay, who's familiar with a paid-to-public key hash script? I'm gonna run through an execution of that further quickly when in Bitcoin you create a transaction that says Alice pays Bob one Bitcoin for a cup of coffee in the Bitcoin transaction What you get instead is a bunch of Alice's inputs with some signatures to an output that identifies Bob's address as the destination pay Right, maybe some change as well. Let's ignore that for now And how does it identify the Bob's address with a script format called pay to? public key hash P2 PKH Okay, and the way that looks on the stack is Doop, which stands for a duplicate hash 160 Bob's public key hash equal check sync Not strictly necessary to do all of this There are reasons why it's done in this particular way Some of the first transactions if you look at the coinbase for example of the first several hundred blocks The point base is not paid like this. It's paid simply with a public key check-sick Right problem with a public key check-sick format if you just use the last part You just put Bob's public key checks it is that you've revealed Bob's public key in the output Before Bob has had a chance to reveal it to redeem it That's dangerous if there's ever a problem with elliptic curve And you can take a public key and reverse it back to a private key is a quantum computing Maybe you don't want all the public keys to be known This format actually preserves it behind a double hash, which is a hell of a lot harder to break Okay So you've got two layers of obfuscation there. There's other reasons why you would use a hash as well We'll see that in a bit, but this is the script So every time you do a Bitcoin transaction if we all pull out our Bitcoin wallets and our smartphones right now we start Sending stuff to each other's QR codes and sending transactions Your woods creating a bunch of transactions on the Bitcoin blockchain that will all have this script Which is called P2PKH They will all have this script in the output All right How do you redeem this script? So you put you provide Two parameters to this let's say you're Bob you want to spend this You put Bob sick and Bob Hubkey So when you put these two things they actually get executed in sequence before this is verified So let's say I'm Bob. I want to spend this. This is the signature. I'm going to provide this goes in the script sake So I want to spend this here is my Signature it'll be two parts signature and your public key Then you put that in the transaction want to spend and then the system evaluates is Bob really authorized to spend this Particular output. How do we know? Well, let's run this through the scripting language first And then let's run that through the scripting language. And if the final outcome is true Don't you get the big if it's false or anything else? Invalid transaction good everybody with me so far great. What happens when you? Evaluate these two things through the scripting language These things are numbers. They get pushed onto the stack So pops it goes to the bottom and Bob popkey goes above it this is the state of the stack when the Locking script is evaluated So our locking script has been pushed onto the stack Locking script is in the script execution engine and now we start running to see if this is a valid Signer for this output if Bob is in fact allowed to spend this Who wants to try running this? So first stack in the first script execution item we have is Duke Oh, also all underscore Duke. I'm taking out the ops right so up to Okay, what does that do it takes how many parameters off the stack one? What it pops one parameter off the stack, but what does it do? It duplicates it and then it pushes two parameters back onto the stack. Yes, so far so good great. So we run Duke Bob's pub key gets popped off the stack and then gets pushed back on the stack twice I'd erase the bottom one and write both of them again But I'm lazy and you know what I'm talking about So now you've got two copies of Bob's public key on the stack and we move to the next item in the script execution And who wants to run the next one? anybody yes well Very good execution pointer is here. I'm guessing it takes one input Takes one input produces one output great. So the first input it takes is Bob pop key What does it do to it? It pops it very good. So pop And it does the hash 160 operation who wants to tell me what the hash 160 operation is It's actually two hashes and more It's a sha 256 wrapped in a ripe MD 160. It's a double hash It is in fact the same hatching operation that goes into constructing a Bitcoin address also known as a public key hash So hash 160 took Bob's public key Hashes it through 256 shout 256 hashes it through ripe MD 160 and produces a 160 bit Public key hash as a result that gets pushed back on to the stack. Let's call that Bob's public key Bob pH Now at this point if all has gone. Well If Bob's public key was in fact the one that Alice was paying these two Should be the same. So let's move to the next point in the stack. This is gone This is now in the script execution execution point who goes here first thing on the step on the script execution It's a number. What do we do in numbers? We push them on a stack. I'll just move these things up very good Who wants to take equal ring? That's an easy one come on. Yes So equal takes two parameters it pops those from the stack now Bob pcage Bob pcage two copies of the same thing Yes Very good next up Yep, which will take one parameter two Well, actually, sorry Let me have this wrong you can help me out here It's equal verify very good. So this isn't equal It's equal verify Why is it equal verify? What's the difference between equal and equal verify? And if it's true it doesn't push this on let's carry on check say Check say pops these two items off the stack and it says is this a signature For this public key and the way it does that is using the elliptic curve Digital signature algorithm to do a signature verification against the public key Now here's an interesting thing This is really important to realize How does it know What's being signed There's some implicit data So I've written a simplification of what's happening here Check say actually takes more than these parameters first of all Bob's signature Consists of three parts It consists of an r value an s value and the sick hash type The sick hash type may be sick hash all sick have singles sick hash only whatever One of those sick hash types. What is the sick hash type do it tells check sick? There's a transaction also in Your data space you take that transaction and if it's sick hash all you create a hash based on a very specific Recipe by mixing together all of the inputs and all of the outputs if it's sick hash single Then it says you create a hash for this input and this output only Right So in here implicit is something that tells check sick which part of the transactions is going to fingerprint So I can check the signature Against the public key against that specific hash So what's being signed is the hash and how you construct that hash Depends on whether this is a sick hash all or some other type of signature Have I lost the rest of the room? Slowly all right Because 160 is the ripe MD 160 which produces the 160 bits which is the final hash to apply So the output of hash 160 is the output of ripe MD But it also internally does a shout to 56. All good. What's up? Oh Very good All right, so is everybody with me so far Okay, now we've demonstrated. I've demonstrated poorly but To a level that maybe you understood a bit how the script is executed on the stack by pushing things You notice they go in reverse order right the first thing that gets pushed is the last thing that comes off Right, so when you have a function in a script it acts on the things that are closest to it Because those get pushed onto the stack class and Then later things in the script act on Parts of the script that are furthest from it because those are the first things that get pushed on the stack, right? So first you move with the parameters in do something with them create new parameters Do something with them create new parameters do something with them And then there may be some leftovers at the bottom they get picked up at the end Yeah, that's a common thing So when you're looking at a script, it's not always easy when you look at it to figure out which part is acting on Which other parts of data because you have to visualize The sequence of pushing things and popping things on to and off of the stack and it depends on how many parameters are being pushed and popped By each of the intermediate commands Everyone with me so far Great, so I'm not going to draw the stack again. What I'm going to do instead is draw some scripts so We talked briefly about the suffix verify Does anybody remember which of the op quotes have a suffix that can be verified? Equal So equal comes in two forms Next anyone Check say So again, you have check say that only comes in one form. We'll get to that in a bit Multi-sig check multi-sig So each of these comes in two forms both with and without verify So can someone has anyone figured out exactly the difference between the two Where would you use one? Where would you use the other? Yes? Correct so very anything that has verify will only continue execution of the script if the outcome of the Conditional operator is true in which case it will not push that true back to the stack And it will simply continue execution. Otherwise Equal check say then check multi-sig put the outcome true false on the stack And whether it's true or false you then have to further down decide what to do with that Maybe afterwards you could do something To verify that it's true But that's not really useful because you would do it right there You could use equal it could be more cumbersome now Not much point in using these at the end of a script Because the end of the script acts like a verify meaning that when you reach the end of the script if True is on the stack You're good. The lock script has been unlocked If anything other than true is on the stack Your script terminates with a false done that locking script has not been satisfied So effectively the end of the script acts as a verify Meaning that you can comfortably put equal check-sig or check multi-sig at the end of a script because the verify is implied right afterwards the reason you would use the Equal verify check-sig verify or check multi-sig verify is If you're putting it earlier in the script You don't want to leave anything on the stack and you want to terminate like this is a kill clause You're not going to worry about whether this is true or false if it's false You're done. You're not going to evaluate anything else Yes Okay, does anybody remember in programming what we call clauses that decide whether the following part of the language is going to be executed or not Anybody if clauses well, yeah, it's a very specific type of an if clause Yes, I think they're called guard clauses. It's called a guard clause so a guard clause is if The previous thing was true then do this So this part only gets executed if you pass by the guard to gatekeepers It says this code only gets executed under a specific condition guard clauses are used extensively in programming For one simple reason. They're very easy to read and very clean We use them in formal languages especially languages where bugs are very dangerous The reason we use guard clauses is because if you wrap Code in a simple guard clause That code will not run If the guard clause is not satisfied, right? So you see that all the time if debug prints to log file Right and all you're doing is turning on or off that functionality when there's a debug Right, otherwise the print to log file never happens If debug mode asserts zero That's the guard clause that should have been in that line and Bitcoin unlimited but wasn't So guard clauses are useful because they simply preclude the execution of the next thing We'll see how we use them in the next section So there's that there's a specific type of command That only has a verify Version and that's time locks the two forms of script based time loss check lock time verify check sequence verify There is no check lock time without verify. There is no check sequence without verify There is a very good reason for that. It actually makes it rather difficult to write scripts that run That are valid now, but not valid in the future You can only write scripts that are invalid and till an event, but from that point to infinity This is the liberty time locks allow you to activate a transaction, but not expire it Once something becomes valid. It is valid forever. This is consistent throughout Bitcoin There's no such thing as a script that is valid today that is not valid tomorrow unless the consensus rules change, right? transactions do not expire and Scripts do not expire and as a result check lock time is written in such a way that you can't say Not if and Then run something afterwards to invert its meaning So check lock time verify for example means this is valid only after block 1,000 you can't invert its meaning and say this is valid only before block 1,000 and not after because The verify doesn't let you evaluate the outcome. It simply stops Does that make sense? Now you can get around that, but it's not easy It's not easy. You have to use something called a revocation All right, who's with me so far? Who's still having fun? This is the geeky meetup. I love it so The verify clause at the end of an operator is a form of a conditional right and It's also a form of flow control. It's the same as writing if true Do what comes after? Else return Right return the return code in Bitcoin causes the script to terminate All right, and does not evaluate true its value is false. Well done. If you find a return in your script and run it Right, so verify is the same as saying if true do this else return But it's a much more compact form and we'll see how that works Okay, so the most useful form of Conditional is a flow control statement and a flow control says statement is an if then else statement Everybody familiar with if then else Yes In in Silicon Valley what we call if then else we call it AI For many programmers AI is 100,000 if then else is concatenated together that evaluate all the possible way something might work I wrote an interpretive interactive Psychiatrists called Eliza in college as a very weak AI that would interact and have a conversation with you and it consisted A lot of if then else Trying to figure out what the hell you were saying in English So if then else statements now this is Bitcoin, of course So take what you know about if then else Spring is weird on it and we get Bitcoin If else and if This is what it looks like in bit so in the Bitcoin script you have If else and if What is a? Anyone a condition you would assume so this is where the weird comes in second best guess Yes It's the code that gets executed if the condition is true So this is the then part You can assume that here. There's a then just to make it easier to read If true then a else B That's how it actually runs So you start reading Bitcoin script you see and if you assume the very next thing is the thing that you're testing It is not The very next thing is the thing you're executing if the thing you tested was true Then there's an L statement or not. They might just be an end if Then there's the thing that runs if it was false Then there's an end if So far so good Where the hell is the condition? Before the if So actually the way this works is It looks like this X is the is the condition so the way this reads is if x then a else B and If problem is the x isn't in the script The x isn't in the locking script it almost Never is it's not as a literal for sure there might be other stuff before there in which case whatever they put on the stack Maybe they put a true or false so if you had an equal here Equal gets evaluated it dumps true or false on the stack if gets evaluated it takes the true or false from the equal So they're saying if equal then a else B So if this X was an equal operator It took whatever two things were on the stack before weigh them together if they were equal this part runs if they were different this part runs Yes So you can actually take an equal verify and write it as equal if what comes after else return and if It's a rather long-winded way of writing the same thing But very often in scripts There is no X and this gets very confusing because you read the script and you think Well, it's just English right programming is just English So if a is true Then I'm not quite sure but else B Right, and that's not what this script does and the first thing you come across conditional flows In Bitcoin script your natural inclination is to read it So you read for example if something check lock time verify something check sig and you think oh it's checking the check lock time It's not The condition came before But it's not on the script. So where the hell is it and why is it not on the script? Is You're doing reverse pole notation. So first it has to get pushed which means it comes before the function that actually uses it Yes But why not put it before the if write in the locking script? There's a very good reason for that because if the condition is in the locking script then You put it in place when the UTXO is created and it only ever has one value the one you put there And therefore the rest of the script is pointless Because if this was something that evaluates to true and you put it in the locking script, then it will always run a And if it was false and you put it in the locking script, it will always run B So why the hell do you have the ifs there? Why don't you just get rid of all that and just say a or B? The reason you can't put the condition in the script is because the script gets recorded on the blockchain and Is immutable and is the part that gets executed every time in exactly the same way So whatever you put there will always evaluate to either true or false will always run a or B and Therefore if you put it in the locking script, you're just wasting space right This is a variable so you need to put it in the part of the scripting language that's variable and that's the unlocking script Which means that the person's spending Provides the condition. Oh, that's weird and So this comes to the basic understanding of what conditional flow does in Bitcoin What that says is this is locked this simple locking script if it was exactly like this it says This can be spent two ways and You choose You show up with an unlocking script that leaves true on the stack. We're gonna try and spend this with method a You show up with an unlocking script that spend that has false on the stack. We're gonna try and spend this with script B The unlocking script chooses one of the two paths to execute so if statements in Bitcoin conditional flow in Bitcoin is Very different from how we would use a procedural language because the condition you're testing is user input It comes from the unlocking script. So in a sense Essentially in Bitcoin script, you're saying there are two ways to spend this UTXO a or B And you can choose equally between both of them by saying true or false in the spending script Now that seems weird Because that doesn't seem very secure. What do you mean they are locking script can choose they can just choose a or B? well Then we've got to see what happens here So usually that means something sophisticated is happening here. Let's have a look So here's a locking script it says Well, you try reading it with English first. So it goes if Bob's public key is check-saked then No, that's wrong Okay, so what this says is if you give me a true I'm gonna try and use Bob's public key to check this if you give me a false I'm gonna try and use Alice's public key to unlock this script Which means that to spend this Bob passes as the unlocking script Bob's a True Alice can spend the same thing by saying Alice's false That's really weird That's really weird. You probably don't understand it at first clients, but let me explain how this works So let's say Bob presented this so how does this execute on the script? Let's put it in our mind and think about it So Bob's saying is the first thing it's a number it gets put onto the stack Then true gets put on top of it in the stack Then the if clause is executed it pops off the true drops everything else and runs this Now pop key goes on top of pop sig check sig runs sig pop key check sig true done Bob spends it Similarly Here Alice sig goes on the stack false goes above it if executes It's false. All of this goes away. The else clause runs Alice's pub key gets pushed on the stack check sig pops Alice's pub key and Alice sig True done Alice spends this output. I just wrote a really freaky weird one of two multi-sig That's a one of two multi-sig between Bob and Alice It's two keys any one of them can spend it with a single signature, right? So what I did was multi-sig, but with an if clause And all they have to do in order to Choose the right clause for their particular execution path the one they want will achieve the result they want is put a true or false at the end Yes Everybody with me some people with me anybody with me Very good Okay, so now you see why the condition is actually provided by the redeemer now That may be a problem you may want to Make sure that some parts of these things can only be executed by a very specific spender Yes, let's say we wanted to do more here Let's say Bob had to produce a secret hash and a signature Well, then we could do hash 160 Bob has equal now Bob has to deliver three things this that true signature and Some number that when hash produces that hash a pre-image. Yes Not quite We need to turn this into a guard clause. How do we turn this into a guard clause? Verify very good So what we're saying now is there are two execution paths available in this script the first execution path must first overcome this guard clause that requires a named public key to provide a signature and Then they must also provide the pre-image to a hash Alice Has a lesser burden. She only needs to produce a signature All right Makes sense. So we've piled two conditions. This is almost like a nested if Because it's a verify verifies the same as doing if else return Everybody with me so far This is getting complicated, right? The reason for doing this would be Well, no the reason for doing this is to To allow a motive a motive redemption that uses a pre-image instead of a public key Lightning uses that kind of technique for hash time locked contracts You'd actually probably put this the other way around So that the guard clause is give me the pre-image first and then give me the signature they're equivalent You could also have this Without this and this means Alice can spend this or anyone with knowledge of the secret can spend this anyone at all Once the secret is out first person to get their transaction into the blockchain Gets to redeem this. Yes Yes I'll let me be going for a minute. I think I have time for one more example, which is the final example for chapter seven. All right So at this point this should be crystal clear It's the same thing with a couple of little twists and Seeing principles of how you put things off the stack pop things off the stack and then evaluate them in sequence What this is A partnership Company that has three partners B C and D These three partners operate a Multi-signature account to store the company's money three lawyers working together They have a lawyer who's not part of the company called a and That lawyer is responsible for assisting in the case. There is key law So if one of the partners loses the keys the lawyer who's under contract has a fiduciary responsibility, etc can step in and Provide a backup key and Basically what this script does is it says Two out of three of the partners can spend this Any time so the basic clause is down here Which is a two of three Multi-sig Yeah It requires two of the three partners to sign if they sign it works like a normal multi-sig small twist but mostly normal and Less the output has not been spent within 30 days of being mined if it hasn't been spent 30 days after its mind it can also be redeemed by a signature from the lawyer and One of the partners not to if 90 days have elapsed From the moment this output has been mined The lawyer can spend it without any other partner signatures Yes So there are three execution paths at any moment in time All three of the execution paths can be selected But not all of them can be run successfully because they have guard clauses and Those dark guard clauses are based on time locks Relativistic time locks check sequence verify is relative to when this was mine That's why I put the notation plus 30 days plus 90 days Right that would be in seconds relative to the time it was mine Everybody good so far Did I make a mistake? They're according to median time past which is a specific consensus measurements of time introduced by Bip68 which introduced check sequence verify check sequence verify came also with bit one one three when it was activated in November I think It measures the median time of the last 11 blocks So it's permanently about an hour in the past But because it depends on the timestamps of the 11 blocks no single minor Can monkey with it? Because it so it makes it a useful consensus rule of time You have to adjust mentally to the fact that it will always be an hour behind because it's looking at the median time past 11 blocks Right. It is just short of two hours and the midpoint is exactly an hour ago right not wall clock time Consensus time and because each minor can make small changes and can drift any one block by a bit But they can't drift all 11 of the past blocks by a lot Therefore, it's not in their hands to modify this and start sniping transactions that are not yet due under the time long So that's a consensus security feature that was introduced with bit one one three questions In order for this to be effective You have to roll it over every 30 days every 29 days to be precise To prevent one of the other lawyers from colluding with the one of the other partners from colluding with the with the external lawyer And taking the money, right? So they would have to sign with two out of three to transaction every 30 days and roll it back into a script like this With a current fee structure in Bitcoin not likely they would do that. So maybe this is as useful for now Depends. Maybe they're a very rich law firm. They're moving like 10 million dollars out of this UTXO into another UTXO So $1 a $5 fee. It's a big script. Is it a big deal? What does the job script do? Yes, okay now? Let's go into some of the nuances right so you notice you get the big picture everybody I think gets the big picture right what this is trying to achieve Multi-sig in the middle very straightforward two or three partners a 30 day clause that allows one partner and the lawyer and the 90-day clause which is the they all died in the car crash together. I told them not to go in the same car and Now he's the last will Executor for their last will in testament and he's like dearly beloved. We have gathered here to split 10 million dollars So that's the final clause right that's the backup cause and what we've done here is we've sequenced some events in time This is really important using time locks Now I want to point out some nuances Do you remember how I said the time locks can be activated but not expired so they only work one way? So once something is valid so the time lock has passed It comes into play, but it doesn't go out of play right So let me just point something out. You might at first glance think it's either or either or Yes, but in fact, it's This and this after 30 days and also this after 90 days meaning that 36 days after this is mine These guys can still do the two of three this clause doesn't go away. This is always an option Maybe it's a who got into a car crash and his key disappeared. So none of the other stuff matters This is always an option All right 92 days After this is mind all three clauses come into play They can it can be redeemed in any of the three ways, right? So the clauses come into play sequence through time, but they never expire You can't say and you can't redeem anymore. That is a problem or solution, but The way it's done in lightning is using a revocation script, which you can find in chapter 12 All right, so everybody got that part Okay, here's a little interesting twist you may notice this You're like, what the hell is that doing there? There's a two. It's just hanging out like how number two up here Like what is that doing up there? Anybody? You've got some ideas Okay, let me give you some hints check multi-sig check multi-sig right takes at least three parameters M which is the quorum a number of keys minimum of one and N which is the how many keys are total, right? So check multi-sig. That's the end. It says there are three keys total One key two key three key. Where's the M? Oh, there's the M or one version of it Because there's another M Now this may start giving you a tiny bit of a glimpse of how flexible this shit is I just took the check multi-sig and I spread it Over two different conditional clauses over two different flows over two execution paths One way of doing this is you go through this way and then it's to Key key key three check multi-sig pretty pretty much straightforward all these things right or you go through this path guard clause 30 days and the signature from the attorney and then one of Key key key three check multi-sig so then it's a one of three So this one plays two different ways It's a two of three or it's a one of three. Does that make sense? That's a really powerful feature We just leave it dangling on the stack and then check multi-signal pick it up when it's time. Yes. Is there an error? It's a very good point It's a two of three or a two of four because we've inserted another key up here, but it's difficult to write to two of four In this particular formulation you could probably do it with By splitting the check multi-sig at a different part, right? Very good point It is a two of four because we introduced this Actually, it's not a two of four it's a one of one and a one of two or one of three because Two or four would imply that two of these guys could do it, but it has to be this plus one of the other three, right Some subtle nuances there, right? Also, you start to realize that this stuff needs some debugging, right? You really have to very carefully think about all of the scenarios And how many keys come into play and when they come into play and what combinations exist and What these people might do to collude with each other? This isn't even a turn complete language It's only 12 lines and you could fit an entire DAO mess right about here Yeah, one little bug. Oops What do you mean a right away with all the money? Well, you see if this happens before this We're fucked Even within Bitcoin script even though it's churning complete even though it's a very very simple stack based language You can introduce quite a bit of complexity there if you see some of the lightning network scripts and you think about all of the game theoretical Aspects of who can work who can operate at which time frame and what can they do it gets rather Complicated to think about all the scenarios. So there's some subtleties there All right Who wants to try and tell me what you have to put on the stack as the unlocking script in order to get to a two of three? We have two nested ifs Or two ifs nested Anybody who hasn't tried so far come on. Yes two signatures and two truths Very good. So two signatures followed by two truths. Why? first true if we go here second true if We go here right Then this gets put on the stack Everything from the else in the end if goes away Then this gets put on the stack then it gets evaluated with the two signatures boom boom dot Yes. All right, great. So we we got here and here with true true How do we get here true false? No Reverse Polish notation False you have to put the thing that's going to be executed first last in your line So unlocking script would be I say that correct false true Yes, false true false gets pushed on the stack true gets pushed on the stack true executes False executes you go in here. You forget the signature And of course the two signatures that are required to do that. So signature signature false truth. Yes Etc Okay, final question of the day. What the hell is that draw? Yes Up check multi-seq has a bug it pops an extra parameter before the first signature. You also need to put an Ops zero in fact Bip one I Want to say 145 I can't remember off the top of my head Actually restricts what that one thing that can be popped is down to a null dummy value It's called the null damn null dummy bit It requires that the value that gets popped by check multi-seq is a zero and the reason is to remove my liability Because at the moment it pops whatever is there So if you create a script that has zero and I change it to a script that has one even though I don't have any of the keys It still works because it will accept any value there So I think it's bit point 45 narrows that down to only zero accepted to overcome that bug Esoteric, but very useful. Yes There's a chapter in the book on why bugs in Bitcoin become consensus rules forever And the final thing is the drop Anybody care to comment on why that drop is there? Yes Bingo every other form of verify leaves nothing behind on the stack Check sequence verify and check lock time verify leave this value on the stack. Why? Because you might want to do more with it For example, let's say after this we wanted to do plus another five days Check sequence verify so we could do five days up add Up check sequence verify So it takes the value that was left on the stack Adds five to it or five days or whatever equivalent in seconds Runs op add pops the two values smushes them together puts the sum and that's what check sequence verify So you can do a arithmetic with this later, right one of the exceptions of the verifiable now That's all good. Yeah, we've got a value that's gonna stay on the stack But what if the very next thing is going to leave us some junk on the stack We don't want that junk passing on to the next thing. So we drop it So you'll very often see after check lock time verify and check sequence verify You'll see a drop occur immediately after and that's just to clean up the junk that's left over You never get to the drop unless the time is right Questions Checks Check check sequence verify is a command that was added by VIP 68 which is a relative lock time Yes verify only exists as specific off codes You can't just slap the word verify onto something it is a specific op codes whose name also includes Verified it's not a compound operator. It's a single operator check sequence verify and it doesn't exist in the other four Yes Yes, what happens after 29 days? What happens after 29 days you said you have to redo the transaction Well, so if the partners don't want to ever open the door to a pub key To be able to collude with one of the partners They better spend this within the 30-day window and create a new UTXO whose time starts again So they have to keep it's a dead man switch, right? You have to restore Reset the clock before it runs out otherwise the dead man switch clause gets activated everybody understand what a dead man switches Yeah